1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * HiSilicon FMC SPI NOR flash controller driver |
4 | * |
5 | * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd. |
6 | */ |
7 | #include <linux/bitops.h> |
8 | #include <linux/clk.h> |
9 | #include <linux/dma-mapping.h> |
10 | #include <linux/iopoll.h> |
11 | #include <linux/module.h> |
12 | #include <linux/mtd/mtd.h> |
13 | #include <linux/mtd/spi-nor.h> |
14 | #include <linux/of.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/slab.h> |
17 | |
18 | /* Hardware register offsets and field definitions */ |
19 | #define FMC_CFG 0x00 |
20 | #define FMC_CFG_OP_MODE_MASK BIT_MASK(0) |
21 | #define FMC_CFG_OP_MODE_BOOT 0 |
22 | #define FMC_CFG_OP_MODE_NORMAL 1 |
23 | #define FMC_CFG_FLASH_SEL(type) (((type) & 0x3) << 1) |
24 | #define FMC_CFG_FLASH_SEL_MASK 0x6 |
25 | #define FMC_ECC_TYPE(type) (((type) & 0x7) << 5) |
26 | #define FMC_ECC_TYPE_MASK GENMASK(7, 5) |
27 | #define SPI_NOR_ADDR_MODE_MASK BIT_MASK(10) |
28 | #define SPI_NOR_ADDR_MODE_3BYTES (0x0 << 10) |
29 | #define SPI_NOR_ADDR_MODE_4BYTES (0x1 << 10) |
30 | #define FMC_GLOBAL_CFG 0x04 |
31 | #define FMC_GLOBAL_CFG_WP_ENABLE BIT(6) |
32 | #define FMC_SPI_TIMING_CFG 0x08 |
33 | #define TIMING_CFG_TCSH(nr) (((nr) & 0xf) << 8) |
34 | #define TIMING_CFG_TCSS(nr) (((nr) & 0xf) << 4) |
35 | #define TIMING_CFG_TSHSL(nr) ((nr) & 0xf) |
36 | #define CS_HOLD_TIME 0x6 |
37 | #define CS_SETUP_TIME 0x6 |
38 | #define CS_DESELECT_TIME 0xf |
39 | #define FMC_INT 0x18 |
40 | #define FMC_INT_OP_DONE BIT(0) |
41 | #define FMC_INT_CLR 0x20 |
42 | #define FMC_CMD 0x24 |
43 | #define FMC_CMD_CMD1(cmd) ((cmd) & 0xff) |
44 | #define FMC_ADDRL 0x2c |
45 | #define FMC_OP_CFG 0x30 |
46 | #define OP_CFG_FM_CS(cs) ((cs) << 11) |
47 | #define OP_CFG_MEM_IF_TYPE(type) (((type) & 0x7) << 7) |
48 | #define OP_CFG_ADDR_NUM(addr) (((addr) & 0x7) << 4) |
49 | #define OP_CFG_DUMMY_NUM(dummy) ((dummy) & 0xf) |
50 | #define FMC_DATA_NUM 0x38 |
51 | #define FMC_DATA_NUM_CNT(cnt) ((cnt) & GENMASK(13, 0)) |
52 | #define FMC_OP 0x3c |
53 | #define FMC_OP_DUMMY_EN BIT(8) |
54 | #define FMC_OP_CMD1_EN BIT(7) |
55 | #define FMC_OP_ADDR_EN BIT(6) |
56 | #define FMC_OP_WRITE_DATA_EN BIT(5) |
57 | #define FMC_OP_READ_DATA_EN BIT(2) |
58 | #define FMC_OP_READ_STATUS_EN BIT(1) |
59 | #define FMC_OP_REG_OP_START BIT(0) |
60 | #define FMC_DMA_LEN 0x40 |
61 | #define FMC_DMA_LEN_SET(len) ((len) & GENMASK(27, 0)) |
62 | #define FMC_DMA_SADDR_D0 0x4c |
63 | #define HIFMC_DMA_MAX_LEN (4096) |
64 | #define HIFMC_DMA_MASK (HIFMC_DMA_MAX_LEN - 1) |
65 | #define FMC_OP_DMA 0x68 |
66 | #define OP_CTRL_RD_OPCODE(code) (((code) & 0xff) << 16) |
67 | #define OP_CTRL_WR_OPCODE(code) (((code) & 0xff) << 8) |
68 | #define OP_CTRL_RW_OP(op) ((op) << 1) |
69 | #define OP_CTRL_DMA_OP_READY BIT(0) |
70 | #define FMC_OP_READ 0x0 |
71 | #define FMC_OP_WRITE 0x1 |
72 | #define FMC_WAIT_TIMEOUT 1000000 |
73 | |
74 | enum hifmc_iftype { |
75 | IF_TYPE_STD, |
76 | IF_TYPE_DUAL, |
77 | IF_TYPE_DIO, |
78 | IF_TYPE_QUAD, |
79 | IF_TYPE_QIO, |
80 | }; |
81 | |
82 | struct hifmc_priv { |
83 | u32 chipselect; |
84 | u32 clkrate; |
85 | struct hifmc_host *host; |
86 | }; |
87 | |
88 | #define HIFMC_MAX_CHIP_NUM 2 |
89 | struct hifmc_host { |
90 | struct device *dev; |
91 | struct mutex lock; |
92 | |
93 | void __iomem *regbase; |
94 | void __iomem *iobase; |
95 | struct clk *clk; |
96 | void *buffer; |
97 | dma_addr_t dma_buffer; |
98 | |
99 | struct spi_nor *nor[HIFMC_MAX_CHIP_NUM]; |
100 | u32 num_chip; |
101 | }; |
102 | |
103 | static inline int hisi_spi_nor_wait_op_finish(struct hifmc_host *host) |
104 | { |
105 | u32 reg; |
106 | |
107 | return readl_poll_timeout(host->regbase + FMC_INT, reg, |
108 | (reg & FMC_INT_OP_DONE), 0, FMC_WAIT_TIMEOUT); |
109 | } |
110 | |
111 | static int hisi_spi_nor_get_if_type(enum spi_nor_protocol proto) |
112 | { |
113 | enum hifmc_iftype if_type; |
114 | |
115 | switch (proto) { |
116 | case SNOR_PROTO_1_1_2: |
117 | if_type = IF_TYPE_DUAL; |
118 | break; |
119 | case SNOR_PROTO_1_2_2: |
120 | if_type = IF_TYPE_DIO; |
121 | break; |
122 | case SNOR_PROTO_1_1_4: |
123 | if_type = IF_TYPE_QUAD; |
124 | break; |
125 | case SNOR_PROTO_1_4_4: |
126 | if_type = IF_TYPE_QIO; |
127 | break; |
128 | case SNOR_PROTO_1_1_1: |
129 | default: |
130 | if_type = IF_TYPE_STD; |
131 | break; |
132 | } |
133 | |
134 | return if_type; |
135 | } |
136 | |
137 | static void hisi_spi_nor_init(struct hifmc_host *host) |
138 | { |
139 | u32 reg; |
140 | |
141 | reg = TIMING_CFG_TCSH(CS_HOLD_TIME) |
142 | | TIMING_CFG_TCSS(CS_SETUP_TIME) |
143 | | TIMING_CFG_TSHSL(CS_DESELECT_TIME); |
144 | writel(val: reg, addr: host->regbase + FMC_SPI_TIMING_CFG); |
145 | } |
146 | |
147 | static int hisi_spi_nor_prep(struct spi_nor *nor) |
148 | { |
149 | struct hifmc_priv *priv = nor->priv; |
150 | struct hifmc_host *host = priv->host; |
151 | int ret; |
152 | |
153 | mutex_lock(&host->lock); |
154 | |
155 | ret = clk_set_rate(clk: host->clk, rate: priv->clkrate); |
156 | if (ret) |
157 | goto out; |
158 | |
159 | ret = clk_prepare_enable(clk: host->clk); |
160 | if (ret) |
161 | goto out; |
162 | |
163 | return 0; |
164 | |
165 | out: |
166 | mutex_unlock(lock: &host->lock); |
167 | return ret; |
168 | } |
169 | |
170 | static void hisi_spi_nor_unprep(struct spi_nor *nor) |
171 | { |
172 | struct hifmc_priv *priv = nor->priv; |
173 | struct hifmc_host *host = priv->host; |
174 | |
175 | clk_disable_unprepare(clk: host->clk); |
176 | mutex_unlock(lock: &host->lock); |
177 | } |
178 | |
179 | static int hisi_spi_nor_op_reg(struct spi_nor *nor, |
180 | u8 opcode, size_t len, u8 optype) |
181 | { |
182 | struct hifmc_priv *priv = nor->priv; |
183 | struct hifmc_host *host = priv->host; |
184 | u32 reg; |
185 | |
186 | reg = FMC_CMD_CMD1(opcode); |
187 | writel(val: reg, addr: host->regbase + FMC_CMD); |
188 | |
189 | reg = FMC_DATA_NUM_CNT(len); |
190 | writel(val: reg, addr: host->regbase + FMC_DATA_NUM); |
191 | |
192 | reg = OP_CFG_FM_CS(priv->chipselect); |
193 | writel(val: reg, addr: host->regbase + FMC_OP_CFG); |
194 | |
195 | writel(val: 0xff, addr: host->regbase + FMC_INT_CLR); |
196 | reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START | optype; |
197 | writel(val: reg, addr: host->regbase + FMC_OP); |
198 | |
199 | return hisi_spi_nor_wait_op_finish(host); |
200 | } |
201 | |
202 | static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, |
203 | size_t len) |
204 | { |
205 | struct hifmc_priv *priv = nor->priv; |
206 | struct hifmc_host *host = priv->host; |
207 | int ret; |
208 | |
209 | ret = hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_READ_DATA_EN); |
210 | if (ret) |
211 | return ret; |
212 | |
213 | memcpy_fromio(buf, host->iobase, len); |
214 | return 0; |
215 | } |
216 | |
217 | static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode, |
218 | const u8 *buf, size_t len) |
219 | { |
220 | struct hifmc_priv *priv = nor->priv; |
221 | struct hifmc_host *host = priv->host; |
222 | |
223 | if (len) |
224 | memcpy_toio(host->iobase, buf, len); |
225 | |
226 | return hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_WRITE_DATA_EN); |
227 | } |
228 | |
229 | static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off, |
230 | dma_addr_t dma_buf, size_t len, u8 op_type) |
231 | { |
232 | struct hifmc_priv *priv = nor->priv; |
233 | struct hifmc_host *host = priv->host; |
234 | u8 if_type = 0; |
235 | u32 reg; |
236 | |
237 | reg = readl(addr: host->regbase + FMC_CFG); |
238 | reg &= ~(FMC_CFG_OP_MODE_MASK | SPI_NOR_ADDR_MODE_MASK); |
239 | reg |= FMC_CFG_OP_MODE_NORMAL; |
240 | reg |= (nor->addr_nbytes == 4) ? SPI_NOR_ADDR_MODE_4BYTES |
241 | : SPI_NOR_ADDR_MODE_3BYTES; |
242 | writel(val: reg, addr: host->regbase + FMC_CFG); |
243 | |
244 | writel(val: start_off, addr: host->regbase + FMC_ADDRL); |
245 | writel(val: dma_buf, addr: host->regbase + FMC_DMA_SADDR_D0); |
246 | writel(FMC_DMA_LEN_SET(len), addr: host->regbase + FMC_DMA_LEN); |
247 | |
248 | reg = OP_CFG_FM_CS(priv->chipselect); |
249 | if (op_type == FMC_OP_READ) |
250 | if_type = hisi_spi_nor_get_if_type(proto: nor->read_proto); |
251 | else |
252 | if_type = hisi_spi_nor_get_if_type(proto: nor->write_proto); |
253 | reg |= OP_CFG_MEM_IF_TYPE(if_type); |
254 | if (op_type == FMC_OP_READ) |
255 | reg |= OP_CFG_DUMMY_NUM(nor->read_dummy >> 3); |
256 | writel(val: reg, addr: host->regbase + FMC_OP_CFG); |
257 | |
258 | writel(val: 0xff, addr: host->regbase + FMC_INT_CLR); |
259 | reg = OP_CTRL_RW_OP(op_type) | OP_CTRL_DMA_OP_READY; |
260 | reg |= (op_type == FMC_OP_READ) |
261 | ? OP_CTRL_RD_OPCODE(nor->read_opcode) |
262 | : OP_CTRL_WR_OPCODE(nor->program_opcode); |
263 | writel(val: reg, addr: host->regbase + FMC_OP_DMA); |
264 | |
265 | return hisi_spi_nor_wait_op_finish(host); |
266 | } |
267 | |
268 | static ssize_t hisi_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len, |
269 | u_char *read_buf) |
270 | { |
271 | struct hifmc_priv *priv = nor->priv; |
272 | struct hifmc_host *host = priv->host; |
273 | size_t offset; |
274 | int ret; |
275 | |
276 | for (offset = 0; offset < len; offset += HIFMC_DMA_MAX_LEN) { |
277 | size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset); |
278 | |
279 | ret = hisi_spi_nor_dma_transfer(nor, |
280 | start_off: from + offset, dma_buf: host->dma_buffer, len: trans, FMC_OP_READ); |
281 | if (ret) { |
282 | dev_warn(nor->dev, "DMA read timeout\n" ); |
283 | return ret; |
284 | } |
285 | memcpy(read_buf + offset, host->buffer, trans); |
286 | } |
287 | |
288 | return len; |
289 | } |
290 | |
291 | static ssize_t hisi_spi_nor_write(struct spi_nor *nor, loff_t to, |
292 | size_t len, const u_char *write_buf) |
293 | { |
294 | struct hifmc_priv *priv = nor->priv; |
295 | struct hifmc_host *host = priv->host; |
296 | size_t offset; |
297 | int ret; |
298 | |
299 | for (offset = 0; offset < len; offset += HIFMC_DMA_MAX_LEN) { |
300 | size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset); |
301 | |
302 | memcpy(host->buffer, write_buf + offset, trans); |
303 | ret = hisi_spi_nor_dma_transfer(nor, |
304 | start_off: to + offset, dma_buf: host->dma_buffer, len: trans, FMC_OP_WRITE); |
305 | if (ret) { |
306 | dev_warn(nor->dev, "DMA write timeout\n" ); |
307 | return ret; |
308 | } |
309 | } |
310 | |
311 | return len; |
312 | } |
313 | |
314 | static const struct spi_nor_controller_ops hisi_controller_ops = { |
315 | .prepare = hisi_spi_nor_prep, |
316 | .unprepare = hisi_spi_nor_unprep, |
317 | .read_reg = hisi_spi_nor_read_reg, |
318 | .write_reg = hisi_spi_nor_write_reg, |
319 | .read = hisi_spi_nor_read, |
320 | .write = hisi_spi_nor_write, |
321 | }; |
322 | |
323 | /* |
324 | * Get spi flash device information and register it as a mtd device. |
325 | */ |
326 | static int hisi_spi_nor_register(struct device_node *np, |
327 | struct hifmc_host *host) |
328 | { |
329 | const struct spi_nor_hwcaps hwcaps = { |
330 | .mask = SNOR_HWCAPS_READ | |
331 | SNOR_HWCAPS_READ_FAST | |
332 | SNOR_HWCAPS_READ_1_1_2 | |
333 | SNOR_HWCAPS_READ_1_1_4 | |
334 | SNOR_HWCAPS_PP, |
335 | }; |
336 | struct device *dev = host->dev; |
337 | struct spi_nor *nor; |
338 | struct hifmc_priv *priv; |
339 | struct mtd_info *mtd; |
340 | int ret; |
341 | |
342 | nor = devm_kzalloc(dev, size: sizeof(*nor), GFP_KERNEL); |
343 | if (!nor) |
344 | return -ENOMEM; |
345 | |
346 | nor->dev = dev; |
347 | spi_nor_set_flash_node(nor, np); |
348 | |
349 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
350 | if (!priv) |
351 | return -ENOMEM; |
352 | |
353 | ret = of_property_read_u32(np, propname: "reg" , out_value: &priv->chipselect); |
354 | if (ret) { |
355 | dev_err(dev, "There's no reg property for %pOF\n" , |
356 | np); |
357 | return ret; |
358 | } |
359 | |
360 | ret = of_property_read_u32(np, propname: "spi-max-frequency" , |
361 | out_value: &priv->clkrate); |
362 | if (ret) { |
363 | dev_err(dev, "There's no spi-max-frequency property for %pOF\n" , |
364 | np); |
365 | return ret; |
366 | } |
367 | priv->host = host; |
368 | nor->priv = priv; |
369 | nor->controller_ops = &hisi_controller_ops; |
370 | |
371 | ret = spi_nor_scan(nor, NULL, hwcaps: &hwcaps); |
372 | if (ret) |
373 | return ret; |
374 | |
375 | mtd = &nor->mtd; |
376 | mtd->name = np->name; |
377 | ret = mtd_device_register(mtd, NULL, 0); |
378 | if (ret) |
379 | return ret; |
380 | |
381 | host->nor[host->num_chip] = nor; |
382 | host->num_chip++; |
383 | return 0; |
384 | } |
385 | |
386 | static void hisi_spi_nor_unregister_all(struct hifmc_host *host) |
387 | { |
388 | int i; |
389 | |
390 | for (i = 0; i < host->num_chip; i++) |
391 | mtd_device_unregister(master: &host->nor[i]->mtd); |
392 | } |
393 | |
394 | static int hisi_spi_nor_register_all(struct hifmc_host *host) |
395 | { |
396 | struct device *dev = host->dev; |
397 | struct device_node *np; |
398 | int ret; |
399 | |
400 | for_each_available_child_of_node(dev->of_node, np) { |
401 | ret = hisi_spi_nor_register(np, host); |
402 | if (ret) { |
403 | of_node_put(node: np); |
404 | goto fail; |
405 | } |
406 | |
407 | if (host->num_chip == HIFMC_MAX_CHIP_NUM) { |
408 | dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n" ); |
409 | of_node_put(node: np); |
410 | break; |
411 | } |
412 | } |
413 | |
414 | return 0; |
415 | |
416 | fail: |
417 | hisi_spi_nor_unregister_all(host); |
418 | return ret; |
419 | } |
420 | |
421 | static int hisi_spi_nor_probe(struct platform_device *pdev) |
422 | { |
423 | struct device *dev = &pdev->dev; |
424 | struct hifmc_host *host; |
425 | int ret; |
426 | |
427 | host = devm_kzalloc(dev, size: sizeof(*host), GFP_KERNEL); |
428 | if (!host) |
429 | return -ENOMEM; |
430 | |
431 | platform_set_drvdata(pdev, data: host); |
432 | host->dev = dev; |
433 | |
434 | host->regbase = devm_platform_ioremap_resource_byname(pdev, name: "control" ); |
435 | if (IS_ERR(ptr: host->regbase)) |
436 | return PTR_ERR(ptr: host->regbase); |
437 | |
438 | host->iobase = devm_platform_ioremap_resource_byname(pdev, name: "memory" ); |
439 | if (IS_ERR(ptr: host->iobase)) |
440 | return PTR_ERR(ptr: host->iobase); |
441 | |
442 | host->clk = devm_clk_get(dev, NULL); |
443 | if (IS_ERR(ptr: host->clk)) |
444 | return PTR_ERR(ptr: host->clk); |
445 | |
446 | ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); |
447 | if (ret) { |
448 | dev_warn(dev, "Unable to set dma mask\n" ); |
449 | return ret; |
450 | } |
451 | |
452 | host->buffer = dmam_alloc_coherent(dev, HIFMC_DMA_MAX_LEN, |
453 | dma_handle: &host->dma_buffer, GFP_KERNEL); |
454 | if (!host->buffer) |
455 | return -ENOMEM; |
456 | |
457 | ret = clk_prepare_enable(clk: host->clk); |
458 | if (ret) |
459 | return ret; |
460 | |
461 | mutex_init(&host->lock); |
462 | hisi_spi_nor_init(host); |
463 | ret = hisi_spi_nor_register_all(host); |
464 | if (ret) |
465 | mutex_destroy(lock: &host->lock); |
466 | |
467 | clk_disable_unprepare(clk: host->clk); |
468 | return ret; |
469 | } |
470 | |
471 | static void hisi_spi_nor_remove(struct platform_device *pdev) |
472 | { |
473 | struct hifmc_host *host = platform_get_drvdata(pdev); |
474 | |
475 | hisi_spi_nor_unregister_all(host); |
476 | mutex_destroy(lock: &host->lock); |
477 | } |
478 | |
479 | static const struct of_device_id hisi_spi_nor_dt_ids[] = { |
480 | { .compatible = "hisilicon,fmc-spi-nor" }, |
481 | { /* sentinel */ } |
482 | }; |
483 | MODULE_DEVICE_TABLE(of, hisi_spi_nor_dt_ids); |
484 | |
485 | static struct platform_driver hisi_spi_nor_driver = { |
486 | .driver = { |
487 | .name = "hisi-sfc" , |
488 | .of_match_table = hisi_spi_nor_dt_ids, |
489 | }, |
490 | .probe = hisi_spi_nor_probe, |
491 | .remove_new = hisi_spi_nor_remove, |
492 | }; |
493 | module_platform_driver(hisi_spi_nor_driver); |
494 | |
495 | MODULE_LICENSE("GPL v2" ); |
496 | MODULE_DESCRIPTION("HiSilicon SPI Nor Flash Controller Driver" ); |
497 | |