1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets
4 //
5 // Copyright (c) 2019 HiSilicon Technologies Co., Ltd.
6 // Author: John Garry <john.garry@huawei.com>
7 
8 #include <linux/acpi.h>
9 #include <linux/bitops.h>
10 #include <linux/dmi.h>
11 #include <linux/iopoll.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
15 #include <linux/spi/spi.h>
16 #include <linux/spi/spi-mem.h>
17 
18 #define HISI_SFC_V3XX_VERSION (0x1f8)
19 
20 #define HISI_SFC_V3XX_INT_STAT (0x120)
21 #define HISI_SFC_V3XX_INT_STAT_PP_ERR BIT(2)
22 #define HISI_SFC_V3XX_INT_STAT_ADDR_IACCES BIT(5)
23 #define HISI_SFC_V3XX_INT_CLR (0x12c)
24 #define HISI_SFC_V3XX_INT_CLR_CLEAR (0xff)
25 #define HISI_SFC_V3XX_CMD_CFG (0x300)
26 #define HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT (1 << 17)
27 #define HISI_SFC_V3XX_CMD_CFG_DUAL_IO (2 << 17)
28 #define HISI_SFC_V3XX_CMD_CFG_FULL_DIO (3 << 17)
29 #define HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT (5 << 17)
30 #define HISI_SFC_V3XX_CMD_CFG_QUAD_IO (6 << 17)
31 #define HISI_SFC_V3XX_CMD_CFG_FULL_QIO (7 << 17)
32 #define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9
33 #define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8)
34 #define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7)
35 #define HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF 4
36 #define HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK BIT(3)
37 #define HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF 1
38 #define HISI_SFC_V3XX_CMD_CFG_START_MSK BIT(0)
39 #define HISI_SFC_V3XX_CMD_INS (0x308)
40 #define HISI_SFC_V3XX_CMD_ADDR (0x30c)
41 #define HISI_SFC_V3XX_CMD_DATABUF0 (0x400)
42 
43 struct hisi_sfc_v3xx_host {
44 	struct device *dev;
45 	void __iomem *regbase;
46 	int max_cmd_dword;
47 };
48 
49 #define HISI_SFC_V3XX_WAIT_TIMEOUT_US		1000000
50 #define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US	10
51 
52 static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host *host)
53 {
54 	u32 reg;
55 
56 	return readl_poll_timeout(host->regbase + HISI_SFC_V3XX_CMD_CFG, reg,
57 				  !(reg & HISI_SFC_V3XX_CMD_CFG_START_MSK),
58 				  HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US,
59 				  HISI_SFC_V3XX_WAIT_TIMEOUT_US);
60 }
61 
62 static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem,
63 					struct spi_mem_op *op)
64 {
65 	struct spi_device *spi = mem->spi;
66 	struct hisi_sfc_v3xx_host *host;
67 	uintptr_t addr = (uintptr_t)op->data.buf.in;
68 	int max_byte_count;
69 
70 	host = spi_controller_get_devdata(spi->master);
71 
72 	max_byte_count = host->max_cmd_dword * 4;
73 
74 	if (!IS_ALIGNED(addr, 4) && op->data.nbytes >= 4)
75 		op->data.nbytes = 4 - (addr % 4);
76 	else if (op->data.nbytes > max_byte_count)
77 		op->data.nbytes = max_byte_count;
78 
79 	return 0;
80 }
81 
82 /*
83  * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the
84  * DATABUF registers -so use __io{read,write}32_copy when possible. For
85  * trailing bytes, copy them byte-by-byte from the DATABUF register, as we
86  * can't clobber outside the source/dest buffer.
87  *
88  * For efficient data read/write, we try to put any start 32b unaligned data
89  * into a separate transaction in hisi_sfc_v3xx_adjust_op_size().
90  */
91 static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host *host,
92 				       u8 *to, unsigned int len)
93 {
94 	void __iomem *from;
95 	int i;
96 
97 	from = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0;
98 
99 	if (IS_ALIGNED((uintptr_t)to, 4)) {
100 		int words = len / 4;
101 
102 		__ioread32_copy(to, from, words);
103 
104 		len -= words * 4;
105 		if (len) {
106 			u32 val;
107 
108 			to += words * 4;
109 			from += words * 4;
110 
111 			val = __raw_readl(from);
112 
113 			for (i = 0; i < len; i++, val >>= 8, to++)
114 				*to = (u8)val;
115 		}
116 	} else {
117 		for (i = 0; i < DIV_ROUND_UP(len, 4); i++, from += 4) {
118 			u32 val = __raw_readl(from);
119 			int j;
120 
121 			for (j = 0; j < 4 && (j + (i * 4) < len);
122 			     to++, val >>= 8, j++)
123 				*to = (u8)val;
124 		}
125 	}
126 }
127 
128 static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host *host,
129 					const u8 *from, unsigned int len)
130 {
131 	void __iomem *to;
132 	int i;
133 
134 	to = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0;
135 
136 	if (IS_ALIGNED((uintptr_t)from, 4)) {
137 		int words = len / 4;
138 
139 		__iowrite32_copy(to, from, words);
140 
141 		len -= words * 4;
142 		if (len) {
143 			u32 val = 0;
144 
145 			to += words * 4;
146 			from += words * 4;
147 
148 			for (i = 0; i < len; i++, from++)
149 				val |= *from << i * 8;
150 			__raw_writel(val, to);
151 		}
152 
153 	} else {
154 		for (i = 0; i < DIV_ROUND_UP(len, 4); i++, to += 4) {
155 			u32 val = 0;
156 			int j;
157 
158 			for (j = 0; j < 4 && (j + (i * 4) < len);
159 			     from++, j++)
160 				val |= *from << j * 8;
161 			__raw_writel(val, to);
162 		}
163 	}
164 }
165 
166 static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host,
167 					 const struct spi_mem_op *op,
168 					 u8 chip_select)
169 {
170 	int ret, len = op->data.nbytes;
171 	u32 int_stat, config = 0;
172 
173 	if (op->addr.nbytes)
174 		config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK;
175 
176 	switch (op->data.buswidth) {
177 	case 0 ... 1:
178 		break;
179 	case 2:
180 		if (op->addr.buswidth <= 1) {
181 			config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT;
182 		} else if (op->addr.buswidth == 2) {
183 			if (op->cmd.buswidth <= 1) {
184 				config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IO;
185 			} else if (op->cmd.buswidth == 2) {
186 				config |= HISI_SFC_V3XX_CMD_CFG_FULL_DIO;
187 			} else {
188 				return -EIO;
189 			}
190 		} else {
191 			return -EIO;
192 		}
193 		break;
194 	case 4:
195 		if (op->addr.buswidth <= 1) {
196 			config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT;
197 		} else if (op->addr.buswidth == 4) {
198 			if (op->cmd.buswidth <= 1) {
199 				config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IO;
200 			} else if (op->cmd.buswidth == 4) {
201 				config |= HISI_SFC_V3XX_CMD_CFG_FULL_QIO;
202 			} else {
203 				return -EIO;
204 			}
205 		} else {
206 			return -EIO;
207 		}
208 		break;
209 	default:
210 		return -EOPNOTSUPP;
211 	}
212 
213 	if (op->data.dir != SPI_MEM_NO_DATA) {
214 		config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF;
215 		config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK;
216 	}
217 
218 	if (op->data.dir == SPI_MEM_DATA_OUT)
219 		hisi_sfc_v3xx_write_databuf(host, op->data.buf.out, len);
220 	else if (op->data.dir == SPI_MEM_DATA_IN)
221 		config |= HISI_SFC_V3XX_CMD_CFG_RW_MSK;
222 
223 	config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF |
224 		  chip_select << HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF |
225 		  HISI_SFC_V3XX_CMD_CFG_START_MSK;
226 
227 	writel(op->addr.val, host->regbase + HISI_SFC_V3XX_CMD_ADDR);
228 	writel(op->cmd.opcode, host->regbase + HISI_SFC_V3XX_CMD_INS);
229 
230 	writel(config, host->regbase + HISI_SFC_V3XX_CMD_CFG);
231 
232 	ret = hisi_sfc_v3xx_wait_cmd_idle(host);
233 	if (ret)
234 		return ret;
235 
236 	/*
237 	 * The interrupt status register indicates whether an error occurs
238 	 * after per operation. Check it, and clear the interrupts for
239 	 * next time judgement.
240 	 */
241 	int_stat = readl(host->regbase + HISI_SFC_V3XX_INT_STAT);
242 	writel(HISI_SFC_V3XX_INT_CLR_CLEAR,
243 	       host->regbase + HISI_SFC_V3XX_INT_CLR);
244 
245 	if (int_stat & HISI_SFC_V3XX_INT_STAT_ADDR_IACCES) {
246 		dev_err(host->dev, "fail to access protected address\n");
247 		return -EIO;
248 	}
249 
250 	if (int_stat & HISI_SFC_V3XX_INT_STAT_PP_ERR) {
251 		dev_err(host->dev, "page program operation failed\n");
252 		return -EIO;
253 	}
254 
255 	if (op->data.dir == SPI_MEM_DATA_IN)
256 		hisi_sfc_v3xx_read_databuf(host, op->data.buf.in, len);
257 
258 	return 0;
259 }
260 
261 static int hisi_sfc_v3xx_exec_op(struct spi_mem *mem,
262 				 const struct spi_mem_op *op)
263 {
264 	struct hisi_sfc_v3xx_host *host;
265 	struct spi_device *spi = mem->spi;
266 	u8 chip_select = spi->chip_select;
267 
268 	host = spi_controller_get_devdata(spi->master);
269 
270 	return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select);
271 }
272 
273 static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = {
274 	.adjust_op_size = hisi_sfc_v3xx_adjust_op_size,
275 	.exec_op = hisi_sfc_v3xx_exec_op,
276 };
277 
278 static int hisi_sfc_v3xx_buswidth_override_bits;
279 
280 /*
281  * ACPI FW does not allow us to currently set the device buswidth, so quirk it
282  * depending on the board.
283  */
284 static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d)
285 {
286 	hisi_sfc_v3xx_buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD;
287 
288 	return 0;
289 }
290 
291 static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[]  = {
292 	{
293 	.callback = hisi_sfc_v3xx_dmi_quirk,
294 	.matches = {
295 		DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
296 		DMI_MATCH(DMI_PRODUCT_NAME, "D06"),
297 	},
298 	},
299 	{
300 	.callback = hisi_sfc_v3xx_dmi_quirk,
301 	.matches = {
302 		DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
303 		DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 2280 V2"),
304 	},
305 	},
306 	{
307 	.callback = hisi_sfc_v3xx_dmi_quirk,
308 	.matches = {
309 		DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
310 		DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 200 (Model 2280)"),
311 	},
312 	},
313 	{}
314 };
315 
316 static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
317 {
318 	struct device *dev = &pdev->dev;
319 	struct hisi_sfc_v3xx_host *host;
320 	struct spi_controller *ctlr;
321 	u32 version;
322 	int ret;
323 
324 	ctlr = spi_alloc_master(&pdev->dev, sizeof(*host));
325 	if (!ctlr)
326 		return -ENOMEM;
327 
328 	ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD |
329 			  SPI_TX_DUAL | SPI_TX_QUAD;
330 
331 	ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits;
332 
333 	host = spi_controller_get_devdata(ctlr);
334 	host->dev = dev;
335 
336 	platform_set_drvdata(pdev, host);
337 
338 	host->regbase = devm_platform_ioremap_resource(pdev, 0);
339 	if (IS_ERR(host->regbase)) {
340 		ret = PTR_ERR(host->regbase);
341 		goto err_put_master;
342 	}
343 
344 	ctlr->bus_num = -1;
345 	ctlr->num_chipselect = 1;
346 	ctlr->mem_ops = &hisi_sfc_v3xx_mem_ops;
347 
348 	version = readl(host->regbase + HISI_SFC_V3XX_VERSION);
349 
350 	switch (version) {
351 	case 0x351:
352 		host->max_cmd_dword = 64;
353 		break;
354 	default:
355 		host->max_cmd_dword = 16;
356 		break;
357 	}
358 
359 	ret = devm_spi_register_controller(dev, ctlr);
360 	if (ret)
361 		goto err_put_master;
362 
363 	dev_info(&pdev->dev, "hw version 0x%x\n", version);
364 
365 	return 0;
366 
367 err_put_master:
368 	spi_master_put(ctlr);
369 	return ret;
370 }
371 
372 #if IS_ENABLED(CONFIG_ACPI)
373 static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] = {
374 	{"HISI0341", 0},
375 	{}
376 };
377 MODULE_DEVICE_TABLE(acpi, hisi_sfc_v3xx_acpi_ids);
378 #endif
379 
380 static struct platform_driver hisi_sfc_v3xx_spi_driver = {
381 	.driver = {
382 		.name	= "hisi-sfc-v3xx",
383 		.acpi_match_table = ACPI_PTR(hisi_sfc_v3xx_acpi_ids),
384 	},
385 	.probe	= hisi_sfc_v3xx_probe,
386 };
387 
388 static int __init hisi_sfc_v3xx_spi_init(void)
389 {
390 	dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table);
391 
392 	return platform_driver_register(&hisi_sfc_v3xx_spi_driver);
393 }
394 
395 static void __exit hisi_sfc_v3xx_spi_exit(void)
396 {
397 	platform_driver_unregister(&hisi_sfc_v3xx_spi_driver);
398 }
399 
400 module_init(hisi_sfc_v3xx_spi_init);
401 module_exit(hisi_sfc_v3xx_spi_exit);
402 
403 MODULE_LICENSE("GPL");
404 MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
405 MODULE_DESCRIPTION("HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets");
406