1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * NXP SC18IS602/603 SPI driver |
4 | * |
5 | * Copyright (C) Guenter Roeck <linux@roeck-us.net> |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/err.h> |
10 | #include <linux/module.h> |
11 | #include <linux/spi/spi.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/pm_runtime.h> |
15 | #include <linux/of.h> |
16 | #include <linux/platform_data/sc18is602.h> |
17 | #include <linux/gpio/consumer.h> |
18 | |
19 | enum chips { sc18is602, sc18is602b, sc18is603 }; |
20 | |
21 | #define SC18IS602_BUFSIZ 200 |
22 | #define SC18IS602_CLOCK 7372000 |
23 | |
24 | #define SC18IS602_MODE_CPHA BIT(2) |
25 | #define SC18IS602_MODE_CPOL BIT(3) |
26 | #define SC18IS602_MODE_LSB_FIRST BIT(5) |
27 | #define SC18IS602_MODE_CLOCK_DIV_4 0x0 |
28 | #define SC18IS602_MODE_CLOCK_DIV_16 0x1 |
29 | #define SC18IS602_MODE_CLOCK_DIV_64 0x2 |
30 | #define SC18IS602_MODE_CLOCK_DIV_128 0x3 |
31 | |
32 | struct sc18is602 { |
33 | struct spi_controller *host; |
34 | struct device *dev; |
35 | u8 ctrl; |
36 | u32 freq; |
37 | u32 speed; |
38 | |
39 | /* I2C data */ |
40 | struct i2c_client *client; |
41 | enum chips id; |
42 | u8 buffer[SC18IS602_BUFSIZ + 1]; |
43 | int tlen; /* Data queued for tx in buffer */ |
44 | int rindex; /* Receive data index in buffer */ |
45 | |
46 | struct gpio_desc *reset; |
47 | }; |
48 | |
49 | static int sc18is602_wait_ready(struct sc18is602 *hw, int len) |
50 | { |
51 | int i, err; |
52 | int usecs = 1000000 * len / hw->speed + 1; |
53 | u8 dummy[1]; |
54 | |
55 | for (i = 0; i < 10; i++) { |
56 | err = i2c_master_recv(client: hw->client, buf: dummy, count: 1); |
57 | if (err >= 0) |
58 | return 0; |
59 | usleep_range(min: usecs, max: usecs * 2); |
60 | } |
61 | return -ETIMEDOUT; |
62 | } |
63 | |
64 | static int sc18is602_txrx(struct sc18is602 *hw, struct spi_message *msg, |
65 | struct spi_transfer *t, bool do_transfer) |
66 | { |
67 | unsigned int len = t->len; |
68 | int ret; |
69 | |
70 | if (hw->tlen == 0) { |
71 | /* First byte (I2C command) is chip select */ |
72 | hw->buffer[0] = 1 << spi_get_chipselect(spi: msg->spi, idx: 0); |
73 | hw->tlen = 1; |
74 | hw->rindex = 0; |
75 | } |
76 | /* |
77 | * We can not immediately send data to the chip, since each I2C message |
78 | * resembles a full SPI message (from CS active to CS inactive). |
79 | * Enqueue messages up to the first read or until do_transfer is true. |
80 | */ |
81 | if (t->tx_buf) { |
82 | memcpy(&hw->buffer[hw->tlen], t->tx_buf, len); |
83 | hw->tlen += len; |
84 | if (t->rx_buf) |
85 | do_transfer = true; |
86 | else |
87 | hw->rindex = hw->tlen - 1; |
88 | } else if (t->rx_buf) { |
89 | /* |
90 | * For receive-only transfers we still need to perform a dummy |
91 | * write to receive data from the SPI chip. |
92 | * Read data starts at the end of transmit data (minus 1 to |
93 | * account for CS). |
94 | */ |
95 | hw->rindex = hw->tlen - 1; |
96 | memset(&hw->buffer[hw->tlen], 0, len); |
97 | hw->tlen += len; |
98 | do_transfer = true; |
99 | } |
100 | |
101 | if (do_transfer && hw->tlen > 1) { |
102 | ret = sc18is602_wait_ready(hw, SC18IS602_BUFSIZ); |
103 | if (ret < 0) |
104 | return ret; |
105 | ret = i2c_master_send(client: hw->client, buf: hw->buffer, count: hw->tlen); |
106 | if (ret < 0) |
107 | return ret; |
108 | if (ret != hw->tlen) |
109 | return -EIO; |
110 | |
111 | if (t->rx_buf) { |
112 | int rlen = hw->rindex + len; |
113 | |
114 | ret = sc18is602_wait_ready(hw, len: hw->tlen); |
115 | if (ret < 0) |
116 | return ret; |
117 | ret = i2c_master_recv(client: hw->client, buf: hw->buffer, count: rlen); |
118 | if (ret < 0) |
119 | return ret; |
120 | if (ret != rlen) |
121 | return -EIO; |
122 | memcpy(t->rx_buf, &hw->buffer[hw->rindex], len); |
123 | } |
124 | hw->tlen = 0; |
125 | } |
126 | return len; |
127 | } |
128 | |
129 | static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode) |
130 | { |
131 | u8 ctrl = 0; |
132 | int ret; |
133 | |
134 | if (mode & SPI_CPHA) |
135 | ctrl |= SC18IS602_MODE_CPHA; |
136 | if (mode & SPI_CPOL) |
137 | ctrl |= SC18IS602_MODE_CPOL; |
138 | if (mode & SPI_LSB_FIRST) |
139 | ctrl |= SC18IS602_MODE_LSB_FIRST; |
140 | |
141 | /* Find the closest clock speed */ |
142 | if (hz >= hw->freq / 4) { |
143 | ctrl |= SC18IS602_MODE_CLOCK_DIV_4; |
144 | hw->speed = hw->freq / 4; |
145 | } else if (hz >= hw->freq / 16) { |
146 | ctrl |= SC18IS602_MODE_CLOCK_DIV_16; |
147 | hw->speed = hw->freq / 16; |
148 | } else if (hz >= hw->freq / 64) { |
149 | ctrl |= SC18IS602_MODE_CLOCK_DIV_64; |
150 | hw->speed = hw->freq / 64; |
151 | } else { |
152 | ctrl |= SC18IS602_MODE_CLOCK_DIV_128; |
153 | hw->speed = hw->freq / 128; |
154 | } |
155 | |
156 | /* |
157 | * Don't do anything if the control value did not change. The initial |
158 | * value of 0xff for hw->ctrl ensures that the correct mode will be set |
159 | * with the first call to this function. |
160 | */ |
161 | if (ctrl == hw->ctrl) |
162 | return 0; |
163 | |
164 | ret = i2c_smbus_write_byte_data(client: hw->client, command: 0xf0, value: ctrl); |
165 | if (ret < 0) |
166 | return ret; |
167 | |
168 | hw->ctrl = ctrl; |
169 | |
170 | return 0; |
171 | } |
172 | |
173 | static int sc18is602_check_transfer(struct spi_device *spi, |
174 | struct spi_transfer *t, int tlen) |
175 | { |
176 | if (t && t->len + tlen > SC18IS602_BUFSIZ + 1) |
177 | return -EINVAL; |
178 | |
179 | return 0; |
180 | } |
181 | |
182 | static int sc18is602_transfer_one(struct spi_controller *host, |
183 | struct spi_message *m) |
184 | { |
185 | struct sc18is602 *hw = spi_controller_get_devdata(ctlr: host); |
186 | struct spi_device *spi = m->spi; |
187 | struct spi_transfer *t; |
188 | int status = 0; |
189 | |
190 | hw->tlen = 0; |
191 | list_for_each_entry(t, &m->transfers, transfer_list) { |
192 | bool do_transfer; |
193 | |
194 | status = sc18is602_check_transfer(spi, t, tlen: hw->tlen); |
195 | if (status < 0) |
196 | break; |
197 | |
198 | status = sc18is602_setup_transfer(hw, hz: t->speed_hz, mode: spi->mode); |
199 | if (status < 0) |
200 | break; |
201 | |
202 | do_transfer = t->cs_change || list_is_last(list: &t->transfer_list, |
203 | head: &m->transfers); |
204 | |
205 | if (t->len) { |
206 | status = sc18is602_txrx(hw, msg: m, t, do_transfer); |
207 | if (status < 0) |
208 | break; |
209 | m->actual_length += status; |
210 | } |
211 | status = 0; |
212 | |
213 | spi_transfer_delay_exec(t); |
214 | } |
215 | m->status = status; |
216 | spi_finalize_current_message(ctlr: host); |
217 | |
218 | return status; |
219 | } |
220 | |
221 | static size_t sc18is602_max_transfer_size(struct spi_device *spi) |
222 | { |
223 | return SC18IS602_BUFSIZ; |
224 | } |
225 | |
226 | static int sc18is602_setup(struct spi_device *spi) |
227 | { |
228 | struct sc18is602 *hw = spi_controller_get_devdata(ctlr: spi->controller); |
229 | |
230 | /* SC18IS602 does not support CS2 */ |
231 | if (hw->id == sc18is602 && (spi_get_chipselect(spi, idx: 0) == 2)) |
232 | return -ENXIO; |
233 | |
234 | return 0; |
235 | } |
236 | |
237 | static int sc18is602_probe(struct i2c_client *client) |
238 | { |
239 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
240 | struct device *dev = &client->dev; |
241 | struct device_node *np = dev->of_node; |
242 | struct sc18is602_platform_data *pdata = dev_get_platdata(dev); |
243 | struct sc18is602 *hw; |
244 | struct spi_controller *host; |
245 | |
246 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C | |
247 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
248 | return -EINVAL; |
249 | |
250 | host = devm_spi_alloc_host(dev, size: sizeof(struct sc18is602)); |
251 | if (!host) |
252 | return -ENOMEM; |
253 | |
254 | hw = spi_controller_get_devdata(ctlr: host); |
255 | i2c_set_clientdata(client, data: hw); |
256 | |
257 | /* assert reset and then release */ |
258 | hw->reset = devm_gpiod_get_optional(dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
259 | if (IS_ERR(ptr: hw->reset)) |
260 | return PTR_ERR(ptr: hw->reset); |
261 | gpiod_set_value_cansleep(desc: hw->reset, value: 0); |
262 | |
263 | hw->host = host; |
264 | hw->client = client; |
265 | hw->dev = dev; |
266 | hw->ctrl = 0xff; |
267 | |
268 | if (client->dev.of_node) |
269 | hw->id = (uintptr_t)of_device_get_match_data(dev: &client->dev); |
270 | else |
271 | hw->id = id->driver_data; |
272 | |
273 | switch (hw->id) { |
274 | case sc18is602: |
275 | case sc18is602b: |
276 | host->num_chipselect = 4; |
277 | hw->freq = SC18IS602_CLOCK; |
278 | break; |
279 | case sc18is603: |
280 | host->num_chipselect = 2; |
281 | if (pdata) { |
282 | hw->freq = pdata->clock_frequency; |
283 | } else { |
284 | const __be32 *val; |
285 | int len; |
286 | |
287 | val = of_get_property(node: np, name: "clock-frequency" , lenp: &len); |
288 | if (val && len >= sizeof(__be32)) |
289 | hw->freq = be32_to_cpup(p: val); |
290 | } |
291 | if (!hw->freq) |
292 | hw->freq = SC18IS602_CLOCK; |
293 | break; |
294 | } |
295 | host->bus_num = np ? -1 : client->adapter->nr; |
296 | host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST; |
297 | host->bits_per_word_mask = SPI_BPW_MASK(8); |
298 | host->setup = sc18is602_setup; |
299 | host->transfer_one_message = sc18is602_transfer_one; |
300 | host->max_transfer_size = sc18is602_max_transfer_size; |
301 | host->max_message_size = sc18is602_max_transfer_size; |
302 | host->dev.of_node = np; |
303 | host->min_speed_hz = hw->freq / 128; |
304 | host->max_speed_hz = hw->freq / 4; |
305 | |
306 | return devm_spi_register_controller(dev, ctlr: host); |
307 | } |
308 | |
309 | static const struct i2c_device_id sc18is602_id[] = { |
310 | { "sc18is602" , sc18is602 }, |
311 | { "sc18is602b" , sc18is602b }, |
312 | { "sc18is603" , sc18is603 }, |
313 | { } |
314 | }; |
315 | MODULE_DEVICE_TABLE(i2c, sc18is602_id); |
316 | |
317 | static const struct of_device_id sc18is602_of_match[] __maybe_unused = { |
318 | { |
319 | .compatible = "nxp,sc18is602" , |
320 | .data = (void *)sc18is602 |
321 | }, |
322 | { |
323 | .compatible = "nxp,sc18is602b" , |
324 | .data = (void *)sc18is602b |
325 | }, |
326 | { |
327 | .compatible = "nxp,sc18is603" , |
328 | .data = (void *)sc18is603 |
329 | }, |
330 | { }, |
331 | }; |
332 | MODULE_DEVICE_TABLE(of, sc18is602_of_match); |
333 | |
334 | static struct i2c_driver sc18is602_driver = { |
335 | .driver = { |
336 | .name = "sc18is602" , |
337 | .of_match_table = of_match_ptr(sc18is602_of_match), |
338 | }, |
339 | .probe = sc18is602_probe, |
340 | .id_table = sc18is602_id, |
341 | }; |
342 | |
343 | module_i2c_driver(sc18is602_driver); |
344 | |
345 | MODULE_DESCRIPTION("SC18IS602/603 SPI Host Driver" ); |
346 | MODULE_AUTHOR("Guenter Roeck" ); |
347 | MODULE_LICENSE("GPL" ); |
348 | |