blob: 3ea25b293d1dc6a6c421fa9447d84b6575cbdcff [file] [log] [blame]
Christian Marangi50da3da2025-04-07 22:01:56 +02001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2024 AIROHA Inc
4 *
5 * Based on spi-airoha-snfi.c on Linux
6 *
7 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
8 * Author: Ray Liu <ray.liu@airoha.com>
9 */
10
11#include <asm/unaligned.h>
12#include <clk.h>
13#include <dm.h>
14#include <dm/device_compat.h>
15#include <dm/devres.h>
16#include <linux/bitfield.h>
17#include <linux/dma-mapping.h>
18#include <linux/mtd/spinand.h>
19#include <linux/time.h>
20#include <regmap.h>
21#include <spi.h>
22#include <spi-mem.h>
23
24/* SPI */
25#define REG_SPI_CTRL_READ_MODE 0x0000
26#define REG_SPI_CTRL_READ_IDLE_EN 0x0004
27#define REG_SPI_CTRL_SIDLY 0x0008
28#define REG_SPI_CTRL_CSHEXT 0x000c
29#define REG_SPI_CTRL_CSLEXT 0x0010
30
31#define REG_SPI_CTRL_MTX_MODE_TOG 0x0014
32#define SPI_CTRL_MTX_MODE_TOG GENMASK(3, 0)
33
34#define REG_SPI_CTRL_RDCTL_FSM 0x0018
35#define SPI_CTRL_RDCTL_FSM GENMASK(3, 0)
36
37#define REG_SPI_CTRL_MACMUX_SEL 0x001c
38
39#define REG_SPI_CTRL_MANUAL_EN 0x0020
40#define SPI_CTRL_MANUAL_EN BIT(0)
41
42#define REG_SPI_CTRL_OPFIFO_EMPTY 0x0024
43#define SPI_CTRL_OPFIFO_EMPTY BIT(0)
44
45#define REG_SPI_CTRL_OPFIFO_WDATA 0x0028
46#define SPI_CTRL_OPFIFO_LEN GENMASK(8, 0)
47#define SPI_CTRL_OPFIFO_OP GENMASK(13, 9)
48
49#define REG_SPI_CTRL_OPFIFO_FULL 0x002c
50#define SPI_CTRL_OPFIFO_FULL BIT(0)
51
52#define REG_SPI_CTRL_OPFIFO_WR 0x0030
53#define SPI_CTRL_OPFIFO_WR BIT(0)
54
55#define REG_SPI_CTRL_DFIFO_FULL 0x0034
56#define SPI_CTRL_DFIFO_FULL BIT(0)
57
58#define REG_SPI_CTRL_DFIFO_WDATA 0x0038
59#define SPI_CTRL_DFIFO_WDATA GENMASK(7, 0)
60
61#define REG_SPI_CTRL_DFIFO_EMPTY 0x003c
62#define SPI_CTRL_DFIFO_EMPTY BIT(0)
63
64#define REG_SPI_CTRL_DFIFO_RD 0x0040
65#define SPI_CTRL_DFIFO_RD BIT(0)
66
67#define REG_SPI_CTRL_DFIFO_RDATA 0x0044
68#define SPI_CTRL_DFIFO_RDATA GENMASK(7, 0)
69
70#define REG_SPI_CTRL_DUMMY 0x0080
71#define SPI_CTRL_CTRL_DUMMY GENMASK(3, 0)
72
73#define REG_SPI_CTRL_PROBE_SEL 0x0088
74#define REG_SPI_CTRL_INTERRUPT 0x0090
75#define REG_SPI_CTRL_INTERRUPT_EN 0x0094
76#define REG_SPI_CTRL_SI_CK_SEL 0x009c
77#define REG_SPI_CTRL_SW_CFGNANDADDR_VAL 0x010c
78#define REG_SPI_CTRL_SW_CFGNANDADDR_EN 0x0110
79#define REG_SPI_CTRL_SFC_STRAP 0x0114
80
81#define REG_SPI_CTRL_NFI2SPI_EN 0x0130
82#define SPI_CTRL_NFI2SPI_EN BIT(0)
83
84/* NFI2SPI */
85#define REG_SPI_NFI_CNFG 0x0000
86#define SPI_NFI_DMA_MODE BIT(0)
87#define SPI_NFI_READ_MODE BIT(1)
88#define SPI_NFI_DMA_BURST_EN BIT(2)
89#define SPI_NFI_HW_ECC_EN BIT(8)
90#define SPI_NFI_AUTO_FDM_EN BIT(9)
91#define SPI_NFI_OPMODE GENMASK(14, 12)
92
93#define REG_SPI_NFI_PAGEFMT 0x0004
94#define SPI_NFI_PAGE_SIZE GENMASK(1, 0)
95#define SPI_NFI_SPARE_SIZE GENMASK(5, 4)
96
97#define REG_SPI_NFI_CON 0x0008
98#define SPI_NFI_FIFO_FLUSH BIT(0)
99#define SPI_NFI_RST BIT(1)
100#define SPI_NFI_RD_TRIG BIT(8)
101#define SPI_NFI_WR_TRIG BIT(9)
102#define SPI_NFI_SEC_NUM GENMASK(15, 12)
103
104#define REG_SPI_NFI_INTR_EN 0x0010
105#define SPI_NFI_RD_DONE_EN BIT(0)
106#define SPI_NFI_WR_DONE_EN BIT(1)
107#define SPI_NFI_RST_DONE_EN BIT(2)
108#define SPI_NFI_ERASE_DONE_EN BIT(3)
109#define SPI_NFI_BUSY_RETURN_EN BIT(4)
110#define SPI_NFI_ACCESS_LOCK_EN BIT(5)
111#define SPI_NFI_AHB_DONE_EN BIT(6)
112#define SPI_NFI_ALL_IRQ_EN \
113 (SPI_NFI_RD_DONE_EN | SPI_NFI_WR_DONE_EN | \
114 SPI_NFI_RST_DONE_EN | SPI_NFI_ERASE_DONE_EN | \
115 SPI_NFI_BUSY_RETURN_EN | SPI_NFI_ACCESS_LOCK_EN | \
116 SPI_NFI_AHB_DONE_EN)
117
118#define REG_SPI_NFI_INTR 0x0014
119#define SPI_NFI_AHB_DONE BIT(6)
120
121#define REG_SPI_NFI_CMD 0x0020
122
123#define REG_SPI_NFI_ADDR_NOB 0x0030
124#define SPI_NFI_ROW_ADDR_NOB GENMASK(6, 4)
125
126#define REG_SPI_NFI_STA 0x0060
127#define REG_SPI_NFI_FIFOSTA 0x0064
128#define REG_SPI_NFI_STRADDR 0x0080
129#define REG_SPI_NFI_FDM0L 0x00a0
130#define REG_SPI_NFI_FDM0M 0x00a4
131#define REG_SPI_NFI_FDM7L 0x00d8
132#define REG_SPI_NFI_FDM7M 0x00dc
133#define REG_SPI_NFI_FIFODATA0 0x0190
134#define REG_SPI_NFI_FIFODATA1 0x0194
135#define REG_SPI_NFI_FIFODATA2 0x0198
136#define REG_SPI_NFI_FIFODATA3 0x019c
137#define REG_SPI_NFI_MASTERSTA 0x0224
138
139#define REG_SPI_NFI_SECCUS_SIZE 0x022c
140#define SPI_NFI_CUS_SEC_SIZE GENMASK(12, 0)
141#define SPI_NFI_CUS_SEC_SIZE_EN BIT(16)
142
143#define REG_SPI_NFI_RD_CTL2 0x0510
144#define REG_SPI_NFI_RD_CTL3 0x0514
145
146#define REG_SPI_NFI_PG_CTL1 0x0524
147#define SPI_NFI_PG_LOAD_CMD GENMASK(15, 8)
148
149#define REG_SPI_NFI_PG_CTL2 0x0528
150#define REG_SPI_NFI_NOR_PROG_ADDR 0x052c
151#define REG_SPI_NFI_NOR_RD_ADDR 0x0534
152
153#define REG_SPI_NFI_SNF_MISC_CTL 0x0538
154#define SPI_NFI_DATA_READ_WR_MODE GENMASK(18, 16)
155
156#define REG_SPI_NFI_SNF_MISC_CTL2 0x053c
157#define SPI_NFI_READ_DATA_BYTE_NUM GENMASK(12, 0)
158#define SPI_NFI_PROG_LOAD_BYTE_NUM GENMASK(28, 16)
159
160#define REG_SPI_NFI_SNF_STA_CTL1 0x0550
161#define SPI_NFI_READ_FROM_CACHE_DONE BIT(25)
162#define SPI_NFI_LOAD_TO_CACHE_DONE BIT(26)
163
164#define REG_SPI_NFI_SNF_STA_CTL2 0x0554
165
166#define REG_SPI_NFI_SNF_NFI_CNFG 0x055c
167#define SPI_NFI_SPI_MODE BIT(0)
168
169/* SPI NAND Protocol OP */
170#define SPI_NAND_OP_GET_FEATURE 0x0f
171#define SPI_NAND_OP_SET_FEATURE 0x1f
172#define SPI_NAND_OP_PAGE_READ 0x13
173#define SPI_NAND_OP_READ_FROM_CACHE_SINGLE 0x03
174#define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST 0x0b
175#define SPI_NAND_OP_READ_FROM_CACHE_DUAL 0x3b
176#define SPI_NAND_OP_READ_FROM_CACHE_QUAD 0x6b
177#define SPI_NAND_OP_WRITE_ENABLE 0x06
178#define SPI_NAND_OP_WRITE_DISABLE 0x04
179#define SPI_NAND_OP_PROGRAM_LOAD_SINGLE 0x02
180#define SPI_NAND_OP_PROGRAM_LOAD_QUAD 0x32
181#define SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE 0x84
182#define SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD 0x34
183#define SPI_NAND_OP_PROGRAM_EXECUTE 0x10
184#define SPI_NAND_OP_READ_ID 0x9f
185#define SPI_NAND_OP_BLOCK_ERASE 0xd8
186#define SPI_NAND_OP_RESET 0xff
187#define SPI_NAND_OP_DIE_SELECT 0xc2
188
189#define SPI_NAND_CACHE_SIZE (SZ_4K + SZ_256)
190#define SPI_MAX_TRANSFER_SIZE 511
191
192enum airoha_snand_mode {
193 SPI_MODE_AUTO,
194 SPI_MODE_MANUAL,
195 SPI_MODE_DMA,
196};
197
198enum airoha_snand_cs {
199 SPI_CHIP_SEL_HIGH,
200 SPI_CHIP_SEL_LOW,
201};
202
203struct airoha_snand_priv {
204 struct regmap *regmap_ctrl;
205 struct regmap *regmap_nfi;
206 struct clk *spi_clk;
207
208 struct {
209 size_t page_size;
210 size_t sec_size;
211 u8 sec_num;
212 u8 spare_size;
213 } nfi_cfg;
214};
215
216static int airoha_snand_set_fifo_op(struct airoha_snand_priv *priv,
217 u8 op_cmd, int op_len)
218{
219 int err;
220 u32 val;
221
222 err = regmap_write(priv->regmap_ctrl, REG_SPI_CTRL_OPFIFO_WDATA,
223 FIELD_PREP(SPI_CTRL_OPFIFO_LEN, op_len) |
224 FIELD_PREP(SPI_CTRL_OPFIFO_OP, op_cmd));
225 if (err)
226 return err;
227
228 err = regmap_read_poll_timeout(priv->regmap_ctrl,
229 REG_SPI_CTRL_OPFIFO_FULL,
230 val, !(val & SPI_CTRL_OPFIFO_FULL),
231 0, 250 * USEC_PER_MSEC);
232 if (err)
233 return err;
234
235 err = regmap_write(priv->regmap_ctrl, REG_SPI_CTRL_OPFIFO_WR,
236 SPI_CTRL_OPFIFO_WR);
237 if (err)
238 return err;
239
240 return regmap_read_poll_timeout(priv->regmap_ctrl,
241 REG_SPI_CTRL_OPFIFO_EMPTY,
242 val, (val & SPI_CTRL_OPFIFO_EMPTY),
243 0, 250 * USEC_PER_MSEC);
244}
245
246static int airoha_snand_set_cs(struct airoha_snand_priv *priv, u8 cs)
247{
248 return airoha_snand_set_fifo_op(priv, cs, sizeof(cs));
249}
250
251static int airoha_snand_write_data_to_fifo(struct airoha_snand_priv *priv,
252 const u8 *data, int len)
253{
254 int i;
255
256 for (i = 0; i < len; i++) {
257 int err;
258 u32 val;
259
260 /* 1. Wait until dfifo is not full */
261 err = regmap_read_poll_timeout(priv->regmap_ctrl,
262 REG_SPI_CTRL_DFIFO_FULL, val,
263 !(val & SPI_CTRL_DFIFO_FULL),
264 0, 250 * USEC_PER_MSEC);
265 if (err)
266 return err;
267
268 /* 2. Write data to register DFIFO_WDATA */
269 err = regmap_write(priv->regmap_ctrl,
270 REG_SPI_CTRL_DFIFO_WDATA,
271 FIELD_PREP(SPI_CTRL_DFIFO_WDATA, data[i]));
272 if (err)
273 return err;
274
275 /* 3. Wait until dfifo is not full */
276 err = regmap_read_poll_timeout(priv->regmap_ctrl,
277 REG_SPI_CTRL_DFIFO_FULL, val,
278 !(val & SPI_CTRL_DFIFO_FULL),
279 0, 250 * USEC_PER_MSEC);
280 if (err)
281 return err;
282 }
283
284 return 0;
285}
286
287static int airoha_snand_read_data_from_fifo(struct airoha_snand_priv *priv,
288 u8 *ptr, int len)
289{
290 int i;
291
292 for (i = 0; i < len; i++) {
293 int err;
294 u32 val;
295
296 /* 1. wait until dfifo is not empty */
297 err = regmap_read_poll_timeout(priv->regmap_ctrl,
298 REG_SPI_CTRL_DFIFO_EMPTY, val,
299 !(val & SPI_CTRL_DFIFO_EMPTY),
300 0, 250 * USEC_PER_MSEC);
301 if (err)
302 return err;
303
304 /* 2. read from dfifo to register DFIFO_RDATA */
305 err = regmap_read(priv->regmap_ctrl,
306 REG_SPI_CTRL_DFIFO_RDATA, &val);
307 if (err)
308 return err;
309
310 ptr[i] = FIELD_GET(SPI_CTRL_DFIFO_RDATA, val);
311 /* 3. enable register DFIFO_RD to read next byte */
312 err = regmap_write(priv->regmap_ctrl,
313 REG_SPI_CTRL_DFIFO_RD, SPI_CTRL_DFIFO_RD);
314 if (err)
315 return err;
316 }
317
318 return 0;
319}
320
321static int airoha_snand_set_mode(struct airoha_snand_priv *priv,
322 enum airoha_snand_mode mode)
323{
324 int err;
325
326 switch (mode) {
327 case SPI_MODE_MANUAL: {
328 u32 val;
329
330 err = regmap_write(priv->regmap_ctrl,
331 REG_SPI_CTRL_NFI2SPI_EN, 0);
332 if (err)
333 return err;
334
335 err = regmap_write(priv->regmap_ctrl,
336 REG_SPI_CTRL_READ_IDLE_EN, 0);
337 if (err)
338 return err;
339
340 err = regmap_read_poll_timeout(priv->regmap_ctrl,
341 REG_SPI_CTRL_RDCTL_FSM, val,
342 !(val & SPI_CTRL_RDCTL_FSM),
343 0, 250 * USEC_PER_MSEC);
344 if (err)
345 return err;
346
347 err = regmap_write(priv->regmap_ctrl,
348 REG_SPI_CTRL_MTX_MODE_TOG, 9);
349 if (err)
350 return err;
351
352 err = regmap_write(priv->regmap_ctrl,
353 REG_SPI_CTRL_MANUAL_EN, SPI_CTRL_MANUAL_EN);
354 if (err)
355 return err;
356 break;
357 }
358 case SPI_MODE_DMA:
359 err = regmap_write(priv->regmap_ctrl,
360 REG_SPI_CTRL_NFI2SPI_EN,
361 SPI_CTRL_MANUAL_EN);
362 if (err < 0)
363 return err;
364
365 err = regmap_write(priv->regmap_ctrl,
366 REG_SPI_CTRL_MTX_MODE_TOG, 0x0);
367 if (err < 0)
368 return err;
369
370 err = regmap_write(priv->regmap_ctrl,
371 REG_SPI_CTRL_MANUAL_EN, 0x0);
372 if (err < 0)
373 return err;
374 break;
375 case SPI_MODE_AUTO:
376 default:
377 break;
378 }
379
380 return regmap_write(priv->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
381}
382
383static int airoha_snand_write_data(struct airoha_snand_priv *priv, u8 cmd,
384 const u8 *data, int len)
385{
386 int i, data_len;
387
388 for (i = 0; i < len; i += data_len) {
389 int err;
390
391 data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
392 err = airoha_snand_set_fifo_op(priv, cmd, data_len);
393 if (err)
394 return err;
395
396 err = airoha_snand_write_data_to_fifo(priv, &data[i],
397 data_len);
398 if (err < 0)
399 return err;
400 }
401
402 return 0;
403}
404
405static int airoha_snand_read_data(struct airoha_snand_priv *priv, u8 *data,
406 int len)
407{
408 int i, data_len;
409
410 for (i = 0; i < len; i += data_len) {
411 int err;
412
413 data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
414 err = airoha_snand_set_fifo_op(priv, 0xc, data_len);
415 if (err)
416 return err;
417
418 err = airoha_snand_read_data_from_fifo(priv, &data[i],
419 data_len);
420 if (err < 0)
421 return err;
422 }
423
424 return 0;
425}
426
427static int airoha_snand_nfi_init(struct airoha_snand_priv *priv)
428{
429 int err;
430
431 /* switch to SNFI mode */
432 err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_SNF_NFI_CNFG,
433 SPI_NFI_SPI_MODE);
434 if (err)
435 return err;
436
437 /* Enable DMA */
438 return regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_INTR_EN,
439 SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);
440}
441
442static int airoha_snand_nfi_config(struct airoha_snand_priv *priv)
443{
444 int err;
445 u32 val;
446
447 err = regmap_write(priv->regmap_nfi, REG_SPI_NFI_CON,
448 SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);
449 if (err)
450 return err;
451
452 /* auto FDM */
453 err = regmap_clear_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
454 SPI_NFI_AUTO_FDM_EN);
455 if (err)
456 return err;
457
458 /* HW ECC */
459 err = regmap_clear_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
460 SPI_NFI_HW_ECC_EN);
461 if (err)
462 return err;
463
464 /* DMA Burst */
465 err = regmap_set_bits(priv->regmap_nfi, REG_SPI_NFI_CNFG,
466 SPI_NFI_DMA_BURST_EN);
467 if (err)
468 return err;
469
470 /* page format */
471 switch (priv->nfi_cfg.spare_size) {
472 case 26:
473 val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1);
474 break;
475 case 27:
476 val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2);
477 break;
478 case 28:
479 val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3);
480 break;
481 default:
482 val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0);
483 break;
484 }
485
486 err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_PAGEFMT,
487 SPI_NFI_SPARE_SIZE, val);
488 if (err)
489 return err;
490
491 switch (priv->nfi_cfg.page_size) {
492 case 2048:
493 val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1);
494 break;
495 case 4096:
496 val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2);
497 break;
498 default:
499 val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0);
500 break;
501 }
502
503 err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_PAGEFMT,
504 SPI_NFI_PAGE_SIZE, val);
505 if (err)
506 return err;
507
508 /* sec num */
509 val = FIELD_PREP(SPI_NFI_SEC_NUM, priv->nfi_cfg.sec_num);
510 err = regmap_update_bits(priv->regmap_nfi, REG_SPI_NFI_CON,
511 SPI_NFI_SEC_NUM, val);
512 if (err)
513 return err;
514
515 /* enable cust sec size */
516 err = regmap_set_bits(priv->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,
517 SPI_NFI_CUS_SEC_SIZE_EN);
518 if (err)
519 return err;
520
521 /* set cust sec size */
522 val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, priv->nfi_cfg.sec_size);
523 return regmap_update_bits(priv->regmap_nfi,
524 REG_SPI_NFI_SECCUS_SIZE,
525 SPI_NFI_CUS_SEC_SIZE, val);
526}
527
528static int airoha_snand_adjust_op_size(struct spi_slave *slave,
529 struct spi_mem_op *op)
530{
531 size_t max_len;
532
533 max_len = 1 + op->addr.nbytes + op->dummy.nbytes;
534 if (max_len >= 160)
535 return -EOPNOTSUPP;
536
537 if (op->data.nbytes > 160 - max_len)
538 op->data.nbytes = 160 - max_len;
539
540 return 0;
541}
542
543static bool airoha_snand_supports_op(struct spi_slave *slave,
544 const struct spi_mem_op *op)
545{
546 if (!spi_mem_default_supports_op(slave, op))
547 return false;
548
549 if (op->cmd.buswidth != 1)
550 return false;
551
552 return (!op->addr.nbytes || op->addr.buswidth == 1) &&
553 (!op->dummy.nbytes || op->dummy.buswidth == 1) &&
554 (!op->data.nbytes || op->data.buswidth == 1);
555}
556
557static int airoha_snand_exec_op(struct spi_slave *slave,
558 const struct spi_mem_op *op)
559{
560 u8 data[8], cmd, opcode = op->cmd.opcode;
561 struct udevice *bus = slave->dev->parent;
562 struct airoha_snand_priv *priv;
563 int i, err;
564
565 priv = dev_get_priv(bus);
566
567 /* switch to manual mode */
568 err = airoha_snand_set_mode(priv, SPI_MODE_MANUAL);
569 if (err < 0)
570 return err;
571
572 err = airoha_snand_set_cs(priv, SPI_CHIP_SEL_LOW);
573 if (err < 0)
574 return err;
575
576 /* opcode */
577 err = airoha_snand_write_data(priv, 0x8, &opcode, sizeof(opcode));
578 if (err)
579 return err;
580
581 /* addr part */
582 cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
583 put_unaligned_be64(op->addr.val, data);
584
585 for (i = ARRAY_SIZE(data) - op->addr.nbytes;
586 i < ARRAY_SIZE(data); i++) {
587 err = airoha_snand_write_data(priv, cmd, &data[i],
588 sizeof(data[0]));
589 if (err)
590 return err;
591 }
592
593 /* dummy */
594 data[0] = 0xff;
595 for (i = 0; i < op->dummy.nbytes; i++) {
596 err = airoha_snand_write_data(priv, 0x8, &data[0],
597 sizeof(data[0]));
598 if (err)
599 return err;
600 }
601
602 /* data */
603 if (op->data.dir == SPI_MEM_DATA_IN) {
604 err = airoha_snand_read_data(priv, op->data.buf.in,
605 op->data.nbytes);
606 if (err)
607 return err;
608 } else {
609 err = airoha_snand_write_data(priv, 0x8, op->data.buf.out,
610 op->data.nbytes);
611 if (err)
612 return err;
613 }
614
615 return airoha_snand_set_cs(priv, SPI_CHIP_SEL_HIGH);
616}
617
618static int airoha_snand_probe(struct udevice *dev)
619{
620 struct airoha_snand_priv *priv = dev_get_priv(dev);
621 int ret;
622
623 ret = regmap_init_mem_index(dev_ofnode(dev), &priv->regmap_ctrl, 0);
624 if (ret) {
625 dev_err(dev, "failed to init spi ctrl regmap\n");
626 return ret;
627 }
628
629 ret = regmap_init_mem_index(dev_ofnode(dev), &priv->regmap_nfi, 1);
630 if (ret) {
631 dev_err(dev, "failed to init spi nfi regmap\n");
632 return ret;
633 }
634
635 priv->spi_clk = devm_clk_get(dev, "spi");
636 if (IS_ERR(priv->spi_clk)) {
637 dev_err(dev, "unable to get spi clk\n");
638 return PTR_ERR(priv->regmap_ctrl);
639 }
640 clk_enable(priv->spi_clk);
641
642 return airoha_snand_nfi_init(priv);
643}
644
645static int airoha_snand_nfi_set_speed(struct udevice *bus, uint speed)
646{
647 struct airoha_snand_priv *priv = dev_get_priv(bus);
648 int ret;
649
650 ret = clk_set_rate(priv->spi_clk, speed);
651 if (ret < 0)
652 return ret;
653
654 return 0;
655}
656
657static int airoha_snand_nfi_set_mode(struct udevice *bus, uint mode)
658{
659 return 0;
660}
661
662static int airoha_snand_nfi_setup(struct spi_slave *slave,
663 const struct spinand_info *spinand_info)
664{
665 struct udevice *bus = slave->dev->parent;
666 struct airoha_snand_priv *priv;
667 u32 sec_size, sec_num;
668 int pagesize, oobsize;
669
670 priv = dev_get_priv(bus);
671
672 pagesize = spinand_info->memorg.pagesize;
673 oobsize = spinand_info->memorg.oobsize;
674
675 if (pagesize == 2 * 1024)
676 sec_num = 4;
677 else if (pagesize == 4 * 1024)
678 sec_num = 8;
679 else
680 sec_num = 1;
681
682 sec_size = (pagesize + oobsize) / sec_num;
683
684 /* init default value */
685 priv->nfi_cfg.sec_size = sec_size;
686 priv->nfi_cfg.sec_num = sec_num;
687 priv->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);
688 priv->nfi_cfg.spare_size = 16;
689
690 return airoha_snand_nfi_config(priv);
691}
692
693static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
694 .adjust_op_size = airoha_snand_adjust_op_size,
695 .supports_op = airoha_snand_supports_op,
696 .exec_op = airoha_snand_exec_op,
697};
698
699static const struct dm_spi_ops airoha_snfi_spi_ops = {
700 .mem_ops = &airoha_snand_mem_ops,
701 .set_speed = airoha_snand_nfi_set_speed,
702 .set_mode = airoha_snand_nfi_set_mode,
703 .setup_for_spinand = airoha_snand_nfi_setup,
704};
705
706static const struct udevice_id airoha_snand_ids[] = {
707 { .compatible = "airoha,en7581-snand" },
708 { }
709};
710
711U_BOOT_DRIVER(airoha_snfi_spi) = {
712 .name = "airoha-snfi-spi",
713 .id = UCLASS_SPI,
714 .of_match = airoha_snand_ids,
715 .ops = &airoha_snfi_spi_ops,
716 .priv_auto = sizeof(struct airoha_snand_priv),
717 .probe = airoha_snand_probe,
718};