[PATCH] [v2] Nios2: Add Altera TSE MAC driver

Franck JULLIEN franck.jullien at gmail.com
Sun Apr 10 03:13:04 EDT 2011


Hello,

2011/4/10 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>

> On 16:08 Sat 09 Apr     , franck.jullien at gmail.com wrote:
> > From: Franck JULLIEN <franck.jullien at gmail.com>
> >
> > Add Altera Triple Speed Ethernet driver
> >
> > Signed-off-by: Franck JULLIEN <franck.jullien at gmail.com>
> > ---
> >  drivers/net/Kconfig      |   16 ++
> >  drivers/net/Makefile     |    5 +-
> >  drivers/net/altera_tse.c |  620
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/net/altera_tse.h |  313 +++++++++++++++++++++++
> >  4 files changed, 952 insertions(+), 2 deletions(-)
> >  create mode 100644 drivers/net/altera_tse.c
> >  create mode 100644 drivers/net/altera_tse.h
> >
> > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> > index 6479417..19e35db 100644
> > --- a/drivers/net/Kconfig
> > +++ b/drivers/net/Kconfig
> > @@ -84,6 +84,22 @@ config DRIVER_NET_TAP
> >       bool "tap Ethernet driver"
> >       depends on LINUX
> >
> > +config DRIVER_NET_TSE
> > +     depends on NIOS2
> > +     bool "Altera TSE ethernet driver"
> > +     select MIIDEV
> > +     help
> > +       This option enables support for the Altera TSE MAC.
> > +
> > +config TSE_USE_DEDICATED_DESC_MEM
> > +     depends on DRIVER_NET_TSE
> > +     bool "Altera TSE uses dedicated descriptor memory"
> > +     help
> > +       This option tells the TSE driver to use an onchip memory
> > +       to store SGDMA descriptors. Descriptor memory is not
> > +       reserved with a malloc but directly mapped to the memory
> > +       address (defined in config.h)
> > +
> >  source "drivers/net/usb/Kconfig"
> >
> >  endmenu
> > diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> > index 96d3d32..f02618b 100644
> > --- a/drivers/net/Makefile
> > +++ b/drivers/net/Makefile
> > @@ -1,7 +1,7 @@
> > -obj-$(CONFIG_DRIVER_NET_CS8900)              += cs8900.o
> > +obj-$(CONFIG_DRIVER_NET_CS8900)              += cs8900.o
> >  obj-$(CONFIG_DRIVER_NET_SMC911X)     += smc911x.o
> >  obj-$(CONFIG_DRIVER_NET_SMC91111)    += smc91111.o
> > -obj-$(CONFIG_DRIVER_NET_DM9000)              += dm9000.o
> > +obj-$(CONFIG_DRIVER_NET_DM9000)              += dm9000.o
> why do you touch this two?
>
> if you want to fix the whitespace please do it in an other commit
>

OK, I'll correct this.



> >  obj-$(CONFIG_DRIVER_NET_NETX)                += netx_eth.o
> >  obj-$(CONFIG_DRIVER_NET_AT91_ETHER)  += at91_ether.o
> >  obj-$(CONFIG_DRIVER_NET_MPC5200)     += fec_mpc5200.o
> > @@ -11,3 +11,4 @@ obj-$(CONFIG_DRIVER_NET_MACB)               += macb.o
> >  obj-$(CONFIG_DRIVER_NET_TAP)         += tap.o
> >  obj-$(CONFIG_MIIDEV)                 += miidev.o
> >  obj-$(CONFIG_NET_USB)                        += usb/
> > +obj-$(CONFIG_DRIVER_NET_TSE)         += altera_tse.o
> > diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c
> > new file mode 100644
> > index 0000000..2687377
> > --- /dev/null
> > +
> > +static int tse_get_ethaddr(struct eth_device *edev, unsigned char *m)
> > +{
> > +     /* There is no eeprom */
> so return the content of the register no?
>

Well, the register is reseted to 0 when the MAC starts so there is no
Ethernet address
to get.


> > +     return -1;
> > +}
> > +
>
> > +static int tse_eth_send(struct eth_device *edev, void *packet, int
> length)
> > +{
> > +
> > +     struct altera_tse_priv *priv = edev->priv;
> > +     struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx;
> > +     struct alt_sgdma_descriptor *tx_desc = (struct alt_sgdma_descriptor
> *)priv->tx_desc;
> > +
> > +     struct alt_sgdma_descriptor *tx_desc_cur = (struct
> alt_sgdma_descriptor *)&tx_desc[0];
> > +
> > +     flush_dcache_range((uint32_t)packet, (uint32_t)packet + length);
> > +     alt_sgdma_construct_descriptor_burst(
> > +             (struct alt_sgdma_descriptor *)&tx_desc[0],
> > +             (struct alt_sgdma_descriptor *)&tx_desc[1],
> > +             (uint32_t *)packet,  /* read addr */
> > +             (uint32_t *)0,       /*           */
> > +             length,              /* length or EOP ,will change for each
> tx */
> > +             0x1,                 /* gen eop */
> > +             0x0,                 /* read fixed */
> > +             0x1,                 /* write fixed or sop */
> > +             0x0,                 /* read burst */
> > +             0x0,                 /* write burst */
> > +             0x0                  /* channel */
> please use tab for indent I see other in the patch please check
>

I use tab for indent, spaces for alignment. I checked the patch with
checkpatch and it
didn't find errors.....


> > +             );
> > +
> > +     alt_sgdma_do_sync_transfer(tx_sgdma, tx_desc_cur);
> > +
> > +     return 0;;
> > +}
> > +
> > +static void tse_eth_halt(struct eth_device *edev)
> > +{
> > +     struct altera_tse_priv *priv = edev->priv;
> > +     struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx;
> > +     struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx;
> > +
> > +     writel(0, &rx_sgdma->control); /* Stop the controller and reset
> settings */
> > +     writel(0, &tx_sgdma->control); /* Stop the controller and reset
> settings */
> > +}
> > +
> > +static int tse_eth_rx(struct eth_device *edev)
> > +{
> > +     uint16_t packet_length = 0;
> > +
> > +     struct altera_tse_priv *priv = edev->priv;
> > +     struct alt_sgdma_descriptor *rx_desc = (struct alt_sgdma_descriptor
> *)priv->rx_desc;
> > +     struct alt_sgdma_descriptor *rx_desc_cur = &rx_desc[0];
> > +     struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx;
> > +
> > +     if (rx_desc_cur->descriptor_status &
> > +             ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK) {
> > +
> > +             packet_length = rx_desc->actual_bytes_transferred;
> > +             net_receive(NetRxPackets[0], packet_length);
> > +
> > +             /* Clear Run */
> > +             rx_sgdma->control = (rx_sgdma->control &
> (~ALT_SGDMA_CONTROL_RUN_MSK));
> > +
> > +             /* start descriptor again */
> > +             flush_dcache_range((uint32_t)(NetRxPackets[0]),
> (uint32_t)(NetRxPackets[0]) + PKTSIZE);
> > +             alt_sgdma_construct_descriptor_burst(
> > +                     (struct alt_sgdma_descriptor *)&rx_desc[0],
> > +                     (struct alt_sgdma_descriptor *)&rx_desc[1],
> > +                     (uint32_t)0x0,               /* read addr */
> > +                     (uint32_t *)NetRxPackets[0], /*           */
> > +                     0x0,                         /* length or EOP */
> > +                     0x0,                         /* gen eop */
> > +                     0x0,                         /* read fixed */
> > +                     0x0,                         /* write fixed or sop
> */
> > +                     0x0,                         /* read burst */
> > +                     0x0,                         /* write burst */
> > +                     0x0                          /* channel */
> please use tab for indent
> > +             );
> > +
> > +             /* setup the sgdma */
> > +             alt_sgdma_do_async_transfer(priv->sgdma_rx, &rx_desc[0]);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static char *get_phy_name(uint32_t phy_ID)
> > +{
> > +     uint8_t i = 0;
> > +
> > +     while (phy_name_table[i].phy_ID != 0) {
> > +             if (phy_name_table[i].phy_ID == phy_ID)
> > +                     return phy_name_table[i].name;
> > +             i++;
> > +     }
> > +
> > +     return "unknown";
> > +}
> why this?
> > +
> > +static int check_phy_address(struct eth_device *edev)
> > +{
> > +     struct altera_tse_priv *priv = edev->priv;
> > +     uint8_t mii_bus_scan = 0;
> > +     uint8_t current_mii_address = 1;
> > +     uint32_t phy_reg;
> > +     uint32_t phy_ID;
> > +
> > +     if ((priv->miidev)->address < 0)
> > +             mii_bus_scan = 1;
> > +     else
> > +             current_mii_address = (priv->miidev)->address;
> > +
> > +     do {
> > +             /* Grab the bits from PHYIR1, and put them in the upper
> half */
> > +             phy_reg = tse_phy_read(priv->miidev, current_mii_address,
> MII_PHYSID1);
> > +             phy_ID = (phy_reg & 0xffff) << 16;
> > +
> > +             /* Grab the bits from PHYIR2, and put them in the lower
> half */
> > +             phy_reg = tse_phy_read(priv->miidev, current_mii_address,
> MII_PHYSID2);
> > +             phy_ID |= (phy_reg & 0xffff);
> > +
> > +             if (phy_ID != 0xffffffff) {
> > +                     printf("PHY (%s) found at address %d\n",
> get_phy_name(phy_ID), current_mii_address);
> > +                     (priv->miidev)->address = current_mii_address;
> > +                     return 0;
> > +             }
> > +
> > +             current_mii_address++;
> > +
> > +     } while (current_mii_address < 32 && mii_bus_scan);
> > +
> > +     return -1;
> > +}
> > +
> why this?
>

Because sometimes (often ?), hardware doesn't run first time. So I like to
have some information on MII bus running correctly....One day I had a PHY
getting the address 1 and sometimes this f***ing PHY got 31 and this
kind of auto scan helped me to immediately find the problem......

I could remove those function if it is a problem....


>
> Best Regards,
> J.
>

Regards,
Franck.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20110410/8b70bfe3/attachment-0001.html>


More information about the barebox mailing list