280 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2018 Spreadtrum Communications Inc.3 4#include <linux/hwspinlock.h>5#include <linux/module.h>6#include <linux/of.h>7#include <linux/platform_device.h>8#include <linux/regmap.h>9#include <linux/nvmem-provider.h>10 11/* PMIC global registers definition */12#define SC27XX_MODULE_EN 0xc0813#define SC2730_MODULE_EN 0x180814#define SC27XX_EFUSE_EN BIT(6)15 16/* Efuse controller registers definition */17#define SC27XX_EFUSE_GLB_CTRL 0x018#define SC27XX_EFUSE_DATA_RD 0x419#define SC27XX_EFUSE_DATA_WR 0x820#define SC27XX_EFUSE_BLOCK_INDEX 0xc21#define SC27XX_EFUSE_MODE_CTRL 0x1022#define SC27XX_EFUSE_STATUS 0x1423#define SC27XX_EFUSE_WR_TIMING_CTRL 0x2024#define SC27XX_EFUSE_RD_TIMING_CTRL 0x2425#define SC27XX_EFUSE_EFUSE_DEB_CTRL 0x2826 27/* Mask definition for SC27XX_EFUSE_BLOCK_INDEX register */28#define SC27XX_EFUSE_BLOCK_MASK GENMASK(4, 0)29 30/* Bits definitions for SC27XX_EFUSE_MODE_CTRL register */31#define SC27XX_EFUSE_PG_START BIT(0)32#define SC27XX_EFUSE_RD_START BIT(1)33#define SC27XX_EFUSE_CLR_RDDONE BIT(2)34 35/* Bits definitions for SC27XX_EFUSE_STATUS register */36#define SC27XX_EFUSE_PGM_BUSY BIT(0)37#define SC27XX_EFUSE_READ_BUSY BIT(1)38#define SC27XX_EFUSE_STANDBY BIT(2)39#define SC27XX_EFUSE_GLOBAL_PROT BIT(3)40#define SC27XX_EFUSE_RD_DONE BIT(4)41 42/* Block number and block width (bytes) definitions */43#define SC27XX_EFUSE_BLOCK_MAX 3244#define SC27XX_EFUSE_BLOCK_WIDTH 245 46/* Timeout (ms) for the trylock of hardware spinlocks */47#define SC27XX_EFUSE_HWLOCK_TIMEOUT 500048 49/* Timeout (us) of polling the status */50#define SC27XX_EFUSE_POLL_TIMEOUT 300000051#define SC27XX_EFUSE_POLL_DELAY_US 1000052 53/*54 * Since different PMICs of SC27xx series can have different55 * address , we should save address in the device data structure.56 */57struct sc27xx_efuse_variant_data {58 u32 module_en;59};60 61struct sc27xx_efuse {62 struct device *dev;63 struct regmap *regmap;64 struct hwspinlock *hwlock;65 struct mutex mutex;66 u32 base;67 const struct sc27xx_efuse_variant_data *var_data;68};69 70static const struct sc27xx_efuse_variant_data sc2731_edata = {71 .module_en = SC27XX_MODULE_EN,72};73 74static const struct sc27xx_efuse_variant_data sc2730_edata = {75 .module_en = SC2730_MODULE_EN,76};77 78/*79 * On Spreadtrum platform, we have multi-subsystems will access the unique80 * efuse controller, so we need one hardware spinlock to synchronize between81 * the multiple subsystems.82 */83static int sc27xx_efuse_lock(struct sc27xx_efuse *efuse)84{85 int ret;86 87 mutex_lock(&efuse->mutex);88 89 ret = hwspin_lock_timeout_raw(efuse->hwlock,90 SC27XX_EFUSE_HWLOCK_TIMEOUT);91 if (ret) {92 dev_err(efuse->dev, "timeout to get the hwspinlock\n");93 mutex_unlock(&efuse->mutex);94 return ret;95 }96 97 return 0;98}99 100static void sc27xx_efuse_unlock(struct sc27xx_efuse *efuse)101{102 hwspin_unlock_raw(efuse->hwlock);103 mutex_unlock(&efuse->mutex);104}105 106static int sc27xx_efuse_poll_status(struct sc27xx_efuse *efuse, u32 bits)107{108 int ret;109 u32 val;110 111 ret = regmap_read_poll_timeout(efuse->regmap,112 efuse->base + SC27XX_EFUSE_STATUS,113 val, (val & bits),114 SC27XX_EFUSE_POLL_DELAY_US,115 SC27XX_EFUSE_POLL_TIMEOUT);116 if (ret) {117 dev_err(efuse->dev, "timeout to update the efuse status\n");118 return ret;119 }120 121 return 0;122}123 124static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes)125{126 struct sc27xx_efuse *efuse = context;127 u32 buf, blk_index = offset / SC27XX_EFUSE_BLOCK_WIDTH;128 u32 blk_offset = (offset % SC27XX_EFUSE_BLOCK_WIDTH) * BITS_PER_BYTE;129 int ret;130 131 if (blk_index > SC27XX_EFUSE_BLOCK_MAX ||132 bytes > SC27XX_EFUSE_BLOCK_WIDTH)133 return -EINVAL;134 135 ret = sc27xx_efuse_lock(efuse);136 if (ret)137 return ret;138 139 /* Enable the efuse controller. */140 ret = regmap_update_bits(efuse->regmap, efuse->var_data->module_en,141 SC27XX_EFUSE_EN, SC27XX_EFUSE_EN);142 if (ret)143 goto unlock_efuse;144 145 /*146 * Before reading, we should ensure the efuse controller is in147 * standby state.148 */149 ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_STANDBY);150 if (ret)151 goto disable_efuse;152 153 /* Set the block address to be read. */154 ret = regmap_write(efuse->regmap,155 efuse->base + SC27XX_EFUSE_BLOCK_INDEX,156 blk_index & SC27XX_EFUSE_BLOCK_MASK);157 if (ret)158 goto disable_efuse;159 160 /* Start reading process from efuse memory. */161 ret = regmap_update_bits(efuse->regmap,162 efuse->base + SC27XX_EFUSE_MODE_CTRL,163 SC27XX_EFUSE_RD_START,164 SC27XX_EFUSE_RD_START);165 if (ret)166 goto disable_efuse;167 168 /*169 * Polling the read done status to make sure the reading process170 * is completed, that means the data can be read out now.171 */172 ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_RD_DONE);173 if (ret)174 goto disable_efuse;175 176 /* Read data from efuse memory. */177 ret = regmap_read(efuse->regmap, efuse->base + SC27XX_EFUSE_DATA_RD,178 &buf);179 if (ret)180 goto disable_efuse;181 182 /* Clear the read done flag. */183 ret = regmap_update_bits(efuse->regmap,184 efuse->base + SC27XX_EFUSE_MODE_CTRL,185 SC27XX_EFUSE_CLR_RDDONE,186 SC27XX_EFUSE_CLR_RDDONE);187 188disable_efuse:189 /* Disable the efuse controller after reading. */190 regmap_update_bits(efuse->regmap, efuse->var_data->module_en, SC27XX_EFUSE_EN, 0);191unlock_efuse:192 sc27xx_efuse_unlock(efuse);193 194 if (!ret) {195 buf >>= blk_offset;196 memcpy(val, &buf, bytes);197 }198 199 return ret;200}201 202static int sc27xx_efuse_probe(struct platform_device *pdev)203{204 struct device_node *np = pdev->dev.of_node;205 struct nvmem_config econfig = { };206 struct nvmem_device *nvmem;207 struct sc27xx_efuse *efuse;208 int ret;209 210 efuse = devm_kzalloc(&pdev->dev, sizeof(*efuse), GFP_KERNEL);211 if (!efuse)212 return -ENOMEM;213 214 efuse->regmap = dev_get_regmap(pdev->dev.parent, NULL);215 if (!efuse->regmap) {216 dev_err(&pdev->dev, "failed to get efuse regmap\n");217 return -ENODEV;218 }219 220 ret = of_property_read_u32(np, "reg", &efuse->base);221 if (ret) {222 dev_err(&pdev->dev, "failed to get efuse base address\n");223 return ret;224 }225 226 ret = of_hwspin_lock_get_id(np, 0);227 if (ret < 0) {228 dev_err(&pdev->dev, "failed to get hwspinlock id\n");229 return ret;230 }231 232 efuse->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret);233 if (!efuse->hwlock) {234 dev_err(&pdev->dev, "failed to request hwspinlock\n");235 return -ENXIO;236 }237 238 mutex_init(&efuse->mutex);239 efuse->dev = &pdev->dev;240 efuse->var_data = of_device_get_match_data(&pdev->dev);241 242 econfig.stride = 1;243 econfig.word_size = 1;244 econfig.read_only = true;245 econfig.name = "sc27xx-efuse";246 econfig.size = SC27XX_EFUSE_BLOCK_MAX * SC27XX_EFUSE_BLOCK_WIDTH;247 econfig.reg_read = sc27xx_efuse_read;248 econfig.priv = efuse;249 econfig.dev = &pdev->dev;250 econfig.add_legacy_fixed_of_cells = true;251 nvmem = devm_nvmem_register(&pdev->dev, &econfig);252 if (IS_ERR(nvmem)) {253 dev_err(&pdev->dev, "failed to register nvmem config\n");254 return PTR_ERR(nvmem);255 }256 257 return 0;258}259 260static const struct of_device_id sc27xx_efuse_of_match[] = {261 { .compatible = "sprd,sc2731-efuse", .data = &sc2731_edata},262 { .compatible = "sprd,sc2730-efuse", .data = &sc2730_edata},263 { }264};265MODULE_DEVICE_TABLE(of, sc27xx_efuse_of_match);266 267static struct platform_driver sc27xx_efuse_driver = {268 .probe = sc27xx_efuse_probe,269 .driver = {270 .name = "sc27xx-efuse",271 .of_match_table = sc27xx_efuse_of_match,272 },273};274 275module_platform_driver(sc27xx_efuse_driver);276 277MODULE_AUTHOR("Freeman Liu <freeman.liu@spreadtrum.com>");278MODULE_DESCRIPTION("Spreadtrum SC27xx efuse driver");279MODULE_LICENSE("GPL v2");280