]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/fsi/fsi-master-aspeed.c
fsi: fsi-occ: fix return value check in occ_probe()
[mirror_ubuntu-jammy-kernel.git] / drivers / fsi / fsi-master-aspeed.c
CommitLineData
606397d6
JS
1// SPDX-License-Identifier: GPL-2.0-or-later
2// Copyright (C) IBM Corporation 2018
3// FSI master driver for AST2600
4
5#include <linux/clk.h>
6#include <linux/delay.h>
7#include <linux/fsi.h>
8#include <linux/io.h>
9#include <linux/mfd/syscon.h>
10#include <linux/module.h>
11#include <linux/of.h>
12#include <linux/platform_device.h>
13#include <linux/regmap.h>
14#include <linux/slab.h>
15#include <linux/iopoll.h>
16
17#include "fsi-master.h"
18
19struct fsi_master_aspeed {
20 struct fsi_master master;
21 struct device *dev;
22 void __iomem *base;
23 struct clk *clk;
24};
25
26#define to_fsi_master_aspeed(m) \
27 container_of(m, struct fsi_master_aspeed, master)
28
29/* Control register (size 0x400) */
30static const u32 ctrl_base = 0x80000000;
31
32static const u32 fsi_base = 0xa0000000;
33
34#define OPB_FSI_VER 0x00
35#define OPB_TRIGGER 0x04
36#define OPB_CTRL_BASE 0x08
37#define OPB_FSI_BASE 0x0c
38#define OPB_CLK_SYNC 0x3c
39#define OPB_IRQ_CLEAR 0x40
40#define OPB_IRQ_MASK 0x44
41#define OPB_IRQ_STATUS 0x48
42
43#define OPB0_SELECT 0x10
44#define OPB0_RW 0x14
45#define OPB0_XFER_SIZE 0x18
46#define OPB0_FSI_ADDR 0x1c
47#define OPB0_FSI_DATA_W 0x20
48#define OPB0_STATUS 0x80
49#define OPB0_FSI_DATA_R 0x84
50
51#define OPB0_WRITE_ORDER1 0x4c
52#define OPB0_WRITE_ORDER2 0x50
53#define OPB1_WRITE_ORDER1 0x54
54#define OPB1_WRITE_ORDER2 0x58
55#define OPB0_READ_ORDER1 0x5c
56#define OPB1_READ_ORDER2 0x60
57
58#define OPB_RETRY_COUNTER 0x64
59
60/* OPBn_STATUS */
61#define STATUS_HALFWORD_ACK BIT(0)
62#define STATUS_FULLWORD_ACK BIT(1)
63#define STATUS_ERR_ACK BIT(2)
64#define STATUS_RETRY BIT(3)
65#define STATUS_TIMEOUT BIT(4)
66
67/* OPB_IRQ_MASK */
68#define OPB1_XFER_ACK_EN BIT(17)
69#define OPB0_XFER_ACK_EN BIT(16)
70
71/* OPB_RW */
72#define CMD_READ BIT(0)
73#define CMD_WRITE 0
74
75/* OPBx_XFER_SIZE */
76#define XFER_FULLWORD (BIT(1) | BIT(0))
77#define XFER_HALFWORD (BIT(0))
78#define XFER_BYTE (0)
79
913b7373
JS
80#define CREATE_TRACE_POINTS
81#include <trace/events/fsi_master_aspeed.h>
82
606397d6
JS
83#define FSI_LINK_ENABLE_SETUP_TIME 10 /* in mS */
84
85#define DEFAULT_DIVISOR 14
86#define OPB_POLL_TIMEOUT 10000
87
88static int __opb_write(struct fsi_master_aspeed *aspeed, u32 addr,
89 u32 val, u32 transfer_size)
90{
91 void __iomem *base = aspeed->base;
92 u32 reg, status;
93 int ret;
94
95 writel(CMD_WRITE, base + OPB0_RW);
96 writel(transfer_size, base + OPB0_XFER_SIZE);
97 writel(addr, base + OPB0_FSI_ADDR);
98 writel(val, base + OPB0_FSI_DATA_W);
99 writel(0x1, base + OPB_IRQ_CLEAR);
100 writel(0x1, base + OPB_TRIGGER);
101
102 ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg,
103 (reg & OPB0_XFER_ACK_EN) != 0,
104 0, OPB_POLL_TIMEOUT);
105
106 status = readl(base + OPB0_STATUS);
107
913b7373
JS
108 trace_fsi_master_aspeed_opb_write(addr, val, transfer_size, status, reg);
109
606397d6
JS
110 /* Return error when poll timed out */
111 if (ret)
112 return ret;
113
114 /* Command failed, master will reset */
115 if (status & STATUS_ERR_ACK)
116 return -EIO;
117
118 return 0;
119}
120
121static int opb_writeb(struct fsi_master_aspeed *aspeed, u32 addr, u8 val)
122{
123 return __opb_write(aspeed, addr, val, XFER_BYTE);
124}
125
126static int opb_writew(struct fsi_master_aspeed *aspeed, u32 addr, __be16 val)
127{
128 return __opb_write(aspeed, addr, (__force u16)val, XFER_HALFWORD);
129}
130
131static int opb_writel(struct fsi_master_aspeed *aspeed, u32 addr, __be32 val)
132{
133 return __opb_write(aspeed, addr, (__force u32)val, XFER_FULLWORD);
134}
135
136static int __opb_read(struct fsi_master_aspeed *aspeed, uint32_t addr,
137 u32 transfer_size, void *out)
138{
139 void __iomem *base = aspeed->base;
140 u32 result, reg;
141 int status, ret;
142
143 writel(CMD_READ, base + OPB0_RW);
144 writel(transfer_size, base + OPB0_XFER_SIZE);
145 writel(addr, base + OPB0_FSI_ADDR);
146 writel(0x1, base + OPB_IRQ_CLEAR);
147 writel(0x1, base + OPB_TRIGGER);
148
149 ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg,
150 (reg & OPB0_XFER_ACK_EN) != 0,
151 0, OPB_POLL_TIMEOUT);
152
153 status = readl(base + OPB0_STATUS);
154
155 result = readl(base + OPB0_FSI_DATA_R);
156
913b7373
JS
157 trace_fsi_master_aspeed_opb_read(addr, transfer_size, result,
158 readl(base + OPB0_STATUS),
159 reg);
160
606397d6
JS
161 /* Return error when poll timed out */
162 if (ret)
163 return ret;
164
165 /* Command failed, master will reset */
166 if (status & STATUS_ERR_ACK)
167 return -EIO;
168
169 if (out) {
170 switch (transfer_size) {
171 case XFER_BYTE:
172 *(u8 *)out = result;
173 break;
174 case XFER_HALFWORD:
175 *(u16 *)out = result;
176 break;
177 case XFER_FULLWORD:
178 *(u32 *)out = result;
179 break;
180 default:
181 return -EINVAL;
182 }
183
184 }
185
186 return 0;
187}
188
189static int opb_readl(struct fsi_master_aspeed *aspeed, uint32_t addr, __be32 *out)
190{
191 return __opb_read(aspeed, addr, XFER_FULLWORD, out);
192}
193
194static int opb_readw(struct fsi_master_aspeed *aspeed, uint32_t addr, __be16 *out)
195{
196 return __opb_read(aspeed, addr, XFER_HALFWORD, (void *)out);
197}
198
199static int opb_readb(struct fsi_master_aspeed *aspeed, uint32_t addr, u8 *out)
200{
201 return __opb_read(aspeed, addr, XFER_BYTE, (void *)out);
202}
203
204static int check_errors(struct fsi_master_aspeed *aspeed, int err)
205{
206 int ret;
207
913b7373
JS
208 if (trace_fsi_master_aspeed_opb_error_enabled()) {
209 __be32 mresp0, mstap0, mesrb0;
210
211 opb_readl(aspeed, ctrl_base + FSI_MRESP0, &mresp0);
212 opb_readl(aspeed, ctrl_base + FSI_MSTAP0, &mstap0);
213 opb_readl(aspeed, ctrl_base + FSI_MESRB0, &mesrb0);
214
215 trace_fsi_master_aspeed_opb_error(
216 be32_to_cpu(mresp0),
217 be32_to_cpu(mstap0),
218 be32_to_cpu(mesrb0));
219 }
220
606397d6
JS
221 if (err == -EIO) {
222 /* Check MAEB (0x70) ? */
223
224 /* Then clear errors in master */
225 ret = opb_writel(aspeed, ctrl_base + FSI_MRESP0,
226 cpu_to_be32(FSI_MRESP_RST_ALL_MASTER));
227 if (ret) {
228 /* TODO: log? return different code? */
229 return ret;
230 }
231 /* TODO: confirm that 0x70 was okay */
232 }
233
234 /* This will pass through timeout errors */
235 return err;
236}
237
238static int aspeed_master_read(struct fsi_master *master, int link,
239 uint8_t id, uint32_t addr, void *val, size_t size)
240{
241 struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
242 int ret;
243
6e0ef7d2 244 if (id > 0x3)
606397d6
JS
245 return -EINVAL;
246
6e0ef7d2 247 addr |= id << 21;
606397d6
JS
248 addr += link * FSI_HUB_LINK_SIZE;
249
250 switch (size) {
251 case 1:
252 ret = opb_readb(aspeed, fsi_base + addr, val);
253 break;
254 case 2:
255 ret = opb_readw(aspeed, fsi_base + addr, val);
256 break;
257 case 4:
258 ret = opb_readl(aspeed, fsi_base + addr, val);
259 break;
260 default:
261 return -EINVAL;
262 }
263
264 ret = check_errors(aspeed, ret);
265 if (ret)
266 return ret;
267
268 return 0;
269}
270
271static int aspeed_master_write(struct fsi_master *master, int link,
272 uint8_t id, uint32_t addr, const void *val, size_t size)
273{
274 struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
275 int ret;
276
6e0ef7d2 277 if (id > 0x3)
606397d6
JS
278 return -EINVAL;
279
6e0ef7d2 280 addr |= id << 21;
606397d6
JS
281 addr += link * FSI_HUB_LINK_SIZE;
282
283 switch (size) {
284 case 1:
285 ret = opb_writeb(aspeed, fsi_base + addr, *(u8 *)val);
286 break;
287 case 2:
288 ret = opb_writew(aspeed, fsi_base + addr, *(__be16 *)val);
289 break;
290 case 4:
291 ret = opb_writel(aspeed, fsi_base + addr, *(__be32 *)val);
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 ret = check_errors(aspeed, ret);
298 if (ret)
299 return ret;
300
301 return 0;
302}
303
304static int aspeed_master_link_enable(struct fsi_master *master, int link)
305{
306 struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
307 int idx, bit, ret;
308 __be32 reg, result;
309
310 idx = link / 32;
311 bit = link % 32;
312
313 reg = cpu_to_be32(0x80000000 >> bit);
314
315 ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg);
316 if (ret)
317 return ret;
318
319 mdelay(FSI_LINK_ENABLE_SETUP_TIME);
320
321 ret = opb_readl(aspeed, ctrl_base + FSI_MENP0 + (4 * idx), &result);
322 if (ret)
323 return ret;
324
325 if (result != reg) {
326 dev_err(aspeed->dev, "%s failed: %08x\n", __func__, result);
327 return -EIO;
328 }
329
330 return 0;
331}
332
333static int aspeed_master_term(struct fsi_master *master, int link, uint8_t id)
334{
335 uint32_t addr;
336 __be32 cmd;
337
338 addr = 0x4;
339 cmd = cpu_to_be32(0xecc00000);
340
341 return aspeed_master_write(master, link, id, addr, &cmd, 4);
342}
343
344static int aspeed_master_break(struct fsi_master *master, int link)
345{
346 uint32_t addr;
347 __be32 cmd;
348
349 addr = 0x0;
350 cmd = cpu_to_be32(0xc0de0000);
351
352 return aspeed_master_write(master, link, 0, addr, &cmd, 4);
353}
354
355static void aspeed_master_release(struct device *dev)
356{
357 struct fsi_master_aspeed *aspeed =
358 to_fsi_master_aspeed(dev_to_fsi_master(dev));
359
360 kfree(aspeed);
361}
362
363/* mmode encoders */
364static inline u32 fsi_mmode_crs0(u32 x)
365{
366 return (x & FSI_MMODE_CRS0MASK) << FSI_MMODE_CRS0SHFT;
367}
368
369static inline u32 fsi_mmode_crs1(u32 x)
370{
371 return (x & FSI_MMODE_CRS1MASK) << FSI_MMODE_CRS1SHFT;
372}
373
374static int aspeed_master_init(struct fsi_master_aspeed *aspeed)
375{
376 __be32 reg;
377
378 reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
379 | FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE);
380 opb_writel(aspeed, ctrl_base + FSI_MRESP0, reg);
381
382 /* Initialize the MFSI (hub master) engine */
383 reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
384 | FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE);
385 opb_writel(aspeed, ctrl_base + FSI_MRESP0, reg);
386
387 reg = cpu_to_be32(FSI_MECTRL_EOAE | FSI_MECTRL_P8_AUTO_TERM);
388 opb_writel(aspeed, ctrl_base + FSI_MECTRL, reg);
389
390 reg = cpu_to_be32(FSI_MMODE_ECRC | FSI_MMODE_EPC | FSI_MMODE_RELA
391 | fsi_mmode_crs0(DEFAULT_DIVISOR)
392 | fsi_mmode_crs1(DEFAULT_DIVISOR)
393 | FSI_MMODE_P8_TO_LSB);
394 opb_writel(aspeed, ctrl_base + FSI_MMODE, reg);
395
396 reg = cpu_to_be32(0xffff0000);
397 opb_writel(aspeed, ctrl_base + FSI_MDLYR, reg);
398
399 reg = cpu_to_be32(~0);
400 opb_writel(aspeed, ctrl_base + FSI_MSENP0, reg);
401
402 /* Leave enabled long enough for master logic to set up */
403 mdelay(FSI_LINK_ENABLE_SETUP_TIME);
404
405 opb_writel(aspeed, ctrl_base + FSI_MCENP0, reg);
406
407 opb_readl(aspeed, ctrl_base + FSI_MAEB, NULL);
408
409 reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK);
410 opb_writel(aspeed, ctrl_base + FSI_MRESP0, reg);
411
412 opb_readl(aspeed, ctrl_base + FSI_MLEVP0, NULL);
413
414 /* Reset the master bridge */
415 reg = cpu_to_be32(FSI_MRESB_RST_GEN);
416 opb_writel(aspeed, ctrl_base + FSI_MRESB0, reg);
417
418 reg = cpu_to_be32(FSI_MRESB_RST_ERR);
419 opb_writel(aspeed, ctrl_base + FSI_MRESB0, reg);
420
421 return 0;
422}
423
424static int fsi_master_aspeed_probe(struct platform_device *pdev)
425{
426 struct fsi_master_aspeed *aspeed;
427 struct resource *res;
428 int rc, links, reg;
429 __be32 raw;
430
431 aspeed = devm_kzalloc(&pdev->dev, sizeof(*aspeed), GFP_KERNEL);
432 if (!aspeed)
433 return -ENOMEM;
434
435 aspeed->dev = &pdev->dev;
436
437 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
438 aspeed->base = devm_ioremap_resource(&pdev->dev, res);
439 if (IS_ERR(aspeed->base))
440 return PTR_ERR(aspeed->base);
441
442 aspeed->clk = devm_clk_get(aspeed->dev, NULL);
443 if (IS_ERR(aspeed->clk)) {
444 dev_err(aspeed->dev, "couldn't get clock\n");
445 return PTR_ERR(aspeed->clk);
446 }
447 rc = clk_prepare_enable(aspeed->clk);
448 if (rc) {
449 dev_err(aspeed->dev, "couldn't enable clock\n");
450 return rc;
451 }
452
453 writel(0x1, aspeed->base + OPB_CLK_SYNC);
454 writel(OPB1_XFER_ACK_EN | OPB0_XFER_ACK_EN,
455 aspeed->base + OPB_IRQ_MASK);
456
457 /* TODO: determine an appropriate value */
458 writel(0x10, aspeed->base + OPB_RETRY_COUNTER);
459
460 writel(ctrl_base, aspeed->base + OPB_CTRL_BASE);
461 writel(fsi_base, aspeed->base + OPB_FSI_BASE);
462
463 /* Set read data order */
5e502299 464 writel(0x00030b1b, aspeed->base + OPB0_READ_ORDER1);
606397d6
JS
465
466 /* Set write data order */
5e502299
AJ
467 writel(0x0011101b, aspeed->base + OPB0_WRITE_ORDER1);
468 writel(0x0c330f3f, aspeed->base + OPB0_WRITE_ORDER2);
606397d6
JS
469
470 /*
471 * Select OPB0 for all operations.
472 * Will need to be reworked when enabling DMA or anything that uses
473 * OPB1.
474 */
475 writel(0x1, aspeed->base + OPB0_SELECT);
476
477 rc = opb_readl(aspeed, ctrl_base + FSI_MVER, &raw);
478 if (rc) {
479 dev_err(&pdev->dev, "failed to read hub version\n");
480 return rc;
481 }
482
483 reg = be32_to_cpu(raw);
484 links = (reg >> 8) & 0xff;
485 dev_info(&pdev->dev, "hub version %08x (%d links)\n", reg, links);
486
487 aspeed->master.dev.parent = &pdev->dev;
488 aspeed->master.dev.release = aspeed_master_release;
489 aspeed->master.dev.of_node = of_node_get(dev_of_node(&pdev->dev));
490
491 aspeed->master.n_links = links;
492 aspeed->master.read = aspeed_master_read;
493 aspeed->master.write = aspeed_master_write;
494 aspeed->master.send_break = aspeed_master_break;
495 aspeed->master.term = aspeed_master_term;
496 aspeed->master.link_enable = aspeed_master_link_enable;
497
498 dev_set_drvdata(&pdev->dev, aspeed);
499
500 aspeed_master_init(aspeed);
501
502 rc = fsi_master_register(&aspeed->master);
503 if (rc)
504 goto err_release;
505
506 /* At this point, fsi_master_register performs the device_initialize(),
507 * and holds the sole reference on master.dev. This means the device
508 * will be freed (via ->release) during any subsequent call to
509 * fsi_master_unregister. We add our own reference to it here, so we
510 * can perform cleanup (in _remove()) without it being freed before
511 * we're ready.
512 */
513 get_device(&aspeed->master.dev);
514 return 0;
515
516err_release:
517 clk_disable_unprepare(aspeed->clk);
518 return rc;
519}
520
521static int fsi_master_aspeed_remove(struct platform_device *pdev)
522{
523 struct fsi_master_aspeed *aspeed = platform_get_drvdata(pdev);
524
525 fsi_master_unregister(&aspeed->master);
526 clk_disable_unprepare(aspeed->clk);
527
528 return 0;
529}
530
531static const struct of_device_id fsi_master_aspeed_match[] = {
532 { .compatible = "aspeed,ast2600-fsi-master" },
533 { },
534};
535
536static struct platform_driver fsi_master_aspeed_driver = {
537 .driver = {
538 .name = "fsi-master-aspeed",
539 .of_match_table = fsi_master_aspeed_match,
540 },
541 .probe = fsi_master_aspeed_probe,
542 .remove = fsi_master_aspeed_remove,
543};
544
545module_platform_driver(fsi_master_aspeed_driver);
546MODULE_LICENSE("GPL");