From 7b083d82554966e94e2ec16cb8df72dde08acbea Mon Sep 17 00:00:00 2001 From: Andrejs Cainikovs Date: Mon, 27 May 2019 17:10:16 +0200 Subject: [PATCH] nmhw23: add sjainfo command --- cmd/Kconfig | 8 +++ cmd/Makefile | 2 + cmd/sjainfo.c | 115 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/sja1105.c | 57 +++++++++++++-------- include/sja1105.h | 18 +++++++ 5 files changed, 180 insertions(+), 20 deletions(-) create mode 100644 cmd/sjainfo.c create mode 100644 include/sja1105.h diff --git a/cmd/Kconfig b/cmd/Kconfig index 0b07b3b9d7..dac21ef04f 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1932,4 +1932,12 @@ config CMD_UBIFS help UBIFS is a file system for flash devices which works on top of UBI. +config CMD_SJAINFO + bool "sjainfo - SJA1105 ethernet switch information tool" + depends on SJA1105 + default y if SJA1105 + help + Enables "sjainfo" command to dump MAC status register and RX/TX frame + counter for every SJA1105 port. + endmenu diff --git a/cmd/Makefile b/cmd/Makefile index acb85f49fb..9d22c9c3d7 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -163,6 +163,8 @@ obj-$(CONFIG_CMD_GPT) += gpt.o obj-$(CONFIG_CMD_ETHSW) += ethsw.o obj-$(CONFIG_CMD_AXI) += axi.o +obj-$(CONFIG_CMD_SJAINFO) += sjainfo.o + # Power obj-$(CONFIG_CMD_PMIC) += pmic.o obj-$(CONFIG_CMD_REGULATOR) += regulator.o diff --git a/cmd/sjainfo.c b/cmd/sjainfo.c new file mode 100644 index 0000000000..d77dcd24ed --- /dev/null +++ b/cmd/sjainfo.c @@ -0,0 +1,115 @@ +/* + * sja1105.c + * + * Functions for NXP SJA1105 Ethernet Switch + * + * Copyright (C) 2018-2019 NetModule AG - http://www.netmodule.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include + +#if !defined(CONFIG_SPL_BUILD) + +#define SJA_NUM_PORTS 5 + +#define SJA_REG_MST_ADDR 0x0200 +#define SJA_REG_MST_INCR 0x02 +#define SJA_REG_RXF_ADDR 0x0406 +#define SJA_REG_RXF_INCR 0x10 +#define SJA_REG_TXF_ADDR 0x0402 +#define SJA_REG_TXF_INCR 0x10 + +struct sja1105_stat +{ + uint32_t mst; + uint32_t rxf; + uint32_t txf; +}; + +static int read_stat(struct spi_slave *spi, struct sja1105_stat *s, int n) +{ + int ret = 0; + + if (!ret) ret = sja1105_read_reg(spi, SJA_REG_MST_ADDR + SJA_REG_MST_INCR * n, &s->mst); + if (!ret) ret = sja1105_read_reg(spi, SJA_REG_RXF_ADDR + SJA_REG_RXF_INCR * n, &s->txf); + if (!ret) ret = sja1105_read_reg(spi, SJA_REG_TXF_ADDR + SJA_REG_TXF_INCR * n, &s->rxf); + + return ret; +} + +static int do_sjainfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct spi_slave *spi; + struct sja1105_stat s[SJA_NUM_PORTS] = { 0 }; + int i; + int ret; + + /* Get sja1105 device */ + + ret = uclass_get_device_by_name(UCLASS_MISC, "sja1105", &dev); + if (ret) + { + printf("sjainfo: switch not found\n"); + return 1; + } + + /* Try to claim SPI bus */ + + spi = dev_get_parent_priv(dev); + if (!spi) + { + printf("sja1105: switch SPI bus not found\n"); + return 1; + } + + ret = spi_claim_bus(spi); + if (ret) + { + printf("sja1105: unable to claim SPI bus\n"); + return 1; + } + + /* Read stats */ + + for (i = 0; i < SJA_NUM_PORTS && !ret; i++) + { + ret = read_stat(spi, &s[i], i); + } + if (ret) + { + printf("sjainfo: could not read port %d status registers\n", i); + goto exit; + } + + printf("Port MAC Stat\t\tRx\tTx\n"); + printf("0 (UM) : %08x\t\t%u\t%u\n", s[0].mst, s[0].rxf, s[0].txf); + printf("1 (BroadR-0) : %08x\t\t%u\t%u\n", s[1].mst, s[1].rxf, s[1].txf); + printf("2 (BroadR-1) : %08x\t\t%u\t%u\n", s[2].mst, s[2].rxf, s[2].txf); + printf("3 (100bTx) : %08x\t\t%u\t%u\n", s[3].mst, s[3].rxf, s[3].txf); + printf("4 (CPU) : %08x\t\t%u\t%u\n", s[4].mst, s[4].rxf, s[4].txf); + + /* Done */ + +exit: + + /* Release SPI bus */ + + spi_release_bus(spi); + + return 0; +} + +U_BOOT_CMD( + sjainfo, 1, 1, do_sjainfo, + "Show SJA1105 ethernet switch information", + "" +); + +#endif diff --git a/drivers/net/sja1105.c b/drivers/net/sja1105.c index 0107c9f299..31ac9d1a72 100644 --- a/drivers/net/sja1105.c +++ b/drivers/net/sja1105.c @@ -14,6 +14,10 @@ #include #include +#include + +#if !defined(CONFIG_SPL_BUILD) + #define SJA_OPCODE_WRITE 0x80 #define SJA_OPCODE_READ 0x00 #define SJA_READ_CNT(x) (((x) & 0x3F) << 1) @@ -63,7 +67,7 @@ int sja1105_read_reg(struct spi_slave *spi, uint32_t address, uint32_t *value) return ret; } -int sja1105_write_reg(struct spi_slave *spi, uint32_t address, uint32_t data) +static int sja1105_write_reg(struct spi_slave *spi, uint32_t address, uint32_t data) { uint8_t out[8]; @@ -83,7 +87,7 @@ int sja1105_write_reg(struct spi_slave *spi, uint32_t address, uint32_t data) SPI_XFER_BEGIN | SPI_XFER_END); } -int sja1105_local_crc_check(struct spi_slave *spi) +static int sja1105_local_crc_check(struct spi_slave *spi) { uint32_t status; int ret; @@ -102,7 +106,7 @@ int sja1105_local_crc_check(struct spi_slave *spi) return 0; } -int sja1105_global_crc_check(struct spi_slave *spi) +static int sja1105_global_crc_check(struct spi_slave *spi) { uint32_t status; int ret; @@ -121,7 +125,7 @@ int sja1105_global_crc_check(struct spi_slave *spi) return 0; } -int sja1105_config_check(struct spi_slave *spi) +static int sja1105_config_check(struct spi_slave *spi) { uint32_t status; int ret; @@ -140,7 +144,7 @@ int sja1105_config_check(struct spi_slave *spi) return -1; } -int sja1105_configure_block(struct spi_slave *spi, int block, const uint8_t *data, size_t length) +static int sja1105_configure_block(struct spi_slave *spi, int block, const uint8_t *data, size_t length) { int ret; @@ -161,7 +165,7 @@ int sja1105_configure_block(struct spi_slave *spi, int block, const uint8_t *dat return 0; } -int sja1105_configure_firmware(struct spi_slave *spi) +static int sja1105_configure_firmware(struct spi_slave *spi) { static const uint8_t config_data_0[] = { 0x80, 0x20, 0x00, 0x00, 0x9E, 0x00, 0x03, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x21, 0x6F, 0x25, 0x6B, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF }; static const uint8_t config_data_1[] = { 0x80, 0x20, 0x04, 0x00, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFE, 0xF7, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFA, 0x2E, 0x19, 0xF8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7D, 0x0B, 0xCB, 0xF2, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x7F, 0x09, 0x52, 0x68, 0x0D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x6A, 0xF6, 0x23, 0x53, 0x10, 0x00, 0x00, 0x00, 0xF7, 0xBD, 0xF5, 0x8D, 0x10, 0x00, 0x00, 0x00, 0xEF, 0x7B, 0xF5, 0x8D, 0x10, 0x00, 0x00, 0x00, 0xDE, 0xF7, 0xF5, 0x8D, 0x10, 0x00, 0x00, 0x00, 0xBD, 0xEF, 0xF5, 0x8D, 0x10, 0x00, 0x00, 0x00, 0x7B, 0xDF, 0xF5, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x04, 0xA6, 0x06, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xDA, 0xB5, 0xBD, 0xC8, 0x00, 0x3F, 0xFC, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -202,7 +206,7 @@ int sja1105_configure_firmware(struct spi_slave *spi) return ret; } -int sja1105_configure_mode_and_clocks(struct spi_slave *spi) +static int sja1105_configure_mode_and_clocks(struct spi_slave *spi) { int ret = 0; @@ -257,7 +261,7 @@ int sja1105_configure_mode_and_clocks(struct spi_slave *spi) return ret; } -int sja1105_configure_io(struct spi_slave *spi) +static int sja1105_configure_io(struct spi_slave *spi) { int ret = 0; @@ -301,21 +305,21 @@ static int sja1105_probe(struct udevice *dev) if (ret) { printf("sja1105: unable to get HSM reset gpio\n"); - return ret; + goto exit; } ret = gpio_request_by_name(dev, "gpio-reset-phy", 0, &priv->rst_phy, GPIOD_IS_OUT); if (ret) { printf("sja1105: unable to get PHY reset gpio\n"); - return ret; + goto exit_gpio_hsm; } ret = gpio_request_by_name(dev, "gpio-reset-sw", 0, &priv->rst_sw, GPIOD_IS_OUT); if (ret) { printf("sja1105: unable to get switch reset gpio\n"); - return ret; + goto exit_gpio_phy; } /* Put HSM, PHY and switch into reset */ @@ -340,20 +344,16 @@ static int sja1105_probe(struct udevice *dev) if (ret) { printf("sja1105: unable to claim SPI bus\n"); - return ret; + goto exit_gpio_sw; } - /* 1ms delay after init before first SPI access */ - - mdelay(1); - /* Configure firmware */ ret = sja1105_configure_firmware(priv->spi); if (ret) { printf("sja1105: unable to configure firmware\n"); - goto exit; + goto exit_spi_release; } /* Configure mode & clocks */ @@ -362,7 +362,7 @@ static int sja1105_probe(struct udevice *dev) if (ret) { printf("sja1105: unable to configure mode and clocks\n"); - goto exit; + goto exit_spi_release; } /* Configure IO pads */ @@ -371,14 +371,29 @@ static int sja1105_probe(struct udevice *dev) if (ret) { printf("sja1105: unable to configure IO pads\n"); - goto exit; + goto exit_spi_release; } /* Done */ -exit: +exit_spi_release: + spi_release_bus(priv->spi); +exit_gpio_sw: + + dm_gpio_free(dev, &priv->rst_sw); + +exit_gpio_phy: + + dm_gpio_free(dev, &priv->rst_phy); + +exit_gpio_hsm: + + dm_gpio_free(dev, &priv->rst_hsm); + +exit: + return ret; } @@ -394,3 +409,5 @@ U_BOOT_DRIVER(sja1105) = { .probe = sja1105_probe, .priv_auto_alloc_size = sizeof(struct sja1105_priv) }; + +#endif diff --git a/include/sja1105.h b/include/sja1105.h new file mode 100644 index 0000000000..af91c38303 --- /dev/null +++ b/include/sja1105.h @@ -0,0 +1,18 @@ +/* + * sja1105.h + * + * Functions for NXP SJA1105 Ethernet Switch + * + * Copyright (C) 2018-2019 NetModule AG - http://www.netmodule.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SJA1105_H_ +#define _SJA1105_H_ + +#include + +int sja1105_read_reg(struct spi_slave *spi, uint32_t address, uint32_t *value); + +#endif