[U-Boot] [PATCH] Add support for Faraday Ethernet IP FTMAC100

Ben Warren biggerbadderben at gmail.com
Wed Apr 1 06:37:27 CEST 2009


Hi Po Yu Chang,

PoYu_Chuang wrote:
> This patch adds support for Faraday Technology Ethernet IP - FTMAC100
>
> Signed-off-by: Po-Yu Chuang <ratbert at faraday-tech.com>
>   
Please use a valid e-mail address (hint - it should have an @ sign).  
You may want to provide a brief description of the controller here.
> ---
> diff -ruN u-boot-2009.03/drivers/net/ftmac100.c FA5A320LINUX26_u-boot/drivers/net/ftmac100.c
>   
It's best to use git tools to generate the patch.  If you use 
git-send-email you're more-or-less guaranteed to avoid line-wrapping issues.
> --- u-boot-2009.03/drivers/net/ftmac100.c	1970-01-01 08:00:00.000000000 +0800
> +++ FA5A320LINUX26_u-boot/drivers/net/ftmac100.c	2009-03-31 15:20:33.000000000 +0800
> @@ -0,0 +1,219 @@
> +/*
> + * Faraday FTMAC100 Ethernet
> + *
> + * (C) Copyright 2009 Faraday Technology
> + * Po-Yu Chuang <ratbert at faraday-tech.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#undef	DEBUG
> +
> +#include <config.h>
> +#include <common.h>
> +#include <net.h>
> +#include <asm/io.h>
> +#include "ftmac100.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static unsigned int	ftmac100_base = CONFIG_SYS_MAC100_BASE;
> +
> +static volatile struct ftmac100_txdes	txdes[1];
> +static volatile struct ftmac100_rxdes	rxdes[PKTBUFSRX];
> +static int	rx_index;
> +
> +/*
> + * Reset MAC
> + */
> +static void
> +ftmac100_reset(void)
> +{
> +	debug("ftmac100_reset()\n");
> +
> +	outl(FTMAC100_MACCR_SW_RST, ftmac100_base + FTMAC100_OFFSET_MACCR);
> +
> +	while (inl(ftmac100_base + FTMAC100_OFFSET_MACCR) & FTMAC100_MACCR_SW_RST);
> +}
> +
> +/*
> + * Set MAC address
> + */
> +static void
> +ftmac100_set_mac(const unsigned char *mac)
> +{
> +	unsigned short	maddr = mac[0] << 8 | mac[1];
> +	unsigned int	laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
>   
This is a strange way of doing this.  Do you really need to use two 
variables?
> +
> +	debug("ftmac100_set_mac()\n");
> +
> +	outl(maddr, ftmac100_base + FTMAC100_OFFSET_MAC_MADR);
> +	outl(laddr, ftmac100_base + FTMAC100_OFFSET_MAC_LADR);
>   
Others have mentioned not using outl(), so echo'd here
> +}
> +
> +/*
> + * disable transmitter, receiver
> + */
> +void
> +eth_halt(void)
> +{
> +	debug("eth_halt()\n");
> +
> +	outl(0, ftmac100_base + FTMAC100_OFFSET_MACCR);
> +}
>   
Please don't use the old-style API (eth_halt(), eth_init() etc.)  You 
should have a single xxx_initialize() function that fills in an 
eth_device struct with function pointers to static functions.  You'll 
find lots of examples in drivers/net
> +
> +int
> +eth_init(bd_t *bd)
> +{
> +	int	i;
> +	unsigned int	maccr;
> +
> +	debug("eth_init()\n");
> +
> +	ftmac100_reset();
> +
> +	/* set the ethernet address */
> +
> +	ftmac100_set_mac(gd->bd->bi_enetaddr);
> +
> +	/* disable all interrupts */
> +
> +	outl(0, ftmac100_base + FTMAC100_OFFSET_IMR);
> +
> +	/* initialize descriptors */
> +
> +	rx_index = 0;
> +
> +	txdes[0].txdes1			= FTMAC100_TXDES1_EDOTR;
> +	rxdes[PKTBUFSRX - 1].rxdes1	= FTMAC100_RXDES1_EDORR;
> +
> +	for (i = 0; i < PKTBUFSRX; i++) {
> +		rxdes[i].rxdes2	= (unsigned int)NetRxPackets[i];	/* RXBUF_BADR */
> +		rxdes[i].rxdes1 |= FTMAC100_RXDES1_RXBUF_SIZE(PKTSIZE_ALIGN);
> +		rxdes[i].rxdes0 = FTMAC100_RXDES0_RXDMA_OWN;
> +	}
> +
> +	/* transmit ring */
> +
> +	outl(txdes, ftmac100_base + FTMAC100_OFFSET_TXR_BADR);
> +
> +	/* receive ring */
> +
> +	outl(rxdes, ftmac100_base + FTMAC100_OFFSET_RXR_BADR);
> +
> +	/* poll receive descriptor automatically */
> +
> +	outl(FTMAC100_APTC_RXPOLL_CNT(1), ftmac100_base + FTMAC100_OFFSET_APTC);
> +
> +	/* enable transmitter, receiver */
> +
> +	maccr	= FTMAC100_MACCR_XMT_EN
> +		| FTMAC100_MACCR_RCV_EN
> +		| FTMAC100_MACCR_XDMA_EN
> +		| FTMAC100_MACCR_RDMA_EN
> +		| FTMAC100_MACCR_CRC_APD
> +		| FTMAC100_MACCR_ENRX_IN_HALFTX 
> +		| FTMAC100_MACCR_RX_RUNT
> +		| FTMAC100_MACCR_RX_BROADPKT;
> +
> +	outl(maccr, ftmac100_base + FTMAC100_OFFSET_MACCR);
> +
> +	return 0;
> +}
> +
> +/*
> + * Get a data block via Ethernet
> + */
> +int
> +eth_rx(void)
> +{
> +	volatile struct ftmac100_rxdes	*curr_des	= &rxdes[rx_index];
> +	unsigned short rxlen;
> +
> +	if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN) {
> +		return -1;
> +	}
> +
> +	if (curr_des->rxdes0 & ( FTMAC100_RXDES0_RX_ERR
> +			       | FTMAC100_RXDES0_CRC_ERR
> +			       | FTMAC100_RXDES0_FTL
> +			       | FTMAC100_RXDES0_RUNT
> +			       | FTMAC100_RXDES0_RX_ODD_NB)) {
> +		return -1;
> +	}
> +
> +	rxlen = FTMAC100_RXDES0_RFL(curr_des->rxdes0);
> +
> +	debug("eth_rx(): RX buffer %d, %x received\n", rx_index, rxlen);
> +
> +	/* pass the packet up to the protocol layers. */
> +
> +	NetReceive((void *)curr_des->rxdes2, rxlen);
> +
> +	/* release buffer to DMA */
> +
> +	curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
> +
> +	rx_index = (rx_index + 1) % PKTBUFSRX;
> +
> +	return 0;
> +}
> +
> +/*
> + * Send a data block via Ethernet
> + */
> +int
> +eth_send(volatile void *packet, int length)
> +{
> +	volatile struct ftmac100_txdes	*curr_des	= txdes;
> +	int	tmo;
> +
> +	if (curr_des->txdes0 & FTMAC100_TXDES0_TXPKT_TXDMA_OWN) {
> +		debug("eth_send(): no TX descriptor available\n");
> +		return -1;
> +	}
> +
> +	debug("eth_send(%x, %x)\n", (int)packet, length);
> +
> +	/* initiate a transmit sequence */
> +
> +	curr_des->txdes2	= (unsigned int)packet;	/* TXBUF_BADR */
> +
> +	curr_des->txdes1	&= FTMAC100_TXDES1_EDOTR;
> +	curr_des->txdes1	|= FTMAC100_TXDES1_FTS
> +				|  FTMAC100_TXDES1_LTS
> +				|  FTMAC100_TXDES1_TXBUF_SIZE((length < 64) ? 64 : length);
> +
> +	curr_des->txdes0	= FTMAC100_TXDES0_TXPKT_TXDMA_OWN;
> +
> +	/* start transmit */
> +
> +	outl(1, ftmac100_base + FTMAC100_OFFSET_TXPD);
> +
> +	/* wait for transfer to succeed */
> +
> +	tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
> +	while (curr_des->txdes0 & FTMAC100_TXDES0_TXPKT_TXDMA_OWN) {
> +		if (get_timer(0) >= tmo) {
> +			debug("eth_send(): timed out\n");
> +			return -1;
> +		}
> +	}
> +
> +	debug("eth_send(): packet sent\n");
> +
> +	return 0;
> +}
> +
> diff -ruN u-boot-2009.03/drivers/net/ftmac100.h FA5A320LINUX26_u-boot/drivers/net/ftmac100.h
> --- u-boot-2009.03/drivers/net/ftmac100.h	1970-01-01 08:00:00.000000000 +0800
> +++ FA5A320LINUX26_u-boot/drivers/net/ftmac100.h	2009-03-31 15:49:05.000000000 +0800
> @@ -0,0 +1,146 @@
> +/*
> + * Faraday FTMAC100 Ethernet
> + *
> + * (C) Copyright 2009 Faraday Technology
> + * Po-Yu Chuang <ratbert at faraday-tech.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#ifndef __FTMAC100_H
> +#define __FTMAC100_H
> +
> +#define	FTMAC100_OFFSET_ISR		0x00
> +#define	FTMAC100_OFFSET_IMR		0x04
> +#define	FTMAC100_OFFSET_MAC_MADR	0x08
> +#define	FTMAC100_OFFSET_MAC_LADR	0x0c
> +#define	FTMAC100_OFFSET_MAHT0		0x10
> +#define	FTMAC100_OFFSET_MAHT1		0x14
> +#define	FTMAC100_OFFSET_TXPD		0x18
> +#define	FTMAC100_OFFSET_RXPD		0x1c
> +#define	FTMAC100_OFFSET_TXR_BADR	0x20
> +#define	FTMAC100_OFFSET_RXR_BADR	0x24
> +#define	FTMAC100_OFFSET_ITC		0x28
> +#define	FTMAC100_OFFSET_APTC		0x2c
> +#define	FTMAC100_OFFSET_DBLAC		0x30
> +#define	FTMAC100_OFFSET_MACCR		0x88
> +#define	FTMAC100_OFFSET_MACSR		0x8c
> +#define	FTMAC100_OFFSET_PHYCR		0x90
> +#define	FTMAC100_OFFSET_PHYWDATA	0x94
> +#define	FTMAC100_OFFSET_FCR		0x98
> +#define	FTMAC100_OFFSET_BPR		0x9c
> +#define	FTMAC100_OFFSET_TS		0xc4
> +#define	FTMAC100_OFFSET_DMAFIFOS	0xc8
> +#define	FTMAC100_OFFSET_TM		0xcc
> +#define	FTMAC100_OFFSET_TX_MCOL_SCOL	0xd4
> +#define	FTMAC100_OFFSET_RPF_AEP		0xd8
> +#define	FTMAC100_OFFSET_XM_PG		0xdc
> +#define	FTMAC100_OFFSET_RUNT_TLCC	0xe0
> +#define	FTMAC100_OFFSET_CRCER_FTL	0xe4
> +#define	FTMAC100_OFFSET_RLC_RCC		0xe8
> +#define	FTMAC100_OFFSET_BROC		0xec
> +#define	FTMAC100_OFFSET_MULCA		0xf0
> +#define	FTMAC100_OFFSET_RP		0xf4
> +#define	FTMAC100_OFFSET_XP		0xf8
> +
> +/*
> + * Interrupt status register & interrupt mask register
> + */
> +#define	FTMAC100_INT_RPKT_FINISH	(1 << 0)
> +#define	FTMAC100_INT_NORXBUF		(1 << 1)
> +#define	FTMAC100_INT_XPKT_FINISH	(1 << 2)
> +#define	FTMAC100_INT_NOTXBUF		(1 << 3)
> +#define	FTMAC100_INT_XPKT_OK		(1 << 4)
> +#define	FTMAC100_INT_XPKT_LOST		(1 << 5)
> +#define	FTMAC100_INT_RPKT_SAV		(1 << 6)
> +#define	FTMAC100_INT_RPKT_LOST		(1 << 7)
> +#define	FTMAC100_INT_AHB_ERR		(1 << 8)
> +#define	FTMAC100_INT_PHYSTS_CHG		(1 << 9)
> +
> +/*
> + * Automatic polling timer control register
> + */
> +#define	FTMAC100_APTC_RXPOLL_CNT(x)	(((x) & 0xf) << 0)
> +#define	FTMAC100_APTC_RXPOLL_TIME_SEL	(1 << 4)
> +#define	FTMAC100_APTC_TXPOLL_CNT(x)	(((x) & 0xf) << 8)
> +#define	FTMAC100_APTC_TXPOLL_TIME_SEL	(1 << 12)
> +
> +/*
> + * MAC control register
> + */
> +#define	FTMAC100_MACCR_XDMA_EN		(1 << 0)
> +#define	FTMAC100_MACCR_RDMA_EN		(1 << 1)
> +#define	FTMAC100_MACCR_SW_RST		(1 << 2)
> +#define	FTMAC100_MACCR_LOOP_EN		(1 << 3)
> +#define	FTMAC100_MACCR_CRC_DIS		(1 << 4)
> +#define	FTMAC100_MACCR_XMT_EN		(1 << 5)
> +#define	FTMAC100_MACCR_ENRX_IN_HALFTX	(1 << 6)
> +#define	FTMAC100_MACCR_RCV_EN		(1 << 8)
> +#define	FTMAC100_MACCR_HT_MULTI_EN	(1 << 9)
> +#define	FTMAC100_MACCR_RX_RUNT		(1 << 10)
> +#define	FTMAC100_MACCR_RX_FTL		(1 << 11)
> +#define	FTMAC100_MACCR_RCV_ALL		(1 << 12)
> +#define	FTMAC100_MACCR_CRC_APD		(1 << 14)
> +#define	FTMAC100_MACCR_FULLDUP		(1 << 15)
> +#define	FTMAC100_MACCR_RX_MULTIPKT	(1 << 16)
> +#define	FTMAC100_MACCR_RX_BROADPKT	(1 << 17)
> +
> +/*
> + * Transmit descriptor, aligned to 16 bytes
> + */
> +struct ftmac100_txdes {
> +	unsigned int	txdes0;
> +	unsigned int	txdes1;
> +	unsigned int	txdes2;	/* TXBUF_BADR */
> +	unsigned int	txdes3;	/* not used by HW */
> +} __attribute__ ((aligned(16)));
> +
> +#define	FTMAC100_TXDES0_TXPKT_LATECOL	(1 << 0)
> +#define	FTMAC100_TXDES0_TXPKT_EXSCOL	(1 << 1)
> +#define	FTMAC100_TXDES0_TXPKT_TXDMA_OWN	(1 << 31)
> +
> +#define	FTMAC100_TXDES1_TXBUF_SIZE(x)	((x) & 0x7ff)
> +#define	FTMAC100_TXDES1_LTS		(1 << 27)
> +#define	FTMAC100_TXDES1_FTS		(1 << 28)
> +#define	FTMAC100_TXDES1_TX2FIC		(1 << 29)
> +#define	FTMAC100_TXDES1_TXIC		(1 << 30)
> +#define	FTMAC100_TXDES1_EDOTR		(1 << 31)
> +
> +/*
> + * Receive descriptor, aligned to 16 bytes
> + */
> +struct ftmac100_rxdes {
> +	unsigned int	rxdes0;
> +	unsigned int	rxdes1;
> +	unsigned int	rxdes2;	/* RXBUF_BADR */
> +	unsigned int	rxdes3;	/* not used by HW */
> +} __attribute__ ((aligned(16)));
> +
> +#define	FTMAC100_RXDES0_RFL(des)	((des) & 0x7ff)
> +#define	FTMAC100_RXDES0_MULTICAST	(1 << 16)
> +#define	FTMAC100_RXDES0_BROADCAST	(1 << 17)
> +#define	FTMAC100_RXDES0_RX_ERR		(1 << 18)
> +#define	FTMAC100_RXDES0_CRC_ERR		(1 << 19)
> +#define	FTMAC100_RXDES0_FTL		(1 << 20)
> +#define	FTMAC100_RXDES0_RUNT		(1 << 21)
> +#define	FTMAC100_RXDES0_RX_ODD_NB	(1 << 22)
> +#define	FTMAC100_RXDES0_LRS		(1 << 28)
> +#define	FTMAC100_RXDES0_FRS		(1 << 29)
> +#define	FTMAC100_RXDES0_RXDMA_OWN	(1 << 31)
> +
> +#define	FTMAC100_RXDES1_RXBUF_SIZE(x)	((x) & 0x7ff)
> +#define	FTMAC100_RXDES1_EDORR		(1 << 31)
> +
> +#endif /* __FTMAC100_H */
> diff -ruN u-boot-2009.03/drivers/net/Makefile FA5A320LINUX26_u-boot/drivers/net/Makefile
> --- u-boot-2009.03/drivers/net/Makefile	2009-03-22 05:04:41.000000000 +0800
> +++ FA5A320LINUX26_u-boot/drivers/net/Makefile	2009-03-31 15:35:35.000000000 +0800
> @@ -38,6 +38,7 @@
>  COBJS-$(CONFIG_EEPRO100) += eepro100.o
>  COBJS-$(CONFIG_ENC28J60) += enc28j60.o
>  COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
> +COBJS-$(CONFIG_DRIVER_FTMAC100) += ftmac100.o
>  COBJS-$(CONFIG_GRETH) += greth.o
>  COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
>  COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o

In general, this is quite promising - thanks a lot!  We tend to not 
include drivers without a board that uses it.  Please consider 
submitting your board code too.

regards,
Ben


More information about the U-Boot mailing list