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 sg2044_spifmc {
88 struct spi_controller *ctrl;
89 void __iomem *io_base;
90 struct device *dev;
91 struct mutex lock;
92 struct clk *clk;
93 };
94
sg2044_spifmc_wait_int(struct sg2044_spifmc * spifmc,u8 int_type)95 static int sg2044_spifmc_wait_int(struct sg2044_spifmc *spifmc, u8 int_type)
96 {
97 u32 stat;
98
99 return readl_poll_timeout(spifmc->io_base + SPIFMC_INT_STS, stat,
100 (stat & int_type), 0, 1000000);
101 }
102
sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc * spifmc,int xfer_size)103 static int sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc *spifmc,
104 int xfer_size)
105 {
106 u8 stat;
107
108 return readl_poll_timeout(spifmc->io_base + SPIFMC_FIFO_PT, stat,
109 ((stat & 0xf) == xfer_size), 1, 1000000);
110 }
111
sg2044_spifmc_init_reg(struct sg2044_spifmc * spifmc)112 static u32 sg2044_spifmc_init_reg(struct sg2044_spifmc *spifmc)
113 {
114 u32 reg;
115
116 reg = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
117 reg &= ~(SPIFMC_TRAN_CSR_TRAN_MODE_MASK |
118 SPIFMC_TRAN_CSR_FAST_MODE |
119 SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT |
120 SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT |
121 SPIFMC_TRAN_CSR_DMA_EN |
122 SPIFMC_TRAN_CSR_ADDR_BYTES_MASK |
123 SPIFMC_TRAN_CSR_WITH_CMD |
124 SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK);
125
126 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
127
128 return reg;
129 }
130
sg2044_spifmc_read_64k(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op,loff_t from,size_t len,u_char * buf)131 static ssize_t sg2044_spifmc_read_64k(struct sg2044_spifmc *spifmc,
132 const struct spi_mem_op *op, loff_t from,
133 size_t len, u_char *buf)
134 {
135 int xfer_size, offset;
136 u32 reg;
137 int ret;
138 int i;
139
140 reg = sg2044_spifmc_init_reg(spifmc);
141 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
142 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
143 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
144 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
145
146 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
147 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
148
149 for (i = op->addr.nbytes - 1; i >= 0; i--)
150 writeb((from >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
151
152 for (i = 0; i < op->dummy.nbytes; i++)
153 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
154
155 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
156 writel(0, spifmc->io_base + SPIFMC_INT_STS);
157 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
158 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
159
160 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_RD_FIFO);
161 if (ret < 0)
162 return ret;
163
164 offset = 0;
165 while (offset < len) {
166 xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, len - offset);
167
168 ret = sg2044_spifmc_wait_xfer_size(spifmc, xfer_size);
169 if (ret < 0)
170 return ret;
171
172 for (i = 0; i < xfer_size; i++)
173 buf[i + offset] = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
174
175 offset += xfer_size;
176 }
177
178 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
179 if (ret < 0)
180 return ret;
181
182 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
183
184 return len;
185 }
186
sg2044_spifmc_read(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)187 static ssize_t sg2044_spifmc_read(struct sg2044_spifmc *spifmc,
188 const struct spi_mem_op *op)
189 {
190 size_t xfer_size;
191 size_t offset;
192 loff_t from = op->addr.val;
193 size_t len = op->data.nbytes;
194 int ret;
195 u8 *din = op->data.buf.in;
196
197 offset = 0;
198 while (offset < len) {
199 xfer_size = min_t(size_t, SPIFMC_MAX_READ_SIZE, len - offset);
200
201 ret = sg2044_spifmc_read_64k(spifmc, op, from, xfer_size, din);
202 if (ret < 0)
203 return ret;
204
205 offset += xfer_size;
206 din += xfer_size;
207 from += xfer_size;
208 }
209
210 return 0;
211 }
212
sg2044_spifmc_write(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)213 static ssize_t sg2044_spifmc_write(struct sg2044_spifmc *spifmc,
214 const struct spi_mem_op *op)
215 {
216 size_t xfer_size;
217 const u8 *dout = op->data.buf.out;
218 int i, offset;
219 int ret;
220 u32 reg;
221
222 reg = sg2044_spifmc_init_reg(spifmc);
223 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
224 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
225 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
226 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
227
228 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
229 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
230
231 for (i = op->addr.nbytes - 1; i >= 0; i--)
232 writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
233
234 for (i = 0; i < op->dummy.nbytes; i++)
235 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
236
237 writel(0, spifmc->io_base + SPIFMC_INT_STS);
238 writel(op->data.nbytes, spifmc->io_base + SPIFMC_TRAN_NUM);
239 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
240 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
241
242 ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
243 if (ret < 0)
244 return ret;
245
246 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
247
248 offset = 0;
249 while (offset < op->data.nbytes) {
250 xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, op->data.nbytes - offset);
251
252 ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
253 if (ret < 0)
254 return ret;
255
256 for (i = 0; i < xfer_size; i++)
257 writeb(dout[i + offset], spifmc->io_base + SPIFMC_FIFO_PORT);
258
259 offset += xfer_size;
260 }
261
262 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
263 if (ret < 0)
264 return ret;
265
266 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
267
268 return 0;
269 }
270
sg2044_spifmc_tran_cmd(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)271 static ssize_t sg2044_spifmc_tran_cmd(struct sg2044_spifmc *spifmc,
272 const struct spi_mem_op *op)
273 {
274 int i, ret;
275 u32 reg;
276
277 reg = sg2044_spifmc_init_reg(spifmc);
278 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
279 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
280 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
281
282 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
283 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
284
285 for (i = op->addr.nbytes - 1; i >= 0; i--)
286 writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
287
288 for (i = 0; i < op->dummy.nbytes; i++)
289 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
290
291 writel(0, spifmc->io_base + SPIFMC_INT_STS);
292 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
293 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
294
295 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
296 if (ret < 0)
297 return ret;
298
299 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
300
301 return 0;
302 }
303
sg2044_spifmc_trans(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)304 static void sg2044_spifmc_trans(struct sg2044_spifmc *spifmc,
305 const struct spi_mem_op *op)
306 {
307 if (op->data.dir == SPI_MEM_DATA_IN)
308 sg2044_spifmc_read(spifmc, op);
309 else if (op->data.dir == SPI_MEM_DATA_OUT)
310 sg2044_spifmc_write(spifmc, op);
311 else
312 sg2044_spifmc_tran_cmd(spifmc, op);
313 }
314
sg2044_spifmc_trans_reg(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)315 static ssize_t sg2044_spifmc_trans_reg(struct sg2044_spifmc *spifmc,
316 const struct spi_mem_op *op)
317 {
318 const u8 *dout = NULL;
319 u8 *din = NULL;
320 size_t len = op->data.nbytes;
321 int ret, i;
322 u32 reg;
323
324 if (op->data.dir == SPI_MEM_DATA_IN)
325 din = op->data.buf.in;
326 else
327 dout = op->data.buf.out;
328
329 reg = sg2044_spifmc_init_reg(spifmc);
330 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
331 reg |= SPIFMC_TRAN_CSR_WITH_CMD;
332
333 if (din) {
334 reg |= SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT;
335 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
336 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
337
338 writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT);
339 } else {
340 /*
341 * If write values to the Status Register,
342 * configure TRAN_CSR register as the same as
343 * sg2044_spifmc_read_reg.
344 */
345 if (op->cmd.opcode == 0x01) {
346 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
347 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
348 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
349 }
350 }
351
352 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
353 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
354
355 for (i = 0; i < len; i++) {
356 if (din)
357 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
358 else
359 writeb(dout[i], spifmc->io_base + SPIFMC_FIFO_PORT);
360 }
361
362 writel(0, spifmc->io_base + SPIFMC_INT_STS);
363 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
364 reg |= SPIFMC_TRAN_CSR_GO_BUSY;
365 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
366
367 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
368 if (ret < 0)
369 return ret;
370
371 if (din) {
372 while (len--)
373 *din++ = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
374 }
375
376 writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
377
378 return 0;
379 }
380
sg2044_spifmc_exec_op(struct spi_mem * mem,const struct spi_mem_op * op)381 static int sg2044_spifmc_exec_op(struct spi_mem *mem,
382 const struct spi_mem_op *op)
383 {
384 struct sg2044_spifmc *spifmc;
385
386 spifmc = spi_controller_get_devdata(mem->spi->controller);
387
388 mutex_lock(&spifmc->lock);
389
390 if (op->addr.nbytes == 0)
391 sg2044_spifmc_trans_reg(spifmc, op);
392 else
393 sg2044_spifmc_trans(spifmc, op);
394
395 mutex_unlock(&spifmc->lock);
396
397 return 0;
398 }
399
400 static const struct spi_controller_mem_ops sg2044_spifmc_mem_ops = {
401 .exec_op = sg2044_spifmc_exec_op,
402 };
403
sg2044_spifmc_init(struct sg2044_spifmc * spifmc)404 static void sg2044_spifmc_init(struct sg2044_spifmc *spifmc)
405 {
406 u32 tran_csr;
407 u32 reg;
408
409 writel(0, spifmc->io_base + SPIFMC_DMMR);
410
411 reg = readl(spifmc->io_base + SPIFMC_CTRL);
412 reg |= SPIFMC_CTRL_SRST;
413 reg &= ~(SPIFMC_CTRL_SCK_DIV_MASK);
414 reg |= 1;
415 writel(reg, spifmc->io_base + SPIFMC_CTRL);
416
417 writel(0, spifmc->io_base + SPIFMC_CE_CTRL);
418
419 tran_csr = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
420 tran_csr |= (0 << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT);
421 tran_csr |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE;
422 tran_csr |= SPIFMC_TRAN_CSR_WITH_CMD;
423 writel(tran_csr, spifmc->io_base + SPIFMC_TRAN_CSR);
424 }
425
sg2044_spifmc_probe(struct platform_device * pdev)426 static int sg2044_spifmc_probe(struct platform_device *pdev)
427 {
428 struct device *dev = &pdev->dev;
429 struct spi_controller *ctrl;
430 struct sg2044_spifmc *spifmc;
431 int ret;
432
433 ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifmc));
434 if (!ctrl)
435 return -ENOMEM;
436
437 spifmc = spi_controller_get_devdata(ctrl);
438
439 spifmc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
440 if (IS_ERR(spifmc->clk))
441 return dev_err_probe(dev, PTR_ERR(spifmc->clk), "Cannot get and enable AHB clock\n");
442
443 spifmc->dev = &pdev->dev;
444 spifmc->ctrl = ctrl;
445
446 spifmc->io_base = devm_platform_ioremap_resource(pdev, 0);
447 if (IS_ERR(spifmc->io_base))
448 return PTR_ERR(spifmc->io_base);
449
450 ctrl->num_chipselect = 1;
451 ctrl->dev.of_node = pdev->dev.of_node;
452 ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
453 ctrl->auto_runtime_pm = false;
454 ctrl->mem_ops = &sg2044_spifmc_mem_ops;
455 ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
456
457 ret = devm_mutex_init(dev, &spifmc->lock);
458 if (ret)
459 return ret;
460
461 sg2044_spifmc_init(spifmc);
462 sg2044_spifmc_init_reg(spifmc);
463
464 ret = devm_spi_register_controller(&pdev->dev, ctrl);
465 if (ret)
466 return dev_err_probe(dev, ret, "spi_register_controller failed\n");
467
468 return 0;
469 }
470
471 static const struct of_device_id sg2044_spifmc_match[] = {
472 { .compatible = "sophgo,sg2044-spifmc-nor" },
473 { /* sentinel */ }
474 };
475 MODULE_DEVICE_TABLE(of, sg2044_spifmc_match);
476
477 static struct platform_driver sg2044_nor_driver = {
478 .driver = {
479 .name = "sg2044,spifmc-nor",
480 .of_match_table = sg2044_spifmc_match,
481 },
482 .probe = sg2044_spifmc_probe,
483 };
484 module_platform_driver(sg2044_nor_driver);
485
486 MODULE_DESCRIPTION("SG2044 SPI NOR controller driver");
487 MODULE_AUTHOR("Longbin Li <looong.bin@gmail.com>");
488 MODULE_LICENSE("GPL");
489