xref: /linux/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c (revision fc5ced75d6dffc9e2a441520b7dc587b95281f86)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2022-2023 Microchip Technology Inc.
3 // PCI1xxxx OTP/EEPROM driver
4 
5 #include <linux/auxiliary_bus.h>
6 #include <linux/device.h>
7 #include <linux/iopoll.h>
8 #include <linux/module.h>
9 #include <linux/nvmem-provider.h>
10 
11 #include "mchp_pci1xxxx_gp.h"
12 
13 #define AUX_DRIVER_NAME			"PCI1xxxxOTPE2P"
14 #define EEPROM_NAME			"pci1xxxx_eeprom"
15 #define OTP_NAME			"pci1xxxx_otp"
16 
17 #define PERI_PF3_SYSTEM_REG_ADDR_BASE	0x2000
18 #define PERI_PF3_SYSTEM_REG_LENGTH	0x4000
19 
20 #define EEPROM_SIZE_BYTES		8192
21 #define OTP_SIZE_BYTES			8192
22 
23 #define CONFIG_REG_ADDR_BASE		0
24 #define EEPROM_REG_ADDR_BASE		0x0E00
25 #define OTP_REG_ADDR_BASE		0x1000
26 
27 #define MMAP_OTP_OFFSET(x)		(OTP_REG_ADDR_BASE + (x))
28 #define MMAP_EEPROM_OFFSET(x)		(EEPROM_REG_ADDR_BASE + (x))
29 #define MMAP_CFG_OFFSET(x)		(CONFIG_REG_ADDR_BASE + (x))
30 
31 #define EEPROM_CMD_REG			0x00
32 #define EEPROM_DATA_REG			0x04
33 
34 #define EEPROM_CMD_EPC_WRITE		(BIT(29) | BIT(28))
35 #define EEPROM_CMD_EPC_TIMEOUT_BIT	BIT(17)
36 #define EEPROM_CMD_EPC_BUSY_BIT		BIT(31)
37 
38 #define STATUS_READ_DELAY_US		1
39 #define STATUS_READ_TIMEOUT_US		20000
40 
41 #define OTP_ADDR_HIGH_OFFSET		0x04
42 #define OTP_ADDR_LOW_OFFSET		0x08
43 #define OTP_PRGM_DATA_OFFSET		0x10
44 #define OTP_PRGM_MODE_OFFSET		0x14
45 #define OTP_RD_DATA_OFFSET		0x18
46 #define OTP_FUNC_CMD_OFFSET		0x20
47 #define OTP_CMD_GO_OFFSET		0x28
48 #define OTP_PASS_FAIL_OFFSET		0x2C
49 #define OTP_STATUS_OFFSET		0x30
50 
51 #define OTP_FUNC_RD_BIT			BIT(0)
52 #define OTP_FUNC_PGM_BIT		BIT(1)
53 #define OTP_CMD_GO_BIT			BIT(0)
54 #define OTP_STATUS_BUSY_BIT		BIT(0)
55 #define OTP_PGM_MODE_BYTE_BIT		BIT(0)
56 #define OTP_FAIL_BIT			BIT(0)
57 
58 #define OTP_PWR_DN_BIT			BIT(0)
59 #define OTP_PWR_DN_OFFSET		0x00
60 
61 #define CFG_SYS_LOCK_OFFSET		0xA0
62 #define CFG_SYS_LOCK_PF3		BIT(5)
63 
64 #define BYTE_LOW			(GENMASK(7, 0))
65 #define BYTE_HIGH			(GENMASK(12, 8))
66 
67 struct pci1xxxx_otp_eeprom_device {
68 	struct auxiliary_device *pdev;
69 	void __iomem *reg_base;
70 	struct nvmem_config nvmem_config_eeprom;
71 	struct nvmem_device *nvmem_eeprom;
72 	struct nvmem_config nvmem_config_otp;
73 	struct nvmem_device *nvmem_otp;
74 };
75 
set_sys_lock(struct pci1xxxx_otp_eeprom_device * priv)76 static int set_sys_lock(struct pci1xxxx_otp_eeprom_device *priv)
77 {
78 	void __iomem *sys_lock = priv->reg_base +
79 				 MMAP_CFG_OFFSET(CFG_SYS_LOCK_OFFSET);
80 	u8 data;
81 
82 	writel(CFG_SYS_LOCK_PF3, sys_lock);
83 	data = readl(sys_lock);
84 	if (data != CFG_SYS_LOCK_PF3)
85 		return -EPERM;
86 
87 	return 0;
88 }
89 
release_sys_lock(struct pci1xxxx_otp_eeprom_device * priv)90 static void release_sys_lock(struct pci1xxxx_otp_eeprom_device *priv)
91 {
92 	void __iomem *sys_lock = priv->reg_base +
93 				 MMAP_CFG_OFFSET(CFG_SYS_LOCK_OFFSET);
94 	writel(0, sys_lock);
95 }
96 
is_eeprom_responsive(struct pci1xxxx_otp_eeprom_device * priv)97 static bool is_eeprom_responsive(struct pci1xxxx_otp_eeprom_device *priv)
98 {
99 	void __iomem *rb = priv->reg_base;
100 	u32 regval;
101 	int ret;
102 
103 	writel(EEPROM_CMD_EPC_TIMEOUT_BIT,
104 	       rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
105 	writel(EEPROM_CMD_EPC_BUSY_BIT,
106 	       rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
107 
108 	/* Wait for the EPC_BUSY bit to get cleared or timeout bit to get set*/
109 	ret = read_poll_timeout(readl, regval, !(regval & EEPROM_CMD_EPC_BUSY_BIT),
110 				STATUS_READ_DELAY_US, STATUS_READ_TIMEOUT_US,
111 				true, rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
112 
113 	/* Return failure if either of software or hardware timeouts happen */
114 	if (ret < 0 || (!ret && (regval & EEPROM_CMD_EPC_TIMEOUT_BIT)))
115 		return false;
116 
117 	return true;
118 }
119 
pci1xxxx_eeprom_read(void * priv_t,unsigned int off,void * buf_t,size_t count)120 static int pci1xxxx_eeprom_read(void *priv_t, unsigned int off,
121 				void *buf_t, size_t count)
122 {
123 	struct pci1xxxx_otp_eeprom_device *priv = priv_t;
124 	void __iomem *rb = priv->reg_base;
125 	char *buf = buf_t;
126 	u32 regval;
127 	u32 byte;
128 	int ret;
129 
130 	if (off >= priv->nvmem_config_eeprom.size)
131 		return -EFAULT;
132 
133 	if ((off + count) > priv->nvmem_config_eeprom.size)
134 		count = priv->nvmem_config_eeprom.size - off;
135 
136 	ret = set_sys_lock(priv);
137 	if (ret)
138 		return ret;
139 
140 	for (byte = 0; byte < count; byte++) {
141 		writel(EEPROM_CMD_EPC_BUSY_BIT | (off + byte), rb +
142 		       MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
143 
144 		ret = read_poll_timeout(readl, regval,
145 					!(regval & EEPROM_CMD_EPC_BUSY_BIT),
146 					STATUS_READ_DELAY_US,
147 					STATUS_READ_TIMEOUT_US, true,
148 					rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
149 		if (ret < 0 || (!ret && (regval & EEPROM_CMD_EPC_TIMEOUT_BIT))) {
150 			ret = -EIO;
151 			goto error;
152 		}
153 
154 		buf[byte] = readl(rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
155 	}
156 error:
157 	release_sys_lock(priv);
158 	return ret;
159 }
160 
pci1xxxx_eeprom_write(void * priv_t,unsigned int off,void * value_t,size_t count)161 static int pci1xxxx_eeprom_write(void *priv_t, unsigned int off,
162 				 void *value_t, size_t count)
163 {
164 	struct pci1xxxx_otp_eeprom_device *priv = priv_t;
165 	void __iomem *rb = priv->reg_base;
166 	char *value = value_t;
167 	u32 regval;
168 	u32 byte;
169 	int ret;
170 
171 	if (off >= priv->nvmem_config_eeprom.size)
172 		return -EFAULT;
173 
174 	if ((off + count) > priv->nvmem_config_eeprom.size)
175 		count = priv->nvmem_config_eeprom.size - off;
176 
177 	ret = set_sys_lock(priv);
178 	if (ret)
179 		return ret;
180 
181 	for (byte = 0; byte < count; byte++) {
182 		writel(*(value + byte), rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
183 		regval = EEPROM_CMD_EPC_TIMEOUT_BIT | EEPROM_CMD_EPC_WRITE |
184 			 (off + byte);
185 		writel(regval, rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
186 		writel(EEPROM_CMD_EPC_BUSY_BIT | regval,
187 		       rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
188 
189 		ret = read_poll_timeout(readl, regval,
190 					!(regval & EEPROM_CMD_EPC_BUSY_BIT),
191 					STATUS_READ_DELAY_US,
192 					STATUS_READ_TIMEOUT_US, true,
193 					rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
194 		if (ret < 0 || (!ret && (regval & EEPROM_CMD_EPC_TIMEOUT_BIT))) {
195 			ret = -EIO;
196 			goto error;
197 		}
198 	}
199 error:
200 	release_sys_lock(priv);
201 	return ret;
202 }
203 
otp_device_set_address(struct pci1xxxx_otp_eeprom_device * priv,u16 address)204 static void otp_device_set_address(struct pci1xxxx_otp_eeprom_device *priv,
205 				   u16 address)
206 {
207 	u16 lo, hi;
208 
209 	lo = address & BYTE_LOW;
210 	hi = (address & BYTE_HIGH) >> 8;
211 	writew(lo, priv->reg_base + MMAP_OTP_OFFSET(OTP_ADDR_LOW_OFFSET));
212 	writew(hi, priv->reg_base + MMAP_OTP_OFFSET(OTP_ADDR_HIGH_OFFSET));
213 }
214 
pci1xxxx_otp_read(void * priv_t,unsigned int off,void * buf_t,size_t count)215 static int pci1xxxx_otp_read(void *priv_t, unsigned int off,
216 			     void *buf_t, size_t count)
217 {
218 	struct pci1xxxx_otp_eeprom_device *priv = priv_t;
219 	void __iomem *rb = priv->reg_base;
220 	char *buf = buf_t;
221 	u32 regval;
222 	u32 byte;
223 	int ret;
224 	u8 data;
225 
226 	if (off >= priv->nvmem_config_otp.size)
227 		return -EFAULT;
228 
229 	if ((off + count) > priv->nvmem_config_otp.size)
230 		count = priv->nvmem_config_otp.size - off;
231 
232 	ret = set_sys_lock(priv);
233 	if (ret)
234 		return ret;
235 
236 	for (byte = 0; byte < count; byte++) {
237 		otp_device_set_address(priv, (u16)(off + byte));
238 		data = readl(rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
239 		writel(data | OTP_FUNC_RD_BIT,
240 		       rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
241 		data = readl(rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
242 		writel(data | OTP_CMD_GO_BIT,
243 		       rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
244 
245 		ret = read_poll_timeout(readl, regval,
246 					!(regval & OTP_STATUS_BUSY_BIT),
247 					STATUS_READ_DELAY_US,
248 					STATUS_READ_TIMEOUT_US, true,
249 					rb + MMAP_OTP_OFFSET(OTP_STATUS_OFFSET));
250 
251 		data = readl(rb + MMAP_OTP_OFFSET(OTP_PASS_FAIL_OFFSET));
252 		if (ret < 0 || data & OTP_FAIL_BIT) {
253 			ret = -EIO;
254 			goto error;
255 		}
256 
257 		buf[byte] = readl(rb + MMAP_OTP_OFFSET(OTP_RD_DATA_OFFSET));
258 	}
259 error:
260 	release_sys_lock(priv);
261 	return ret;
262 }
263 
pci1xxxx_otp_write(void * priv_t,unsigned int off,void * value_t,size_t count)264 static int pci1xxxx_otp_write(void *priv_t, unsigned int off,
265 			      void *value_t, size_t count)
266 {
267 	struct pci1xxxx_otp_eeprom_device *priv = priv_t;
268 	void __iomem *rb = priv->reg_base;
269 	char *value = value_t;
270 	u32 regval;
271 	u32 byte;
272 	int ret;
273 	u8 data;
274 
275 	if (off >= priv->nvmem_config_otp.size)
276 		return -EFAULT;
277 
278 	if ((off + count) > priv->nvmem_config_otp.size)
279 		count = priv->nvmem_config_otp.size - off;
280 
281 	ret = set_sys_lock(priv);
282 	if (ret)
283 		return ret;
284 
285 	for (byte = 0; byte < count; byte++) {
286 		otp_device_set_address(priv, (u16)(off + byte));
287 
288 		/*
289 		 * Set OTP_PGM_MODE_BYTE command bit in OTP_PRGM_MODE register
290 		 * to enable Byte programming
291 		 */
292 		data = readl(rb + MMAP_OTP_OFFSET(OTP_PRGM_MODE_OFFSET));
293 		writel(data | OTP_PGM_MODE_BYTE_BIT,
294 		       rb + MMAP_OTP_OFFSET(OTP_PRGM_MODE_OFFSET));
295 		writel(*(value + byte), rb + MMAP_OTP_OFFSET(OTP_PRGM_DATA_OFFSET));
296 		data = readl(rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
297 		writel(data | OTP_FUNC_PGM_BIT,
298 		       rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
299 		data = readl(rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
300 		writel(data | OTP_CMD_GO_BIT,
301 		       rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
302 
303 		ret = read_poll_timeout(readl, regval,
304 					!(regval & OTP_STATUS_BUSY_BIT),
305 					STATUS_READ_DELAY_US,
306 					STATUS_READ_TIMEOUT_US, true,
307 					rb + MMAP_OTP_OFFSET(OTP_STATUS_OFFSET));
308 
309 		data = readl(rb + MMAP_OTP_OFFSET(OTP_PASS_FAIL_OFFSET));
310 		if (ret < 0 || data & OTP_FAIL_BIT) {
311 			ret = -EIO;
312 			goto error;
313 		}
314 	}
315 error:
316 	release_sys_lock(priv);
317 	return ret;
318 }
319 
pci1xxxx_otp_eeprom_probe(struct auxiliary_device * aux_dev,const struct auxiliary_device_id * id)320 static int pci1xxxx_otp_eeprom_probe(struct auxiliary_device *aux_dev,
321 				     const struct auxiliary_device_id *id)
322 {
323 	struct auxiliary_device_wrapper *aux_dev_wrapper;
324 	struct pci1xxxx_otp_eeprom_device *priv;
325 	struct gp_aux_data_type *pdata;
326 	int ret;
327 	u8 data;
328 
329 	aux_dev_wrapper = container_of(aux_dev, struct auxiliary_device_wrapper,
330 				       aux_dev);
331 	pdata = &aux_dev_wrapper->gp_aux_data;
332 	if (!pdata)
333 		return -EINVAL;
334 
335 	priv = devm_kzalloc(&aux_dev->dev, sizeof(*priv), GFP_KERNEL);
336 	if (!priv)
337 		return -ENOMEM;
338 
339 	priv->pdev = aux_dev;
340 
341 	if (!devm_request_mem_region(&aux_dev->dev, pdata->region_start +
342 				     PERI_PF3_SYSTEM_REG_ADDR_BASE,
343 				     PERI_PF3_SYSTEM_REG_LENGTH,
344 				     aux_dev->name))
345 		return -ENOMEM;
346 
347 	priv->reg_base = devm_ioremap(&aux_dev->dev, pdata->region_start +
348 				      PERI_PF3_SYSTEM_REG_ADDR_BASE,
349 				      PERI_PF3_SYSTEM_REG_LENGTH);
350 	if (!priv->reg_base)
351 		return -ENOMEM;
352 
353 	ret = set_sys_lock(priv);
354 	if (ret)
355 		return ret;
356 
357 	/* Set OTP_PWR_DN to 0 to make OTP Operational */
358 	data = readl(priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
359 	writel(data & ~OTP_PWR_DN_BIT,
360 	       priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
361 
362 	dev_set_drvdata(&aux_dev->dev, priv);
363 
364 	if (is_eeprom_responsive(priv)) {
365 		priv->nvmem_config_eeprom.type = NVMEM_TYPE_EEPROM;
366 		priv->nvmem_config_eeprom.name = EEPROM_NAME;
367 		priv->nvmem_config_eeprom.id = NVMEM_DEVID_AUTO;
368 		priv->nvmem_config_eeprom.dev = &aux_dev->dev;
369 		priv->nvmem_config_eeprom.owner = THIS_MODULE;
370 		priv->nvmem_config_eeprom.reg_read = pci1xxxx_eeprom_read;
371 		priv->nvmem_config_eeprom.reg_write = pci1xxxx_eeprom_write;
372 		priv->nvmem_config_eeprom.priv = priv;
373 		priv->nvmem_config_eeprom.stride = 1;
374 		priv->nvmem_config_eeprom.word_size = 1;
375 		priv->nvmem_config_eeprom.size = EEPROM_SIZE_BYTES;
376 
377 		priv->nvmem_eeprom = devm_nvmem_register(&aux_dev->dev,
378 							 &priv->nvmem_config_eeprom);
379 		if (IS_ERR(priv->nvmem_eeprom))
380 			return PTR_ERR(priv->nvmem_eeprom);
381 	}
382 
383 	release_sys_lock(priv);
384 
385 	priv->nvmem_config_otp.type = NVMEM_TYPE_OTP;
386 	priv->nvmem_config_otp.name = OTP_NAME;
387 	priv->nvmem_config_otp.id = NVMEM_DEVID_AUTO;
388 	priv->nvmem_config_otp.dev = &aux_dev->dev;
389 	priv->nvmem_config_otp.owner = THIS_MODULE;
390 	priv->nvmem_config_otp.reg_read = pci1xxxx_otp_read;
391 	priv->nvmem_config_otp.reg_write = pci1xxxx_otp_write;
392 	priv->nvmem_config_otp.priv = priv;
393 	priv->nvmem_config_otp.stride = 1;
394 	priv->nvmem_config_otp.word_size = 1;
395 	priv->nvmem_config_otp.size = OTP_SIZE_BYTES;
396 
397 	priv->nvmem_otp = devm_nvmem_register(&aux_dev->dev,
398 					      &priv->nvmem_config_otp);
399 	if (IS_ERR(priv->nvmem_otp))
400 		return PTR_ERR(priv->nvmem_otp);
401 
402 	return ret;
403 }
404 
pci1xxxx_otp_eeprom_remove(struct auxiliary_device * aux_dev)405 static void pci1xxxx_otp_eeprom_remove(struct auxiliary_device *aux_dev)
406 {
407 	struct pci1xxxx_otp_eeprom_device *priv;
408 	void __iomem *sys_lock;
409 
410 	priv = dev_get_drvdata(&aux_dev->dev);
411 	sys_lock = priv->reg_base + MMAP_CFG_OFFSET(CFG_SYS_LOCK_OFFSET);
412 	writel(CFG_SYS_LOCK_PF3, sys_lock);
413 
414 	/* Shut down OTP */
415 	writel(OTP_PWR_DN_BIT,
416 	       priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
417 
418 	writel(0, sys_lock);
419 }
420 
421 static const struct auxiliary_device_id pci1xxxx_otp_eeprom_auxiliary_id_table[] = {
422 	{.name = "mchp_pci1xxxx_gp.gp_otp_e2p"},
423 	{},
424 };
425 MODULE_DEVICE_TABLE(auxiliary, pci1xxxx_otp_eeprom_auxiliary_id_table);
426 
427 static struct auxiliary_driver pci1xxxx_otp_eeprom_driver = {
428 	.driver = {
429 		.name = AUX_DRIVER_NAME,
430 	},
431 	.probe = pci1xxxx_otp_eeprom_probe,
432 	.remove = pci1xxxx_otp_eeprom_remove,
433 	.id_table = pci1xxxx_otp_eeprom_auxiliary_id_table
434 };
435 module_auxiliary_driver(pci1xxxx_otp_eeprom_driver);
436 
437 MODULE_LICENSE("GPL");
438 MODULE_AUTHOR("Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>");
439 MODULE_AUTHOR("Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>");
440 MODULE_AUTHOR("Vaibhaav Ram T.L <vaibhaavram.tl@microchip.com>");
441 MODULE_DESCRIPTION("Microchip Technology Inc. PCI1xxxx OTP EEPROM Programmer");
442