From mboxrd@z Thu Jan 1 00:00:00 1970 From: Joe Hershberger Date: Fri, 22 Jan 2016 14:15:04 -0600 Subject: [U-Boot] [PATCH v2 3/8] drivers: net: keystone_net: convert driver to adopt device driver model In-Reply-To: <1453451002-21444-4-git-send-email-mugunthanvnm@ti.com> References: <1453451002-21444-1-git-send-email-mugunthanvnm@ti.com> <1453451002-21444-4-git-send-email-mugunthanvnm@ti.com> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On Fri, Jan 22, 2016 at 2:23 AM, Mugunthan V N wrote: > Adopt keystone_net driver to adopt device driver model > > Signed-off-by: Mugunthan V N > Reviewed-by: Tom Rini > --- > drivers/net/keystone_net.c | 418 ++++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 376 insertions(+), 42 deletions(-) > > diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c > index 209fae9..21ebaeb 100644 > --- a/drivers/net/keystone_net.c > +++ b/drivers/net/keystone_net.c > @@ -10,6 +10,8 @@ > #include > #include > > +#include > + > #include > #include > #include > @@ -18,10 +20,15 @@ > #include > #include > #include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > > +#ifndef CONFIG_DM_ETH > unsigned int emac_open; > static struct mii_dev *mdio_bus; > static unsigned int sys_has_mdio = 1; > +#endif > > #ifdef KEYSTONE2_EMAC_GIG_ENABLE > #define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x) > @@ -36,40 +43,44 @@ static unsigned int sys_has_mdio = 1; > > static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16); > > +#ifndef CONFIG_DM_ETH > struct rx_buff_desc net_rx_buffs = { > .buff_ptr = rx_buffs, > .num_buffs = RX_BUFF_NUMS, > .buff_len = RX_BUFF_LEN, > .rx_flow = 22, > }; > - > -#ifndef CONFIG_SOC_K2G > -static void keystone2_net_serdes_setup(void); > #endif > > -int keystone2_eth_read_mac_addr(struct eth_device *dev) > -{ > - struct eth_priv_t *eth_priv; > - u32 maca = 0; > - u32 macb = 0; > - > - eth_priv = (struct eth_priv_t *)dev->priv; > +#ifdef CONFIG_DM_ETH > > - /* Read the e-fuse mac address */ > - if (eth_priv->slave_port == 1) { > - maca = __raw_readl(MAC_ID_BASE_ADDR); > - macb = __raw_readl(MAC_ID_BASE_ADDR + 4); > - } > - > - dev->enetaddr[0] = (macb >> 8) & 0xff; > - dev->enetaddr[1] = (macb >> 0) & 0xff; > - dev->enetaddr[2] = (maca >> 24) & 0xff; > - dev->enetaddr[3] = (maca >> 16) & 0xff; > - dev->enetaddr[4] = (maca >> 8) & 0xff; > - dev->enetaddr[5] = (maca >> 0) & 0xff; > +enum link_type { > + LINK_TYPE_MAC_TO_MAC_AUTO = 0, > + LINK_TYPE_MAC_TO_PHY_MODE = 1, > + LINK_TYPE_MAC_TO_MAC_FORCED_MODE = 2, > + LINK_TYPE_MAC_TO_FIBRE_MODE = 3, > + LINK_TYPE_MAC_TO_PHY_NO_MDIO_MODE = 4, > + LINK_TYPE_10G_MAC_TO_PHY_MODE = 10, > + LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE = 11, > +}; > > - return 0; > -} > +struct ks2_eth_priv { > + struct udevice *dev; > + struct phy_device *phydev; > + struct mii_dev *mdio_bus; > + int phy_addr; > + phy_interface_t phy_if; > + int sgmii_link_type; > + void *mdio_base; > + struct rx_buff_desc net_rx_buffs; > + struct pktdma_cfg *netcp_pktdma; > + void *hd; > + int slave_port; > + enum link_type link_type; > + bool emac_open; > + bool has_mdio; > +}; > +#endif > > /* MDIO */ > > @@ -140,6 +151,7 @@ static int keystone2_mdio_write(struct mii_dev *bus, > return 0; > } > > +#ifndef CONFIG_DM_ETH > static void __attribute__((unused)) > keystone2_eth_gigabit_enable(struct eth_device *dev) > { > @@ -163,6 +175,31 @@ static void __attribute__((unused)) > EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, > DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL); > } > +#else > +static void __attribute__((unused)) > + keystone2_eth_gigabit_enable(struct udevice *dev) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + u_int16_t data; > + > + if (priv->has_mdio) { > + data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr, > + MDIO_DEVAD_NONE, 0); > + /* speed selection MSB */ > + if (!(data & (1 << 6))) > + return; > + } > + > + /* > + * Check if link detected is giga-bit > + * If Gigabit mode detected, enable gigbit in MAC > + */ > + writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) + > + CPGMACSL_REG_CTL) | > + EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, > + DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL); > +} > +#endif > > #ifdef CONFIG_SOC_K2G > int keystone_rgmii_config(struct phy_device *phy_dev) > @@ -401,6 +438,58 @@ int ethss_stop(void) > return 0; > } > > +struct ks2_serdes ks2_serdes_sgmii_156p25mhz = { > + .clk = SERDES_CLOCK_156P25M, > + .rate = SERDES_RATE_5G, > + .rate_mode = SERDES_QUARTER_RATE, > + .intf = SERDES_PHY_SGMII, > + .loopback = 0, > +}; > + > +#ifndef CONFIG_SOC_K2G > +static void keystone2_net_serdes_setup(void) > +{ > + ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE, > + &ks2_serdes_sgmii_156p25mhz, > + CONFIG_KSNET_SERDES_LANES_PER_SGMII); > + > +#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L) > + ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, > + &ks2_serdes_sgmii_156p25mhz, > + CONFIG_KSNET_SERDES_LANES_PER_SGMII); > +#endif > + > + /* wait till setup */ > + udelay(5000); > +} > +#endif > + > +#ifndef CONFIG_DM_ETH > + > +int keystone2_eth_read_mac_addr(struct eth_device *dev) > +{ > + struct eth_priv_t *eth_priv; > + u32 maca = 0; > + u32 macb = 0; > + > + eth_priv = (struct eth_priv_t *)dev->priv; > + > + /* Read the e-fuse mac address */ > + if (eth_priv->slave_port == 1) { > + maca = __raw_readl(MAC_ID_BASE_ADDR); > + macb = __raw_readl(MAC_ID_BASE_ADDR + 4); > + } > + > + dev->enetaddr[0] = (macb >> 8) & 0xff; > + dev->enetaddr[1] = (macb >> 0) & 0xff; > + dev->enetaddr[2] = (maca >> 24) & 0xff; > + dev->enetaddr[3] = (maca >> 16) & 0xff; > + dev->enetaddr[4] = (maca >> 8) & 0xff; > + dev->enetaddr[5] = (maca >> 0) & 0xff; > + > + return 0; > +} > + > int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) > { > if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) > @@ -556,6 +645,7 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) > int res; > struct eth_device *dev; > struct phy_device *phy_dev; > + struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; > > dev = malloc(sizeof(struct eth_device)); > if (dev == NULL) > @@ -612,28 +702,272 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) > return 0; > } > > -struct ks2_serdes ks2_serdes_sgmii_156p25mhz = { > - .clk = SERDES_CLOCK_156P25M, > - .rate = SERDES_RATE_5G, > - .rate_mode = SERDES_QUARTER_RATE, > - .intf = SERDES_PHY_SGMII, > - .loopback = 0, > -}; > +#else > > -#ifndef CONFIG_SOC_K2G > -static void keystone2_net_serdes_setup(void) > +int keystone2_eth_read_mac_addr(struct ks2_eth_priv *priv, > + struct eth_pdata *pdata) > { > - ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE, > - &ks2_serdes_sgmii_156p25mhz, > - CONFIG_KSNET_SERDES_LANES_PER_SGMII); > + u32 maca = 0; > + u32 macb = 0; > > -#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L) > - ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, > - &ks2_serdes_sgmii_156p25mhz, > - CONFIG_KSNET_SERDES_LANES_PER_SGMII); > + /* Read the e-fuse mac address */ > + if (priv->slave_port == 1) { > + maca = __raw_readl(MAC_ID_BASE_ADDR); > + macb = __raw_readl(MAC_ID_BASE_ADDR + 4); > + } > + > + pdata->enetaddr[0] = (macb >> 8) & 0xff; > + pdata->enetaddr[1] = (macb >> 0) & 0xff; > + pdata->enetaddr[2] = (maca >> 24) & 0xff; > + pdata->enetaddr[3] = (maca >> 16) & 0xff; > + pdata->enetaddr[4] = (maca >> 8) & 0xff; > + pdata->enetaddr[5] = (maca >> 0) & 0xff; > + > + return 0; > +} > + > +static int ks2_eth_start(struct udevice *dev) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + > +#ifdef CONFIG_SOC_K2G > + keystone_rgmii_config(priv->phydev); > +#else > + keystone_sgmii_config(priv->phydev, priv->slave_port - 1, > + priv->sgmii_link_type); > #endif > > - /* wait till setup */ > - udelay(5000); > + udelay(10000); > + > + /* On chip switch configuration */ > + ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); > + > + qm_init(); > + > + if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) { > + error("ksnav_init failed\n"); > + goto err_knav_init; > + } > + > + /* > + * Streaming switch configuration. If not present this > + * statement is defined to void in target.h. > + * If present this is usually defined to a series of register writes > + */ > + hw_config_streaming_switch(); > + > + if (priv->has_mdio) { > + phy_startup(priv->phydev); > + if (priv->phydev->link == 0) { > + error("phy startup failed\n"); > + goto err_phy_start; > + } > + } > + > + emac_gigabit_enable(dev); > + > + ethss_start(); > + > + priv->emac_open = true; > + > + return 0; > + > +err_phy_start: > + ksnav_close(priv->netcp_pktdma); > +err_knav_init: > + qm_close(); > + > + return -EFAULT; > +} > + > +static int ks2_eth_send(struct udevice *dev, void *packet, int length) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + > + genphy_update_link(priv->phydev); > + if (priv->phydev->link == 0) > + return -1; > + > + if (length < EMAC_MIN_ETHERNET_PKT_SIZE) > + length = EMAC_MIN_ETHERNET_PKT_SIZE; > + > + return ksnav_send(priv->netcp_pktdma, (u32 *)packet, > + length, (priv->slave_port) << 16); > +} > + > +static int ks2_eth_recv(struct udevice *dev, int flags, uchar **packetp) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + int pkt_size; > + u32 *pkt = NULL; > + > + priv->hd = ksnav_recv(priv->netcp_pktdma, &pkt, &pkt_size); > + if (priv->hd == NULL) > + return -EAGAIN; > + > + *packetp = (uchar *)pkt; > + > + return pkt_size; > +} > + > +static int ks2_eth_free_pkt(struct udevice *dev, uchar *packet, > + int length) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + > + ksnav_release_rxhd(priv->netcp_pktdma, priv->hd); > + > + return 0; > +} > + > +static void ks2_eth_stop(struct udevice *dev) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + > + if (!priv->emac_open) > + return; > + ethss_stop(); > + > + ksnav_close(priv->netcp_pktdma); > + qm_close(); > + phy_shutdown(priv->phydev); > + priv->emac_open = false; > +} > + > +static int ks2_eth_probe(struct udevice *dev) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + struct mii_dev *mdio_bus; > + int ret; > + > + priv->dev = dev; > + > + /* These clock enables has to be moved to common location */ > + if (cpu_is_k2g()) > + writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG); > + > + /* By default, select PA PLL clock as PA clock source */ > +#ifndef CONFIG_SOC_K2G > + if (psc_enable_module(KS2_LPSC_PA)) > + return -1; > +#endif > + if (psc_enable_module(KS2_LPSC_CPGMAC)) > + return -1; > + if (psc_enable_module(KS2_LPSC_CRYPTO)) > + return -1; Is there not a more appropriate error code that could be used here for these 3? > + > + if (cpu_is_k2e() || cpu_is_k2l()) > + pll_pa_clk_sel(); > + > + > + priv->net_rx_buffs.buff_ptr = rx_buffs, > + priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS, > + priv->net_rx_buffs.buff_len = RX_BUFF_LEN, > + > + /* Register MDIO bus */ > + mdio_bus = mdio_alloc(); > + if (!mdio_bus) { > + error("MDIO alloc failed\n"); > + return -ENOMEM; > + } > + priv->mdio_bus = mdio_bus; > + mdio_bus->read = keystone2_mdio_read; > + mdio_bus->write = keystone2_mdio_write; > + mdio_bus->reset = keystone2_mdio_reset; > + mdio_bus->priv = priv->mdio_base; > + sprintf(mdio_bus->name, "ethernet-mdio"); > + > + ret = mdio_register(mdio_bus); > + if (ret) { > + error("MDIO bus register failed\n"); > + return ret; > + } > + > +#ifndef CONFIG_SOC_K2G > + keystone2_net_serdes_setup(); > +#endif > + > + priv->netcp_pktdma = &netcp_pktdma; > + > + priv->phydev = phy_connect(mdio_bus, priv->phy_addr, dev, priv->phy_if); > + phy_config(priv->phydev); > + > + return 0; > } > + > +static const struct eth_ops ks2_eth_ops = { > + .start = ks2_eth_start, > + .send = ks2_eth_send, > + .recv = ks2_eth_recv, > + .free_pkt = ks2_eth_free_pkt, > + .stop = ks2_eth_stop, Do you not have a function to set the MAC address in the emac for packet filtering (write_hwaddr)? > +}; > + > + > +static int ks2_eth_ofdata_to_platdata(struct udevice *dev) > +{ > + struct ks2_eth_priv *priv = dev_get_priv(dev); > + struct eth_pdata *pdata = dev_get_platdata(dev); > + const void *fdt = gd->fdt_blob; > + int interfaces; > + int interface_0; > + int netcp_gbe_0; > + int phy; > + int mdio; > + u32 dma_channel[6]; > + > + interfaces = fdt_subnode_offset(fdt, dev->of_offset, > + "netcp-interfaces"); > + interface_0 = fdt_subnode_offset(fdt, interfaces, "interface-0"); > + > + netcp_gbe_0 = fdtdec_lookup_phandle(fdt, interface_0, "netcp-gbe"); > + priv->link_type = fdtdec_get_int(fdt, netcp_gbe_0, > + "link-interface", -1); > + priv->slave_port = fdtdec_get_int(fdt, netcp_gbe_0, "slave-port", -1); > + /* U-Boot slave port number starts with 1 instead of 0 */ > + priv->slave_port += 1; > + > + phy = fdtdec_lookup_phandle(fdt, netcp_gbe_0, "phy-handle"); > + priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1); > + > + mdio = fdt_parent_offset(fdt, phy); > + if (mdio < 0) { > + error("mdio dt not found\n"); > + return -ENODEV; > + } > + priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg"); > + > + keystone2_eth_read_mac_addr(priv, pdata); Would this not be more appropriate to just set a pointer to this function to read_rom_hwaddr in the ops structure? > + > + if (priv->link_type == LINK_TYPE_MAC_TO_PHY_MODE) { > + priv->phy_if = PHY_INTERFACE_MODE_SGMII; > + pdata->phy_interface = priv->phy_if; > + priv->sgmii_link_type = SGMII_LINK_MAC_PHY; > + priv->has_mdio = true; > + } > + pdata->iobase = dev_get_addr(dev); > + > + fdtdec_get_int_array(fdt, dev->of_offset, "ti,navigator-dmas", > + dma_channel, 6); > + priv->net_rx_buffs.rx_flow = dma_channel[1]; > + > + return 0; > +} > + > +static const struct udevice_id ks2_eth_ids[] = { > + { .compatible = "ti,netcp-1.0" }, > + { } > +}; > + > +U_BOOT_DRIVER(eth_ks2) = { > + .name = "eth_ks2", > + .id = UCLASS_ETH, > + .of_match = ks2_eth_ids, > + .ofdata_to_platdata = ks2_eth_ofdata_to_platdata, > + .probe = ks2_eth_probe, > + .ops = &ks2_eth_ops, > + .priv_auto_alloc_size = sizeof(struct ks2_eth_priv), > + .platdata_auto_alloc_size = sizeof(struct eth_pdata), > + .flags = DM_FLAG_ALLOC_PRIV_DMA, > +}; > #endif > -- > 2.7.0.rc3 > > _______________________________________________ > U-Boot mailing list > U-Boot at lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot