diff options
Diffstat (limited to 'drivers/nvmem/sc27xx-efuse.c')
| -rw-r--r-- | drivers/nvmem/sc27xx-efuse.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/nvmem/sc27xx-efuse.c b/drivers/nvmem/sc27xx-efuse.c index 33185d8d82cf..4e2ffefac96c 100644 --- a/drivers/nvmem/sc27xx-efuse.c +++ b/drivers/nvmem/sc27xx-efuse.c @@ -10,6 +10,7 @@ /* PMIC global registers definition */ #define SC27XX_MODULE_EN 0xc08 +#define SC2730_MODULE_EN 0x1808 #define SC27XX_EFUSE_EN BIT(6) /* Efuse controller registers definition */ @@ -49,12 +50,29 @@ #define SC27XX_EFUSE_POLL_TIMEOUT 3000000 #define SC27XX_EFUSE_POLL_DELAY_US 10000 +/* + * Since different PMICs of SC27xx series can have different + * address , we should save address in the device data structure. + */ +struct sc27xx_efuse_variant_data { + u32 module_en; +}; + struct sc27xx_efuse { struct device *dev; struct regmap *regmap; struct hwspinlock *hwlock; struct mutex mutex; u32 base; + const struct sc27xx_efuse_variant_data *var_data; +}; + +static const struct sc27xx_efuse_variant_data sc2731_edata = { + .module_en = SC27XX_MODULE_EN, +}; + +static const struct sc27xx_efuse_variant_data sc2730_edata = { + .module_en = SC2730_MODULE_EN, }; /* @@ -106,10 +124,12 @@ static int sc27xx_efuse_poll_status(struct sc27xx_efuse *efuse, u32 bits) static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes) { struct sc27xx_efuse *efuse = context; - u32 buf; + u32 buf, blk_index = offset / SC27XX_EFUSE_BLOCK_WIDTH; + u32 blk_offset = (offset % SC27XX_EFUSE_BLOCK_WIDTH) * BITS_PER_BYTE; int ret; - if (offset > SC27XX_EFUSE_BLOCK_MAX || bytes > SC27XX_EFUSE_BLOCK_WIDTH) + if (blk_index > SC27XX_EFUSE_BLOCK_MAX || + bytes > SC27XX_EFUSE_BLOCK_WIDTH) return -EINVAL; ret = sc27xx_efuse_lock(efuse); @@ -117,7 +137,7 @@ static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes) return ret; /* Enable the efuse controller. */ - ret = regmap_update_bits(efuse->regmap, SC27XX_MODULE_EN, + ret = regmap_update_bits(efuse->regmap, efuse->var_data->module_en, SC27XX_EFUSE_EN, SC27XX_EFUSE_EN); if (ret) goto unlock_efuse; @@ -133,7 +153,7 @@ static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes) /* Set the block address to be read. */ ret = regmap_write(efuse->regmap, efuse->base + SC27XX_EFUSE_BLOCK_INDEX, - offset & SC27XX_EFUSE_BLOCK_MASK); + blk_index & SC27XX_EFUSE_BLOCK_MASK); if (ret) goto disable_efuse; @@ -167,12 +187,14 @@ static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes) disable_efuse: /* Disable the efuse controller after reading. */ - regmap_update_bits(efuse->regmap, SC27XX_MODULE_EN, SC27XX_EFUSE_EN, 0); + regmap_update_bits(efuse->regmap, efuse->var_data->module_en, SC27XX_EFUSE_EN, 0); unlock_efuse: sc27xx_efuse_unlock(efuse); - if (!ret) + if (!ret) { + buf >>= blk_offset; memcpy(val, &buf, bytes); + } return ret; } @@ -207,7 +229,7 @@ static int sc27xx_efuse_probe(struct platform_device *pdev) return ret; } - efuse->hwlock = hwspin_lock_request_specific(ret); + efuse->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret); if (!efuse->hwlock) { dev_err(&pdev->dev, "failed to request hwspinlock\n"); return -ENXIO; @@ -215,7 +237,7 @@ static int sc27xx_efuse_probe(struct platform_device *pdev) mutex_init(&efuse->mutex); efuse->dev = &pdev->dev; - platform_set_drvdata(pdev, efuse); + efuse->var_data = of_device_get_match_data(&pdev->dev); econfig.stride = 1; econfig.word_size = 1; @@ -225,32 +247,25 @@ static int sc27xx_efuse_probe(struct platform_device *pdev) econfig.reg_read = sc27xx_efuse_read; econfig.priv = efuse; econfig.dev = &pdev->dev; + econfig.add_legacy_fixed_of_cells = true; nvmem = devm_nvmem_register(&pdev->dev, &econfig); if (IS_ERR(nvmem)) { dev_err(&pdev->dev, "failed to register nvmem config\n"); - hwspin_lock_free(efuse->hwlock); return PTR_ERR(nvmem); } return 0; } -static int sc27xx_efuse_remove(struct platform_device *pdev) -{ - struct sc27xx_efuse *efuse = platform_get_drvdata(pdev); - - hwspin_lock_free(efuse->hwlock); - return 0; -} - static const struct of_device_id sc27xx_efuse_of_match[] = { - { .compatible = "sprd,sc2731-efuse" }, + { .compatible = "sprd,sc2731-efuse", .data = &sc2731_edata}, + { .compatible = "sprd,sc2730-efuse", .data = &sc2730_edata}, { } }; +MODULE_DEVICE_TABLE(of, sc27xx_efuse_of_match); static struct platform_driver sc27xx_efuse_driver = { .probe = sc27xx_efuse_probe, - .remove = sc27xx_efuse_remove, .driver = { .name = "sc27xx-efuse", .of_match_table = sc27xx_efuse_of_match, |
