linux/drivers/spi/spi-hisi-sfc-v3xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2//
   3// HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets
   4//
   5// Copyright (c) 2019 HiSilicon Technologies Co., Ltd.
   6// Author: John Garry <john.garry@huawei.com>
   7
   8#include <linux/bitops.h>
   9#include <linux/completion.h>
  10#include <linux/dmi.h>
  11#include <linux/interrupt.h>
  12#include <linux/iopoll.h>
  13#include <linux/module.h>
  14#include <linux/mod_devicetable.h>
  15#include <linux/platform_device.h>
  16#include <linux/slab.h>
  17#include <linux/spi/spi.h>
  18#include <linux/spi/spi-mem.h>
  19
  20#define HISI_SFC_V3XX_VERSION (0x1f8)
  21
  22#define HISI_SFC_V3XX_GLB_CFG (0x100)
  23#define HISI_SFC_V3XX_GLB_CFG_CS0_ADDR_MODE BIT(2)
  24#define HISI_SFC_V3XX_RAW_INT_STAT (0x120)
  25#define HISI_SFC_V3XX_INT_STAT (0x124)
  26#define HISI_SFC_V3XX_INT_MASK (0x128)
  27#define HISI_SFC_V3XX_INT_CLR (0x12c)
  28#define HISI_SFC_V3XX_CMD_CFG (0x300)
  29#define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9
  30#define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8)
  31#define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7)
  32#define HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF 4
  33#define HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK BIT(3)
  34#define HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF 1
  35#define HISI_SFC_V3XX_CMD_CFG_START_MSK BIT(0)
  36#define HISI_SFC_V3XX_CMD_INS (0x308)
  37#define HISI_SFC_V3XX_CMD_ADDR (0x30c)
  38#define HISI_SFC_V3XX_CMD_DATABUF0 (0x400)
  39
  40/* Common definition of interrupt bit masks */
  41#define HISI_SFC_V3XX_INT_MASK_ALL (0x1ff)      /* all the masks */
  42#define HISI_SFC_V3XX_INT_MASK_CPLT BIT(0)      /* command execution complete */
  43#define HISI_SFC_V3XX_INT_MASK_PP_ERR BIT(2)    /* page progrom error */
  44#define HISI_SFC_V3XX_INT_MASK_IACCES BIT(5)    /* error visiting inaccessible/
  45                                                 * protected address
  46                                                 */
  47
  48/* IO Mode definition in HISI_SFC_V3XX_CMD_CFG */
  49#define HISI_SFC_V3XX_STD (0 << 17)
  50#define HISI_SFC_V3XX_DIDO (1 << 17)
  51#define HISI_SFC_V3XX_DIO (2 << 17)
  52#define HISI_SFC_V3XX_FULL_DIO (3 << 17)
  53#define HISI_SFC_V3XX_QIQO (5 << 17)
  54#define HISI_SFC_V3XX_QIO (6 << 17)
  55#define HISI_SFC_V3XX_FULL_QIO (7 << 17)
  56
  57/*
  58 * The IO modes lookup table. hisi_sfc_v3xx_io_modes[(z - 1) / 2][y / 2][x / 2]
  59 * stands for x-y-z mode, as described in SFDP terminology. -EIO indicates
  60 * an invalid mode.
  61 */
  62static const int hisi_sfc_v3xx_io_modes[2][3][3] = {
  63        {
  64                { HISI_SFC_V3XX_DIDO, HISI_SFC_V3XX_DIDO, HISI_SFC_V3XX_DIDO },
  65                { HISI_SFC_V3XX_DIO, HISI_SFC_V3XX_FULL_DIO, -EIO },
  66                { -EIO, -EIO, -EIO },
  67        },
  68        {
  69                { HISI_SFC_V3XX_QIQO, HISI_SFC_V3XX_QIQO, HISI_SFC_V3XX_QIQO },
  70                { -EIO, -EIO, -EIO },
  71                { HISI_SFC_V3XX_QIO, -EIO, HISI_SFC_V3XX_FULL_QIO },
  72        },
  73};
  74
  75struct hisi_sfc_v3xx_host {
  76        struct device *dev;
  77        void __iomem *regbase;
  78        int max_cmd_dword;
  79        struct completion *completion;
  80        u8 address_mode;
  81        int irq;
  82};
  83
  84static void hisi_sfc_v3xx_disable_int(struct hisi_sfc_v3xx_host *host)
  85{
  86        writel(0, host->regbase + HISI_SFC_V3XX_INT_MASK);
  87}
  88
  89static void hisi_sfc_v3xx_enable_int(struct hisi_sfc_v3xx_host *host)
  90{
  91        writel(HISI_SFC_V3XX_INT_MASK_ALL, host->regbase + HISI_SFC_V3XX_INT_MASK);
  92}
  93
  94static void hisi_sfc_v3xx_clear_int(struct hisi_sfc_v3xx_host *host)
  95{
  96        writel(HISI_SFC_V3XX_INT_MASK_ALL, host->regbase + HISI_SFC_V3XX_INT_CLR);
  97}
  98
  99/*
 100 * The interrupt status register indicates whether an error occurs
 101 * after per operation. Check it, and clear the interrupts for
 102 * next time judgement.
 103 */
 104static int hisi_sfc_v3xx_handle_completion(struct hisi_sfc_v3xx_host *host)
 105{
 106        u32 reg;
 107
 108        reg = readl(host->regbase + HISI_SFC_V3XX_RAW_INT_STAT);
 109        hisi_sfc_v3xx_clear_int(host);
 110
 111        if (reg & HISI_SFC_V3XX_INT_MASK_IACCES) {
 112                dev_err(host->dev, "fail to access protected address\n");
 113                return -EIO;
 114        }
 115
 116        if (reg & HISI_SFC_V3XX_INT_MASK_PP_ERR) {
 117                dev_err(host->dev, "page program operation failed\n");
 118                return -EIO;
 119        }
 120
 121        /*
 122         * The other bits of the interrupt registers is not currently
 123         * used and probably not be triggered in this driver. When it
 124         * happens, we regard it as an unsupported error here.
 125         */
 126        if (!(reg & HISI_SFC_V3XX_INT_MASK_CPLT)) {
 127                dev_err(host->dev, "unsupported error occurred, status=0x%x\n", reg);
 128                return -EIO;
 129        }
 130
 131        return 0;
 132}
 133
 134#define HISI_SFC_V3XX_WAIT_TIMEOUT_US           1000000
 135#define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US     10
 136
 137static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host *host)
 138{
 139        u32 reg;
 140
 141        return readl_poll_timeout(host->regbase + HISI_SFC_V3XX_CMD_CFG, reg,
 142                                  !(reg & HISI_SFC_V3XX_CMD_CFG_START_MSK),
 143                                  HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US,
 144                                  HISI_SFC_V3XX_WAIT_TIMEOUT_US);
 145}
 146
 147static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem,
 148                                        struct spi_mem_op *op)
 149{
 150        struct spi_device *spi = mem->spi;
 151        struct hisi_sfc_v3xx_host *host;
 152        uintptr_t addr = (uintptr_t)op->data.buf.in;
 153        int max_byte_count;
 154
 155        host = spi_controller_get_devdata(spi->master);
 156
 157        max_byte_count = host->max_cmd_dword * 4;
 158
 159        if (!IS_ALIGNED(addr, 4) && op->data.nbytes >= 4)
 160                op->data.nbytes = 4 - (addr % 4);
 161        else if (op->data.nbytes > max_byte_count)
 162                op->data.nbytes = max_byte_count;
 163
 164        return 0;
 165}
 166
 167/*
 168 * The controller only supports Standard SPI mode, Duall mode and
 169 * Quad mode. Double sanitize the ops here to avoid OOB access.
 170 */
 171static bool hisi_sfc_v3xx_supports_op(struct spi_mem *mem,
 172                                      const struct spi_mem_op *op)
 173{
 174        struct spi_device *spi = mem->spi;
 175        struct hisi_sfc_v3xx_host *host;
 176
 177        host = spi_controller_get_devdata(spi->master);
 178
 179        if (op->data.buswidth > 4 || op->dummy.buswidth > 4 ||
 180            op->addr.buswidth > 4 || op->cmd.buswidth > 4)
 181                return false;
 182
 183        if (op->addr.nbytes != host->address_mode && op->addr.nbytes)
 184                return false;
 185
 186        return spi_mem_default_supports_op(mem, op);
 187}
 188
 189/*
 190 * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the
 191 * DATABUF registers -so use __io{read,write}32_copy when possible. For
 192 * trailing bytes, copy them byte-by-byte from the DATABUF register, as we
 193 * can't clobber outside the source/dest buffer.
 194 *
 195 * For efficient data read/write, we try to put any start 32b unaligned data
 196 * into a separate transaction in hisi_sfc_v3xx_adjust_op_size().
 197 */
 198static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host *host,
 199                                       u8 *to, unsigned int len)
 200{
 201        void __iomem *from;
 202        int i;
 203
 204        from = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0;
 205
 206        if (IS_ALIGNED((uintptr_t)to, 4)) {
 207                int words = len / 4;
 208
 209                __ioread32_copy(to, from, words);
 210
 211                len -= words * 4;
 212                if (len) {
 213                        u32 val;
 214
 215                        to += words * 4;
 216                        from += words * 4;
 217
 218                        val = __raw_readl(from);
 219
 220                        for (i = 0; i < len; i++, val >>= 8, to++)
 221                                *to = (u8)val;
 222                }
 223        } else {
 224                for (i = 0; i < DIV_ROUND_UP(len, 4); i++, from += 4) {
 225                        u32 val = __raw_readl(from);
 226                        int j;
 227
 228                        for (j = 0; j < 4 && (j + (i * 4) < len);
 229                             to++, val >>= 8, j++)
 230                                *to = (u8)val;
 231                }
 232        }
 233}
 234
 235static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host *host,
 236                                        const u8 *from, unsigned int len)
 237{
 238        void __iomem *to;
 239        int i;
 240
 241        to = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0;
 242
 243        if (IS_ALIGNED((uintptr_t)from, 4)) {
 244                int words = len / 4;
 245
 246                __iowrite32_copy(to, from, words);
 247
 248                len -= words * 4;
 249                if (len) {
 250                        u32 val = 0;
 251
 252                        to += words * 4;
 253                        from += words * 4;
 254
 255                        for (i = 0; i < len; i++, from++)
 256                                val |= *from << i * 8;
 257                        __raw_writel(val, to);
 258                }
 259
 260        } else {
 261                for (i = 0; i < DIV_ROUND_UP(len, 4); i++, to += 4) {
 262                        u32 val = 0;
 263                        int j;
 264
 265                        for (j = 0; j < 4 && (j + (i * 4) < len);
 266                             from++, j++)
 267                                val |= *from << j * 8;
 268                        __raw_writel(val, to);
 269                }
 270        }
 271}
 272
 273static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host *host,
 274                                   const struct spi_mem_op *op,
 275                                   u8 chip_select)
 276{
 277        int len = op->data.nbytes, buswidth_mode;
 278        u32 config = 0;
 279
 280        if (op->addr.nbytes)
 281                config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK;
 282
 283        if (op->data.buswidth == 0 || op->data.buswidth == 1) {
 284                buswidth_mode = HISI_SFC_V3XX_STD;
 285        } else {
 286                int data_idx, addr_idx, cmd_idx;
 287
 288                data_idx = (op->data.buswidth - 1) / 2;
 289                addr_idx = op->addr.buswidth / 2;
 290                cmd_idx = op->cmd.buswidth / 2;
 291                buswidth_mode = hisi_sfc_v3xx_io_modes[data_idx][addr_idx][cmd_idx];
 292        }
 293        if (buswidth_mode < 0)
 294                return buswidth_mode;
 295        config |= buswidth_mode;
 296
 297        if (op->data.dir != SPI_MEM_NO_DATA) {
 298                config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF;
 299                config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK;
 300        }
 301
 302        if (op->data.dir == SPI_MEM_DATA_IN)
 303                config |= HISI_SFC_V3XX_CMD_CFG_RW_MSK;
 304
 305        config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF |
 306                  chip_select << HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF |
 307                  HISI_SFC_V3XX_CMD_CFG_START_MSK;
 308
 309        writel(op->addr.val, host->regbase + HISI_SFC_V3XX_CMD_ADDR);
 310        writel(op->cmd.opcode, host->regbase + HISI_SFC_V3XX_CMD_INS);
 311
 312        writel(config, host->regbase + HISI_SFC_V3XX_CMD_CFG);
 313
 314        return 0;
 315}
 316
 317static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host,
 318                                         const struct spi_mem_op *op,
 319                                         u8 chip_select)
 320{
 321        DECLARE_COMPLETION_ONSTACK(done);
 322        int ret;
 323
 324        if (host->irq) {
 325                host->completion = &done;
 326                hisi_sfc_v3xx_enable_int(host);
 327        }
 328
 329        if (op->data.dir == SPI_MEM_DATA_OUT)
 330                hisi_sfc_v3xx_write_databuf(host, op->data.buf.out, op->data.nbytes);
 331
 332        ret = hisi_sfc_v3xx_start_bus(host, op, chip_select);
 333        if (ret)
 334                return ret;
 335
 336        if (host->irq) {
 337                ret = wait_for_completion_timeout(host->completion,
 338                                                  usecs_to_jiffies(HISI_SFC_V3XX_WAIT_TIMEOUT_US));
 339                if (!ret)
 340                        ret = -ETIMEDOUT;
 341                else
 342                        ret = 0;
 343
 344                hisi_sfc_v3xx_disable_int(host);
 345                synchronize_irq(host->irq);
 346                host->completion = NULL;
 347        } else {
 348                ret = hisi_sfc_v3xx_wait_cmd_idle(host);
 349        }
 350        if (hisi_sfc_v3xx_handle_completion(host) || ret)
 351                return -EIO;
 352
 353        if (op->data.dir == SPI_MEM_DATA_IN)
 354                hisi_sfc_v3xx_read_databuf(host, op->data.buf.in, op->data.nbytes);
 355
 356        return 0;
 357}
 358
 359static int hisi_sfc_v3xx_exec_op(struct spi_mem *mem,
 360                                 const struct spi_mem_op *op)
 361{
 362        struct hisi_sfc_v3xx_host *host;
 363        struct spi_device *spi = mem->spi;
 364        u8 chip_select = spi->chip_select;
 365
 366        host = spi_controller_get_devdata(spi->master);
 367
 368        return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select);
 369}
 370
 371static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = {
 372        .adjust_op_size = hisi_sfc_v3xx_adjust_op_size,
 373        .supports_op = hisi_sfc_v3xx_supports_op,
 374        .exec_op = hisi_sfc_v3xx_exec_op,
 375};
 376
 377static irqreturn_t hisi_sfc_v3xx_isr(int irq, void *data)
 378{
 379        struct hisi_sfc_v3xx_host *host = data;
 380
 381        hisi_sfc_v3xx_disable_int(host);
 382
 383        complete(host->completion);
 384
 385        return IRQ_HANDLED;
 386}
 387
 388static int hisi_sfc_v3xx_buswidth_override_bits;
 389
 390/*
 391 * ACPI FW does not allow us to currently set the device buswidth, so quirk it
 392 * depending on the board.
 393 */
 394static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d)
 395{
 396        hisi_sfc_v3xx_buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD;
 397
 398        return 0;
 399}
 400
 401static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[]  = {
 402        {
 403        .callback = hisi_sfc_v3xx_dmi_quirk,
 404        .matches = {
 405                DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
 406                DMI_MATCH(DMI_PRODUCT_NAME, "D06"),
 407        },
 408        },
 409        {
 410        .callback = hisi_sfc_v3xx_dmi_quirk,
 411        .matches = {
 412                DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
 413                DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 2280 V2"),
 414        },
 415        },
 416        {
 417        .callback = hisi_sfc_v3xx_dmi_quirk,
 418        .matches = {
 419                DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
 420                DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 200 (Model 2280)"),
 421        },
 422        },
 423        {}
 424};
 425
 426static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
 427{
 428        struct device *dev = &pdev->dev;
 429        struct hisi_sfc_v3xx_host *host;
 430        struct spi_controller *ctlr;
 431        u32 version, glb_config;
 432        int ret;
 433
 434        ctlr = spi_alloc_master(&pdev->dev, sizeof(*host));
 435        if (!ctlr)
 436                return -ENOMEM;
 437
 438        ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD |
 439                          SPI_TX_DUAL | SPI_TX_QUAD;
 440
 441        ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits;
 442
 443        host = spi_controller_get_devdata(ctlr);
 444        host->dev = dev;
 445
 446        platform_set_drvdata(pdev, host);
 447
 448        host->regbase = devm_platform_ioremap_resource(pdev, 0);
 449        if (IS_ERR(host->regbase)) {
 450                ret = PTR_ERR(host->regbase);
 451                goto err_put_master;
 452        }
 453
 454        host->irq = platform_get_irq_optional(pdev, 0);
 455        if (host->irq == -EPROBE_DEFER) {
 456                ret = -EPROBE_DEFER;
 457                goto err_put_master;
 458        }
 459
 460        hisi_sfc_v3xx_disable_int(host);
 461
 462        if (host->irq > 0) {
 463                ret = devm_request_irq(dev, host->irq, hisi_sfc_v3xx_isr, 0,
 464                                       "hisi-sfc-v3xx", host);
 465
 466                if (ret) {
 467                        dev_err(dev, "failed to request irq%d, ret = %d\n", host->irq, ret);
 468                        host->irq = 0;
 469                }
 470        } else {
 471                host->irq = 0;
 472        }
 473
 474        ctlr->bus_num = -1;
 475        ctlr->num_chipselect = 1;
 476        ctlr->mem_ops = &hisi_sfc_v3xx_mem_ops;
 477
 478        /*
 479         * The address mode of the controller is either 3 or 4,
 480         * which is indicated by the address mode bit in
 481         * the global config register. The register is read only
 482         * for the OS driver.
 483         */
 484        glb_config = readl(host->regbase + HISI_SFC_V3XX_GLB_CFG);
 485        if (glb_config & HISI_SFC_V3XX_GLB_CFG_CS0_ADDR_MODE)
 486                host->address_mode = 4;
 487        else
 488                host->address_mode = 3;
 489
 490        version = readl(host->regbase + HISI_SFC_V3XX_VERSION);
 491
 492        if (version >= 0x351)
 493                host->max_cmd_dword = 64;
 494        else
 495                host->max_cmd_dword = 16;
 496
 497        ret = devm_spi_register_controller(dev, ctlr);
 498        if (ret)
 499                goto err_put_master;
 500
 501        dev_info(&pdev->dev, "hw version 0x%x, %s mode.\n",
 502                 version, host->irq ? "irq" : "polling");
 503
 504        return 0;
 505
 506err_put_master:
 507        spi_master_put(ctlr);
 508        return ret;
 509}
 510
 511static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] = {
 512        {"HISI0341", 0},
 513        {}
 514};
 515MODULE_DEVICE_TABLE(acpi, hisi_sfc_v3xx_acpi_ids);
 516
 517static struct platform_driver hisi_sfc_v3xx_spi_driver = {
 518        .driver = {
 519                .name   = "hisi-sfc-v3xx",
 520                .acpi_match_table = hisi_sfc_v3xx_acpi_ids,
 521        },
 522        .probe  = hisi_sfc_v3xx_probe,
 523};
 524
 525static int __init hisi_sfc_v3xx_spi_init(void)
 526{
 527        dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table);
 528
 529        return platform_driver_register(&hisi_sfc_v3xx_spi_driver);
 530}
 531
 532static void __exit hisi_sfc_v3xx_spi_exit(void)
 533{
 534        platform_driver_unregister(&hisi_sfc_v3xx_spi_driver);
 535}
 536
 537module_init(hisi_sfc_v3xx_spi_init);
 538module_exit(hisi_sfc_v3xx_spi_exit);
 539
 540MODULE_LICENSE("GPL");
 541MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
 542MODULE_DESCRIPTION("HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets");
 543