1 // SPDX-License-Identifier: GPL-2.0-only
3 // HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets
5 // Copyright (c) 2019 HiSilicon Technologies Co., Ltd.
6 // Author: John Garry <john.garry@huawei.com>
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>
20 #define HISI_SFC_V3XX_VERSION (0x1f8)
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)
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 program error */
44 #define HISI_SFC_V3XX_INT_MASK_IACCES BIT(5) /* error visiting inaccessible/
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)
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
62 static const int hisi_sfc_v3xx_io_modes
[2][3][3] = {
64 { HISI_SFC_V3XX_DIDO
, HISI_SFC_V3XX_DIDO
, HISI_SFC_V3XX_DIDO
},
65 { HISI_SFC_V3XX_DIO
, HISI_SFC_V3XX_FULL_DIO
, -EIO
},
69 { HISI_SFC_V3XX_QIQO
, HISI_SFC_V3XX_QIQO
, HISI_SFC_V3XX_QIQO
},
71 { HISI_SFC_V3XX_QIO
, -EIO
, HISI_SFC_V3XX_FULL_QIO
},
75 struct hisi_sfc_v3xx_host
{
77 void __iomem
*regbase
;
79 struct completion
*completion
;
84 static void hisi_sfc_v3xx_disable_int(struct hisi_sfc_v3xx_host
*host
)
86 writel(0, host
->regbase
+ HISI_SFC_V3XX_INT_MASK
);
89 static void hisi_sfc_v3xx_enable_int(struct hisi_sfc_v3xx_host
*host
)
91 writel(HISI_SFC_V3XX_INT_MASK_ALL
, host
->regbase
+ HISI_SFC_V3XX_INT_MASK
);
94 static void hisi_sfc_v3xx_clear_int(struct hisi_sfc_v3xx_host
*host
)
96 writel(HISI_SFC_V3XX_INT_MASK_ALL
, host
->regbase
+ HISI_SFC_V3XX_INT_CLR
);
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.
104 static int hisi_sfc_v3xx_handle_completion(struct hisi_sfc_v3xx_host
*host
)
108 reg
= readl(host
->regbase
+ HISI_SFC_V3XX_RAW_INT_STAT
);
109 hisi_sfc_v3xx_clear_int(host
);
111 if (reg
& HISI_SFC_V3XX_INT_MASK_IACCES
) {
112 dev_err(host
->dev
, "fail to access protected address\n");
116 if (reg
& HISI_SFC_V3XX_INT_MASK_PP_ERR
) {
117 dev_err(host
->dev
, "page program operation failed\n");
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.
126 if (!(reg
& HISI_SFC_V3XX_INT_MASK_CPLT
)) {
127 dev_err(host
->dev
, "unsupported error occurred, status=0x%x\n", reg
);
134 #define HISI_SFC_V3XX_WAIT_TIMEOUT_US 1000000
135 #define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US 10
137 static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host
*host
)
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
);
147 static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem
*mem
,
148 struct spi_mem_op
*op
)
150 struct spi_device
*spi
= mem
->spi
;
151 struct hisi_sfc_v3xx_host
*host
;
152 uintptr_t addr
= (uintptr_t)op
->data
.buf
.in
;
155 host
= spi_controller_get_devdata(spi
->controller
);
157 max_byte_count
= host
->max_cmd_dword
* 4;
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
;
168 * The controller only supports Standard SPI mode, Dual mode and
169 * Quad mode. Double sanitize the ops here to avoid OOB access.
171 static bool hisi_sfc_v3xx_supports_op(struct spi_mem
*mem
,
172 const struct spi_mem_op
*op
)
174 struct spi_device
*spi
= mem
->spi
;
175 struct hisi_sfc_v3xx_host
*host
;
177 host
= spi_controller_get_devdata(spi
->controller
);
179 if (op
->data
.buswidth
> 4 || op
->dummy
.buswidth
> 4 ||
180 op
->addr
.buswidth
> 4 || op
->cmd
.buswidth
> 4)
183 if (op
->addr
.nbytes
!= host
->address_mode
&& op
->addr
.nbytes
)
186 return spi_mem_default_supports_op(mem
, op
);
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.
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().
198 static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host
*host
,
199 u8
*to
, unsigned int len
)
204 from
= host
->regbase
+ HISI_SFC_V3XX_CMD_DATABUF0
;
206 if (IS_ALIGNED((uintptr_t)to
, 4)) {
209 __ioread32_copy(to
, from
, words
);
218 val
= __raw_readl(from
);
220 for (i
= 0; i
< len
; i
++, val
>>= 8, to
++)
224 for (i
= 0; i
< DIV_ROUND_UP(len
, 4); i
++, from
+= 4) {
225 u32 val
= __raw_readl(from
);
228 for (j
= 0; j
< 4 && (j
+ (i
* 4) < len
);
229 to
++, val
>>= 8, j
++)
235 static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host
*host
,
236 const u8
*from
, unsigned int len
)
241 to
= host
->regbase
+ HISI_SFC_V3XX_CMD_DATABUF0
;
243 if (IS_ALIGNED((uintptr_t)from
, 4)) {
246 __iowrite32_copy(to
, from
, words
);
255 for (i
= 0; i
< len
; i
++, from
++)
256 val
|= *from
<< i
* 8;
257 __raw_writel(val
, to
);
261 for (i
= 0; i
< DIV_ROUND_UP(len
, 4); i
++, to
+= 4) {
265 for (j
= 0; j
< 4 && (j
+ (i
* 4) < len
);
267 val
|= *from
<< j
* 8;
268 __raw_writel(val
, to
);
273 static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host
*host
,
274 const struct spi_mem_op
*op
,
277 int len
= op
->data
.nbytes
, buswidth_mode
;
281 config
|= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK
;
283 if (op
->data
.buswidth
== 0 || op
->data
.buswidth
== 1) {
284 buswidth_mode
= HISI_SFC_V3XX_STD
;
286 int data_idx
, addr_idx
, cmd_idx
;
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
];
293 if (buswidth_mode
< 0)
294 return buswidth_mode
;
295 config
|= buswidth_mode
;
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
;
302 if (op
->data
.dir
== SPI_MEM_DATA_IN
)
303 config
|= HISI_SFC_V3XX_CMD_CFG_RW_MSK
;
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
;
309 writel(op
->addr
.val
, host
->regbase
+ HISI_SFC_V3XX_CMD_ADDR
);
310 writel(op
->cmd
.opcode
, host
->regbase
+ HISI_SFC_V3XX_CMD_INS
);
312 writel(config
, host
->regbase
+ HISI_SFC_V3XX_CMD_CFG
);
317 static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host
*host
,
318 const struct spi_mem_op
*op
,
321 DECLARE_COMPLETION_ONSTACK(done
);
325 host
->completion
= &done
;
326 hisi_sfc_v3xx_enable_int(host
);
329 if (op
->data
.dir
== SPI_MEM_DATA_OUT
)
330 hisi_sfc_v3xx_write_databuf(host
, op
->data
.buf
.out
, op
->data
.nbytes
);
332 ret
= hisi_sfc_v3xx_start_bus(host
, op
, chip_select
);
337 ret
= wait_for_completion_timeout(host
->completion
,
338 usecs_to_jiffies(HISI_SFC_V3XX_WAIT_TIMEOUT_US
));
344 hisi_sfc_v3xx_disable_int(host
);
345 synchronize_irq(host
->irq
);
346 host
->completion
= NULL
;
348 ret
= hisi_sfc_v3xx_wait_cmd_idle(host
);
350 if (hisi_sfc_v3xx_handle_completion(host
) || ret
)
353 if (op
->data
.dir
== SPI_MEM_DATA_IN
)
354 hisi_sfc_v3xx_read_databuf(host
, op
->data
.buf
.in
, op
->data
.nbytes
);
359 static int hisi_sfc_v3xx_exec_op(struct spi_mem
*mem
,
360 const struct spi_mem_op
*op
)
362 struct hisi_sfc_v3xx_host
*host
;
363 struct spi_device
*spi
= mem
->spi
;
364 u8 chip_select
= spi_get_chipselect(spi
, 0);
366 host
= spi_controller_get_devdata(spi
->controller
);
368 return hisi_sfc_v3xx_generic_exec_op(host
, op
, chip_select
);
371 static 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
,
377 static irqreturn_t
hisi_sfc_v3xx_isr(int irq
, void *data
)
379 struct hisi_sfc_v3xx_host
*host
= data
;
382 reg
= readl(host
->regbase
+ HISI_SFC_V3XX_INT_STAT
);
386 hisi_sfc_v3xx_disable_int(host
);
388 complete(host
->completion
);
393 static int hisi_sfc_v3xx_buswidth_override_bits
;
396 * ACPI FW does not allow us to currently set the device buswidth, so quirk it
397 * depending on the board.
399 static int __init
hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id
*d
)
401 hisi_sfc_v3xx_buswidth_override_bits
= SPI_RX_QUAD
| SPI_TX_QUAD
;
406 static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table
[] = {
408 .callback
= hisi_sfc_v3xx_dmi_quirk
,
410 DMI_MATCH(DMI_SYS_VENDOR
, "Huawei"),
411 DMI_MATCH(DMI_PRODUCT_NAME
, "D06"),
415 .callback
= hisi_sfc_v3xx_dmi_quirk
,
417 DMI_MATCH(DMI_SYS_VENDOR
, "Huawei"),
418 DMI_MATCH(DMI_PRODUCT_NAME
, "TaiShan 2280 V2"),
422 .callback
= hisi_sfc_v3xx_dmi_quirk
,
424 DMI_MATCH(DMI_SYS_VENDOR
, "Huawei"),
425 DMI_MATCH(DMI_PRODUCT_NAME
, "TaiShan 200 (Model 2280)"),
431 static int hisi_sfc_v3xx_probe(struct platform_device
*pdev
)
433 struct device
*dev
= &pdev
->dev
;
434 struct hisi_sfc_v3xx_host
*host
;
435 struct spi_controller
*ctlr
;
436 u32 version
, glb_config
;
439 ctlr
= spi_alloc_host(&pdev
->dev
, sizeof(*host
));
443 ctlr
->mode_bits
= SPI_RX_DUAL
| SPI_RX_QUAD
|
444 SPI_TX_DUAL
| SPI_TX_QUAD
;
446 ctlr
->buswidth_override_bits
= hisi_sfc_v3xx_buswidth_override_bits
;
448 host
= spi_controller_get_devdata(ctlr
);
451 platform_set_drvdata(pdev
, host
);
453 host
->regbase
= devm_platform_ioremap_resource(pdev
, 0);
454 if (IS_ERR(host
->regbase
)) {
455 ret
= PTR_ERR(host
->regbase
);
459 host
->irq
= platform_get_irq_optional(pdev
, 0);
460 if (host
->irq
== -EPROBE_DEFER
) {
465 hisi_sfc_v3xx_disable_int(host
);
468 ret
= devm_request_irq(dev
, host
->irq
, hisi_sfc_v3xx_isr
, 0,
469 "hisi-sfc-v3xx", host
);
472 dev_err(dev
, "failed to request irq%d, ret = %d\n", host
->irq
, ret
);
480 ctlr
->num_chipselect
= 1;
481 ctlr
->mem_ops
= &hisi_sfc_v3xx_mem_ops
;
484 * The address mode of the controller is either 3 or 4,
485 * which is indicated by the address mode bit in
486 * the global config register. The register is read only
489 glb_config
= readl(host
->regbase
+ HISI_SFC_V3XX_GLB_CFG
);
490 if (glb_config
& HISI_SFC_V3XX_GLB_CFG_CS0_ADDR_MODE
)
491 host
->address_mode
= 4;
493 host
->address_mode
= 3;
495 version
= readl(host
->regbase
+ HISI_SFC_V3XX_VERSION
);
497 if (version
>= 0x351)
498 host
->max_cmd_dword
= 64;
500 host
->max_cmd_dword
= 16;
502 ret
= devm_spi_register_controller(dev
, ctlr
);
506 dev_info(&pdev
->dev
, "hw version 0x%x, %s mode.\n",
507 version
, host
->irq
? "irq" : "polling");
512 spi_controller_put(ctlr
);
516 static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids
[] = {
520 MODULE_DEVICE_TABLE(acpi
, hisi_sfc_v3xx_acpi_ids
);
522 static struct platform_driver hisi_sfc_v3xx_spi_driver
= {
524 .name
= "hisi-sfc-v3xx",
525 .acpi_match_table
= hisi_sfc_v3xx_acpi_ids
,
527 .probe
= hisi_sfc_v3xx_probe
,
530 static int __init
hisi_sfc_v3xx_spi_init(void)
532 dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table
);
534 return platform_driver_register(&hisi_sfc_v3xx_spi_driver
);
537 static void __exit
hisi_sfc_v3xx_spi_exit(void)
539 platform_driver_unregister(&hisi_sfc_v3xx_spi_driver
);
542 module_init(hisi_sfc_v3xx_spi_init
);
543 module_exit(hisi_sfc_v3xx_spi_exit
);
545 MODULE_LICENSE("GPL");
546 MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
547 MODULE_DESCRIPTION("HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets");