1 /* 2 * Copyright (C) 2015 Toradex AG. 3 * 4 * Author: Sanchayan Maity <sanchayan.maity@toradex.com> 5 * 6 * Based on the barebox ocotp driver, 7 * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il> 8 * Orex Computed Radiography 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 and 12 * only version 2 as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 */ 19 20 #include <linux/clk.h> 21 #include <linux/delay.h> 22 #include <linux/device.h> 23 #include <linux/io.h> 24 #include <linux/module.h> 25 #include <linux/nvmem-provider.h> 26 #include <linux/of.h> 27 #include <linux/platform_device.h> 28 #include <linux/slab.h> 29 30 /* OCOTP Register Offsets */ 31 #define OCOTP_CTRL_REG 0x00 32 #define OCOTP_CTRL_SET 0x04 33 #define OCOTP_CTRL_CLR 0x08 34 #define OCOTP_TIMING 0x10 35 #define OCOTP_DATA 0x20 36 #define OCOTP_READ_CTRL_REG 0x30 37 #define OCOTP_READ_FUSE_DATA 0x40 38 39 /* OCOTP Register bits and masks */ 40 #define OCOTP_CTRL_WR_UNLOCK 16 41 #define OCOTP_CTRL_WR_UNLOCK_KEY 0x3E77 42 #define OCOTP_CTRL_WR_UNLOCK_MASK GENMASK(31, 16) 43 #define OCOTP_CTRL_ADDR 0 44 #define OCOTP_CTRL_ADDR_MASK GENMASK(6, 0) 45 #define OCOTP_CTRL_RELOAD_SHADOWS BIT(10) 46 #define OCOTP_CTRL_ERR BIT(9) 47 #define OCOTP_CTRL_BUSY BIT(8) 48 49 #define OCOTP_TIMING_STROBE_READ 16 50 #define OCOTP_TIMING_STROBE_READ_MASK GENMASK(21, 16) 51 #define OCOTP_TIMING_RELAX 12 52 #define OCOTP_TIMING_RELAX_MASK GENMASK(15, 12) 53 #define OCOTP_TIMING_STROBE_PROG 0 54 #define OCOTP_TIMING_STROBE_PROG_MASK GENMASK(11, 0) 55 56 #define OCOTP_READ_CTRL_READ_FUSE 0x1 57 58 #define VF610_OCOTP_TIMEOUT 100000 59 60 #define BF(value, field) (((value) << field) & field##_MASK) 61 62 #define DEF_RELAX 20 63 64 static const int base_to_fuse_addr_mappings[][2] = { 65 {0x400, 0x00}, 66 {0x410, 0x01}, 67 {0x420, 0x02}, 68 {0x450, 0x05}, 69 {0x4F0, 0x0F}, 70 {0x600, 0x20}, 71 {0x610, 0x21}, 72 {0x620, 0x22}, 73 {0x630, 0x23}, 74 {0x640, 0x24}, 75 {0x650, 0x25}, 76 {0x660, 0x26}, 77 {0x670, 0x27}, 78 {0x6F0, 0x2F}, 79 {0x880, 0x38}, 80 {0x890, 0x39}, 81 {0x8A0, 0x3A}, 82 {0x8B0, 0x3B}, 83 {0x8C0, 0x3C}, 84 {0x8D0, 0x3D}, 85 {0x8E0, 0x3E}, 86 {0x8F0, 0x3F}, 87 {0xC80, 0x78}, 88 {0xC90, 0x79}, 89 {0xCA0, 0x7A}, 90 {0xCB0, 0x7B}, 91 {0xCC0, 0x7C}, 92 {0xCD0, 0x7D}, 93 {0xCE0, 0x7E}, 94 {0xCF0, 0x7F}, 95 }; 96 97 struct vf610_ocotp { 98 void __iomem *base; 99 struct clk *clk; 100 struct device *dev; 101 struct nvmem_device *nvmem; 102 int timing; 103 }; 104 105 static int vf610_ocotp_wait_busy(void __iomem *base) 106 { 107 int timeout = VF610_OCOTP_TIMEOUT; 108 109 while ((readl(base) & OCOTP_CTRL_BUSY) && --timeout) 110 udelay(10); 111 112 if (!timeout) { 113 writel(OCOTP_CTRL_ERR, base + OCOTP_CTRL_CLR); 114 return -ETIMEDOUT; 115 } 116 117 udelay(10); 118 119 return 0; 120 } 121 122 static int vf610_ocotp_calculate_timing(struct vf610_ocotp *ocotp_dev) 123 { 124 u32 clk_rate; 125 u32 relax, strobe_read, strobe_prog; 126 u32 timing; 127 128 clk_rate = clk_get_rate(ocotp_dev->clk); 129 130 /* Refer section OTP read/write timing parameters in TRM */ 131 relax = clk_rate / (1000000000 / DEF_RELAX) - 1; 132 strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; 133 strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; 134 135 timing = BF(relax, OCOTP_TIMING_RELAX); 136 timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ); 137 timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG); 138 139 return timing; 140 } 141 142 static int vf610_get_fuse_address(int base_addr_offset) 143 { 144 int i; 145 146 for (i = 0; i < ARRAY_SIZE(base_to_fuse_addr_mappings); i++) { 147 if (base_to_fuse_addr_mappings[i][0] == base_addr_offset) 148 return base_to_fuse_addr_mappings[i][1]; 149 } 150 151 return -EINVAL; 152 } 153 154 static int vf610_ocotp_read(void *context, unsigned int offset, 155 void *val, size_t bytes) 156 { 157 struct vf610_ocotp *ocotp = context; 158 void __iomem *base = ocotp->base; 159 u32 reg, *buf = val; 160 int fuse_addr; 161 int ret; 162 163 while (bytes > 0) { 164 fuse_addr = vf610_get_fuse_address(offset); 165 if (fuse_addr > 0) { 166 writel(ocotp->timing, base + OCOTP_TIMING); 167 ret = vf610_ocotp_wait_busy(base + OCOTP_CTRL_REG); 168 if (ret) 169 return ret; 170 171 reg = readl(base + OCOTP_CTRL_REG); 172 reg &= ~OCOTP_CTRL_ADDR_MASK; 173 reg &= ~OCOTP_CTRL_WR_UNLOCK_MASK; 174 reg |= BF(fuse_addr, OCOTP_CTRL_ADDR); 175 writel(reg, base + OCOTP_CTRL_REG); 176 177 writel(OCOTP_READ_CTRL_READ_FUSE, 178 base + OCOTP_READ_CTRL_REG); 179 ret = vf610_ocotp_wait_busy(base + OCOTP_CTRL_REG); 180 if (ret) 181 return ret; 182 183 if (readl(base) & OCOTP_CTRL_ERR) { 184 dev_dbg(ocotp->dev, "Error reading from fuse address %x\n", 185 fuse_addr); 186 writel(OCOTP_CTRL_ERR, base + OCOTP_CTRL_CLR); 187 } 188 189 /* 190 * In case of error, we do not abort and expect to read 191 * 0xBADABADA as mentioned by the TRM. We just read this 192 * value and return. 193 */ 194 *buf = readl(base + OCOTP_READ_FUSE_DATA); 195 } else { 196 *buf = 0; 197 } 198 199 buf++; 200 bytes -= 4; 201 offset += 4; 202 } 203 204 return 0; 205 } 206 207 static struct nvmem_config ocotp_config = { 208 .name = "ocotp", 209 .stride = 4, 210 .word_size = 4, 211 .reg_read = vf610_ocotp_read, 212 }; 213 214 static const struct of_device_id ocotp_of_match[] = { 215 { .compatible = "fsl,vf610-ocotp", }, 216 {/* sentinel */}, 217 }; 218 MODULE_DEVICE_TABLE(of, ocotp_of_match); 219 220 static int vf610_ocotp_remove(struct platform_device *pdev) 221 { 222 struct vf610_ocotp *ocotp_dev = platform_get_drvdata(pdev); 223 224 return nvmem_unregister(ocotp_dev->nvmem); 225 } 226 227 static int vf610_ocotp_probe(struct platform_device *pdev) 228 { 229 struct device *dev = &pdev->dev; 230 struct resource *res; 231 struct vf610_ocotp *ocotp_dev; 232 233 ocotp_dev = devm_kzalloc(&pdev->dev, 234 sizeof(struct vf610_ocotp), GFP_KERNEL); 235 if (!ocotp_dev) 236 return -ENOMEM; 237 238 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 239 ocotp_dev->base = devm_ioremap_resource(dev, res); 240 if (IS_ERR(ocotp_dev->base)) 241 return PTR_ERR(ocotp_dev->base); 242 243 ocotp_dev->clk = devm_clk_get(dev, NULL); 244 if (IS_ERR(ocotp_dev->clk)) { 245 dev_err(dev, "failed getting clock, err = %ld\n", 246 PTR_ERR(ocotp_dev->clk)); 247 return PTR_ERR(ocotp_dev->clk); 248 } 249 250 ocotp_config.size = resource_size(res); 251 ocotp_config.priv = ocotp_dev; 252 ocotp_config.dev = dev; 253 254 ocotp_dev->nvmem = nvmem_register(&ocotp_config); 255 if (IS_ERR(ocotp_dev->nvmem)) 256 return PTR_ERR(ocotp_dev->nvmem); 257 258 ocotp_dev->dev = dev; 259 platform_set_drvdata(pdev, ocotp_dev); 260 261 ocotp_dev->timing = vf610_ocotp_calculate_timing(ocotp_dev); 262 263 return 0; 264 } 265 266 static struct platform_driver vf610_ocotp_driver = { 267 .probe = vf610_ocotp_probe, 268 .remove = vf610_ocotp_remove, 269 .driver = { 270 .name = "vf610-ocotp", 271 .of_match_table = ocotp_of_match, 272 }, 273 }; 274 module_platform_driver(vf610_ocotp_driver); 275 MODULE_AUTHOR("Sanchayan Maity <sanchayan.maity@toradex.com>"); 276 MODULE_DESCRIPTION("Vybrid OCOTP driver"); 277 MODULE_LICENSE("GPL v2"); 278