brintos

brintos / linux-shallow public Read only

0
0
Text · 27.7 KiB · 1369691 Raw
1119 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2024 AIROHA Inc4 * Author: Lorenzo Bianconi <lorenzo@kernel.org>5 * Author: Ray Liu <ray.liu@airoha.com>6 */7 8#include <linux/bitfield.h>9#include <linux/clk.h>10#include <linux/delay.h>11#include <linux/device.h>12#include <linux/dma-mapping.h>13#include <linux/errno.h>14#include <linux/limits.h>15#include <linux/math.h>16#include <linux/minmax.h>17#include <linux/module.h>18#include <linux/mutex.h>19#include <linux/platform_device.h>20#include <linux/property.h>21#include <linux/regmap.h>22#include <linux/sizes.h>23#include <linux/spi/spi.h>24#include <linux/spi/spi-mem.h>25#include <linux/types.h>26#include <linux/unaligned.h>27 28/* SPI */29#define REG_SPI_CTRL_BASE			0x1FA1000030 31#define REG_SPI_CTRL_READ_MODE			0x000032#define REG_SPI_CTRL_READ_IDLE_EN		0x000433#define REG_SPI_CTRL_SIDLY			0x000834#define REG_SPI_CTRL_CSHEXT			0x000c35#define REG_SPI_CTRL_CSLEXT			0x001036 37#define REG_SPI_CTRL_MTX_MODE_TOG		0x001438#define SPI_CTRL_MTX_MODE_TOG			GENMASK(3, 0)39 40#define REG_SPI_CTRL_RDCTL_FSM			0x001841#define SPI_CTRL_RDCTL_FSM			GENMASK(3, 0)42 43#define REG_SPI_CTRL_MACMUX_SEL			0x001c44 45#define REG_SPI_CTRL_MANUAL_EN			0x002046#define SPI_CTRL_MANUAL_EN			BIT(0)47 48#define REG_SPI_CTRL_OPFIFO_EMPTY		0x002449#define SPI_CTRL_OPFIFO_EMPTY			BIT(0)50 51#define REG_SPI_CTRL_OPFIFO_WDATA		0x002852#define SPI_CTRL_OPFIFO_LEN			GENMASK(8, 0)53#define SPI_CTRL_OPFIFO_OP			GENMASK(13, 9)54 55#define REG_SPI_CTRL_OPFIFO_FULL		0x002c56#define SPI_CTRL_OPFIFO_FULL			BIT(0)57 58#define REG_SPI_CTRL_OPFIFO_WR			0x003059#define SPI_CTRL_OPFIFO_WR			BIT(0)60 61#define REG_SPI_CTRL_DFIFO_FULL			0x003462#define SPI_CTRL_DFIFO_FULL			BIT(0)63 64#define REG_SPI_CTRL_DFIFO_WDATA		0x003865#define SPI_CTRL_DFIFO_WDATA			GENMASK(7, 0)66 67#define REG_SPI_CTRL_DFIFO_EMPTY		0x003c68#define SPI_CTRL_DFIFO_EMPTY			BIT(0)69 70#define REG_SPI_CTRL_DFIFO_RD			0x004071#define SPI_CTRL_DFIFO_RD			BIT(0)72 73#define REG_SPI_CTRL_DFIFO_RDATA		0x004474#define SPI_CTRL_DFIFO_RDATA			GENMASK(7, 0)75 76#define REG_SPI_CTRL_DUMMY			0x008077#define SPI_CTRL_CTRL_DUMMY			GENMASK(3, 0)78 79#define REG_SPI_CTRL_PROBE_SEL			0x008880#define REG_SPI_CTRL_INTERRUPT			0x009081#define REG_SPI_CTRL_INTERRUPT_EN		0x009482#define REG_SPI_CTRL_SI_CK_SEL			0x009c83#define REG_SPI_CTRL_SW_CFGNANDADDR_VAL		0x010c84#define REG_SPI_CTRL_SW_CFGNANDADDR_EN		0x011085#define REG_SPI_CTRL_SFC_STRAP			0x011486 87#define REG_SPI_CTRL_NFI2SPI_EN			0x013088#define SPI_CTRL_NFI2SPI_EN			BIT(0)89 90/* NFI2SPI */91#define REG_SPI_NFI_CNFG			0x000092#define SPI_NFI_DMA_MODE			BIT(0)93#define SPI_NFI_READ_MODE			BIT(1)94#define SPI_NFI_DMA_BURST_EN			BIT(2)95#define SPI_NFI_HW_ECC_EN			BIT(8)96#define SPI_NFI_AUTO_FDM_EN			BIT(9)97#define SPI_NFI_OPMODE				GENMASK(14, 12)98 99#define REG_SPI_NFI_PAGEFMT			0x0004100#define SPI_NFI_PAGE_SIZE			GENMASK(1, 0)101#define SPI_NFI_SPARE_SIZE			GENMASK(5, 4)102 103#define REG_SPI_NFI_CON				0x0008104#define SPI_NFI_FIFO_FLUSH			BIT(0)105#define SPI_NFI_RST				BIT(1)106#define SPI_NFI_RD_TRIG				BIT(8)107#define SPI_NFI_WR_TRIG				BIT(9)108#define SPI_NFI_SEC_NUM				GENMASK(15, 12)109 110#define REG_SPI_NFI_INTR_EN			0x0010111#define SPI_NFI_RD_DONE_EN			BIT(0)112#define SPI_NFI_WR_DONE_EN			BIT(1)113#define SPI_NFI_RST_DONE_EN			BIT(2)114#define SPI_NFI_ERASE_DONE_EN			BIT(3)115#define SPI_NFI_BUSY_RETURN_EN			BIT(4)116#define SPI_NFI_ACCESS_LOCK_EN			BIT(5)117#define SPI_NFI_AHB_DONE_EN			BIT(6)118#define SPI_NFI_ALL_IRQ_EN					\119	(SPI_NFI_RD_DONE_EN | SPI_NFI_WR_DONE_EN |		\120	 SPI_NFI_RST_DONE_EN | SPI_NFI_ERASE_DONE_EN |		\121	 SPI_NFI_BUSY_RETURN_EN | SPI_NFI_ACCESS_LOCK_EN |	\122	 SPI_NFI_AHB_DONE_EN)123 124#define REG_SPI_NFI_INTR			0x0014125#define SPI_NFI_AHB_DONE			BIT(6)126 127#define REG_SPI_NFI_CMD				0x0020128 129#define REG_SPI_NFI_ADDR_NOB			0x0030130#define SPI_NFI_ROW_ADDR_NOB			GENMASK(6, 4)131 132#define REG_SPI_NFI_STA				0x0060133#define REG_SPI_NFI_FIFOSTA			0x0064134#define REG_SPI_NFI_STRADDR			0x0080135#define REG_SPI_NFI_FDM0L			0x00a0136#define REG_SPI_NFI_FDM0M			0x00a4137#define REG_SPI_NFI_FDM7L			0x00d8138#define REG_SPI_NFI_FDM7M			0x00dc139#define REG_SPI_NFI_FIFODATA0			0x0190140#define REG_SPI_NFI_FIFODATA1			0x0194141#define REG_SPI_NFI_FIFODATA2			0x0198142#define REG_SPI_NFI_FIFODATA3			0x019c143#define REG_SPI_NFI_MASTERSTA			0x0224144 145#define REG_SPI_NFI_SECCUS_SIZE			0x022c146#define SPI_NFI_CUS_SEC_SIZE			GENMASK(12, 0)147#define SPI_NFI_CUS_SEC_SIZE_EN			BIT(16)148 149#define REG_SPI_NFI_RD_CTL2			0x0510150#define REG_SPI_NFI_RD_CTL3			0x0514151 152#define REG_SPI_NFI_PG_CTL1			0x0524153#define SPI_NFI_PG_LOAD_CMD			GENMASK(15, 8)154 155#define REG_SPI_NFI_PG_CTL2			0x0528156#define REG_SPI_NFI_NOR_PROG_ADDR		0x052c157#define REG_SPI_NFI_NOR_RD_ADDR			0x0534158 159#define REG_SPI_NFI_SNF_MISC_CTL		0x0538160#define SPI_NFI_DATA_READ_WR_MODE		GENMASK(18, 16)161 162#define REG_SPI_NFI_SNF_MISC_CTL2		0x053c163#define SPI_NFI_READ_DATA_BYTE_NUM		GENMASK(12, 0)164#define SPI_NFI_PROG_LOAD_BYTE_NUM		GENMASK(28, 16)165 166#define REG_SPI_NFI_SNF_STA_CTL1		0x0550167#define SPI_NFI_READ_FROM_CACHE_DONE		BIT(25)168#define SPI_NFI_LOAD_TO_CACHE_DONE		BIT(26)169 170#define REG_SPI_NFI_SNF_STA_CTL2		0x0554171 172#define REG_SPI_NFI_SNF_NFI_CNFG		0x055c173#define SPI_NFI_SPI_MODE			BIT(0)174 175/* SPI NAND Protocol OP */176#define SPI_NAND_OP_GET_FEATURE			0x0f177#define SPI_NAND_OP_SET_FEATURE			0x1f178#define SPI_NAND_OP_PAGE_READ			0x13179#define SPI_NAND_OP_READ_FROM_CACHE_SINGLE	0x03180#define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST	0x0b181#define SPI_NAND_OP_READ_FROM_CACHE_DUAL	0x3b182#define SPI_NAND_OP_READ_FROM_CACHE_QUAD	0x6b183#define SPI_NAND_OP_WRITE_ENABLE		0x06184#define SPI_NAND_OP_WRITE_DISABLE		0x04185#define SPI_NAND_OP_PROGRAM_LOAD_SINGLE		0x02186#define SPI_NAND_OP_PROGRAM_LOAD_QUAD		0x32187#define SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE	0x84188#define SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD	0x34189#define SPI_NAND_OP_PROGRAM_EXECUTE		0x10190#define SPI_NAND_OP_READ_ID			0x9f191#define SPI_NAND_OP_BLOCK_ERASE			0xd8192#define SPI_NAND_OP_RESET			0xff193#define SPI_NAND_OP_DIE_SELECT			0xc2194 195#define SPI_NAND_CACHE_SIZE			(SZ_4K + SZ_256)196#define SPI_MAX_TRANSFER_SIZE			511197 198enum airoha_snand_mode {199	SPI_MODE_AUTO,200	SPI_MODE_MANUAL,201	SPI_MODE_DMA,202};203 204enum airoha_snand_cs {205	SPI_CHIP_SEL_HIGH,206	SPI_CHIP_SEL_LOW,207};208 209struct airoha_snand_dev {210	size_t buf_len;211 212	u8 *txrx_buf;213	dma_addr_t dma_addr;214};215 216struct airoha_snand_ctrl {217	struct device *dev;218	struct regmap *regmap_ctrl;219	struct regmap *regmap_nfi;220	struct clk *spi_clk;221 222	struct {223		size_t page_size;224		size_t sec_size;225		u8 sec_num;226		u8 spare_size;227	} nfi_cfg;228};229 230static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl,231				    u8 op_cmd, int op_len)232{233	int err;234	u32 val;235 236	err = regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_OPFIFO_WDATA,237			   FIELD_PREP(SPI_CTRL_OPFIFO_LEN, op_len) |238			   FIELD_PREP(SPI_CTRL_OPFIFO_OP, op_cmd));239	if (err)240		return err;241 242	err = regmap_read_poll_timeout(as_ctrl->regmap_ctrl,243				       REG_SPI_CTRL_OPFIFO_FULL,244				       val, !(val & SPI_CTRL_OPFIFO_FULL),245				       0, 250 * USEC_PER_MSEC);246	if (err)247		return err;248 249	err = regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_OPFIFO_WR,250			   SPI_CTRL_OPFIFO_WR);251	if (err)252		return err;253 254	return regmap_read_poll_timeout(as_ctrl->regmap_ctrl,255					REG_SPI_CTRL_OPFIFO_EMPTY,256					val, (val & SPI_CTRL_OPFIFO_EMPTY),257					0, 250 * USEC_PER_MSEC);258}259 260static int airoha_snand_set_cs(struct airoha_snand_ctrl *as_ctrl, u8 cs)261{262	return airoha_snand_set_fifo_op(as_ctrl, cs, sizeof(cs));263}264 265static int airoha_snand_write_data_to_fifo(struct airoha_snand_ctrl *as_ctrl,266					   const u8 *data, int len)267{268	int i;269 270	for (i = 0; i < len; i++) {271		int err;272		u32 val;273 274		/* 1. Wait until dfifo is not full */275		err = regmap_read_poll_timeout(as_ctrl->regmap_ctrl,276					       REG_SPI_CTRL_DFIFO_FULL, val,277					       !(val & SPI_CTRL_DFIFO_FULL),278					       0, 250 * USEC_PER_MSEC);279		if (err)280			return err;281 282		/* 2. Write data to register DFIFO_WDATA */283		err = regmap_write(as_ctrl->regmap_ctrl,284				   REG_SPI_CTRL_DFIFO_WDATA,285				   FIELD_PREP(SPI_CTRL_DFIFO_WDATA, data[i]));286		if (err)287			return err;288 289		/* 3. Wait until dfifo is not full */290		err = regmap_read_poll_timeout(as_ctrl->regmap_ctrl,291					       REG_SPI_CTRL_DFIFO_FULL, val,292					       !(val & SPI_CTRL_DFIFO_FULL),293					       0, 250 * USEC_PER_MSEC);294		if (err)295			return err;296	}297 298	return 0;299}300 301static int airoha_snand_read_data_from_fifo(struct airoha_snand_ctrl *as_ctrl,302					    u8 *ptr, int len)303{304	int i;305 306	for (i = 0; i < len; i++) {307		int err;308		u32 val;309 310		/* 1. wait until dfifo is not empty */311		err = regmap_read_poll_timeout(as_ctrl->regmap_ctrl,312					       REG_SPI_CTRL_DFIFO_EMPTY, val,313					       !(val & SPI_CTRL_DFIFO_EMPTY),314					       0, 250 * USEC_PER_MSEC);315		if (err)316			return err;317 318		/* 2. read from dfifo to register DFIFO_RDATA */319		err = regmap_read(as_ctrl->regmap_ctrl,320				  REG_SPI_CTRL_DFIFO_RDATA, &val);321		if (err)322			return err;323 324		ptr[i] = FIELD_GET(SPI_CTRL_DFIFO_RDATA, val);325		/* 3. enable register DFIFO_RD to read next byte */326		err = regmap_write(as_ctrl->regmap_ctrl,327				   REG_SPI_CTRL_DFIFO_RD, SPI_CTRL_DFIFO_RD);328		if (err)329			return err;330	}331 332	return 0;333}334 335static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,336				 enum airoha_snand_mode mode)337{338	int err;339 340	switch (mode) {341	case SPI_MODE_MANUAL: {342		u32 val;343 344		err = regmap_write(as_ctrl->regmap_ctrl,345				   REG_SPI_CTRL_NFI2SPI_EN, 0);346		if (err)347			return err;348 349		err = regmap_write(as_ctrl->regmap_ctrl,350				   REG_SPI_CTRL_READ_IDLE_EN, 0);351		if (err)352			return err;353 354		err = regmap_read_poll_timeout(as_ctrl->regmap_ctrl,355					       REG_SPI_CTRL_RDCTL_FSM, val,356					       !(val & SPI_CTRL_RDCTL_FSM),357					       0, 250 * USEC_PER_MSEC);358		if (err)359			return err;360 361		err = regmap_write(as_ctrl->regmap_ctrl,362				   REG_SPI_CTRL_MTX_MODE_TOG, 9);363		if (err)364			return err;365 366		err = regmap_write(as_ctrl->regmap_ctrl,367				   REG_SPI_CTRL_MANUAL_EN, SPI_CTRL_MANUAL_EN);368		if (err)369			return err;370		break;371	}372	case SPI_MODE_DMA:373		err = regmap_write(as_ctrl->regmap_ctrl,374				   REG_SPI_CTRL_NFI2SPI_EN,375				   SPI_CTRL_MANUAL_EN);376		if (err < 0)377			return err;378 379		err = regmap_write(as_ctrl->regmap_ctrl,380				   REG_SPI_CTRL_MTX_MODE_TOG, 0x0);381		if (err < 0)382			return err;383 384		err = regmap_write(as_ctrl->regmap_ctrl,385				   REG_SPI_CTRL_MANUAL_EN, 0x0);386		if (err < 0)387			return err;388		break;389	case SPI_MODE_AUTO:390	default:391		break;392	}393 394	return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);395}396 397static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,398				   const u8 *data, int len)399{400	int i, data_len;401 402	for (i = 0; i < len; i += data_len) {403		int err;404 405		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);406		err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);407		if (err)408			return err;409 410		err = airoha_snand_write_data_to_fifo(as_ctrl, &data[i],411						      data_len);412		if (err < 0)413			return err;414	}415 416	return 0;417}418 419static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,420				  int len)421{422	int i, data_len;423 424	for (i = 0; i < len; i += data_len) {425		int err;426 427		data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);428		err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);429		if (err)430			return err;431 432		err = airoha_snand_read_data_from_fifo(as_ctrl, &data[i],433						       data_len);434		if (err < 0)435			return err;436	}437 438	return 0;439}440 441static int airoha_snand_nfi_init(struct airoha_snand_ctrl *as_ctrl)442{443	int err;444 445	/* switch to SNFI mode */446	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_NFI_CNFG,447			   SPI_NFI_SPI_MODE);448	if (err)449		return err;450 451	/* Enable DMA */452	return regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR_EN,453				  SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN);454}455 456static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl)457{458	int err;459	u32 val;460 461	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,462			   SPI_NFI_FIFO_FLUSH | SPI_NFI_RST);463	if (err)464		return err;465 466	/* auto FDM */467	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,468				SPI_NFI_AUTO_FDM_EN);469	if (err)470		return err;471 472	/* HW ECC */473	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,474				SPI_NFI_HW_ECC_EN);475	if (err)476		return err;477 478	/* DMA Burst */479	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,480			      SPI_NFI_DMA_BURST_EN);481	if (err)482		return err;483 484	/* page format */485	switch (as_ctrl->nfi_cfg.spare_size) {486	case 26:487		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1);488		break;489	case 27:490		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2);491		break;492	case 28:493		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3);494		break;495	default:496		val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0);497		break;498	}499 500	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,501				 SPI_NFI_SPARE_SIZE, val);502	if (err)503		return err;504 505	switch (as_ctrl->nfi_cfg.page_size) {506	case 2048:507		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1);508		break;509	case 4096:510		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2);511		break;512	default:513		val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0);514		break;515	}516 517	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT,518				 SPI_NFI_PAGE_SIZE, val);519	if (err)520		return err;521 522	/* sec num */523	val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num);524	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,525				 SPI_NFI_SEC_NUM, val);526	if (err)527		return err;528 529	/* enable cust sec size */530	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE,531			      SPI_NFI_CUS_SEC_SIZE_EN);532	if (err)533		return err;534 535	/* set cust sec size */536	val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size);537	return regmap_update_bits(as_ctrl->regmap_nfi,538				  REG_SPI_NFI_SECCUS_SIZE,539				  SPI_NFI_CUS_SEC_SIZE, val);540}541 542static bool airoha_snand_is_page_ops(const struct spi_mem_op *op)543{544	if (op->addr.nbytes != 2)545		return false;546 547	if (op->addr.buswidth != 1 && op->addr.buswidth != 2 &&548	    op->addr.buswidth != 4)549		return false;550 551	switch (op->data.dir) {552	case SPI_MEM_DATA_IN:553		if (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth > 0xf)554			return false;555 556		/* quad in / quad out */557		if (op->addr.buswidth == 4)558			return op->data.buswidth == 4;559 560		if (op->addr.buswidth == 2)561			return op->data.buswidth == 2;562 563		/* standard spi */564		return op->data.buswidth == 4 || op->data.buswidth == 2 ||565		       op->data.buswidth == 1;566	case SPI_MEM_DATA_OUT:567		return !op->dummy.nbytes && op->addr.buswidth == 1 &&568		       (op->data.buswidth == 4 || op->data.buswidth == 1);569	default:570		return false;571	}572}573 574static int airoha_snand_adjust_op_size(struct spi_mem *mem,575				       struct spi_mem_op *op)576{577	size_t max_len;578 579	if (airoha_snand_is_page_ops(op)) {580		struct airoha_snand_ctrl *as_ctrl;581 582		as_ctrl = spi_controller_get_devdata(mem->spi->controller);583		max_len = as_ctrl->nfi_cfg.sec_size;584		max_len += as_ctrl->nfi_cfg.spare_size;585		max_len *= as_ctrl->nfi_cfg.sec_num;586 587		if (op->data.nbytes > max_len)588			op->data.nbytes = max_len;589	} else {590		max_len = 1 + op->addr.nbytes + op->dummy.nbytes;591		if (max_len >= 160)592			return -EOPNOTSUPP;593 594		if (op->data.nbytes > 160 - max_len)595			op->data.nbytes = 160 - max_len;596	}597 598	return 0;599}600 601static bool airoha_snand_supports_op(struct spi_mem *mem,602				     const struct spi_mem_op *op)603{604	if (!spi_mem_default_supports_op(mem, op))605		return false;606 607	if (op->cmd.buswidth != 1)608		return false;609 610	if (airoha_snand_is_page_ops(op))611		return true;612 613	return (!op->addr.nbytes || op->addr.buswidth == 1) &&614	       (!op->dummy.nbytes || op->dummy.buswidth == 1) &&615	       (!op->data.nbytes || op->data.buswidth == 1);616}617 618static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)619{620	struct airoha_snand_dev *as_dev = spi_get_ctldata(desc->mem->spi);621 622	if (!as_dev->txrx_buf)623		return -EINVAL;624 625	if (desc->info.offset + desc->info.length > U32_MAX)626		return -EINVAL;627 628	if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))629		return -EOPNOTSUPP;630 631	return 0;632}633 634static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,635					u64 offs, size_t len, void *buf)636{637	struct spi_device *spi = desc->mem->spi;638	struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);639	struct spi_mem_op *op = &desc->info.op_tmpl;640	struct airoha_snand_ctrl *as_ctrl;641	u32 val, rd_mode;642	int err;643 644	switch (op->cmd.opcode) {645	case SPI_NAND_OP_READ_FROM_CACHE_DUAL:646		rd_mode = 1;647		break;648	case SPI_NAND_OP_READ_FROM_CACHE_QUAD:649		rd_mode = 2;650		break;651	default:652		rd_mode = 0;653		break;654	}655 656	as_ctrl = spi_controller_get_devdata(spi->controller);657	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);658	if (err < 0)659		return err;660 661	err = airoha_snand_nfi_config(as_ctrl);662	if (err)663		return err;664 665	dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,666				   as_dev->buf_len, DMA_BIDIRECTIONAL);667 668	/* set dma addr */669	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,670			   as_dev->dma_addr);671	if (err)672		return err;673 674	/* set cust sec size */675	val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;676	val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val);677	err = regmap_update_bits(as_ctrl->regmap_nfi,678				 REG_SPI_NFI_SNF_MISC_CTL2,679				 SPI_NFI_READ_DATA_BYTE_NUM, val);680	if (err)681		return err;682 683	/* set read command */684	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,685			   op->cmd.opcode);686	if (err)687		return err;688 689	/* set read mode */690	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,691			   FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, rd_mode));692	if (err)693		return err;694 695	/* set read addr */696	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);697	if (err)698		return err;699 700	/* set nfi read */701	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,702				 SPI_NFI_OPMODE,703				 FIELD_PREP(SPI_NFI_OPMODE, 6));704	if (err)705		return err;706 707	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,708			      SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);709	if (err)710		return err;711 712	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);713	if (err)714		return err;715 716	/* trigger dma start read */717	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,718				SPI_NFI_RD_TRIG);719	if (err)720		return err;721 722	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,723			      SPI_NFI_RD_TRIG);724	if (err)725		return err;726 727	err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,728				       REG_SPI_NFI_SNF_STA_CTL1, val,729				       (val & SPI_NFI_READ_FROM_CACHE_DONE),730				       0, 1 * USEC_PER_SEC);731	if (err)732		return err;733 734	/*735	 * SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end736	 * of dirmap_read operation even if it is already set.737	 */738	err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,739				SPI_NFI_READ_FROM_CACHE_DONE,740				SPI_NFI_READ_FROM_CACHE_DONE);741	if (err)742		return err;743 744	err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,745				       val, (val & SPI_NFI_AHB_DONE), 0,746				       1 * USEC_PER_SEC);747	if (err)748		return err;749 750	/* DMA read need delay for data ready from controller to DRAM */751	udelay(1);752 753	dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,754				as_dev->buf_len, DMA_BIDIRECTIONAL);755	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);756	if (err < 0)757		return err;758 759	memcpy(buf, as_dev->txrx_buf + offs, len);760 761	return len;762}763 764static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,765					 u64 offs, size_t len, const void *buf)766{767	struct spi_device *spi = desc->mem->spi;768	struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);769	struct spi_mem_op *op = &desc->info.op_tmpl;770	struct airoha_snand_ctrl *as_ctrl;771	u32 wr_mode, val;772	int err;773 774	as_ctrl = spi_controller_get_devdata(spi->controller);775	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);776	if (err < 0)777		return err;778 779	dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,780				as_dev->buf_len, DMA_BIDIRECTIONAL);781	memcpy(as_dev->txrx_buf + offs, buf, len);782	dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,783				   as_dev->buf_len, DMA_BIDIRECTIONAL);784 785	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);786	if (err < 0)787		return err;788 789	err = airoha_snand_nfi_config(as_ctrl);790	if (err)791		return err;792 793	if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||794	    op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)795		wr_mode = BIT(1);796	else797		wr_mode = 0;798 799	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,800			   as_dev->dma_addr);801	if (err)802		return err;803 804	val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,805			 as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);806	err = regmap_update_bits(as_ctrl->regmap_nfi,807				 REG_SPI_NFI_SNF_MISC_CTL2,808				 SPI_NFI_PROG_LOAD_BYTE_NUM, val);809	if (err)810		return err;811 812	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,813			   FIELD_PREP(SPI_NFI_PG_LOAD_CMD,814				      op->cmd.opcode));815	if (err)816		return err;817 818	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,819			   FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));820	if (err)821		return err;822 823	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);824	if (err)825		return err;826 827	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,828				SPI_NFI_READ_MODE);829	if (err)830		return err;831 832	err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,833				 SPI_NFI_OPMODE,834				 FIELD_PREP(SPI_NFI_OPMODE, 3));835	if (err)836		return err;837 838	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,839			      SPI_NFI_DMA_MODE);840	if (err)841		return err;842 843	err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);844	if (err)845		return err;846 847	err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,848				SPI_NFI_WR_TRIG);849	if (err)850		return err;851 852	err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,853			      SPI_NFI_WR_TRIG);854	if (err)855		return err;856 857	err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,858				       val, (val & SPI_NFI_AHB_DONE), 0,859				       1 * USEC_PER_SEC);860	if (err)861		return err;862 863	err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,864				       REG_SPI_NFI_SNF_STA_CTL1, val,865				       (val & SPI_NFI_LOAD_TO_CACHE_DONE),866				       0, 1 * USEC_PER_SEC);867	if (err)868		return err;869 870	/*871	 * SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end872	 * of dirmap_write operation even if it is already set.873	 */874	err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,875				SPI_NFI_LOAD_TO_CACHE_DONE,876				SPI_NFI_LOAD_TO_CACHE_DONE);877	if (err)878		return err;879 880	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);881	if (err < 0)882		return err;883 884	return len;885}886 887static int airoha_snand_exec_op(struct spi_mem *mem,888				const struct spi_mem_op *op)889{890	u8 data[8], cmd, opcode = op->cmd.opcode;891	struct airoha_snand_ctrl *as_ctrl;892	int i, err;893 894	as_ctrl = spi_controller_get_devdata(mem->spi->controller);895 896	/* switch to manual mode */897	err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);898	if (err < 0)899		return err;900 901	err = airoha_snand_set_cs(as_ctrl, SPI_CHIP_SEL_LOW);902	if (err < 0)903		return err;904 905	/* opcode */906	err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));907	if (err)908		return err;909 910	/* addr part */911	cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;912	put_unaligned_be64(op->addr.val, data);913 914	for (i = ARRAY_SIZE(data) - op->addr.nbytes;915	     i < ARRAY_SIZE(data); i++) {916		err = airoha_snand_write_data(as_ctrl, cmd, &data[i],917					      sizeof(data[0]));918		if (err)919			return err;920	}921 922	/* dummy */923	data[0] = 0xff;924	for (i = 0; i < op->dummy.nbytes; i++) {925		err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],926					      sizeof(data[0]));927		if (err)928			return err;929	}930 931	/* data */932	if (op->data.dir == SPI_MEM_DATA_IN) {933		err = airoha_snand_read_data(as_ctrl, op->data.buf.in,934					     op->data.nbytes);935		if (err)936			return err;937	} else {938		err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,939					      op->data.nbytes);940		if (err)941			return err;942	}943 944	return airoha_snand_set_cs(as_ctrl, SPI_CHIP_SEL_HIGH);945}946 947static const struct spi_controller_mem_ops airoha_snand_mem_ops = {948	.adjust_op_size = airoha_snand_adjust_op_size,949	.supports_op = airoha_snand_supports_op,950	.exec_op = airoha_snand_exec_op,951	.dirmap_create = airoha_snand_dirmap_create,952	.dirmap_read = airoha_snand_dirmap_read,953	.dirmap_write = airoha_snand_dirmap_write,954};955 956static int airoha_snand_setup(struct spi_device *spi)957{958	struct airoha_snand_ctrl *as_ctrl;959	struct airoha_snand_dev *as_dev;960 961	as_ctrl = spi_controller_get_devdata(spi->controller);962 963	as_dev = devm_kzalloc(as_ctrl->dev, sizeof(*as_dev), GFP_KERNEL);964	if (!as_dev)965		return -ENOMEM;966 967	/* prepare device buffer */968	as_dev->buf_len = SPI_NAND_CACHE_SIZE;969	as_dev->txrx_buf = devm_kzalloc(as_ctrl->dev, as_dev->buf_len,970					GFP_KERNEL);971	if (!as_dev->txrx_buf)972		return -ENOMEM;973 974	as_dev->dma_addr = dma_map_single(as_ctrl->dev, as_dev->txrx_buf,975					  as_dev->buf_len, DMA_BIDIRECTIONAL);976	if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))977		return -ENOMEM;978 979	spi_set_ctldata(spi, as_dev);980 981	return 0;982}983 984static void airoha_snand_cleanup(struct spi_device *spi)985{986	struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);987	struct airoha_snand_ctrl *as_ctrl;988 989	as_ctrl = spi_controller_get_devdata(spi->controller);990	dma_unmap_single(as_ctrl->dev, as_dev->dma_addr,991			 as_dev->buf_len, DMA_BIDIRECTIONAL);992	spi_set_ctldata(spi, NULL);993}994 995static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)996{997	u32 val, sec_size, sec_num;998	int err;999 1000	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val);1001	if (err)1002		return err;1003 1004	sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val);1005 1006	err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val);1007	if (err)1008		return err;1009 1010	sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val);1011 1012	/* init default value */1013	as_ctrl->nfi_cfg.sec_size = sec_size;1014	as_ctrl->nfi_cfg.sec_num = sec_num;1015	as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024);1016	as_ctrl->nfi_cfg.spare_size = 16;1017 1018	err = airoha_snand_nfi_init(as_ctrl);1019	if (err)1020		return err;1021 1022	return airoha_snand_nfi_config(as_ctrl);1023}1024 1025static const struct regmap_config spi_ctrl_regmap_config = {1026	.name		= "ctrl",1027	.reg_bits	= 32,1028	.val_bits	= 32,1029	.reg_stride	= 4,1030	.max_register	= REG_SPI_CTRL_NFI2SPI_EN,1031};1032 1033static const struct regmap_config spi_nfi_regmap_config = {1034	.name		= "nfi",1035	.reg_bits	= 32,1036	.val_bits	= 32,1037	.reg_stride	= 4,1038	.max_register	= REG_SPI_NFI_SNF_NFI_CNFG,1039};1040 1041static const struct of_device_id airoha_snand_ids[] = {1042	{ .compatible	= "airoha,en7581-snand" },1043	{ /* sentinel */ }1044};1045MODULE_DEVICE_TABLE(of, airoha_snand_ids);1046 1047static int airoha_snand_probe(struct platform_device *pdev)1048{1049	struct airoha_snand_ctrl *as_ctrl;1050	struct device *dev = &pdev->dev;1051	struct spi_controller *ctrl;1052	void __iomem *base;1053	int err;1054 1055	ctrl = devm_spi_alloc_host(dev, sizeof(*as_ctrl));1056	if (!ctrl)1057		return -ENOMEM;1058 1059	as_ctrl = spi_controller_get_devdata(ctrl);1060	as_ctrl->dev = dev;1061 1062	base = devm_platform_ioremap_resource(pdev, 0);1063	if (IS_ERR(base))1064		return PTR_ERR(base);1065 1066	as_ctrl->regmap_ctrl = devm_regmap_init_mmio(dev, base,1067						     &spi_ctrl_regmap_config);1068	if (IS_ERR(as_ctrl->regmap_ctrl))1069		return dev_err_probe(dev, PTR_ERR(as_ctrl->regmap_ctrl),1070				     "failed to init spi ctrl regmap\n");1071 1072	base = devm_platform_ioremap_resource(pdev, 1);1073	if (IS_ERR(base))1074		return PTR_ERR(base);1075 1076	as_ctrl->regmap_nfi = devm_regmap_init_mmio(dev, base,1077						    &spi_nfi_regmap_config);1078	if (IS_ERR(as_ctrl->regmap_nfi))1079		return dev_err_probe(dev, PTR_ERR(as_ctrl->regmap_nfi),1080				     "failed to init spi nfi regmap\n");1081 1082	as_ctrl->spi_clk = devm_clk_get_enabled(dev, "spi");1083	if (IS_ERR(as_ctrl->spi_clk))1084		return dev_err_probe(dev, PTR_ERR(as_ctrl->spi_clk),1085				     "unable to get spi clk\n");1086 1087	err = dma_set_mask(as_ctrl->dev, DMA_BIT_MASK(32));1088	if (err)1089		return err;1090 1091	ctrl->num_chipselect = 2;1092	ctrl->mem_ops = &airoha_snand_mem_ops;1093	ctrl->bits_per_word_mask = SPI_BPW_MASK(8);1094	ctrl->mode_bits = SPI_RX_DUAL;1095	ctrl->setup = airoha_snand_setup;1096	ctrl->cleanup = airoha_snand_cleanup;1097	device_set_node(&ctrl->dev, dev_fwnode(dev));1098 1099	err = airoha_snand_nfi_setup(as_ctrl);1100	if (err)1101		return err;1102 1103	return devm_spi_register_controller(dev, ctrl);1104}1105 1106static struct platform_driver airoha_snand_driver = {1107	.driver = {1108		.name = "airoha-spi",1109		.of_match_table = airoha_snand_ids,1110	},1111	.probe = airoha_snand_probe,1112};1113module_platform_driver(airoha_snand_driver);1114 1115MODULE_DESCRIPTION("Airoha SPI-NAND Flash Controller Driver");1116MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");1117MODULE_AUTHOR("Ray Liu <ray.liu@airoha.com>");1118MODULE_LICENSE("GPL");1119