Home | History | Annotate | Download | only in mach-au1x00
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /* Only eth0 supported for now
      3  *
      4  * (C) Copyright 2003
      5  * Thomas.Lange (at) corelatus.se
      6  */
      7 #include <config.h>
      8 
      9 #if defined(CONFIG_SYS_DISCOVER_PHY)
     10 #error "PHY not supported yet"
     11 /* We just assume that we are running 100FD for now */
     12 /* We all use switches, right? ;-) */
     13 #endif
     14 
     15 /* I assume ethernet behaves like au1000 */
     16 
     17 #ifdef CONFIG_SOC_AU1000
     18 /* Base address differ between cpu:s */
     19 #define ETH0_BASE AU1000_ETH0_BASE
     20 #define MAC0_ENABLE AU1000_MAC0_ENABLE
     21 #else
     22 #ifdef CONFIG_SOC_AU1100
     23 #define ETH0_BASE AU1100_ETH0_BASE
     24 #define MAC0_ENABLE AU1100_MAC0_ENABLE
     25 #else
     26 #ifdef CONFIG_SOC_AU1500
     27 #define ETH0_BASE AU1500_ETH0_BASE
     28 #define MAC0_ENABLE AU1500_MAC0_ENABLE
     29 #else
     30 #ifdef CONFIG_SOC_AU1550
     31 #define ETH0_BASE AU1550_ETH0_BASE
     32 #define MAC0_ENABLE AU1550_MAC0_ENABLE
     33 #else
     34 #error "No valid cpu set"
     35 #endif
     36 #endif
     37 #endif
     38 #endif
     39 
     40 #include <common.h>
     41 #include <malloc.h>
     42 #include <net.h>
     43 #include <command.h>
     44 #include <asm/io.h>
     45 #include <mach/au1x00.h>
     46 
     47 #if defined(CONFIG_CMD_MII)
     48 #include <miiphy.h>
     49 #endif
     50 
     51 /* Ethernet Transmit and Receive Buffers */
     52 #define DBUF_LENGTH  1520
     53 #define PKT_MAXBUF_SIZE		1518
     54 
     55 static char txbuf[DBUF_LENGTH];
     56 
     57 static int next_tx;
     58 static int next_rx;
     59 
     60 /* 4 rx and 4 tx fifos */
     61 #define NO_OF_FIFOS 4
     62 
     63 typedef struct{
     64 	u32 status;
     65 	u32 addr;
     66 	u32 len; /* Only used for tx */
     67 	u32 not_used;
     68 } mac_fifo_t;
     69 
     70 mac_fifo_t mac_fifo[NO_OF_FIFOS];
     71 
     72 #define MAX_WAIT 1000
     73 
     74 #if defined(CONFIG_CMD_MII)
     75 int au1x00_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
     76 {
     77 	unsigned short value = 0;
     78 	volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
     79 	volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
     80 	u32 mii_control;
     81 	unsigned int timedout = 20;
     82 
     83 	while (*mii_control_reg & MAC_MII_BUSY) {
     84 		udelay(1000);
     85 		if (--timedout == 0) {
     86 			printf("au1x00_eth: miiphy_read busy timeout!!\n");
     87 			return -1;
     88 		}
     89 	}
     90 
     91 	mii_control = MAC_SET_MII_SELECT_REG(reg) |
     92 		MAC_SET_MII_SELECT_PHY(addr) | MAC_MII_READ;
     93 
     94 	*mii_control_reg = mii_control;
     95 
     96 	timedout = 20;
     97 	while (*mii_control_reg & MAC_MII_BUSY) {
     98 		udelay(1000);
     99 		if (--timedout == 0) {
    100 			printf("au1x00_eth: miiphy_read busy timeout!!\n");
    101 			return -1;
    102 		}
    103 	}
    104 	value = *mii_data_reg;
    105 	return value;
    106 }
    107 
    108 int au1x00_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
    109 			u16 value)
    110 {
    111 	volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
    112 	volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
    113 	u32 mii_control;
    114 	unsigned int timedout = 20;
    115 
    116 	while (*mii_control_reg & MAC_MII_BUSY) {
    117 		udelay(1000);
    118 		if (--timedout == 0) {
    119 			printf("au1x00_eth: miiphy_write busy timeout!!\n");
    120 			return -1;
    121 		}
    122 	}
    123 
    124 	mii_control = MAC_SET_MII_SELECT_REG(reg) |
    125 		MAC_SET_MII_SELECT_PHY(addr) | MAC_MII_WRITE;
    126 
    127 	*mii_data_reg = value;
    128 	*mii_control_reg = mii_control;
    129 	return 0;
    130 }
    131 #endif
    132 
    133 static int au1x00_send(struct eth_device *dev, void *packet, int length)
    134 {
    135 	volatile mac_fifo_t *fifo_tx =
    136 		(volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS);
    137 	int i;
    138 	int res;
    139 
    140 	/* tx fifo should always be idle */
    141 	fifo_tx[next_tx].len = length;
    142 	fifo_tx[next_tx].addr = (virt_to_phys(packet))|TX_DMA_ENABLE;
    143 	au_sync();
    144 
    145 	udelay(1);
    146 	i=0;
    147 	while(!(fifo_tx[next_tx].addr&TX_T_DONE)){
    148 		if(i>MAX_WAIT){
    149 			printf("TX timeout\n");
    150 			break;
    151 		}
    152 		udelay(1);
    153 		i++;
    154 	}
    155 
    156 	/* Clear done bit */
    157 	fifo_tx[next_tx].addr = 0;
    158 	fifo_tx[next_tx].len = 0;
    159 	au_sync();
    160 
    161 	res = fifo_tx[next_tx].status;
    162 
    163 	next_tx++;
    164 	if(next_tx>=NO_OF_FIFOS){
    165 		next_tx=0;
    166 	}
    167 	return(res);
    168 }
    169 
    170 static int au1x00_recv(struct eth_device* dev){
    171 	volatile mac_fifo_t *fifo_rx =
    172 		(volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS);
    173 
    174 	int length;
    175 	u32 status;
    176 
    177 	for(;;){
    178 		if(!(fifo_rx[next_rx].addr&RX_T_DONE)){
    179 			/* Nothing has been received */
    180 			return(-1);
    181 		}
    182 
    183 		status = fifo_rx[next_rx].status;
    184 
    185 		length = status&0x3FFF;
    186 
    187 		if(status&RX_ERROR){
    188 			printf("Rx error 0x%x\n", status);
    189 		} else {
    190 			/* Pass the packet up to the protocol layers. */
    191 			net_process_received_packet(net_rx_packets[next_rx],
    192 						    length - 4);
    193 		}
    194 
    195 		fifo_rx[next_rx].addr =
    196 			(virt_to_phys(net_rx_packets[next_rx])) | RX_DMA_ENABLE;
    197 
    198 		next_rx++;
    199 		if(next_rx>=NO_OF_FIFOS){
    200 			next_rx=0;
    201 		}
    202 	} /* for */
    203 
    204 	return(0); /* Does anyone use this? */
    205 }
    206 
    207 static int au1x00_init(struct eth_device* dev, bd_t * bd){
    208 
    209 	volatile u32 *macen = (volatile u32*)MAC0_ENABLE;
    210 	volatile u32 *mac_ctrl = (volatile u32*)(ETH0_BASE+MAC_CONTROL);
    211 	volatile u32 *mac_addr_high = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_HIGH);
    212 	volatile u32 *mac_addr_low = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_LOW);
    213 	volatile u32 *mac_mcast_high = (volatile u32*)(ETH0_BASE+MAC_MCAST_HIGH);
    214 	volatile u32 *mac_mcast_low = (volatile u32*)(ETH0_BASE+MAC_MCAST_LOW);
    215 	volatile mac_fifo_t *fifo_tx =
    216 		(volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS);
    217 	volatile mac_fifo_t *fifo_rx =
    218 		(volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS);
    219 	int i;
    220 
    221 	next_tx = TX_GET_DMA_BUFFER(fifo_tx[0].addr);
    222 	next_rx = RX_GET_DMA_BUFFER(fifo_rx[0].addr);
    223 
    224 	/* We have to enable clocks before releasing reset */
    225 	*macen = MAC_EN_CLOCK_ENABLE;
    226 	udelay(10);
    227 
    228 	/* Enable MAC0 */
    229 	/* We have to release reset before accessing registers */
    230 	*macen = MAC_EN_CLOCK_ENABLE|MAC_EN_RESET0|
    231 		MAC_EN_RESET1|MAC_EN_RESET2;
    232 	udelay(10);
    233 
    234 	for(i=0;i<NO_OF_FIFOS;i++){
    235 		fifo_tx[i].len = 0;
    236 		fifo_tx[i].addr = virt_to_phys(&txbuf[0]);
    237 		fifo_rx[i].addr = (virt_to_phys(net_rx_packets[i])) |
    238 			RX_DMA_ENABLE;
    239 	}
    240 
    241 	/* Put mac addr in little endian */
    242 #define ea eth_get_ethaddr()
    243 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
    244 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
    245 		(ea[1] <<  8) | (ea[0]	    ) ;
    246 #undef ea
    247 	*mac_mcast_low = 0;
    248 	*mac_mcast_high = 0;
    249 
    250 	/* Make sure the MAC buffer is in the correct endian mode */
    251 #ifdef __LITTLE_ENDIAN
    252 	*mac_ctrl = MAC_FULL_DUPLEX;
    253 	udelay(1);
    254 	*mac_ctrl = MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE;
    255 #else
    256 	*mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX;
    257 	udelay(1);
    258 	*mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE;
    259 #endif
    260 
    261 	return(1);
    262 }
    263 
    264 static void au1x00_halt(struct eth_device* dev){
    265 	volatile u32 *macen = (volatile u32*)MAC0_ENABLE;
    266 
    267 	/* Put MAC0 in reset */
    268 	*macen = 0;
    269 }
    270 
    271 int au1x00_enet_initialize(bd_t *bis){
    272 	struct eth_device* dev;
    273 
    274 	if ((dev = (struct eth_device*)malloc(sizeof *dev)) == NULL) {
    275 		puts ("malloc failed\n");
    276 		return -1;
    277 	}
    278 
    279 	memset(dev, 0, sizeof *dev);
    280 
    281 	strcpy(dev->name, "Au1X00 ethernet");
    282 	dev->iobase = 0;
    283 	dev->priv   = 0;
    284 	dev->init   = au1x00_init;
    285 	dev->halt   = au1x00_halt;
    286 	dev->send   = au1x00_send;
    287 	dev->recv   = au1x00_recv;
    288 
    289 	eth_register(dev);
    290 
    291 #if defined(CONFIG_CMD_MII)
    292 	int retval;
    293 	struct mii_dev *mdiodev = mdio_alloc();
    294 	if (!mdiodev)
    295 		return -ENOMEM;
    296 	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
    297 	mdiodev->read = au1x00_miiphy_read;
    298 	mdiodev->write = au1x00_miiphy_write;
    299 
    300 	retval = mdio_register(mdiodev);
    301 	if (retval < 0)
    302 		return retval;
    303 #endif
    304 
    305 	return 1;
    306 }
    307 
    308 int cpu_eth_init(bd_t *bis)
    309 {
    310 	au1x00_enet_initialize(bis);
    311 	return 0;
    312 }
    313