diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2016-05-13 12:13:44 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-11-08 14:43:26 +0100 |
commit | ce864aa5a42895fc91b2bc8f5b83d63f844f50b1 (patch) | |
tree | 954e3e05631c9b49108e26fb84e3a0cbd8decc4d /arch/arm/mach-imx/ocotp.c | |
parent | 36be2505d698e506423131d7c53458d297ee5fa3 (diff) | |
download | barebox-ce864aa5a42895fc91b2bc8f5b83d63f844f50b1.tar.gz barebox-ce864aa5a42895fc91b2bc8f5b83d63f844f50b1.tar.xz |
ARM: i.MX: OCOTP: Add functions to access fuses field wise
Add functions to access the OCOTP fuses field wise, similar to what has
been done for the IIM. Also add a i.MX6 fusemap header file.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-imx/ocotp.c')
-rw-r--r-- | arch/arm/mach-imx/ocotp.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index 17b944be14..3acec7f05a 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -28,6 +28,7 @@ #include <clock.h> #include <regmap.h> #include <linux/clk.h> +#include <mach/ocotp.h> /* * a single MAC address reference has the form @@ -87,6 +88,8 @@ struct ocotp_priv { struct regmap_config map_config; }; +static struct ocotp_priv *imx_ocotp; + static int imx6_ocotp_set_timing(struct ocotp_priv *priv) { u32 clk_rate; @@ -282,6 +285,66 @@ static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val) return 0; } +static void imx_ocotp_field_decode(uint32_t field, unsigned *word, + unsigned *bit, unsigned *mask) +{ + unsigned width; + + *word = ((field >> OCOTP_WORD_MASK_SHIFT) & ((1 << OCOTP_WORD_MASK_WIDTH) - 1)) * 4; + *bit = (field >> OCOTP_BIT_MASK_SHIFT) & ((1 << OCOTP_BIT_MASK_WIDTH) - 1); + width = ((field >> OCOTP_WIDTH_MASK_SHIFT) & ((1 << OCOTP_WIDTH_MASK_WIDTH) - 1)) + 1; + *mask = (1 << width) - 1; +} + +int imx_ocotp_read_field(uint32_t field, unsigned *value) +{ + unsigned word, bit, mask, val; + int ret; + + imx_ocotp_field_decode(field, &word, &bit, &mask); + + ret = imx_ocotp_reg_read(imx_ocotp, word, &val); + if (ret) + return ret; + + val >>= bit; + val &= mask; + + dev_dbg(&imx_ocotp->dev, "%s: word: 0x%x bit: %d mask: 0x%x val: 0x%x\n", + __func__, word, bit, mask, val); + + *value = val; + + return 0; +} + +int imx_ocotp_write_field(uint32_t field, unsigned value) +{ + unsigned word, bit, mask; + int ret; + + imx_ocotp_field_decode(field, &word, &bit, &mask); + + value &= mask; + value <<= bit; + + ret = imx_ocotp_reg_write(imx_ocotp, word, value); + if (ret) + return ret; + + dev_dbg(&imx_ocotp->dev, "%s: word: 0x%x bit: %d mask: 0x%x val: 0x%x\n", + __func__, word, bit, mask, value); + + return 0; +} + +int imx_ocotp_permanent_write(int enable) +{ + imx_ocotp->permanent_write_enable = enable; + + return 0; +} + static uint32_t inc_offset(uint32_t offset) { if ((offset & 0x3) == 0x3) @@ -412,6 +475,8 @@ static int imx_ocotp_probe(struct device_d *dev) if (ret) return ret; + imx_ocotp = priv; + if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) { dev_add_param_bool(&(priv->dev), "permanent_write_enable", NULL, NULL, &priv->permanent_write_enable, NULL); |