From f36c383bcc053da35edcbc3ca1dfffe78993e3e0 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:08:55 -0800 Subject: i.MX: ocotp: Move memory reversing into a subroutine Move memory reversing, found in imx_ocotp_get_mac and imx_ocotp_set_mac, into a subroutine to avoid code duplication. Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/ocotp.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'arch/arm/mach-imx/ocotp.c') diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index 68ff0ce28b..7f625d8645 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -397,19 +397,26 @@ static void imx_ocotp_init_dt(struct device_d *dev, void __iomem *base) } } +static void memreverse(void *dest, const void *src, size_t n) +{ + char *destp = dest; + const char *srcp = src + n - 1; + + while(n--) + *destp++ = *srcp--; +} + static int imx_ocotp_get_mac(struct param_d *param, void *priv) { struct ocotp_priv *ocotp_priv = priv; char buf[8]; - int i, ret; + int ret; ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); if (ret < 0) return ret; - for (i = 0; i < 6; i++) - ocotp_priv->ethaddr[i] = buf[5 - i]; - + memreverse(ocotp_priv->ethaddr, buf, 6); return 0; } @@ -417,10 +424,9 @@ static int imx_ocotp_set_mac(struct param_d *param, void *priv) { struct ocotp_priv *ocotp_priv = priv; char buf[8]; - int i, ret; + int ret; - for (i = 0; i < 6; i++) - buf[5 - i] = ocotp_priv->ethaddr[i]; + memreverse(buf, ocotp_priv->ethaddr, 6); buf[6] = 0; buf[7] = 0; ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); -- cgit v1.2.3 From 75b6972be4ec9c7edb7e4a42fc3d3fa6778cb5d1 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:08:56 -0800 Subject: i.MX: ocotp: Add provisions for storing multiple MAC addresses i.MX SoC variants like Vybrid have more than one built-in Ethernet interface and as a consequence support storing more than one MAC address in OCOTP module. Add code to create multiple 'mac_addr' parameters as well as 'mac_addr' as an "alias" to 'mac_addr0' for backwards compatibility. Acked-by: Stefan Lengfeld Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/ocotp.c | 70 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 19 deletions(-) (limited to 'arch/arm/mach-imx/ocotp.c') diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index 7f625d8645..bd5448dddb 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -69,12 +69,22 @@ /* Other definitions */ #define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA #define DEF_RELAX 20 -#define MAC_OFFSET (0x22 * 4) +#define MAC_OFFSET_0 (0x22 * 4) +#define MAC_OFFSET_1 (0x24 * 4) +#define MAX_MAC_OFFSETS 2 #define MAC_BYTES 8 struct imx_ocotp_data { int num_regs; u32 (*addr_to_offset)(u32 addr); + u8 mac_offsets[MAX_MAC_OFFSETS]; + u8 mac_offsets_num; +}; + +struct ocotp_priv_ethaddr { + char value[MAC_BYTES]; + struct regmap *map; + u8 offset; }; struct ocotp_priv { @@ -84,9 +94,10 @@ struct ocotp_priv { struct device_d dev; int permanent_write_enable; int sense_enable; - char ethaddr[6]; + struct ocotp_priv_ethaddr ethaddr[MAX_MAC_OFFSETS]; struct regmap_config map_config; const struct imx_ocotp_data *data; + int mac_offset_idx; }; static struct ocotp_priv *imx_ocotp; @@ -408,32 +419,28 @@ static void memreverse(void *dest, const void *src, size_t n) static int imx_ocotp_get_mac(struct param_d *param, void *priv) { - struct ocotp_priv *ocotp_priv = priv; - char buf[8]; + char buf[MAC_BYTES]; int ret; + struct ocotp_priv_ethaddr *ethaddr = priv; - ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); + ret = regmap_bulk_read(ethaddr->map, ethaddr->offset, + buf, MAC_BYTES); if (ret < 0) return ret; - memreverse(ocotp_priv->ethaddr, buf, 6); + memreverse(ethaddr->value, buf, 6); return 0; } static int imx_ocotp_set_mac(struct param_d *param, void *priv) { - struct ocotp_priv *ocotp_priv = priv; - char buf[8]; - int ret; + char buf[MAC_BYTES]; + struct ocotp_priv_ethaddr *ethaddr = priv; - memreverse(buf, ocotp_priv->ethaddr, 6); - buf[6] = 0; buf[7] = 0; - - ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); - if (ret < 0) - return ret; + memreverse(buf, ethaddr->value, 6); - return 0; + return regmap_bulk_write(ethaddr->map, ethaddr->offset, + buf, MAC_BYTES); } static struct regmap_bus imx_ocotp_regmap_bus = { @@ -492,9 +499,28 @@ static int imx_ocotp_probe(struct device_d *dev) NULL, NULL, &priv->permanent_write_enable, NULL); } - if (IS_ENABLED(CONFIG_NET)) - dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac, - imx_ocotp_get_mac, priv->ethaddr, priv); + if (IS_ENABLED(CONFIG_NET)) { + int i; + struct ocotp_priv_ethaddr *ethaddr; + + for (i = 0; i < priv->data->mac_offsets_num; i++) { + ethaddr = &priv->ethaddr[i]; + ethaddr->map = priv->map; + ethaddr->offset = priv->data->mac_offsets[i]; + + dev_add_param_mac(&priv->dev, xasprintf("mac_addr%d", i), + imx_ocotp_set_mac, imx_ocotp_get_mac, + ethaddr->value, ethaddr); + } + + /* + * Alias to mac_addr0 for backwards compatibility + */ + ethaddr = &priv->ethaddr[0]; + dev_add_param_mac(&priv->dev, "mac_addr", + imx_ocotp_set_mac, imx_ocotp_get_mac, + ethaddr->value, ethaddr); + } dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv); @@ -533,16 +559,22 @@ static u32 vf610_addr_to_offset(u32 addr) static struct imx_ocotp_data imx6q_ocotp_data = { .num_regs = 512, .addr_to_offset = imx6q_addr_to_offset, + .mac_offsets_num = 1, + .mac_offsets = { MAC_OFFSET_0 }, }; static struct imx_ocotp_data imx6sl_ocotp_data = { .num_regs = 256, .addr_to_offset = imx6sl_addr_to_offset, + .mac_offsets_num = 1, + .mac_offsets = { MAC_OFFSET_0 }, }; static struct imx_ocotp_data vf610_ocotp_data = { .num_regs = 512, .addr_to_offset = vf610_addr_to_offset, + .mac_offsets_num = 2, + .mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 }, }; static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = { -- cgit v1.2.3 From 390f49096e8b1dea250ab4439461211601e51f03 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:08:57 -0800 Subject: i.MX: ocotp: Initialize OCOTP as early as possible On Vybrid SoC OCOTP module contains speed grading information that is needed to correctly adjust CPU clock to its maxumum rate, so we need to have this information handy as early as possible. Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/ocotp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-imx/ocotp.c') diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index bd5448dddb..c67e37ad01 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -610,4 +610,4 @@ static int imx_ocotp_init(void) return 0; } -coredevice_initcall(imx_ocotp_init); +postcore_initcall(imx_ocotp_init); -- cgit v1.2.3 From afaf9bf09f02df46dcf3d7cbe0694a00d0170d21 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:08:59 -0800 Subject: i.MX: ocotp: Add imx_ocotp_sense_enable() Add imx_ocotp_sense_enable() function to allow changing that aspect of OCOTP driver behaviour before calling imx_ocotp_read_field() Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/include/mach/ocotp.h | 1 + arch/arm/mach-imx/ocotp.c | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'arch/arm/mach-imx/ocotp.c') diff --git a/arch/arm/mach-imx/include/mach/ocotp.h b/arch/arm/mach-imx/include/mach/ocotp.h index 430bc756be..5474c27ede 100644 --- a/arch/arm/mach-imx/include/mach/ocotp.h +++ b/arch/arm/mach-imx/include/mach/ocotp.h @@ -16,5 +16,6 @@ int imx_ocotp_read_field(uint32_t field, unsigned *value); int imx_ocotp_write_field(uint32_t field, unsigned value); int imx_ocotp_permanent_write(int enable); +bool imx_ocotp_sense_enable(bool enable); #endif /* __MACH_IMX_OCOTP_H */ diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index c67e37ad01..99b365aad8 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -359,6 +359,13 @@ int imx_ocotp_permanent_write(int enable) return 0; } +bool imx_ocotp_sense_enable(bool enable) +{ + const bool old_value = imx_ocotp->sense_enable; + imx_ocotp->sense_enable = enable; + return old_value; +} + static uint32_t inc_offset(uint32_t offset) { if ((offset & 0x3) == 0x3) -- cgit v1.2.3