From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ben Warren Date: Tue, 31 Mar 2009 21:37:27 -0700 Subject: [U-Boot] [PATCH] Add support for Faraday Ethernet IP FTMAC100 In-Reply-To: <200903310813.n2V8DBic010484@ftcpcw82.faraday.com.tw> References: <200903310813.n2V8DBic010484@ftcpcw82.faraday.com.tw> Message-ID: <49D2EF87.3040202@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Po Yu Chang, PoYu_Chuang wrote: > This patch adds support for Faraday Technology Ethernet IP - FTMAC100 > > Signed-off-by: Po-Yu Chuang > 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 > + * > + * 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 > +#include > +#include > +#include > +#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 > + * > + * 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