linux/drivers/fsi/fsi-master-aspeed.c
<<
>>
Prefs
   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
  80#define CREATE_TRACE_POINTS
  81#include <trace/events/fsi_master_aspeed.h>
  82
  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
 108        trace_fsi_master_aspeed_opb_write(addr, val, transfer_size, status, reg);
 109
 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
 157        trace_fsi_master_aspeed_opb_read(addr, transfer_size, result,
 158                        readl(base + OPB0_STATUS),
 159                        reg);
 160
 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
 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
 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
 244        if (id != 0)
 245                return -EINVAL;
 246
 247        addr += link * FSI_HUB_LINK_SIZE;
 248
 249        switch (size) {
 250        case 1:
 251                ret = opb_readb(aspeed, fsi_base + addr, val);
 252                break;
 253        case 2:
 254                ret = opb_readw(aspeed, fsi_base + addr, val);
 255                break;
 256        case 4:
 257                ret = opb_readl(aspeed, fsi_base + addr, val);
 258                break;
 259        default:
 260                return -EINVAL;
 261        }
 262
 263        ret = check_errors(aspeed, ret);
 264        if (ret)
 265                return ret;
 266
 267        return 0;
 268}
 269
 270static int aspeed_master_write(struct fsi_master *master, int link,
 271                        uint8_t id, uint32_t addr, const void *val, size_t size)
 272{
 273        struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
 274        int ret;
 275
 276        if (id != 0)
 277                return -EINVAL;
 278
 279        addr += link * FSI_HUB_LINK_SIZE;
 280
 281        switch (size) {
 282        case 1:
 283                ret = opb_writeb(aspeed, fsi_base + addr, *(u8 *)val);
 284                break;
 285        case 2:
 286                ret = opb_writew(aspeed, fsi_base + addr, *(__be16 *)val);
 287                break;
 288        case 4:
 289                ret = opb_writel(aspeed, fsi_base + addr, *(__be32 *)val);
 290                break;
 291        default:
 292                return -EINVAL;
 293        }
 294
 295        ret = check_errors(aspeed, ret);
 296        if (ret)
 297                return ret;
 298
 299        return 0;
 300}
 301
 302static int aspeed_master_link_enable(struct fsi_master *master, int link)
 303{
 304        struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
 305        int idx, bit, ret;
 306        __be32 reg, result;
 307
 308        idx = link / 32;
 309        bit = link % 32;
 310
 311        reg = cpu_to_be32(0x80000000 >> bit);
 312
 313        ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg);
 314        if (ret)
 315                return ret;
 316
 317        mdelay(FSI_LINK_ENABLE_SETUP_TIME);
 318
 319        ret = opb_readl(aspeed, ctrl_base + FSI_MENP0 + (4 * idx), &result);
 320        if (ret)
 321                return ret;
 322
 323        if (result != reg) {
 324                dev_err(aspeed->dev, "%s failed: %08x\n", __func__, result);
 325                return -EIO;
 326        }
 327
 328        return 0;
 329}
 330
 331static int aspeed_master_term(struct fsi_master *master, int link, uint8_t id)
 332{
 333        uint32_t addr;
 334        __be32 cmd;
 335
 336        addr = 0x4;
 337        cmd = cpu_to_be32(0xecc00000);
 338
 339        return aspeed_master_write(master, link, id, addr, &cmd, 4);
 340}
 341
 342static int aspeed_master_break(struct fsi_master *master, int link)
 343{
 344        uint32_t addr;
 345        __be32 cmd;
 346
 347        addr = 0x0;
 348        cmd = cpu_to_be32(0xc0de0000);
 349
 350        return aspeed_master_write(master, link, 0, addr, &cmd, 4);
 351}
 352
 353static void aspeed_master_release(struct device *dev)
 354{
 355        struct fsi_master_aspeed *aspeed =
 356                to_fsi_master_aspeed(dev_to_fsi_master(dev));
 357
 358        kfree(aspeed);
 359}
 360
 361/* mmode encoders */
 362static inline u32 fsi_mmode_crs0(u32 x)
 363{
 364        return (x & FSI_MMODE_CRS0MASK) << FSI_MMODE_CRS0SHFT;
 365}
 366
 367static inline u32 fsi_mmode_crs1(u32 x)
 368{
 369        return (x & FSI_MMODE_CRS1MASK) << FSI_MMODE_CRS1SHFT;
 370}
 371
 372static int aspeed_master_init(struct fsi_master_aspeed *aspeed)
 373{
 374        __be32 reg;
 375
 376        reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
 377                        | FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE);
 378        opb_writel(aspeed, ctrl_base + FSI_MRESP0, reg);
 379
 380        /* Initialize the MFSI (hub master) engine */
 381        reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK
 382                        | FSI_MRESP_RST_MCR | FSI_MRESP_RST_PYE);
 383        opb_writel(aspeed, ctrl_base + FSI_MRESP0, reg);
 384
 385        reg = cpu_to_be32(FSI_MECTRL_EOAE | FSI_MECTRL_P8_AUTO_TERM);
 386        opb_writel(aspeed, ctrl_base + FSI_MECTRL, reg);
 387
 388        reg = cpu_to_be32(FSI_MMODE_ECRC | FSI_MMODE_EPC | FSI_MMODE_RELA
 389                        | fsi_mmode_crs0(DEFAULT_DIVISOR)
 390                        | fsi_mmode_crs1(DEFAULT_DIVISOR)
 391                        | FSI_MMODE_P8_TO_LSB);
 392        opb_writel(aspeed, ctrl_base + FSI_MMODE, reg);
 393
 394        reg = cpu_to_be32(0xffff0000);
 395        opb_writel(aspeed, ctrl_base + FSI_MDLYR, reg);
 396
 397        reg = cpu_to_be32(~0);
 398        opb_writel(aspeed, ctrl_base + FSI_MSENP0, reg);
 399
 400        /* Leave enabled long enough for master logic to set up */
 401        mdelay(FSI_LINK_ENABLE_SETUP_TIME);
 402
 403        opb_writel(aspeed, ctrl_base + FSI_MCENP0, reg);
 404
 405        opb_readl(aspeed, ctrl_base + FSI_MAEB, NULL);
 406
 407        reg = cpu_to_be32(FSI_MRESP_RST_ALL_MASTER | FSI_MRESP_RST_ALL_LINK);
 408        opb_writel(aspeed, ctrl_base + FSI_MRESP0, reg);
 409
 410        opb_readl(aspeed, ctrl_base + FSI_MLEVP0, NULL);
 411
 412        /* Reset the master bridge */
 413        reg = cpu_to_be32(FSI_MRESB_RST_GEN);
 414        opb_writel(aspeed, ctrl_base + FSI_MRESB0, reg);
 415
 416        reg = cpu_to_be32(FSI_MRESB_RST_ERR);
 417        opb_writel(aspeed, ctrl_base + FSI_MRESB0, reg);
 418
 419        return 0;
 420}
 421
 422static int fsi_master_aspeed_probe(struct platform_device *pdev)
 423{
 424        struct fsi_master_aspeed *aspeed;
 425        struct resource *res;
 426        int rc, links, reg;
 427        __be32 raw;
 428
 429        aspeed = devm_kzalloc(&pdev->dev, sizeof(*aspeed), GFP_KERNEL);
 430        if (!aspeed)
 431                return -ENOMEM;
 432
 433        aspeed->dev = &pdev->dev;
 434
 435        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 436        aspeed->base = devm_ioremap_resource(&pdev->dev, res);
 437        if (IS_ERR(aspeed->base))
 438                return PTR_ERR(aspeed->base);
 439
 440        aspeed->clk = devm_clk_get(aspeed->dev, NULL);
 441        if (IS_ERR(aspeed->clk)) {
 442                dev_err(aspeed->dev, "couldn't get clock\n");
 443                return PTR_ERR(aspeed->clk);
 444        }
 445        rc = clk_prepare_enable(aspeed->clk);
 446        if (rc) {
 447                dev_err(aspeed->dev, "couldn't enable clock\n");
 448                return rc;
 449        }
 450
 451        writel(0x1, aspeed->base + OPB_CLK_SYNC);
 452        writel(OPB1_XFER_ACK_EN | OPB0_XFER_ACK_EN,
 453                        aspeed->base + OPB_IRQ_MASK);
 454
 455        /* TODO: determine an appropriate value */
 456        writel(0x10, aspeed->base + OPB_RETRY_COUNTER);
 457
 458        writel(ctrl_base, aspeed->base + OPB_CTRL_BASE);
 459        writel(fsi_base, aspeed->base + OPB_FSI_BASE);
 460
 461        /* Set read data order */
 462        writel(0x00030b1b, aspeed->base + OPB0_READ_ORDER1);
 463
 464        /* Set write data order */
 465        writel(0x0011101b, aspeed->base + OPB0_WRITE_ORDER1);
 466        writel(0x0c330f3f, aspeed->base + OPB0_WRITE_ORDER2);
 467
 468        /*
 469         * Select OPB0 for all operations.
 470         * Will need to be reworked when enabling DMA or anything that uses
 471         * OPB1.
 472         */
 473        writel(0x1, aspeed->base + OPB0_SELECT);
 474
 475        rc = opb_readl(aspeed, ctrl_base + FSI_MVER, &raw);
 476        if (rc) {
 477                dev_err(&pdev->dev, "failed to read hub version\n");
 478                return rc;
 479        }
 480
 481        reg = be32_to_cpu(raw);
 482        links = (reg >> 8) & 0xff;
 483        dev_info(&pdev->dev, "hub version %08x (%d links)\n", reg, links);
 484
 485        aspeed->master.dev.parent = &pdev->dev;
 486        aspeed->master.dev.release = aspeed_master_release;
 487        aspeed->master.dev.of_node = of_node_get(dev_of_node(&pdev->dev));
 488
 489        aspeed->master.n_links = links;
 490        aspeed->master.read = aspeed_master_read;
 491        aspeed->master.write = aspeed_master_write;
 492        aspeed->master.send_break = aspeed_master_break;
 493        aspeed->master.term = aspeed_master_term;
 494        aspeed->master.link_enable = aspeed_master_link_enable;
 495
 496        dev_set_drvdata(&pdev->dev, aspeed);
 497
 498        aspeed_master_init(aspeed);
 499
 500        rc = fsi_master_register(&aspeed->master);
 501        if (rc)
 502                goto err_release;
 503
 504        /* At this point, fsi_master_register performs the device_initialize(),
 505         * and holds the sole reference on master.dev. This means the device
 506         * will be freed (via ->release) during any subsequent call to
 507         * fsi_master_unregister.  We add our own reference to it here, so we
 508         * can perform cleanup (in _remove()) without it being freed before
 509         * we're ready.
 510         */
 511        get_device(&aspeed->master.dev);
 512        return 0;
 513
 514err_release:
 515        clk_disable_unprepare(aspeed->clk);
 516        return rc;
 517}
 518
 519static int fsi_master_aspeed_remove(struct platform_device *pdev)
 520{
 521        struct fsi_master_aspeed *aspeed = platform_get_drvdata(pdev);
 522
 523        fsi_master_unregister(&aspeed->master);
 524        clk_disable_unprepare(aspeed->clk);
 525
 526        return 0;
 527}
 528
 529static const struct of_device_id fsi_master_aspeed_match[] = {
 530        { .compatible = "aspeed,ast2600-fsi-master" },
 531        { },
 532};
 533
 534static struct platform_driver fsi_master_aspeed_driver = {
 535        .driver = {
 536                .name           = "fsi-master-aspeed",
 537                .of_match_table = fsi_master_aspeed_match,
 538        },
 539        .probe  = fsi_master_aspeed_probe,
 540        .remove = fsi_master_aspeed_remove,
 541};
 542
 543module_platform_driver(fsi_master_aspeed_driver);
 544MODULE_LICENSE("GPL");
 545