1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * SG2044 SPI NOR controller driver
4 *
5 * Copyright (c) 2025 Longbin Li <looong.bin@gmail.com>
6 */
7
8 #include <linux/bitfield.h>
9 #include <linux/clk.h>
10 #include <linux/iopoll.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/platform_device.h>
14 #include <linux/spi/spi-mem.h>
15
16 /* Hardware register definitions */
17 #define SPIFMC_CTRL 0x00
18 #define SPIFMC_CTRL_CPHA BIT(12)
19 #define SPIFMC_CTRL_CPOL BIT(13)
20 #define SPIFMC_CTRL_HOLD_OL BIT(14)
21 #define SPIFMC_CTRL_WP_OL BIT(15)
22 #define SPIFMC_CTRL_LSBF BIT(20)
23 #define SPIFMC_CTRL_SRST BIT(21)
24 #define SPIFMC_CTRL_SCK_DIV_SHIFT 0
25 #define SPIFMC_CTRL_FRAME_LEN_SHIFT 16
26 #define SPIFMC_CTRL_SCK_DIV_MASK 0x7FF
27
28 #define SPIFMC_CE_CTRL 0x04
29 #define SPIFMC_CE_CTRL_CEMANUAL BIT(0)
30 #define SPIFMC_CE_CTRL_CEMANUAL_EN BIT(1)
31
32 #define SPIFMC_DLY_CTRL 0x08
33 #define SPIFMC_CTRL_FM_INTVL_MASK 0x000f
34 #define SPIFMC_CTRL_FM_INTVL BIT(0)
35 #define SPIFMC_CTRL_CET_MASK 0x0f00
36 #define SPIFMC_CTRL_CET BIT(8)
37
38 #define SPIFMC_DMMR 0x0c
39
40 #define SPIFMC_TRAN_CSR 0x10
41 #define SPIFMC_TRAN_CSR_TRAN_MODE_MASK GENMASK(1, 0)
42 #define SPIFMC_TRAN_CSR_TRAN_MODE_RX BIT(0)
43 #define SPIFMC_TRAN_CSR_TRAN_MODE_TX BIT(1)
44 #define SPIFMC_TRAN_CSR_FAST_MODE BIT(3)
45 #define SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT (0x00 << 4)
46 #define SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT (0x01 << 4)
47 #define SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT (0x02 << 4)
48 #define SPIFMC_TRAN_CSR_DMA_EN BIT(6)
49 #define SPIFMC_TRAN_CSR_MISO_LEVEL BIT(7)
50 #define SPIFMC_TRAN_CSR_ADDR_BYTES_MASK GENMASK(10, 8)
51 #define SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT 8
52 #define SPIFMC_TRAN_CSR_WITH_CMD BIT(11)
53 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK GENMASK(13, 12)
54 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE (0x00 << 12)
55 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_2_BYTE (0x01 << 12)
56 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE (0x02 << 12)
57 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE (0x03 << 12)
58 #define SPIFMC_TRAN_CSR_GO_BUSY BIT(15)
59 #define SPIFMC_TRAN_CSR_ADDR4B_SHIFT 20
60 #define SPIFMC_TRAN_CSR_CMD4B_SHIFT 21
61
62 #define SPIFMC_TRAN_NUM 0x14
63 #define SPIFMC_FIFO_PORT 0x18
64 #define SPIFMC_FIFO_PT 0x20
65
66 #define SPIFMC_INT_STS 0x28
67 #define SPIFMC_INT_TRAN_DONE BIT(0)
68 #define SPIFMC_INT_RD_FIFO BIT(2)
69 #define SPIFMC_INT_WR_FIFO BIT(3)
70 #define SPIFMC_INT_RX_FRAME BIT(4)
71 #define SPIFMC_INT_TX_FRAME BIT(5)
72
73 #define SPIFMC_INT_EN 0x2c
74 #define SPIFMC_INT_TRAN_DONE_EN BIT(0)
75 #define SPIFMC_INT_RD_FIFO_EN BIT(2)
76 #define SPIFMC_INT_WR_FIFO_EN BIT(3)
77 #define SPIFMC_INT_RX_FRAME_EN BIT(4)
78 #define SPIFMC_INT_TX_FRAME_EN BIT(5)
79
80 #define SPIFMC_OPT 0x030
81 #define SPIFMC_OPT_DISABLE_FIFO_FLUSH BIT(1)
82
83 #define SPIFMC_MAX_FIFO_DEPTH 8
84
85 #define SPIFMC_MAX_READ_SIZE 0x10000
86
87 struct sg204x_spifmc_chip_info {
88 bool has_opt_reg;
89 u32 rd_fifo_int_trigger_level;
90 };
91
92 struct sg2044_spifmc {
93 struct spi_controller *ctrl;
94 void __iomem *io_base;
95 struct device *dev;
96 struct mutex lock;
97 struct clk *clk;
98 const struct sg204x_spifmc_chip_info *chip_info;
99 };
100
sg2044_spifmc_wait_int(struct sg2044_spifmc * spifmc,u8 int_type)101 static int sg2044_spifmc_wait_int(struct sg2044_spifmc *spifmc, u8 int_type)
102 {
103 u32 stat;
104
105 return readl_poll_timeout(spifmc->io_base + SPIFMC_INT_STS, stat,
106 (stat & int_type), 0, 1000000);
107 }
108
sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc * spifmc,int xfer_size)109 static int sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc *spifmc,
110 int xfer_size)
111 {
112 u8 stat;
113
114 return readl_poll_timeout(spifmc->io_base + SPIFMC_FIFO_PT, stat,
115 ((stat & 0xf) == xfer_size), 1, 1000000);
116 }
117
sg2044_spifmc_init_reg(struct sg2044_spifmc * spifmc)118 static u32 sg2044_spifmc_init_reg(struct sg2044_spifmc *spifmc)
119 {
120 u32 reg;
121
122 reg = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
123 reg &= ~(SPIFMC_TRAN_CSR_TRAN_MODE_MASK |
124 SPIFMC_TRAN_CSR_FAST_MODE |
125 SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT |
126 SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT |
127 SPIFMC_TRAN_CSR_DMA_EN |
128 SPIFMC_TRAN_CSR_ADDR_BYTES_MASK |
129 SPIFMC_TRAN_CSR_WITH_CMD |
130 SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK);
131
132 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
133
134 return reg;
135 }
136
sg2044_spifmc_read_64k(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op,loff_t from,size_t len,u_char * buf)137 static ssize_t sg2044_spifmc_read_64k(struct sg2044_spifmc *spifmc,
138 const struct spi_mem_op *op, loff_t from,
139 size_t len, u_char *buf)
140 {
141 int xfer_size, offset;
142 u32 reg;
143 int ret;
144 int i;
145
146 reg = sg2044_spifmc_init_reg(spifmc);
147 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
148 reg |= spifmc->chip_info->rd_fifo_int_trigger_level;
149 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
150 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
151
152 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
153 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
154
155 for (i = op->addr.nbytes - 1; i >= 0; i--)
156 writeb((from >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
157
158 for (i = 0; i < op->dummy.nbytes; i++)
159 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
160
161 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
162 writel(0, spifmc->io_base + SPIFMC_INT_STS);
163 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
164 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
165
166 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_RD_FIFO);
167 if (ret < 0)
168 return ret;
169
170 offset = 0;
171 while (offset < len) {
172 xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, len - offset);
173
174 ret = sg2044_spifmc_wait_xfer_size(spifmc, xfer_size);
175 if (ret < 0)
176 return ret;
177
178 for (i = 0; i < xfer_size; i++)
179 buf[i + offset] = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
180
181 offset += xfer_size;
182 }
183
184 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
185 if (ret < 0)
186 return ret;
187
188 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
189
190 return len;
191 }
192
sg2044_spifmc_read(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)193 static ssize_t sg2044_spifmc_read(struct sg2044_spifmc *spifmc,
194 const struct spi_mem_op *op)
195 {
196 size_t xfer_size;
197 size_t offset;
198 loff_t from = op->addr.val;
199 size_t len = op->data.nbytes;
200 int ret;
201 u8 *din = op->data.buf.in;
202
203 offset = 0;
204 while (offset < len) {
205 xfer_size = min_t(size_t, SPIFMC_MAX_READ_SIZE, len - offset);
206
207 ret = sg2044_spifmc_read_64k(spifmc, op, from, xfer_size, din);
208 if (ret < 0)
209 return ret;
210
211 offset += xfer_size;
212 din += xfer_size;
213 from += xfer_size;
214 }
215
216 return 0;
217 }
218
sg2044_spifmc_write(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)219 static ssize_t sg2044_spifmc_write(struct sg2044_spifmc *spifmc,
220 const struct spi_mem_op *op)
221 {
222 size_t xfer_size;
223 const u8 *dout = op->data.buf.out;
224 int i, offset;
225 int ret;
226 u32 reg;
227
228 reg = sg2044_spifmc_init_reg(spifmc);
229 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
230 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
231 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
232 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
233
234 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
235 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
236
237 for (i = op->addr.nbytes - 1; i >= 0; i--)
238 writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
239
240 for (i = 0; i < op->dummy.nbytes; i++)
241 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
242
243 writel(0, spifmc->io_base + SPIFMC_INT_STS);
244 writel(op->data.nbytes, spifmc->io_base + SPIFMC_TRAN_NUM);
245 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
246 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
247
248 ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
249 if (ret < 0)
250 return ret;
251
252 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
253
254 offset = 0;
255 while (offset < op->data.nbytes) {
256 xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, op->data.nbytes - offset);
257
258 ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
259 if (ret < 0)
260 return ret;
261
262 for (i = 0; i < xfer_size; i++)
263 writeb(dout[i + offset], spifmc->io_base + SPIFMC_FIFO_PORT);
264
265 offset += xfer_size;
266 }
267
268 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
269 if (ret < 0)
270 return ret;
271
272 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
273
274 return 0;
275 }
276
sg2044_spifmc_tran_cmd(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)277 static ssize_t sg2044_spifmc_tran_cmd(struct sg2044_spifmc *spifmc,
278 const struct spi_mem_op *op)
279 {
280 int i, ret;
281 u32 reg;
282
283 reg = sg2044_spifmc_init_reg(spifmc);
284 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
285 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
286 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
287
288 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
289 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
290
291 for (i = op->addr.nbytes - 1; i >= 0; i--)
292 writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
293
294 for (i = 0; i < op->dummy.nbytes; i++)
295 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
296
297 writel(0, spifmc->io_base + SPIFMC_INT_STS);
298 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
299 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
300
301 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
302 if (ret < 0)
303 return ret;
304
305 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
306
307 return 0;
308 }
309
sg2044_spifmc_trans(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)310 static void sg2044_spifmc_trans(struct sg2044_spifmc *spifmc,
311 const struct spi_mem_op *op)
312 {
313 if (op->data.dir == SPI_MEM_DATA_IN)
314 sg2044_spifmc_read(spifmc, op);
315 else if (op->data.dir == SPI_MEM_DATA_OUT)
316 sg2044_spifmc_write(spifmc, op);
317 else
318 sg2044_spifmc_tran_cmd(spifmc, op);
319 }
320
sg2044_spifmc_trans_reg(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)321 static ssize_t sg2044_spifmc_trans_reg(struct sg2044_spifmc *spifmc,
322 const struct spi_mem_op *op)
323 {
324 const u8 *dout = NULL;
325 u8 *din = NULL;
326 size_t len = op->data.nbytes;
327 int ret, i;
328 u32 reg;
329
330 if (op->data.dir == SPI_MEM_DATA_IN)
331 din = op->data.buf.in;
332 else
333 dout = op->data.buf.out;
334
335 reg = sg2044_spifmc_init_reg(spifmc);
336 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
337 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
338
339 if (din) {
340 reg |= SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT;
341 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
342 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
343
344 if (spifmc->chip_info->has_opt_reg)
345 writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT);
346 } else {
347 /*
348 * If write values to the Status Register,
349 * configure TRAN_CSR register as the same as
350 * sg2044_spifmc_read_reg.
351 */
352 if (op->cmd.opcode == 0x01) {
353 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
354 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
355 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
356 }
357 }
358
359 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
360 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
361
362 for (i = 0; i < len; i++) {
363 if (din)
364 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
365 else
366 writeb(dout[i], spifmc->io_base + SPIFMC_FIFO_PORT);
367 }
368
369 writel(0, spifmc->io_base + SPIFMC_INT_STS);
370 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
371 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
372 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
373
374 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
375 if (ret < 0)
376 return ret;
377
378 if (din) {
379 while (len--)
380 *din++ = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
381 }
382
383 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
384
385 return 0;
386 }
387
sg2044_spifmc_exec_op(struct spi_mem * mem,const struct spi_mem_op * op)388 static int sg2044_spifmc_exec_op(struct spi_mem *mem,
389 const struct spi_mem_op *op)
390 {
391 struct sg2044_spifmc *spifmc;
392
393 spifmc = spi_controller_get_devdata(mem->spi->controller);
394
395 mutex_lock(&spifmc->lock);
396
397 if (op->addr.nbytes == 0)
398 sg2044_spifmc_trans_reg(spifmc, op);
399 else
400 sg2044_spifmc_trans(spifmc, op);
401
402 mutex_unlock(&spifmc->lock);
403
404 return 0;
405 }
406
407 static const struct spi_controller_mem_ops sg2044_spifmc_mem_ops = {
408 .exec_op = sg2044_spifmc_exec_op,
409 };
410
sg2044_spifmc_init(struct sg2044_spifmc * spifmc)411 static void sg2044_spifmc_init(struct sg2044_spifmc *spifmc)
412 {
413 u32 tran_csr;
414 u32 reg;
415
416 writel(0, spifmc->io_base + SPIFMC_DMMR);
417
418 reg = readl(spifmc->io_base + SPIFMC_CTRL);
419 reg |= SPIFMC_CTRL_SRST;
420 reg &= ~(SPIFMC_CTRL_SCK_DIV_MASK);
421 reg |= 1;
422 writel(reg, spifmc->io_base + SPIFMC_CTRL);
423
424 writel(0, spifmc->io_base + SPIFMC_CE_CTRL);
425
426 tran_csr = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
427 tran_csr |= (0 << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT);
428 tran_csr |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE;
429 tran_csr |= SPIFMC_TRAN_CSR_WITH_CMD;
430 writel(tran_csr, spifmc->io_base + SPIFMC_TRAN_CSR);
431 }
432
sg2044_spifmc_probe(struct platform_device * pdev)433 static int sg2044_spifmc_probe(struct platform_device *pdev)
434 {
435 struct device *dev = &pdev->dev;
436 struct spi_controller *ctrl;
437 struct sg2044_spifmc *spifmc;
438 int ret;
439
440 ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifmc));
441 if (!ctrl)
442 return -ENOMEM;
443
444 spifmc = spi_controller_get_devdata(ctrl);
445
446 spifmc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
447 if (IS_ERR(spifmc->clk))
448 return dev_err_probe(dev, PTR_ERR(spifmc->clk), "Cannot get and enable AHB clock\n");
449
450 spifmc->dev = &pdev->dev;
451 spifmc->ctrl = ctrl;
452
453 spifmc->io_base = devm_platform_ioremap_resource(pdev, 0);
454 if (IS_ERR(spifmc->io_base))
455 return PTR_ERR(spifmc->io_base);
456
457 ctrl->num_chipselect = 1;
458 ctrl->dev.of_node = pdev->dev.of_node;
459 ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
460 ctrl->auto_runtime_pm = false;
461 ctrl->mem_ops = &sg2044_spifmc_mem_ops;
462 ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
463
464 ret = devm_mutex_init(dev, &spifmc->lock);
465 if (ret)
466 return ret;
467 spifmc->chip_info = device_get_match_data(&pdev->dev);
468 if (!spifmc->chip_info) {
469 dev_err(&pdev->dev, "Failed to get specific chip info\n");
470 return -EINVAL;
471 }
472
473 sg2044_spifmc_init(spifmc);
474 sg2044_spifmc_init_reg(spifmc);
475
476 ret = devm_spi_register_controller(&pdev->dev, ctrl);
477 if (ret)
478 return dev_err_probe(dev, ret, "spi_register_controller failed\n");
479
480 return 0;
481 }
482
483 static const struct sg204x_spifmc_chip_info sg2044_chip_info = {
484 .has_opt_reg = true,
485 .rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE,
486 };
487
488 static const struct sg204x_spifmc_chip_info sg2042_chip_info = {
489 .has_opt_reg = false,
490 .rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE,
491 };
492
493 static const struct of_device_id sg2044_spifmc_match[] = {
494 { .compatible = "sophgo,sg2044-spifmc-nor", .data = &sg2044_chip_info },
495 { .compatible = "sophgo,sg2042-spifmc-nor", .data = &sg2042_chip_info },
496 { /* sentinel */ }
497 };
498 MODULE_DEVICE_TABLE(of, sg2044_spifmc_match);
499
500 static struct platform_driver sg2044_nor_driver = {
501 .driver = {
502 .name = "sg2044,spifmc-nor",
503 .of_match_table = sg2044_spifmc_match,
504 },
505 .probe = sg2044_spifmc_probe,
506 };
507 module_platform_driver(sg2044_nor_driver);
508
509 MODULE_DESCRIPTION("SG2044 SPI NOR controller driver");
510 MODULE_AUTHOR("Longbin Li <looong.bin@gmail.com>");
511 MODULE_LICENSE("GPL");
512