diff options
Diffstat (limited to 'drivers/nvmem/qfprom.c')
| -rw-r--r-- | drivers/nvmem/qfprom.c | 57 |
1 files changed, 32 insertions, 25 deletions
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c index c500d6235bf6..a872c640b8c5 100644 --- a/drivers/nvmem/qfprom.c +++ b/drivers/nvmem/qfprom.c @@ -22,7 +22,7 @@ /* Amount of time required to hold charge to blow fuse in micro-seconds */ #define QFPROM_FUSE_BLOW_POLL_US 100 -#define QFPROM_FUSE_BLOW_TIMEOUT_US 1000 +#define QFPROM_FUSE_BLOW_TIMEOUT_US 10000 #define QFPROM_BLOW_STATUS_OFFSET 0x048 #define QFPROM_BLOW_STATUS_BUSY 0x1 @@ -217,9 +217,8 @@ static int qfprom_enable_fuse_blowing(const struct qfprom_priv *priv, goto err_clk_rate_set; } - ret = pm_runtime_get_sync(priv->dev); + ret = pm_runtime_resume_and_get(priv->dev); if (ret < 0) { - pm_runtime_put_noidle(priv->dev); dev_err(priv->dev, "Failed to enable power-domain\n"); goto err_reg_enable; } @@ -244,7 +243,7 @@ err_clk_prepared: } /** - * qfprom_efuse_reg_write() - Write to fuses. + * qfprom_reg_write() - Write to fuses. * @context: Our driver data. * @reg: The offset to write at. * @_val: Pointer to data to write. @@ -322,19 +321,32 @@ static int qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes) { struct qfprom_priv *priv = context; - u8 *val = _val; - int i = 0, words = bytes; + u32 *val = _val; void __iomem *base = priv->qfpcorrected; + int words = DIV_ROUND_UP(bytes, sizeof(u32)); + int i; if (read_raw_data && priv->qfpraw) base = priv->qfpraw; - while (words--) - *val++ = readb(base + reg + i++); + for (i = 0; i < words; i++) + *val++ = readl(base + reg + i * sizeof(u32)); return 0; } +/* Align reads to word boundary */ +static void qfprom_fixup_dt_cell_info(struct nvmem_device *nvmem, + struct nvmem_cell_info *cell) +{ + unsigned int byte_offset = cell->offset % sizeof(u32); + + cell->bit_offset += byte_offset * BITS_PER_BYTE; + cell->offset -= byte_offset; + if (byte_offset && !cell->nbits) + cell->nbits = cell->bytes * BITS_PER_BYTE; +} + static void qfprom_runtime_disable(void *data) { pm_runtime_disable(data); @@ -358,10 +370,12 @@ static int qfprom_probe(struct platform_device *pdev) { struct nvmem_config econfig = { .name = "qfprom", - .stride = 1, - .word_size = 1, + .add_legacy_fixed_of_cells = true, + .stride = 4, + .word_size = 4, .id = NVMEM_DEVID_AUTO, .reg_read = qfprom_reg_read, + .fixup_dt_cell_info = qfprom_fixup_dt_cell_info, }; struct device *dev = &pdev->dev; struct resource *res; @@ -375,8 +389,7 @@ static int qfprom_probe(struct platform_device *pdev) return -ENOMEM; /* The corrected section is always provided */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->qfpcorrected = devm_ioremap_resource(dev, res); + priv->qfpcorrected = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(priv->qfpcorrected)) return PTR_ERR(priv->qfpcorrected); @@ -403,12 +416,10 @@ static int qfprom_probe(struct platform_device *pdev) priv->qfpraw = devm_ioremap_resource(dev, res); if (IS_ERR(priv->qfpraw)) return PTR_ERR(priv->qfpraw); - res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - priv->qfpconf = devm_ioremap_resource(dev, res); + priv->qfpconf = devm_platform_ioremap_resource(pdev, 2); if (IS_ERR(priv->qfpconf)) return PTR_ERR(priv->qfpconf); - res = platform_get_resource(pdev, IORESOURCE_MEM, 3); - priv->qfpsecurity = devm_ioremap_resource(dev, res); + priv->qfpsecurity = devm_platform_ioremap_resource(pdev, 3); if (IS_ERR(priv->qfpsecurity)) return PTR_ERR(priv->qfpsecurity); @@ -427,16 +438,12 @@ static int qfprom_probe(struct platform_device *pdev) if (IS_ERR(priv->vcc)) return PTR_ERR(priv->vcc); - priv->secclk = devm_clk_get(dev, "core"); - if (IS_ERR(priv->secclk)) { - ret = PTR_ERR(priv->secclk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Error getting clock: %d\n", ret); - return ret; - } + priv->secclk = devm_clk_get_optional(dev, "core"); + if (IS_ERR(priv->secclk)) + return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); - /* Only enable writing if we have SoC data. */ - if (priv->soc_data) + /* Only enable writing if we have SoC data and a valid clock */ + if (priv->soc_data && priv->secclk) econfig.reg_write = qfprom_reg_write; } |
