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