1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // Copyright 2018 IBM Corp |
3 | /* |
4 | * A FSI master controller, using a simple GPIO bit-banging interface |
5 | */ |
6 | |
7 | #include <linux/crc4.h> |
8 | #include <linux/delay.h> |
9 | #include <linux/device.h> |
10 | #include <linux/fsi.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/io.h> |
13 | #include <linux/irqflags.h> |
14 | #include <linux/module.h> |
15 | #include <linux/of.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/regmap.h> |
19 | #include <linux/firmware.h> |
20 | #include <linux/gpio/aspeed.h> |
21 | #include <linux/mfd/syscon.h> |
22 | #include <linux/of_address.h> |
23 | #include <linux/genalloc.h> |
24 | |
25 | #include "fsi-master.h" |
26 | #include "cf-fsi-fw.h" |
27 | |
28 | #define FW_FILE_NAME "cf-fsi-fw.bin" |
29 | |
30 | /* Common SCU based coprocessor control registers */ |
31 | #define SCU_COPRO_CTRL 0x100 |
32 | #define SCU_COPRO_RESET 0x00000002 |
33 | #define SCU_COPRO_CLK_EN 0x00000001 |
34 | |
35 | /* AST2500 specific ones */ |
36 | #define SCU_2500_COPRO_SEG0 0x104 |
37 | #define SCU_2500_COPRO_SEG1 0x108 |
38 | #define SCU_2500_COPRO_SEG2 0x10c |
39 | #define SCU_2500_COPRO_SEG3 0x110 |
40 | #define SCU_2500_COPRO_SEG4 0x114 |
41 | #define SCU_2500_COPRO_SEG5 0x118 |
42 | #define SCU_2500_COPRO_SEG6 0x11c |
43 | #define SCU_2500_COPRO_SEG7 0x120 |
44 | #define SCU_2500_COPRO_SEG8 0x124 |
45 | #define SCU_2500_COPRO_SEG_SWAP 0x00000001 |
46 | #define SCU_2500_COPRO_CACHE_CTL 0x128 |
47 | #define SCU_2500_COPRO_CACHE_EN 0x00000001 |
48 | #define SCU_2500_COPRO_SEG0_CACHE_EN 0x00000002 |
49 | #define SCU_2500_COPRO_SEG1_CACHE_EN 0x00000004 |
50 | #define SCU_2500_COPRO_SEG2_CACHE_EN 0x00000008 |
51 | #define SCU_2500_COPRO_SEG3_CACHE_EN 0x00000010 |
52 | #define SCU_2500_COPRO_SEG4_CACHE_EN 0x00000020 |
53 | #define SCU_2500_COPRO_SEG5_CACHE_EN 0x00000040 |
54 | #define SCU_2500_COPRO_SEG6_CACHE_EN 0x00000080 |
55 | #define SCU_2500_COPRO_SEG7_CACHE_EN 0x00000100 |
56 | #define SCU_2500_COPRO_SEG8_CACHE_EN 0x00000200 |
57 | |
58 | #define SCU_2400_COPRO_SEG0 0x104 |
59 | #define SCU_2400_COPRO_SEG2 0x108 |
60 | #define SCU_2400_COPRO_SEG4 0x10c |
61 | #define SCU_2400_COPRO_SEG6 0x110 |
62 | #define SCU_2400_COPRO_SEG8 0x114 |
63 | #define SCU_2400_COPRO_SEG_SWAP 0x80000000 |
64 | #define SCU_2400_COPRO_CACHE_CTL 0x118 |
65 | #define SCU_2400_COPRO_CACHE_EN 0x00000001 |
66 | #define SCU_2400_COPRO_SEG0_CACHE_EN 0x00000002 |
67 | #define SCU_2400_COPRO_SEG2_CACHE_EN 0x00000004 |
68 | #define SCU_2400_COPRO_SEG4_CACHE_EN 0x00000008 |
69 | #define SCU_2400_COPRO_SEG6_CACHE_EN 0x00000010 |
70 | #define SCU_2400_COPRO_SEG8_CACHE_EN 0x00000020 |
71 | |
72 | /* CVIC registers */ |
73 | #define CVIC_EN_REG 0x10 |
74 | #define CVIC_TRIG_REG 0x18 |
75 | |
76 | /* |
77 | * System register base address (needed for configuring the |
78 | * coldfire maps) |
79 | */ |
80 | #define SYSREG_BASE 0x1e600000 |
81 | |
82 | /* Amount of SRAM required */ |
83 | #define SRAM_SIZE 0x1000 |
84 | |
85 | #define LAST_ADDR_INVALID 0x1 |
86 | |
87 | struct fsi_master_acf { |
88 | struct fsi_master master; |
89 | struct device *dev; |
90 | struct regmap *scu; |
91 | struct mutex lock; /* mutex for command ordering */ |
92 | struct gpio_desc *gpio_clk; |
93 | struct gpio_desc *gpio_data; |
94 | struct gpio_desc *gpio_trans; /* Voltage translator */ |
95 | struct gpio_desc *gpio_enable; /* FSI enable */ |
96 | struct gpio_desc *gpio_mux; /* Mux control */ |
97 | uint16_t gpio_clk_vreg; |
98 | uint16_t gpio_clk_dreg; |
99 | uint16_t gpio_dat_vreg; |
100 | uint16_t gpio_dat_dreg; |
101 | uint16_t gpio_tra_vreg; |
102 | uint16_t gpio_tra_dreg; |
103 | uint8_t gpio_clk_bit; |
104 | uint8_t gpio_dat_bit; |
105 | uint8_t gpio_tra_bit; |
106 | uint32_t cf_mem_addr; |
107 | size_t cf_mem_size; |
108 | void __iomem *cf_mem; |
109 | void __iomem *cvic; |
110 | struct gen_pool *sram_pool; |
111 | void __iomem *sram; |
112 | bool is_ast2500; |
113 | bool external_mode; |
114 | bool trace_enabled; |
115 | uint32_t last_addr; |
116 | uint8_t t_send_delay; |
117 | uint8_t t_echo_delay; |
118 | uint32_t cvic_sw_irq; |
119 | }; |
120 | #define to_fsi_master_acf(m) container_of(m, struct fsi_master_acf, master) |
121 | |
122 | struct fsi_msg { |
123 | uint64_t msg; |
124 | uint8_t bits; |
125 | }; |
126 | |
127 | #define CREATE_TRACE_POINTS |
128 | #include <trace/events/fsi_master_ast_cf.h> |
129 | |
130 | static void msg_push_bits(struct fsi_msg *msg, uint64_t data, int bits) |
131 | { |
132 | msg->msg <<= bits; |
133 | msg->msg |= data & ((1ull << bits) - 1); |
134 | msg->bits += bits; |
135 | } |
136 | |
137 | static void msg_push_crc(struct fsi_msg *msg) |
138 | { |
139 | uint8_t crc; |
140 | int top; |
141 | |
142 | top = msg->bits & 0x3; |
143 | |
144 | /* start bit, and any non-aligned top bits */ |
145 | crc = crc4(c: 0, x: 1 << top | msg->msg >> (msg->bits - top), bits: top + 1); |
146 | |
147 | /* aligned bits */ |
148 | crc = crc4(c: crc, x: msg->msg, bits: msg->bits - top); |
149 | |
150 | msg_push_bits(msg, data: crc, bits: 4); |
151 | } |
152 | |
153 | static void msg_finish_cmd(struct fsi_msg *cmd) |
154 | { |
155 | /* Left align message */ |
156 | cmd->msg <<= (64 - cmd->bits); |
157 | } |
158 | |
159 | static bool check_same_address(struct fsi_master_acf *master, int id, |
160 | uint32_t addr) |
161 | { |
162 | /* this will also handle LAST_ADDR_INVALID */ |
163 | return master->last_addr == (((id & 0x3) << 21) | (addr & ~0x3)); |
164 | } |
165 | |
166 | static bool check_relative_address(struct fsi_master_acf *master, int id, |
167 | uint32_t addr, uint32_t *rel_addrp) |
168 | { |
169 | uint32_t last_addr = master->last_addr; |
170 | int32_t rel_addr; |
171 | |
172 | if (last_addr == LAST_ADDR_INVALID) |
173 | return false; |
174 | |
175 | /* We may be in 23-bit addressing mode, which uses the id as the |
176 | * top two address bits. So, if we're referencing a different ID, |
177 | * use absolute addresses. |
178 | */ |
179 | if (((last_addr >> 21) & 0x3) != id) |
180 | return false; |
181 | |
182 | /* remove the top two bits from any 23-bit addressing */ |
183 | last_addr &= (1 << 21) - 1; |
184 | |
185 | /* We know that the addresses are limited to 21 bits, so this won't |
186 | * overflow the signed rel_addr */ |
187 | rel_addr = addr - last_addr; |
188 | if (rel_addr > 255 || rel_addr < -256) |
189 | return false; |
190 | |
191 | *rel_addrp = (uint32_t)rel_addr; |
192 | |
193 | return true; |
194 | } |
195 | |
196 | static void last_address_update(struct fsi_master_acf *master, |
197 | int id, bool valid, uint32_t addr) |
198 | { |
199 | if (!valid) |
200 | master->last_addr = LAST_ADDR_INVALID; |
201 | else |
202 | master->last_addr = ((id & 0x3) << 21) | (addr & ~0x3); |
203 | } |
204 | |
205 | /* |
206 | * Encode an Absolute/Relative/Same Address command |
207 | */ |
208 | static void build_ar_command(struct fsi_master_acf *master, |
209 | struct fsi_msg *cmd, uint8_t id, |
210 | uint32_t addr, size_t size, |
211 | const void *data) |
212 | { |
213 | int i, addr_bits, opcode_bits; |
214 | bool write = !!data; |
215 | uint8_t ds, opcode; |
216 | uint32_t rel_addr; |
217 | |
218 | cmd->bits = 0; |
219 | cmd->msg = 0; |
220 | |
221 | /* we have 21 bits of address max */ |
222 | addr &= ((1 << 21) - 1); |
223 | |
224 | /* cmd opcodes are variable length - SAME_AR is only two bits */ |
225 | opcode_bits = 3; |
226 | |
227 | if (check_same_address(master, id, addr)) { |
228 | /* we still address the byte offset within the word */ |
229 | addr_bits = 2; |
230 | opcode_bits = 2; |
231 | opcode = FSI_CMD_SAME_AR; |
232 | trace_fsi_master_acf_cmd_same_addr(master); |
233 | |
234 | } else if (check_relative_address(master, id, addr, rel_addrp: &rel_addr)) { |
235 | /* 8 bits plus sign */ |
236 | addr_bits = 9; |
237 | addr = rel_addr; |
238 | opcode = FSI_CMD_REL_AR; |
239 | trace_fsi_master_acf_cmd_rel_addr(master, rel_addr); |
240 | |
241 | } else { |
242 | addr_bits = 21; |
243 | opcode = FSI_CMD_ABS_AR; |
244 | trace_fsi_master_acf_cmd_abs_addr(master, addr); |
245 | } |
246 | |
247 | /* |
248 | * The read/write size is encoded in the lower bits of the address |
249 | * (as it must be naturally-aligned), and the following ds bit. |
250 | * |
251 | * size addr:1 addr:0 ds |
252 | * 1 x x 0 |
253 | * 2 x 0 1 |
254 | * 4 0 1 1 |
255 | * |
256 | */ |
257 | ds = size > 1 ? 1 : 0; |
258 | addr &= ~(size - 1); |
259 | if (size == 4) |
260 | addr |= 1; |
261 | |
262 | msg_push_bits(msg: cmd, data: id, bits: 2); |
263 | msg_push_bits(msg: cmd, data: opcode, bits: opcode_bits); |
264 | msg_push_bits(msg: cmd, data: write ? 0 : 1, bits: 1); |
265 | msg_push_bits(msg: cmd, data: addr, bits: addr_bits); |
266 | msg_push_bits(msg: cmd, data: ds, bits: 1); |
267 | for (i = 0; write && i < size; i++) |
268 | msg_push_bits(msg: cmd, data: ((uint8_t *)data)[i], bits: 8); |
269 | |
270 | msg_push_crc(msg: cmd); |
271 | msg_finish_cmd(cmd); |
272 | } |
273 | |
274 | static void build_dpoll_command(struct fsi_msg *cmd, uint8_t slave_id) |
275 | { |
276 | cmd->bits = 0; |
277 | cmd->msg = 0; |
278 | |
279 | msg_push_bits(msg: cmd, data: slave_id, bits: 2); |
280 | msg_push_bits(msg: cmd, FSI_CMD_DPOLL, bits: 3); |
281 | msg_push_crc(msg: cmd); |
282 | msg_finish_cmd(cmd); |
283 | } |
284 | |
285 | static void build_epoll_command(struct fsi_msg *cmd, uint8_t slave_id) |
286 | { |
287 | cmd->bits = 0; |
288 | cmd->msg = 0; |
289 | |
290 | msg_push_bits(msg: cmd, data: slave_id, bits: 2); |
291 | msg_push_bits(msg: cmd, FSI_CMD_EPOLL, bits: 3); |
292 | msg_push_crc(msg: cmd); |
293 | msg_finish_cmd(cmd); |
294 | } |
295 | |
296 | static void build_term_command(struct fsi_msg *cmd, uint8_t slave_id) |
297 | { |
298 | cmd->bits = 0; |
299 | cmd->msg = 0; |
300 | |
301 | msg_push_bits(msg: cmd, data: slave_id, bits: 2); |
302 | msg_push_bits(msg: cmd, FSI_CMD_TERM, bits: 6); |
303 | msg_push_crc(msg: cmd); |
304 | msg_finish_cmd(cmd); |
305 | } |
306 | |
307 | static int do_copro_command(struct fsi_master_acf *master, uint32_t op) |
308 | { |
309 | uint32_t timeout = 10000000; |
310 | uint8_t stat; |
311 | |
312 | trace_fsi_master_acf_copro_command(master, op); |
313 | |
314 | /* Send command */ |
315 | iowrite32be(op, master->sram + CMD_STAT_REG); |
316 | |
317 | /* Ring doorbell if any */ |
318 | if (master->cvic) |
319 | iowrite32(0x2, master->cvic + CVIC_TRIG_REG); |
320 | |
321 | /* Wait for status to indicate completion (or error) */ |
322 | do { |
323 | if (timeout-- == 0) { |
324 | dev_warn(master->dev, |
325 | "Timeout waiting for coprocessor completion\n" ); |
326 | return -ETIMEDOUT; |
327 | } |
328 | stat = ioread8(master->sram + CMD_STAT_REG); |
329 | } while(stat < STAT_COMPLETE || stat == 0xff); |
330 | |
331 | if (stat == STAT_COMPLETE) |
332 | return 0; |
333 | switch(stat) { |
334 | case STAT_ERR_INVAL_CMD: |
335 | return -EINVAL; |
336 | case STAT_ERR_INVAL_IRQ: |
337 | return -EIO; |
338 | case STAT_ERR_MTOE: |
339 | return -ESHUTDOWN; |
340 | } |
341 | return -ENXIO; |
342 | } |
343 | |
344 | static int clock_zeros(struct fsi_master_acf *master, int count) |
345 | { |
346 | while (count) { |
347 | int rc, lcnt = min(count, 255); |
348 | |
349 | rc = do_copro_command(master, |
350 | CMD_IDLE_CLOCKS | (lcnt << CMD_REG_CLEN_SHIFT)); |
351 | if (rc) |
352 | return rc; |
353 | count -= lcnt; |
354 | } |
355 | return 0; |
356 | } |
357 | |
358 | static int send_request(struct fsi_master_acf *master, struct fsi_msg *cmd, |
359 | unsigned int resp_bits) |
360 | { |
361 | uint32_t op; |
362 | |
363 | trace_fsi_master_acf_send_request(master, cmd, rbits: resp_bits); |
364 | |
365 | /* Store message into SRAM */ |
366 | iowrite32be((cmd->msg >> 32), master->sram + CMD_DATA); |
367 | iowrite32be((cmd->msg & 0xffffffff), master->sram + CMD_DATA + 4); |
368 | |
369 | op = CMD_COMMAND; |
370 | op |= cmd->bits << CMD_REG_CLEN_SHIFT; |
371 | if (resp_bits) |
372 | op |= resp_bits << CMD_REG_RLEN_SHIFT; |
373 | |
374 | return do_copro_command(master, op); |
375 | } |
376 | |
377 | static int read_copro_response(struct fsi_master_acf *master, uint8_t size, |
378 | uint32_t *response, u8 *tag) |
379 | { |
380 | uint8_t rtag = ioread8(master->sram + STAT_RTAG) & 0xf; |
381 | uint8_t rcrc = ioread8(master->sram + STAT_RCRC) & 0xf; |
382 | uint32_t rdata = 0; |
383 | uint32_t crc; |
384 | uint8_t ack; |
385 | |
386 | *tag = ack = rtag & 3; |
387 | |
388 | /* we have a whole message now; check CRC */ |
389 | crc = crc4(c: 0, x: 1, bits: 1); |
390 | crc = crc4(c: crc, x: rtag, bits: 4); |
391 | if (ack == FSI_RESP_ACK && size) { |
392 | rdata = ioread32be(master->sram + RSP_DATA); |
393 | crc = crc4(c: crc, x: rdata, bits: size); |
394 | if (response) |
395 | *response = rdata; |
396 | } |
397 | crc = crc4(c: crc, x: rcrc, bits: 4); |
398 | |
399 | trace_fsi_master_acf_copro_response(master, rtag, rcrc, rdata, crc_ok: crc == 0); |
400 | |
401 | if (crc) { |
402 | /* |
403 | * Check if it's all 1's or all 0's, that probably means |
404 | * the host is off |
405 | */ |
406 | if ((rtag == 0xf && rcrc == 0xf) || (rtag == 0 && rcrc == 0)) |
407 | return -ENODEV; |
408 | dev_dbg(master->dev, "Bad response CRC !\n" ); |
409 | return -EAGAIN; |
410 | } |
411 | return 0; |
412 | } |
413 | |
414 | static int send_term(struct fsi_master_acf *master, uint8_t slave) |
415 | { |
416 | struct fsi_msg cmd; |
417 | uint8_t tag; |
418 | int rc; |
419 | |
420 | build_term_command(cmd: &cmd, slave_id: slave); |
421 | |
422 | rc = send_request(master, cmd: &cmd, resp_bits: 0); |
423 | if (rc) { |
424 | dev_warn(master->dev, "Error %d sending term\n" , rc); |
425 | return rc; |
426 | } |
427 | |
428 | rc = read_copro_response(master, size: 0, NULL, tag: &tag); |
429 | if (rc < 0) { |
430 | dev_err(master->dev, |
431 | "TERM failed; lost communication with slave\n" ); |
432 | return -EIO; |
433 | } else if (tag != FSI_RESP_ACK) { |
434 | dev_err(master->dev, "TERM failed; response %d\n" , tag); |
435 | return -EIO; |
436 | } |
437 | return 0; |
438 | } |
439 | |
440 | static void dump_ucode_trace(struct fsi_master_acf *master) |
441 | { |
442 | char trbuf[52]; |
443 | char *p; |
444 | int i; |
445 | |
446 | dev_dbg(master->dev, |
447 | "CMDSTAT:%08x RTAG=%02x RCRC=%02x RDATA=%02x #INT=%08x\n" , |
448 | ioread32be(master->sram + CMD_STAT_REG), |
449 | ioread8(master->sram + STAT_RTAG), |
450 | ioread8(master->sram + STAT_RCRC), |
451 | ioread32be(master->sram + RSP_DATA), |
452 | ioread32be(master->sram + INT_CNT)); |
453 | |
454 | for (i = 0; i < 512; i++) { |
455 | uint8_t v; |
456 | if ((i % 16) == 0) |
457 | p = trbuf; |
458 | v = ioread8(master->sram + TRACEBUF + i); |
459 | p += sprintf(buf: p, fmt: "%02x " , v); |
460 | if (((i % 16) == 15) || v == TR_END) |
461 | dev_dbg(master->dev, "%s\n" , trbuf); |
462 | if (v == TR_END) |
463 | break; |
464 | } |
465 | } |
466 | |
467 | static int handle_response(struct fsi_master_acf *master, |
468 | uint8_t slave, uint8_t size, void *data) |
469 | { |
470 | int busy_count = 0, rc; |
471 | int crc_err_retries = 0; |
472 | struct fsi_msg cmd; |
473 | uint32_t response; |
474 | uint8_t tag; |
475 | retry: |
476 | rc = read_copro_response(master, size, response: &response, tag: &tag); |
477 | |
478 | /* Handle retries on CRC errors */ |
479 | if (rc == -EAGAIN) { |
480 | /* Too many retries ? */ |
481 | if (crc_err_retries++ > FSI_CRC_ERR_RETRIES) { |
482 | /* |
483 | * Pass it up as a -EIO otherwise upper level will retry |
484 | * the whole command which isn't what we want here. |
485 | */ |
486 | rc = -EIO; |
487 | goto bail; |
488 | } |
489 | trace_fsi_master_acf_crc_rsp_error(master, retries: crc_err_retries); |
490 | if (master->trace_enabled) |
491 | dump_ucode_trace(master); |
492 | rc = clock_zeros(master, FSI_MASTER_EPOLL_CLOCKS); |
493 | if (rc) { |
494 | dev_warn(master->dev, |
495 | "Error %d clocking zeros for E_POLL\n" , rc); |
496 | return rc; |
497 | } |
498 | build_epoll_command(cmd: &cmd, slave_id: slave); |
499 | rc = send_request(master, cmd: &cmd, resp_bits: size); |
500 | if (rc) { |
501 | dev_warn(master->dev, "Error %d sending E_POLL\n" , rc); |
502 | return -EIO; |
503 | } |
504 | goto retry; |
505 | } |
506 | if (rc) |
507 | return rc; |
508 | |
509 | switch (tag) { |
510 | case FSI_RESP_ACK: |
511 | if (size && data) { |
512 | if (size == 32) |
513 | *(__be32 *)data = cpu_to_be32(response); |
514 | else if (size == 16) |
515 | *(__be16 *)data = cpu_to_be16(response); |
516 | else |
517 | *(u8 *)data = response; |
518 | } |
519 | break; |
520 | case FSI_RESP_BUSY: |
521 | /* |
522 | * Its necessary to clock slave before issuing |
523 | * d-poll, not indicated in the hardware protocol |
524 | * spec. < 20 clocks causes slave to hang, 21 ok. |
525 | */ |
526 | dev_dbg(master->dev, "Busy, retrying...\n" ); |
527 | if (master->trace_enabled) |
528 | dump_ucode_trace(master); |
529 | rc = clock_zeros(master, FSI_MASTER_DPOLL_CLOCKS); |
530 | if (rc) { |
531 | dev_warn(master->dev, |
532 | "Error %d clocking zeros for D_POLL\n" , rc); |
533 | break; |
534 | } |
535 | if (busy_count++ < FSI_MASTER_MAX_BUSY) { |
536 | build_dpoll_command(cmd: &cmd, slave_id: slave); |
537 | rc = send_request(master, cmd: &cmd, resp_bits: size); |
538 | if (rc) { |
539 | dev_warn(master->dev, "Error %d sending D_POLL\n" , rc); |
540 | break; |
541 | } |
542 | goto retry; |
543 | } |
544 | dev_dbg(master->dev, |
545 | "ERR slave is stuck in busy state, issuing TERM\n" ); |
546 | send_term(master, slave); |
547 | rc = -EIO; |
548 | break; |
549 | |
550 | case FSI_RESP_ERRA: |
551 | dev_dbg(master->dev, "ERRA received\n" ); |
552 | if (master->trace_enabled) |
553 | dump_ucode_trace(master); |
554 | rc = -EIO; |
555 | break; |
556 | case FSI_RESP_ERRC: |
557 | dev_dbg(master->dev, "ERRC received\n" ); |
558 | if (master->trace_enabled) |
559 | dump_ucode_trace(master); |
560 | rc = -EAGAIN; |
561 | break; |
562 | } |
563 | bail: |
564 | if (busy_count > 0) { |
565 | trace_fsi_master_acf_poll_response_busy(master, busy_count); |
566 | } |
567 | |
568 | return rc; |
569 | } |
570 | |
571 | static int fsi_master_acf_xfer(struct fsi_master_acf *master, uint8_t slave, |
572 | struct fsi_msg *cmd, size_t resp_len, void *resp) |
573 | { |
574 | int rc = -EAGAIN, retries = 0; |
575 | |
576 | resp_len <<= 3; |
577 | while ((retries++) < FSI_CRC_ERR_RETRIES) { |
578 | rc = send_request(master, cmd, resp_bits: resp_len); |
579 | if (rc) { |
580 | if (rc != -ESHUTDOWN) |
581 | dev_warn(master->dev, "Error %d sending command\n" , rc); |
582 | break; |
583 | } |
584 | rc = handle_response(master, slave, size: resp_len, data: resp); |
585 | if (rc != -EAGAIN) |
586 | break; |
587 | rc = -EIO; |
588 | dev_dbg(master->dev, "ECRC retry %d\n" , retries); |
589 | |
590 | /* Pace it a bit before retry */ |
591 | msleep(msecs: 1); |
592 | } |
593 | |
594 | return rc; |
595 | } |
596 | |
597 | static int fsi_master_acf_read(struct fsi_master *_master, int link, |
598 | uint8_t id, uint32_t addr, void *val, |
599 | size_t size) |
600 | { |
601 | struct fsi_master_acf *master = to_fsi_master_acf(_master); |
602 | struct fsi_msg cmd; |
603 | int rc; |
604 | |
605 | if (link != 0) |
606 | return -ENODEV; |
607 | |
608 | mutex_lock(&master->lock); |
609 | dev_dbg(master->dev, "read id %d addr %x size %zd\n" , id, addr, size); |
610 | build_ar_command(master, cmd: &cmd, id, addr, size, NULL); |
611 | rc = fsi_master_acf_xfer(master, slave: id, cmd: &cmd, resp_len: size, resp: val); |
612 | last_address_update(master, id, valid: rc == 0, addr); |
613 | if (rc) |
614 | dev_dbg(master->dev, "read id %d addr 0x%08x err: %d\n" , |
615 | id, addr, rc); |
616 | mutex_unlock(lock: &master->lock); |
617 | |
618 | return rc; |
619 | } |
620 | |
621 | static int fsi_master_acf_write(struct fsi_master *_master, int link, |
622 | uint8_t id, uint32_t addr, const void *val, |
623 | size_t size) |
624 | { |
625 | struct fsi_master_acf *master = to_fsi_master_acf(_master); |
626 | struct fsi_msg cmd; |
627 | int rc; |
628 | |
629 | if (link != 0) |
630 | return -ENODEV; |
631 | |
632 | mutex_lock(&master->lock); |
633 | build_ar_command(master, cmd: &cmd, id, addr, size, data: val); |
634 | dev_dbg(master->dev, "write id %d addr %x size %zd raw_data: %08x\n" , |
635 | id, addr, size, *(uint32_t *)val); |
636 | rc = fsi_master_acf_xfer(master, slave: id, cmd: &cmd, resp_len: 0, NULL); |
637 | last_address_update(master, id, valid: rc == 0, addr); |
638 | if (rc) |
639 | dev_dbg(master->dev, "write id %d addr 0x%08x err: %d\n" , |
640 | id, addr, rc); |
641 | mutex_unlock(lock: &master->lock); |
642 | |
643 | return rc; |
644 | } |
645 | |
646 | static int fsi_master_acf_term(struct fsi_master *_master, |
647 | int link, uint8_t id) |
648 | { |
649 | struct fsi_master_acf *master = to_fsi_master_acf(_master); |
650 | struct fsi_msg cmd; |
651 | int rc; |
652 | |
653 | if (link != 0) |
654 | return -ENODEV; |
655 | |
656 | mutex_lock(&master->lock); |
657 | build_term_command(cmd: &cmd, slave_id: id); |
658 | dev_dbg(master->dev, "term id %d\n" , id); |
659 | rc = fsi_master_acf_xfer(master, slave: id, cmd: &cmd, resp_len: 0, NULL); |
660 | last_address_update(master, id, valid: false, addr: 0); |
661 | mutex_unlock(lock: &master->lock); |
662 | |
663 | return rc; |
664 | } |
665 | |
666 | static int fsi_master_acf_break(struct fsi_master *_master, int link) |
667 | { |
668 | struct fsi_master_acf *master = to_fsi_master_acf(_master); |
669 | int rc; |
670 | |
671 | if (link != 0) |
672 | return -ENODEV; |
673 | |
674 | mutex_lock(&master->lock); |
675 | if (master->external_mode) { |
676 | mutex_unlock(lock: &master->lock); |
677 | return -EBUSY; |
678 | } |
679 | dev_dbg(master->dev, "sending BREAK\n" ); |
680 | rc = do_copro_command(master, CMD_BREAK); |
681 | last_address_update(master, id: 0, valid: false, addr: 0); |
682 | mutex_unlock(lock: &master->lock); |
683 | |
684 | /* Wait for logic reset to take effect */ |
685 | udelay(200); |
686 | |
687 | return rc; |
688 | } |
689 | |
690 | static void reset_cf(struct fsi_master_acf *master) |
691 | { |
692 | regmap_write(map: master->scu, SCU_COPRO_CTRL, SCU_COPRO_RESET); |
693 | usleep_range(min: 20,max: 20); |
694 | regmap_write(map: master->scu, SCU_COPRO_CTRL, val: 0); |
695 | usleep_range(min: 20,max: 20); |
696 | } |
697 | |
698 | static void start_cf(struct fsi_master_acf *master) |
699 | { |
700 | regmap_write(map: master->scu, SCU_COPRO_CTRL, SCU_COPRO_CLK_EN); |
701 | } |
702 | |
703 | static void setup_ast2500_cf_maps(struct fsi_master_acf *master) |
704 | { |
705 | /* |
706 | * Note about byteswap setting: the bus is wired backwards, |
707 | * so setting the byteswap bit actually makes the ColdFire |
708 | * work "normally" for a BE processor, ie, put the MSB in |
709 | * the lowest address byte. |
710 | * |
711 | * We thus need to set the bit for our main memory which |
712 | * contains our program code. We create two mappings for |
713 | * the register, one with each setting. |
714 | * |
715 | * Segments 2 and 3 has a "swapped" mapping (BE) |
716 | * and 6 and 7 have a non-swapped mapping (LE) which allows |
717 | * us to avoid byteswapping register accesses since the |
718 | * registers are all LE. |
719 | */ |
720 | |
721 | /* Setup segment 0 to our memory region */ |
722 | regmap_write(map: master->scu, SCU_2500_COPRO_SEG0, val: master->cf_mem_addr | |
723 | SCU_2500_COPRO_SEG_SWAP); |
724 | |
725 | /* Segments 2 and 3 to sysregs with byteswap (for SRAM) */ |
726 | regmap_write(map: master->scu, SCU_2500_COPRO_SEG2, SYSREG_BASE | |
727 | SCU_2500_COPRO_SEG_SWAP); |
728 | regmap_write(map: master->scu, SCU_2500_COPRO_SEG3, SYSREG_BASE | 0x100000 | |
729 | SCU_2500_COPRO_SEG_SWAP); |
730 | |
731 | /* And segment 6 and 7 to sysregs no byteswap */ |
732 | regmap_write(map: master->scu, SCU_2500_COPRO_SEG6, SYSREG_BASE); |
733 | regmap_write(map: master->scu, SCU_2500_COPRO_SEG7, SYSREG_BASE | 0x100000); |
734 | |
735 | /* Memory cachable, regs and SRAM not cachable */ |
736 | regmap_write(map: master->scu, SCU_2500_COPRO_CACHE_CTL, |
737 | SCU_2500_COPRO_SEG0_CACHE_EN | SCU_2500_COPRO_CACHE_EN); |
738 | } |
739 | |
740 | static void setup_ast2400_cf_maps(struct fsi_master_acf *master) |
741 | { |
742 | /* Setup segment 0 to our memory region */ |
743 | regmap_write(map: master->scu, SCU_2400_COPRO_SEG0, val: master->cf_mem_addr | |
744 | SCU_2400_COPRO_SEG_SWAP); |
745 | |
746 | /* Segments 2 to sysregs with byteswap (for SRAM) */ |
747 | regmap_write(map: master->scu, SCU_2400_COPRO_SEG2, SYSREG_BASE | |
748 | SCU_2400_COPRO_SEG_SWAP); |
749 | |
750 | /* And segment 6 to sysregs no byteswap */ |
751 | regmap_write(map: master->scu, SCU_2400_COPRO_SEG6, SYSREG_BASE); |
752 | |
753 | /* Memory cachable, regs and SRAM not cachable */ |
754 | regmap_write(map: master->scu, SCU_2400_COPRO_CACHE_CTL, |
755 | SCU_2400_COPRO_SEG0_CACHE_EN | SCU_2400_COPRO_CACHE_EN); |
756 | } |
757 | |
758 | static void setup_common_fw_config(struct fsi_master_acf *master, |
759 | void __iomem *base) |
760 | { |
761 | iowrite16be(master->gpio_clk_vreg, base + HDR_CLOCK_GPIO_VADDR); |
762 | iowrite16be(master->gpio_clk_dreg, base + HDR_CLOCK_GPIO_DADDR); |
763 | iowrite16be(master->gpio_dat_vreg, base + HDR_DATA_GPIO_VADDR); |
764 | iowrite16be(master->gpio_dat_dreg, base + HDR_DATA_GPIO_DADDR); |
765 | iowrite16be(master->gpio_tra_vreg, base + HDR_TRANS_GPIO_VADDR); |
766 | iowrite16be(master->gpio_tra_dreg, base + HDR_TRANS_GPIO_DADDR); |
767 | iowrite8(master->gpio_clk_bit, base + HDR_CLOCK_GPIO_BIT); |
768 | iowrite8(master->gpio_dat_bit, base + HDR_DATA_GPIO_BIT); |
769 | iowrite8(master->gpio_tra_bit, base + HDR_TRANS_GPIO_BIT); |
770 | } |
771 | |
772 | static void setup_ast2500_fw_config(struct fsi_master_acf *master) |
773 | { |
774 | void __iomem *base = master->cf_mem + HDR_OFFSET; |
775 | |
776 | setup_common_fw_config(master, base); |
777 | iowrite32be(FW_CONTROL_USE_STOP, base + HDR_FW_CONTROL); |
778 | } |
779 | |
780 | static void setup_ast2400_fw_config(struct fsi_master_acf *master) |
781 | { |
782 | void __iomem *base = master->cf_mem + HDR_OFFSET; |
783 | |
784 | setup_common_fw_config(master, base); |
785 | iowrite32be(FW_CONTROL_CONT_CLOCK|FW_CONTROL_DUMMY_RD, base + HDR_FW_CONTROL); |
786 | } |
787 | |
788 | static int setup_gpios_for_copro(struct fsi_master_acf *master) |
789 | { |
790 | |
791 | int rc; |
792 | |
793 | /* This aren't under ColdFire control, just set them up appropriately */ |
794 | gpiod_direction_output(desc: master->gpio_mux, value: 1); |
795 | gpiod_direction_output(desc: master->gpio_enable, value: 1); |
796 | |
797 | /* Those are under ColdFire control, let it configure them */ |
798 | rc = aspeed_gpio_copro_grab_gpio(desc: master->gpio_clk, vreg_offset: &master->gpio_clk_vreg, |
799 | dreg_offset: &master->gpio_clk_dreg, bit: &master->gpio_clk_bit); |
800 | if (rc) { |
801 | dev_err(master->dev, "failed to assign clock gpio to coprocessor\n" ); |
802 | return rc; |
803 | } |
804 | rc = aspeed_gpio_copro_grab_gpio(desc: master->gpio_data, vreg_offset: &master->gpio_dat_vreg, |
805 | dreg_offset: &master->gpio_dat_dreg, bit: &master->gpio_dat_bit); |
806 | if (rc) { |
807 | dev_err(master->dev, "failed to assign data gpio to coprocessor\n" ); |
808 | aspeed_gpio_copro_release_gpio(desc: master->gpio_clk); |
809 | return rc; |
810 | } |
811 | rc = aspeed_gpio_copro_grab_gpio(desc: master->gpio_trans, vreg_offset: &master->gpio_tra_vreg, |
812 | dreg_offset: &master->gpio_tra_dreg, bit: &master->gpio_tra_bit); |
813 | if (rc) { |
814 | dev_err(master->dev, "failed to assign trans gpio to coprocessor\n" ); |
815 | aspeed_gpio_copro_release_gpio(desc: master->gpio_clk); |
816 | aspeed_gpio_copro_release_gpio(desc: master->gpio_data); |
817 | return rc; |
818 | } |
819 | return 0; |
820 | } |
821 | |
822 | static void release_copro_gpios(struct fsi_master_acf *master) |
823 | { |
824 | aspeed_gpio_copro_release_gpio(desc: master->gpio_clk); |
825 | aspeed_gpio_copro_release_gpio(desc: master->gpio_data); |
826 | aspeed_gpio_copro_release_gpio(desc: master->gpio_trans); |
827 | } |
828 | |
829 | static int load_copro_firmware(struct fsi_master_acf *master) |
830 | { |
831 | const struct firmware *fw; |
832 | uint16_t sig = 0, wanted_sig; |
833 | const u8 *data; |
834 | size_t size = 0; |
835 | int rc; |
836 | |
837 | /* Get the binary */ |
838 | rc = request_firmware(fw: &fw, FW_FILE_NAME, device: master->dev); |
839 | if (rc) { |
840 | dev_err( |
841 | master->dev, "Error %d to load firmware '%s' !\n" , |
842 | rc, FW_FILE_NAME); |
843 | return rc; |
844 | } |
845 | |
846 | /* Which image do we want ? (shared vs. split clock/data GPIOs) */ |
847 | if (master->gpio_clk_vreg == master->gpio_dat_vreg) |
848 | wanted_sig = SYS_SIG_SHARED; |
849 | else |
850 | wanted_sig = SYS_SIG_SPLIT; |
851 | dev_dbg(master->dev, "Looking for image sig %04x\n" , wanted_sig); |
852 | |
853 | /* Try to find it */ |
854 | for (data = fw->data; data < (fw->data + fw->size);) { |
855 | sig = be16_to_cpup(p: (__be16 *)(data + HDR_OFFSET + HDR_SYS_SIG)); |
856 | size = be32_to_cpup(p: (__be32 *)(data + HDR_OFFSET + HDR_FW_SIZE)); |
857 | if (sig == wanted_sig) |
858 | break; |
859 | data += size; |
860 | } |
861 | if (sig != wanted_sig) { |
862 | dev_err(master->dev, "Failed to locate image sig %04x in FW blob\n" , |
863 | wanted_sig); |
864 | rc = -ENODEV; |
865 | goto release_fw; |
866 | } |
867 | if (size > master->cf_mem_size) { |
868 | dev_err(master->dev, "FW size (%zd) bigger than memory reserve (%zd)\n" , |
869 | fw->size, master->cf_mem_size); |
870 | rc = -ENOMEM; |
871 | } else { |
872 | memcpy_toio(master->cf_mem, data, size); |
873 | } |
874 | |
875 | release_fw: |
876 | release_firmware(fw); |
877 | return rc; |
878 | } |
879 | |
880 | static int check_firmware_image(struct fsi_master_acf *master) |
881 | { |
882 | uint32_t fw_vers, fw_api, fw_options; |
883 | |
884 | fw_vers = ioread16be(master->cf_mem + HDR_OFFSET + HDR_FW_VERS); |
885 | fw_api = ioread16be(master->cf_mem + HDR_OFFSET + HDR_API_VERS); |
886 | fw_options = ioread32be(master->cf_mem + HDR_OFFSET + HDR_FW_OPTIONS); |
887 | master->trace_enabled = !!(fw_options & FW_OPTION_TRACE_EN); |
888 | |
889 | /* Check version and signature */ |
890 | dev_info(master->dev, "ColdFire initialized, firmware v%d API v%d.%d (trace %s)\n" , |
891 | fw_vers, fw_api >> 8, fw_api & 0xff, |
892 | master->trace_enabled ? "enabled" : "disabled" ); |
893 | |
894 | if ((fw_api >> 8) != API_VERSION_MAJ) { |
895 | dev_err(master->dev, "Unsupported coprocessor API version !\n" ); |
896 | return -ENODEV; |
897 | } |
898 | |
899 | return 0; |
900 | } |
901 | |
902 | static int copro_enable_sw_irq(struct fsi_master_acf *master) |
903 | { |
904 | int timeout; |
905 | uint32_t val; |
906 | |
907 | /* |
908 | * Enable coprocessor interrupt input. I've had problems getting the |
909 | * value to stick, so try in a loop |
910 | */ |
911 | for (timeout = 0; timeout < 10; timeout++) { |
912 | iowrite32(0x2, master->cvic + CVIC_EN_REG); |
913 | val = ioread32(master->cvic + CVIC_EN_REG); |
914 | if (val & 2) |
915 | break; |
916 | msleep(msecs: 1); |
917 | } |
918 | if (!(val & 2)) { |
919 | dev_err(master->dev, "Failed to enable coprocessor interrupt !\n" ); |
920 | return -ENODEV; |
921 | } |
922 | return 0; |
923 | } |
924 | |
925 | static int fsi_master_acf_setup(struct fsi_master_acf *master) |
926 | { |
927 | int timeout, rc; |
928 | uint32_t val; |
929 | |
930 | /* Make sure the ColdFire is stopped */ |
931 | reset_cf(master); |
932 | |
933 | /* |
934 | * Clear SRAM. This needs to happen before we setup the GPIOs |
935 | * as we might start trying to arbitrate as soon as that happens. |
936 | */ |
937 | memset_io(master->sram, 0, SRAM_SIZE); |
938 | |
939 | /* Configure GPIOs */ |
940 | rc = setup_gpios_for_copro(master); |
941 | if (rc) |
942 | return rc; |
943 | |
944 | /* Load the firmware into the reserved memory */ |
945 | rc = load_copro_firmware(master); |
946 | if (rc) |
947 | return rc; |
948 | |
949 | /* Read signature and check versions */ |
950 | rc = check_firmware_image(master); |
951 | if (rc) |
952 | return rc; |
953 | |
954 | /* Setup coldfire memory map */ |
955 | if (master->is_ast2500) { |
956 | setup_ast2500_cf_maps(master); |
957 | setup_ast2500_fw_config(master); |
958 | } else { |
959 | setup_ast2400_cf_maps(master); |
960 | setup_ast2400_fw_config(master); |
961 | } |
962 | |
963 | /* Start the ColdFire */ |
964 | start_cf(master); |
965 | |
966 | /* Wait for status register to indicate command completion |
967 | * which signals the initialization is complete |
968 | */ |
969 | for (timeout = 0; timeout < 10; timeout++) { |
970 | val = ioread8(master->sram + CF_STARTED); |
971 | if (val) |
972 | break; |
973 | msleep(msecs: 1); |
974 | } |
975 | if (!val) { |
976 | dev_err(master->dev, "Coprocessor startup timeout !\n" ); |
977 | rc = -ENODEV; |
978 | goto err; |
979 | } |
980 | |
981 | /* Configure echo & send delay */ |
982 | iowrite8(master->t_send_delay, master->sram + SEND_DLY_REG); |
983 | iowrite8(master->t_echo_delay, master->sram + ECHO_DLY_REG); |
984 | |
985 | /* Enable SW interrupt to copro if any */ |
986 | if (master->cvic) { |
987 | rc = copro_enable_sw_irq(master); |
988 | if (rc) |
989 | goto err; |
990 | } |
991 | return 0; |
992 | err: |
993 | /* An error occurred, don't leave the coprocessor running */ |
994 | reset_cf(master); |
995 | |
996 | /* Release the GPIOs */ |
997 | release_copro_gpios(master); |
998 | |
999 | return rc; |
1000 | } |
1001 | |
1002 | |
1003 | static void fsi_master_acf_terminate(struct fsi_master_acf *master) |
1004 | { |
1005 | unsigned long flags; |
1006 | |
1007 | /* |
1008 | * A GPIO arbitration requestion could come in while this is |
1009 | * happening. To avoid problems, we disable interrupts so it |
1010 | * cannot preempt us on this CPU |
1011 | */ |
1012 | |
1013 | local_irq_save(flags); |
1014 | |
1015 | /* Stop the coprocessor */ |
1016 | reset_cf(master); |
1017 | |
1018 | /* We mark the copro not-started */ |
1019 | iowrite32(0, master->sram + CF_STARTED); |
1020 | |
1021 | /* We mark the ARB register as having given up arbitration to |
1022 | * deal with a potential race with the arbitration request |
1023 | */ |
1024 | iowrite8(ARB_ARM_ACK, master->sram + ARB_REG); |
1025 | |
1026 | local_irq_restore(flags); |
1027 | |
1028 | /* Return the GPIOs to the ARM */ |
1029 | release_copro_gpios(master); |
1030 | } |
1031 | |
1032 | static void fsi_master_acf_setup_external(struct fsi_master_acf *master) |
1033 | { |
1034 | /* Setup GPIOs for external FSI master (FSP box) */ |
1035 | gpiod_direction_output(desc: master->gpio_mux, value: 0); |
1036 | gpiod_direction_output(desc: master->gpio_trans, value: 0); |
1037 | gpiod_direction_output(desc: master->gpio_enable, value: 1); |
1038 | gpiod_direction_input(desc: master->gpio_clk); |
1039 | gpiod_direction_input(desc: master->gpio_data); |
1040 | } |
1041 | |
1042 | static int fsi_master_acf_link_enable(struct fsi_master *_master, int link, |
1043 | bool enable) |
1044 | { |
1045 | struct fsi_master_acf *master = to_fsi_master_acf(_master); |
1046 | int rc = -EBUSY; |
1047 | |
1048 | if (link != 0) |
1049 | return -ENODEV; |
1050 | |
1051 | mutex_lock(&master->lock); |
1052 | if (!master->external_mode) { |
1053 | gpiod_set_value(desc: master->gpio_enable, value: enable ? 1 : 0); |
1054 | rc = 0; |
1055 | } |
1056 | mutex_unlock(lock: &master->lock); |
1057 | |
1058 | return rc; |
1059 | } |
1060 | |
1061 | static int fsi_master_acf_link_config(struct fsi_master *_master, int link, |
1062 | u8 t_send_delay, u8 t_echo_delay) |
1063 | { |
1064 | struct fsi_master_acf *master = to_fsi_master_acf(_master); |
1065 | |
1066 | if (link != 0) |
1067 | return -ENODEV; |
1068 | |
1069 | mutex_lock(&master->lock); |
1070 | master->t_send_delay = t_send_delay; |
1071 | master->t_echo_delay = t_echo_delay; |
1072 | dev_dbg(master->dev, "Changing delays: send=%d echo=%d\n" , |
1073 | t_send_delay, t_echo_delay); |
1074 | iowrite8(master->t_send_delay, master->sram + SEND_DLY_REG); |
1075 | iowrite8(master->t_echo_delay, master->sram + ECHO_DLY_REG); |
1076 | mutex_unlock(lock: &master->lock); |
1077 | |
1078 | return 0; |
1079 | } |
1080 | |
1081 | static ssize_t external_mode_show(struct device *dev, |
1082 | struct device_attribute *attr, char *buf) |
1083 | { |
1084 | struct fsi_master_acf *master = dev_get_drvdata(dev); |
1085 | |
1086 | return snprintf(buf, PAGE_SIZE - 1, fmt: "%u\n" , |
1087 | master->external_mode ? 1 : 0); |
1088 | } |
1089 | |
1090 | static ssize_t external_mode_store(struct device *dev, |
1091 | struct device_attribute *attr, const char *buf, size_t count) |
1092 | { |
1093 | struct fsi_master_acf *master = dev_get_drvdata(dev); |
1094 | unsigned long val; |
1095 | bool external_mode; |
1096 | int err; |
1097 | |
1098 | err = kstrtoul(s: buf, base: 0, res: &val); |
1099 | if (err) |
1100 | return err; |
1101 | |
1102 | external_mode = !!val; |
1103 | |
1104 | mutex_lock(&master->lock); |
1105 | |
1106 | if (external_mode == master->external_mode) { |
1107 | mutex_unlock(lock: &master->lock); |
1108 | return count; |
1109 | } |
1110 | |
1111 | master->external_mode = external_mode; |
1112 | if (master->external_mode) { |
1113 | fsi_master_acf_terminate(master); |
1114 | fsi_master_acf_setup_external(master); |
1115 | } else |
1116 | fsi_master_acf_setup(master); |
1117 | |
1118 | mutex_unlock(lock: &master->lock); |
1119 | |
1120 | fsi_master_rescan(master: &master->master); |
1121 | |
1122 | return count; |
1123 | } |
1124 | |
1125 | static DEVICE_ATTR(external_mode, 0664, |
1126 | external_mode_show, external_mode_store); |
1127 | |
1128 | static int fsi_master_acf_gpio_request(void *data) |
1129 | { |
1130 | struct fsi_master_acf *master = data; |
1131 | int timeout; |
1132 | u8 val; |
1133 | |
1134 | /* Note: This doesn't require holding out mutex */ |
1135 | |
1136 | /* Write request */ |
1137 | iowrite8(ARB_ARM_REQ, master->sram + ARB_REG); |
1138 | |
1139 | /* |
1140 | * There is a race (which does happen at boot time) when we get an |
1141 | * arbitration request as we are either about to or just starting |
1142 | * the coprocessor. |
1143 | * |
1144 | * To handle it, we first check if we are running. If not yet we |
1145 | * check whether the copro is started in the SCU. |
1146 | * |
1147 | * If it's not started, we can basically just assume we have arbitration |
1148 | * and return. Otherwise, we wait normally expecting for the arbitration |
1149 | * to eventually complete. |
1150 | */ |
1151 | if (ioread32(master->sram + CF_STARTED) == 0) { |
1152 | unsigned int reg = 0; |
1153 | |
1154 | regmap_read(map: master->scu, SCU_COPRO_CTRL, val: ®); |
1155 | if (!(reg & SCU_COPRO_CLK_EN)) |
1156 | return 0; |
1157 | } |
1158 | |
1159 | /* Ring doorbell if any */ |
1160 | if (master->cvic) |
1161 | iowrite32(0x2, master->cvic + CVIC_TRIG_REG); |
1162 | |
1163 | for (timeout = 0; timeout < 10000; timeout++) { |
1164 | val = ioread8(master->sram + ARB_REG); |
1165 | if (val != ARB_ARM_REQ) |
1166 | break; |
1167 | udelay(1); |
1168 | } |
1169 | |
1170 | /* If it failed, override anyway */ |
1171 | if (val != ARB_ARM_ACK) |
1172 | dev_warn(master->dev, "GPIO request arbitration timeout\n" ); |
1173 | |
1174 | return 0; |
1175 | } |
1176 | |
1177 | static int fsi_master_acf_gpio_release(void *data) |
1178 | { |
1179 | struct fsi_master_acf *master = data; |
1180 | |
1181 | /* Write release */ |
1182 | iowrite8(0, master->sram + ARB_REG); |
1183 | |
1184 | /* Ring doorbell if any */ |
1185 | if (master->cvic) |
1186 | iowrite32(0x2, master->cvic + CVIC_TRIG_REG); |
1187 | |
1188 | return 0; |
1189 | } |
1190 | |
1191 | static void fsi_master_acf_release(struct device *dev) |
1192 | { |
1193 | struct fsi_master_acf *master = to_fsi_master_acf(to_fsi_master(dev)); |
1194 | |
1195 | /* Cleanup, stop coprocessor */ |
1196 | mutex_lock(&master->lock); |
1197 | fsi_master_acf_terminate(master); |
1198 | aspeed_gpio_copro_set_ops(NULL, NULL); |
1199 | mutex_unlock(lock: &master->lock); |
1200 | |
1201 | /* Free resources */ |
1202 | gen_pool_free(pool: master->sram_pool, addr: (unsigned long)master->sram, SRAM_SIZE); |
1203 | of_node_put(node: dev_of_node(dev: master->dev)); |
1204 | |
1205 | kfree(objp: master); |
1206 | } |
1207 | |
1208 | static const struct aspeed_gpio_copro_ops fsi_master_acf_gpio_ops = { |
1209 | .request_access = fsi_master_acf_gpio_request, |
1210 | .release_access = fsi_master_acf_gpio_release, |
1211 | }; |
1212 | |
1213 | static int fsi_master_acf_probe(struct platform_device *pdev) |
1214 | { |
1215 | struct device_node *np, *mnode = dev_of_node(dev: &pdev->dev); |
1216 | struct genpool_data_fixed gpdf; |
1217 | struct fsi_master_acf *master; |
1218 | struct gpio_desc *gpio; |
1219 | struct resource res; |
1220 | uint32_t cf_mem_align; |
1221 | int rc; |
1222 | |
1223 | master = kzalloc(size: sizeof(*master), GFP_KERNEL); |
1224 | if (!master) |
1225 | return -ENOMEM; |
1226 | |
1227 | master->dev = &pdev->dev; |
1228 | master->master.dev.parent = master->dev; |
1229 | master->last_addr = LAST_ADDR_INVALID; |
1230 | |
1231 | /* AST2400 vs. AST2500 */ |
1232 | master->is_ast2500 = of_device_is_compatible(device: mnode, "aspeed,ast2500-cf-fsi-master" ); |
1233 | |
1234 | /* Grab the SCU, we'll need to access it to configure the coprocessor */ |
1235 | if (master->is_ast2500) |
1236 | master->scu = syscon_regmap_lookup_by_compatible(s: "aspeed,ast2500-scu" ); |
1237 | else |
1238 | master->scu = syscon_regmap_lookup_by_compatible(s: "aspeed,ast2400-scu" ); |
1239 | if (IS_ERR(ptr: master->scu)) { |
1240 | dev_err(&pdev->dev, "failed to find SCU regmap\n" ); |
1241 | rc = PTR_ERR(ptr: master->scu); |
1242 | goto err_free; |
1243 | } |
1244 | |
1245 | /* Grab all the GPIOs we need */ |
1246 | gpio = devm_gpiod_get(dev: &pdev->dev, con_id: "clock" , flags: 0); |
1247 | if (IS_ERR(ptr: gpio)) { |
1248 | dev_err(&pdev->dev, "failed to get clock gpio\n" ); |
1249 | rc = PTR_ERR(ptr: gpio); |
1250 | goto err_free; |
1251 | } |
1252 | master->gpio_clk = gpio; |
1253 | |
1254 | gpio = devm_gpiod_get(dev: &pdev->dev, con_id: "data" , flags: 0); |
1255 | if (IS_ERR(ptr: gpio)) { |
1256 | dev_err(&pdev->dev, "failed to get data gpio\n" ); |
1257 | rc = PTR_ERR(ptr: gpio); |
1258 | goto err_free; |
1259 | } |
1260 | master->gpio_data = gpio; |
1261 | |
1262 | /* Optional GPIOs */ |
1263 | gpio = devm_gpiod_get_optional(dev: &pdev->dev, con_id: "trans" , flags: 0); |
1264 | if (IS_ERR(ptr: gpio)) { |
1265 | dev_err(&pdev->dev, "failed to get trans gpio\n" ); |
1266 | rc = PTR_ERR(ptr: gpio); |
1267 | goto err_free; |
1268 | } |
1269 | master->gpio_trans = gpio; |
1270 | |
1271 | gpio = devm_gpiod_get_optional(dev: &pdev->dev, con_id: "enable" , flags: 0); |
1272 | if (IS_ERR(ptr: gpio)) { |
1273 | dev_err(&pdev->dev, "failed to get enable gpio\n" ); |
1274 | rc = PTR_ERR(ptr: gpio); |
1275 | goto err_free; |
1276 | } |
1277 | master->gpio_enable = gpio; |
1278 | |
1279 | gpio = devm_gpiod_get_optional(dev: &pdev->dev, con_id: "mux" , flags: 0); |
1280 | if (IS_ERR(ptr: gpio)) { |
1281 | dev_err(&pdev->dev, "failed to get mux gpio\n" ); |
1282 | rc = PTR_ERR(ptr: gpio); |
1283 | goto err_free; |
1284 | } |
1285 | master->gpio_mux = gpio; |
1286 | |
1287 | /* Grab the reserved memory region (use DMA API instead ?) */ |
1288 | np = of_parse_phandle(np: mnode, phandle_name: "memory-region" , index: 0); |
1289 | if (!np) { |
1290 | dev_err(&pdev->dev, "Didn't find reserved memory\n" ); |
1291 | rc = -EINVAL; |
1292 | goto err_free; |
1293 | } |
1294 | rc = of_address_to_resource(dev: np, index: 0, r: &res); |
1295 | of_node_put(node: np); |
1296 | if (rc) { |
1297 | dev_err(&pdev->dev, "Couldn't address to resource for reserved memory\n" ); |
1298 | rc = -ENOMEM; |
1299 | goto err_free; |
1300 | } |
1301 | master->cf_mem_size = resource_size(res: &res); |
1302 | master->cf_mem_addr = (uint32_t)res.start; |
1303 | cf_mem_align = master->is_ast2500 ? 0x00100000 : 0x00200000; |
1304 | if (master->cf_mem_addr & (cf_mem_align - 1)) { |
1305 | dev_err(&pdev->dev, "Reserved memory has insufficient alignment\n" ); |
1306 | rc = -ENOMEM; |
1307 | goto err_free; |
1308 | } |
1309 | master->cf_mem = devm_ioremap_resource(dev: &pdev->dev, res: &res); |
1310 | if (IS_ERR(ptr: master->cf_mem)) { |
1311 | rc = PTR_ERR(ptr: master->cf_mem); |
1312 | goto err_free; |
1313 | } |
1314 | dev_dbg(&pdev->dev, "DRAM allocation @%x\n" , master->cf_mem_addr); |
1315 | |
1316 | /* AST2500 has a SW interrupt to the coprocessor */ |
1317 | if (master->is_ast2500) { |
1318 | /* Grab the CVIC (ColdFire interrupts controller) */ |
1319 | np = of_parse_phandle(np: mnode, phandle_name: "aspeed,cvic" , index: 0); |
1320 | if (!np) { |
1321 | dev_err(&pdev->dev, "Didn't find CVIC\n" ); |
1322 | rc = -EINVAL; |
1323 | goto err_free; |
1324 | } |
1325 | master->cvic = devm_of_iomap(dev: &pdev->dev, node: np, index: 0, NULL); |
1326 | if (IS_ERR(ptr: master->cvic)) { |
1327 | of_node_put(node: np); |
1328 | rc = PTR_ERR(ptr: master->cvic); |
1329 | dev_err(&pdev->dev, "Error %d mapping CVIC\n" , rc); |
1330 | goto err_free; |
1331 | } |
1332 | rc = of_property_read_u32(np, propname: "copro-sw-interrupts" , |
1333 | out_value: &master->cvic_sw_irq); |
1334 | of_node_put(node: np); |
1335 | if (rc) { |
1336 | dev_err(&pdev->dev, "Can't find coprocessor SW interrupt\n" ); |
1337 | goto err_free; |
1338 | } |
1339 | } |
1340 | |
1341 | /* Grab the SRAM */ |
1342 | master->sram_pool = of_gen_pool_get(np: dev_of_node(dev: &pdev->dev), propname: "aspeed,sram" , index: 0); |
1343 | if (!master->sram_pool) { |
1344 | rc = -ENODEV; |
1345 | dev_err(&pdev->dev, "Can't find sram pool\n" ); |
1346 | goto err_free; |
1347 | } |
1348 | |
1349 | /* Current microcode only deals with fixed location in SRAM */ |
1350 | gpdf.offset = 0; |
1351 | master->sram = (void __iomem *)gen_pool_alloc_algo(pool: master->sram_pool, SRAM_SIZE, |
1352 | algo: gen_pool_fixed_alloc, data: &gpdf); |
1353 | if (!master->sram) { |
1354 | rc = -ENOMEM; |
1355 | dev_err(&pdev->dev, "Failed to allocate sram from pool\n" ); |
1356 | goto err_free; |
1357 | } |
1358 | dev_dbg(&pdev->dev, "SRAM allocation @%lx\n" , |
1359 | (unsigned long)gen_pool_virt_to_phys(master->sram_pool, |
1360 | (unsigned long)master->sram)); |
1361 | |
1362 | /* |
1363 | * Hookup with the GPIO driver for arbitration of GPIO banks |
1364 | * ownership. |
1365 | */ |
1366 | aspeed_gpio_copro_set_ops(ops: &fsi_master_acf_gpio_ops, data: master); |
1367 | |
1368 | /* Default FSI command delays */ |
1369 | master->t_send_delay = FSI_SEND_DELAY_CLOCKS; |
1370 | master->t_echo_delay = FSI_ECHO_DELAY_CLOCKS; |
1371 | master->master.n_links = 1; |
1372 | if (master->is_ast2500) |
1373 | master->master.flags = FSI_MASTER_FLAG_SWCLOCK; |
1374 | master->master.read = fsi_master_acf_read; |
1375 | master->master.write = fsi_master_acf_write; |
1376 | master->master.term = fsi_master_acf_term; |
1377 | master->master.send_break = fsi_master_acf_break; |
1378 | master->master.link_enable = fsi_master_acf_link_enable; |
1379 | master->master.link_config = fsi_master_acf_link_config; |
1380 | master->master.dev.of_node = of_node_get(node: dev_of_node(dev: master->dev)); |
1381 | master->master.dev.release = fsi_master_acf_release; |
1382 | platform_set_drvdata(pdev, data: master); |
1383 | mutex_init(&master->lock); |
1384 | |
1385 | mutex_lock(&master->lock); |
1386 | rc = fsi_master_acf_setup(master); |
1387 | mutex_unlock(lock: &master->lock); |
1388 | if (rc) |
1389 | goto release_of_dev; |
1390 | |
1391 | rc = device_create_file(device: &pdev->dev, entry: &dev_attr_external_mode); |
1392 | if (rc) |
1393 | goto stop_copro; |
1394 | |
1395 | rc = fsi_master_register(master: &master->master); |
1396 | if (!rc) |
1397 | return 0; |
1398 | |
1399 | device_remove_file(dev: master->dev, attr: &dev_attr_external_mode); |
1400 | put_device(dev: &master->master.dev); |
1401 | return rc; |
1402 | |
1403 | stop_copro: |
1404 | fsi_master_acf_terminate(master); |
1405 | release_of_dev: |
1406 | aspeed_gpio_copro_set_ops(NULL, NULL); |
1407 | gen_pool_free(pool: master->sram_pool, addr: (unsigned long)master->sram, SRAM_SIZE); |
1408 | of_node_put(node: dev_of_node(dev: master->dev)); |
1409 | err_free: |
1410 | kfree(objp: master); |
1411 | return rc; |
1412 | } |
1413 | |
1414 | |
1415 | static int fsi_master_acf_remove(struct platform_device *pdev) |
1416 | { |
1417 | struct fsi_master_acf *master = platform_get_drvdata(pdev); |
1418 | |
1419 | device_remove_file(dev: master->dev, attr: &dev_attr_external_mode); |
1420 | |
1421 | fsi_master_unregister(master: &master->master); |
1422 | |
1423 | return 0; |
1424 | } |
1425 | |
1426 | static const struct of_device_id fsi_master_acf_match[] = { |
1427 | { .compatible = "aspeed,ast2400-cf-fsi-master" }, |
1428 | { .compatible = "aspeed,ast2500-cf-fsi-master" }, |
1429 | { }, |
1430 | }; |
1431 | MODULE_DEVICE_TABLE(of, fsi_master_acf_match); |
1432 | |
1433 | static struct platform_driver fsi_master_acf = { |
1434 | .driver = { |
1435 | .name = "fsi-master-acf" , |
1436 | .of_match_table = fsi_master_acf_match, |
1437 | }, |
1438 | .probe = fsi_master_acf_probe, |
1439 | .remove = fsi_master_acf_remove, |
1440 | }; |
1441 | |
1442 | module_platform_driver(fsi_master_acf); |
1443 | MODULE_LICENSE("GPL" ); |
1444 | MODULE_FIRMWARE(FW_FILE_NAME); |
1445 | |