[U-Boot] [PATCH] drivers/net/vsc9953: Initialize action RAM in VCAP complex
Joe Hershberger
joe.hershberger at ni.com
Wed May 16 22:37:48 UTC 2018
On Wed, May 9, 2018 at 9:22 AM, <radu-andrei.bulie at nxp.com> wrote:
> From: Radu Bulie <radu-andrei.bulie at 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 at 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 at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
More information about the U-Boot
mailing list