1 /*
2  * Copyright (c) 2021 Telink Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT telink_b91_i2c
8 
9 #include "i2c.h"
10 #include "clock.h"
11 
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(i2c_telink);
14 
15 #include <drivers/i2c.h>
16 #include "i2c-priv.h"
17 #include <drivers/pinmux.h>
18 #include <dt-bindings/pinctrl/b91-pinctrl.h>
19 
20 /* I2C configuration structure */
21 struct i2c_b91_cfg {
22 	uint32_t bitrate;
23 	const uint32_t *pinctrl_list;
24 	size_t pinctrl_list_size;
25 };
26 
27 /* I2C data structure */
28 struct i2c_b91_data {
29 	struct k_sem mutex;
30 };
31 
32 /* API implementation: configure */
i2c_b91_configure(const struct device * dev,uint32_t dev_config)33 static int i2c_b91_configure(const struct device *dev, uint32_t dev_config)
34 {
35 	ARG_UNUSED(dev);
36 
37 	uint32_t i2c_speed = 0u;
38 
39 	/* check address size */
40 	if (dev_config & I2C_ADDR_10_BITS) {
41 		LOG_ERR("10-bits address is not supported");
42 		return -ENOTSUP;
43 	}
44 
45 	/* check I2C Master/Slave configuration */
46 	if (!(dev_config & I2C_MODE_MASTER)) {
47 		LOG_ERR("I2C slave is not implemented");
48 		return -ENOTSUP;
49 	}
50 
51 	/* check i2c speed */
52 	switch (I2C_SPEED_GET(dev_config)) {
53 	case I2C_SPEED_STANDARD:
54 		i2c_speed = 100000u;
55 		break;
56 
57 	case I2C_SPEED_FAST:
58 		i2c_speed = 400000U;
59 		break;
60 
61 	case I2C_SPEED_FAST_PLUS:
62 	case I2C_SPEED_HIGH:
63 	case I2C_SPEED_ULTRA:
64 	default:
65 		LOG_ERR("Unsupported I2C speed requested");
66 		return -ENOTSUP;
67 	}
68 
69 	/* init i2c */
70 	i2c_master_init();
71 	i2c_set_master_clk((unsigned char)(sys_clk.pclk * 1000 * 1000 / (4 * i2c_speed)));
72 
73 	return 0;
74 }
75 
76 /* API implementation: transfer */
i2c_b91_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)77 static int i2c_b91_transfer(const struct device *dev,
78 			    struct i2c_msg *msgs,
79 			    uint8_t num_msgs,
80 			    uint16_t addr)
81 {
82 	int status = 0;
83 	uint8_t send_stop = 0;
84 	struct i2c_b91_data *data = dev->data;
85 
86 	/* get the mutex */
87 	k_sem_take(&data->mutex, K_FOREVER);
88 
89 	/* loop through all messages */
90 	for (int i = 0; i < num_msgs; i++) {
91 		/* check addr size */
92 		if (msgs[i].flags & I2C_MSG_ADDR_10_BITS) {
93 			LOG_ERR("10-bits address is not supported");
94 			k_sem_give(&data->mutex);
95 			return -ENOTSUP;
96 		}
97 
98 		/* config stop bit */
99 		send_stop = msgs[i].flags & I2C_MSG_STOP ? 1 : 0;
100 		i2c_master_send_stop(send_stop);
101 
102 		/* transfer data */
103 		if (msgs[i].flags & I2C_MSG_READ) {
104 			status = i2c_master_read(addr, msgs[i].buf, msgs[i].len);
105 		} else {
106 			status = i2c_master_write(addr, msgs[i].buf, msgs[i].len);
107 		}
108 
109 		/* check status */
110 		if (!status) {
111 			LOG_ERR("Failed to transfer I2C messages\n");
112 			k_sem_give(&data->mutex);
113 			return -EIO;
114 		}
115 	}
116 
117 	/* release the mutex */
118 	k_sem_give(&data->mutex);
119 
120 	return 0;
121 };
122 
123 /* API implementation: init */
i2c_b91_init(const struct device * dev)124 static int i2c_b91_init(const struct device *dev)
125 {
126 	int status = 0;
127 	const struct device *pinmux;
128 	const struct i2c_b91_cfg *cfg = dev->config;
129 	struct i2c_b91_data *data = dev->data;
130 	uint32_t dev_config = (I2C_MODE_MASTER | i2c_map_dt_bitrate(cfg->bitrate));
131 
132 	/* init mutex */
133 	k_sem_init(&data->mutex, 1, 1);
134 
135 	/* config i2c on startup */
136 	status = i2c_b91_configure(dev, dev_config);
137 	if (status != 0) {
138 		LOG_ERR("Failed to configure I2C on init");
139 		return status;
140 	}
141 
142 	/* get pinmux driver */
143 	pinmux = DEVICE_DT_GET(DT_NODELABEL(pinmux));
144 	if (!device_is_ready(pinmux)) {
145 		return -ENODEV;
146 	}
147 
148 	/* config pins */
149 	for (int i = 0; i < cfg->pinctrl_list_size; i++) {
150 		pinmux_pin_set(pinmux, B91_PINMUX_GET_PIN(cfg->pinctrl_list[i]),
151 			       B91_PINMUX_GET_FUNC(cfg->pinctrl_list[i]));
152 	}
153 
154 	return 0;
155 }
156 
157 /* I2C driver APIs structure */
158 static const struct i2c_driver_api i2c_b91_api = {
159 	.configure = i2c_b91_configure,
160 	.transfer = i2c_b91_transfer,
161 };
162 
163 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1,
164 	     "unsupported I2C instance");
165 
166 /* I2C driver registration */
167 #define I2C_B91_INIT(inst)					  \
168 								  \
169 	static const uint32_t i2c_pins_##inst[] =		  \
170 		B91_PINMUX_DT_INST_GET_ARRAY(inst, 0);		  \
171 								  \
172 	static struct i2c_b91_data i2c_b91_data_##inst;		  \
173 								  \
174 	static struct i2c_b91_cfg i2c_b91_cfg_##inst = {	  \
175 		.bitrate = DT_INST_PROP(inst, clock_frequency),	  \
176 		.pinctrl_list_size = ARRAY_SIZE(i2c_pins_##inst), \
177 		.pinctrl_list = i2c_pins_##inst			  \
178 	};							  \
179 								  \
180 	DEVICE_DT_INST_DEFINE(inst, i2c_b91_init,		  \
181 			      NULL,				  \
182 			      &i2c_b91_data_##inst,		  \
183 			      &i2c_b91_cfg_##inst,		  \
184 			      POST_KERNEL,			  \
185 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
186 			      &i2c_b91_api);
187 
188 DT_INST_FOREACH_STATUS_OKAY(I2C_B91_INIT)
189