diff --git a/arch/arm/dts/imx8_nmhw23.dts b/arch/arm/dts/imx8_nmhw23.dts index e86d0b24a4..6d008566ae 100644 --- a/arch/arm/dts/imx8_nmhw23.dts +++ b/arch/arm/dts/imx8_nmhw23.dts @@ -35,7 +35,16 @@ gpio-mosi = <&gpio0 14 GPIO_ACTIVE_HIGH>; gpio-miso = <&gpio0 15 GPIO_ACTIVE_HIGH>; cs-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; - num-chipselects = <1>; + + sja1105 { + compatible = "nxp,sja1105"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reset_hsm &pinctrl_reset_phy &pinctrl_reset_sw>; + + gpio-reset-hsm = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpio-reset-phy = <&gpio4 6 GPIO_ACTIVE_LOW>; + gpio-reset-sw = <&gpio0 5 GPIO_ACTIVE_LOW>; + }; }; }; @@ -76,10 +85,28 @@ pinctrl_spi3: spi3_grp { fsl,pins = < - SC_P_SPI3_SCK_LSIO_GPIO0_IO13 0x00000060 - SC_P_SPI3_SDO_LSIO_GPIO0_IO14 0x00000020 - SC_P_SPI3_SDI_LSIO_GPIO0_IO15 0x00000020 - SC_P_SPI3_CS0_LSIO_GPIO0_IO16 0x00000060 + SC_P_SPI3_SCK_LSIO_GPIO0_IO13 0x00000041 + SC_P_SPI3_SDO_LSIO_GPIO0_IO14 0x00000041 + SC_P_SPI3_SDI_LSIO_GPIO0_IO15 0x00000041 + SC_P_SPI3_CS0_LSIO_GPIO0_IO16 0x00000061 + >; + }; + + pinctrl_reset_hsm: reset_hsm_grp { + fsl,pins = < + SC_P_SPDIF0_EXT_CLK_LSIO_GPIO0_IO12 0x00000060 + >; + }; + + pinctrl_reset_phy: reset_phy_grp { + fsl,pins = < + SC_P_USB_SS3_TC3_LSIO_GPIO4_IO06 0x06000021 + >; + }; + + pinctrl_reset_sw: reset_sw_grp { + fsl,pins = < + SC_P_ESAI0_TX1_LSIO_GPIO0_IO05 0x00000060 >; }; }; diff --git a/board/netmodule/imx8_nmhw23/imx8_nmhw23.c b/board/netmodule/imx8_nmhw23/imx8_nmhw23.c index d3cae048f7..045a856cde 100644 --- a/board/netmodule/imx8_nmhw23/imx8_nmhw23.c +++ b/board/netmodule/imx8_nmhw23/imx8_nmhw23.c @@ -66,21 +66,7 @@ int board_early_init_f(void) #if IS_ENABLED(CONFIG_DM_GPIO) static void board_gpio_init(void) { - struct gpio_desc desc; - int ret; - - ret = dm_gpio_lookup_name("gpio@1a_3", &desc); - if (ret) - return; - - ret = dm_gpio_request(&desc, "bb_per_rst_b"); - if (ret) - return; - - dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT); - dm_gpio_set_value(&desc, 0); - udelay(50); - dm_gpio_set_value(&desc, 1); + /* TODO */ } #else static inline void board_gpio_init(void) {} diff --git a/configs/imx8_nmhw23_defconfig b/configs/imx8_nmhw23_defconfig index af0a5ae605..b92e3e5df1 100644 --- a/configs/imx8_nmhw23_defconfig +++ b/configs/imx8_nmhw23_defconfig @@ -78,3 +78,4 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_SOFT_SPI=y CONFIG_CMD_SPI=y +CONFIG_SJA1105=y diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c4cbe34798..fdbe564ea8 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -421,4 +421,11 @@ config SYS_DPAA_QBMAN help QBman fixups to allow deep sleep in DPAA 1 SOCs +config SJA1105 + select DM_SPI + select DM_RESET + bool "NXP SJA1105 Ethernet switch support" + help + Enable support for NXP SJA1105 Ethernet switch. + endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 4a16c62bac..922ab69c76 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -73,3 +73,4 @@ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_SJA1105) += sja1105.o diff --git a/drivers/net/sja1105.c b/drivers/net/sja1105.c new file mode 100644 index 0000000000..0107c9f299 --- /dev/null +++ b/drivers/net/sja1105.c @@ -0,0 +1,396 @@ +/* + * 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 +#include + +#define SJA_OPCODE_WRITE 0x80 +#define SJA_OPCODE_READ 0x00 +#define SJA_READ_CNT(x) (((x) & 0x3F) << 1) + +#define SJA_REG_DEVICE_ID 0x000000 +#define SJA_REG_CONFIG_STATUS 0x000001 + +#define SJA_STATUS_CONFIG (1 << 31) +#define SJA_STATUS_CRC_LOCAL (1 << 30) +#define SJA_STATUS_CRC_GLOBAL (1 << 28) + +struct sja1105_priv +{ + struct spi_slave *spi; + + struct gpio_desc rst_hsm; + struct gpio_desc rst_phy; + struct gpio_desc rst_sw; +}; + +int sja1105_read_reg(struct spi_slave *spi, uint32_t address, uint32_t *value) +{ + uint8_t out[8]; + uint8_t in[8]; + int ret; + + /* Command: read [31], length [30-25], address [24-4] */ + + out[0] = (SJA_OPCODE_READ | SJA_READ_CNT(1)) | ((address >> 20) & 0x01); + out[1] = (address >> 12) & 0xFF; + out[2] = (address >> 4) & 0xFF; + out[3] = (address << 4) & 0xF0; + + out[4] = 0x00; + out[5] = 0x00; + out[6] = 0x00; + out[7] = 0x00; + + ret = spi_xfer(spi, 8 * sizeof(out), out, in, + SPI_XFER_BEGIN | SPI_XFER_END); + + if (!ret) + { + *value = (in[4] << 24) | (in[5] << 16) | (in[6] << 8) | (in[7] << 0); + } + + return ret; +} + +int sja1105_write_reg(struct spi_slave *spi, uint32_t address, uint32_t data) +{ + uint8_t out[8]; + + /* Command: write [31], address [24-4] */ + + out[0] = SJA_OPCODE_WRITE | (address >> 20 & 0x01); + out[1] = (address >> 12) & 0xFF;/* */ + out[2] = (address >> 4) & 0xFF; + out[3] = (address << 4) & 0xF0; + + out[4] = (data >> 24) & 0xFF; + out[5] = (data >> 16) & 0xFF; + out[6] = (data >> 8) & 0xFF; + out[7] = (data >> 0) & 0xFF; + + return spi_xfer(spi, 8 * sizeof(out), out, NULL, + SPI_XFER_BEGIN | SPI_XFER_END); +} + +int sja1105_local_crc_check(struct spi_slave *spi) +{ + uint32_t status; + int ret; + + ret = sja1105_read_reg(spi, SJA_REG_CONFIG_STATUS, &status); + if (ret) + { + printf("sja1105: failed to read status register\n"); + return ret; + } + if (status & SJA_STATUS_CRC_LOCAL) + { + return -1; + } + + return 0; +} + +int sja1105_global_crc_check(struct spi_slave *spi) +{ + uint32_t status; + int ret; + + ret = sja1105_read_reg(spi, SJA_REG_CONFIG_STATUS, &status); + if (ret) + { + printf("sja1105: failed to read status register\n"); + return ret; + } + if (status & SJA_STATUS_CRC_GLOBAL) + { + return -1; + } + + return 0; +} + +int sja1105_config_check(struct spi_slave *spi) +{ + uint32_t status; + int ret; + + ret = sja1105_read_reg(spi, SJA_REG_CONFIG_STATUS, &status); + if (ret) + { + printf("sja1105: failed to read status register\n"); + return ret; + } + if (status & SJA_STATUS_CONFIG) + { + return 0; + } + + return -1; +} + +int sja1105_configure_block(struct spi_slave *spi, int block, const uint8_t *data, size_t length) +{ + int ret; + + ret = spi_xfer(spi, 8 * length, data, NULL, + SPI_XFER_BEGIN | SPI_XFER_END); + if (ret) + { + printf("sja1105: failed to send configuration block %d\n", block); + return ret; + } + ret = sja1105_local_crc_check(spi); + if (ret) + { + printf("sja1105: CRC failed on configuration block %d\n", block); + return ret; + } + + return 0; +} + +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 }; + static const uint8_t config_data_2[] = { 0x80, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x75, 0xF9, 0x8D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x25, 0x0E, 0x7C, 0xBD, 0x00, 0x01, 0x25, 0xC0, 0x70, 0x94, 0x84, 0x50, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC8, 0xA7, 0xCE, 0xE6, 0x00, 0x71, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xF7, 0x04, 0xB9, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x57, 0x1F, 0x81, 0x3F, 0x06, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0D, 0xB0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x5A, 0x9C, 0x37, 0x20, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3A, 0x5D, 0x5E, 0x24, 0xA4, 0x9A, 0x00, 0x00, 0x7B, 0x51, 0xDA, 0x7D, 0x00, 0x00, 0x00, 0x00 }; + static const uint8_t config_data_3[] = { 0x80, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x6E, 0x02, 0x8B }; + + int ret = 0; + + /* Send firmware config block 0 */ + + if (!ret) ret = sja1105_configure_block(spi, 0, config_data_0, sizeof(config_data_0)); + if (!ret) ret = sja1105_configure_block(spi, 1, config_data_1, sizeof(config_data_1)); + if (!ret) ret = sja1105_configure_block(spi, 2, config_data_2, sizeof(config_data_2)); + if (!ret) ret = sja1105_configure_block(spi, 3, config_data_3, sizeof(config_data_3)); + if (ret) + { + return ret; + } + + /* Check that config was properly loaded */ + + ret = sja1105_global_crc_check(spi); + if (ret) + { + printf("sja1105: global CRC check failed\n"); + return ret; + } + + /* Check that config was properly loaded */ + + ret = sja1105_config_check(spi); + if (ret) + { + printf("sja1105: configuration is invalid\n"); + return ret; + } + + return ret; +} + +int sja1105_configure_mode_and_clocks(struct spi_slave *spi) +{ + int ret = 0; + + /* PLL */ + + /* PLL 1 setup for 50MHz */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000A, 0x0A010141); + /* PLL 1 setup for 50MHz */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000A, 0x0A010940); + + /* Port 0: RMII (PHY mode = external REFCLK) */ + + /* Disable IDIV0 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000B, 0x0A000001); + /* CLKSRC of RMII_REF_CLK_0 = TX_CLK_0 */ + if (!ret) ret = sja1105_write_reg(spi, 0x100015, 0x00000800); + + /* Port 1: RMII (MAC mode) */ + + /* Disable IDIV1 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000C, 0x0A000001); + /* CLKSRC of RMII_REF_CLK_1 = TX_CLK_1 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10001C, 0x02000800); + /* CLKSRC of EXT_TX_CLK1 = PLL1 (50 MHz) */ + if (!ret) ret = sja1105_write_reg(spi, 0x10001F, 0x0E000800); + + /* Port 2: RMII (MAC mode) */ + + /* Disable IDIV2 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000D, 0x0A000001); + /* CLKSRC of RMII_REF_CLK_2 = TX_CLK_2 */ + if (!ret) ret = sja1105_write_reg(spi, 0x100023, 0x04000800); + /* CLKSRC of EXT_TX_CLK2 = PLL1 (50 MHz) */ + if (!ret) ret = sja1105_write_reg(spi, 0x100026, 0x0E000800); + + /* Port 3: RMII (MAC mode) */ + + /* Disable IDIV3 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000E, 0x0A000001); + /* CLKSRC of RMII_REF_CLK_3 = TX_CLK_3 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10002A, 0x06000800); + /* CLKSRC of EXT_TX_CLK3 = PLL1 (50 MHz) */ + if (!ret) ret = sja1105_write_reg(spi, 0x10002D, 0x0E000800); + + /* Port 4: RMII (PHY mode = external REFCLK) */ + + /* Disable IDIV4 */ + if (!ret) ret = sja1105_write_reg(spi, 0x10000F, 0x0A000001); + /* CLKSRC of RMII_REF_CLK_4 = TX_CLK_4 */ + if (!ret) ret = sja1105_write_reg(spi, 0x100031, 0x08000800); + + return ret; +} + +int sja1105_configure_io(struct spi_slave *spi) +{ + + int ret = 0; + + /* Port 0 and Port 4 RX */ + + /* Enable pull down on CPU Port: + RX_DV/CRS_DV/RX_CTL, RX_ER, RX_CLK/RXC, RXD2, RXD3 */ + if (!ret) ret = sja1105_write_reg(spi, 0x100801, 0x03020313); + if (!ret) ret = sja1105_write_reg(spi, 0x100809, 0x03020313); + + /* Port 1 to Port 3 RX */ + + /* Enable pull down on CPU Port: + TODO, RX_CLK/RXC, RXD2, RXD3 */ + if (!ret) ret = sja1105_write_reg(spi, 0x100803, 0x03020213); + if (!ret) ret = sja1105_write_reg(spi, 0x100805, 0x03020213); + if (!ret) ret = sja1105_write_reg(spi, 0x100807, 0x03020213); + + /* Port 0 to Port 4 TX */ + + /* Enable pull down on CPU Port: + TX_ER, TXD2, TXD3 */ + if (!ret) ret = sja1105_write_reg(spi, 0x100800, 0x13121312); + if (!ret) ret = sja1105_write_reg(spi, 0x100802, 0x13121312); + if (!ret) ret = sja1105_write_reg(spi, 0x100804, 0x13121312); + if (!ret) ret = sja1105_write_reg(spi, 0x100806, 0x13121312); + if (!ret) ret = sja1105_write_reg(spi, 0x100808, 0x13121312); + + return ret; +} + +static int sja1105_probe(struct udevice *dev) +{ + struct sja1105_priv *priv = dev_get_priv(dev); + int ret; + + /* Obtain reset gpios */ + + ret = gpio_request_by_name(dev, "gpio-reset-hsm", 0, &priv->rst_hsm, GPIOD_IS_OUT); + if (ret) + { + printf("sja1105: unable to get HSM reset gpio\n"); + return ret; + } + + 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; + } + + 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; + } + + /* Put HSM, PHY and switch into reset */ + + dm_gpio_set_value(&priv->rst_hsm, 1); + dm_gpio_set_value(&priv->rst_phy, 1); + dm_gpio_set_value(&priv->rst_sw, 1); + + /* Take switch out of reset. Minimum Reset Pulse = 5us */ + + mdelay(1); + dm_gpio_set_value(&priv->rst_sw, 0); + + /* Give clocks time to stabilize */ + + mdelay(1); + + /* Try to claim SPI bus */ + + priv->spi = dev_get_parent_priv(dev); + ret = spi_claim_bus(priv->spi); + if (ret) + { + printf("sja1105: unable to claim SPI bus\n"); + return ret; + } + + /* 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; + } + + /* Configure mode & clocks */ + + ret = sja1105_configure_mode_and_clocks(priv->spi); + if (ret) + { + printf("sja1105: unable to configure mode and clocks\n"); + goto exit; + } + + /* Configure IO pads */ + + ret = sja1105_configure_io(priv->spi); + if (ret) + { + printf("sja1105: unable to configure IO pads\n"); + goto exit; + } + + /* Done */ + +exit: + spi_release_bus(priv->spi); + + return ret; +} + +static const struct udevice_id sja1105_ids[] = { + { .compatible = "nxp,sja1105" }, + { } +}; + +U_BOOT_DRIVER(sja1105) = { + .name = "sja1105", + .id = UCLASS_MISC, + .of_match = sja1105_ids, + .probe = sja1105_probe, + .priv_auto_alloc_size = sizeof(struct sja1105_priv) +};