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/dmi.h> 11 #include <linux/iopoll.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/slab.h> 15 #include <linux/spi/spi.h> 16 #include <linux/spi/spi-mem.h> 17 18 #define HISI_SFC_V3XX_VERSION (0x1f8) 19 20 #define HISI_SFC_V3XX_INT_STAT (0x120) 21 #define HISI_SFC_V3XX_INT_STAT_PP_ERR BIT(2) 22 #define HISI_SFC_V3XX_INT_STAT_ADDR_IACCES BIT(5) 23 #define HISI_SFC_V3XX_INT_CLR (0x12c) 24 #define HISI_SFC_V3XX_INT_CLR_CLEAR (0xff) 25 #define HISI_SFC_V3XX_CMD_CFG (0x300) 26 #define HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT (1 << 17) 27 #define HISI_SFC_V3XX_CMD_CFG_DUAL_IO (2 << 17) 28 #define HISI_SFC_V3XX_CMD_CFG_FULL_DIO (3 << 17) 29 #define HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT (5 << 17) 30 #define HISI_SFC_V3XX_CMD_CFG_QUAD_IO (6 << 17) 31 #define HISI_SFC_V3XX_CMD_CFG_FULL_QIO (7 << 17) 32 #define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9 33 #define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8) 34 #define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7) 35 #define HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF 4 36 #define HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK BIT(3) 37 #define HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF 1 38 #define HISI_SFC_V3XX_CMD_CFG_START_MSK BIT(0) 39 #define HISI_SFC_V3XX_CMD_INS (0x308) 40 #define HISI_SFC_V3XX_CMD_ADDR (0x30c) 41 #define HISI_SFC_V3XX_CMD_DATABUF0 (0x400) 42 43 struct hisi_sfc_v3xx_host { 44 struct device *dev; 45 void __iomem *regbase; 46 int max_cmd_dword; 47 }; 48 49 #define HISI_SFC_V3XX_WAIT_TIMEOUT_US 1000000 50 #define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US 10 51 52 static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host *host) 53 { 54 u32 reg; 55 56 return readl_poll_timeout(host->regbase + HISI_SFC_V3XX_CMD_CFG, reg, 57 !(reg & HISI_SFC_V3XX_CMD_CFG_START_MSK), 58 HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US, 59 HISI_SFC_V3XX_WAIT_TIMEOUT_US); 60 } 61 62 static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem, 63 struct spi_mem_op *op) 64 { 65 struct spi_device *spi = mem->spi; 66 struct hisi_sfc_v3xx_host *host; 67 uintptr_t addr = (uintptr_t)op->data.buf.in; 68 int max_byte_count; 69 70 host = spi_controller_get_devdata(spi->master); 71 72 max_byte_count = host->max_cmd_dword * 4; 73 74 if (!IS_ALIGNED(addr, 4) && op->data.nbytes >= 4) 75 op->data.nbytes = 4 - (addr % 4); 76 else if (op->data.nbytes > max_byte_count) 77 op->data.nbytes = max_byte_count; 78 79 return 0; 80 } 81 82 /* 83 * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the 84 * DATABUF registers -so use __io{read,write}32_copy when possible. For 85 * trailing bytes, copy them byte-by-byte from the DATABUF register, as we 86 * can't clobber outside the source/dest buffer. 87 * 88 * For efficient data read/write, we try to put any start 32b unaligned data 89 * into a separate transaction in hisi_sfc_v3xx_adjust_op_size(). 90 */ 91 static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host *host, 92 u8 *to, unsigned int len) 93 { 94 void __iomem *from; 95 int i; 96 97 from = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; 98 99 if (IS_ALIGNED((uintptr_t)to, 4)) { 100 int words = len / 4; 101 102 __ioread32_copy(to, from, words); 103 104 len -= words * 4; 105 if (len) { 106 u32 val; 107 108 to += words * 4; 109 from += words * 4; 110 111 val = __raw_readl(from); 112 113 for (i = 0; i < len; i++, val >>= 8, to++) 114 *to = (u8)val; 115 } 116 } else { 117 for (i = 0; i < DIV_ROUND_UP(len, 4); i++, from += 4) { 118 u32 val = __raw_readl(from); 119 int j; 120 121 for (j = 0; j < 4 && (j + (i * 4) < len); 122 to++, val >>= 8, j++) 123 *to = (u8)val; 124 } 125 } 126 } 127 128 static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host *host, 129 const u8 *from, unsigned int len) 130 { 131 void __iomem *to; 132 int i; 133 134 to = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; 135 136 if (IS_ALIGNED((uintptr_t)from, 4)) { 137 int words = len / 4; 138 139 __iowrite32_copy(to, from, words); 140 141 len -= words * 4; 142 if (len) { 143 u32 val = 0; 144 145 to += words * 4; 146 from += words * 4; 147 148 for (i = 0; i < len; i++, from++) 149 val |= *from << i * 8; 150 __raw_writel(val, to); 151 } 152 153 } else { 154 for (i = 0; i < DIV_ROUND_UP(len, 4); i++, to += 4) { 155 u32 val = 0; 156 int j; 157 158 for (j = 0; j < 4 && (j + (i * 4) < len); 159 from++, j++) 160 val |= *from << j * 8; 161 __raw_writel(val, to); 162 } 163 } 164 } 165 166 static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host, 167 const struct spi_mem_op *op, 168 u8 chip_select) 169 { 170 int ret, len = op->data.nbytes; 171 u32 int_stat, config = 0; 172 173 if (op->addr.nbytes) 174 config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK; 175 176 switch (op->data.buswidth) { 177 case 0 ... 1: 178 break; 179 case 2: 180 if (op->addr.buswidth <= 1) { 181 config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT; 182 } else if (op->addr.buswidth == 2) { 183 if (op->cmd.buswidth <= 1) { 184 config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IO; 185 } else if (op->cmd.buswidth == 2) { 186 config |= HISI_SFC_V3XX_CMD_CFG_FULL_DIO; 187 } else { 188 return -EIO; 189 } 190 } else { 191 return -EIO; 192 } 193 break; 194 case 4: 195 if (op->addr.buswidth <= 1) { 196 config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT; 197 } else if (op->addr.buswidth == 4) { 198 if (op->cmd.buswidth <= 1) { 199 config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IO; 200 } else if (op->cmd.buswidth == 4) { 201 config |= HISI_SFC_V3XX_CMD_CFG_FULL_QIO; 202 } else { 203 return -EIO; 204 } 205 } else { 206 return -EIO; 207 } 208 break; 209 default: 210 return -EOPNOTSUPP; 211 } 212 213 if (op->data.dir != SPI_MEM_NO_DATA) { 214 config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF; 215 config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK; 216 } 217 218 if (op->data.dir == SPI_MEM_DATA_OUT) 219 hisi_sfc_v3xx_write_databuf(host, op->data.buf.out, len); 220 else if (op->data.dir == SPI_MEM_DATA_IN) 221 config |= HISI_SFC_V3XX_CMD_CFG_RW_MSK; 222 223 config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF | 224 chip_select << HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF | 225 HISI_SFC_V3XX_CMD_CFG_START_MSK; 226 227 writel(op->addr.val, host->regbase + HISI_SFC_V3XX_CMD_ADDR); 228 writel(op->cmd.opcode, host->regbase + HISI_SFC_V3XX_CMD_INS); 229 230 writel(config, host->regbase + HISI_SFC_V3XX_CMD_CFG); 231 232 ret = hisi_sfc_v3xx_wait_cmd_idle(host); 233 if (ret) 234 return ret; 235 236 /* 237 * The interrupt status register indicates whether an error occurs 238 * after per operation. Check it, and clear the interrupts for 239 * next time judgement. 240 */ 241 int_stat = readl(host->regbase + HISI_SFC_V3XX_INT_STAT); 242 writel(HISI_SFC_V3XX_INT_CLR_CLEAR, 243 host->regbase + HISI_SFC_V3XX_INT_CLR); 244 245 if (int_stat & HISI_SFC_V3XX_INT_STAT_ADDR_IACCES) { 246 dev_err(host->dev, "fail to access protected address\n"); 247 return -EIO; 248 } 249 250 if (int_stat & HISI_SFC_V3XX_INT_STAT_PP_ERR) { 251 dev_err(host->dev, "page program operation failed\n"); 252 return -EIO; 253 } 254 255 if (op->data.dir == SPI_MEM_DATA_IN) 256 hisi_sfc_v3xx_read_databuf(host, op->data.buf.in, len); 257 258 return 0; 259 } 260 261 static int hisi_sfc_v3xx_exec_op(struct spi_mem *mem, 262 const struct spi_mem_op *op) 263 { 264 struct hisi_sfc_v3xx_host *host; 265 struct spi_device *spi = mem->spi; 266 u8 chip_select = spi->chip_select; 267 268 host = spi_controller_get_devdata(spi->master); 269 270 return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select); 271 } 272 273 static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = { 274 .adjust_op_size = hisi_sfc_v3xx_adjust_op_size, 275 .exec_op = hisi_sfc_v3xx_exec_op, 276 }; 277 278 static int hisi_sfc_v3xx_buswidth_override_bits; 279 280 /* 281 * ACPI FW does not allow us to currently set the device buswidth, so quirk it 282 * depending on the board. 283 */ 284 static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d) 285 { 286 hisi_sfc_v3xx_buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD; 287 288 return 0; 289 } 290 291 static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[] = { 292 { 293 .callback = hisi_sfc_v3xx_dmi_quirk, 294 .matches = { 295 DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), 296 DMI_MATCH(DMI_PRODUCT_NAME, "D06"), 297 }, 298 }, 299 { 300 .callback = hisi_sfc_v3xx_dmi_quirk, 301 .matches = { 302 DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), 303 DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 2280 V2"), 304 }, 305 }, 306 { 307 .callback = hisi_sfc_v3xx_dmi_quirk, 308 .matches = { 309 DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), 310 DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 200 (Model 2280)"), 311 }, 312 }, 313 {} 314 }; 315 316 static int hisi_sfc_v3xx_probe(struct platform_device *pdev) 317 { 318 struct device *dev = &pdev->dev; 319 struct hisi_sfc_v3xx_host *host; 320 struct spi_controller *ctlr; 321 u32 version; 322 int ret; 323 324 ctlr = spi_alloc_master(&pdev->dev, sizeof(*host)); 325 if (!ctlr) 326 return -ENOMEM; 327 328 ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | 329 SPI_TX_DUAL | SPI_TX_QUAD; 330 331 ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits; 332 333 host = spi_controller_get_devdata(ctlr); 334 host->dev = dev; 335 336 platform_set_drvdata(pdev, host); 337 338 host->regbase = devm_platform_ioremap_resource(pdev, 0); 339 if (IS_ERR(host->regbase)) { 340 ret = PTR_ERR(host->regbase); 341 goto err_put_master; 342 } 343 344 ctlr->bus_num = -1; 345 ctlr->num_chipselect = 1; 346 ctlr->mem_ops = &hisi_sfc_v3xx_mem_ops; 347 348 version = readl(host->regbase + HISI_SFC_V3XX_VERSION); 349 350 switch (version) { 351 case 0x351: 352 host->max_cmd_dword = 64; 353 break; 354 default: 355 host->max_cmd_dword = 16; 356 break; 357 } 358 359 ret = devm_spi_register_controller(dev, ctlr); 360 if (ret) 361 goto err_put_master; 362 363 dev_info(&pdev->dev, "hw version 0x%x\n", version); 364 365 return 0; 366 367 err_put_master: 368 spi_master_put(ctlr); 369 return ret; 370 } 371 372 #if IS_ENABLED(CONFIG_ACPI) 373 static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] = { 374 {"HISI0341", 0}, 375 {} 376 }; 377 MODULE_DEVICE_TABLE(acpi, hisi_sfc_v3xx_acpi_ids); 378 #endif 379 380 static struct platform_driver hisi_sfc_v3xx_spi_driver = { 381 .driver = { 382 .name = "hisi-sfc-v3xx", 383 .acpi_match_table = ACPI_PTR(hisi_sfc_v3xx_acpi_ids), 384 }, 385 .probe = hisi_sfc_v3xx_probe, 386 }; 387 388 static int __init hisi_sfc_v3xx_spi_init(void) 389 { 390 dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table); 391 392 return platform_driver_register(&hisi_sfc_v3xx_spi_driver); 393 } 394 395 static void __exit hisi_sfc_v3xx_spi_exit(void) 396 { 397 platform_driver_unregister(&hisi_sfc_v3xx_spi_driver); 398 } 399 400 module_init(hisi_sfc_v3xx_spi_init); 401 module_exit(hisi_sfc_v3xx_spi_exit); 402 403 MODULE_LICENSE("GPL"); 404 MODULE_AUTHOR("John Garry <john.garry@huawei.com>"); 405 MODULE_DESCRIPTION("HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets"); 406