1 /*
2  * Copyright (c) 2019 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT litex_i2c
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/i2c.h>
11 
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(i2c_litex, CONFIG_I2C_LOG_LEVEL);
14 
15 #include "i2c-priv.h"
16 #include "i2c_bitbang.h"
17 
18 #include <soc.h>
19 
20 #define SCL_BIT_POS                0
21 #define SDA_DIR_BIT_POS            1
22 #define SDA_BIT_W_POS              2
23 #define SDA_BIT_R_POS              0
24 
25 #define SDA_DIR_OUTPUT             1
26 #define SDA_DIR_INPUT              0
27 
28 #define HIGH_STATE_ON_I2C_LINES    0x7
29 
30 struct i2c_litex_cfg {
31 	uint32_t write_addr;
32 	uint32_t read_addr;
33 	uint32_t bitrate;
34 };
35 
36 #define GET_I2C_CFG(dev)						     \
37 	((const struct i2c_litex_cfg *) dev->config)
38 
39 #define GET_I2C_BITBANG(dev)						     \
40 	((struct i2c_bitbang *) dev->data)
41 
set_bit(uint32_t addr,uint32_t bit,uint32_t val)42 static inline void set_bit(uint32_t addr, uint32_t bit, uint32_t val)
43 {
44 	uint32_t mask = BIT(bit);
45 
46 	if (val) {
47 		litex_write8(litex_read8(addr) | mask, addr);
48 	} else {
49 		litex_write8(litex_read8(addr) & ~mask, addr);
50 	}
51 }
52 
get_bit(uint32_t addr,uint32_t bit)53 static inline int get_bit(uint32_t addr, uint32_t bit)
54 {
55 	uint32_t mask = BIT(bit);
56 
57 	return !!(litex_read8(addr) & mask);
58 }
59 
i2c_litex_bitbang_set_scl(void * context,int state)60 static void i2c_litex_bitbang_set_scl(void *context, int state)
61 {
62 	const struct i2c_litex_cfg *config =
63 		(const struct i2c_litex_cfg *) context;
64 
65 	set_bit(config->write_addr, SCL_BIT_POS, state);
66 }
67 
i2c_litex_bitbang_set_sda(void * context,int state)68 static void i2c_litex_bitbang_set_sda(void *context, int state)
69 {
70 	const struct i2c_litex_cfg *config =
71 		(const struct i2c_litex_cfg *) context;
72 
73 	set_bit(config->write_addr, SDA_DIR_BIT_POS, SDA_DIR_OUTPUT);
74 	set_bit(config->write_addr, SDA_BIT_W_POS, state);
75 }
76 
i2c_litex_bitbang_get_sda(void * context)77 static int i2c_litex_bitbang_get_sda(void *context)
78 {
79 	const struct i2c_litex_cfg *config =
80 		(const struct i2c_litex_cfg *) context;
81 
82 	set_bit(config->write_addr, SDA_DIR_BIT_POS, SDA_DIR_INPUT);
83 	return get_bit(config->read_addr, SDA_BIT_R_POS);
84 }
85 
86 static const struct i2c_bitbang_io i2c_litex_bitbang_io = {
87 	.set_scl = i2c_litex_bitbang_set_scl,
88 	.set_sda = i2c_litex_bitbang_set_sda,
89 	.get_sda = i2c_litex_bitbang_get_sda,
90 };
91 
i2c_litex_init(const struct device * dev)92 static int i2c_litex_init(const struct device *dev)
93 {
94 	const struct i2c_litex_cfg *config = GET_I2C_CFG(dev);
95 	struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev);
96 	int ret;
97 
98 	litex_write8(litex_read8(config->write_addr) | HIGH_STATE_ON_I2C_LINES, config->write_addr);
99 	i2c_bitbang_init(bitbang, &i2c_litex_bitbang_io, (void *)config);
100 
101 	ret = i2c_bitbang_configure(bitbang,
102 				    I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate));
103 	if (ret != 0) {
104 		LOG_ERR("failed to configure I2C bitbang: %d", ret);
105 	}
106 
107 	return ret;
108 }
109 
i2c_litex_configure(const struct device * dev,uint32_t dev_config)110 static int i2c_litex_configure(const struct device *dev, uint32_t dev_config)
111 {
112 	struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev);
113 
114 	return i2c_bitbang_configure(bitbang, dev_config);
115 }
116 
i2c_litex_get_config(const struct device * dev,uint32_t * config)117 static int i2c_litex_get_config(const struct device *dev, uint32_t *config)
118 {
119 	struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev);
120 
121 	return i2c_bitbang_get_config(bitbang, config);
122 }
123 
i2c_litex_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)124 static int i2c_litex_transfer(const struct device *dev,  struct i2c_msg *msgs,
125 			      uint8_t num_msgs, uint16_t addr)
126 {
127 	struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev);
128 
129 	return i2c_bitbang_transfer(bitbang, msgs, num_msgs, addr);
130 }
131 
i2c_litex_recover_bus(const struct device * dev)132 static int i2c_litex_recover_bus(const struct device *dev)
133 {
134 	struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev);
135 
136 	return i2c_bitbang_recover_bus(bitbang);
137 }
138 
139 static DEVICE_API(i2c, i2c_litex_driver_api) = {
140 	.configure = i2c_litex_configure,
141 	.get_config = i2c_litex_get_config,
142 	.transfer = i2c_litex_transfer,
143 	.recover_bus = i2c_litex_recover_bus,
144 #ifdef CONFIG_I2C_RTIO
145 	.iodev_submit = i2c_iodev_submit_fallback,
146 #endif
147 };
148 
149 /* Device Instantiation */
150 
151 #define I2C_LITEX_INIT(n)						       \
152 	static const struct i2c_litex_cfg i2c_litex_cfg_##n = {		       \
153 		.write_addr = DT_INST_REG_ADDR_BY_NAME(n, write),	       \
154 		.read_addr = DT_INST_REG_ADDR_BY_NAME(n, read),		       \
155 		.bitrate = DT_INST_PROP(n, clock_frequency),                   \
156 	};								       \
157 									       \
158 	static struct i2c_bitbang i2c_bitbang_##n;			       \
159 									       \
160 	I2C_DEVICE_DT_INST_DEFINE(n,					       \
161 			   i2c_litex_init,				       \
162 			   NULL,					       \
163 			   &i2c_bitbang_##n,	                               \
164 			   &i2c_litex_cfg_##n,				       \
165 			   POST_KERNEL,					       \
166 			   CONFIG_I2C_INIT_PRIORITY,			       \
167 			   &i2c_litex_driver_api			       \
168 			   );
169 
170 DT_INST_FOREACH_STATUS_OKAY(I2C_LITEX_INIT)
171