net: add altera triple speeds ethernet mac driver
This driver supports the Altera triple speeds 10/100/1000 ethernet mac. Signed-off-by: Thomas Chou <thomas@wytron.com.tw> Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
This commit is contained in:
		
							parent
							
								
									f6569884b4
								
							
						
					
					
						commit
						c960b13ed2
					
				|  | @ -27,6 +27,7 @@ LIB	:= $(obj)libnet.a | ||||||
| 
 | 
 | ||||||
| COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o | COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o | ||||||
| COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o | COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o | ||||||
|  | COBJS-$(CONFIG_ALTERA_TSE) += altera_tse.o | ||||||
| COBJS-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o | COBJS-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o | ||||||
| COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o | COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o | ||||||
| COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o | COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o | ||||||
|  |  | ||||||
|  | @ -0,0 +1,935 @@ | ||||||
|  | /*
 | ||||||
|  |  * Altera 10/100/1000 triple speed ethernet mac driver | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2008 Altera Corporation. | ||||||
|  |  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #include <config.h> | ||||||
|  | #include <common.h> | ||||||
|  | #include <malloc.h> | ||||||
|  | #include <net.h> | ||||||
|  | #include <command.h> | ||||||
|  | #include <asm/cache.h> | ||||||
|  | #include <asm/dma-mapping.h> | ||||||
|  | #include <miiphy.h> | ||||||
|  | #include "altera_tse.h" | ||||||
|  | 
 | ||||||
|  | /* sgdma debug - print descriptor */ | ||||||
|  | static void alt_sgdma_print_desc(volatile struct alt_sgdma_descriptor *desc) | ||||||
|  | { | ||||||
|  | 	debug("SGDMA DEBUG :\n"); | ||||||
|  | 	debug("desc->source : 0x%x \n", (unsigned int)desc->source); | ||||||
|  | 	debug("desc->destination : 0x%x \n", (unsigned int)desc->destination); | ||||||
|  | 	debug("desc->next : 0x%x \n", (unsigned int)desc->next); | ||||||
|  | 	debug("desc->source_pad : 0x%x \n", (unsigned int)desc->source_pad); | ||||||
|  | 	debug("desc->destination_pad : 0x%x \n", | ||||||
|  | 	      (unsigned int)desc->destination_pad); | ||||||
|  | 	debug("desc->next_pad : 0x%x \n", (unsigned int)desc->next_pad); | ||||||
|  | 	debug("desc->bytes_to_transfer : 0x%x \n", | ||||||
|  | 	      (unsigned int)desc->bytes_to_transfer); | ||||||
|  | 	debug("desc->actual_bytes_transferred : 0x%x \n", | ||||||
|  | 	      (unsigned int)desc->actual_bytes_transferred); | ||||||
|  | 	debug("desc->descriptor_status : 0x%x \n", | ||||||
|  | 	      (unsigned int)desc->descriptor_status); | ||||||
|  | 	debug("desc->descriptor_control : 0x%x \n", | ||||||
|  | 	      (unsigned int)desc->descriptor_control); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* This is a generic routine that the SGDMA mode-specific routines
 | ||||||
|  |  * call to populate a descriptor. | ||||||
|  |  * arg1	    :pointer to first SGDMA descriptor. | ||||||
|  |  * arg2	    :pointer to next  SGDMA descriptor. | ||||||
|  |  * arg3	    :Address to where data to be written. | ||||||
|  |  * arg4	    :Address from where data to be read. | ||||||
|  |  * arg5	    :no of byte to transaction. | ||||||
|  |  * arg6	    :variable indicating to generate start of packet or not | ||||||
|  |  * arg7	    :read fixed | ||||||
|  |  * arg8	    :write fixed | ||||||
|  |  * arg9	    :read burst | ||||||
|  |  * arg10    :write burst | ||||||
|  |  * arg11    :atlantic_channel number | ||||||
|  |  */ | ||||||
|  | static void alt_sgdma_construct_descriptor_burst( | ||||||
|  | 	volatile struct alt_sgdma_descriptor *desc, | ||||||
|  | 	volatile struct alt_sgdma_descriptor *next, | ||||||
|  | 	unsigned int *read_addr, | ||||||
|  | 	unsigned int *write_addr, | ||||||
|  | 	unsigned short length_or_eop, | ||||||
|  | 	int generate_eop, | ||||||
|  | 	int read_fixed, | ||||||
|  | 	int write_fixed_or_sop, | ||||||
|  | 	int read_burst, | ||||||
|  | 	int write_burst, | ||||||
|  | 	unsigned char atlantic_channel) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * Mark the "next" descriptor as "not" owned by hardware. This prevents | ||||||
|  | 	 * The SGDMA controller from continuing to process the chain. This is | ||||||
|  | 	 * done as a single IO write to bypass cache, without flushing | ||||||
|  | 	 * the entire descriptor, since only the 8-bit descriptor status must | ||||||
|  | 	 * be flushed. | ||||||
|  | 	 */ | ||||||
|  | 	if (!next) | ||||||
|  | 		debug("Next descriptor not defined!!\n"); | ||||||
|  | 
 | ||||||
|  | 	next->descriptor_control = (next->descriptor_control & | ||||||
|  | 		~ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK); | ||||||
|  | 
 | ||||||
|  | 	desc->source = (unsigned int *)((unsigned int)read_addr & 0x1FFFFFFF); | ||||||
|  | 	desc->destination = | ||||||
|  | 	    (unsigned int *)((unsigned int)write_addr & 0x1FFFFFFF); | ||||||
|  | 	desc->next = (unsigned int *)((unsigned int)next & 0x1FFFFFFF); | ||||||
|  | 	desc->source_pad = 0x0; | ||||||
|  | 	desc->destination_pad = 0x0; | ||||||
|  | 	desc->next_pad = 0x0; | ||||||
|  | 	desc->bytes_to_transfer = length_or_eop; | ||||||
|  | 	desc->actual_bytes_transferred = 0; | ||||||
|  | 	desc->descriptor_status = 0x0; | ||||||
|  | 
 | ||||||
|  | 	/* SGDMA burst not currently supported */ | ||||||
|  | 	desc->read_burst = 0; | ||||||
|  | 	desc->write_burst = 0; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Set the descriptor control block as follows: | ||||||
|  | 	 * - Set "owned by hardware" bit | ||||||
|  | 	 * - Optionally set "generate EOP" bit | ||||||
|  | 	 * - Optionally set the "read from fixed address" bit | ||||||
|  | 	 * - Optionally set the "write to fixed address bit (which serves | ||||||
|  | 	 *   serves as a "generate SOP" control bit in memory-to-stream mode). | ||||||
|  | 	 * - Set the 4-bit atlantic channel, if specified | ||||||
|  | 	 * | ||||||
|  | 	 * Note this step is performed after all other descriptor information | ||||||
|  | 	 * has been filled out so that, if the controller already happens to be | ||||||
|  | 	 * pointing at this descriptor, it will not run (via the "owned by | ||||||
|  | 	 * hardware" bit) until all other descriptor has been set up. | ||||||
|  | 	 */ | ||||||
|  | 
 | ||||||
|  | 	desc->descriptor_control = | ||||||
|  | 	    ((ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK) | | ||||||
|  | 	     (generate_eop ? | ||||||
|  | 	      ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK : 0x0) | | ||||||
|  | 	     (read_fixed ? | ||||||
|  | 	      ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK : 0x0) | | ||||||
|  | 	     (write_fixed_or_sop ? | ||||||
|  | 	      ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK : 0x0) | | ||||||
|  | 	     (atlantic_channel ? ((atlantic_channel & 0x0F) << 3) : 0) | ||||||
|  | 		    ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int alt_sgdma_do_sync_transfer(volatile struct alt_sgdma_registers *dev, | ||||||
|  | 			       volatile struct alt_sgdma_descriptor *desc) | ||||||
|  | { | ||||||
|  | 	unsigned int status; | ||||||
|  | 	int counter = 0; | ||||||
|  | 
 | ||||||
|  | 	/* Wait for any pending transfers to complete */ | ||||||
|  | 	alt_sgdma_print_desc(desc); | ||||||
|  | 	status = dev->status; | ||||||
|  | 
 | ||||||
|  | 	counter = 0; | ||||||
|  | 	while (dev->status & ALT_SGDMA_STATUS_BUSY_MSK) { | ||||||
|  | 		if (counter++ > ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (counter >= ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) | ||||||
|  | 		debug("Timeout waiting sgdma in do sync!\n"); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Clear any (previous) status register information | ||||||
|  | 	 * that might occlude our error checking later. | ||||||
|  | 	 */ | ||||||
|  | 	dev->status = 0xFF; | ||||||
|  | 
 | ||||||
|  | 	/* Point the controller at the descriptor */ | ||||||
|  | 	dev->next_descriptor_pointer = (unsigned int)desc & 0x1FFFFFFF; | ||||||
|  | 	debug("next desc in sgdma 0x%x\n", | ||||||
|  | 	      (unsigned int)dev->next_descriptor_pointer); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Set up SGDMA controller to: | ||||||
|  | 	 * - Disable interrupt generation | ||||||
|  | 	 * - Run once a valid descriptor is written to controller | ||||||
|  | 	 * - Stop on an error with any particular descriptor | ||||||
|  | 	 */ | ||||||
|  | 	dev->control = (ALT_SGDMA_CONTROL_RUN_MSK | | ||||||
|  | 			ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK); | ||||||
|  | 
 | ||||||
|  | 	/* Wait for the descriptor (chain) to complete */ | ||||||
|  | 	status = dev->status; | ||||||
|  | 	debug("wait for sgdma...."); | ||||||
|  | 	while (dev->status & ALT_SGDMA_STATUS_BUSY_MSK) | ||||||
|  | 		; | ||||||
|  | 	debug("done\n"); | ||||||
|  | 
 | ||||||
|  | 	/* Clear Run */ | ||||||
|  | 	dev->control = (dev->control & (~ALT_SGDMA_CONTROL_RUN_MSK)); | ||||||
|  | 
 | ||||||
|  | 	/* Get & clear status register contents */ | ||||||
|  | 	status = dev->status; | ||||||
|  | 	dev->status = 0xFF; | ||||||
|  | 
 | ||||||
|  | 	/* we really should check if the transfer completes properly */ | ||||||
|  | 	debug("tx sgdma status = 0x%x", status); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int alt_sgdma_do_async_transfer(volatile struct alt_sgdma_registers *dev, | ||||||
|  | 				volatile struct alt_sgdma_descriptor *desc) | ||||||
|  | { | ||||||
|  | 	unsigned int status; | ||||||
|  | 	int counter = 0; | ||||||
|  | 
 | ||||||
|  | 	/* Wait for any pending transfers to complete */ | ||||||
|  | 	alt_sgdma_print_desc(desc); | ||||||
|  | 	status = dev->status; | ||||||
|  | 
 | ||||||
|  | 	counter = 0; | ||||||
|  | 	while (dev->status & ALT_SGDMA_STATUS_BUSY_MSK) { | ||||||
|  | 		if (counter++ > ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (counter >= ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) | ||||||
|  | 		debug("Timeout waiting sgdma in do async!\n"); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Clear any (previous) status register information | ||||||
|  | 	 * that might occlude our error checking later. | ||||||
|  | 	 */ | ||||||
|  | 	dev->status = 0xFF; | ||||||
|  | 
 | ||||||
|  | 	/* Point the controller at the descriptor */ | ||||||
|  | 	dev->next_descriptor_pointer = (unsigned int)desc & 0x1FFFFFFF; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Set up SGDMA controller to: | ||||||
|  | 	 * - Disable interrupt generation | ||||||
|  | 	 * - Run once a valid descriptor is written to controller | ||||||
|  | 	 * - Stop on an error with any particular descriptor | ||||||
|  | 	 */ | ||||||
|  | 	dev->control = (ALT_SGDMA_CONTROL_RUN_MSK | | ||||||
|  | 			ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK); | ||||||
|  | 
 | ||||||
|  | 	/* we really should check if the transfer completes properly */ | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* u-boot interface */ | ||||||
|  | static int tse_adjust_link(struct altera_tse_priv *priv) | ||||||
|  | { | ||||||
|  | 	unsigned int refvar; | ||||||
|  | 
 | ||||||
|  | 	refvar = priv->mac_dev->command_config.image; | ||||||
|  | 
 | ||||||
|  | 	if (!(priv->duplexity)) | ||||||
|  | 		refvar |= ALTERA_TSE_CMD_HD_ENA_MSK; | ||||||
|  | 	else | ||||||
|  | 		refvar &= ~ALTERA_TSE_CMD_HD_ENA_MSK; | ||||||
|  | 
 | ||||||
|  | 	switch (priv->speed) { | ||||||
|  | 	case 1000: | ||||||
|  | 		refvar |= ALTERA_TSE_CMD_ETH_SPEED_MSK; | ||||||
|  | 		refvar &= ~ALTERA_TSE_CMD_ENA_10_MSK; | ||||||
|  | 		break; | ||||||
|  | 	case 100: | ||||||
|  | 		refvar &= ~ALTERA_TSE_CMD_ETH_SPEED_MSK; | ||||||
|  | 		refvar &= ~ALTERA_TSE_CMD_ENA_10_MSK; | ||||||
|  | 		break; | ||||||
|  | 	case 10: | ||||||
|  | 		refvar &= ~ALTERA_TSE_CMD_ETH_SPEED_MSK; | ||||||
|  | 		refvar |= ALTERA_TSE_CMD_ENA_10_MSK; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	priv->mac_dev->command_config.image = refvar; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tse_eth_send(struct eth_device *dev, | ||||||
|  | 			volatile void *packet, int length) | ||||||
|  | { | ||||||
|  | 	struct altera_tse_priv *priv = dev->priv; | ||||||
|  | 	volatile struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *tx_desc = | ||||||
|  | 	    (volatile struct alt_sgdma_descriptor *)priv->tx_desc; | ||||||
|  | 
 | ||||||
|  | 	volatile struct alt_sgdma_descriptor *tx_desc_cur = | ||||||
|  | 	    (volatile struct alt_sgdma_descriptor *)&tx_desc[0]; | ||||||
|  | 
 | ||||||
|  | 	flush_dcache((unsigned long)packet, length); | ||||||
|  | 	alt_sgdma_construct_descriptor_burst( | ||||||
|  | 		(volatile struct alt_sgdma_descriptor *)&tx_desc[0], | ||||||
|  | 		(volatile struct alt_sgdma_descriptor *)&tx_desc[1], | ||||||
|  | 		(unsigned int *)packet,	/* read addr */ | ||||||
|  | 		(unsigned int *)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 */ | ||||||
|  | 		); | ||||||
|  | 	debug("TX Packet @ 0x%x,0x%x bytes", (unsigned int)packet, length); | ||||||
|  | 
 | ||||||
|  | 	/* send the packet */ | ||||||
|  | 	debug("sending packet\n"); | ||||||
|  | 	alt_sgdma_do_sync_transfer(tx_sgdma, tx_desc_cur); | ||||||
|  | 	debug("sent %d bytes\n", tx_desc_cur->actual_bytes_transferred); | ||||||
|  | 	return tx_desc_cur->actual_bytes_transferred; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tse_eth_rx(struct eth_device *dev) | ||||||
|  | { | ||||||
|  | 	int packet_length = 0; | ||||||
|  | 	struct altera_tse_priv *priv = dev->priv; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *rx_desc = | ||||||
|  | 	    (volatile struct alt_sgdma_descriptor *)priv->rx_desc; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *rx_desc_cur = &rx_desc[0]; | ||||||
|  | 
 | ||||||
|  | 	if (rx_desc_cur->descriptor_status & | ||||||
|  | 	    ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK) { | ||||||
|  | 		debug("got packet\n"); | ||||||
|  | 		packet_length = rx_desc->actual_bytes_transferred; | ||||||
|  | 		NetReceive(NetRxPackets[0], packet_length); | ||||||
|  | 
 | ||||||
|  | 		/* start descriptor again */ | ||||||
|  | 		flush_dcache((unsigned long)(NetRxPackets[0]), PKTSIZE_ALIGN); | ||||||
|  | 		alt_sgdma_construct_descriptor_burst( | ||||||
|  | 			(volatile struct alt_sgdma_descriptor *)&rx_desc[0], | ||||||
|  | 			(volatile struct alt_sgdma_descriptor *)&rx_desc[1], | ||||||
|  | 			(unsigned int)0x0,	/* read addr */ | ||||||
|  | 			(unsigned int *)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 */ | ||||||
|  | 		    ); | ||||||
|  | 
 | ||||||
|  | 		/* setup the sgdma */ | ||||||
|  | 		alt_sgdma_do_async_transfer(priv->sgdma_rx, &rx_desc[0]); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void tse_eth_halt(struct eth_device *dev) | ||||||
|  | { | ||||||
|  | 	/* don't do anything! */ | ||||||
|  | 	/* this gets called after each uboot  */ | ||||||
|  | 	/* network command.  don't need to reset the thing all of the time */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void tse_eth_reset(struct eth_device *dev) | ||||||
|  | { | ||||||
|  | 	/* stop sgdmas, disable tse receive */ | ||||||
|  | 	struct altera_tse_priv *priv = dev->priv; | ||||||
|  | 	volatile struct alt_tse_mac *mac_dev = priv->mac_dev; | ||||||
|  | 	volatile struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx; | ||||||
|  | 	volatile struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx; | ||||||
|  | 	int counter; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *rx_desc = | ||||||
|  | 	    (volatile struct alt_sgdma_descriptor *)&priv->rx_desc[0]; | ||||||
|  | 
 | ||||||
|  | 	/* clear rx desc & wait for sgdma to complete */ | ||||||
|  | 	rx_desc->descriptor_control = 0; | ||||||
|  | 	rx_sgdma->control = 0; | ||||||
|  | 	counter = 0; | ||||||
|  | 	while (rx_sgdma->status & ALT_SGDMA_STATUS_BUSY_MSK) { | ||||||
|  | 		if (counter++ > ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (counter >= ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) { | ||||||
|  | 		debug("Timeout waiting for rx sgdma!\n"); | ||||||
|  | 		rx_sgdma->control &= ALT_SGDMA_CONTROL_SOFTWARERESET_MSK; | ||||||
|  | 		rx_sgdma->control &= ALT_SGDMA_CONTROL_SOFTWARERESET_MSK; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	counter = 0; | ||||||
|  | 	tx_sgdma->control = 0; | ||||||
|  | 	while (tx_sgdma->status & ALT_SGDMA_STATUS_BUSY_MSK) { | ||||||
|  | 		if (counter++ > ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (counter >= ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR) { | ||||||
|  | 		debug("Timeout waiting for tx sgdma!\n"); | ||||||
|  | 		tx_sgdma->control &= ALT_SGDMA_CONTROL_SOFTWARERESET_MSK; | ||||||
|  | 		tx_sgdma->control &= ALT_SGDMA_CONTROL_SOFTWARERESET_MSK; | ||||||
|  | 	} | ||||||
|  | 	/* reset the mac */ | ||||||
|  | 	mac_dev->command_config.bits.transmit_enable = 1; | ||||||
|  | 	mac_dev->command_config.bits.receive_enable = 1; | ||||||
|  | 	mac_dev->command_config.bits.software_reset = 1; | ||||||
|  | 
 | ||||||
|  | 	counter = 0; | ||||||
|  | 	while (mac_dev->command_config.bits.software_reset) { | ||||||
|  | 		if (counter++ > ALT_TSE_SW_RESET_WATCHDOG_CNTR) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (counter >= ALT_TSE_SW_RESET_WATCHDOG_CNTR) | ||||||
|  | 		debug("TSEMAC SW reset bit never cleared!\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tse_mdio_read(struct altera_tse_priv *priv, unsigned int regnum) | ||||||
|  | { | ||||||
|  | 	volatile struct alt_tse_mac *mac_dev; | ||||||
|  | 	unsigned int *mdio_regs; | ||||||
|  | 	unsigned int data; | ||||||
|  | 	u16 value; | ||||||
|  | 
 | ||||||
|  | 	mac_dev = priv->mac_dev; | ||||||
|  | 
 | ||||||
|  | 	/* set mdio address */ | ||||||
|  | 	mac_dev->mdio_phy1_addr = priv->phyaddr; | ||||||
|  | 	mdio_regs = (unsigned int *)&mac_dev->mdio_phy1; | ||||||
|  | 
 | ||||||
|  | 	/* get the data */ | ||||||
|  | 	data = mdio_regs[regnum]; | ||||||
|  | 
 | ||||||
|  | 	value = data & 0xffff; | ||||||
|  | 
 | ||||||
|  | 	return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tse_mdio_write(struct altera_tse_priv *priv, unsigned int regnum, | ||||||
|  | 		   unsigned int value) | ||||||
|  | { | ||||||
|  | 	volatile struct alt_tse_mac *mac_dev; | ||||||
|  | 	unsigned int *mdio_regs; | ||||||
|  | 	unsigned int data; | ||||||
|  | 
 | ||||||
|  | 	mac_dev = priv->mac_dev; | ||||||
|  | 
 | ||||||
|  | 	/* set mdio address */ | ||||||
|  | 	mac_dev->mdio_phy1_addr = priv->phyaddr; | ||||||
|  | 	mdio_regs = (unsigned int *)&mac_dev->mdio_phy1; | ||||||
|  | 
 | ||||||
|  | 	/* get the data */ | ||||||
|  | 	data = (unsigned int)value; | ||||||
|  | 
 | ||||||
|  | 	mdio_regs[regnum] = data; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* MDIO access to phy */ | ||||||
|  | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) && !defined(BITBANGMII) | ||||||
|  | static int altera_tse_miiphy_write(char *devname, unsigned char addr, | ||||||
|  | 				   unsigned char reg, unsigned short value) | ||||||
|  | { | ||||||
|  | 	struct eth_device *dev; | ||||||
|  | 	struct altera_tse_priv *priv; | ||||||
|  | 	dev = eth_get_dev_by_name(devname); | ||||||
|  | 	priv = dev->priv; | ||||||
|  | 
 | ||||||
|  | 	tse_mdio_write(priv, (uint) reg, (uint) value); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int altera_tse_miiphy_read(char *devname, unsigned char addr, | ||||||
|  | 				  unsigned char reg, unsigned short *value) | ||||||
|  | { | ||||||
|  | 	struct eth_device *dev; | ||||||
|  | 	struct altera_tse_priv *priv; | ||||||
|  | 	volatile struct alt_tse_mac *mac_dev; | ||||||
|  | 	unsigned int *mdio_regs; | ||||||
|  | 
 | ||||||
|  | 	dev = eth_get_dev_by_name(devname); | ||||||
|  | 	priv = dev->priv; | ||||||
|  | 
 | ||||||
|  | 	mac_dev = priv->mac_dev; | ||||||
|  | 	mac_dev->mdio_phy1_addr = (int)addr; | ||||||
|  | 	mdio_regs = (unsigned int *)&mac_dev->mdio_phy1; | ||||||
|  | 
 | ||||||
|  | 	*value = 0xffff & mdio_regs[reg]; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Also copied from tsec.c | ||||||
|  |  */ | ||||||
|  | /* Parse the status register for link, and then do
 | ||||||
|  |  * auto-negotiation | ||||||
|  |  */ | ||||||
|  | static uint mii_parse_sr(uint mii_reg, struct altera_tse_priv *priv) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * Wait if the link is up, and autonegotiation is in progress | ||||||
|  | 	 * (ie - we're capable and it's not done) | ||||||
|  | 	 */ | ||||||
|  | 	mii_reg = tse_mdio_read(priv, MIIM_STATUS); | ||||||
|  | 
 | ||||||
|  | 	if (!(mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE) | ||||||
|  | 	    && !(mii_reg & PHY_BMSR_AUTN_COMP)) { | ||||||
|  | 		int i = 0; | ||||||
|  | 
 | ||||||
|  | 		puts("Waiting for PHY auto negotiation to complete"); | ||||||
|  | 		while (!(mii_reg & PHY_BMSR_AUTN_COMP)) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * Timeout reached ? | ||||||
|  | 			 */ | ||||||
|  | 			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { | ||||||
|  | 				puts(" TIMEOUT !\n"); | ||||||
|  | 				priv->link = 0; | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if ((i++ % 1000) == 0) | ||||||
|  | 				putc('.'); | ||||||
|  | 			udelay(1000);	/* 1 ms */ | ||||||
|  | 			mii_reg = tse_mdio_read(priv, MIIM_STATUS); | ||||||
|  | 		} | ||||||
|  | 		puts(" done\n"); | ||||||
|  | 		priv->link = 1; | ||||||
|  | 		udelay(500000);	/* another 500 ms (results in faster booting) */ | ||||||
|  | 	} else { | ||||||
|  | 		if (mii_reg & MIIM_STATUS_LINK) { | ||||||
|  | 			debug("Link is up\n"); | ||||||
|  | 			priv->link = 1; | ||||||
|  | 		} else { | ||||||
|  | 			debug("Link is down\n"); | ||||||
|  | 			priv->link = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Parse the 88E1011's status register for speed and duplex
 | ||||||
|  |  * information | ||||||
|  |  */ | ||||||
|  | static uint mii_parse_88E1011_psr(uint mii_reg, struct altera_tse_priv *priv) | ||||||
|  | { | ||||||
|  | 	uint speed; | ||||||
|  | 
 | ||||||
|  | 	mii_reg = tse_mdio_read(priv, MIIM_88E1011_PHY_STATUS); | ||||||
|  | 
 | ||||||
|  | 	if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) && | ||||||
|  | 	    !(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { | ||||||
|  | 		int i = 0; | ||||||
|  | 
 | ||||||
|  | 		puts("Waiting for PHY realtime link"); | ||||||
|  | 		while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { | ||||||
|  | 			/* Timeout reached ? */ | ||||||
|  | 			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { | ||||||
|  | 				puts(" TIMEOUT !\n"); | ||||||
|  | 				priv->link = 0; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if ((i++ == 1000) == 0) { | ||||||
|  | 				i = 0; | ||||||
|  | 				puts("."); | ||||||
|  | 			} | ||||||
|  | 			udelay(1000);	/* 1 ms */ | ||||||
|  | 			mii_reg = tse_mdio_read(priv, MIIM_88E1011_PHY_STATUS); | ||||||
|  | 		} | ||||||
|  | 		puts(" done\n"); | ||||||
|  | 		udelay(500000);	/* another 500 ms (results in faster booting) */ | ||||||
|  | 	} else { | ||||||
|  | 		if (mii_reg & MIIM_88E1011_PHYSTAT_LINK) | ||||||
|  | 			priv->link = 1; | ||||||
|  | 		else | ||||||
|  | 			priv->link = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX) | ||||||
|  | 		priv->duplexity = 1; | ||||||
|  | 	else | ||||||
|  | 		priv->duplexity = 0; | ||||||
|  | 
 | ||||||
|  | 	speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED); | ||||||
|  | 
 | ||||||
|  | 	switch (speed) { | ||||||
|  | 	case MIIM_88E1011_PHYSTAT_GBIT: | ||||||
|  | 		priv->speed = 1000; | ||||||
|  | 		debug("PHY Speed is 1000Mbit\n"); | ||||||
|  | 		break; | ||||||
|  | 	case MIIM_88E1011_PHYSTAT_100: | ||||||
|  | 		debug("PHY Speed is 100Mbit\n"); | ||||||
|  | 		priv->speed = 100; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		debug("PHY Speed is 10Mbit\n"); | ||||||
|  | 		priv->speed = 10; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint mii_m88e1111s_setmode_sr(uint mii_reg, struct altera_tse_priv *priv) | ||||||
|  | { | ||||||
|  | 	uint mii_data = tse_mdio_read(priv, mii_reg); | ||||||
|  | 	mii_data &= 0xfff0; | ||||||
|  | 	mii_data |= 0xb; | ||||||
|  | 	return mii_data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint mii_m88e1111s_setmode_cr(uint mii_reg, struct altera_tse_priv *priv) | ||||||
|  | { | ||||||
|  | 	uint mii_data = tse_mdio_read(priv, mii_reg); | ||||||
|  | 	mii_data &= ~0x82; | ||||||
|  | 	mii_data |= 0x82; | ||||||
|  | 	return mii_data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Returns which value to write to the control register. | ||||||
|  |  * For 10/100, the value is slightly different | ||||||
|  |  */ | ||||||
|  | static uint mii_cr_init(uint mii_reg, struct altera_tse_priv *priv) | ||||||
|  | { | ||||||
|  | 	return MIIM_CONTROL_INIT; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * PHY & MDIO code | ||||||
|  |  * Need to add SGMII stuff | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static struct phy_info phy_info_M88E1111S = { | ||||||
|  | 	0x01410cc, | ||||||
|  | 	"Marvell 88E1111S", | ||||||
|  | 	4, | ||||||
|  | 	(struct phy_cmd[]){	/* config */ | ||||||
|  | 			   /* Reset and configure the PHY */ | ||||||
|  | 			   {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, | ||||||
|  | 			   {MIIM_88E1111_PHY_EXT_SR, 0x848f, | ||||||
|  | 			    &mii_m88e1111s_setmode_sr}, | ||||||
|  | 			   /* Delay RGMII TX and RX */ | ||||||
|  | 			   {MIIM_88E1111_PHY_EXT_CR, 0x0cd2, | ||||||
|  | 			    &mii_m88e1111s_setmode_cr}, | ||||||
|  | 			   {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, | ||||||
|  | 			   {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, | ||||||
|  | 			   {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, | ||||||
|  | 			   {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, | ||||||
|  | 			   {miim_end,} | ||||||
|  | 			   }, | ||||||
|  | 	(struct phy_cmd[]){	/* startup */ | ||||||
|  | 			   /* Status is read once to clear old link state */ | ||||||
|  | 			   {MIIM_STATUS, miim_read, NULL}, | ||||||
|  | 			   /* Auto-negotiate */ | ||||||
|  | 			   {MIIM_STATUS, miim_read, &mii_parse_sr}, | ||||||
|  | 			   /* Read the status */ | ||||||
|  | 			   {MIIM_88E1011_PHY_STATUS, miim_read, | ||||||
|  | 			    &mii_parse_88E1011_psr}, | ||||||
|  | 			   {miim_end,} | ||||||
|  | 			   }, | ||||||
|  | 	(struct phy_cmd[]){	/* shutdown */ | ||||||
|  | 			   {miim_end,} | ||||||
|  | 			   }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* a generic flavor.  */ | ||||||
|  | static struct phy_info phy_info_generic = { | ||||||
|  | 	0, | ||||||
|  | 	"Unknown/Generic PHY", | ||||||
|  | 	32, | ||||||
|  | 	(struct phy_cmd[]){	/* config */ | ||||||
|  | 			   {PHY_BMCR, PHY_BMCR_RESET, NULL}, | ||||||
|  | 			   {PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG, NULL}, | ||||||
|  | 			   {miim_end,} | ||||||
|  | 			   }, | ||||||
|  | 	(struct phy_cmd[]){	/* startup */ | ||||||
|  | 			   {PHY_BMSR, miim_read, NULL}, | ||||||
|  | 			   {PHY_BMSR, miim_read, &mii_parse_sr}, | ||||||
|  | 			   {miim_end,} | ||||||
|  | 			   }, | ||||||
|  | 	(struct phy_cmd[]){	/* shutdown */ | ||||||
|  | 			   {miim_end,} | ||||||
|  | 			   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct phy_info *phy_info[] = { | ||||||
|  | 	&phy_info_M88E1111S, | ||||||
|  | 	NULL | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  |  /* Grab the identifier of the device's PHY, and search through
 | ||||||
|  |   * all of the known PHYs to see if one matches.	 If so, return | ||||||
|  |   * it, if not, return NULL | ||||||
|  |   */ | ||||||
|  | static struct phy_info *get_phy_info(struct eth_device *dev) | ||||||
|  | { | ||||||
|  | 	struct altera_tse_priv *priv = (struct altera_tse_priv *)dev->priv; | ||||||
|  | 	uint phy_reg, phy_ID; | ||||||
|  | 	int i; | ||||||
|  | 	struct phy_info *theInfo = NULL; | ||||||
|  | 
 | ||||||
|  | 	/* Grab the bits from PHYIR1, and put them in the upper half */ | ||||||
|  | 	phy_reg = tse_mdio_read(priv, MIIM_PHYIR1); | ||||||
|  | 	phy_ID = (phy_reg & 0xffff) << 16; | ||||||
|  | 
 | ||||||
|  | 	/* Grab the bits from PHYIR2, and put them in the lower half */ | ||||||
|  | 	phy_reg = tse_mdio_read(priv, MIIM_PHYIR2); | ||||||
|  | 	phy_ID |= (phy_reg & 0xffff); | ||||||
|  | 
 | ||||||
|  | 	/* loop through all the known PHY types, and find one that */ | ||||||
|  | 	/* matches the ID we read from the PHY. */ | ||||||
|  | 	for (i = 0; phy_info[i]; i++) { | ||||||
|  | 		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) { | ||||||
|  | 			theInfo = phy_info[i]; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (theInfo == NULL) { | ||||||
|  | 		theInfo = &phy_info_generic; | ||||||
|  | 		debug("%s: No support for PHY id %x; assuming generic\n", | ||||||
|  | 		      dev->name, phy_ID); | ||||||
|  | 	} else | ||||||
|  | 		debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID); | ||||||
|  | 
 | ||||||
|  | 	return theInfo; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Execute the given series of commands on the given device's
 | ||||||
|  |  * PHY, running functions as necessary | ||||||
|  |  */ | ||||||
|  | static void phy_run_commands(struct altera_tse_priv *priv, struct phy_cmd *cmd) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	uint result; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; cmd->mii_reg != miim_end; i++) { | ||||||
|  | 		if (cmd->mii_data == miim_read) { | ||||||
|  | 			result = tse_mdio_read(priv, cmd->mii_reg); | ||||||
|  | 
 | ||||||
|  | 			if (cmd->funct != NULL) | ||||||
|  | 				(*(cmd->funct)) (result, priv); | ||||||
|  | 
 | ||||||
|  | 		} else { | ||||||
|  | 			if (cmd->funct != NULL) | ||||||
|  | 				result = (*(cmd->funct)) (cmd->mii_reg, priv); | ||||||
|  | 			else | ||||||
|  | 				result = cmd->mii_data; | ||||||
|  | 
 | ||||||
|  | 			tse_mdio_write(priv, cmd->mii_reg, result); | ||||||
|  | 
 | ||||||
|  | 		} | ||||||
|  | 		cmd++; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Phy init code */ | ||||||
|  | static int init_phy(struct eth_device *dev) | ||||||
|  | { | ||||||
|  | 	struct altera_tse_priv *priv = (struct altera_tse_priv *)dev->priv; | ||||||
|  | 	struct phy_info *curphy; | ||||||
|  | 
 | ||||||
|  | 	/* Get the cmd structure corresponding to the attached
 | ||||||
|  | 	 * PHY */ | ||||||
|  | 	curphy = get_phy_info(dev); | ||||||
|  | 
 | ||||||
|  | 	if (curphy == NULL) { | ||||||
|  | 		priv->phyinfo = NULL; | ||||||
|  | 		debug("%s: No PHY found\n", dev->name); | ||||||
|  | 
 | ||||||
|  | 		return 0; | ||||||
|  | 	} else | ||||||
|  | 		debug("%s found\n", curphy->name); | ||||||
|  | 	priv->phyinfo = curphy; | ||||||
|  | 
 | ||||||
|  | 	phy_run_commands(priv, priv->phyinfo->config); | ||||||
|  | 
 | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tse_eth_init(struct eth_device *dev, bd_t * bd) | ||||||
|  | { | ||||||
|  | 	int dat; | ||||||
|  | 	struct altera_tse_priv *priv = dev->priv; | ||||||
|  | 	volatile struct alt_tse_mac *mac_dev = priv->mac_dev; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *tx_desc = priv->tx_desc; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *rx_desc = priv->rx_desc; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *rx_desc_cur = | ||||||
|  | 	    (volatile struct alt_sgdma_descriptor *)&rx_desc[0]; | ||||||
|  | 
 | ||||||
|  | 	/* stop controller */ | ||||||
|  | 	debug("Reseting TSE & SGDMAs\n"); | ||||||
|  | 	tse_eth_reset(dev); | ||||||
|  | 
 | ||||||
|  | 	/* start the phy */ | ||||||
|  | 	debug("Configuring PHY\n"); | ||||||
|  | 	phy_run_commands(priv, priv->phyinfo->startup); | ||||||
|  | 
 | ||||||
|  | 	/* need to create sgdma */ | ||||||
|  | 	debug("Configuring tx desc\n"); | ||||||
|  | 	alt_sgdma_construct_descriptor_burst( | ||||||
|  | 		(volatile struct alt_sgdma_descriptor *)&tx_desc[0], | ||||||
|  | 		(volatile struct alt_sgdma_descriptor *)&tx_desc[1], | ||||||
|  | 		(unsigned int *)NULL,	/* read addr */ | ||||||
|  | 		(unsigned int *)0, | ||||||
|  | 		0,	/* 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 */ | ||||||
|  | 		); | ||||||
|  | 	debug("Configuring rx desc\n"); | ||||||
|  | 	flush_dcache((unsigned long)(NetRxPackets[0]), PKTSIZE_ALIGN); | ||||||
|  | 	alt_sgdma_construct_descriptor_burst( | ||||||
|  | 		(volatile struct alt_sgdma_descriptor *)&rx_desc[0], | ||||||
|  | 		(volatile struct alt_sgdma_descriptor *)&rx_desc[1], | ||||||
|  | 		(unsigned int)0x0,	/* read addr */ | ||||||
|  | 		(unsigned int *)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 */ | ||||||
|  | 		); | ||||||
|  | 	/* start rx async transfer */ | ||||||
|  | 	debug("Starting rx sgdma\n"); | ||||||
|  | 	alt_sgdma_do_async_transfer(priv->sgdma_rx, rx_desc_cur); | ||||||
|  | 
 | ||||||
|  | 	/* start TSE */ | ||||||
|  | 	debug("Configuring TSE Mac\n"); | ||||||
|  | 	/* Initialize MAC registers */ | ||||||
|  | 	mac_dev->max_frame_length = PKTSIZE_ALIGN; | ||||||
|  | 	mac_dev->rx_almost_empty_threshold = 8; | ||||||
|  | 	mac_dev->rx_almost_full_threshold = 8; | ||||||
|  | 	mac_dev->tx_almost_empty_threshold = 8; | ||||||
|  | 	mac_dev->tx_almost_full_threshold = 3; | ||||||
|  | 	mac_dev->tx_sel_empty_threshold = | ||||||
|  | 	    CONFIG_SYS_ALTERA_TSE_TX_FIFO - 16; | ||||||
|  | 	mac_dev->tx_sel_full_threshold = 0; | ||||||
|  | 	mac_dev->rx_sel_empty_threshold = | ||||||
|  | 	    CONFIG_SYS_ALTERA_TSE_TX_FIFO - 16; | ||||||
|  | 	mac_dev->rx_sel_full_threshold = 0; | ||||||
|  | 
 | ||||||
|  | 	/* NO Shift */ | ||||||
|  | 	mac_dev->rx_cmd_stat.bits.rx_shift16 = 0; | ||||||
|  | 	mac_dev->tx_cmd_stat.bits.tx_shift16 = 0; | ||||||
|  | 
 | ||||||
|  | 	/* enable MAC */ | ||||||
|  | 	dat = 0; | ||||||
|  | 	dat = ALTERA_TSE_CMD_TX_ENA_MSK | ALTERA_TSE_CMD_RX_ENA_MSK; | ||||||
|  | 
 | ||||||
|  | 	mac_dev->command_config.image = dat; | ||||||
|  | 
 | ||||||
|  | 	/* Set the MAC address */ | ||||||
|  | 	debug("Setting MAC address to 0x%x%x%x%x%x%x\n", | ||||||
|  | 	      dev->enetaddr[5], dev->enetaddr[4], | ||||||
|  | 	      dev->enetaddr[3], dev->enetaddr[2], | ||||||
|  | 	      dev->enetaddr[1], dev->enetaddr[0]); | ||||||
|  | 	mac_dev->mac_addr_0 = ((dev->enetaddr[3]) << 24 | | ||||||
|  | 			       (dev->enetaddr[2]) << 16 | | ||||||
|  | 			       (dev->enetaddr[1]) << 8 | (dev->enetaddr[0])); | ||||||
|  | 
 | ||||||
|  | 	mac_dev->mac_addr_1 = ((dev->enetaddr[5] << 8 | | ||||||
|  | 				(dev->enetaddr[4])) & 0xFFFF); | ||||||
|  | 
 | ||||||
|  | 	/* Set the MAC address */ | ||||||
|  | 	mac_dev->supp_mac_addr_0_0 = mac_dev->mac_addr_0; | ||||||
|  | 	mac_dev->supp_mac_addr_0_1 = mac_dev->mac_addr_1; | ||||||
|  | 
 | ||||||
|  | 	/* Set the MAC address */ | ||||||
|  | 	mac_dev->supp_mac_addr_1_0 = mac_dev->mac_addr_0; | ||||||
|  | 	mac_dev->supp_mac_addr_1_1 = mac_dev->mac_addr_1; | ||||||
|  | 
 | ||||||
|  | 	/* Set the MAC address */ | ||||||
|  | 	mac_dev->supp_mac_addr_2_0 = mac_dev->mac_addr_0; | ||||||
|  | 	mac_dev->supp_mac_addr_2_1 = mac_dev->mac_addr_1; | ||||||
|  | 
 | ||||||
|  | 	/* Set the MAC address */ | ||||||
|  | 	mac_dev->supp_mac_addr_3_0 = mac_dev->mac_addr_0; | ||||||
|  | 	mac_dev->supp_mac_addr_3_1 = mac_dev->mac_addr_1; | ||||||
|  | 
 | ||||||
|  | 	/* configure the TSE core  */ | ||||||
|  | 	/*  -- output clocks,  */ | ||||||
|  | 	/*  -- and later config stuff for SGMII */ | ||||||
|  | 	if (priv->link) { | ||||||
|  | 		debug("Adjusting TSE to link speed\n"); | ||||||
|  | 		tse_adjust_link(priv); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return priv->link ? 0 : -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* TSE init code */ | ||||||
|  | int altera_tse_initialize(u8 dev_num, int mac_base, | ||||||
|  | 			  int sgdma_rx_base, int sgdma_tx_base) | ||||||
|  | { | ||||||
|  | 	struct altera_tse_priv *priv; | ||||||
|  | 	struct eth_device *dev; | ||||||
|  | 	struct alt_sgdma_descriptor *rx_desc; | ||||||
|  | 	struct alt_sgdma_descriptor *tx_desc; | ||||||
|  | 	unsigned long dma_handle; | ||||||
|  | 
 | ||||||
|  | 	dev = (struct eth_device *)malloc(sizeof *dev); | ||||||
|  | 
 | ||||||
|  | 	if (NULL == dev) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	memset(dev, 0, sizeof *dev); | ||||||
|  | 
 | ||||||
|  | 	priv = malloc(sizeof(*priv)); | ||||||
|  | 
 | ||||||
|  | 	if (!priv) { | ||||||
|  | 		free(dev); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	tx_desc = dma_alloc_coherent(sizeof(*tx_desc) * (3 + PKTBUFSRX), | ||||||
|  | 				     &dma_handle); | ||||||
|  | 	rx_desc = tx_desc + 2; | ||||||
|  | 	debug("tx desc: address = 0x%x\n", (unsigned int)tx_desc); | ||||||
|  | 	debug("rx desc: address = 0x%x\n", (unsigned int)rx_desc); | ||||||
|  | 
 | ||||||
|  | 	if (!tx_desc) { | ||||||
|  | 		free(priv); | ||||||
|  | 		free(dev); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	memset(rx_desc, 0, (sizeof *rx_desc) * (PKTBUFSRX + 1)); | ||||||
|  | 	memset(tx_desc, 0, (sizeof *tx_desc) * 2); | ||||||
|  | 
 | ||||||
|  | 	/* initialize tse priv */ | ||||||
|  | 	priv->mac_dev = (volatile struct alt_tse_mac *)mac_base; | ||||||
|  | 	priv->sgdma_rx = (volatile struct alt_sgdma_registers *)sgdma_rx_base; | ||||||
|  | 	priv->sgdma_tx = (volatile struct alt_sgdma_registers *)sgdma_tx_base; | ||||||
|  | 	priv->phyaddr = CONFIG_SYS_ALTERA_TSE_PHY_ADDR; | ||||||
|  | 	priv->flags = CONFIG_SYS_ALTERA_TSE_FLAGS; | ||||||
|  | 	priv->rx_desc = rx_desc; | ||||||
|  | 	priv->tx_desc = tx_desc; | ||||||
|  | 
 | ||||||
|  | 	/* init eth structure */ | ||||||
|  | 	dev->priv = priv; | ||||||
|  | 	dev->init = tse_eth_init; | ||||||
|  | 	dev->halt = tse_eth_halt; | ||||||
|  | 	dev->send = tse_eth_send; | ||||||
|  | 	dev->recv = tse_eth_rx; | ||||||
|  | 	sprintf(dev->name, "%s-%hu", "ALTERA_TSE", dev_num); | ||||||
|  | 
 | ||||||
|  | 	eth_register(dev); | ||||||
|  | 
 | ||||||
|  | #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) && !defined(BITBANGMII) | ||||||
|  | 	miiphy_register(dev->name, altera_tse_miiphy_read, | ||||||
|  | 			altera_tse_miiphy_write); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	init_phy(dev); | ||||||
|  | 
 | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,494 @@ | ||||||
|  | /*
 | ||||||
|  |  * Altera 10/100/1000 triple speed ethernet mac | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2008 Altera Corporation. | ||||||
|  |  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef _ALTERA_TSE_H_ | ||||||
|  | #define _ALTERA_TSE_H_ | ||||||
|  | 
 | ||||||
|  | #define __packed_1_    __attribute__ ((packed, aligned(1))) | ||||||
|  | 
 | ||||||
|  | /* PHY Stuff */ | ||||||
|  | #define miim_end -2 | ||||||
|  | #define miim_read -1 | ||||||
|  | 
 | ||||||
|  | #define PHY_AUTONEGOTIATE_TIMEOUT	5000	/* in ms */ | ||||||
|  | 
 | ||||||
|  | #ifndef CONFIG_SYS_TBIPA_VALUE | ||||||
|  | #define CONFIG_SYS_TBIPA_VALUE	0x1f | ||||||
|  | #endif | ||||||
|  | #define MIIMCFG_INIT_VALUE	0x00000003 | ||||||
|  | #define MIIMCFG_RESET		0x80000000 | ||||||
|  | 
 | ||||||
|  | #define MIIMIND_BUSY		0x00000001 | ||||||
|  | #define MIIMIND_NOTVALID	0x00000004 | ||||||
|  | 
 | ||||||
|  | #define MIIM_CONTROL		0x00 | ||||||
|  | #define MIIM_CONTROL_RESET	0x00009140 | ||||||
|  | #define MIIM_CONTROL_INIT	0x00001140 | ||||||
|  | #define MIIM_CONTROL_RESTART	0x00001340 | ||||||
|  | #define MIIM_ANEN		0x00001000 | ||||||
|  | 
 | ||||||
|  | #define MIIM_CR		0x00 | ||||||
|  | #define MIIM_CR_RST		0x00008000 | ||||||
|  | #define MIIM_CR_INIT		0x00001000 | ||||||
|  | 
 | ||||||
|  | #define MIIM_STATUS		0x1 | ||||||
|  | #define MIIM_STATUS_AN_DONE	0x00000020 | ||||||
|  | #define MIIM_STATUS_LINK	0x0004 | ||||||
|  | #define PHY_BMSR_AUTN_ABLE	0x0008 | ||||||
|  | #define PHY_BMSR_AUTN_COMP	0x0020 | ||||||
|  | 
 | ||||||
|  | #define MIIM_PHYIR1		0x2 | ||||||
|  | #define MIIM_PHYIR2		0x3 | ||||||
|  | 
 | ||||||
|  | #define MIIM_ANAR		0x4 | ||||||
|  | #define MIIM_ANAR_INIT		0x1e1 | ||||||
|  | 
 | ||||||
|  | #define MIIM_TBI_ANLPBPA	0x5 | ||||||
|  | #define MIIM_TBI_ANLPBPA_HALF	0x00000040 | ||||||
|  | #define MIIM_TBI_ANLPBPA_FULL	0x00000020 | ||||||
|  | 
 | ||||||
|  | #define MIIM_TBI_ANEX		0x6 | ||||||
|  | #define MIIM_TBI_ANEX_NP	0x00000004 | ||||||
|  | #define MIIM_TBI_ANEX_PRX	0x00000002 | ||||||
|  | 
 | ||||||
|  | #define MIIM_GBIT_CONTROL	0x9 | ||||||
|  | #define MIIM_GBIT_CONTROL_INIT	0xe00 | ||||||
|  | 
 | ||||||
|  | #define MIIM_EXT_PAGE_ACCESS	0x1f | ||||||
|  | 
 | ||||||
|  | /* 88E1011 PHY Status Register */ | ||||||
|  | #define MIIM_88E1011_PHY_STATUS	0x11 | ||||||
|  | #define MIIM_88E1011_PHYSTAT_SPEED	0xc000 | ||||||
|  | #define MIIM_88E1011_PHYSTAT_GBIT	0x8000 | ||||||
|  | #define MIIM_88E1011_PHYSTAT_100	0x4000 | ||||||
|  | #define MIIM_88E1011_PHYSTAT_DUPLEX	0x2000 | ||||||
|  | #define MIIM_88E1011_PHYSTAT_SPDDONE	0x0800 | ||||||
|  | #define MIIM_88E1011_PHYSTAT_LINK	0x0400 | ||||||
|  | 
 | ||||||
|  | #define MIIM_88E1011_PHY_SCR		0x10 | ||||||
|  | #define MIIM_88E1011_PHY_MDI_X_AUTO	0x0060 | ||||||
|  | 
 | ||||||
|  | #define MIIM_88E1111_PHY_EXT_CR	0x14 | ||||||
|  | #define MIIM_88E1111_PHY_EXT_SR	0x1b | ||||||
|  | 
 | ||||||
|  | /* 88E1111 PHY LED Control Register */ | ||||||
|  | #define MIIM_88E1111_PHY_LED_CONTROL	24 | ||||||
|  | #define MIIM_88E1111_PHY_LED_DIRECT	0x4100 | ||||||
|  | #define MIIM_88E1111_PHY_LED_COMBINE	0x411C | ||||||
|  | 
 | ||||||
|  | #define MIIM_READ_COMMAND	0x00000001 | ||||||
|  | 
 | ||||||
|  | /* struct phy_info: a structure which defines attributes for a PHY
 | ||||||
|  |  * id will contain a number which represents the PHY.  During | ||||||
|  |  * startup, the driver will poll the PHY to find out what its | ||||||
|  |  * UID--as defined by registers 2 and 3--is.  The 32-bit result | ||||||
|  |  * gotten from the PHY will be shifted right by "shift" bits to | ||||||
|  |  * discard any bits which may change based on revision numbers | ||||||
|  |  * unimportant to functionality | ||||||
|  |  * | ||||||
|  |  * The struct phy_cmd entries represent pointers to an arrays of | ||||||
|  |  * commands which tell the driver what to do to the PHY. | ||||||
|  |  */ | ||||||
|  | struct phy_info { | ||||||
|  | 	uint id; | ||||||
|  | 	char *name; | ||||||
|  | 	uint shift; | ||||||
|  | 	/* Called to configure the PHY, and modify the controller
 | ||||||
|  | 	 * based on the results */ | ||||||
|  | 	struct phy_cmd *config; | ||||||
|  | 
 | ||||||
|  | 	/* Called when starting up the controller */ | ||||||
|  | 	struct phy_cmd *startup; | ||||||
|  | 
 | ||||||
|  | 	/* Called when bringing down the controller */ | ||||||
|  | 	struct phy_cmd *shutdown; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SGDMA Stuff */ | ||||||
|  | #define ALT_SGDMA_STATUS_ERROR_MSK			(0x00000001) | ||||||
|  | #define ALT_SGDMA_STATUS_EOP_ENCOUNTERED_MSK		(0x00000002) | ||||||
|  | #define ALT_SGDMA_STATUS_DESC_COMPLETED_MSK		(0x00000004) | ||||||
|  | #define ALT_SGDMA_STATUS_CHAIN_COMPLETED_MSK		(0x00000008) | ||||||
|  | #define ALT_SGDMA_STATUS_BUSY_MSK			(0x00000010) | ||||||
|  | 
 | ||||||
|  | #define ALT_SGDMA_CONTROL_IE_ERROR_MSK			(0x00000001) | ||||||
|  | #define ALT_SGDMA_CONTROL_IE_EOP_ENCOUNTERED_MSK	(0x00000002) | ||||||
|  | #define ALT_SGDMA_CONTROL_IE_DESC_COMPLETED_MSK	(0x00000004) | ||||||
|  | #define ALT_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK	(0x00000008) | ||||||
|  | #define ALT_SGDMA_CONTROL_IE_GLOBAL_MSK		(0x00000010) | ||||||
|  | #define ALT_SGDMA_CONTROL_RUN_MSK			(0x00000020) | ||||||
|  | #define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK		(0x00000040) | ||||||
|  | #define ALT_SGDMA_CONTROL_IE_MAX_DESC_PROCESSED_MSK	(0x00000080) | ||||||
|  | #define ALT_SGDMA_CONTROL_MAX_DESC_PROCESSED_MSK	(0x0000FF00) | ||||||
|  | #define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK		(0x00010000) | ||||||
|  | #define ALT_SGDMA_CONTROL_PARK_MSK			(0x00020000) | ||||||
|  | #define ALT_SGDMA_CONTROL_CLEAR_INTERRUPT_MSK		(0x80000000) | ||||||
|  | 
 | ||||||
|  | #define ALTERA_TSE_SGDMA_INTR_MASK  (ALT_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK \ | ||||||
|  | 			| ALT_SGDMA_STATUS_DESC_COMPLETED_MSK \ | ||||||
|  | 			| ALT_SGDMA_CONTROL_IE_GLOBAL_MSK) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Descriptor control bit masks & offsets | ||||||
|  |  * | ||||||
|  |  * Note: The control byte physically occupies bits [31:24] in memory. | ||||||
|  |  *	 The following bit-offsets are expressed relative to the LSB of | ||||||
|  |  *	 the control register bitfield. | ||||||
|  |  */ | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK		(0x00000001) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK	(0x00000002) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK	(0x00000004) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_CONTROL_ATLANTIC_CHANNEL_MSK	(0x00000008) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK		(0x00000080) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Descriptor status bit masks & offsets | ||||||
|  |  * | ||||||
|  |  * Note: The status byte physically occupies bits [23:16] in memory. | ||||||
|  |  *	 The following bit-offsets are expressed relative to the LSB of | ||||||
|  |  *	 the status register bitfield. | ||||||
|  |  */ | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_CRC_MSK			(0x00000001) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_PARITY_MSK		(0x00000002) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_OVERFLOW_MSK		(0x00000004) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_SYNC_MSK			(0x00000008) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_UEOP_MSK			(0x00000010) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_MEOP_MSK			(0x00000020) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_E_MSOP_MSK			(0x00000040) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK	(0x00000080) | ||||||
|  | #define ALT_SGDMA_DESCRIPTOR_STATUS_ERROR_MSK			(0x0000007F) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * The SGDMA controller buffer descriptor allocates | ||||||
|  |  * 64 bits for each address. To support ANSI C, the | ||||||
|  |  * struct implementing a descriptor places 32-bits | ||||||
|  |  * of padding directly above each address; each pad must | ||||||
|  |  * be cleared when initializing a descriptor. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Buffer Descriptor data structure | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | struct alt_sgdma_descriptor { | ||||||
|  | 	unsigned int *source;	/* the address of data to be read. */ | ||||||
|  | 	unsigned int source_pad; | ||||||
|  | 
 | ||||||
|  | 	unsigned int *destination;	/* the address to write data */ | ||||||
|  | 	unsigned int destination_pad; | ||||||
|  | 
 | ||||||
|  | 	unsigned int *next;	/* the next descriptor in the list. */ | ||||||
|  | 	unsigned int next_pad; | ||||||
|  | 
 | ||||||
|  | 	unsigned short bytes_to_transfer; /* the number of bytes to transfer */ | ||||||
|  | 	unsigned char read_burst; | ||||||
|  | 	unsigned char write_burst; | ||||||
|  | 
 | ||||||
|  | 	unsigned short actual_bytes_transferred;/* bytes transferred by DMA */ | ||||||
|  | 	unsigned char descriptor_status; | ||||||
|  | 	unsigned char descriptor_control; | ||||||
|  | 
 | ||||||
|  | } __packed_1_; | ||||||
|  | 
 | ||||||
|  | /* SG-DMA Control/Status Slave registers map */ | ||||||
|  | 
 | ||||||
|  | struct alt_sgdma_registers { | ||||||
|  | 	unsigned int status; | ||||||
|  | 	unsigned int status_pad[3]; | ||||||
|  | 	unsigned int control; | ||||||
|  | 	unsigned int control_pad[3]; | ||||||
|  | 	unsigned int next_descriptor_pointer; | ||||||
|  | 	unsigned int descriptor_pad[3]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* TSE Stuff */ | ||||||
|  | #define ALTERA_TSE_CMD_TX_ENA_MSK		(0x00000001) | ||||||
|  | #define ALTERA_TSE_CMD_RX_ENA_MSK		(0x00000002) | ||||||
|  | #define ALTERA_TSE_CMD_XON_GEN_MSK		(0x00000004) | ||||||
|  | #define ALTERA_TSE_CMD_ETH_SPEED_MSK		(0x00000008) | ||||||
|  | #define ALTERA_TSE_CMD_PROMIS_EN_MSK		(0x00000010) | ||||||
|  | #define ALTERA_TSE_CMD_PAD_EN_MSK		(0x00000020) | ||||||
|  | #define ALTERA_TSE_CMD_CRC_FWD_MSK		(0x00000040) | ||||||
|  | #define ALTERA_TSE_CMD_PAUSE_FWD_MSK		(0x00000080) | ||||||
|  | #define ALTERA_TSE_CMD_PAUSE_IGNORE_MSK	(0x00000100) | ||||||
|  | #define ALTERA_TSE_CMD_TX_ADDR_INS_MSK		(0x00000200) | ||||||
|  | #define ALTERA_TSE_CMD_HD_ENA_MSK		(0x00000400) | ||||||
|  | #define ALTERA_TSE_CMD_EXCESS_COL_MSK		(0x00000800) | ||||||
|  | #define ALTERA_TSE_CMD_LATE_COL_MSK		(0x00001000) | ||||||
|  | #define ALTERA_TSE_CMD_SW_RESET_MSK		(0x00002000) | ||||||
|  | #define ALTERA_TSE_CMD_MHASH_SEL_MSK		(0x00004000) | ||||||
|  | #define ALTERA_TSE_CMD_LOOPBACK_MSK		(0x00008000) | ||||||
|  | /* Bits (18:16) = address select */ | ||||||
|  | #define ALTERA_TSE_CMD_TX_ADDR_SEL_MSK		(0x00070000) | ||||||
|  | #define ALTERA_TSE_CMD_MAGIC_ENA_MSK		(0x00080000) | ||||||
|  | #define ALTERA_TSE_CMD_SLEEP_MSK		(0x00100000) | ||||||
|  | #define ALTERA_TSE_CMD_WAKEUP_MSK		(0x00200000) | ||||||
|  | #define ALTERA_TSE_CMD_XOFF_GEN_MSK		(0x00400000) | ||||||
|  | #define ALTERA_TSE_CMD_CNTL_FRM_ENA_MSK	(0x00800000) | ||||||
|  | #define ALTERA_TSE_CMD_NO_LENGTH_CHECK_MSK	(0x01000000) | ||||||
|  | #define ALTERA_TSE_CMD_ENA_10_MSK		(0x02000000) | ||||||
|  | #define ALTERA_TSE_CMD_RX_ERR_DISC_MSK		(0x04000000) | ||||||
|  | /* Bits (30..27) reserved */ | ||||||
|  | #define ALTERA_TSE_CMD_CNT_RESET_MSK		(0x80000000) | ||||||
|  | 
 | ||||||
|  | #define ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16	(0x00040000) | ||||||
|  | #define ALTERA_TSE_TX_CMD_STAT_OMIT_CRC	(0x00020000) | ||||||
|  | 
 | ||||||
|  | #define ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16	(0x02000000) | ||||||
|  | 
 | ||||||
|  | #define ALT_TSE_SW_RESET_WATCHDOG_CNTR		10000 | ||||||
|  | #define ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR	90000000 | ||||||
|  | 
 | ||||||
|  | /* Command_Config Register Bit Definitions */ | ||||||
|  | 
 | ||||||
|  | typedef volatile union __alt_tse_command_config { | ||||||
|  | 	unsigned int image; | ||||||
|  | 	struct { | ||||||
|  | 		unsigned int | ||||||
|  | 		 transmit_enable:1,		/* bit 0 */ | ||||||
|  | 		 receive_enable:1,		/* bit 1 */ | ||||||
|  | 		 pause_frame_xon_gen:1,	/* bit 2 */ | ||||||
|  | 		 ethernet_speed:1,		/* bit 3 */ | ||||||
|  | 		 promiscuous_enable:1,		/* bit 4 */ | ||||||
|  | 		 pad_enable:1,			/* bit 5 */ | ||||||
|  | 		 crc_forward:1,		/* bit 6 */ | ||||||
|  | 		 pause_frame_forward:1,	/* bit 7 */ | ||||||
|  | 		 pause_frame_ignore:1,		/* bit 8 */ | ||||||
|  | 		 set_mac_address_on_tx:1,	/* bit 9 */ | ||||||
|  | 		 halfduplex_enable:1,		/* bit 10 */ | ||||||
|  | 		 excessive_collision:1,	/* bit 11 */ | ||||||
|  | 		 late_collision:1,		/* bit 12 */ | ||||||
|  | 		 software_reset:1,		/* bit 13 */ | ||||||
|  | 		 multicast_hash_mode_sel:1,	/* bit 14 */ | ||||||
|  | 		 loopback_enable:1,		/* bit 15 */ | ||||||
|  | 		 src_mac_addr_sel_on_tx:3,	/* bit 18:16 */ | ||||||
|  | 		 magic_packet_detect:1,	/* bit 19 */ | ||||||
|  | 		 sleep_mode_enable:1,		/* bit 20 */ | ||||||
|  | 		 wake_up_request:1,		/* bit 21 */ | ||||||
|  | 		 pause_frame_xoff_gen:1,	/* bit 22 */ | ||||||
|  | 		 control_frame_enable:1,	/* bit 23 */ | ||||||
|  | 		 payload_len_chk_disable:1,	/* bit 24 */ | ||||||
|  | 		 enable_10mbps_intf:1,		/* bit 25 */ | ||||||
|  | 		 rx_error_discard_enable:1,	/* bit 26 */ | ||||||
|  | 		 reserved_bits:4,		/* bit 30:27 */ | ||||||
|  | 		 self_clear_counter_reset:1;	/* bit 31 */ | ||||||
|  | 	} __packed_1_ bits; | ||||||
|  | } __packed_1_ alt_tse_command_config; | ||||||
|  | 
 | ||||||
|  | /* Tx_Cmd_Stat Register Bit Definitions */ | ||||||
|  | 
 | ||||||
|  | typedef volatile union __alt_tse_tx_cmd_stat { | ||||||
|  | 	unsigned int image; | ||||||
|  | 	struct { | ||||||
|  | 		unsigned int reserved_lsbs:17,	/* bit 16:0  */ | ||||||
|  | 		 omit_crc:1,			/* bit 17 */ | ||||||
|  | 		 tx_shift16:1,			/* bit 18 */ | ||||||
|  | 		 reserved_msbs:13;		/* bit 31:19 */ | ||||||
|  | 
 | ||||||
|  | 	} __packed_1_ bits; | ||||||
|  | } alt_tse_tx_cmd_stat; | ||||||
|  | 
 | ||||||
|  | /* Rx_Cmd_Stat Register Bit Definitions */ | ||||||
|  | 
 | ||||||
|  | typedef volatile union __alt_tse_rx_cmd_stat { | ||||||
|  | 	unsigned int image; | ||||||
|  | 	struct { | ||||||
|  | 		unsigned int reserved_lsbs:25,	/* bit 24:0  */ | ||||||
|  | 		 rx_shift16:1,			/* bit 25 */ | ||||||
|  | 		 reserved_msbs:6;		/* bit 31:26 */ | ||||||
|  | 
 | ||||||
|  | 	} __packed_1_ bits; | ||||||
|  | } alt_tse_rx_cmd_stat; | ||||||
|  | 
 | ||||||
|  | struct alt_tse_mdio { | ||||||
|  | 	unsigned int control;	/*PHY device operation control register */ | ||||||
|  | 	unsigned int status;	/*PHY device operation status register */ | ||||||
|  | 	unsigned int phy_id1;	/*Bits 31:16 of PHY identifier. */ | ||||||
|  | 	unsigned int phy_id2;	/*Bits 15:0 of PHY identifier. */ | ||||||
|  | 	unsigned int auto_negotiation_advertisement; | ||||||
|  | 	unsigned int remote_partner_base_page_ability; | ||||||
|  | 
 | ||||||
|  | 	unsigned int reg6; | ||||||
|  | 	unsigned int reg7; | ||||||
|  | 	unsigned int reg8; | ||||||
|  | 	unsigned int reg9; | ||||||
|  | 	unsigned int rega; | ||||||
|  | 	unsigned int regb; | ||||||
|  | 	unsigned int regc; | ||||||
|  | 	unsigned int regd; | ||||||
|  | 	unsigned int rege; | ||||||
|  | 	unsigned int regf; | ||||||
|  | 	unsigned int reg10; | ||||||
|  | 	unsigned int reg11; | ||||||
|  | 	unsigned int reg12; | ||||||
|  | 	unsigned int reg13; | ||||||
|  | 	unsigned int reg14; | ||||||
|  | 	unsigned int reg15; | ||||||
|  | 	unsigned int reg16; | ||||||
|  | 	unsigned int reg17; | ||||||
|  | 	unsigned int reg18; | ||||||
|  | 	unsigned int reg19; | ||||||
|  | 	unsigned int reg1a; | ||||||
|  | 	unsigned int reg1b; | ||||||
|  | 	unsigned int reg1c; | ||||||
|  | 	unsigned int reg1d; | ||||||
|  | 	unsigned int reg1e; | ||||||
|  | 	unsigned int reg1f; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* MAC register Space */ | ||||||
|  | 
 | ||||||
|  | struct alt_tse_mac { | ||||||
|  | 	unsigned int megacore_revision; | ||||||
|  | 	unsigned int scratch_pad; | ||||||
|  | 	alt_tse_command_config command_config; | ||||||
|  | 	unsigned int mac_addr_0; | ||||||
|  | 	unsigned int mac_addr_1; | ||||||
|  | 	unsigned int max_frame_length; | ||||||
|  | 	unsigned int pause_quanta; | ||||||
|  | 	unsigned int rx_sel_empty_threshold; | ||||||
|  | 	unsigned int rx_sel_full_threshold; | ||||||
|  | 	unsigned int tx_sel_empty_threshold; | ||||||
|  | 	unsigned int tx_sel_full_threshold; | ||||||
|  | 	unsigned int rx_almost_empty_threshold; | ||||||
|  | 	unsigned int rx_almost_full_threshold; | ||||||
|  | 	unsigned int tx_almost_empty_threshold; | ||||||
|  | 	unsigned int tx_almost_full_threshold; | ||||||
|  | 	unsigned int mdio_phy0_addr; | ||||||
|  | 	unsigned int mdio_phy1_addr; | ||||||
|  | 
 | ||||||
|  | 	/* only if 100/1000 BaseX PCS, reserved otherwise */ | ||||||
|  | 	unsigned int reservedx44[5]; | ||||||
|  | 
 | ||||||
|  | 	unsigned int reg_read_access_status; | ||||||
|  | 	unsigned int min_tx_ipg_length; | ||||||
|  | 
 | ||||||
|  | 	/* IEEE 802.3 oEntity Managed Object Support */ | ||||||
|  | 	unsigned int aMACID_1;	/*The MAC addresses */ | ||||||
|  | 	unsigned int aMACID_2; | ||||||
|  | 	unsigned int aFramesTransmittedOK; | ||||||
|  | 	unsigned int aFramesReceivedOK; | ||||||
|  | 	unsigned int aFramesCheckSequenceErrors; | ||||||
|  | 	unsigned int aAlignmentErrors; | ||||||
|  | 	unsigned int aOctetsTransmittedOK; | ||||||
|  | 	unsigned int aOctetsReceivedOK; | ||||||
|  | 
 | ||||||
|  | 	/* IEEE 802.3 oPausedEntity Managed Object Support */ | ||||||
|  | 	unsigned int aTxPAUSEMACCtrlFrames; | ||||||
|  | 	unsigned int aRxPAUSEMACCtrlFrames; | ||||||
|  | 
 | ||||||
|  | 	/* IETF MIB (MIB-II) Object Support */ | ||||||
|  | 	unsigned int ifInErrors; | ||||||
|  | 	unsigned int ifOutErrors; | ||||||
|  | 	unsigned int ifInUcastPkts; | ||||||
|  | 	unsigned int ifInMulticastPkts; | ||||||
|  | 	unsigned int ifInBroadcastPkts; | ||||||
|  | 	unsigned int ifOutDiscards; | ||||||
|  | 	unsigned int ifOutUcastPkts; | ||||||
|  | 	unsigned int ifOutMulticastPkts; | ||||||
|  | 	unsigned int ifOutBroadcastPkts; | ||||||
|  | 
 | ||||||
|  | 	/* IETF RMON MIB Object Support */ | ||||||
|  | 	unsigned int etherStatsDropEvent; | ||||||
|  | 	unsigned int etherStatsOctets; | ||||||
|  | 	unsigned int etherStatsPkts; | ||||||
|  | 	unsigned int etherStatsUndersizePkts; | ||||||
|  | 	unsigned int etherStatsOversizePkts; | ||||||
|  | 	unsigned int etherStatsPkts64Octets; | ||||||
|  | 	unsigned int etherStatsPkts65to127Octets; | ||||||
|  | 	unsigned int etherStatsPkts128to255Octets; | ||||||
|  | 	unsigned int etherStatsPkts256to511Octets; | ||||||
|  | 	unsigned int etherStatsPkts512to1023Octets; | ||||||
|  | 	unsigned int etherStatsPkts1024to1518Octets; | ||||||
|  | 
 | ||||||
|  | 	unsigned int etherStatsPkts1519toXOctets; | ||||||
|  | 	unsigned int etherStatsJabbers; | ||||||
|  | 	unsigned int etherStatsFragments; | ||||||
|  | 
 | ||||||
|  | 	unsigned int reservedxE4; | ||||||
|  | 
 | ||||||
|  | 	/*FIFO control register. */ | ||||||
|  | 	alt_tse_tx_cmd_stat tx_cmd_stat; | ||||||
|  | 	alt_tse_rx_cmd_stat rx_cmd_stat; | ||||||
|  | 
 | ||||||
|  | 	unsigned int ipaccTxConf; | ||||||
|  | 	unsigned int ipaccRxConf; | ||||||
|  | 	unsigned int ipaccRxStat; | ||||||
|  | 	unsigned int ipaccRxStatSum; | ||||||
|  | 
 | ||||||
|  | 	/*Multicast address resolution table */ | ||||||
|  | 	unsigned int hash_table[64]; | ||||||
|  | 
 | ||||||
|  | 	/*Registers 0 to 31 within PHY device 0/1 */ | ||||||
|  | 	struct alt_tse_mdio mdio_phy0; | ||||||
|  | 	struct alt_tse_mdio mdio_phy1; | ||||||
|  | 
 | ||||||
|  | 	/*4 Supplemental MAC Addresses */ | ||||||
|  | 	unsigned int supp_mac_addr_0_0; | ||||||
|  | 	unsigned int supp_mac_addr_0_1; | ||||||
|  | 	unsigned int supp_mac_addr_1_0; | ||||||
|  | 	unsigned int supp_mac_addr_1_1; | ||||||
|  | 	unsigned int supp_mac_addr_2_0; | ||||||
|  | 	unsigned int supp_mac_addr_2_1; | ||||||
|  | 	unsigned int supp_mac_addr_3_0; | ||||||
|  | 	unsigned int supp_mac_addr_3_1; | ||||||
|  | 
 | ||||||
|  | 	unsigned int reservedx320[56]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* flags: TSE MII modes */ | ||||||
|  | /* GMII/MII	= 0 */ | ||||||
|  | /* RGMII	= 1 */ | ||||||
|  | /* RGMII_ID	= 2 */ | ||||||
|  | /* RGMII_TXID	= 3 */ | ||||||
|  | /* RGMII_RXID	= 4 */ | ||||||
|  | /* SGMII	= 5 */ | ||||||
|  | struct altera_tse_priv { | ||||||
|  | 	char devname[16]; | ||||||
|  | 	volatile struct alt_tse_mac *mac_dev; | ||||||
|  | 	volatile struct alt_sgdma_registers *sgdma_rx; | ||||||
|  | 	volatile struct alt_sgdma_registers *sgdma_tx; | ||||||
|  | 	unsigned int rx_sgdma_irq; | ||||||
|  | 	unsigned int tx_sgdma_irq; | ||||||
|  | 	unsigned int has_descriptor_mem; | ||||||
|  | 	unsigned int descriptor_mem_base; | ||||||
|  | 	unsigned int descriptor_mem_size; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *rx_desc; | ||||||
|  | 	volatile struct alt_sgdma_descriptor *tx_desc; | ||||||
|  | 	volatile unsigned char *rx_buf; | ||||||
|  | 	struct phy_info *phyinfo; | ||||||
|  | 	unsigned int phyaddr; | ||||||
|  | 	unsigned int flags; | ||||||
|  | 	unsigned int link; | ||||||
|  | 	unsigned int duplexity; | ||||||
|  | 	unsigned int speed; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Phy stuff continued */ | ||||||
|  | /*
 | ||||||
|  |  * struct phy_cmd:  A command for reading or writing a PHY register | ||||||
|  |  * | ||||||
|  |  * mii_reg:  The register to read or write | ||||||
|  |  * | ||||||
|  |  * mii_data:  For writes, the value to put in the register. | ||||||
|  |  *	A value of -1 indicates this is a read. | ||||||
|  |  * | ||||||
|  |  * funct: A function pointer which is invoked for each command. | ||||||
|  |  *	For reads, this function will be passed the value read | ||||||
|  |  *	from the PHY, and process it. | ||||||
|  |  *	For writes, the result of this function will be written | ||||||
|  |  *	to the PHY register | ||||||
|  |  */ | ||||||
|  | struct phy_cmd { | ||||||
|  | 	uint mii_reg; | ||||||
|  | 	uint mii_data; | ||||||
|  | 	uint(*funct) (uint mii_reg, struct altera_tse_priv *priv); | ||||||
|  | }; | ||||||
|  | #endif /* _ALTERA_TSE_H_ */ | ||||||
|  | @ -41,6 +41,8 @@ int board_eth_init(bd_t *bis); | ||||||
| int cpu_eth_init(bd_t *bis); | int cpu_eth_init(bd_t *bis); | ||||||
| 
 | 
 | ||||||
| /* Driver initialization prototypes */ | /* Driver initialization prototypes */ | ||||||
|  | int altera_tse_initialize(u8 dev_num, int mac_base, | ||||||
|  | 			  int sgdma_rx_base, int sgdma_tx_base); | ||||||
| int au1x00_enet_initialize(bd_t*); | int au1x00_enet_initialize(bd_t*); | ||||||
| int at91emac_register(bd_t *bis, unsigned long iobase); | int at91emac_register(bd_t *bis, unsigned long iobase); | ||||||
| int bfin_EMAC_initialize(bd_t *bis); | int bfin_EMAC_initialize(bd_t *bis); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue