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/stm32_i2c.h>
9 #include <i2c_native.h>
10 #include <kernel/boot.h>
11 #include <kernel/dt.h>
12 #include <libfdt.h>
13 #include <phNxpEsePal_i2c.h>
14 
15 static_assert(CFG_CORE_SE05X_I2C_BUS < 10);
16 static struct i2c_handle_s i2c;
17 
native_i2c_transfer(struct rpc_i2c_request * req,size_t * bytes)18 TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes)
19 {
20 	if (req->mode == RPC_I2C_MODE_READ) {
21 		if (stm32_i2c_master_receive(&i2c, req->chip << 1, req->buffer,
22 					     req->buffer_len, 25))
23 			return TEE_ERROR_GENERIC;
24 	} else {
25 		if (stm32_i2c_master_transmit(&i2c, req->chip << 1, req->buffer,
26 					      req->buffer_len, 25))
27 			return TEE_ERROR_GENERIC;
28 	}
29 
30 	*bytes = req->buffer_len;
31 
32 	return TEE_SUCCESS;
33 }
34 
dt_i2c_bus_config(struct stm32_i2c_init_s * init,struct stm32_pinctrl ** pctrl,size_t * pcnt)35 static int dt_i2c_bus_config(struct stm32_i2c_init_s *init,
36 			     struct stm32_pinctrl **pctrl,  size_t *pcnt)
37 {
38 	const fdt32_t *cuint = NULL;
39 	const char *path = NULL;
40 	char bus[6] = { };
41 	void *fdt = NULL;
42 	int node = 0;
43 
44 	fdt = get_embedded_dt();
45 	if (!fdt)
46 		return -FDT_ERR_NOTFOUND;
47 
48 	snprintf(bus, sizeof(bus), "i2c%d", CFG_CORE_SE05X_I2C_BUS);
49 
50 	path = fdt_get_alias(fdt, bus);
51 	if (!path)
52 		return -FDT_ERR_NOTFOUND;
53 
54 	node = fdt_path_offset(fdt, path);
55 	if (node < 0)
56 		return -FDT_ERR_NOTFOUND;
57 
58 	cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
59 	if (cuint && fdt32_to_cpu(*cuint) != CFG_CORE_SE05X_BAUDRATE)
60 		IMSG("SE05X ignoring CFG_CORE_SE05X_BAUDRATE, use DTB");
61 	else if (I2C_STANDARD_RATE != CFG_CORE_SE05X_BAUDRATE)
62 		IMSG("SE05x ignoring CFG_CORE_SE05X_BAUDRATE, use built-in");
63 
64 	return stm32_i2c_get_setup_from_fdt(fdt, node, init, pctrl, pcnt);
65 }
66 
native_i2c_init(void)67 int native_i2c_init(void)
68 {
69 	struct stm32_i2c_init_s i2c_init = { };
70 	struct stm32_pinctrl *pinctrl = NULL;
71 	size_t pin_count = 0;
72 
73 	/* No need to re-initialize */
74 	if (i2c.base.pa)
75 		return 0;
76 
77 	/* Support only one device on the platform */
78 	if (dt_i2c_bus_config(&i2c_init, &pinctrl, &pin_count))
79 		return -1;
80 
81 	/* Probe the device */
82 	i2c_init.own_address1 = SMCOM_I2C_ADDRESS;
83 	i2c_init.digital_filter_coef = 0;
84 	i2c_init.analog_filter = true;
85 	i2c.pinctrl_count = pin_count;
86 	i2c.pinctrl = pinctrl;
87 
88 	stm32_i2c_resume(&i2c);
89 
90 	return stm32_i2c_init(&i2c, &i2c_init);
91 }
92