sunxi: emac: Add driver model support
Subsystems (3)
v2 cover sunxi: emac: Add driver model support
Hi All,
Here is v2 of my patch series to add driver model support to the sunxi emac driver.
Changes since v1:
-Add a patch to rename DMA_CPU_TRRESHOLD to EMAC_RX_BUFSIZE.
Please review.
Regards,
Hans
PATCH v2 1/4 sunxi: emac: port to phylib
This is a preparation-patch for adding device-model support to the emac driver.
--- drivers/net/sunxi_emac.c | 111 +++++++++++++++++++++++++---------------- include/configs/sunxi-common.h | 2 + 2 files changed, 71 insertions(+), 42 deletions(-)
drivers/net/sunxi_emac.c +69 -42
@@ -156,9 +156,9 @@ struct sunxi_sramc_regs {#define DMA_CPU_TRRESHOLD 2000struct emac_eth_dev { -u32 speed; -u32 duplex; -u32 phy_configured; +struct emac_regs *regs; +struct mii_dev *bus; +struct phy_device *phydev;int link_printed; };
@@ -195,11 +195,10 @@ static void emac_outblk_32bit(void *reg, void *data, int count) }/* Read a word from phyxcer */ -static int emac_phy_read (const char *devname,unsigned char addr, -unsigned char reg,unsigned short *value) +static int emac_mdio_read (struct mii_dev *bus,int addr,int devad,int reg) { -struct eth_device *dev =eth_get_dev_by_name (devname); -struct emac_regs *regs = (struct emac_regs *)dev->iobase; +struct emac_eth_dev *priv = bus->priv; +struct emac_regs *regs = priv->regs;/* issue the phy address and reg */ writel (addr <<8 | reg, ®s->mac_madr);
@@ -213,18 +212,16 @@ static int emac_phy_read(const char *devname, unsigned char addr,/* push down the phy io line */ writel (0x0 , ®s->mac_mcmd); -/* and write data */ - *value =readl (®s->mac_mrdd); - -return 0 ; +/* And read data */ +return readl (®s->mac_mrdd); }/* Write a word to phyxcer */ -static int emac_phy_write (const char *devname,unsigned char addr, -unsigned char reg,unsigned short value) +static int emac_mdio_write (struct mii_dev *bus,int addr,int devad,int reg, +u16 value) { -struct eth_device *dev =eth_get_dev_by_name (devname); -struct emac_regs *regs = (struct emac_regs *)dev->iobase; +struct emac_eth_dev *priv = bus->priv; +struct emac_regs *regs = priv->regs;/* issue the phy address and reg */ writel (addr <<8 | reg, ®s->mac_madr);
@@ -244,12 +241,44 @@ static int emac_phy_write(const char *devname, unsigned char addr,return 0 ; } -static void emac_setup (struct eth_device *dev) +static int sunxi_emac_init_phy (struct emac_eth_dev *priv,void *dev) { -struct emac_regs *regs = (struct emac_regs *)dev->iobase; +int ret, mask =0xffffffff ; + +#ifdef CONFIG_PHY_ADDR + mask =1 <<CONFIG_PHY_ADDR ; +#endif + + priv->bus =mdio_alloc (); +if (!priv->bus) { +printf ("Failed to allocate MDIO bus\n" ); +return -ENOMEM ; + } + + priv->bus->read = emac_mdio_read; + priv->bus->write = emac_mdio_write; + priv->bus->priv = priv; +strcpy (priv->bus->name,"emac" ); + + ret =mdio_register (priv->bus); +if (ret) +return ret; + + priv->phydev =phy_find_by_mask (priv->bus, mask, +PHY_INTERFACE_MODE_MII ); +if (!priv->phydev) +return -ENODEV ; + +phy_connect_dev (priv->phydev, dev); +phy_config (priv->phydev); + +return 0 ; +} + +static void emac_setup (struct emac_eth_dev *priv) +{ +struct emac_regs *regs = priv->regs;u32 reg_val; -u16 phy_val; -u32 duplex_flag;/* Set up TX */ writel (EMAC_TX_SETUP , ®s->tx_mode);
@@ -262,12 +291,8 @@ static void emac_setup(struct eth_device *dev)writel (EMAC_MAC_CTL0_SETUP , ®s->mac_ctl0);/* Set MAC CTL1 */ -emac_phy_read (dev->name,1 ,0 , &phy_val); -debug ("PHY SETUP, reg 0 value: %x\n" , phy_val); - duplex_flag = !!(phy_val & (1 <<8 )); - reg_val =0 ; -if (duplex_flag) +if (priv->phydev->duplex ==DUPLEX_FULL ) reg_val = (0x1 <<0 );writel (EMAC_MAC_CTL1_SETUP | reg_val, ®s->mac_ctl1);
@@ -302,7 +327,7 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) {struct emac_regs *regs = (struct emac_regs *)dev->iobase;struct emac_eth_dev *priv = dev->priv; -u16 phy_reg; +int ret;/* Init EMAC */
@@ -320,7 +345,7 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)udelay (1 );/* Set up EMAC */ -emac_setup (dev); +emac_setup (priv);writel (dev->enetaddr[0 ] <<16 | dev->enetaddr[1 ] <<8 | dev->enetaddr[2 ], ®s->mac_a1);
@@ -332,29 +357,32 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)emac_reset (dev);/* PHY POWER UP */ -emac_phy_read (dev->name,1 ,0 , &phy_reg); -emac_phy_write (dev->name,1 ,0 , phy_reg & (~(0x1 <<11 ))); -mdelay (1 ); - -emac_phy_read (dev->name,1 ,0 , &phy_reg); - - priv->speed =miiphy_speed (dev->name,0 ); - priv->duplex =miiphy_duplex (dev->name,0 ); + ret =phy_startup (priv->phydev); +if (ret) { +printf ("Could not initialize PHY %s\n" , + priv->phydev->dev->name); +return ret; + }/* Print link status only once */ if (!priv->link_printed) {printf ("ENET Speed is %d Mbps - %s duplex connection\n" , - priv->speed, (priv->duplex ==HALF ) ?"HALF" :"FULL" ); + priv->phydev->speed, + priv->phydev->duplex ?"FULL" :"HALF" ); priv->link_printed =1 ; }/* Set EMAC SPEED depend on PHY */ -clrsetbits_le32 (®s->mac_supp,1 <<8 , - ((phy_reg & (0x1 <<13 )) >>13 ) <<8 ); +if (priv->phydev->speed ==SPEED_100 ) +setbits_le32 (®s->mac_supp,1 <<8 ); +else +clrbits_le32 (®s->mac_supp,1 <<8 );/* Set duplex depend on phy */ -clrsetbits_le32 (®s->mac_ctl1,1 <<0 , - ((phy_reg & (0x1 <<8 )) >>8 ) <<0 ); +if (priv->phydev->duplex ==DUPLEX_FULL ) +setbits_le32 (®s->mac_ctl1,1 <<0 ); +else +clrbits_le32 (®s->mac_ctl1,1 <<0 );/* Enable RX/TX */ setbits_le32 (®s->ctl,0x7 );
@@ -505,6 +533,7 @@ int sunxi_emac_initialize(void)/* Set MII clock */ clrsetbits_le32 (®s->mac_mcfg,0xf <<2 ,0xd <<2 ); + priv->regs = regs; dev->iobase = (int )regs; dev->priv = priv; dev->init = sunxi_emac_eth_init;
@@ -515,7 +544,5 @@ int sunxi_emac_initialize(void)eth_register (dev); -miiphy_register (dev->name, emac_phy_read, emac_phy_write); - -return 0 ; +return sunxi_emac_init_phy (priv, dev); }
include/configs/sunxi-common.h +2 -0
@@ -350,7 +350,9 @@ extern int soft_i2c_gpio_scl;/* Ethernet support */ #ifdef CONFIG_SUNXI_EMAC +#define CONFIG_PHY_ADDR 1#define CONFIG_MII /* MII PHY management */ +#define CONFIG_PHYLIB #endif #ifdef CONFIG_SUNXI_GMAC
Signature · 1 line
2.3.5
PATCH v2 2/4 sunxi: emac: Prepare for driver-model support
In reply to Hans de GoedeSplit all the core functionality out into functions taking a struct emac_eth_dev *priv argument as preparation for adding driver-model support.
--- drivers/net/sunxi_emac.c | 115 +++++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 44 deletions(-)
drivers/net/sunxi_emac.c +71 -44
@@ -309,9 +309,9 @@ static void emac_setup(struct emac_eth_dev *priv)writel (EMAC_MAC_MFL , ®s->mac_maxf); } -static void emac_reset (struct eth_device *dev) +static void emac_reset (struct emac_eth_dev *priv) { -struct emac_regs *regs = (struct emac_regs *)dev->iobase; +struct emac_regs *regs = priv->regs;debug ("resetting device\n" );
@@ -323,10 +323,9 @@ static void emac_reset(struct eth_device *dev)udelay (200 ); } -static int sunxi_emac_eth_init (struct eth_device *dev,bd_t *bd) +static int _sunxi_emac_eth_init (struct emac_eth_dev *priv,u8 *enetaddr) { -struct emac_regs *regs = (struct emac_regs *)dev->iobase; -struct emac_eth_dev *priv = dev->priv; +struct emac_regs *regs = priv->regs;int ret;/* Init EMAC */
@@ -347,14 +346,14 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)/* Set up EMAC */ emac_setup (priv); -writel (dev->enetaddr[0 ] <<16 | dev->enetaddr[1 ] <<8 | - dev->enetaddr[2 ], ®s->mac_a1); -writel (dev->enetaddr[3 ] <<16 | dev->enetaddr[4 ] <<8 | - dev->enetaddr[5 ], ®s->mac_a0); +writel (enetaddr[0 ] <<16 | enetaddr[1 ] <<8 | enetaddr[2 ], + ®s->mac_a1); +writel (enetaddr[3 ] <<16 | enetaddr[4 ] <<8 | enetaddr[5 ], + ®s->mac_a0);mdelay (1 ); -emac_reset (dev); +emac_reset (priv);/* PHY POWER UP */ ret =phy_startup (priv->phydev);
@@ -390,14 +389,9 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)return 0 ; } -static void sunxi_emac_eth_halt (struct eth_device *dev) +static int _sunxi_emac_eth_recv (struct emac_eth_dev *priv,void *packet) { -/* Nothing to do here */ -} - -static int sunxi_emac_eth_recv (struct eth_device *dev) -{ -struct emac_regs *regs = (struct emac_regs *)dev->iobase; +struct emac_regs *regs = priv->regs;struct emac_rxhdr rxhdr;u32 rxcount;u32 reg_val;
@@ -415,7 +409,7 @@ static int sunxi_emac_eth_recv(struct eth_device *dev)/* Had one stuck? */ rxcount =readl (®s->rx_fbc);if (!rxcount) -return 0 ; +return -EAGAIN ; } reg_val =readl (®s->rx_io_data);
@@ -431,7 +425,7 @@ static int sunxi_emac_eth_recv(struct eth_device *dev)/* Enable RX */ setbits_le32 (®s->ctl,0x1 <<2 ); -return 0 ; +return -EAGAIN ; }/* A packet ready now
@@ -463,22 +457,19 @@ static int sunxi_emac_eth_recv(struct eth_device *dev)if (good_packet) {if (rx_len >DMA_CPU_TRRESHOLD ) {printf ("Received packet is too big (len=%d)\n" , rx_len); - }else { -emac_inblk_32bit ((void *)®s->rx_io_data, - net_rx_packets[0 ], rx_len); - -/* Pass to upper layer */ -net_process_received_packet (net_rx_packets[0 ], rx_len); -return rx_len; +return -EMSGSIZE ; } +emac_inblk_32bit ((void *)®s->rx_io_data, packet, rx_len); +return rx_len; } -return 0 ; +return -EIO ;/* Bad packet */ } -static int sunxi_emac_eth_send (struct eth_device *dev,void *packet,int len) +static int _sunxi_emac_eth_send (struct emac_eth_dev *priv,void *packet, +int len) { -struct emac_regs *regs = (struct emac_regs *)dev->iobase; +struct emac_regs *regs = priv->regs;/* Select channel 0 */ writel (0 , ®s->tx_ins);
@@ -495,17 +486,64 @@ static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len)return 0 ; } -int sunxi_emac_initialize (void ) +static void sunxi_emac_board_setup (struct emac_eth_dev *priv) {struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ;struct sunxi_sramc_regs *sram = (struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE ; +struct emac_regs *regs = priv->regs; +int pin; + +/* Map SRAM to EMAC */ +setbits_le32 (&sram->ctrl1,0x5 <<2 ); + +/* Configure pin mux settings for MII Ethernet */ +for (pin =SUNXI_GPA (0 ); pin <=SUNXI_GPA (17 ); pin++) +sunxi_gpio_set_cfgpin (pin,SUNXI_GPA_EMAC ); + +/* Set up clock gating */ +setbits_le32 (&ccm->ahb_gate0,0x1 <<AHB_GATE_OFFSET_EMAC ); + +/* Set MII clock */ +clrsetbits_le32 (®s->mac_mcfg,0xf <<2 ,0xd <<2 ); +} + +static int sunxi_emac_eth_init (struct eth_device *dev,bd_t *bis) +{ +return _sunxi_emac_eth_init (dev->priv, dev->enetaddr); +} + +static void sunxi_emac_eth_halt (struct eth_device *dev) +{ +/* Nothing to do here */ +} + +static int sunxi_emac_eth_recv (struct eth_device *dev) +{ +int rx_len; + + rx_len =_sunxi_emac_eth_recv (dev->priv, net_rx_packets[0 ]); +if (rx_len <=0 ) +return 0 ; + +/* Pass to upper layer */ +net_process_received_packet (net_rx_packets[0 ], rx_len); + +return rx_len; +} + +static int sunxi_emac_eth_send (struct eth_device *dev,void *packet,int length) +{ +return _sunxi_emac_eth_send (dev->priv, packet, length); +} + +int sunxi_emac_initialize (void ) +{struct emac_regs *regs = (struct emac_regs *)SUNXI_EMAC_BASE ;struct eth_device *dev;struct emac_eth_dev *priv; -int pin; dev =malloc (sizeof (*dev));if (dev ==NULL )
@@ -520,19 +558,6 @@ int sunxi_emac_initialize(void)memset (dev,0 ,sizeof (*dev));memset (priv,0 ,sizeof (struct emac_eth_dev )); -/* Map SRAM to EMAC */ -setbits_le32 (&sram->ctrl1,0x5 <<2 ); - -/* Configure pin mux settings for MII Ethernet */ -for (pin =SUNXI_GPA (0 ); pin <=SUNXI_GPA (17 ); pin++) -sunxi_gpio_set_cfgpin (pin,SUNXI_GPA_EMAC ); - -/* Set up clock gating */ -setbits_le32 (&ccm->ahb_gate0,0x1 <<AHB_GATE_OFFSET_EMAC ); - -/* Set MII clock */ -clrsetbits_le32 (®s->mac_mcfg,0xf <<2 ,0xd <<2 ); - priv->regs = regs; dev->iobase = (int )regs; dev->priv = priv;
@@ -542,6 +567,8 @@ int sunxi_emac_initialize(void) dev->recv = sunxi_emac_eth_recv;strcpy (dev->name,"emac" ); +sunxi_emac_board_setup (priv); +eth_register (dev);return sunxi_emac_init_phy (priv, dev);
Signature · 1 line
2.3.5
PATCH v2 3/4 sunxi: emac: Rename DMA_CPU_TRRESHOLD to EMAC_RX_BUFSIZE
In reply to Hans de GoedeBesides being spelled wron, the DMA_CPU_TRRESHOLD define actually has nothing to do with DMA as we only use mmio fifo access. Rename it to EMAC_RX_BUFSIZE to properly reflect what it does.
--- drivers/net/sunxi_emac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/sunxi_emac.c +2 -2
@@ -153,7 +153,7 @@ struct sunxi_sramc_regs {#define EMAC_CRCERR (0x1 << 4)#define EMAC_LENERR (0x3 << 5) -#define DMA_CPU_TRRESHOLD 2000 +#define EMAC_RX_BUFSIZE 2000struct emac_eth_dev {struct emac_regs *regs;
@@ -455,7 +455,7 @@ static int _sunxi_emac_eth_recv(struct emac_eth_dev *priv, void *packet)/* Move data from EMAC */ if (good_packet) { -if (rx_len >DMA_CPU_TRRESHOLD ) { +if (rx_len >EMAC_RX_BUFSIZE ) {printf ("Received packet is too big (len=%d)\n" , rx_len);return -EMSGSIZE ; }
Signature · 1 line
2.3.5
PATCH v2 3/4 sunxi: emac: Rename DMA_CPU_TRRESHOLD to EMAC_RX_BUFSIZE
Quoted 1 line · Hans de Goede
Besides being spelled wron, the
DMA_CPU_TRRESHOLDdefine actually has
:-)
Quoted 7 lines
nothing to do with DMA as we only use mmio fifo access. Rename it to
EMAC_RX_BUFSIZEto properly reflect what it does.Signed-off-by Hans de Goede <[email protected]>--- drivers/net/sunxi_emac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Quoted 26 lines
drivers/net/sunxi_emac.c +2
-3@@ -153,7 +153,7 @@ struct sunxi_sramc_regs {#define EMAC_CRCERR (0x1 << 4)#define EMAC_LENERR (0x3 << 5) -#define DMA_CPU_TRRESHOLD 2000 +#define EMAC_RX_BUFSIZE 2000struct emac_eth_dev {struct emac_regs *regs;@@ -455,7 +455,7 @@ static int _sunxi_emac_eth_recv(struct emac_eth_dev *priv, void *packet)/* Move data from EMAC */ if (good_packet) { -if (rx_len >DMA_CPU_TRRESHOLD ) { +if (rx_len >EMAC_RX_BUFSIZE ) {printf ("Received packet is too big (len=%d)\n" , rx_len);return -EMSGSIZE ; } --2.3.5
PATCH v2 4/4 sunxi: emac: Add driver model support
In reply to Hans de GoedeModify the sunxi-emac eth driver to support driver model.
--- arch/arm/cpu/armv7/sunxi/board.c | 4 +- drivers/net/sunxi_emac.c | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-)
arch/arm/cpu/armv7/sunxi/board.c +3 -1
@@ -12,7 +12,9 @@#include <common.h> #include <i2c.h> +#ifndef CONFIG_DM_ETH #include <netdev.h> +#endif #include <miiphy.h> #include <serial.h> #ifdef CONFIG_SPL_BUILD
@@ -224,7 +226,7 @@ int cpu_eth_init(bd_t *bis)mdelay (200 );#endif -#ifdef CONFIG_SUNXI_EMAC +#if definedCONFIG_SUNXI_EMAC && !definedCONFIG_DM_ETH rc =sunxi_emac_initialize (bis);if (rc <0 ) {printf ("sunxi: failed to initialize emac\n" );
drivers/net/sunxi_emac.c +81 -0
102 lines not on this page · raw message
Signature · 1 line
2.3.5
v2 cover sunxi: emac: Add driver model support
In reply to Hans de GoedeQuoted 9 lines · Hans de Goede
Hi All,
Here is v2 of my patch series to add driver model support to the sunxi emac driver.
Changes since v1:
-Add a patch to renameDMA_CPU_TRRESHOLDtoEMAC_RX_BUFSIZE.Please review.
All LGTM: Acked-by: Ian Campbell <[email protected]>
v2 cover sunxi: emac: Add driver model support
In reply to Hans de GoedeQuoted 7 lines · Hans de Goede
Here is v2 of my patch series to add driver model support to the sunxi emac driver.
Changes since v1:
-Add a patch to renameDMA_CPU_TRRESHOLDtoEMAC_RX_BUFSIZE.Please review.
Looks good, so:
Thanks,
Stefan