Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / misc / mchp_pci1xxxx / mchp_pci1xxxx_otpe2p.c
bloba2ed477e0370bc08ebf71085cb083720e7bbcf5f
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2022-2023 Microchip Technology Inc.
3 // PCI1xxxx OTP/EEPROM driver
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>
11 #include "mchp_pci1xxxx_gp.h"
13 #define AUX_DRIVER_NAME "PCI1xxxxOTPE2P"
14 #define EEPROM_NAME "pci1xxxx_eeprom"
15 #define OTP_NAME "pci1xxxx_otp"
17 #define PERI_PF3_SYSTEM_REG_ADDR_BASE 0x2000
18 #define PERI_PF3_SYSTEM_REG_LENGTH 0x4000
20 #define EEPROM_SIZE_BYTES 8192
21 #define OTP_SIZE_BYTES 8192
23 #define CONFIG_REG_ADDR_BASE 0
24 #define EEPROM_REG_ADDR_BASE 0x0E00
25 #define OTP_REG_ADDR_BASE 0x1000
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))
31 #define EEPROM_CMD_REG 0x00
32 #define EEPROM_DATA_REG 0x04
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)
38 #define STATUS_READ_DELAY_US 1
39 #define STATUS_READ_TIMEOUT_US 20000
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
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)
58 #define OTP_PWR_DN_BIT BIT(0)
59 #define OTP_PWR_DN_OFFSET 0x00
61 #define CFG_SYS_LOCK_OFFSET 0xA0
62 #define CFG_SYS_LOCK_PF3 BIT(5)
64 #define BYTE_LOW (GENMASK(7, 0))
65 #define BYTE_HIGH (GENMASK(12, 8))
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;
76 static int set_sys_lock(struct pci1xxxx_otp_eeprom_device *priv)
78 void __iomem *sys_lock = priv->reg_base +
79 MMAP_CFG_OFFSET(CFG_SYS_LOCK_OFFSET);
80 u8 data;
82 writel(CFG_SYS_LOCK_PF3, sys_lock);
83 data = readl(sys_lock);
84 if (data != CFG_SYS_LOCK_PF3)
85 return -EPERM;
87 return 0;
90 static void release_sys_lock(struct pci1xxxx_otp_eeprom_device *priv)
92 void __iomem *sys_lock = priv->reg_base +
93 MMAP_CFG_OFFSET(CFG_SYS_LOCK_OFFSET);
94 writel(0, sys_lock);
97 static bool is_eeprom_responsive(struct pci1xxxx_otp_eeprom_device *priv)
99 void __iomem *rb = priv->reg_base;
100 u32 regval;
101 int ret;
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));
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));
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;
117 return true;
120 static int pci1xxxx_eeprom_read(void *priv_t, unsigned int off,
121 void *buf_t, size_t count)
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;
130 if (off >= priv->nvmem_config_eeprom.size)
131 return -EFAULT;
133 if ((off + count) > priv->nvmem_config_eeprom.size)
134 count = priv->nvmem_config_eeprom.size - off;
136 ret = set_sys_lock(priv);
137 if (ret)
138 return ret;
140 for (byte = 0; byte < count; byte++) {
141 writel(EEPROM_CMD_EPC_BUSY_BIT | (off + byte), rb +
142 MMAP_EEPROM_OFFSET(EEPROM_CMD_REG));
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;
154 buf[byte] = readl(rb + MMAP_EEPROM_OFFSET(EEPROM_DATA_REG));
156 error:
157 release_sys_lock(priv);
158 return ret;
161 static int pci1xxxx_eeprom_write(void *priv_t, unsigned int off,
162 void *value_t, size_t count)
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;
171 if (off >= priv->nvmem_config_eeprom.size)
172 return -EFAULT;
174 if ((off + count) > priv->nvmem_config_eeprom.size)
175 count = priv->nvmem_config_eeprom.size - off;
177 ret = set_sys_lock(priv);
178 if (ret)
179 return ret;
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));
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;
199 error:
200 release_sys_lock(priv);
201 return ret;
204 static void otp_device_set_address(struct pci1xxxx_otp_eeprom_device *priv,
205 u16 address)
207 u16 lo, hi;
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));
215 static int pci1xxxx_otp_read(void *priv_t, unsigned int off,
216 void *buf_t, size_t count)
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;
226 if (off >= priv->nvmem_config_otp.size)
227 return -EFAULT;
229 if ((off + count) > priv->nvmem_config_otp.size)
230 count = priv->nvmem_config_otp.size - off;
232 ret = set_sys_lock(priv);
233 if (ret)
234 return ret;
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));
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));
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;
257 buf[byte] = readl(rb + MMAP_OTP_OFFSET(OTP_RD_DATA_OFFSET));
259 error:
260 release_sys_lock(priv);
261 return ret;
264 static int pci1xxxx_otp_write(void *priv_t, unsigned int off,
265 void *value_t, size_t count)
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;
275 if (off >= priv->nvmem_config_otp.size)
276 return -EFAULT;
278 if ((off + count) > priv->nvmem_config_otp.size)
279 count = priv->nvmem_config_otp.size - off;
281 ret = set_sys_lock(priv);
282 if (ret)
283 return ret;
285 for (byte = 0; byte < count; byte++) {
286 otp_device_set_address(priv, (u16)(off + byte));
289 * Set OTP_PGM_MODE_BYTE command bit in OTP_PRGM_MODE register
290 * to enable Byte programming
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));
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));
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;
315 error:
316 release_sys_lock(priv);
317 return ret;
320 static int pci1xxxx_otp_eeprom_probe(struct auxiliary_device *aux_dev,
321 const struct auxiliary_device_id *id)
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;
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;
335 priv = devm_kzalloc(&aux_dev->dev, sizeof(*priv), GFP_KERNEL);
336 if (!priv)
337 return -ENOMEM;
339 priv->pdev = aux_dev;
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;
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;
353 ret = set_sys_lock(priv);
354 if (ret)
355 return ret;
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));
362 dev_set_drvdata(&aux_dev->dev, priv);
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;
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);
383 release_sys_lock(priv);
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;
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);
402 return ret;
405 static void pci1xxxx_otp_eeprom_remove(struct auxiliary_device *aux_dev)
407 struct pci1xxxx_otp_eeprom_device *priv;
408 void __iomem *sys_lock;
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);
414 /* Shut down OTP */
415 writel(OTP_PWR_DN_BIT,
416 priv->reg_base + MMAP_OTP_OFFSET(OTP_PWR_DN_OFFSET));
418 writel(0, sys_lock);
421 static const struct auxiliary_device_id pci1xxxx_otp_eeprom_auxiliary_id_table[] = {
422 {.name = "mchp_pci1xxxx_gp.gp_otp_e2p"},
425 MODULE_DEVICE_TABLE(auxiliary, pci1xxxx_otp_eeprom_auxiliary_id_table);
427 static struct auxiliary_driver pci1xxxx_otp_eeprom_driver = {
428 .driver = {
429 .name = AUX_DRIVER_NAME,
431 .probe = pci1xxxx_otp_eeprom_probe,
432 .remove = pci1xxxx_otp_eeprom_remove,
433 .id_table = pci1xxxx_otp_eeprom_auxiliary_id_table
435 module_auxiliary_driver(pci1xxxx_otp_eeprom_driver);
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");