jz4780-efuse.c (6276B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * JZ4780 EFUSE Memory Support driver 4 * 5 * Copyright (c) 2017 PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com> 6 * Copyright (c) 2020 H. Nikolaus Schaller <hns@goldelico.com> 7 */ 8 9/* 10 * Currently supports JZ4780 efuse which has 8K programmable bit. 11 * Efuse is separated into seven segments as below: 12 * 13 * ----------------------------------------------------------------------- 14 * | 64 bit | 128 bit | 128 bit | 3520 bit | 8 bit | 2296 bit | 2048 bit | 15 * ----------------------------------------------------------------------- 16 * 17 * The rom itself is accessed using a 9 bit address line and an 8 word wide bus 18 * which reads/writes based on strobes. The strobe is configured in the config 19 * register and is based on number of cycles of the bus clock. 20 * 21 * Driver supports read only as the writes are done in the Factory. 22 */ 23 24#include <linux/bitops.h> 25#include <linux/clk.h> 26#include <linux/module.h> 27#include <linux/nvmem-provider.h> 28#include <linux/of.h> 29#include <linux/platform_device.h> 30#include <linux/regmap.h> 31#include <linux/timer.h> 32 33#define JZ_EFUCTRL (0x0) /* Control Register */ 34#define JZ_EFUCFG (0x4) /* Configure Register*/ 35#define JZ_EFUSTATE (0x8) /* Status Register */ 36#define JZ_EFUDATA(n) (0xC + (n) * 4) 37 38/* We read 32 byte chunks to avoid complexity in the driver. */ 39#define JZ_EFU_READ_SIZE 32 40 41#define EFUCTRL_ADDR_MASK 0x3FF 42#define EFUCTRL_ADDR_SHIFT 21 43#define EFUCTRL_LEN_MASK 0x1F 44#define EFUCTRL_LEN_SHIFT 16 45#define EFUCTRL_PG_EN BIT(15) 46#define EFUCTRL_WR_EN BIT(1) 47#define EFUCTRL_RD_EN BIT(0) 48 49#define EFUCFG_INT_EN BIT(31) 50#define EFUCFG_RD_ADJ_MASK 0xF 51#define EFUCFG_RD_ADJ_SHIFT 20 52#define EFUCFG_RD_STR_MASK 0xF 53#define EFUCFG_RD_STR_SHIFT 16 54#define EFUCFG_WR_ADJ_MASK 0xF 55#define EFUCFG_WR_ADJ_SHIFT 12 56#define EFUCFG_WR_STR_MASK 0xFFF 57#define EFUCFG_WR_STR_SHIFT 0 58 59#define EFUSTATE_WR_DONE BIT(1) 60#define EFUSTATE_RD_DONE BIT(0) 61 62struct jz4780_efuse { 63 struct device *dev; 64 struct regmap *map; 65 struct clk *clk; 66}; 67 68/* main entry point */ 69static int jz4780_efuse_read(void *context, unsigned int offset, 70 void *val, size_t bytes) 71{ 72 struct jz4780_efuse *efuse = context; 73 74 while (bytes > 0) { 75 size_t start = offset & ~(JZ_EFU_READ_SIZE - 1); 76 size_t chunk = min(bytes, (start + JZ_EFU_READ_SIZE) 77 - offset); 78 char buf[JZ_EFU_READ_SIZE]; 79 unsigned int tmp; 80 u32 ctrl; 81 int ret; 82 83 ctrl = (start << EFUCTRL_ADDR_SHIFT) 84 | ((JZ_EFU_READ_SIZE - 1) << EFUCTRL_LEN_SHIFT) 85 | EFUCTRL_RD_EN; 86 87 regmap_update_bits(efuse->map, JZ_EFUCTRL, 88 (EFUCTRL_ADDR_MASK << EFUCTRL_ADDR_SHIFT) | 89 (EFUCTRL_LEN_MASK << EFUCTRL_LEN_SHIFT) | 90 EFUCTRL_PG_EN | EFUCTRL_WR_EN | 91 EFUCTRL_RD_EN, 92 ctrl); 93 94 ret = regmap_read_poll_timeout(efuse->map, JZ_EFUSTATE, 95 tmp, tmp & EFUSTATE_RD_DONE, 96 1 * MSEC_PER_SEC, 97 50 * MSEC_PER_SEC); 98 if (ret < 0) { 99 dev_err(efuse->dev, "Time out while reading efuse data"); 100 return ret; 101 } 102 103 ret = regmap_bulk_read(efuse->map, JZ_EFUDATA(0), 104 buf, JZ_EFU_READ_SIZE / sizeof(u32)); 105 if (ret < 0) 106 return ret; 107 108 memcpy(val, &buf[offset - start], chunk); 109 110 val += chunk; 111 offset += chunk; 112 bytes -= chunk; 113 } 114 115 return 0; 116} 117 118static struct nvmem_config jz4780_efuse_nvmem_config = { 119 .name = "jz4780-efuse", 120 .size = 1024, 121 .word_size = 1, 122 .stride = 1, 123 .owner = THIS_MODULE, 124 .reg_read = jz4780_efuse_read, 125}; 126 127static const struct regmap_config jz4780_efuse_regmap_config = { 128 .reg_bits = 32, 129 .val_bits = 32, 130 .reg_stride = 4, 131 .max_register = JZ_EFUDATA(7), 132}; 133 134static void clk_disable_unprepare_helper(void *clock) 135{ 136 clk_disable_unprepare(clock); 137} 138 139static int jz4780_efuse_probe(struct platform_device *pdev) 140{ 141 struct nvmem_device *nvmem; 142 struct jz4780_efuse *efuse; 143 struct nvmem_config cfg; 144 unsigned long clk_rate; 145 unsigned long rd_adj; 146 unsigned long rd_strobe; 147 struct device *dev = &pdev->dev; 148 void __iomem *regs; 149 int ret; 150 151 efuse = devm_kzalloc(dev, sizeof(*efuse), GFP_KERNEL); 152 if (!efuse) 153 return -ENOMEM; 154 155 regs = devm_platform_ioremap_resource(pdev, 0); 156 if (IS_ERR(regs)) 157 return PTR_ERR(regs); 158 159 efuse->map = devm_regmap_init_mmio(dev, regs, 160 &jz4780_efuse_regmap_config); 161 if (IS_ERR(efuse->map)) 162 return PTR_ERR(efuse->map); 163 164 efuse->clk = devm_clk_get(&pdev->dev, NULL); 165 if (IS_ERR(efuse->clk)) 166 return PTR_ERR(efuse->clk); 167 168 ret = clk_prepare_enable(efuse->clk); 169 if (ret < 0) 170 return ret; 171 172 ret = devm_add_action_or_reset(&pdev->dev, 173 clk_disable_unprepare_helper, 174 efuse->clk); 175 if (ret < 0) 176 return ret; 177 178 clk_rate = clk_get_rate(efuse->clk); 179 180 efuse->dev = dev; 181 182 /* 183 * rd_adj and rd_strobe are 4 bit values 184 * conditions: 185 * bus clk_period * (rd_adj + 1) > 6.5ns 186 * bus clk_period * (rd_adj + 5 + rd_strobe) > 35ns 187 * i.e. rd_adj >= 6.5ns / clk_period 188 * i.e. rd_strobe >= 35 ns / clk_period - 5 - rd_adj + 1 189 * constants: 190 * 1 / 6.5ns == 153846154 Hz 191 * 1 / 35ns == 28571429 Hz 192 */ 193 194 rd_adj = clk_rate / 153846154; 195 rd_strobe = clk_rate / 28571429 - 5 - rd_adj + 1; 196 197 if (rd_adj > EFUCFG_RD_ADJ_MASK || 198 rd_strobe > EFUCFG_RD_STR_MASK) { 199 dev_err(&pdev->dev, "Cannot set clock configuration\n"); 200 return -EINVAL; 201 } 202 203 regmap_update_bits(efuse->map, JZ_EFUCFG, 204 (EFUCFG_RD_ADJ_MASK << EFUCFG_RD_ADJ_SHIFT) | 205 (EFUCFG_RD_STR_MASK << EFUCFG_RD_STR_SHIFT), 206 (rd_adj << EFUCFG_RD_ADJ_SHIFT) | 207 (rd_strobe << EFUCFG_RD_STR_SHIFT)); 208 209 cfg = jz4780_efuse_nvmem_config; 210 cfg.dev = &pdev->dev; 211 cfg.priv = efuse; 212 213 nvmem = devm_nvmem_register(dev, &cfg); 214 215 return PTR_ERR_OR_ZERO(nvmem); 216} 217 218static const struct of_device_id jz4780_efuse_match[] = { 219 { .compatible = "ingenic,jz4780-efuse" }, 220 { /* sentinel */ }, 221}; 222MODULE_DEVICE_TABLE(of, jz4780_efuse_match); 223 224static struct platform_driver jz4780_efuse_driver = { 225 .probe = jz4780_efuse_probe, 226 .driver = { 227 .name = "jz4780-efuse", 228 .of_match_table = jz4780_efuse_match, 229 }, 230}; 231module_platform_driver(jz4780_efuse_driver); 232 233MODULE_AUTHOR("PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>"); 234MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>"); 235MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 236MODULE_DESCRIPTION("Ingenic JZ4780 efuse driver"); 237MODULE_LICENSE("GPL v2");