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