xref: /linux/drivers/mtd/spi-nor/controllers/hisi-sfc.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1a0900d01SBoris Brezillon // SPDX-License-Identifier: GPL-2.0-or-later
2a0900d01SBoris Brezillon /*
31ac71ec0STudor Ambarus  * HiSilicon FMC SPI NOR flash controller driver
4a0900d01SBoris Brezillon  *
5a0900d01SBoris Brezillon  * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
6a0900d01SBoris Brezillon  */
7a0900d01SBoris Brezillon #include <linux/bitops.h>
8a0900d01SBoris Brezillon #include <linux/clk.h>
9a0900d01SBoris Brezillon #include <linux/dma-mapping.h>
10a0900d01SBoris Brezillon #include <linux/iopoll.h>
11a0900d01SBoris Brezillon #include <linux/module.h>
12a0900d01SBoris Brezillon #include <linux/mtd/mtd.h>
13a0900d01SBoris Brezillon #include <linux/mtd/spi-nor.h>
14a0900d01SBoris Brezillon #include <linux/of.h>
15a0900d01SBoris Brezillon #include <linux/platform_device.h>
16a0900d01SBoris Brezillon #include <linux/slab.h>
17a0900d01SBoris Brezillon 
18a0900d01SBoris Brezillon /* Hardware register offsets and field definitions */
19a0900d01SBoris Brezillon #define FMC_CFG				0x00
20a0900d01SBoris Brezillon #define FMC_CFG_OP_MODE_MASK		BIT_MASK(0)
21a0900d01SBoris Brezillon #define FMC_CFG_OP_MODE_BOOT		0
22a0900d01SBoris Brezillon #define FMC_CFG_OP_MODE_NORMAL		1
23a0900d01SBoris Brezillon #define FMC_CFG_FLASH_SEL(type)		(((type) & 0x3) << 1)
24a0900d01SBoris Brezillon #define FMC_CFG_FLASH_SEL_MASK		0x6
25a0900d01SBoris Brezillon #define FMC_ECC_TYPE(type)		(((type) & 0x7) << 5)
26a0900d01SBoris Brezillon #define FMC_ECC_TYPE_MASK		GENMASK(7, 5)
27a0900d01SBoris Brezillon #define SPI_NOR_ADDR_MODE_MASK		BIT_MASK(10)
28a0900d01SBoris Brezillon #define SPI_NOR_ADDR_MODE_3BYTES	(0x0 << 10)
29a0900d01SBoris Brezillon #define SPI_NOR_ADDR_MODE_4BYTES	(0x1 << 10)
30a0900d01SBoris Brezillon #define FMC_GLOBAL_CFG			0x04
31a0900d01SBoris Brezillon #define FMC_GLOBAL_CFG_WP_ENABLE	BIT(6)
32a0900d01SBoris Brezillon #define FMC_SPI_TIMING_CFG		0x08
33a0900d01SBoris Brezillon #define TIMING_CFG_TCSH(nr)		(((nr) & 0xf) << 8)
34a0900d01SBoris Brezillon #define TIMING_CFG_TCSS(nr)		(((nr) & 0xf) << 4)
35a0900d01SBoris Brezillon #define TIMING_CFG_TSHSL(nr)		((nr) & 0xf)
36a0900d01SBoris Brezillon #define CS_HOLD_TIME			0x6
37a0900d01SBoris Brezillon #define CS_SETUP_TIME			0x6
38a0900d01SBoris Brezillon #define CS_DESELECT_TIME		0xf
39a0900d01SBoris Brezillon #define FMC_INT				0x18
40a0900d01SBoris Brezillon #define FMC_INT_OP_DONE			BIT(0)
41a0900d01SBoris Brezillon #define FMC_INT_CLR			0x20
42a0900d01SBoris Brezillon #define FMC_CMD				0x24
43a0900d01SBoris Brezillon #define FMC_CMD_CMD1(cmd)		((cmd) & 0xff)
44a0900d01SBoris Brezillon #define FMC_ADDRL			0x2c
45a0900d01SBoris Brezillon #define FMC_OP_CFG			0x30
46a0900d01SBoris Brezillon #define OP_CFG_FM_CS(cs)		((cs) << 11)
47a0900d01SBoris Brezillon #define OP_CFG_MEM_IF_TYPE(type)	(((type) & 0x7) << 7)
48a0900d01SBoris Brezillon #define OP_CFG_ADDR_NUM(addr)		(((addr) & 0x7) << 4)
49a0900d01SBoris Brezillon #define OP_CFG_DUMMY_NUM(dummy)		((dummy) & 0xf)
50a0900d01SBoris Brezillon #define FMC_DATA_NUM			0x38
51a0900d01SBoris Brezillon #define FMC_DATA_NUM_CNT(cnt)		((cnt) & GENMASK(13, 0))
52a0900d01SBoris Brezillon #define FMC_OP				0x3c
53a0900d01SBoris Brezillon #define FMC_OP_DUMMY_EN			BIT(8)
54a0900d01SBoris Brezillon #define FMC_OP_CMD1_EN			BIT(7)
55a0900d01SBoris Brezillon #define FMC_OP_ADDR_EN			BIT(6)
56a0900d01SBoris Brezillon #define FMC_OP_WRITE_DATA_EN		BIT(5)
57a0900d01SBoris Brezillon #define FMC_OP_READ_DATA_EN		BIT(2)
58a0900d01SBoris Brezillon #define FMC_OP_READ_STATUS_EN		BIT(1)
59a0900d01SBoris Brezillon #define FMC_OP_REG_OP_START		BIT(0)
60a0900d01SBoris Brezillon #define FMC_DMA_LEN			0x40
61a0900d01SBoris Brezillon #define FMC_DMA_LEN_SET(len)		((len) & GENMASK(27, 0))
62a0900d01SBoris Brezillon #define FMC_DMA_SADDR_D0		0x4c
63a0900d01SBoris Brezillon #define HIFMC_DMA_MAX_LEN		(4096)
64a0900d01SBoris Brezillon #define HIFMC_DMA_MASK			(HIFMC_DMA_MAX_LEN - 1)
65a0900d01SBoris Brezillon #define FMC_OP_DMA			0x68
66a0900d01SBoris Brezillon #define OP_CTRL_RD_OPCODE(code)		(((code) & 0xff) << 16)
67a0900d01SBoris Brezillon #define OP_CTRL_WR_OPCODE(code)		(((code) & 0xff) << 8)
68a0900d01SBoris Brezillon #define OP_CTRL_RW_OP(op)		((op) << 1)
69a0900d01SBoris Brezillon #define OP_CTRL_DMA_OP_READY		BIT(0)
70a0900d01SBoris Brezillon #define FMC_OP_READ			0x0
71a0900d01SBoris Brezillon #define FMC_OP_WRITE			0x1
72a0900d01SBoris Brezillon #define FMC_WAIT_TIMEOUT		1000000
73a0900d01SBoris Brezillon 
74a0900d01SBoris Brezillon enum hifmc_iftype {
75a0900d01SBoris Brezillon 	IF_TYPE_STD,
76a0900d01SBoris Brezillon 	IF_TYPE_DUAL,
77a0900d01SBoris Brezillon 	IF_TYPE_DIO,
78a0900d01SBoris Brezillon 	IF_TYPE_QUAD,
79a0900d01SBoris Brezillon 	IF_TYPE_QIO,
80a0900d01SBoris Brezillon };
81a0900d01SBoris Brezillon 
82a0900d01SBoris Brezillon struct hifmc_priv {
83a0900d01SBoris Brezillon 	u32 chipselect;
84a0900d01SBoris Brezillon 	u32 clkrate;
85a0900d01SBoris Brezillon 	struct hifmc_host *host;
86a0900d01SBoris Brezillon };
87a0900d01SBoris Brezillon 
88a0900d01SBoris Brezillon #define HIFMC_MAX_CHIP_NUM		2
89a0900d01SBoris Brezillon struct hifmc_host {
90a0900d01SBoris Brezillon 	struct device *dev;
91a0900d01SBoris Brezillon 	struct mutex lock;
92a0900d01SBoris Brezillon 
93a0900d01SBoris Brezillon 	void __iomem *regbase;
94a0900d01SBoris Brezillon 	void __iomem *iobase;
95a0900d01SBoris Brezillon 	struct clk *clk;
96a0900d01SBoris Brezillon 	void *buffer;
97a0900d01SBoris Brezillon 	dma_addr_t dma_buffer;
98a0900d01SBoris Brezillon 
99a0900d01SBoris Brezillon 	struct spi_nor	*nor[HIFMC_MAX_CHIP_NUM];
100a0900d01SBoris Brezillon 	u32 num_chip;
101a0900d01SBoris Brezillon };
102a0900d01SBoris Brezillon 
hisi_spi_nor_wait_op_finish(struct hifmc_host * host)103a0900d01SBoris Brezillon static inline int hisi_spi_nor_wait_op_finish(struct hifmc_host *host)
104a0900d01SBoris Brezillon {
105a0900d01SBoris Brezillon 	u32 reg;
106a0900d01SBoris Brezillon 
107a0900d01SBoris Brezillon 	return readl_poll_timeout(host->regbase + FMC_INT, reg,
108a0900d01SBoris Brezillon 		(reg & FMC_INT_OP_DONE), 0, FMC_WAIT_TIMEOUT);
109a0900d01SBoris Brezillon }
110a0900d01SBoris Brezillon 
hisi_spi_nor_get_if_type(enum spi_nor_protocol proto)111a0900d01SBoris Brezillon static int hisi_spi_nor_get_if_type(enum spi_nor_protocol proto)
112a0900d01SBoris Brezillon {
113a0900d01SBoris Brezillon 	enum hifmc_iftype if_type;
114a0900d01SBoris Brezillon 
115a0900d01SBoris Brezillon 	switch (proto) {
116a0900d01SBoris Brezillon 	case SNOR_PROTO_1_1_2:
117a0900d01SBoris Brezillon 		if_type = IF_TYPE_DUAL;
118a0900d01SBoris Brezillon 		break;
119a0900d01SBoris Brezillon 	case SNOR_PROTO_1_2_2:
120a0900d01SBoris Brezillon 		if_type = IF_TYPE_DIO;
121a0900d01SBoris Brezillon 		break;
122a0900d01SBoris Brezillon 	case SNOR_PROTO_1_1_4:
123a0900d01SBoris Brezillon 		if_type = IF_TYPE_QUAD;
124a0900d01SBoris Brezillon 		break;
125a0900d01SBoris Brezillon 	case SNOR_PROTO_1_4_4:
126a0900d01SBoris Brezillon 		if_type = IF_TYPE_QIO;
127a0900d01SBoris Brezillon 		break;
128a0900d01SBoris Brezillon 	case SNOR_PROTO_1_1_1:
129a0900d01SBoris Brezillon 	default:
130a0900d01SBoris Brezillon 		if_type = IF_TYPE_STD;
131a0900d01SBoris Brezillon 		break;
132a0900d01SBoris Brezillon 	}
133a0900d01SBoris Brezillon 
134a0900d01SBoris Brezillon 	return if_type;
135a0900d01SBoris Brezillon }
136a0900d01SBoris Brezillon 
hisi_spi_nor_init(struct hifmc_host * host)137a0900d01SBoris Brezillon static void hisi_spi_nor_init(struct hifmc_host *host)
138a0900d01SBoris Brezillon {
139a0900d01SBoris Brezillon 	u32 reg;
140a0900d01SBoris Brezillon 
141a0900d01SBoris Brezillon 	reg = TIMING_CFG_TCSH(CS_HOLD_TIME)
142a0900d01SBoris Brezillon 		| TIMING_CFG_TCSS(CS_SETUP_TIME)
143a0900d01SBoris Brezillon 		| TIMING_CFG_TSHSL(CS_DESELECT_TIME);
144a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_SPI_TIMING_CFG);
145a0900d01SBoris Brezillon }
146a0900d01SBoris Brezillon 
hisi_spi_nor_prep(struct spi_nor * nor)147a0900d01SBoris Brezillon static int hisi_spi_nor_prep(struct spi_nor *nor)
148a0900d01SBoris Brezillon {
149a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
150a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
151a0900d01SBoris Brezillon 	int ret;
152a0900d01SBoris Brezillon 
153a0900d01SBoris Brezillon 	mutex_lock(&host->lock);
154a0900d01SBoris Brezillon 
155a0900d01SBoris Brezillon 	ret = clk_set_rate(host->clk, priv->clkrate);
156a0900d01SBoris Brezillon 	if (ret)
157a0900d01SBoris Brezillon 		goto out;
158a0900d01SBoris Brezillon 
159a0900d01SBoris Brezillon 	ret = clk_prepare_enable(host->clk);
160a0900d01SBoris Brezillon 	if (ret)
161a0900d01SBoris Brezillon 		goto out;
162a0900d01SBoris Brezillon 
163a0900d01SBoris Brezillon 	return 0;
164a0900d01SBoris Brezillon 
165a0900d01SBoris Brezillon out:
166a0900d01SBoris Brezillon 	mutex_unlock(&host->lock);
167a0900d01SBoris Brezillon 	return ret;
168a0900d01SBoris Brezillon }
169a0900d01SBoris Brezillon 
hisi_spi_nor_unprep(struct spi_nor * nor)170a0900d01SBoris Brezillon static void hisi_spi_nor_unprep(struct spi_nor *nor)
171a0900d01SBoris Brezillon {
172a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
173a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
174a0900d01SBoris Brezillon 
175a0900d01SBoris Brezillon 	clk_disable_unprepare(host->clk);
176a0900d01SBoris Brezillon 	mutex_unlock(&host->lock);
177a0900d01SBoris Brezillon }
178a0900d01SBoris Brezillon 
hisi_spi_nor_op_reg(struct spi_nor * nor,u8 opcode,size_t len,u8 optype)179a0900d01SBoris Brezillon static int hisi_spi_nor_op_reg(struct spi_nor *nor,
180a0900d01SBoris Brezillon 				u8 opcode, size_t len, u8 optype)
181a0900d01SBoris Brezillon {
182a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
183a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
184a0900d01SBoris Brezillon 	u32 reg;
185a0900d01SBoris Brezillon 
186a0900d01SBoris Brezillon 	reg = FMC_CMD_CMD1(opcode);
187a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_CMD);
188a0900d01SBoris Brezillon 
189a0900d01SBoris Brezillon 	reg = FMC_DATA_NUM_CNT(len);
190a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_DATA_NUM);
191a0900d01SBoris Brezillon 
192a0900d01SBoris Brezillon 	reg = OP_CFG_FM_CS(priv->chipselect);
193a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_OP_CFG);
194a0900d01SBoris Brezillon 
195a0900d01SBoris Brezillon 	writel(0xff, host->regbase + FMC_INT_CLR);
196a0900d01SBoris Brezillon 	reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START | optype;
197a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_OP);
198a0900d01SBoris Brezillon 
199a0900d01SBoris Brezillon 	return hisi_spi_nor_wait_op_finish(host);
200a0900d01SBoris Brezillon }
201a0900d01SBoris Brezillon 
hisi_spi_nor_read_reg(struct spi_nor * nor,u8 opcode,u8 * buf,size_t len)202a0900d01SBoris Brezillon static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
203a0900d01SBoris Brezillon 				 size_t len)
204a0900d01SBoris Brezillon {
205a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
206a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
207a0900d01SBoris Brezillon 	int ret;
208a0900d01SBoris Brezillon 
209a0900d01SBoris Brezillon 	ret = hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_READ_DATA_EN);
210a0900d01SBoris Brezillon 	if (ret)
211a0900d01SBoris Brezillon 		return ret;
212a0900d01SBoris Brezillon 
213a0900d01SBoris Brezillon 	memcpy_fromio(buf, host->iobase, len);
214a0900d01SBoris Brezillon 	return 0;
215a0900d01SBoris Brezillon }
216a0900d01SBoris Brezillon 
hisi_spi_nor_write_reg(struct spi_nor * nor,u8 opcode,const u8 * buf,size_t len)217a0900d01SBoris Brezillon static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode,
218a0900d01SBoris Brezillon 				  const u8 *buf, size_t len)
219a0900d01SBoris Brezillon {
220a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
221a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
222a0900d01SBoris Brezillon 
223a0900d01SBoris Brezillon 	if (len)
224a0900d01SBoris Brezillon 		memcpy_toio(host->iobase, buf, len);
225a0900d01SBoris Brezillon 
226a0900d01SBoris Brezillon 	return hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_WRITE_DATA_EN);
227a0900d01SBoris Brezillon }
228a0900d01SBoris Brezillon 
hisi_spi_nor_dma_transfer(struct spi_nor * nor,loff_t start_off,dma_addr_t dma_buf,size_t len,u8 op_type)229a0900d01SBoris Brezillon static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off,
230a0900d01SBoris Brezillon 		dma_addr_t dma_buf, size_t len, u8 op_type)
231a0900d01SBoris Brezillon {
232a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
233a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
234a0900d01SBoris Brezillon 	u8 if_type = 0;
235a0900d01SBoris Brezillon 	u32 reg;
236a0900d01SBoris Brezillon 
237a0900d01SBoris Brezillon 	reg = readl(host->regbase + FMC_CFG);
238a0900d01SBoris Brezillon 	reg &= ~(FMC_CFG_OP_MODE_MASK | SPI_NOR_ADDR_MODE_MASK);
239a0900d01SBoris Brezillon 	reg |= FMC_CFG_OP_MODE_NORMAL;
240c452d498STudor Ambarus 	reg |= (nor->addr_nbytes == 4) ? SPI_NOR_ADDR_MODE_4BYTES
241a0900d01SBoris Brezillon 		: SPI_NOR_ADDR_MODE_3BYTES;
242a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_CFG);
243a0900d01SBoris Brezillon 
244a0900d01SBoris Brezillon 	writel(start_off, host->regbase + FMC_ADDRL);
245a0900d01SBoris Brezillon 	writel(dma_buf, host->regbase + FMC_DMA_SADDR_D0);
246a0900d01SBoris Brezillon 	writel(FMC_DMA_LEN_SET(len), host->regbase + FMC_DMA_LEN);
247a0900d01SBoris Brezillon 
248a0900d01SBoris Brezillon 	reg = OP_CFG_FM_CS(priv->chipselect);
249a0900d01SBoris Brezillon 	if (op_type == FMC_OP_READ)
250a0900d01SBoris Brezillon 		if_type = hisi_spi_nor_get_if_type(nor->read_proto);
251a0900d01SBoris Brezillon 	else
252a0900d01SBoris Brezillon 		if_type = hisi_spi_nor_get_if_type(nor->write_proto);
253a0900d01SBoris Brezillon 	reg |= OP_CFG_MEM_IF_TYPE(if_type);
254a0900d01SBoris Brezillon 	if (op_type == FMC_OP_READ)
255a0900d01SBoris Brezillon 		reg |= OP_CFG_DUMMY_NUM(nor->read_dummy >> 3);
256a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_OP_CFG);
257a0900d01SBoris Brezillon 
258a0900d01SBoris Brezillon 	writel(0xff, host->regbase + FMC_INT_CLR);
259a0900d01SBoris Brezillon 	reg = OP_CTRL_RW_OP(op_type) | OP_CTRL_DMA_OP_READY;
260a0900d01SBoris Brezillon 	reg |= (op_type == FMC_OP_READ)
261a0900d01SBoris Brezillon 		? OP_CTRL_RD_OPCODE(nor->read_opcode)
262a0900d01SBoris Brezillon 		: OP_CTRL_WR_OPCODE(nor->program_opcode);
263a0900d01SBoris Brezillon 	writel(reg, host->regbase + FMC_OP_DMA);
264a0900d01SBoris Brezillon 
265a0900d01SBoris Brezillon 	return hisi_spi_nor_wait_op_finish(host);
266a0900d01SBoris Brezillon }
267a0900d01SBoris Brezillon 
hisi_spi_nor_read(struct spi_nor * nor,loff_t from,size_t len,u_char * read_buf)268a0900d01SBoris Brezillon static ssize_t hisi_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len,
269a0900d01SBoris Brezillon 		u_char *read_buf)
270a0900d01SBoris Brezillon {
271a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
272a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
273a0900d01SBoris Brezillon 	size_t offset;
274a0900d01SBoris Brezillon 	int ret;
275a0900d01SBoris Brezillon 
276a0900d01SBoris Brezillon 	for (offset = 0; offset < len; offset += HIFMC_DMA_MAX_LEN) {
277a0900d01SBoris Brezillon 		size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset);
278a0900d01SBoris Brezillon 
279a0900d01SBoris Brezillon 		ret = hisi_spi_nor_dma_transfer(nor,
280a0900d01SBoris Brezillon 			from + offset, host->dma_buffer, trans, FMC_OP_READ);
281a0900d01SBoris Brezillon 		if (ret) {
282a0900d01SBoris Brezillon 			dev_warn(nor->dev, "DMA read timeout\n");
283a0900d01SBoris Brezillon 			return ret;
284a0900d01SBoris Brezillon 		}
285a0900d01SBoris Brezillon 		memcpy(read_buf + offset, host->buffer, trans);
286a0900d01SBoris Brezillon 	}
287a0900d01SBoris Brezillon 
288a0900d01SBoris Brezillon 	return len;
289a0900d01SBoris Brezillon }
290a0900d01SBoris Brezillon 
hisi_spi_nor_write(struct spi_nor * nor,loff_t to,size_t len,const u_char * write_buf)291a0900d01SBoris Brezillon static ssize_t hisi_spi_nor_write(struct spi_nor *nor, loff_t to,
292a0900d01SBoris Brezillon 			size_t len, const u_char *write_buf)
293a0900d01SBoris Brezillon {
294a0900d01SBoris Brezillon 	struct hifmc_priv *priv = nor->priv;
295a0900d01SBoris Brezillon 	struct hifmc_host *host = priv->host;
296a0900d01SBoris Brezillon 	size_t offset;
297a0900d01SBoris Brezillon 	int ret;
298a0900d01SBoris Brezillon 
299a0900d01SBoris Brezillon 	for (offset = 0; offset < len; offset += HIFMC_DMA_MAX_LEN) {
300a0900d01SBoris Brezillon 		size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset);
301a0900d01SBoris Brezillon 
302a0900d01SBoris Brezillon 		memcpy(host->buffer, write_buf + offset, trans);
303a0900d01SBoris Brezillon 		ret = hisi_spi_nor_dma_transfer(nor,
304a0900d01SBoris Brezillon 			to + offset, host->dma_buffer, trans, FMC_OP_WRITE);
305a0900d01SBoris Brezillon 		if (ret) {
306a0900d01SBoris Brezillon 			dev_warn(nor->dev, "DMA write timeout\n");
307a0900d01SBoris Brezillon 			return ret;
308a0900d01SBoris Brezillon 		}
309a0900d01SBoris Brezillon 	}
310a0900d01SBoris Brezillon 
311a0900d01SBoris Brezillon 	return len;
312a0900d01SBoris Brezillon }
313a0900d01SBoris Brezillon 
314a0900d01SBoris Brezillon static const struct spi_nor_controller_ops hisi_controller_ops = {
315a0900d01SBoris Brezillon 	.prepare = hisi_spi_nor_prep,
316a0900d01SBoris Brezillon 	.unprepare = hisi_spi_nor_unprep,
317a0900d01SBoris Brezillon 	.read_reg = hisi_spi_nor_read_reg,
318a0900d01SBoris Brezillon 	.write_reg = hisi_spi_nor_write_reg,
319a0900d01SBoris Brezillon 	.read = hisi_spi_nor_read,
320a0900d01SBoris Brezillon 	.write = hisi_spi_nor_write,
321a0900d01SBoris Brezillon };
322a0900d01SBoris Brezillon 
323d67b272fSLee Jones /*
324a0900d01SBoris Brezillon  * Get spi flash device information and register it as a mtd device.
325a0900d01SBoris Brezillon  */
hisi_spi_nor_register(struct device_node * np,struct hifmc_host * host)326a0900d01SBoris Brezillon static int hisi_spi_nor_register(struct device_node *np,
327a0900d01SBoris Brezillon 				struct hifmc_host *host)
328a0900d01SBoris Brezillon {
329a0900d01SBoris Brezillon 	const struct spi_nor_hwcaps hwcaps = {
330a0900d01SBoris Brezillon 		.mask = SNOR_HWCAPS_READ |
331a0900d01SBoris Brezillon 			SNOR_HWCAPS_READ_FAST |
332a0900d01SBoris Brezillon 			SNOR_HWCAPS_READ_1_1_2 |
333a0900d01SBoris Brezillon 			SNOR_HWCAPS_READ_1_1_4 |
334a0900d01SBoris Brezillon 			SNOR_HWCAPS_PP,
335a0900d01SBoris Brezillon 	};
336a0900d01SBoris Brezillon 	struct device *dev = host->dev;
337a0900d01SBoris Brezillon 	struct spi_nor *nor;
338a0900d01SBoris Brezillon 	struct hifmc_priv *priv;
339a0900d01SBoris Brezillon 	struct mtd_info *mtd;
340a0900d01SBoris Brezillon 	int ret;
341a0900d01SBoris Brezillon 
342a0900d01SBoris Brezillon 	nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL);
343a0900d01SBoris Brezillon 	if (!nor)
344a0900d01SBoris Brezillon 		return -ENOMEM;
345a0900d01SBoris Brezillon 
346a0900d01SBoris Brezillon 	nor->dev = dev;
347a0900d01SBoris Brezillon 	spi_nor_set_flash_node(nor, np);
348a0900d01SBoris Brezillon 
349a0900d01SBoris Brezillon 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
350a0900d01SBoris Brezillon 	if (!priv)
351a0900d01SBoris Brezillon 		return -ENOMEM;
352a0900d01SBoris Brezillon 
353a0900d01SBoris Brezillon 	ret = of_property_read_u32(np, "reg", &priv->chipselect);
354a0900d01SBoris Brezillon 	if (ret) {
355a0900d01SBoris Brezillon 		dev_err(dev, "There's no reg property for %pOF\n",
356a0900d01SBoris Brezillon 			np);
357a0900d01SBoris Brezillon 		return ret;
358a0900d01SBoris Brezillon 	}
359a0900d01SBoris Brezillon 
360a0900d01SBoris Brezillon 	ret = of_property_read_u32(np, "spi-max-frequency",
361a0900d01SBoris Brezillon 			&priv->clkrate);
362a0900d01SBoris Brezillon 	if (ret) {
363a0900d01SBoris Brezillon 		dev_err(dev, "There's no spi-max-frequency property for %pOF\n",
364a0900d01SBoris Brezillon 			np);
365a0900d01SBoris Brezillon 		return ret;
366a0900d01SBoris Brezillon 	}
367a0900d01SBoris Brezillon 	priv->host = host;
368a0900d01SBoris Brezillon 	nor->priv = priv;
369a0900d01SBoris Brezillon 	nor->controller_ops = &hisi_controller_ops;
370a0900d01SBoris Brezillon 
371a0900d01SBoris Brezillon 	ret = spi_nor_scan(nor, NULL, &hwcaps);
372a0900d01SBoris Brezillon 	if (ret)
373a0900d01SBoris Brezillon 		return ret;
374a0900d01SBoris Brezillon 
375a0900d01SBoris Brezillon 	mtd = &nor->mtd;
376a0900d01SBoris Brezillon 	mtd->name = np->name;
377a0900d01SBoris Brezillon 	ret = mtd_device_register(mtd, NULL, 0);
378a0900d01SBoris Brezillon 	if (ret)
379a0900d01SBoris Brezillon 		return ret;
380a0900d01SBoris Brezillon 
381a0900d01SBoris Brezillon 	host->nor[host->num_chip] = nor;
382a0900d01SBoris Brezillon 	host->num_chip++;
383a0900d01SBoris Brezillon 	return 0;
384a0900d01SBoris Brezillon }
385a0900d01SBoris Brezillon 
hisi_spi_nor_unregister_all(struct hifmc_host * host)386a0900d01SBoris Brezillon static void hisi_spi_nor_unregister_all(struct hifmc_host *host)
387a0900d01SBoris Brezillon {
388a0900d01SBoris Brezillon 	int i;
389a0900d01SBoris Brezillon 
390a0900d01SBoris Brezillon 	for (i = 0; i < host->num_chip; i++)
391a0900d01SBoris Brezillon 		mtd_device_unregister(&host->nor[i]->mtd);
392a0900d01SBoris Brezillon }
393a0900d01SBoris Brezillon 
hisi_spi_nor_register_all(struct hifmc_host * host)394a0900d01SBoris Brezillon static int hisi_spi_nor_register_all(struct hifmc_host *host)
395a0900d01SBoris Brezillon {
396a0900d01SBoris Brezillon 	struct device *dev = host->dev;
397a0900d01SBoris Brezillon 	struct device_node *np;
398a0900d01SBoris Brezillon 	int ret;
399a0900d01SBoris Brezillon 
400a0900d01SBoris Brezillon 	for_each_available_child_of_node(dev->of_node, np) {
401a0900d01SBoris Brezillon 		ret = hisi_spi_nor_register(np, host);
402fe665346SPan Bian 		if (ret) {
403fe665346SPan Bian 			of_node_put(np);
404a0900d01SBoris Brezillon 			goto fail;
405fe665346SPan Bian 		}
406a0900d01SBoris Brezillon 
407a0900d01SBoris Brezillon 		if (host->num_chip == HIFMC_MAX_CHIP_NUM) {
408a0900d01SBoris Brezillon 			dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n");
409a0900d01SBoris Brezillon 			of_node_put(np);
410a0900d01SBoris Brezillon 			break;
411a0900d01SBoris Brezillon 		}
412a0900d01SBoris Brezillon 	}
413a0900d01SBoris Brezillon 
414a0900d01SBoris Brezillon 	return 0;
415a0900d01SBoris Brezillon 
416a0900d01SBoris Brezillon fail:
417a0900d01SBoris Brezillon 	hisi_spi_nor_unregister_all(host);
418a0900d01SBoris Brezillon 	return ret;
419a0900d01SBoris Brezillon }
420a0900d01SBoris Brezillon 
hisi_spi_nor_probe(struct platform_device * pdev)421a0900d01SBoris Brezillon static int hisi_spi_nor_probe(struct platform_device *pdev)
422a0900d01SBoris Brezillon {
423a0900d01SBoris Brezillon 	struct device *dev = &pdev->dev;
424a0900d01SBoris Brezillon 	struct hifmc_host *host;
425a0900d01SBoris Brezillon 	int ret;
426a0900d01SBoris Brezillon 
427a0900d01SBoris Brezillon 	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
428a0900d01SBoris Brezillon 	if (!host)
429a0900d01SBoris Brezillon 		return -ENOMEM;
430a0900d01SBoris Brezillon 
431a0900d01SBoris Brezillon 	platform_set_drvdata(pdev, host);
432a0900d01SBoris Brezillon 	host->dev = dev;
433a0900d01SBoris Brezillon 
434a10ed4c4SCai Huoqing 	host->regbase = devm_platform_ioremap_resource_byname(pdev, "control");
435a0900d01SBoris Brezillon 	if (IS_ERR(host->regbase))
436a0900d01SBoris Brezillon 		return PTR_ERR(host->regbase);
437a0900d01SBoris Brezillon 
438a10ed4c4SCai Huoqing 	host->iobase = devm_platform_ioremap_resource_byname(pdev, "memory");
439a0900d01SBoris Brezillon 	if (IS_ERR(host->iobase))
440a0900d01SBoris Brezillon 		return PTR_ERR(host->iobase);
441a0900d01SBoris Brezillon 
442a0900d01SBoris Brezillon 	host->clk = devm_clk_get(dev, NULL);
443a0900d01SBoris Brezillon 	if (IS_ERR(host->clk))
444a0900d01SBoris Brezillon 		return PTR_ERR(host->clk);
445a0900d01SBoris Brezillon 
446a0900d01SBoris Brezillon 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
447a0900d01SBoris Brezillon 	if (ret) {
448a0900d01SBoris Brezillon 		dev_warn(dev, "Unable to set dma mask\n");
449a0900d01SBoris Brezillon 		return ret;
450a0900d01SBoris Brezillon 	}
451a0900d01SBoris Brezillon 
452a0900d01SBoris Brezillon 	host->buffer = dmam_alloc_coherent(dev, HIFMC_DMA_MAX_LEN,
453a0900d01SBoris Brezillon 			&host->dma_buffer, GFP_KERNEL);
454a0900d01SBoris Brezillon 	if (!host->buffer)
455a0900d01SBoris Brezillon 		return -ENOMEM;
456a0900d01SBoris Brezillon 
457a0900d01SBoris Brezillon 	ret = clk_prepare_enable(host->clk);
458a0900d01SBoris Brezillon 	if (ret)
459a0900d01SBoris Brezillon 		return ret;
460a0900d01SBoris Brezillon 
461a0900d01SBoris Brezillon 	mutex_init(&host->lock);
462a0900d01SBoris Brezillon 	hisi_spi_nor_init(host);
463a0900d01SBoris Brezillon 	ret = hisi_spi_nor_register_all(host);
464a0900d01SBoris Brezillon 	if (ret)
465a0900d01SBoris Brezillon 		mutex_destroy(&host->lock);
466a0900d01SBoris Brezillon 
467a0900d01SBoris Brezillon 	clk_disable_unprepare(host->clk);
468a0900d01SBoris Brezillon 	return ret;
469a0900d01SBoris Brezillon }
470a0900d01SBoris Brezillon 
hisi_spi_nor_remove(struct platform_device * pdev)471*ac2bc659SUwe Kleine-König static void hisi_spi_nor_remove(struct platform_device *pdev)
472a0900d01SBoris Brezillon {
473a0900d01SBoris Brezillon 	struct hifmc_host *host = platform_get_drvdata(pdev);
474a0900d01SBoris Brezillon 
475a0900d01SBoris Brezillon 	hisi_spi_nor_unregister_all(host);
476a0900d01SBoris Brezillon 	mutex_destroy(&host->lock);
477a0900d01SBoris Brezillon }
478a0900d01SBoris Brezillon 
479a0900d01SBoris Brezillon static const struct of_device_id hisi_spi_nor_dt_ids[] = {
480a0900d01SBoris Brezillon 	{ .compatible = "hisilicon,fmc-spi-nor"},
481a0900d01SBoris Brezillon 	{ /* sentinel */ }
482a0900d01SBoris Brezillon };
483a0900d01SBoris Brezillon MODULE_DEVICE_TABLE(of, hisi_spi_nor_dt_ids);
484a0900d01SBoris Brezillon 
485a0900d01SBoris Brezillon static struct platform_driver hisi_spi_nor_driver = {
486a0900d01SBoris Brezillon 	.driver = {
487a0900d01SBoris Brezillon 		.name	= "hisi-sfc",
488a0900d01SBoris Brezillon 		.of_match_table = hisi_spi_nor_dt_ids,
489a0900d01SBoris Brezillon 	},
490a0900d01SBoris Brezillon 	.probe	= hisi_spi_nor_probe,
491*ac2bc659SUwe Kleine-König 	.remove_new = hisi_spi_nor_remove,
492a0900d01SBoris Brezillon };
493a0900d01SBoris Brezillon module_platform_driver(hisi_spi_nor_driver);
494a0900d01SBoris Brezillon 
495a0900d01SBoris Brezillon MODULE_LICENSE("GPL v2");
496a0900d01SBoris Brezillon MODULE_DESCRIPTION("HiSilicon SPI Nor Flash Controller Driver");
497