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
67struct 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
76static 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, addr: sys_lock);
83 data = readl(addr: sys_lock);
84 if (data != CFG_SYS_LOCK_PF3)
85 return -EPERM;
86
87 return 0;
88}
89
90static 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(val: 0, addr: sys_lock);
95}
96
97static 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 addr: rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
105 writel(EEPROM_CMD_EPC_BUSY_BIT,
106 addr: 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
120static 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), addr: 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(addr: rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
155 }
156 ret = byte;
157error:
158 release_sys_lock(priv);
159 return ret;
160}
161
162static int pci1xxxx_eeprom_write(void *priv_t, unsigned int off,
163 void *value_t, size_t count)
164{
165 struct pci1xxxx_otp_eeprom_device *priv = priv_t;
166 void __iomem *rb = priv->reg_base;
167 char *value = value_t;
168 u32 regval;
169 u32 byte;
170 int ret;
171
172 if (off >= priv->nvmem_config_eeprom.size)
173 return -EFAULT;
174
175 if ((off + count) > priv->nvmem_config_eeprom.size)
176 count = priv->nvmem_config_eeprom.size - off;
177
178 ret = set_sys_lock(priv);
179 if (ret)
180 return ret;
181
182 for (byte = 0; byte < count; byte++) {
183 writel(val: *(value + byte), addr: rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
184 regval = EEPROM_CMD_EPC_TIMEOUT_BIT | EEPROM_CMD_EPC_WRITE |
185 (off + byte);
186 writel(val: regval, addr: rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
187 writel(EEPROM_CMD_EPC_BUSY_BIT | regval,
188 addr: rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
189
190 ret = read_poll_timeout(readl, regval,
191 !(regval & EEPROM_CMD_EPC_BUSY_BIT),
192 STATUS_READ_DELAY_US,
193 STATUS_READ_TIMEOUT_US, true,
194 rb + MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
195 if (ret < 0 || (!ret && (regval & EEPROM_CMD_EPC_TIMEOUT_BIT))) {
196 ret = -EIO;
197 goto error;
198 }
199 }
200 ret = byte;
201error:
202 release_sys_lock(priv);
203 return ret;
204}
205
206static void otp_device_set_address(struct pci1xxxx_otp_eeprom_device *priv,
207 u16 address)
208{
209 u16 lo, hi;
210
211 lo = address & BYTE_LOW;
212 hi = (address & BYTE_HIGH) >> 8;
213 writew(val: lo, addr: priv->reg_base + MMAP_OTP_OFFSET(OTP_ADDR_LOW_OFFSET));
214 writew(val: hi, addr: priv->reg_base + MMAP_OTP_OFFSET(OTP_ADDR_HIGH_OFFSET));
215}
216
217static int pci1xxxx_otp_read(void *priv_t, unsigned int off,
218 void *buf_t, size_t count)
219{
220 struct pci1xxxx_otp_eeprom_device *priv = priv_t;
221 void __iomem *rb = priv->reg_base;
222 char *buf = buf_t;
223 u32 regval;
224 u32 byte;
225 int ret;
226 u8 data;
227
228 if (off >= priv->nvmem_config_otp.size)
229 return -EFAULT;
230
231 if ((off + count) > priv->nvmem_config_otp.size)
232 count = priv->nvmem_config_otp.size - off;
233
234 ret = set_sys_lock(priv);
235 if (ret)
236 return ret;
237
238 for (byte = 0; byte < count; byte++) {
239 otp_device_set_address(priv, address: (u16)(off + byte));
240 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
241 writel(val: data | OTP_FUNC_RD_BIT,
242 addr: rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
243 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
244 writel(val: data | OTP_CMD_GO_BIT,
245 addr: rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
246
247 ret = read_poll_timeout(readl, regval,
248 !(regval & OTP_STATUS_BUSY_BIT),
249 STATUS_READ_DELAY_US,
250 STATUS_READ_TIMEOUT_US, true,
251 rb + MMAP_OTP_OFFSET(OTP_STATUS_OFFSET));
252
253 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_PASS_FAIL_OFFSET));
254 if (ret < 0 || data & OTP_FAIL_BIT) {
255 ret = -EIO;
256 goto error;
257 }
258
259 buf[byte] = readl(addr: rb + MMAP_OTP_OFFSET(OTP_RD_DATA_OFFSET));
260 }
261 ret = byte;
262error:
263 release_sys_lock(priv);
264 return ret;
265}
266
267static int pci1xxxx_otp_write(void *priv_t, unsigned int off,
268 void *value_t, size_t count)
269{
270 struct pci1xxxx_otp_eeprom_device *priv = priv_t;
271 void __iomem *rb = priv->reg_base;
272 char *value = value_t;
273 u32 regval;
274 u32 byte;
275 int ret;
276 u8 data;
277
278 if (off >= priv->nvmem_config_otp.size)
279 return -EFAULT;
280
281 if ((off + count) > priv->nvmem_config_otp.size)
282 count = priv->nvmem_config_otp.size - off;
283
284 ret = set_sys_lock(priv);
285 if (ret)
286 return ret;
287
288 for (byte = 0; byte < count; byte++) {
289 otp_device_set_address(priv, address: (u16)(off + byte));
290
291 /*
292 * Set OTP_PGM_MODE_BYTE command bit in OTP_PRGM_MODE register
293 * to enable Byte programming
294 */
295 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_PRGM_MODE_OFFSET));
296 writel(val: data | OTP_PGM_MODE_BYTE_BIT,
297 addr: rb + MMAP_OTP_OFFSET(OTP_PRGM_MODE_OFFSET));
298 writel(val: *(value + byte), addr: rb + MMAP_OTP_OFFSET(OTP_PRGM_DATA_OFFSET));
299 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
300 writel(val: data | OTP_FUNC_PGM_BIT,
301 addr: rb + MMAP_OTP_OFFSET(OTP_FUNC_CMD_OFFSET));
302 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
303 writel(val: data | OTP_CMD_GO_BIT,
304 addr: rb + MMAP_OTP_OFFSET(OTP_CMD_GO_OFFSET));
305
306 ret = read_poll_timeout(readl, regval,
307 !(regval & OTP_STATUS_BUSY_BIT),
308 STATUS_READ_DELAY_US,
309 STATUS_READ_TIMEOUT_US, true,
310 rb + MMAP_OTP_OFFSET(OTP_STATUS_OFFSET));
311
312 data = readl(addr: rb + MMAP_OTP_OFFSET(OTP_PASS_FAIL_OFFSET));
313 if (ret < 0 || data & OTP_FAIL_BIT) {
314 ret = -EIO;
315 goto error;
316 }
317 }
318 ret = byte;
319error:
320 release_sys_lock(priv);
321 return ret;
322}
323
324static int pci1xxxx_otp_eeprom_probe(struct auxiliary_device *aux_dev,
325 const struct auxiliary_device_id *id)
326{
327 struct auxiliary_device_wrapper *aux_dev_wrapper;
328 struct pci1xxxx_otp_eeprom_device *priv;
329 struct gp_aux_data_type *pdata;
330 int ret;
331 u8 data;
332
333 aux_dev_wrapper = container_of(aux_dev, struct auxiliary_device_wrapper,
334 aux_dev);
335 pdata = &aux_dev_wrapper->gp_aux_data;
336 if (!pdata)
337 return -EINVAL;
338
339 priv = devm_kzalloc(dev: &aux_dev->dev, size: sizeof(*priv), GFP_KERNEL);
340 if (!priv)
341 return -ENOMEM;
342
343 priv->pdev = aux_dev;
344
345 if (!devm_request_mem_region(&aux_dev->dev, pdata->region_start +
346 PERI_PF3_SYSTEM_REG_ADDR_BASE,
347 PERI_PF3_SYSTEM_REG_LENGTH,
348 aux_dev->name))
349 return -ENOMEM;
350
351 priv->reg_base = devm_ioremap(dev: &aux_dev->dev, offset: pdata->region_start +
352 PERI_PF3_SYSTEM_REG_ADDR_BASE,
353 PERI_PF3_SYSTEM_REG_LENGTH);
354 if (!priv->reg_base)
355 return -ENOMEM;
356
357 ret = set_sys_lock(priv);
358 if (ret)
359 return ret;
360
361 /* Set OTP_PWR_DN to 0 to make OTP Operational */
362 data = readl(addr: priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
363 writel(val: data & ~OTP_PWR_DN_BIT,
364 addr: priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
365
366 dev_set_drvdata(dev: &aux_dev->dev, data: priv);
367
368 if (is_eeprom_responsive(priv)) {
369 priv->nvmem_config_eeprom.type = NVMEM_TYPE_EEPROM;
370 priv->nvmem_config_eeprom.name = EEPROM_NAME;
371 priv->nvmem_config_eeprom.dev = &aux_dev->dev;
372 priv->nvmem_config_eeprom.owner = THIS_MODULE;
373 priv->nvmem_config_eeprom.reg_read = pci1xxxx_eeprom_read;
374 priv->nvmem_config_eeprom.reg_write = pci1xxxx_eeprom_write;
375 priv->nvmem_config_eeprom.priv = priv;
376 priv->nvmem_config_eeprom.stride = 1;
377 priv->nvmem_config_eeprom.word_size = 1;
378 priv->nvmem_config_eeprom.size = EEPROM_SIZE_BYTES;
379
380 priv->nvmem_eeprom = devm_nvmem_register(dev: &aux_dev->dev,
381 cfg: &priv->nvmem_config_eeprom);
382 if (IS_ERR(ptr: priv->nvmem_eeprom))
383 return PTR_ERR(ptr: priv->nvmem_eeprom);
384 }
385
386 release_sys_lock(priv);
387
388 priv->nvmem_config_otp.type = NVMEM_TYPE_OTP;
389 priv->nvmem_config_otp.name = OTP_NAME;
390 priv->nvmem_config_otp.dev = &aux_dev->dev;
391 priv->nvmem_config_otp.owner = THIS_MODULE;
392 priv->nvmem_config_otp.reg_read = pci1xxxx_otp_read;
393 priv->nvmem_config_otp.reg_write = pci1xxxx_otp_write;
394 priv->nvmem_config_otp.priv = priv;
395 priv->nvmem_config_otp.stride = 1;
396 priv->nvmem_config_otp.word_size = 1;
397 priv->nvmem_config_otp.size = OTP_SIZE_BYTES;
398
399 priv->nvmem_otp = devm_nvmem_register(dev: &aux_dev->dev,
400 cfg: &priv->nvmem_config_otp);
401 if (IS_ERR(ptr: priv->nvmem_otp))
402 return PTR_ERR(ptr: priv->nvmem_otp);
403
404 return ret;
405}
406
407static void pci1xxxx_otp_eeprom_remove(struct auxiliary_device *aux_dev)
408{
409 struct pci1xxxx_otp_eeprom_device *priv;
410 void __iomem *sys_lock;
411
412 priv = dev_get_drvdata(dev: &aux_dev->dev);
413 sys_lock = priv->reg_base + MMAP_CFG_OFFSET(CFG_SYS_LOCK_OFFSET);
414 writel(CFG_SYS_LOCK_PF3, addr: sys_lock);
415
416 /* Shut down OTP */
417 writel(OTP_PWR_DN_BIT,
418 addr: priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
419
420 writel(val: 0, addr: sys_lock);
421}
422
423static const struct auxiliary_device_id pci1xxxx_otp_eeprom_auxiliary_id_table[] = {
424 {.name = "mchp_pci1xxxx_gp.gp_otp_e2p"},
425 {},
426};
427MODULE_DEVICE_TABLE(auxiliary, pci1xxxx_otp_eeprom_auxiliary_id_table);
428
429static struct auxiliary_driver pci1xxxx_otp_eeprom_driver = {
430 .driver = {
431 .name = AUX_DRIVER_NAME,
432 },
433 .probe = pci1xxxx_otp_eeprom_probe,
434 .remove = pci1xxxx_otp_eeprom_remove,
435 .id_table = pci1xxxx_otp_eeprom_auxiliary_id_table
436};
437module_auxiliary_driver(pci1xxxx_otp_eeprom_driver);
438
439MODULE_LICENSE("GPL");
440MODULE_AUTHOR("Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>");
441MODULE_AUTHOR("Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>");
442MODULE_AUTHOR("Vaibhaav Ram T.L <vaibhaavram.tl@microchip.com>");
443MODULE_DESCRIPTION("Microchip Technology Inc. PCI1xxxx OTP EEPROM Programmer");
444

source code of linux/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_otpe2p.c