From 2c97e2ff04dfec2a811db0434ec6743f74c7368e Mon Sep 17 00:00:00 2001 From: Aditya Kumar Patra S Date: Mon, 26 Sep 2016 16:38:36 +0530 Subject: [PATCH] qca: ipq806x: Modified Eth and Switch drivers to read data from DTB. Change-Id: Ie35b52a2c022c29de341c63af13c67b95f7e565a Signed-off-by: Aditya Kumar Patra S --- arch/arm/include/asm/arch-ipq806x/ipq_gmac.h | 65 +++++++++- drivers/net/Makefile | 3 + drivers/net/ipq806x/athrs17_phy.c | 4 +- drivers/net/ipq806x/ipq_gmac_eth.c | 122 ++++++++++++------- drivers/net/ipq806x/qca8511.c | 1 + 5 files changed, 150 insertions(+), 45 deletions(-) diff --git a/arch/arm/include/asm/arch-ipq806x/ipq_gmac.h b/arch/arm/include/asm/arch-ipq806x/ipq_gmac.h index 8a77d228f3..b74ffb0230 100644 --- a/arch/arm/include/asm/arch-ipq806x/ipq_gmac.h +++ b/arch/arm/include/asm/arch-ipq806x/ipq_gmac.h @@ -15,7 +15,7 @@ #define _IPQ_GMAC_H #include #include -#include +#include #define CONFIG_MACRESET_TIMEOUT (3 * CONFIG_SYS_HZ) #define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) @@ -337,6 +337,25 @@ #define phy_reg_write(base, addr, reg, data) \ ipq_mdio_write(addr, reg, data) +#define MII_BUSY (1 << 0) +#define MII_WRITE (1 << 1) +#define MII_CLKRANGE_60_100M (0) +#define MII_CLKRANGE_100_150M (0x4) +#define MII_CLKRANGE_20_35M (0x8) +#define MII_CLKRANGE_35_60M (0xC) +#define MII_CLKRANGE_150_250M (0x10) +#define MII_CLKRANGE_250_300M (0x14) +#define MII_DATA_REG_ADDR (0x14) +#define MII_ADDR_REG_ADDR (0x10) +#define MII_MDIO_TIMEOUT (10000) +#define MIIADDRSHIFT (11) +#define MIIREGSHIFT (6) +#define MII_REGMSK (0x1F << 6) +#define MII_ADDRMSK (0x1F << 11) +#define MII_PHY_STAT_SHIFT (10) +#define AUTO_NEG_ENABLE (1 << 12) +#define FORCE_RATE_10 (0 << 13) | (1 << 15) | (1 << 8) +#define FORCE_RATE_100 (1 << 13) | (1 << 15) | (1 << 8) typedef struct { @@ -743,4 +762,48 @@ enum GmacFlowControlReg GmacFlowControlBackPressure = 0x00000001, GmacSendPauseFrame = 0x00000001, /* (FCB/PBA)send pause frm/Apply back pressure 0 RW 0 */ }; + +/* + * Below is "88E1011/88E1011S Integrated 10/100/1000 Gigabit Ethernet Transceiver" + * Register and their layouts. This Phy has been used in the Dot Aster GMAC Phy daughter. + * Since the Phy register map is standard, this map hardly changes to a different Ppy + */ +enum MiiRegisters +{ + PHY_CONTROL_REG = 0x0000, /* Control Register */ + PHY_STATUS_REG = 0x0001, /* Status Register */ + PHY_ID_HI_REG = 0x0002, /* PHY Identifier High Register */ + PHY_ID_LOW_REG = 0x0003, /* PHY Identifier High Register */ + PHY_AN_ADV_REG = 0x0004, /* Auto-Negotiation Advertisement Register */ + PHY_LNK_PART_ABl_REG = 0x0005, /* Link Partner Ability Register (Base Page) */ + PHY_AN_EXP_REG = 0x0006, /* Auto-Negotiation Expansion Register */ + PHY_AN_NXT_PAGE_TX_REG = 0x0007, /* Next Page Transmit Register */ + PHY_LNK_PART_NXT_PAGE_REG = 0x0008, /* Link Partner Next Page Register */ + PHY_1000BT_CTRL_REG = 0x0009, /* 1000BASE-T Control Register */ + PHY_1000BT_STATUS_REG = 0x000a, /* 1000BASE-T Status Register */ + PHY_SPECIFIC_CTRL_REG = 0x0010, /* Phy specific control register */ + PHY_SPECIFIC_STATUS_REG = 0x0011, /* Phy specific status register */ + PHY_INTERRUPT_ENABLE_REG = 0x0012, /* Phy interrupt enable register */ + PHY_INTERRUPT_STATUS_REG = 0x0013, /* Phy interrupt status register */ + PHY_EXT_PHY_SPC_CTRL = 0x0014, /* Extended Phy specific control */ + PHY_RX_ERR_COUNTER = 0x0015, /* Receive Error Counter */ + PHY_EXT_ADDR_CBL_DIAG = 0x0016, /* Extended address for cable diagnostic register */ + PHY_LED_CONTROL = 0x0018, /* LED Control */ + PHY_MAN_LED_OVERIDE = 0x0019, /* Manual LED override register */ + PHY_EXT_PHY_SPC_CTRL2 = 0x001a, /* Extended Phy specific control 2 */ + PHY_EXT_PHY_SPC_STATUS = 0x001b, /* Extended Phy specific status */ + PHY_CBL_DIAG_REG = 0x001c, /* Cable diagnostic registers */ +}; + +enum Mii_Phy_Status { + Mii_phy_status_speed_10 = 0x0000, + Mii_phy_status_speed_100 = 0x4000, + Mii_phy_status_speed_1000 = 0x8000, + + Mii_phy_status_full_duplex = 0x2000, + Mii_phy_status_half_duplex = 0x0000, + + Mii_phy_status_link_up = 0x0400, +}; + #endif /* _IPQ_GMAC_H */ diff --git a/drivers/net/Makefile b/drivers/net/Makefile index edca474e26..6a3576572c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -79,3 +79,6 @@ obj-$(CONFIG_IPQ40XX_ESS) += ipq40xx/ipq40xx_ess_sw.o obj-$(CONFIG_QCA8075_PHY) += ipq40xx/ipq40xx_qca8075.o obj-$(CONFIG_QCA8033_PHY) += ipq40xx/ipq40xx_qca8033.o obj-$(CONFIG_IPQ40XX_MDIO) += ipq40xx/ipq40xx_mdio.o +obj-$(CONFIG_IPQ_SNPS_GMAC) += ipq806x/ipq_gmac_eth.o +obj-$(CONFIG_IPQ_SWITCH_ATHRS17) += ipq806x/athrs17_phy.o +obj-$(CONFIG_IPQ_SWITCH_QCA8511) += ipq806x/qca8511.o diff --git a/drivers/net/ipq806x/athrs17_phy.c b/drivers/net/ipq806x/athrs17_phy.c index 1de69240f7..ad4c143952 100644 --- a/drivers/net/ipq806x/athrs17_phy.c +++ b/drivers/net/ipq806x/athrs17_phy.c @@ -272,9 +272,9 @@ int do_ar8xxx_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct athrs17_regmap *section = ®map[i]; for (reg = section->start; reg <= section->end; reg += sizeof(uint32_t)) { - ipq_gmac_board_cfg_t *gmac_tmp_cfg = gboard_param->gmac_cfg; + ipq_gmac_board_cfg_t *gmac_tmp_cfg = gmac_cfg; uint32_t val = athrs17_reg_read(gmac_tmp_cfg, reg); - printf("%03zu: %08zu\n", reg, val); + printf("%03zx: %08zx\n", reg, val); } } diff --git a/drivers/net/ipq806x/ipq_gmac_eth.c b/drivers/net/ipq806x/ipq_gmac_eth.c index 25db8c01e3..d44f3f8af1 100644 --- a/drivers/net/ipq806x/ipq_gmac_eth.c +++ b/drivers/net/ipq806x/ipq_gmac_eth.c @@ -15,17 +15,15 @@ #include #include #include -#include -#include #include #include #include #include -#include -#include -#include -#include +#include +#include #include +#include +#include #define ipq_info printf #define ipq_dbg printf @@ -33,13 +31,20 @@ #define DESC_FLUSH_SIZE (((DESC_SIZE + (CONFIG_SYS_CACHELINE_SIZE - 1)) \ / CONFIG_SYS_CACHELINE_SIZE) * \ (CONFIG_SYS_CACHELINE_SIZE)) -static struct ipq_eth_dev *ipq_gmac_macs[IPQ_GMAC_NMACS]; + +uchar ipq_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xAB, 0xBD, 0xDA}; + +static struct ipq_eth_dev *ipq_gmac_macs[CONFIG_IPQ_NO_MACS]; static int (*ipq_switch_init)(ipq_gmac_board_cfg_t *cfg); static struct ipq_forced_mode get_params; -static struct bitbang_nodes *bb_nodes[IPQ_GMAC_NMACS]; +static struct bitbang_nodes *bb_nodes[CONFIG_IPQ_NO_MACS]; static void ipq_gmac_mii_clk_init(struct ipq_eth_dev *priv, uint clk_div, ipq_gmac_board_cfg_t *gmac_cfg); +extern ipq_gmac_board_cfg_t gmac_cfg[]; + +DECLARE_GLOBAL_DATA_PTR; + void ipq_register_switch(int(*sw_init)(ipq_gmac_board_cfg_t *cfg)) { ipq_switch_init = sw_init; @@ -244,7 +249,7 @@ static int ipq_gmac_rx_desc_setup(struct ipq_eth_dev *priv) rxdesc = priv->desc_rx[i]; rxdesc->length |= ((ETH_MAX_FRAME_LEN << DescSize1Shift) & DescSize1Mask); - rxdesc->buffer1 = virt_to_phys(NetRxPackets[i]); + rxdesc->buffer1 = virt_to_phys(net_rx_packets[i]); rxdesc->data1 = (unsigned long)priv->desc_rx[(i + 1) % NO_OF_RX_DESC]; @@ -540,11 +545,10 @@ static int ipq_eth_recv(struct eth_device *dev) invalidate_dcache_range( - (unsigned long)(NetRxPackets[priv->next_rx]), - (unsigned long)(NetRxPackets[priv->next_rx]) + + (unsigned long)(net_rx_packets[priv->next_rx]), + (unsigned long)(net_rx_packets[priv->next_rx]) + PKTSIZE_ALIGN); - - NetReceive(NetRxPackets[priv->next_rx], length - 4); + net_process_received_packet(net_rx_packets[priv->next_rx], length - 4); rxdesc->length = ((ETH_MAX_FRAME_LEN << DescSize1Shift) & @@ -554,7 +558,7 @@ static int ipq_eth_recv(struct eth_device *dev) RxDescEndOfRing : 0; rxdesc->length |= RxDescChain; - rxdesc->buffer1 = virt_to_phys(NetRxPackets[priv->next_rx]); + rxdesc->buffer1 = virt_to_phys(net_rx_packets[priv->next_rx]); priv->next_rx = (priv->next_rx + 1) % NO_OF_RX_DESC; @@ -714,19 +718,19 @@ static void ipq_gmac_mii_clk_init(struct ipq_eth_dev *priv, uint clk_div, int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) { static int sw_init_done = 0; - struct eth_device *dev[IPQ_GMAC_NMACS]; + struct eth_device *dev[CONFIG_IPQ_NO_MACS]; uint clk_div_val; - uchar enet_addr[IPQ_GMAC_NMACS * 6]; + uchar enet_addr[CONFIG_IPQ_NO_MACS * 6]; uchar *mac_addr; char ethaddr[32] = "ethaddr"; char mac[64]; int i; int ret; - + int gmac_gpio_node = 0, ar8033_gpio_node = 0, offset = 0; memset(enet_addr, 0, sizeof(enet_addr)); /* Getting the MAC address from ART partition */ - ret = get_eth_mac_address(enet_addr, IPQ_GMAC_NMACS); + ret = get_eth_mac_address(enet_addr, CONFIG_IPQ_NO_MACS); for (i = 0; gmac_cfg_is_valid(gmac_cfg); gmac_cfg++, i++) { @@ -756,7 +760,7 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) * is invalid. */ if ((ret < 0) || - (!is_valid_ether_addr(&enet_addr[i * 6]))) { + (!is_valid_ethaddr(&enet_addr[i * 6]))) { memcpy(&dev[i]->enetaddr[0], ipq_def_enetaddr, 6); dev[i]->enetaddr[5] = gmac_cfg->unit & 0xff; } else { @@ -850,12 +854,19 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) if (bb_nodes[i] == NULL) goto failed; memset(bb_nodes[i], 0, sizeof(struct bitbang_nodes)); - bb_nodes[i]->mdio = gboard_param->gmac_gpio[0].gpio; - bb_nodes[i]->mdc = gboard_param->gmac_gpio[1].gpio; - bb_miiphy_buses[i].priv = bb_nodes[i]; - strncpy(bb_miiphy_buses[i].name, gmac_cfg->phy_name, - sizeof(bb_miiphy_buses[i].name)); - miiphy_register(bb_miiphy_buses[i].name, bb_miiphy_read, bb_miiphy_write); + + gmac_gpio_node = fdt_path_offset(gd->fdt_blob, "/gmac/gmac_gpio"); + if (gmac_gpio_node >= 0) { + offset = fdt_first_subnode(gd->fdt_blob, gmac_gpio_node); + bb_nodes[i]->mdio = fdtdec_get_uint(gd->fdt_blob, offset, "gpio", 0); + + offset = fdt_next_subnode(gd->fdt_blob, offset); + bb_nodes[i]->mdc = fdtdec_get_uint(gd->fdt_blob, offset, "gpio", 0); + bb_miiphy_buses[i].priv = bb_nodes[i]; + strncpy(bb_miiphy_buses[i].name, gmac_cfg->phy_name, + sizeof(bb_miiphy_buses[i].name)); + miiphy_register(bb_miiphy_buses[i].name, bb_miiphy_read, bb_miiphy_write); + } eth_register(dev[i]); @@ -871,9 +882,9 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) /* set the mac address in environment for unconfigured GMAC */ if (ret >= 0) { - for (; i < IPQ_GMAC_NMACS; i++) { + for (; i < CONFIG_IPQ_NO_MACS; i++) { mac_addr = &enet_addr[i * 6]; - if (is_valid_ether_addr(mac_addr)) { + if (is_valid_ethaddr(mac_addr)) { /* * U-Boot uses these to patch the 'local-mac-address' * dts entry for the ethernet entries, which in turn @@ -889,11 +900,18 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) } } - if (gboard_param->ar8033_gpio) { + ar8033_gpio_node = fdt_path_offset(gd->fdt_blob, "/ar8033_gpio"); + + if (ar8033_gpio_node != 0) { bb_nodes[i] = malloc(sizeof(struct bitbang_nodes)); memset(bb_nodes[i], 0, sizeof(struct bitbang_nodes)); - bb_nodes[i]->mdio = gboard_param->ar8033_gpio[0].gpio; - bb_nodes[i]->mdc = gboard_param->ar8033_gpio[1].gpio; + + offset = fdt_first_subnode(gd->fdt_blob, ar8033_gpio_node); + bb_nodes[i]->mdio = fdtdec_get_uint(gd->fdt_blob, offset, "gpio", 0); + + offset = fdt_next_subnode(gd->fdt_blob, offset); + bb_nodes[i]->mdc = fdtdec_get_uint(gd->fdt_blob, offset, "gpio", 0); + bb_miiphy_buses[i].priv = bb_nodes[i]; strncpy(bb_miiphy_buses[i].name, "8033", sizeof(bb_miiphy_buses[i].name)); @@ -903,7 +921,7 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) return 0; failed: - for (i = 0; i < IPQ_GMAC_NMACS; i++) { + for (i = 0; i < CONFIG_IPQ_NO_MACS; i++) { if (bb_nodes[i]) free(bb_nodes[i]); if (dev[i]) { @@ -1006,11 +1024,20 @@ static int ipq_eth_bb_init(struct bb_miiphy_bus *bus) static int ipq_eth_bb_mdio_active(struct bb_miiphy_bus *bus) { struct bitbang_nodes *bb_node = bus->priv; + struct qca_gpio_config gmac_gpio_config = {0}; - gpio_tlmm_config(bb_node->mdio, 0, - GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, 1); - gpio_tlmm_config(bb_node->mdc, 0, - GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, 1); + gmac_gpio_config.gpio = bb_node->mdio; + gmac_gpio_config.func = 0; + gmac_gpio_config.out = GPIO_OUTPUT; + gmac_gpio_config.pull = GPIO_NO_PULL; + gmac_gpio_config.drvstr = GPIO_8MA; + gmac_gpio_config.oe = 1; + + gpio_tlmm_config(&gmac_gpio_config); + + gmac_gpio_config.gpio = bb_node->mdc; + + gpio_tlmm_config(&gmac_gpio_config); return 0; } @@ -1018,12 +1045,23 @@ static int ipq_eth_bb_mdio_active(struct bb_miiphy_bus *bus) static int ipq_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) { struct bitbang_nodes *bb_node = bus->priv; + struct qca_gpio_config gmac_gpio_config = {0}; - gpio_tlmm_config(bb_node->mdio, 0, - GPIO_INPUT, GPIO_NO_PULL, GPIO_8MA, 0); - gpio_tlmm_config(bb_node->mdc, 0, - GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, 1); + gmac_gpio_config.gpio = bb_node->mdio; + gmac_gpio_config.func = 0; + gmac_gpio_config.out = GPIO_INPUT; + gmac_gpio_config.pull = GPIO_NO_PULL; + gmac_gpio_config.drvstr = GPIO_8MA; + gmac_gpio_config.oe = 0; + gpio_tlmm_config(&gmac_gpio_config); + + + gmac_gpio_config.gpio = bb_node->mdc; + gmac_gpio_config.out = GPIO_OUTPUT; + gmac_gpio_config.oe = 1; + + gpio_tlmm_config(&gmac_gpio_config); return 0; } @@ -1106,7 +1144,7 @@ static int ipq_eth_unregister(void) int i; struct eth_device *dev; - for (i = 0; i < IPQ_GMAC_NMACS; i++) { + for (i = 0; i < CONFIG_IPQ_NO_MACS; i++) { if (bb_nodes[i]) free(bb_nodes[i]); if (ipq_gmac_macs[i]) { @@ -1132,7 +1170,7 @@ static int do_force_eth_speed(cmd_tbl_t *cmdtp, int flag, int argc, if (argc != 3) return CMD_RET_USAGE; - ipq_gmac_board_cfg_t *gmac_tmp_cfg = gboard_param->gmac_cfg; + ipq_gmac_board_cfg_t *gmac_tmp_cfg = gmac_cfg; if (strict_strtoul(argv[1], 16, (unsigned long *)&phy_addr) < 0) { ipq_info("Invalid Phy addr configured\n"); @@ -1167,7 +1205,7 @@ static int do_force_eth_speed(cmd_tbl_t *cmdtp, int flag, int argc, get_params.is_forced = 1; get_params.miiwrite_done = 1; ipq_eth_unregister(); - status = ipq_gmac_init(gboard_param->gmac_cfg); + status = ipq_gmac_init(gmac_cfg); return status; } diff --git a/drivers/net/ipq806x/qca8511.c b/drivers/net/ipq806x/qca8511.c index df888efbab..68a78660a2 100644 --- a/drivers/net/ipq806x/qca8511.c +++ b/drivers/net/ipq806x/qca8511.c @@ -17,6 +17,7 @@ * All definitions in this file are operating system independent! */ +#include #include #include #include