diff options
Diffstat (limited to 'drivers/nvmem')
-rw-r--r-- | drivers/nvmem/core.c | 17 | ||||
-rw-r--r-- | drivers/nvmem/rockchip-efuse.c | 70 | ||||
-rw-r--r-- | drivers/nvmem/uniphier-efuse.c | 10 |
3 files changed, 79 insertions, 18 deletions
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 5a5cefd12153..35a3dbeea324 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -444,7 +444,6 @@ static int nvmem_setup_compat(struct nvmem_device *nvmem, struct nvmem_device *nvmem_register(const struct nvmem_config *config) { struct nvmem_device *nvmem; - struct device_node *np; int rval; if (!config->dev) @@ -464,8 +463,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->owner = config->owner; if (!nvmem->owner && config->dev->driver) nvmem->owner = config->dev->driver->owner; - nvmem->stride = config->stride; - nvmem->word_size = config->word_size; + nvmem->stride = config->stride ?: 1; + nvmem->word_size = config->word_size ?: 1; nvmem->size = config->size; nvmem->dev.type = &nvmem_provider_type; nvmem->dev.bus = &nvmem_bus_type; @@ -473,13 +472,12 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->priv = config->priv; nvmem->reg_read = config->reg_read; nvmem->reg_write = config->reg_write; - np = config->dev->of_node; - nvmem->dev.of_node = np; + nvmem->dev.of_node = config->dev->of_node; dev_set_name(&nvmem->dev, "%s%d", config->name ? : "nvmem", config->name ? config->id : nvmem->id); - nvmem->read_only = of_property_read_bool(np, "read-only") | + nvmem->read_only = device_property_present(config->dev, "read-only") | config->read_only; if (config->root_only) @@ -600,16 +598,11 @@ static void __nvmem_device_put(struct nvmem_device *nvmem) mutex_unlock(&nvmem_mutex); } -static int nvmem_match(struct device *dev, void *data) -{ - return !strcmp(dev_name(dev), data); -} - static struct nvmem_device *nvmem_find(const char *name) { struct device *d; - d = bus_find_device(&nvmem_bus_type, NULL, (void *)name, nvmem_match); + d = bus_find_device_by_name(&nvmem_bus_type, NULL, name); if (!d) return NULL; diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index 123de77ca5d6..f13a8335f364 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -32,6 +32,14 @@ #define RK3288_STROBE BIT(1) #define RK3288_CSB BIT(0) +#define RK3328_SECURE_SIZES 96 +#define RK3328_INT_STATUS 0x0018 +#define RK3328_DOUT 0x0020 +#define RK3328_AUTO_CTRL 0x0024 +#define RK3328_INT_FINISH BIT(0) +#define RK3328_AUTO_ENB BIT(0) +#define RK3328_AUTO_RD BIT(1) + #define RK3399_A_SHIFT 16 #define RK3399_A_MASK 0x3ff #define RK3399_NBYTES 4 @@ -92,6 +100,60 @@ static int rockchip_rk3288_efuse_read(void *context, unsigned int offset, return 0; } +static int rockchip_rk3328_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct rockchip_efuse_chip *efuse = context; + unsigned int addr_start, addr_end, addr_offset, addr_len; + u32 out_value, status; + u8 *buf; + int ret, i = 0; + + ret = clk_prepare_enable(efuse->clk); + if (ret < 0) { + dev_err(efuse->dev, "failed to prepare/enable efuse clk\n"); + return ret; + } + + /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */ + offset += RK3328_SECURE_SIZES; + addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES; + addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES; + addr_offset = offset % RK3399_NBYTES; + addr_len = addr_end - addr_start; + + buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto nomem; + } + + while (addr_len--) { + writel(RK3328_AUTO_RD | RK3328_AUTO_ENB | + ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT), + efuse->base + RK3328_AUTO_CTRL); + udelay(4); + status = readl(efuse->base + RK3328_INT_STATUS); + if (!(status & RK3328_INT_FINISH)) { + ret = -EIO; + goto err; + } + out_value = readl(efuse->base + RK3328_DOUT); + writel(RK3328_INT_FINISH, efuse->base + RK3328_INT_STATUS); + + memcpy(&buf[i], &out_value, RK3399_NBYTES); + i += RK3399_NBYTES; + } + + memcpy(val, buf + addr_offset, bytes); +err: + kfree(buf); +nomem: + clk_disable_unprepare(efuse->clk); + + return ret; +} + static int rockchip_rk3399_efuse_read(void *context, unsigned int offset, void *val, size_t bytes) { @@ -181,6 +243,10 @@ static const struct of_device_id rockchip_efuse_match[] = { .data = (void *)&rockchip_rk3288_efuse_read, }, { + .compatible = "rockchip,rk3328-efuse", + .data = (void *)&rockchip_rk3328_efuse_read, + }, + { .compatible = "rockchip,rk3399-efuse", .data = (void *)&rockchip_rk3399_efuse_read, }, @@ -217,7 +283,9 @@ static int rockchip_efuse_probe(struct platform_device *pdev) return PTR_ERR(efuse->clk); efuse->dev = &pdev->dev; - econfig.size = resource_size(res); + if (of_property_read_u32(dev->of_node, "rockchip,efuse-size", + &econfig.size)) + econfig.size = resource_size(res); econfig.reg_read = match->data; econfig.priv = efuse; econfig.dev = efuse->dev; diff --git a/drivers/nvmem/uniphier-efuse.c b/drivers/nvmem/uniphier-efuse.c index 9d278b4e1dc7..be11880a1358 100644 --- a/drivers/nvmem/uniphier-efuse.c +++ b/drivers/nvmem/uniphier-efuse.c @@ -27,11 +27,11 @@ static int uniphier_reg_read(void *context, unsigned int reg, void *_val, size_t bytes) { struct uniphier_efuse_priv *priv = context; - u32 *val = _val; + u8 *val = _val; int offs; - for (offs = 0; offs < bytes; offs += sizeof(u32)) - *val++ = readl(priv->base + reg + offs); + for (offs = 0; offs < bytes; offs += sizeof(u8)) + *val++ = readb(priv->base + reg + offs); return 0; } @@ -53,8 +53,8 @@ static int uniphier_efuse_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - econfig.stride = 4; - econfig.word_size = 4; + econfig.stride = 1; + econfig.word_size = 1; econfig.read_only = true; econfig.reg_read = uniphier_reg_read; econfig.size = resource_size(res); |