diff options
author | Peng Fan <van.freenix@gmail.com> | 2016-06-02 11:05:11 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-06-25 14:42:55 (GMT) |
commit | deb319705e7eb60a870e24f75ff8d6452372e350 (patch) | |
tree | 0b0ab9a66dc65f7b20b34d44ed955c9b4c3a7818 /drivers/nvmem/imx-ocotp.c | |
parent | 7d8867d71fba7604e5d6417e5cbd68a6ffd85bb4 (diff) | |
download | linux-deb319705e7eb60a870e24f75ff8d6452372e350.tar.xz |
nvmem: imx-ocotp: handling clock
Before access ocotp nvmem area, the clock should be enabled.
Or, `hexdump nvmem` will hang the system. So, use such flow:
"
1. clock_enable_prepare
2. read nvmem ocotp area
3. clock_disable_unprepare
"
Signed-off-by: Peng Fan <van.freenix@gmail.com>
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Shawn Guo <shawnguo@kernel.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/nvmem/imx-ocotp.c')
-rw-r--r-- | drivers/nvmem/imx-ocotp.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index 75e66ef..a340390 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c @@ -15,6 +15,7 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/clk.h> #include <linux/device.h> #include <linux/io.h> #include <linux/module.h> @@ -26,6 +27,7 @@ struct ocotp_priv { struct device *dev; + struct clk *clk; void __iomem *base; unsigned int nregs; }; @@ -36,7 +38,7 @@ static int imx_ocotp_read(void *context, unsigned int offset, struct ocotp_priv *priv = context; unsigned int count; u32 *buf = val; - int i; + int i, ret; u32 index; index = offset >> 2; @@ -45,9 +47,16 @@ static int imx_ocotp_read(void *context, unsigned int offset, if (count > (priv->nregs - index)) count = priv->nregs - index; + ret = clk_prepare_enable(priv->clk); + if (ret < 0) { + dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); + return ret; + } for (i = index; i < (index + count); i++) *buf++ = readl(priv->base + 0x400 + i * 0x10); + clk_disable_unprepare(priv->clk); + return 0; } @@ -85,6 +94,10 @@ static int imx_ocotp_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); + priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + of_id = of_match_device(imx_ocotp_dt_ids, dev); priv->nregs = (unsigned int)of_id->data; imx_ocotp_nvmem_config.size = 4 * priv->nregs; |