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/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>
20 #define HISI_SFC_V3XX_VERSION (0x1f8)
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)
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/
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)
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
60 static const int hisi_sfc_v3xx_io_modes
[2][3][3] = {
62 { HISI_SFC_V3XX_DIDO
, HISI_SFC_V3XX_DIDO
, HISI_SFC_V3XX_DIDO
},
63 { HISI_SFC_V3XX_DIO
, HISI_SFC_V3XX_FULL_DIO
, -EIO
},
67 { HISI_SFC_V3XX_QIQO
, HISI_SFC_V3XX_QIQO
, HISI_SFC_V3XX_QIQO
},
69 { HISI_SFC_V3XX_QIO
, -EIO
, HISI_SFC_V3XX_FULL_QIO
},
73 struct hisi_sfc_v3xx_host
{
75 void __iomem
*regbase
;
77 struct completion
*completion
;
81 static void hisi_sfc_v3xx_disable_int(struct hisi_sfc_v3xx_host
*host
)
83 writel(0, host
->regbase
+ HISI_SFC_V3XX_INT_MASK
);
86 static void hisi_sfc_v3xx_enable_int(struct hisi_sfc_v3xx_host
*host
)
88 writel(HISI_SFC_V3XX_INT_MASK_ALL
, host
->regbase
+ HISI_SFC_V3XX_INT_MASK
);
91 static void hisi_sfc_v3xx_clear_int(struct hisi_sfc_v3xx_host
*host
)
93 writel(HISI_SFC_V3XX_INT_MASK_ALL
, host
->regbase
+ HISI_SFC_V3XX_INT_CLR
);
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.
101 static int hisi_sfc_v3xx_handle_completion(struct hisi_sfc_v3xx_host
*host
)
105 reg
= readl(host
->regbase
+ HISI_SFC_V3XX_RAW_INT_STAT
);
106 hisi_sfc_v3xx_clear_int(host
);
108 if (reg
& HISI_SFC_V3XX_INT_MASK_IACCES
) {
109 dev_err(host
->dev
, "fail to access protected address\n");
113 if (reg
& HISI_SFC_V3XX_INT_MASK_PP_ERR
) {
114 dev_err(host
->dev
, "page program operation failed\n");
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.
123 if (!(reg
& HISI_SFC_V3XX_INT_MASK_CPLT
)) {
124 dev_err(host
->dev
, "unsupported error occurred, status=0x%x\n", reg
);
131 #define HISI_SFC_V3XX_WAIT_TIMEOUT_US 1000000
132 #define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US 10
134 static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host
*host
)
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
);
144 static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem
*mem
,
145 struct spi_mem_op
*op
)
147 struct spi_device
*spi
= mem
->spi
;
148 struct hisi_sfc_v3xx_host
*host
;
149 uintptr_t addr
= (uintptr_t)op
->data
.buf
.in
;
152 host
= spi_controller_get_devdata(spi
->master
);
154 max_byte_count
= host
->max_cmd_dword
* 4;
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
;
165 * The controller only supports Standard SPI mode, Duall mode and
166 * Quad mode. Double sanitize the ops here to avoid OOB access.
168 static bool hisi_sfc_v3xx_supports_op(struct spi_mem
*mem
,
169 const struct spi_mem_op
*op
)
171 if (op
->data
.buswidth
> 4 || op
->dummy
.buswidth
> 4 ||
172 op
->addr
.buswidth
> 4 || op
->cmd
.buswidth
> 4)
175 return spi_mem_default_supports_op(mem
, op
);
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.
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().
187 static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host
*host
,
188 u8
*to
, unsigned int len
)
193 from
= host
->regbase
+ HISI_SFC_V3XX_CMD_DATABUF0
;
195 if (IS_ALIGNED((uintptr_t)to
, 4)) {
198 __ioread32_copy(to
, from
, words
);
207 val
= __raw_readl(from
);
209 for (i
= 0; i
< len
; i
++, val
>>= 8, to
++)
213 for (i
= 0; i
< DIV_ROUND_UP(len
, 4); i
++, from
+= 4) {
214 u32 val
= __raw_readl(from
);
217 for (j
= 0; j
< 4 && (j
+ (i
* 4) < len
);
218 to
++, val
>>= 8, j
++)
224 static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host
*host
,
225 const u8
*from
, unsigned int len
)
230 to
= host
->regbase
+ HISI_SFC_V3XX_CMD_DATABUF0
;
232 if (IS_ALIGNED((uintptr_t)from
, 4)) {
235 __iowrite32_copy(to
, from
, words
);
244 for (i
= 0; i
< len
; i
++, from
++)
245 val
|= *from
<< i
* 8;
246 __raw_writel(val
, to
);
250 for (i
= 0; i
< DIV_ROUND_UP(len
, 4); i
++, to
+= 4) {
254 for (j
= 0; j
< 4 && (j
+ (i
* 4) < len
);
256 val
|= *from
<< j
* 8;
257 __raw_writel(val
, to
);
262 static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host
*host
,
263 const struct spi_mem_op
*op
,
266 int len
= op
->data
.nbytes
, buswidth_mode
;
270 config
|= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK
;
272 if (op
->data
.buswidth
== 0 || op
->data
.buswidth
== 1) {
273 buswidth_mode
= HISI_SFC_V3XX_STD
;
275 int data_idx
, addr_idx
, cmd_idx
;
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
];
282 if (buswidth_mode
< 0)
283 return buswidth_mode
;
284 config
|= buswidth_mode
;
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
;
291 if (op
->data
.dir
== SPI_MEM_DATA_IN
)
292 config
|= HISI_SFC_V3XX_CMD_CFG_RW_MSK
;
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
;
298 writel(op
->addr
.val
, host
->regbase
+ HISI_SFC_V3XX_CMD_ADDR
);
299 writel(op
->cmd
.opcode
, host
->regbase
+ HISI_SFC_V3XX_CMD_INS
);
301 writel(config
, host
->regbase
+ HISI_SFC_V3XX_CMD_CFG
);
306 static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host
*host
,
307 const struct spi_mem_op
*op
,
310 DECLARE_COMPLETION_ONSTACK(done
);
314 host
->completion
= &done
;
315 hisi_sfc_v3xx_enable_int(host
);
318 if (op
->data
.dir
== SPI_MEM_DATA_OUT
)
319 hisi_sfc_v3xx_write_databuf(host
, op
->data
.buf
.out
, op
->data
.nbytes
);
321 ret
= hisi_sfc_v3xx_start_bus(host
, op
, chip_select
);
326 ret
= wait_for_completion_timeout(host
->completion
,
327 usecs_to_jiffies(HISI_SFC_V3XX_WAIT_TIMEOUT_US
));
333 hisi_sfc_v3xx_disable_int(host
);
334 host
->completion
= NULL
;
336 ret
= hisi_sfc_v3xx_wait_cmd_idle(host
);
338 if (hisi_sfc_v3xx_handle_completion(host
) || ret
)
341 if (op
->data
.dir
== SPI_MEM_DATA_IN
)
342 hisi_sfc_v3xx_read_databuf(host
, op
->data
.buf
.in
, op
->data
.nbytes
);
347 static int hisi_sfc_v3xx_exec_op(struct spi_mem
*mem
,
348 const struct spi_mem_op
*op
)
350 struct hisi_sfc_v3xx_host
*host
;
351 struct spi_device
*spi
= mem
->spi
;
352 u8 chip_select
= spi
->chip_select
;
354 host
= spi_controller_get_devdata(spi
->master
);
356 return hisi_sfc_v3xx_generic_exec_op(host
, op
, chip_select
);
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
,
365 static irqreturn_t
hisi_sfc_v3xx_isr(int irq
, void *data
)
367 struct hisi_sfc_v3xx_host
*host
= data
;
369 hisi_sfc_v3xx_disable_int(host
);
371 complete(host
->completion
);
376 static int hisi_sfc_v3xx_buswidth_override_bits
;
379 * ACPI FW does not allow us to currently set the device buswidth, so quirk it
380 * depending on the board.
382 static int __init
hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id
*d
)
384 hisi_sfc_v3xx_buswidth_override_bits
= SPI_RX_QUAD
| SPI_TX_QUAD
;
389 static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table
[] = {
391 .callback
= hisi_sfc_v3xx_dmi_quirk
,
393 DMI_MATCH(DMI_SYS_VENDOR
, "Huawei"),
394 DMI_MATCH(DMI_PRODUCT_NAME
, "D06"),
398 .callback
= hisi_sfc_v3xx_dmi_quirk
,
400 DMI_MATCH(DMI_SYS_VENDOR
, "Huawei"),
401 DMI_MATCH(DMI_PRODUCT_NAME
, "TaiShan 2280 V2"),
405 .callback
= hisi_sfc_v3xx_dmi_quirk
,
407 DMI_MATCH(DMI_SYS_VENDOR
, "Huawei"),
408 DMI_MATCH(DMI_PRODUCT_NAME
, "TaiShan 200 (Model 2280)"),
414 static int hisi_sfc_v3xx_probe(struct platform_device
*pdev
)
416 struct device
*dev
= &pdev
->dev
;
417 struct hisi_sfc_v3xx_host
*host
;
418 struct spi_controller
*ctlr
;
422 ctlr
= spi_alloc_master(&pdev
->dev
, sizeof(*host
));
426 ctlr
->mode_bits
= SPI_RX_DUAL
| SPI_RX_QUAD
|
427 SPI_TX_DUAL
| SPI_TX_QUAD
;
429 ctlr
->buswidth_override_bits
= hisi_sfc_v3xx_buswidth_override_bits
;
431 host
= spi_controller_get_devdata(ctlr
);
434 platform_set_drvdata(pdev
, host
);
436 host
->regbase
= devm_platform_ioremap_resource(pdev
, 0);
437 if (IS_ERR(host
->regbase
)) {
438 ret
= PTR_ERR(host
->regbase
);
442 host
->irq
= platform_get_irq_optional(pdev
, 0);
443 if (host
->irq
== -EPROBE_DEFER
) {
448 hisi_sfc_v3xx_disable_int(host
);
451 ret
= devm_request_irq(dev
, host
->irq
, hisi_sfc_v3xx_isr
, 0,
452 "hisi-sfc-v3xx", host
);
455 dev_err(dev
, "failed to request irq%d, ret = %d\n", host
->irq
, ret
);
463 ctlr
->num_chipselect
= 1;
464 ctlr
->mem_ops
= &hisi_sfc_v3xx_mem_ops
;
466 version
= readl(host
->regbase
+ HISI_SFC_V3XX_VERSION
);
470 host
->max_cmd_dword
= 64;
473 host
->max_cmd_dword
= 16;
477 ret
= devm_spi_register_controller(dev
, ctlr
);
481 dev_info(&pdev
->dev
, "hw version 0x%x, %s mode.\n",
482 version
, host
->irq
? "irq" : "polling");
487 spi_master_put(ctlr
);
491 #if IS_ENABLED(CONFIG_ACPI)
492 static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids
[] = {
496 MODULE_DEVICE_TABLE(acpi
, hisi_sfc_v3xx_acpi_ids
);
499 static struct platform_driver hisi_sfc_v3xx_spi_driver
= {
501 .name
= "hisi-sfc-v3xx",
502 .acpi_match_table
= ACPI_PTR(hisi_sfc_v3xx_acpi_ids
),
504 .probe
= hisi_sfc_v3xx_probe
,
507 static int __init
hisi_sfc_v3xx_spi_init(void)
509 dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table
);
511 return platform_driver_register(&hisi_sfc_v3xx_spi_driver
);
514 static void __exit
hisi_sfc_v3xx_spi_exit(void)
516 platform_driver_unregister(&hisi_sfc_v3xx_spi_driver
);
519 module_init(hisi_sfc_v3xx_spi_init
);
520 module_exit(hisi_sfc_v3xx_spi_exit
);
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");