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