Commit | Line | Data |
---|---|---|
09c434b8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
ac0385d9 CB |
2 | /* |
3 | * A FSI master controller, using a simple GPIO bit-banging interface | |
4 | */ | |
5 | ||
6 | #include <linux/crc4.h> | |
7 | #include <linux/delay.h> | |
8 | #include <linux/device.h> | |
9 | #include <linux/fsi.h> | |
10 | #include <linux/gpio/consumer.h> | |
11 | #include <linux/io.h> | |
26d79b27 | 12 | #include <linux/irqflags.h> |
ac0385d9 | 13 | #include <linux/module.h> |
f6a2f8eb | 14 | #include <linux/of.h> |
ac0385d9 CB |
15 | #include <linux/platform_device.h> |
16 | #include <linux/slab.h> | |
ac0385d9 CB |
17 | |
18 | #include "fsi-master.h" | |
19 | ||
20 | #define FSI_GPIO_STD_DLY 1 /* Standard pin delay in nS */ | |
0e82e5c1 JK |
21 | #define LAST_ADDR_INVALID 0x1 |
22 | ||
ac0385d9 CB |
23 | struct fsi_master_gpio { |
24 | struct fsi_master master; | |
25 | struct device *dev; | |
e5538139 | 26 | struct mutex cmd_lock; /* mutex for command ordering */ |
ac0385d9 CB |
27 | struct gpio_desc *gpio_clk; |
28 | struct gpio_desc *gpio_data; | |
29 | struct gpio_desc *gpio_trans; /* Voltage translator */ | |
30 | struct gpio_desc *gpio_enable; /* FSI enable */ | |
31 | struct gpio_desc *gpio_mux; /* Mux control */ | |
b8bd146d | 32 | bool external_mode; |
bc1099d2 | 33 | bool no_delays; |
0e82e5c1 | 34 | uint32_t last_addr; |
75854c14 BH |
35 | uint8_t t_send_delay; |
36 | uint8_t t_echo_delay; | |
ac0385d9 CB |
37 | }; |
38 | ||
1247cf7a JK |
39 | #define CREATE_TRACE_POINTS |
40 | #include <trace/events/fsi_master_gpio.h> | |
41 | ||
ac0385d9 CB |
42 | #define to_fsi_master_gpio(m) container_of(m, struct fsi_master_gpio, master) |
43 | ||
44 | struct fsi_gpio_msg { | |
45 | uint64_t msg; | |
46 | uint8_t bits; | |
47 | }; | |
48 | ||
49 | static void clock_toggle(struct fsi_master_gpio *master, int count) | |
50 | { | |
51 | int i; | |
52 | ||
53 | for (i = 0; i < count; i++) { | |
bc1099d2 BH |
54 | if (!master->no_delays) |
55 | ndelay(FSI_GPIO_STD_DLY); | |
ac0385d9 | 56 | gpiod_set_value(master->gpio_clk, 0); |
bc1099d2 BH |
57 | if (!master->no_delays) |
58 | ndelay(FSI_GPIO_STD_DLY); | |
ac0385d9 CB |
59 | gpiod_set_value(master->gpio_clk, 1); |
60 | } | |
61 | } | |
62 | ||
5d0d16f1 | 63 | static int sda_clock_in(struct fsi_master_gpio *master) |
ac0385d9 CB |
64 | { |
65 | int in; | |
66 | ||
bc1099d2 BH |
67 | if (!master->no_delays) |
68 | ndelay(FSI_GPIO_STD_DLY); | |
5d0d16f1 | 69 | gpiod_set_value(master->gpio_clk, 0); |
f3ca4834 BH |
70 | |
71 | /* Dummy read to feed the synchronizers */ | |
72 | gpiod_get_value(master->gpio_data); | |
73 | ||
74 | /* Actual data read */ | |
ac0385d9 | 75 | in = gpiod_get_value(master->gpio_data); |
bc1099d2 BH |
76 | if (!master->no_delays) |
77 | ndelay(FSI_GPIO_STD_DLY); | |
5d0d16f1 | 78 | gpiod_set_value(master->gpio_clk, 1); |
ac0385d9 CB |
79 | return in ? 1 : 0; |
80 | } | |
81 | ||
82 | static void sda_out(struct fsi_master_gpio *master, int value) | |
83 | { | |
84 | gpiod_set_value(master->gpio_data, value); | |
85 | } | |
86 | ||
87 | static void set_sda_input(struct fsi_master_gpio *master) | |
88 | { | |
89 | gpiod_direction_input(master->gpio_data); | |
90 | gpiod_set_value(master->gpio_trans, 0); | |
91 | } | |
92 | ||
93 | static void set_sda_output(struct fsi_master_gpio *master, int value) | |
94 | { | |
95 | gpiod_set_value(master->gpio_trans, 1); | |
96 | gpiod_direction_output(master->gpio_data, value); | |
97 | } | |
98 | ||
99 | static void clock_zeros(struct fsi_master_gpio *master, int count) | |
100 | { | |
777fd524 | 101 | trace_fsi_master_gpio_clock_zeros(master, count); |
ac0385d9 CB |
102 | set_sda_output(master, 1); |
103 | clock_toggle(master, count); | |
104 | } | |
105 | ||
777fd524 BH |
106 | static void echo_delay(struct fsi_master_gpio *master) |
107 | { | |
108 | clock_zeros(master, master->t_echo_delay); | |
109 | } | |
110 | ||
111 | ||
ac0385d9 CB |
112 | static void serial_in(struct fsi_master_gpio *master, struct fsi_gpio_msg *msg, |
113 | uint8_t num_bits) | |
114 | { | |
115 | uint8_t bit, in_bit; | |
116 | ||
117 | set_sda_input(master); | |
118 | ||
119 | for (bit = 0; bit < num_bits; bit++) { | |
5d0d16f1 | 120 | in_bit = sda_clock_in(master); |
ac0385d9 CB |
121 | msg->msg <<= 1; |
122 | msg->msg |= ~in_bit & 0x1; /* Data is active low */ | |
123 | } | |
124 | msg->bits += num_bits; | |
1247cf7a JK |
125 | |
126 | trace_fsi_master_gpio_in(master, num_bits, msg->msg); | |
ac0385d9 CB |
127 | } |
128 | ||
129 | static void serial_out(struct fsi_master_gpio *master, | |
130 | const struct fsi_gpio_msg *cmd) | |
131 | { | |
132 | uint8_t bit; | |
133 | uint64_t msg = ~cmd->msg; /* Data is active low */ | |
134 | uint64_t sda_mask = 0x1ULL << (cmd->bits - 1); | |
135 | uint64_t last_bit = ~0; | |
136 | int next_bit; | |
137 | ||
1247cf7a JK |
138 | trace_fsi_master_gpio_out(master, cmd->bits, cmd->msg); |
139 | ||
ac0385d9 CB |
140 | if (!cmd->bits) { |
141 | dev_warn(master->dev, "trying to output 0 bits\n"); | |
142 | return; | |
143 | } | |
144 | set_sda_output(master, 0); | |
145 | ||
146 | /* Send the start bit */ | |
147 | sda_out(master, 0); | |
148 | clock_toggle(master, 1); | |
149 | ||
150 | /* Send the message */ | |
151 | for (bit = 0; bit < cmd->bits; bit++) { | |
152 | next_bit = (msg & sda_mask) >> (cmd->bits - 1); | |
153 | if (last_bit ^ next_bit) { | |
154 | sda_out(master, next_bit); | |
155 | last_bit = next_bit; | |
156 | } | |
157 | clock_toggle(master, 1); | |
158 | msg <<= 1; | |
159 | } | |
160 | } | |
161 | ||
162 | static void msg_push_bits(struct fsi_gpio_msg *msg, uint64_t data, int bits) | |
163 | { | |
164 | msg->msg <<= bits; | |
165 | msg->msg |= data & ((1ull << bits) - 1); | |
166 | msg->bits += bits; | |
167 | } | |
168 | ||
169 | static void msg_push_crc(struct fsi_gpio_msg *msg) | |
170 | { | |
171 | uint8_t crc; | |
172 | int top; | |
173 | ||
174 | top = msg->bits & 0x3; | |
175 | ||
176 | /* start bit, and any non-aligned top bits */ | |
177 | crc = crc4(0, 1 << top | msg->msg >> (msg->bits - top), top + 1); | |
178 | ||
179 | /* aligned bits */ | |
180 | crc = crc4(crc, msg->msg, msg->bits - top); | |
181 | ||
182 | msg_push_bits(msg, crc, 4); | |
183 | } | |
184 | ||
0e82e5c1 JK |
185 | static bool check_same_address(struct fsi_master_gpio *master, int id, |
186 | uint32_t addr) | |
187 | { | |
188 | /* this will also handle LAST_ADDR_INVALID */ | |
189 | return master->last_addr == (((id & 0x3) << 21) | (addr & ~0x3)); | |
190 | } | |
191 | ||
192 | static bool check_relative_address(struct fsi_master_gpio *master, int id, | |
193 | uint32_t addr, uint32_t *rel_addrp) | |
194 | { | |
195 | uint32_t last_addr = master->last_addr; | |
196 | int32_t rel_addr; | |
197 | ||
198 | if (last_addr == LAST_ADDR_INVALID) | |
199 | return false; | |
200 | ||
201 | /* We may be in 23-bit addressing mode, which uses the id as the | |
202 | * top two address bits. So, if we're referencing a different ID, | |
203 | * use absolute addresses. | |
204 | */ | |
205 | if (((last_addr >> 21) & 0x3) != id) | |
206 | return false; | |
207 | ||
208 | /* remove the top two bits from any 23-bit addressing */ | |
209 | last_addr &= (1 << 21) - 1; | |
210 | ||
211 | /* We know that the addresses are limited to 21 bits, so this won't | |
212 | * overflow the signed rel_addr */ | |
213 | rel_addr = addr - last_addr; | |
214 | if (rel_addr > 255 || rel_addr < -256) | |
215 | return false; | |
216 | ||
217 | *rel_addrp = (uint32_t)rel_addr; | |
218 | ||
219 | return true; | |
220 | } | |
221 | ||
222 | static void last_address_update(struct fsi_master_gpio *master, | |
223 | int id, bool valid, uint32_t addr) | |
224 | { | |
225 | if (!valid) | |
226 | master->last_addr = LAST_ADDR_INVALID; | |
227 | else | |
228 | master->last_addr = ((id & 0x3) << 21) | (addr & ~0x3); | |
229 | } | |
230 | ||
ac0385d9 | 231 | /* |
0e82e5c1 | 232 | * Encode an Absolute/Relative/Same Address command |
ac0385d9 | 233 | */ |
0e82e5c1 JK |
234 | static void build_ar_command(struct fsi_master_gpio *master, |
235 | struct fsi_gpio_msg *cmd, uint8_t id, | |
236 | uint32_t addr, size_t size, const void *data) | |
ac0385d9 | 237 | { |
0e82e5c1 | 238 | int i, addr_bits, opcode_bits; |
ac0385d9 | 239 | bool write = !!data; |
0e82e5c1 JK |
240 | uint8_t ds, opcode; |
241 | uint32_t rel_addr; | |
ac0385d9 CB |
242 | |
243 | cmd->bits = 0; | |
244 | cmd->msg = 0; | |
245 | ||
0e82e5c1 JK |
246 | /* we have 21 bits of address max */ |
247 | addr &= ((1 << 21) - 1); | |
248 | ||
249 | /* cmd opcodes are variable length - SAME_AR is only two bits */ | |
250 | opcode_bits = 3; | |
251 | ||
252 | if (check_same_address(master, id, addr)) { | |
253 | /* we still address the byte offset within the word */ | |
254 | addr_bits = 2; | |
255 | opcode_bits = 2; | |
55382d30 | 256 | opcode = FSI_CMD_SAME_AR; |
777fd524 | 257 | trace_fsi_master_gpio_cmd_same_addr(master); |
0e82e5c1 JK |
258 | |
259 | } else if (check_relative_address(master, id, addr, &rel_addr)) { | |
260 | /* 8 bits plus sign */ | |
261 | addr_bits = 9; | |
262 | addr = rel_addr; | |
55382d30 | 263 | opcode = FSI_CMD_REL_AR; |
777fd524 | 264 | trace_fsi_master_gpio_cmd_rel_addr(master, rel_addr); |
0e82e5c1 JK |
265 | |
266 | } else { | |
267 | addr_bits = 21; | |
55382d30 | 268 | opcode = FSI_CMD_ABS_AR; |
777fd524 | 269 | trace_fsi_master_gpio_cmd_abs_addr(master, addr); |
0e82e5c1 | 270 | } |
ac0385d9 CB |
271 | |
272 | /* | |
273 | * The read/write size is encoded in the lower bits of the address | |
274 | * (as it must be naturally-aligned), and the following ds bit. | |
275 | * | |
276 | * size addr:1 addr:0 ds | |
277 | * 1 x x 0 | |
278 | * 2 x 0 1 | |
279 | * 4 0 1 1 | |
280 | * | |
281 | */ | |
282 | ds = size > 1 ? 1 : 0; | |
283 | addr &= ~(size - 1); | |
284 | if (size == 4) | |
285 | addr |= 1; | |
286 | ||
0e82e5c1 JK |
287 | msg_push_bits(cmd, id, 2); |
288 | msg_push_bits(cmd, opcode, opcode_bits); | |
289 | msg_push_bits(cmd, write ? 0 : 1, 1); | |
290 | msg_push_bits(cmd, addr, addr_bits); | |
ac0385d9 CB |
291 | msg_push_bits(cmd, ds, 1); |
292 | for (i = 0; write && i < size; i++) | |
293 | msg_push_bits(cmd, ((uint8_t *)data)[i], 8); | |
294 | ||
295 | msg_push_crc(cmd); | |
296 | } | |
297 | ||
298 | static void build_dpoll_command(struct fsi_gpio_msg *cmd, uint8_t slave_id) | |
299 | { | |
300 | cmd->bits = 0; | |
301 | cmd->msg = 0; | |
302 | ||
303 | msg_push_bits(cmd, slave_id, 2); | |
55382d30 | 304 | msg_push_bits(cmd, FSI_CMD_DPOLL, 3); |
ac0385d9 CB |
305 | msg_push_crc(cmd); |
306 | } | |
307 | ||
4e56828a BH |
308 | static void build_epoll_command(struct fsi_gpio_msg *cmd, uint8_t slave_id) |
309 | { | |
310 | cmd->bits = 0; | |
311 | cmd->msg = 0; | |
312 | ||
313 | msg_push_bits(cmd, slave_id, 2); | |
55382d30 | 314 | msg_push_bits(cmd, FSI_CMD_EPOLL, 3); |
4e56828a BH |
315 | msg_push_crc(cmd); |
316 | } | |
317 | ||
ac0385d9 CB |
318 | static void build_term_command(struct fsi_gpio_msg *cmd, uint8_t slave_id) |
319 | { | |
320 | cmd->bits = 0; | |
321 | cmd->msg = 0; | |
322 | ||
323 | msg_push_bits(cmd, slave_id, 2); | |
55382d30 | 324 | msg_push_bits(cmd, FSI_CMD_TERM, 6); |
ac0385d9 CB |
325 | msg_push_crc(cmd); |
326 | } | |
327 | ||
4e56828a BH |
328 | /* |
329 | * Note: callers rely specifically on this returning -EAGAIN for | |
330 | * a CRC error detected in the response. Use other error code | |
331 | * for other situations. It will be converted to something else | |
332 | * higher up the stack before it reaches userspace. | |
333 | */ | |
ac0385d9 CB |
334 | static int read_one_response(struct fsi_master_gpio *master, |
335 | uint8_t data_size, struct fsi_gpio_msg *msgp, uint8_t *tagp) | |
336 | { | |
337 | struct fsi_gpio_msg msg; | |
e5538139 | 338 | unsigned long flags; |
ac0385d9 | 339 | uint32_t crc; |
e5538139 | 340 | uint8_t tag; |
ac0385d9 CB |
341 | int i; |
342 | ||
26d79b27 | 343 | local_irq_save(flags); |
e5538139 | 344 | |
ac0385d9 | 345 | /* wait for the start bit */ |
55382d30 | 346 | for (i = 0; i < FSI_MASTER_MTOE_COUNT; i++) { |
ac0385d9 CB |
347 | msg.bits = 0; |
348 | msg.msg = 0; | |
349 | serial_in(master, &msg, 1); | |
350 | if (msg.msg) | |
351 | break; | |
352 | } | |
55382d30 | 353 | if (i == FSI_MASTER_MTOE_COUNT) { |
ac0385d9 CB |
354 | dev_dbg(master->dev, |
355 | "Master time out waiting for response\n"); | |
26d79b27 | 356 | local_irq_restore(flags); |
4e56828a | 357 | return -ETIMEDOUT; |
ac0385d9 CB |
358 | } |
359 | ||
360 | msg.bits = 0; | |
361 | msg.msg = 0; | |
362 | ||
363 | /* Read slave ID & response tag */ | |
364 | serial_in(master, &msg, 4); | |
365 | ||
ac0385d9 CB |
366 | tag = msg.msg & 0x3; |
367 | ||
368 | /* If we have an ACK and we're expecting data, clock the data in too */ | |
55382d30 | 369 | if (tag == FSI_RESP_ACK && data_size) |
ac0385d9 CB |
370 | serial_in(master, &msg, data_size * 8); |
371 | ||
372 | /* read CRC */ | |
55382d30 | 373 | serial_in(master, &msg, FSI_CRC_SIZE); |
ac0385d9 | 374 | |
26d79b27 | 375 | local_irq_restore(flags); |
e5538139 | 376 | |
ac0385d9 CB |
377 | /* we have a whole message now; check CRC */ |
378 | crc = crc4(0, 1, 1); | |
379 | crc = crc4(crc, msg.msg, msg.bits); | |
380 | if (crc) { | |
c49e3440 BH |
381 | /* Check if it's all 1's, that probably means the host is off */ |
382 | if (((~msg.msg) & ((1ull << msg.bits) - 1)) == 0) | |
383 | return -ENODEV; | |
384 | dev_dbg(master->dev, "ERR response CRC msg: 0x%016llx (%d bits)\n", | |
385 | msg.msg, msg.bits); | |
4e56828a | 386 | return -EAGAIN; |
ac0385d9 CB |
387 | } |
388 | ||
389 | if (msgp) | |
390 | *msgp = msg; | |
391 | if (tagp) | |
392 | *tagp = tag; | |
393 | ||
394 | return 0; | |
395 | } | |
396 | ||
397 | static int issue_term(struct fsi_master_gpio *master, uint8_t slave) | |
398 | { | |
399 | struct fsi_gpio_msg cmd; | |
e5538139 | 400 | unsigned long flags; |
ac0385d9 CB |
401 | uint8_t tag; |
402 | int rc; | |
403 | ||
404 | build_term_command(&cmd, slave); | |
e5538139 | 405 | |
26d79b27 | 406 | local_irq_save(flags); |
ac0385d9 CB |
407 | serial_out(master, &cmd); |
408 | echo_delay(master); | |
26d79b27 | 409 | local_irq_restore(flags); |
ac0385d9 CB |
410 | |
411 | rc = read_one_response(master, 0, NULL, &tag); | |
412 | if (rc < 0) { | |
413 | dev_err(master->dev, | |
414 | "TERM failed; lost communication with slave\n"); | |
415 | return -EIO; | |
55382d30 | 416 | } else if (tag != FSI_RESP_ACK) { |
ac0385d9 CB |
417 | dev_err(master->dev, "TERM failed; response %d\n", tag); |
418 | return -EIO; | |
419 | } | |
420 | ||
421 | return 0; | |
422 | } | |
423 | ||
424 | static int poll_for_response(struct fsi_master_gpio *master, | |
425 | uint8_t slave, uint8_t size, void *data) | |
426 | { | |
427 | struct fsi_gpio_msg response, cmd; | |
428 | int busy_count = 0, rc, i; | |
e5538139 | 429 | unsigned long flags; |
ac0385d9 CB |
430 | uint8_t tag; |
431 | uint8_t *data_byte = data; | |
4e56828a | 432 | int crc_err_retries = 0; |
ac0385d9 CB |
433 | retry: |
434 | rc = read_one_response(master, size, &response, &tag); | |
4e56828a BH |
435 | |
436 | /* Handle retries on CRC errors */ | |
437 | if (rc == -EAGAIN) { | |
438 | /* Too many retries ? */ | |
439 | if (crc_err_retries++ > FSI_CRC_ERR_RETRIES) { | |
440 | /* | |
441 | * Pass it up as a -EIO otherwise upper level will retry | |
442 | * the whole command which isn't what we want here. | |
443 | */ | |
444 | rc = -EIO; | |
445 | goto fail; | |
446 | } | |
447 | dev_dbg(master->dev, | |
448 | "CRC error retry %d\n", crc_err_retries); | |
449 | trace_fsi_master_gpio_crc_rsp_error(master); | |
450 | build_epoll_command(&cmd, slave); | |
26d79b27 | 451 | local_irq_save(flags); |
55382d30 | 452 | clock_zeros(master, FSI_MASTER_EPOLL_CLOCKS); |
4e56828a BH |
453 | serial_out(master, &cmd); |
454 | echo_delay(master); | |
26d79b27 | 455 | local_irq_restore(flags); |
4e56828a BH |
456 | goto retry; |
457 | } else if (rc) | |
458 | goto fail; | |
ac0385d9 CB |
459 | |
460 | switch (tag) { | |
55382d30 | 461 | case FSI_RESP_ACK: |
ac0385d9 CB |
462 | if (size && data) { |
463 | uint64_t val = response.msg; | |
464 | /* clear crc & mask */ | |
465 | val >>= 4; | |
466 | val &= (1ull << (size * 8)) - 1; | |
467 | ||
468 | for (i = 0; i < size; i++) { | |
469 | data_byte[size-i-1] = val; | |
470 | val >>= 8; | |
471 | } | |
472 | } | |
473 | break; | |
55382d30 | 474 | case FSI_RESP_BUSY: |
ac0385d9 CB |
475 | /* |
476 | * Its necessary to clock slave before issuing | |
477 | * d-poll, not indicated in the hardware protocol | |
478 | * spec. < 20 clocks causes slave to hang, 21 ok. | |
479 | */ | |
55382d30 | 480 | if (busy_count++ < FSI_MASTER_MAX_BUSY) { |
ac0385d9 | 481 | build_dpoll_command(&cmd, slave); |
26d79b27 | 482 | local_irq_save(flags); |
55382d30 | 483 | clock_zeros(master, FSI_MASTER_DPOLL_CLOCKS); |
ac0385d9 CB |
484 | serial_out(master, &cmd); |
485 | echo_delay(master); | |
26d79b27 | 486 | local_irq_restore(flags); |
ac0385d9 CB |
487 | goto retry; |
488 | } | |
489 | dev_warn(master->dev, | |
490 | "ERR slave is stuck in busy state, issuing TERM\n"); | |
26d79b27 | 491 | local_irq_save(flags); |
55382d30 | 492 | clock_zeros(master, FSI_MASTER_DPOLL_CLOCKS); |
26d79b27 | 493 | local_irq_restore(flags); |
ac0385d9 CB |
494 | issue_term(master, slave); |
495 | rc = -EIO; | |
496 | break; | |
497 | ||
55382d30 | 498 | case FSI_RESP_ERRA: |
4e56828a | 499 | dev_dbg(master->dev, "ERRA received: 0x%x\n", (int)response.msg); |
ac0385d9 CB |
500 | rc = -EIO; |
501 | break; | |
55382d30 | 502 | case FSI_RESP_ERRC: |
4e56828a | 503 | dev_dbg(master->dev, "ERRC received: 0x%x\n", (int)response.msg); |
4e56828a BH |
504 | trace_fsi_master_gpio_crc_cmd_error(master); |
505 | rc = -EAGAIN; | |
506 | break; | |
ac0385d9 CB |
507 | } |
508 | ||
918da951 AJ |
509 | if (busy_count > 0) |
510 | trace_fsi_master_gpio_poll_response_busy(master, busy_count); | |
4e56828a | 511 | fail: |
edc24851 BH |
512 | /* |
513 | * tSendDelay clocks, avoids signal reflections when switching | |
514 | * from receive of response back to send of data. | |
515 | */ | |
26d79b27 | 516 | local_irq_save(flags); |
75854c14 | 517 | clock_zeros(master, master->t_send_delay); |
26d79b27 JK |
518 | local_irq_restore(flags); |
519 | ||
ac0385d9 CB |
520 | return rc; |
521 | } | |
522 | ||
e5538139 JK |
523 | static int send_request(struct fsi_master_gpio *master, |
524 | struct fsi_gpio_msg *cmd) | |
ac0385d9 CB |
525 | { |
526 | unsigned long flags; | |
b8bd146d | 527 | |
26d79b27 | 528 | if (master->external_mode) |
b8bd146d | 529 | return -EBUSY; |
b8bd146d | 530 | |
26d79b27 | 531 | local_irq_save(flags); |
ac0385d9 CB |
532 | serial_out(master, cmd); |
533 | echo_delay(master); | |
26d79b27 | 534 | local_irq_restore(flags); |
e5538139 JK |
535 | |
536 | return 0; | |
537 | } | |
538 | ||
539 | static int fsi_master_gpio_xfer(struct fsi_master_gpio *master, uint8_t slave, | |
540 | struct fsi_gpio_msg *cmd, size_t resp_len, void *resp) | |
541 | { | |
4e56828a | 542 | int rc = -EAGAIN, retries = 0; |
e5538139 | 543 | |
4e56828a BH |
544 | while ((retries++) < FSI_CRC_ERR_RETRIES) { |
545 | rc = send_request(master, cmd); | |
546 | if (rc) | |
547 | break; | |
e5538139 | 548 | rc = poll_for_response(master, slave, resp_len, resp); |
4e56828a BH |
549 | if (rc != -EAGAIN) |
550 | break; | |
551 | rc = -EIO; | |
552 | dev_warn(master->dev, "ECRC retry %d\n", retries); | |
553 | ||
554 | /* Pace it a bit before retry */ | |
555 | msleep(1); | |
556 | } | |
e5538139 | 557 | |
ac0385d9 CB |
558 | return rc; |
559 | } | |
560 | ||
561 | static int fsi_master_gpio_read(struct fsi_master *_master, int link, | |
562 | uint8_t id, uint32_t addr, void *val, size_t size) | |
563 | { | |
564 | struct fsi_master_gpio *master = to_fsi_master_gpio(_master); | |
565 | struct fsi_gpio_msg cmd; | |
8193fb44 | 566 | int rc; |
ac0385d9 CB |
567 | |
568 | if (link != 0) | |
569 | return -ENODEV; | |
570 | ||
8193fb44 | 571 | mutex_lock(&master->cmd_lock); |
0e82e5c1 | 572 | build_ar_command(master, &cmd, id, addr, size, NULL); |
8193fb44 | 573 | rc = fsi_master_gpio_xfer(master, id, &cmd, size, val); |
0e82e5c1 | 574 | last_address_update(master, id, rc == 0, addr); |
8193fb44 JK |
575 | mutex_unlock(&master->cmd_lock); |
576 | ||
577 | return rc; | |
ac0385d9 CB |
578 | } |
579 | ||
580 | static int fsi_master_gpio_write(struct fsi_master *_master, int link, | |
581 | uint8_t id, uint32_t addr, const void *val, size_t size) | |
582 | { | |
583 | struct fsi_master_gpio *master = to_fsi_master_gpio(_master); | |
584 | struct fsi_gpio_msg cmd; | |
8193fb44 | 585 | int rc; |
ac0385d9 CB |
586 | |
587 | if (link != 0) | |
588 | return -ENODEV; | |
589 | ||
8193fb44 | 590 | mutex_lock(&master->cmd_lock); |
0e82e5c1 | 591 | build_ar_command(master, &cmd, id, addr, size, val); |
8193fb44 | 592 | rc = fsi_master_gpio_xfer(master, id, &cmd, 0, NULL); |
0e82e5c1 | 593 | last_address_update(master, id, rc == 0, addr); |
8193fb44 JK |
594 | mutex_unlock(&master->cmd_lock); |
595 | ||
596 | return rc; | |
ac0385d9 CB |
597 | } |
598 | ||
599 | static int fsi_master_gpio_term(struct fsi_master *_master, | |
600 | int link, uint8_t id) | |
601 | { | |
602 | struct fsi_master_gpio *master = to_fsi_master_gpio(_master); | |
603 | struct fsi_gpio_msg cmd; | |
8193fb44 | 604 | int rc; |
ac0385d9 CB |
605 | |
606 | if (link != 0) | |
607 | return -ENODEV; | |
608 | ||
8193fb44 | 609 | mutex_lock(&master->cmd_lock); |
ac0385d9 | 610 | build_term_command(&cmd, id); |
8193fb44 | 611 | rc = fsi_master_gpio_xfer(master, id, &cmd, 0, NULL); |
0e82e5c1 | 612 | last_address_update(master, id, false, 0); |
8193fb44 JK |
613 | mutex_unlock(&master->cmd_lock); |
614 | ||
615 | return rc; | |
ac0385d9 CB |
616 | } |
617 | ||
618 | static int fsi_master_gpio_break(struct fsi_master *_master, int link) | |
619 | { | |
620 | struct fsi_master_gpio *master = to_fsi_master_gpio(_master); | |
29d9b927 | 621 | unsigned long flags; |
ac0385d9 CB |
622 | |
623 | if (link != 0) | |
624 | return -ENODEV; | |
625 | ||
1247cf7a JK |
626 | trace_fsi_master_gpio_break(master); |
627 | ||
e5538139 | 628 | mutex_lock(&master->cmd_lock); |
b8bd146d | 629 | if (master->external_mode) { |
e5538139 | 630 | mutex_unlock(&master->cmd_lock); |
b8bd146d JK |
631 | return -EBUSY; |
632 | } | |
e5538139 | 633 | |
26d79b27 | 634 | local_irq_save(flags); |
e5538139 | 635 | |
ac0385d9 CB |
636 | set_sda_output(master, 1); |
637 | sda_out(master, 1); | |
638 | clock_toggle(master, FSI_PRE_BREAK_CLOCKS); | |
639 | sda_out(master, 0); | |
640 | clock_toggle(master, FSI_BREAK_CLOCKS); | |
641 | echo_delay(master); | |
642 | sda_out(master, 1); | |
643 | clock_toggle(master, FSI_POST_BREAK_CLOCKS); | |
e5538139 | 644 | |
26d79b27 JK |
645 | local_irq_restore(flags); |
646 | ||
0e82e5c1 | 647 | last_address_update(master, 0, false, 0); |
e5538139 | 648 | mutex_unlock(&master->cmd_lock); |
ac0385d9 CB |
649 | |
650 | /* Wait for logic reset to take effect */ | |
651 | udelay(200); | |
652 | ||
653 | return 0; | |
654 | } | |
655 | ||
656 | static void fsi_master_gpio_init(struct fsi_master_gpio *master) | |
657 | { | |
e5538139 JK |
658 | unsigned long flags; |
659 | ||
ac0385d9 CB |
660 | gpiod_direction_output(master->gpio_mux, 1); |
661 | gpiod_direction_output(master->gpio_trans, 1); | |
662 | gpiod_direction_output(master->gpio_enable, 1); | |
663 | gpiod_direction_output(master->gpio_clk, 1); | |
664 | gpiod_direction_output(master->gpio_data, 1); | |
665 | ||
666 | /* todo: evaluate if clocks can be reduced */ | |
26d79b27 | 667 | local_irq_save(flags); |
ac0385d9 | 668 | clock_zeros(master, FSI_INIT_CLOCKS); |
26d79b27 | 669 | local_irq_restore(flags); |
ac0385d9 CB |
670 | } |
671 | ||
b8bd146d JK |
672 | static void fsi_master_gpio_init_external(struct fsi_master_gpio *master) |
673 | { | |
674 | gpiod_direction_output(master->gpio_mux, 0); | |
675 | gpiod_direction_output(master->gpio_trans, 0); | |
676 | gpiod_direction_output(master->gpio_enable, 1); | |
677 | gpiod_direction_input(master->gpio_clk); | |
678 | gpiod_direction_input(master->gpio_data); | |
679 | } | |
680 | ||
04635a30 EJ |
681 | static int fsi_master_gpio_link_enable(struct fsi_master *_master, int link, |
682 | bool enable) | |
ac0385d9 CB |
683 | { |
684 | struct fsi_master_gpio *master = to_fsi_master_gpio(_master); | |
b8bd146d | 685 | int rc = -EBUSY; |
ac0385d9 CB |
686 | |
687 | if (link != 0) | |
688 | return -ENODEV; | |
29d9b927 | 689 | |
e5538139 | 690 | mutex_lock(&master->cmd_lock); |
b8bd146d | 691 | if (!master->external_mode) { |
04635a30 | 692 | gpiod_set_value(master->gpio_enable, enable ? 1 : 0); |
b8bd146d JK |
693 | rc = 0; |
694 | } | |
e5538139 | 695 | mutex_unlock(&master->cmd_lock); |
ac0385d9 | 696 | |
b8bd146d JK |
697 | return rc; |
698 | } | |
699 | ||
75854c14 BH |
700 | static int fsi_master_gpio_link_config(struct fsi_master *_master, int link, |
701 | u8 t_send_delay, u8 t_echo_delay) | |
702 | { | |
703 | struct fsi_master_gpio *master = to_fsi_master_gpio(_master); | |
704 | ||
705 | if (link != 0) | |
706 | return -ENODEV; | |
707 | ||
708 | mutex_lock(&master->cmd_lock); | |
709 | master->t_send_delay = t_send_delay; | |
710 | master->t_echo_delay = t_echo_delay; | |
711 | mutex_unlock(&master->cmd_lock); | |
712 | ||
713 | return 0; | |
714 | } | |
715 | ||
b8bd146d JK |
716 | static ssize_t external_mode_show(struct device *dev, |
717 | struct device_attribute *attr, char *buf) | |
718 | { | |
719 | struct fsi_master_gpio *master = dev_get_drvdata(dev); | |
720 | ||
721 | return snprintf(buf, PAGE_SIZE - 1, "%u\n", | |
722 | master->external_mode ? 1 : 0); | |
723 | } | |
724 | ||
725 | static ssize_t external_mode_store(struct device *dev, | |
726 | struct device_attribute *attr, const char *buf, size_t count) | |
727 | { | |
728 | struct fsi_master_gpio *master = dev_get_drvdata(dev); | |
e5538139 | 729 | unsigned long val; |
b8bd146d JK |
730 | bool external_mode; |
731 | int err; | |
732 | ||
733 | err = kstrtoul(buf, 0, &val); | |
734 | if (err) | |
735 | return err; | |
736 | ||
737 | external_mode = !!val; | |
738 | ||
e5538139 | 739 | mutex_lock(&master->cmd_lock); |
b8bd146d JK |
740 | |
741 | if (external_mode == master->external_mode) { | |
e5538139 | 742 | mutex_unlock(&master->cmd_lock); |
b8bd146d JK |
743 | return count; |
744 | } | |
745 | ||
746 | master->external_mode = external_mode; | |
747 | if (master->external_mode) | |
748 | fsi_master_gpio_init_external(master); | |
749 | else | |
750 | fsi_master_gpio_init(master); | |
e5538139 JK |
751 | |
752 | mutex_unlock(&master->cmd_lock); | |
b8bd146d JK |
753 | |
754 | fsi_master_rescan(&master->master); | |
755 | ||
756 | return count; | |
ac0385d9 CB |
757 | } |
758 | ||
b8bd146d JK |
759 | static DEVICE_ATTR(external_mode, 0664, |
760 | external_mode_show, external_mode_store); | |
761 | ||
8ef9ccf8 BH |
762 | static void fsi_master_gpio_release(struct device *dev) |
763 | { | |
d5d8dfb0 | 764 | struct fsi_master_gpio *master = to_fsi_master_gpio(to_fsi_master(dev)); |
8ef9ccf8 BH |
765 | |
766 | of_node_put(dev_of_node(master->dev)); | |
767 | ||
768 | kfree(master); | |
769 | } | |
770 | ||
ac0385d9 CB |
771 | static int fsi_master_gpio_probe(struct platform_device *pdev) |
772 | { | |
773 | struct fsi_master_gpio *master; | |
774 | struct gpio_desc *gpio; | |
b8bd146d | 775 | int rc; |
ac0385d9 | 776 | |
8ef9ccf8 | 777 | master = kzalloc(sizeof(*master), GFP_KERNEL); |
ac0385d9 CB |
778 | if (!master) |
779 | return -ENOMEM; | |
780 | ||
781 | master->dev = &pdev->dev; | |
782 | master->master.dev.parent = master->dev; | |
f6a2f8eb | 783 | master->master.dev.of_node = of_node_get(dev_of_node(master->dev)); |
8ef9ccf8 | 784 | master->master.dev.release = fsi_master_gpio_release; |
0e82e5c1 | 785 | master->last_addr = LAST_ADDR_INVALID; |
ac0385d9 CB |
786 | |
787 | gpio = devm_gpiod_get(&pdev->dev, "clock", 0); | |
788 | if (IS_ERR(gpio)) { | |
789 | dev_err(&pdev->dev, "failed to get clock gpio\n"); | |
8ef9ccf8 BH |
790 | rc = PTR_ERR(gpio); |
791 | goto err_free; | |
ac0385d9 CB |
792 | } |
793 | master->gpio_clk = gpio; | |
794 | ||
795 | gpio = devm_gpiod_get(&pdev->dev, "data", 0); | |
796 | if (IS_ERR(gpio)) { | |
797 | dev_err(&pdev->dev, "failed to get data gpio\n"); | |
8ef9ccf8 BH |
798 | rc = PTR_ERR(gpio); |
799 | goto err_free; | |
ac0385d9 CB |
800 | } |
801 | master->gpio_data = gpio; | |
802 | ||
803 | /* Optional GPIOs */ | |
804 | gpio = devm_gpiod_get_optional(&pdev->dev, "trans", 0); | |
805 | if (IS_ERR(gpio)) { | |
806 | dev_err(&pdev->dev, "failed to get trans gpio\n"); | |
8ef9ccf8 BH |
807 | rc = PTR_ERR(gpio); |
808 | goto err_free; | |
ac0385d9 CB |
809 | } |
810 | master->gpio_trans = gpio; | |
811 | ||
812 | gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 0); | |
813 | if (IS_ERR(gpio)) { | |
814 | dev_err(&pdev->dev, "failed to get enable gpio\n"); | |
8ef9ccf8 BH |
815 | rc = PTR_ERR(gpio); |
816 | goto err_free; | |
ac0385d9 CB |
817 | } |
818 | master->gpio_enable = gpio; | |
819 | ||
820 | gpio = devm_gpiod_get_optional(&pdev->dev, "mux", 0); | |
821 | if (IS_ERR(gpio)) { | |
822 | dev_err(&pdev->dev, "failed to get mux gpio\n"); | |
8ef9ccf8 BH |
823 | rc = PTR_ERR(gpio); |
824 | goto err_free; | |
ac0385d9 CB |
825 | } |
826 | master->gpio_mux = gpio; | |
827 | ||
bc1099d2 BH |
828 | /* |
829 | * Check if GPIO block is slow enought that no extra delays | |
830 | * are necessary. This improves performance on ast2500 by | |
831 | * an order of magnitude. | |
832 | */ | |
833 | master->no_delays = device_property_present(&pdev->dev, "no-gpio-delays"); | |
834 | ||
75854c14 BH |
835 | /* Default FSI command delays */ |
836 | master->t_send_delay = FSI_SEND_DELAY_CLOCKS; | |
837 | master->t_echo_delay = FSI_ECHO_DELAY_CLOCKS; | |
838 | ||
ac0385d9 | 839 | master->master.n_links = 1; |
4af889b0 | 840 | master->master.flags = FSI_MASTER_FLAG_SWCLOCK; |
ac0385d9 CB |
841 | master->master.read = fsi_master_gpio_read; |
842 | master->master.write = fsi_master_gpio_write; | |
843 | master->master.term = fsi_master_gpio_term; | |
844 | master->master.send_break = fsi_master_gpio_break; | |
845 | master->master.link_enable = fsi_master_gpio_link_enable; | |
75854c14 | 846 | master->master.link_config = fsi_master_gpio_link_config; |
ac0385d9 | 847 | platform_set_drvdata(pdev, master); |
e5538139 | 848 | mutex_init(&master->cmd_lock); |
ac0385d9 CB |
849 | |
850 | fsi_master_gpio_init(master); | |
851 | ||
b8bd146d JK |
852 | rc = device_create_file(&pdev->dev, &dev_attr_external_mode); |
853 | if (rc) | |
8ef9ccf8 | 854 | goto err_free; |
b8bd146d | 855 | |
8ef9ccf8 BH |
856 | rc = fsi_master_register(&master->master); |
857 | if (rc) { | |
858 | device_remove_file(&pdev->dev, &dev_attr_external_mode); | |
859 | put_device(&master->master.dev); | |
860 | return rc; | |
861 | } | |
862 | return 0; | |
863 | err_free: | |
864 | kfree(master); | |
865 | return rc; | |
ac0385d9 CB |
866 | } |
867 | ||
868 | ||
8ef9ccf8 | 869 | |
ac0385d9 CB |
870 | static int fsi_master_gpio_remove(struct platform_device *pdev) |
871 | { | |
872 | struct fsi_master_gpio *master = platform_get_drvdata(pdev); | |
873 | ||
8ef9ccf8 | 874 | device_remove_file(&pdev->dev, &dev_attr_external_mode); |
ac0385d9 | 875 | |
8ef9ccf8 | 876 | fsi_master_unregister(&master->master); |
f6a2f8eb | 877 | |
ac0385d9 CB |
878 | return 0; |
879 | } | |
880 | ||
881 | static const struct of_device_id fsi_master_gpio_match[] = { | |
882 | { .compatible = "fsi-master-gpio" }, | |
883 | { }, | |
884 | }; | |
19a52178 | 885 | MODULE_DEVICE_TABLE(of, fsi_master_gpio_match); |
ac0385d9 CB |
886 | |
887 | static struct platform_driver fsi_master_gpio_driver = { | |
888 | .driver = { | |
889 | .name = "fsi-master-gpio", | |
890 | .of_match_table = fsi_master_gpio_match, | |
891 | }, | |
892 | .probe = fsi_master_gpio_probe, | |
893 | .remove = fsi_master_gpio_remove, | |
894 | }; | |
895 | ||
896 | module_platform_driver(fsi_master_gpio_driver); | |
897 | MODULE_LICENSE("GPL"); |