xref: /optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c (revision 9ef7a09c9db150ca8c33444b215b032665cdf0b8)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved
4  * Author: Jorge Ramirez-Ortiz <jorge@foundries.io>
5  */
6 
7 #include <assert.h>
8 #include <drivers/pinctrl.h>
9 #include <drivers/stm32_i2c.h>
10 #include <i2c_native.h>
11 #include <kernel/boot.h>
12 #include <kernel/dt.h>
13 #include <libfdt.h>
14 #include <phNxpEsePal_i2c.h>
15 
16 static_assert(CFG_CORE_SE05X_I2C_BUS < 10);
17 static struct i2c_handle_s i2c;
18 
native_i2c_transfer(struct rpc_i2c_request * req,size_t * bytes)19 TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes)
20 {
21 	if (req->mode == RPC_I2C_MODE_READ) {
22 		if (stm32_i2c_master_receive(&i2c, req->chip << 1, req->buffer,
23 					     req->buffer_len, 25))
24 			return TEE_ERROR_GENERIC;
25 	} else {
26 		if (stm32_i2c_master_transmit(&i2c, req->chip << 1, req->buffer,
27 					      req->buffer_len, 25))
28 			return TEE_ERROR_GENERIC;
29 	}
30 
31 	*bytes = req->buffer_len;
32 
33 	return TEE_SUCCESS;
34 }
35 
dt_i2c_bus_config(struct stm32_i2c_init_s * init,struct pinctrl_state ** pinctrl_active,struct pinctrl_state ** pinctrl_sleep)36 static int dt_i2c_bus_config(struct stm32_i2c_init_s *init,
37 			     struct pinctrl_state **pinctrl_active,
38 			     struct pinctrl_state **pinctrl_sleep)
39 {
40 	const fdt32_t *cuint = NULL;
41 	const char *path = NULL;
42 	char bus[6] = { };
43 	void *fdt = NULL;
44 	int node = 0;
45 
46 	fdt = get_embedded_dt();
47 	if (!fdt)
48 		return -FDT_ERR_NOTFOUND;
49 
50 	snprintf(bus, sizeof(bus), "i2c%d", CFG_CORE_SE05X_I2C_BUS);
51 
52 	path = fdt_get_alias(fdt, bus);
53 	if (!path)
54 		return -FDT_ERR_NOTFOUND;
55 
56 	node = fdt_path_offset(fdt, path);
57 	if (node < 0)
58 		return -FDT_ERR_NOTFOUND;
59 
60 	cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
61 	if (cuint && fdt32_to_cpu(*cuint) != CFG_CORE_SE05X_BAUDRATE)
62 		IMSG("SE05X ignoring CFG_CORE_SE05X_BAUDRATE, use DTB");
63 	else if (I2C_STANDARD_RATE != CFG_CORE_SE05X_BAUDRATE)
64 		IMSG("SE05x ignoring CFG_CORE_SE05X_BAUDRATE, use built-in");
65 
66 	return stm32_i2c_get_setup_from_fdt(fdt, node, init, pinctrl_active,
67 					    pinctrl_sleep);
68 }
69 
native_i2c_init(void)70 int native_i2c_init(void)
71 {
72 	struct stm32_i2c_init_s i2c_init = { };
73 
74 	/* No need to re-initialize */
75 	if (i2c.base.pa)
76 		return 0;
77 
78 	/* Support only one device on the platform */
79 	if (dt_i2c_bus_config(&i2c_init, &i2c.pinctrl, &i2c.pinctrl_sleep))
80 		return -1;
81 
82 	/* Probe the device */
83 	i2c_init.own_address1 = SMCOM_I2C_ADDRESS;
84 	i2c_init.digital_filter_coef = 0;
85 	i2c_init.analog_filter = true;
86 
87 	stm32_i2c_resume(&i2c);
88 
89 	return stm32_i2c_init(&i2c, &i2c_init);
90 }
91