Message ID | 1525875740-31352-1-git-send-email-radu-andrei.bulie@nxp.com |
---|---|
State | Superseded |
Delegated to: | York Sun |
Headers | show |
Series | [U-Boot] drivers/net/vsc9953: Initialize action RAM in VCAP complex | expand |
On Wed, May 9, 2018 at 9:22 AM, <radu-andrei.bulie@nxp.com> wrote: > From: Radu Bulie <radu-andrei.bulie@nxp.com> > > VCAP tables must be initialized even if no advanced classification > is used. If no initialization is performed, then ECC error will > be observed by the user when the first packet enters the l2switch. > The error is marked in MPIC_EISR0 -bit 29 which means - Internal RAM > multi-bit ECC error. > This patch fixes the aforementioned ECC error by performing the > initialization of VCAP tables. > > Signed-off-by: Radu Bulie <radu-andrei.bulie@nxp.com> > --- > drivers/net/vsc9953.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ > include/vsc9953.h | 58 ++++++++++++++++++++++ > 2 files changed, 192 insertions(+) > > diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c > index 2388438..f90181d 100644 > --- a/drivers/net/vsc9953.c > +++ b/drivers/net/vsc9953.c > @@ -2469,6 +2469,139 @@ void vsc9953_default_configuration(void) > debug("VSC9953: failed to set default aggregation code mode\n"); > } > > +static void vcap_entry2cache_init(u32 target, u32 entry_words) > +{ > + int i; > + > + for (i = 0; i < entry_words; i++) { > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CACHE_ENTRY_DAT(target, i)), 0x00); > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CACHE_MASK_DAT(target, i)), 0xFF); > + } > + > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CACHE_TG_DAT(target)), 0x00); > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CFG_MV_CFG(target)), > + VSC9953_VCAP_CFG_MV_CFG_SIZE(entry_words)); > +} > + > +static void vcap_action2cache_init(u32 target, u32 action_words, > + u32 counter_words) > +{ > + int i; > + > + for (i = 0; i < action_words; i++) > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CACHE_ACTION_DAT(target, i)), 0x00); > + > + for (i = 0; i < counter_words; i++) > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CACHE_CNT_DAT(target, i)), 0x00); > +} > + > +static int vcap_cmd(u32 target, u16 ix, int cmd, int sel, int entry_count) > +{ > + u32 tgt = target; > + u32 value = (VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(cmd) | > + VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(ix) | > + VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT); > + > + if ((sel & TCAM_SEL_ENTRY) && ix >= entry_count) > + return CMD_RET_FAILURE; > + > + if (!(sel & TCAM_SEL_ENTRY)) > + value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS; > + > + if (!(sel & TCAM_SEL_ACTION)) > + value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS; > + > + if (!(sel & TCAM_SEL_COUNTER)) > + value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS; > + > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)), value); > + > + do { > + value = in_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CFG_UPDATE_CTRL(tgt))); > + > + } while (value & VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT); > + > + return CMD_RET_SUCCESS; > +} > + > +static void vsc9953_vcap_init(void) > +{ > + u32 tgt = VSC9953_ES0; > + int cmd_ret; > + > + /* write entries */ > + vcap_entry2cache_init(tgt, ENTRY_WORDS_ES0); > + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY, > + ENTRY_WORDS_ES0); > + if (cmd_ret != CMD_RET_SUCCESS) > + debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n", > + __LINE__); > + > + /* write actions and counters */ > + vcap_action2cache_init(tgt, BITS_TO_DWORD(91), BITS_TO_DWORD(1)); > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CFG_MV_CFG(tgt)), > + VSC9953_VCAP_CFG_MV_CFG_SIZE(VSC9953_ES0_CNT + VSC9953_PORTS)); > + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, > + TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_ES0); > + if (cmd_ret != CMD_RET_SUCCESS) > + debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n", > + __LINE__); > + > + tgt = VSC9953_IS1; > + > + /* write entries */ > + vcap_entry2cache_init(tgt, ENTRY_WORDS_IS1); > + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY, > + ENTRY_WORDS_IS1); > + if (cmd_ret != CMD_RET_SUCCESS) > + debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n", > + __LINE__); > + > + /* write actions and counters */ > + vcap_action2cache_init(tgt, BITS_TO_DWORD(320), BITS_TO_DWORD(4)); > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CFG_MV_CFG(tgt)), > + VSC9953_VCAP_CFG_MV_CFG_SIZE(VSC9953_IS1_CNT + 1)); > + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, > + TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS1); > + if (cmd_ret != CMD_RET_SUCCESS) > + debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n", > + __LINE__); > + > + tgt = VSC9953_IS2; > + > + /* write entries */ > + vcap_entry2cache_init(tgt, ENTRY_WORDS_IS2); > + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY, > + ENTRY_WORDS_IS2); > + if (cmd_ret != CMD_RET_SUCCESS) > + debug("VSC9953:%d invalid selection: TCAM_SEL_ENTRY\n", > + __LINE__); > + > + /* write actions and counters */ > + vcap_action2cache_init(tgt, BITS_TO_DWORD(103 - 2 * > + VSC9953_PORT_OFFSET), > + BITS_TO_DWORD(4 * 32)); Please don't use magic numbers. > + out_le32((unsigned int *)(VSC9953_OFFSET + > + VSC9953_VCAP_CFG_MV_CFG(tgt)), > + VSC9953_VCAP_CFG_MV_CFG_SIZE(VSC9953_IS2_CNT + > + VSC9953_PORTS + 2)); Why plus 2? Comment at least, but probably a define. > + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, > + TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS2); > + if (cmd_ret != CMD_RET_SUCCESS) > + debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n", > + __LINE__); > +} > + > void vsc9953_init(bd_t *bis) > { > u32 i; > @@ -2605,6 +2738,7 @@ void vsc9953_init(bd_t *bis) > } > } > > + vsc9953_vcap_init(); > vsc9953_default_configuration(); > > #ifdef CONFIG_CMD_ETHSW > diff --git a/include/vsc9953.h b/include/vsc9953.h > index a2d4554..a1c31ce 100644 > --- a/include/vsc9953.h > +++ b/include/vsc9953.h > @@ -187,6 +187,64 @@ > > #define MIIMIND_OPR_PEND 0x00000004 > > +#define VSC9953_BIT(x) (1U << (x)) Please use the standard macros for all. > +#define VSC9953_IO_BASE_OFFSET 0x00000000 This doesn't seem to add anything (literally). > +#define VSC9953_IO_OFFSET(offset) (VSC9953_IO_BASE_OFFSET + offset) > +#define VSC9953_BITMASK(x) ((1U << (x)) - 1) > +#define VSC9953_ENC_BITFIELD(x, o, w) (((x) & VSC9953_BITMASK(w)) << (o)) > +#define VSC9953_IO_ADDR(t, o) ((((t) - VSC9953_IO_BASE_OFFSET)) + \ > + (o << 2)) Please use descriptive parameters, not single letters. Also, whatever "o" is, should be "(o)". > + > +#define VSC9953_IO_REG(t, o) (VSC9953_IO_ADDR(t, o)) > +#define VSC9953_VCAP_CACHE_ENTRY_DAT(target, ri) \ > + VSC9953_IO_REG(target, (0x2 + (ri))) > + > +#define VSC9953_VCAP_CACHE_MASK_DAT(target, ri) \ > + VSC9953_IO_REG(target, (0x42 + (ri))) > + > +#define VSC9953_VCAP_CACHE_TG_DAT(target) VSC9953_IO_REG(target, 0xe2) > +#define VSC9953_VCAP_CFG_MV_CFG(target) VSC9953_IO_REG(target, 0x1) > +#define VSC9953_VCAP_CFG_MV_CFG_SIZE(x) VSC9953_ENC_BITFIELD(x, 0, 16) > +#define VSC9953_VCAP_CFG_UPDATE_CTRL(target) VSC9953_IO_REG(target, 0x0) > +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(x) VSC9953_ENC_BITFIELD(x, 22, 3) > +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(x) VSC9953_ENC_BITFIELD(x, 3, 16) > +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT VSC9953_BIT(2) > +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS VSC9953_BIT(21) > +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS VSC9953_BIT(20) > +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS VSC9953_BIT(19) > +#define VSC9953_VCAP_CACHE_ACTION_DAT(target, ri) \ > + VSC9953_IO_REG(target, (0x82 + (ri))) > + > +#define VSC9953_VCAP_CACHE_CNT_DAT(target, ri) \ > + VSC9953_IO_REG(target, (0xc2 + (ri))) > + > +#define VSC9953_PORT_OFFSET 1 > +#define VSC9953_IS1_CNT 256 > +#define VSC9953_IS2_CNT 1024 > +#define VSC9953_ES0_CNT 1024 > + > +#define BITS_TO_DWORD(x) (1 + (((x) - 1) / 32)) > +#define ENTRY_WORDS_ES0 BITS_TO_DWORD(29) > +#define ENTRY_WORDS_IS1 BITS_TO_DWORD(376) > +#define ENTRY_WORDS_IS2 BITS_TO_DWORD(376) > +#define VSC9953_PORTS VSC9953_MAX_PORTS Why do we need another name for this? > + > +/* TCAM entries */ > +enum tcam_sel { > + TCAM_SEL_ENTRY = VSC9953_BIT(0), > + TCAM_SEL_ACTION = VSC9953_BIT(1), > + TCAM_SEL_COUNTER = VSC9953_BIT(2), > + TCAM_SEL_ALL = VSC9953_BITMASK(3), > +}; > + > +enum tcam_cmd { > + TCAM_CMD_WRITE = 0, > + TCAM_CMD_READ = 1, > + TCAM_CMD_MOVE_UP = 2, > + TCAM_CMD_MOVE_DOWN = 3, > + TCAM_CMD_INITIALIZE = 4, > +}; > + > struct vsc9953_mdio_info { > struct vsc9953_mii_mng *regs; > char *name; > -- > 1.9.1 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > https://lists.denx.de/listinfo/u-boot
diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c index 2388438..f90181d 100644 --- a/drivers/net/vsc9953.c +++ b/drivers/net/vsc9953.c @@ -2469,6 +2469,139 @@ void vsc9953_default_configuration(void) debug("VSC9953: failed to set default aggregation code mode\n"); } +static void vcap_entry2cache_init(u32 target, u32 entry_words) +{ + int i; + + for (i = 0; i < entry_words; i++) { + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CACHE_ENTRY_DAT(target, i)), 0x00); + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CACHE_MASK_DAT(target, i)), 0xFF); + } + + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CACHE_TG_DAT(target)), 0x00); + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CFG_MV_CFG(target)), + VSC9953_VCAP_CFG_MV_CFG_SIZE(entry_words)); +} + +static void vcap_action2cache_init(u32 target, u32 action_words, + u32 counter_words) +{ + int i; + + for (i = 0; i < action_words; i++) + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CACHE_ACTION_DAT(target, i)), 0x00); + + for (i = 0; i < counter_words; i++) + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CACHE_CNT_DAT(target, i)), 0x00); +} + +static int vcap_cmd(u32 target, u16 ix, int cmd, int sel, int entry_count) +{ + u32 tgt = target; + u32 value = (VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(cmd) | + VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(ix) | + VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT); + + if ((sel & TCAM_SEL_ENTRY) && ix >= entry_count) + return CMD_RET_FAILURE; + + if (!(sel & TCAM_SEL_ENTRY)) + value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS; + + if (!(sel & TCAM_SEL_ACTION)) + value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS; + + if (!(sel & TCAM_SEL_COUNTER)) + value |= VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS; + + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CFG_UPDATE_CTRL(tgt)), value); + + do { + value = in_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CFG_UPDATE_CTRL(tgt))); + + } while (value & VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT); + + return CMD_RET_SUCCESS; +} + +static void vsc9953_vcap_init(void) +{ + u32 tgt = VSC9953_ES0; + int cmd_ret; + + /* write entries */ + vcap_entry2cache_init(tgt, ENTRY_WORDS_ES0); + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY, + ENTRY_WORDS_ES0); + if (cmd_ret != CMD_RET_SUCCESS) + debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n", + __LINE__); + + /* write actions and counters */ + vcap_action2cache_init(tgt, BITS_TO_DWORD(91), BITS_TO_DWORD(1)); + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CFG_MV_CFG(tgt)), + VSC9953_VCAP_CFG_MV_CFG_SIZE(VSC9953_ES0_CNT + VSC9953_PORTS)); + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, + TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_ES0); + if (cmd_ret != CMD_RET_SUCCESS) + debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n", + __LINE__); + + tgt = VSC9953_IS1; + + /* write entries */ + vcap_entry2cache_init(tgt, ENTRY_WORDS_IS1); + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY, + ENTRY_WORDS_IS1); + if (cmd_ret != CMD_RET_SUCCESS) + debug("VSC9953:%d invalid TCAM_SEL_ENTRY\n", + __LINE__); + + /* write actions and counters */ + vcap_action2cache_init(tgt, BITS_TO_DWORD(320), BITS_TO_DWORD(4)); + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CFG_MV_CFG(tgt)), + VSC9953_VCAP_CFG_MV_CFG_SIZE(VSC9953_IS1_CNT + 1)); + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, + TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS1); + if (cmd_ret != CMD_RET_SUCCESS) + debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n", + __LINE__); + + tgt = VSC9953_IS2; + + /* write entries */ + vcap_entry2cache_init(tgt, ENTRY_WORDS_IS2); + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, TCAM_SEL_ENTRY, + ENTRY_WORDS_IS2); + if (cmd_ret != CMD_RET_SUCCESS) + debug("VSC9953:%d invalid selection: TCAM_SEL_ENTRY\n", + __LINE__); + + /* write actions and counters */ + vcap_action2cache_init(tgt, BITS_TO_DWORD(103 - 2 * + VSC9953_PORT_OFFSET), + BITS_TO_DWORD(4 * 32)); + out_le32((unsigned int *)(VSC9953_OFFSET + + VSC9953_VCAP_CFG_MV_CFG(tgt)), + VSC9953_VCAP_CFG_MV_CFG_SIZE(VSC9953_IS2_CNT + + VSC9953_PORTS + 2)); + cmd_ret = vcap_cmd(tgt, 0, TCAM_CMD_INITIALIZE, + TCAM_SEL_ACTION | TCAM_SEL_COUNTER, ENTRY_WORDS_IS2); + if (cmd_ret != CMD_RET_SUCCESS) + debug("VSC9953:%d invalid TCAM_SEL_ACTION | TCAM_SEL_COUNTER\n", + __LINE__); +} + void vsc9953_init(bd_t *bis) { u32 i; @@ -2605,6 +2738,7 @@ void vsc9953_init(bd_t *bis) } } + vsc9953_vcap_init(); vsc9953_default_configuration(); #ifdef CONFIG_CMD_ETHSW diff --git a/include/vsc9953.h b/include/vsc9953.h index a2d4554..a1c31ce 100644 --- a/include/vsc9953.h +++ b/include/vsc9953.h @@ -187,6 +187,64 @@ #define MIIMIND_OPR_PEND 0x00000004 +#define VSC9953_BIT(x) (1U << (x)) +#define VSC9953_IO_BASE_OFFSET 0x00000000 +#define VSC9953_IO_OFFSET(offset) (VSC9953_IO_BASE_OFFSET + offset) +#define VSC9953_BITMASK(x) ((1U << (x)) - 1) +#define VSC9953_ENC_BITFIELD(x, o, w) (((x) & VSC9953_BITMASK(w)) << (o)) +#define VSC9953_IO_ADDR(t, o) ((((t) - VSC9953_IO_BASE_OFFSET)) + \ + (o << 2)) + +#define VSC9953_IO_REG(t, o) (VSC9953_IO_ADDR(t, o)) +#define VSC9953_VCAP_CACHE_ENTRY_DAT(target, ri) \ + VSC9953_IO_REG(target, (0x2 + (ri))) + +#define VSC9953_VCAP_CACHE_MASK_DAT(target, ri) \ + VSC9953_IO_REG(target, (0x42 + (ri))) + +#define VSC9953_VCAP_CACHE_TG_DAT(target) VSC9953_IO_REG(target, 0xe2) +#define VSC9953_VCAP_CFG_MV_CFG(target) VSC9953_IO_REG(target, 0x1) +#define VSC9953_VCAP_CFG_MV_CFG_SIZE(x) VSC9953_ENC_BITFIELD(x, 0, 16) +#define VSC9953_VCAP_CFG_UPDATE_CTRL(target) VSC9953_IO_REG(target, 0x0) +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_CMD(x) VSC9953_ENC_BITFIELD(x, 22, 3) +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ADDR(x) VSC9953_ENC_BITFIELD(x, 3, 16) +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_SHOT VSC9953_BIT(2) +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS VSC9953_BIT(21) +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS VSC9953_BIT(20) +#define VSC9953_VCAP_UPDATE_CTRL_UPDATE_CNT_DIS VSC9953_BIT(19) +#define VSC9953_VCAP_CACHE_ACTION_DAT(target, ri) \ + VSC9953_IO_REG(target, (0x82 + (ri))) + +#define VSC9953_VCAP_CACHE_CNT_DAT(target, ri) \ + VSC9953_IO_REG(target, (0xc2 + (ri))) + +#define VSC9953_PORT_OFFSET 1 +#define VSC9953_IS1_CNT 256 +#define VSC9953_IS2_CNT 1024 +#define VSC9953_ES0_CNT 1024 + +#define BITS_TO_DWORD(x) (1 + (((x) - 1) / 32)) +#define ENTRY_WORDS_ES0 BITS_TO_DWORD(29) +#define ENTRY_WORDS_IS1 BITS_TO_DWORD(376) +#define ENTRY_WORDS_IS2 BITS_TO_DWORD(376) +#define VSC9953_PORTS VSC9953_MAX_PORTS + +/* TCAM entries */ +enum tcam_sel { + TCAM_SEL_ENTRY = VSC9953_BIT(0), + TCAM_SEL_ACTION = VSC9953_BIT(1), + TCAM_SEL_COUNTER = VSC9953_BIT(2), + TCAM_SEL_ALL = VSC9953_BITMASK(3), +}; + +enum tcam_cmd { + TCAM_CMD_WRITE = 0, + TCAM_CMD_READ = 1, + TCAM_CMD_MOVE_UP = 2, + TCAM_CMD_MOVE_DOWN = 3, + TCAM_CMD_INITIALIZE = 4, +}; + struct vsc9953_mdio_info { struct vsc9953_mii_mng *regs; char *name;