Skip to content

Commit edd2e26

Browse files
mkshevetskiybroonie
authored andcommitted
spi: airoha: add support of dual/quad wires spi modes to exec_op() handler
Booting without this patch and disabled dirmap support results in [ 2.980719] spi-nand spi0.0: Micron SPI NAND was found. [ 2.986040] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128 [ 2.994709] 2 fixed-partitions partitions found on MTD device spi0.0 [ 3.001075] Creating 2 MTD partitions on "spi0.0": [ 3.005862] 0x000000000000-0x000000020000 : "bl2" [ 3.011272] 0x000000020000-0x000010000000 : "ubi" ... [ 6.195594] ubi0: attaching mtd1 [ 13.338398] ubi0: scanning is finished [ 13.342188] ubi0 error: ubi_read_volume_table: the layout volume was not found [ 13.349784] ubi0 error: ubi_attach_mtd_dev: failed to attach mtd1, error -22 [ 13.356897] UBI error: cannot attach mtd1 If dirmap is disabled or not supported in the spi driver, the dirmap requests will be executed via exec_op() handler. Thus, if the hardware supports dual/quad spi modes, then corresponding requests will be sent to exec_op() handler. Current driver does not support such requests, so error is arrised. As result the flash can't be read/write. This patch adds support of dual and quad wires spi modes to exec_op() handler. Fixes: a403997 ("spi: airoha: add SPI-NAND Flash controller driver") Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Link: https://patch.msgid.link/20251012121707.2296160-4-mikhail.kshevetskiy@iopsys.eu Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 4314ffc commit edd2e26

1 file changed

Lines changed: 82 additions & 26 deletions

File tree

drivers/spi/spi-airoha-snfi.c

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@
192192
#define SPI_NAND_OP_RESET 0xff
193193
#define SPI_NAND_OP_DIE_SELECT 0xc2
194194

195+
/* SNAND FIFO commands */
196+
#define SNAND_FIFO_TX_BUSWIDTH_SINGLE 0x08
197+
#define SNAND_FIFO_TX_BUSWIDTH_DUAL 0x09
198+
#define SNAND_FIFO_TX_BUSWIDTH_QUAD 0x0a
199+
#define SNAND_FIFO_RX_BUSWIDTH_SINGLE 0x0c
200+
#define SNAND_FIFO_RX_BUSWIDTH_DUAL 0x0e
201+
#define SNAND_FIFO_RX_BUSWIDTH_QUAD 0x0f
202+
195203
#define SPI_NAND_CACHE_SIZE (SZ_4K + SZ_256)
196204
#define SPI_MAX_TRANSFER_SIZE 511
197205

@@ -387,10 +395,26 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,
387395
return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
388396
}
389397

390-
static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
391-
const u8 *data, int len)
398+
static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
399+
const u8 *data, int len, int buswidth)
392400
{
393401
int i, data_len;
402+
u8 cmd;
403+
404+
switch (buswidth) {
405+
case 0:
406+
case 1:
407+
cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
408+
break;
409+
case 2:
410+
cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
411+
break;
412+
case 4:
413+
cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
414+
break;
415+
default:
416+
return -EINVAL;
417+
}
394418

395419
for (i = 0; i < len; i += data_len) {
396420
int err;
@@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
409433
return 0;
410434
}
411435

412-
static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
413-
int len)
436+
static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
437+
u8 *data, int len, int buswidth)
414438
{
415439
int i, data_len;
440+
u8 cmd;
441+
442+
switch (buswidth) {
443+
case 0:
444+
case 1:
445+
cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
446+
break;
447+
case 2:
448+
cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
449+
break;
450+
case 4:
451+
cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
452+
break;
453+
default:
454+
return -EINVAL;
455+
}
416456

417457
for (i = 0; i < len; i += data_len) {
418458
int err;
419459

420460
data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
421-
err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
461+
err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
422462
if (err)
423463
return err;
424464

@@ -902,12 +942,28 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
902942
static int airoha_snand_exec_op(struct spi_mem *mem,
903943
const struct spi_mem_op *op)
904944
{
905-
u8 data[8], cmd, opcode = op->cmd.opcode;
906945
struct airoha_snand_ctrl *as_ctrl;
946+
int op_len, addr_len, dummy_len;
947+
u8 buf[20], *data;
907948
int i, err;
908949

909950
as_ctrl = spi_controller_get_devdata(mem->spi->controller);
910951

952+
op_len = op->cmd.nbytes;
953+
addr_len = op->addr.nbytes;
954+
dummy_len = op->dummy.nbytes;
955+
956+
if (op_len + dummy_len + addr_len > sizeof(buf))
957+
return -EIO;
958+
959+
data = buf;
960+
for (i = 0; i < op_len; i++)
961+
*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
962+
for (i = 0; i < addr_len; i++)
963+
*data++ = op->addr.val >> (8 * (addr_len - i - 1));
964+
for (i = 0; i < dummy_len; i++)
965+
*data++ = 0xff;
966+
911967
/* switch to manual mode */
912968
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
913969
if (err < 0)
@@ -918,40 +974,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
918974
return err;
919975

920976
/* opcode */
921-
err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
977+
data = buf;
978+
err = airoha_snand_write_data(as_ctrl, data, op_len,
979+
op->cmd.buswidth);
922980
if (err)
923981
return err;
924982

925983
/* addr part */
926-
cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
927-
put_unaligned_be64(op->addr.val, data);
928-
929-
for (i = ARRAY_SIZE(data) - op->addr.nbytes;
930-
i < ARRAY_SIZE(data); i++) {
931-
err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
932-
sizeof(data[0]));
984+
data += op_len;
985+
if (addr_len) {
986+
err = airoha_snand_write_data(as_ctrl, data, addr_len,
987+
op->addr.buswidth);
933988
if (err)
934989
return err;
935990
}
936991

937992
/* dummy */
938-
data[0] = 0xff;
939-
for (i = 0; i < op->dummy.nbytes; i++) {
940-
err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
941-
sizeof(data[0]));
993+
data += addr_len;
994+
if (dummy_len) {
995+
err = airoha_snand_write_data(as_ctrl, data, dummy_len,
996+
op->dummy.buswidth);
942997
if (err)
943998
return err;
944999
}
9451000

9461001
/* data */
947-
if (op->data.dir == SPI_MEM_DATA_IN) {
948-
err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
949-
op->data.nbytes);
950-
if (err)
951-
return err;
952-
} else {
953-
err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
954-
op->data.nbytes);
1002+
if (op->data.nbytes) {
1003+
if (op->data.dir == SPI_MEM_DATA_IN)
1004+
err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
1005+
op->data.nbytes,
1006+
op->data.buswidth);
1007+
else
1008+
err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
1009+
op->data.nbytes,
1010+
op->data.buswidth);
9551011
if (err)
9561012
return err;
9571013
}

0 commit comments

Comments
 (0)