1// SPDX-License-Identifier: GPL-2.0 2 3#include <linux/iopoll.h> 4#include <linux/module.h> 5#include <linux/nvmem-provider.h> 6#include <linux/of.h> 7#include <linux/platform_device.h> 8 9#define OTP_OTP_PWR_DN(t) (t + 0x00) 10#define OTP_OTP_PWR_DN_OTP_PWRDN_N BIT(0) 11#define OTP_OTP_ADDR_HI(t) (t + 0x04) 12#define OTP_OTP_ADDR_LO(t) (t + 0x08) 13#define OTP_OTP_PRGM_DATA(t) (t + 0x10) 14#define OTP_OTP_PRGM_MODE(t) (t + 0x14) 15#define OTP_OTP_PRGM_MODE_OTP_PGM_MODE_BYTE BIT(0) 16#define OTP_OTP_RD_DATA(t) (t + 0x18) 17#define OTP_OTP_FUNC_CMD(t) (t + 0x20) 18#define OTP_OTP_FUNC_CMD_OTP_PROGRAM BIT(1) 19#define OTP_OTP_FUNC_CMD_OTP_READ BIT(0) 20#define OTP_OTP_CMD_GO(t) (t + 0x28) 21#define OTP_OTP_CMD_GO_OTP_GO BIT(0) 22#define OTP_OTP_PASS_FAIL(t) (t + 0x2c) 23#define OTP_OTP_PASS_FAIL_OTP_READ_PROHIBITED BIT(3) 24#define OTP_OTP_PASS_FAIL_OTP_WRITE_PROHIBITED BIT(2) 25#define OTP_OTP_PASS_FAIL_OTP_FAIL BIT(0) 26#define OTP_OTP_STATUS(t) (t + 0x30) 27#define OTP_OTP_STATUS_OTP_CPUMPEN BIT(1) 28#define OTP_OTP_STATUS_OTP_BUSY BIT(0) 29 30#define OTP_MEM_SIZE 8192 31#define OTP_SLEEP_US 10 32#define OTP_TIMEOUT_US 500000 33 34struct lan9662_otp { 35 struct device *dev; 36 void __iomem *base; 37}; 38 39static int lan9662_otp_wait_flag_clear(void __iomem *reg, u32 flag) 40{ 41 u32 val; 42 43 return readl_poll_timeout(reg, val, !(val & flag), 44 OTP_SLEEP_US, OTP_TIMEOUT_US); 45} 46 47static int lan9662_otp_power(struct lan9662_otp *otp, bool up) 48{ 49 void __iomem *pwrdn = OTP_OTP_PWR_DN(otp->base); 50 51 if (up) { 52 writel(readl(pwrdn) & ~OTP_OTP_PWR_DN_OTP_PWRDN_N, pwrdn); 53 if (lan9662_otp_wait_flag_clear(OTP_OTP_STATUS(otp->base), 54 OTP_OTP_STATUS_OTP_CPUMPEN)) 55 return -ETIMEDOUT; 56 } else { 57 writel(readl(pwrdn) | OTP_OTP_PWR_DN_OTP_PWRDN_N, pwrdn); 58 } 59 60 return 0; 61} 62 63static int lan9662_otp_execute(struct lan9662_otp *otp) 64{ 65 if (lan9662_otp_wait_flag_clear(OTP_OTP_CMD_GO(otp->base), 66 OTP_OTP_CMD_GO_OTP_GO)) 67 return -ETIMEDOUT; 68 69 if (lan9662_otp_wait_flag_clear(OTP_OTP_STATUS(otp->base), 70 OTP_OTP_STATUS_OTP_BUSY)) 71 return -ETIMEDOUT; 72 73 return 0; 74} 75 76static void lan9662_otp_set_address(struct lan9662_otp *otp, u32 offset) 77{ 78 writel(0xff & (offset >> 8), OTP_OTP_ADDR_HI(otp->base)); 79 writel(0xff & offset, OTP_OTP_ADDR_LO(otp->base)); 80} 81 82static int lan9662_otp_read_byte(struct lan9662_otp *otp, u32 offset, u8 *dst) 83{ 84 u32 pass; 85 int rc; 86 87 lan9662_otp_set_address(otp, offset); 88 writel(OTP_OTP_FUNC_CMD_OTP_READ, OTP_OTP_FUNC_CMD(otp->base)); 89 writel(OTP_OTP_CMD_GO_OTP_GO, OTP_OTP_CMD_GO(otp->base)); 90 rc = lan9662_otp_execute(otp); 91 if (!rc) { 92 pass = readl(OTP_OTP_PASS_FAIL(otp->base)); 93 if (pass & OTP_OTP_PASS_FAIL_OTP_READ_PROHIBITED) 94 return -EACCES; 95 *dst = (u8) readl(OTP_OTP_RD_DATA(otp->base)); 96 } 97 return rc; 98} 99 100static int lan9662_otp_write_byte(struct lan9662_otp *otp, u32 offset, u8 data) 101{ 102 u32 pass; 103 int rc; 104 105 lan9662_otp_set_address(otp, offset); 106 writel(OTP_OTP_PRGM_MODE_OTP_PGM_MODE_BYTE, OTP_OTP_PRGM_MODE(otp->base)); 107 writel(data, OTP_OTP_PRGM_DATA(otp->base)); 108 writel(OTP_OTP_FUNC_CMD_OTP_PROGRAM, OTP_OTP_FUNC_CMD(otp->base)); 109 writel(OTP_OTP_CMD_GO_OTP_GO, OTP_OTP_CMD_GO(otp->base)); 110 111 rc = lan9662_otp_execute(otp); 112 if (!rc) { 113 pass = readl(OTP_OTP_PASS_FAIL(otp->base)); 114 if (pass & OTP_OTP_PASS_FAIL_OTP_WRITE_PROHIBITED) 115 return -EACCES; 116 if (pass & OTP_OTP_PASS_FAIL_OTP_FAIL) 117 return -EIO; 118 } 119 return rc; 120} 121 122static int lan9662_otp_read(void *context, unsigned int offset, 123 void *_val, size_t bytes) 124{ 125 struct lan9662_otp *otp = context; 126 u8 *val = _val; 127 uint8_t data; 128 int i, rc = 0; 129 130 lan9662_otp_power(otp, true); 131 for (i = 0; i < bytes; i++) { 132 rc = lan9662_otp_read_byte(otp, offset + i, &data); 133 if (rc < 0) 134 break; 135 *val++ = data; 136 } 137 lan9662_otp_power(otp, false); 138 139 return rc; 140} 141 142static int lan9662_otp_write(void *context, unsigned int offset, 143 void *_val, size_t bytes) 144{ 145 struct lan9662_otp *otp = context; 146 u8 *val = _val; 147 u8 data, newdata; 148 int i, rc = 0; 149 150 lan9662_otp_power(otp, true); 151 for (i = 0; i < bytes; i++) { 152 /* Skip zero bytes */ 153 if (val[i]) { 154 rc = lan9662_otp_read_byte(otp, offset + i, &data); 155 if (rc < 0) 156 break; 157 158 newdata = data | val[i]; 159 if (newdata == data) 160 continue; 161 162 rc = lan9662_otp_write_byte(otp, offset + i, 163 newdata); 164 if (rc < 0) 165 break; 166 } 167 } 168 lan9662_otp_power(otp, false); 169 170 return rc; 171} 172 173static struct nvmem_config otp_config = { 174 .name = "lan9662-otp", 175 .stride = 1, 176 .word_size = 1, 177 .reg_read = lan9662_otp_read, 178 .reg_write = lan9662_otp_write, 179 .size = OTP_MEM_SIZE, 180}; 181 182static int lan9662_otp_probe(struct platform_device *pdev) 183{ 184 struct device *dev = &pdev->dev; 185 struct nvmem_device *nvmem; 186 struct lan9662_otp *otp; 187 188 otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL); 189 if (!otp) 190 return -ENOMEM; 191 192 otp->dev = dev; 193 otp->base = devm_platform_ioremap_resource(pdev, 0); 194 if (IS_ERR(otp->base)) 195 return PTR_ERR(otp->base); 196 197 otp_config.priv = otp; 198 otp_config.dev = dev; 199 200 nvmem = devm_nvmem_register(dev, &otp_config); 201 202 return PTR_ERR_OR_ZERO(nvmem); 203} 204 205static const struct of_device_id lan9662_otp_match[] = { 206 { .compatible = "microchip,lan9662-otpc", }, 207 { }, 208}; 209MODULE_DEVICE_TABLE(of, lan9662_otp_match); 210 211static struct platform_driver lan9662_otp_driver = { 212 .probe = lan9662_otp_probe, 213 .driver = { 214 .name = "lan9662-otp", 215 .of_match_table = lan9662_otp_match, 216 }, 217}; 218module_platform_driver(lan9662_otp_driver); 219 220MODULE_AUTHOR("Horatiu Vultur <horatiu.vultur@microchip.com>"); 221MODULE_DESCRIPTION("lan9662 OTP driver"); 222MODULE_LICENSE("GPL"); 223