9
0
Fork 0

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<n>' parameters as
well as 'mac_addr' as an "alias" to 'mac_addr0' for backwards
compatibility.

Acked-by: Stefan Lengfeld <s.lengfeld@phytec.de>
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Andrey Smirnov 2017-01-10 07:08:56 -08:00 committed by Sascha Hauer
parent f36c383bcc
commit 75b6972be4
1 changed files with 51 additions and 19 deletions

View File

@ -69,12 +69,22 @@
/* Other definitions */ /* Other definitions */
#define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA #define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA
#define DEF_RELAX 20 #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 #define MAC_BYTES 8
struct imx_ocotp_data { struct imx_ocotp_data {
int num_regs; int num_regs;
u32 (*addr_to_offset)(u32 addr); 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 { struct ocotp_priv {
@ -84,9 +94,10 @@ struct ocotp_priv {
struct device_d dev; struct device_d dev;
int permanent_write_enable; int permanent_write_enable;
int sense_enable; int sense_enable;
char ethaddr[6]; struct ocotp_priv_ethaddr ethaddr[MAX_MAC_OFFSETS];
struct regmap_config map_config; struct regmap_config map_config;
const struct imx_ocotp_data *data; const struct imx_ocotp_data *data;
int mac_offset_idx;
}; };
static struct ocotp_priv *imx_ocotp; 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) static int imx_ocotp_get_mac(struct param_d *param, void *priv)
{ {
struct ocotp_priv *ocotp_priv = priv; char buf[MAC_BYTES];
char buf[8];
int ret; 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) if (ret < 0)
return ret; return ret;
memreverse(ocotp_priv->ethaddr, buf, 6); memreverse(ethaddr->value, buf, 6);
return 0; return 0;
} }
static int imx_ocotp_set_mac(struct param_d *param, void *priv) static int imx_ocotp_set_mac(struct param_d *param, void *priv)
{ {
struct ocotp_priv *ocotp_priv = priv; char buf[MAC_BYTES];
char buf[8]; struct ocotp_priv_ethaddr *ethaddr = priv;
int ret;
memreverse(buf, ocotp_priv->ethaddr, 6); memreverse(buf, ethaddr->value, 6);
buf[6] = 0; buf[7] = 0;
ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); return regmap_bulk_write(ethaddr->map, ethaddr->offset,
if (ret < 0) buf, MAC_BYTES);
return ret;
return 0;
} }
static struct regmap_bus imx_ocotp_regmap_bus = { 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); NULL, NULL, &priv->permanent_write_enable, NULL);
} }
if (IS_ENABLED(CONFIG_NET)) if (IS_ENABLED(CONFIG_NET)) {
dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac, int i;
imx_ocotp_get_mac, priv->ethaddr, priv); 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); 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 = { static struct imx_ocotp_data imx6q_ocotp_data = {
.num_regs = 512, .num_regs = 512,
.addr_to_offset = imx6q_addr_to_offset, .addr_to_offset = imx6q_addr_to_offset,
.mac_offsets_num = 1,
.mac_offsets = { MAC_OFFSET_0 },
}; };
static struct imx_ocotp_data imx6sl_ocotp_data = { static struct imx_ocotp_data imx6sl_ocotp_data = {
.num_regs = 256, .num_regs = 256,
.addr_to_offset = imx6sl_addr_to_offset, .addr_to_offset = imx6sl_addr_to_offset,
.mac_offsets_num = 1,
.mac_offsets = { MAC_OFFSET_0 },
}; };
static struct imx_ocotp_data vf610_ocotp_data = { static struct imx_ocotp_data vf610_ocotp_data = {
.num_regs = 512, .num_regs = 512,
.addr_to_offset = vf610_addr_to_offset, .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[] = { static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {