add rk29xx vmac driver

This commit is contained in:
lyx
2010-12-13 20:43:35 -08:00
parent 458a5b61b2
commit 6951306dd2
9 changed files with 1908 additions and 2 deletions

View File

@@ -574,7 +574,46 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_NET_ETHERNET is not set
CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
# CONFIG_MARVELL_PHY is not set
# CONFIG_DAVICOM_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
# CONFIG_NATIONAL_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
CONFIG_RK29_VMAC=y
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
# CONFIG_ETHOC is not set
# CONFIG_SMC911X is not set
# CONFIG_SMSC911X is not set
# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
# CONFIG_KS8842 is not set
# CONFIG_KS8851_MLL is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_WLAN=y

View File

@@ -1044,6 +1044,19 @@ static void __init rk29_board_iomux_init(void)
rk29_mux_api_set(GPIO2C6_SPI1TXD_NAME, GPIO2H_SPI1_TXD);
rk29_mux_api_set(GPIO2C7_SPI1RXD_NAME, GPIO2H_SPI1_RXD);
#endif
#ifdef CONFIG_RK29_VMAC
rk29_mux_api_set(GPIO4C0_RMIICLKOUT_RMIICLKIN_NAME, GPIO4H_RMII_CLKOUT);
rk29_mux_api_set(GPIO4C1_RMIITXEN_MIITXEN_NAME, GPIO4H_RMII_TX_EN);
rk29_mux_api_set(GPIO4C2_RMIITXD1_MIITXD1_NAME, GPIO4H_RMII_TXD1);
rk29_mux_api_set(GPIO4C3_RMIITXD0_MIITXD0_NAME, GPIO4H_RMII_TXD0);
rk29_mux_api_set(GPIO4C4_RMIIRXERR_MIIRXERR_NAME, GPIO4H_RMII_RX_ERR);
rk29_mux_api_set(GPIO4C5_RMIICSRDVALID_MIIRXDVALID_NAME, GPIO4H_RMII_CSR_DVALID);
rk29_mux_api_set(GPIO4C6_RMIIRXD1_MIIRXD1_NAME, GPIO4H_RMII_RXD1);
rk29_mux_api_set(GPIO4C7_RMIIRXD0_MIIRXD0_NAME, GPIO4H_RMII_RXD0);
rk29_mux_api_set(GPIO0A7_MIIMDCLK_NAME, GPIO0L_MII_MDCLK);
rk29_mux_api_set(GPIO0A6_MIIMD_NAME, GPIO0L_MII_MD);
#endif
}
static struct platform_device *devices[] __initdata = {
@@ -1106,6 +1119,9 @@ static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_BACKLIGHT_RK29_BL
&rk29_device_backlight,
#endif
#ifdef CONFIG_RK29_VMAC
&rk29_device_vmac,
#endif
#ifdef CONFIG_VIVANTE
&rk29_device_gpu,
#endif
@@ -1126,6 +1142,74 @@ static struct platform_device *devices[] __initdata = {
#endif
};
/*****************************************************************************************
* spi devices
* author: cmc@rock-chips.com
*****************************************************************************************/
static int rk29_vmac_register_set(void)
{
//config rk29 vmac as rmii, 100MHz
u32 value= readl(RK29_GRF_BASE + 0xbc);
value = (value & 0xfff7ff) | (0x400);
writel(value, RK29_GRF_BASE + 0xbc);
return 0;
}
static int rk29_rmii_io_init(void)
{
int err;
//set dm9161 rmii
rk29_mux_api_set(GPIO2D3_I2S0SDI_MIICOL_NAME, GPIO2H_GPIO2D3);
err = gpio_request(RK29_PIN2_PD3, "rmii");
if (err) {
gpio_free(RK29_PIN2_PD3);
printk("-------request RK29_PIN2_PD3 fail--------\n");
return -1;
}
gpio_direction_output(RK29_PIN2_PD3, GPIO_HIGH);
gpio_set_value(RK29_PIN2_PD3, GPIO_HIGH);
//rmii power on
err = gpio_request(RK29_PIN6_PB0, "rmii_power_en");
if (err) {
gpio_free(RK29_PIN6_PB0);
gpio_free(RK29_PIN2_PD3);
printk("-------request RK29_PIN6_PB0 fail--------\n");
return -1;
}
gpio_direction_output(RK29_PIN6_PB0, GPIO_HIGH);
gpio_set_value(RK29_PIN6_PB0, GPIO_HIGH);
return 0;
}
static int rk29_rmii_power_control(int enable)
{
if (enable) {
//set dm9161 as rmii
gpio_direction_output(RK29_PIN2_PD3, GPIO_HIGH);
gpio_set_value(RK29_PIN2_PD3, GPIO_HIGH);
//enable rmii power
gpio_direction_output(RK29_PIN6_PB0, GPIO_HIGH);
gpio_set_value(RK29_PIN6_PB0, GPIO_HIGH);
}
else {
gpio_direction_output(RK29_PIN6_PB0, GPIO_LOW);
gpio_set_value(RK29_PIN6_PB0, GPIO_LOW);
}
return 0;
}
struct rk29_vmac_platform_data rk29_vmac_pdata = {
.vmac_register_set = rk29_vmac_register_set,
.rmii_io_init = rk29_rmii_io_init,
.rmii_power_control = rk29_rmii_power_control,
};
/*****************************************************************************************
* spi devices
* author: cmc@rock-chips.com

View File

@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/usb/android_composite.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <mach/irqs.h>
#include <mach/rk29_iomap.h>
#include <mach/rk29-dma-pl330.h>
@@ -46,6 +47,36 @@ struct platform_device rk29_device_adc = {
};
#endif
#ifdef CONFIG_RK29_VMAC
static u64 eth_dmamask = DMA_BIT_MASK(32);
static struct resource rk29_vmac_resource[] = {
[0] = {
.start = RK29_MAC_PHYS,
.end = RK29_MAC_PHYS + RK29_MAC_SIZE - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_MAC,
.end = IRQ_MAC,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device rk29_device_vmac = {
.name = "rk29 vmac",
.id = 0,
.dev = {
.dma_mask = &eth_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &rk29_vmac_pdata,
},
.num_resources = ARRAY_SIZE(rk29_vmac_resource),
.resource = rk29_vmac_resource,
};
#endif
#ifdef CONFIG_I2C_RK29
static struct resource resources_i2c0[] = {
{

View File

@@ -47,11 +47,13 @@ extern struct rk29_sdmmc_platform_data default_sdmmc1_data;
extern struct platform_device rk29_device_sdmmc0;
extern struct platform_device rk29_device_sdmmc1;
extern struct platform_device rk29_device_adc;
extern struct platform_device rk29_device_vmac;
extern struct rk29_bl_info rk29_bl_info;
extern struct platform_device rk29_device_backlight;
extern struct platform_device rk29_device_dwc_otg;
extern struct platform_device android_usb_device;
extern struct usb_mass_storage_platform_data mass_storage_pdata;
extern struct platform_device usb_mass_storage_device;
extern struct platform_device rk29_device_vmac;
extern struct rk29_vmac_platform_data rk29_vmac_pdata;
#endif

View File

@@ -36,6 +36,13 @@ struct rk29xx_spi_platform_data {
u16 num_chipselect;
};
/*vmac*/
struct rk29_vmac_platform_data {
int (*vmac_register_set)(void);
int (*rmii_io_init)(void);
int (*rmii_power_control)(int enable);
};
#define INVALID_GPIO -1
struct rk29lcd_info{

View File

@@ -236,6 +236,16 @@ config AX88796_93CX6
help
Select this if your platform comes with an external 93CX6 eeprom.
config RK29_VMAC
tristate "RK29 VMAC ethernet support"
depends on HAS_DMA
select MII
select PHYLIB
select CRC32
help
MAC device present on rockchip rk29xx
config MACE
tristate "MACE (Power Mac ethernet) support"
depends on PPC_PMAC && PPC32

View File

@@ -132,6 +132,7 @@ obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
obj-$(CONFIG_E2100) += e2100.o 8390.o
obj-$(CONFIG_RK29_VMAC) += rk29_vmac.o
obj-$(CONFIG_ES3210) += es3210.o 8390.o
obj-$(CONFIG_LNE390) += lne390.o 8390.o
obj-$(CONFIG_NE3210) += ne3210.o 8390.o

1464
drivers/net/rk29_vmac.c Executable file

File diff suppressed because it is too large Load Diff

268
drivers/net/rk29_vmac.h Executable file
View File

@@ -0,0 +1,268 @@
/*
* linux/arch/arc/drivers/arcvmac.h
*
* Copyright (C) 2003-2006 Codito Technologies, for linux-2.4 port
* Copyright (C) 2006-2007 Celunite Inc, for linux-2.6 port
* Copyright (C) 2007-2008 Sagem Communications, Fehmi HAFSI
* Copyright (C) 2009 Sagem Communications, Andreas Fenkart
* All Rights Reserved.
*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Authors: amit.bhor@celunite.com, sameer.dhavale@celunite.com
*/
#ifndef _ARCVMAC_H
#define _ARCVMAC_H
#define VMAC_NAME "rk29 vmac"
#define VMAC_VERSION "1.0"
/* Buffer descriptors */
#define TX_BDT_LEN 16 /* Number of receive BD's */
#define RX_BDT_LEN 255 /* Number of transmit BD's */
/* BD poll rate, in 1024 cycles. @100Mhz: x * 1024 cy * 10ns = 1ms */
#define POLLRATE_TIME 200
/* next power of two, bigger than ETH_FRAME_LEN + VLAN */
#define MAX_RX_BUFFER_LEN 0x800 /* 2^11 = 2048 = 0x800 */
#define MAX_TX_BUFFER_LEN 0x800 /* 2^11 = 2048 = 0x800 */
/* 14 bytes of ethernet header, 4 bytes VLAN, FCS,
* plus extra pad to prevent buffer chaining of
* maximum sized ethernet packets (1514 bytes) */
#define VMAC_BUFFER_PAD (ETH_HLEN + 4 + ETH_FCS_LEN + 4)
/* VMAC register definitions, offsets in the ref manual are in bytes */
#define ID_OFFSET (0x00/0x4)
#define STAT_OFFSET (0x04/0x4)
#define ENABLE_OFFSET (0x08/0x4)
#define CONTROL_OFFSET (0x0c/0x4)
#define POLLRATE_OFFSET (0x10/0x4)
#define RXERR_OFFSET (0x14/0x4)
#define MISS_OFFSET (0x18/0x4)
#define TXRINGPTR_OFFSET (0x1c/0x4)
#define RXRINGPTR_OFFSET (0x20/0x4)
#define ADDRL_OFFSET (0x24/0x4)
#define ADDRH_OFFSET (0x28/0x4)
#define LAFL_OFFSET (0x2c/0x4)
#define LAFH_OFFSET (0x30/0x4)
#define MDIO_DATA_OFFSET (0x34/0x4)
#define MAC_TXRING_HEAD_OFFSET (0x38/0x4)
#define MAC_RXRING_HEAD_OFFSET (0x3C/0x4)
/* STATUS and ENABLE register bit masks */
#define TXINT_MASK (1<<0) /* Transmit interrupt */
#define RXINT_MASK (1<<1) /* Receive interrupt */
#define ERR_MASK (1<<2) /* Error interrupt */
#define TXCH_MASK (1<<3) /* Transmit chaining error interrupt */
#define MSER_MASK (1<<4) /* Missed packet counter error */
#define RXCR_MASK (1<<8) /* RXCRCERR counter rolled over */
#define RXFR_MASK (1<<9) /* RXFRAMEERR counter rolled over */
#define RXFL_MASK (1<<10) /* RXOFLOWERR counter rolled over */
#define MDIO_MASK (1<<12) /* MDIO complete */
#define TXPL_MASK (1<<31) /* TXPOLL */
/* CONTROL register bitmasks */
#define EN_MASK (1<<0) /* VMAC enable */
#define TXRN_MASK (1<<3) /* TX enable */
#define RXRN_MASK (1<<4) /* RX enable */
#define DSBC_MASK (1<<8) /* Disable receive broadcast */
#define ENFL_MASK (1<<10) /* Enable Full Duplex */ ///////
#define PROM_MASK (1<<11) /* Promiscuous mode */
/* RXERR register bitmasks */
#define RXERR_CRC 0x000000ff
#define RXERR_FRM 0x0000ff00
#define RXERR_OFLO 0x00ff0000 /* fifo overflow */
/* MDIO data register bit masks */
#define MDIO_SFD 0xC0000000
#define MDIO_OP 0x30000000
#define MDIO_ID_MASK 0x0F800000
#define MDIO_REG_MASK 0x007C0000
#define MDIO_TA 0x00030000
#define MDIO_DATA_MASK 0x0000FFFF
#define MDIO_BASE 0x40020000
#define MDIO_OP_READ 0x20000000
#define MDIO_OP_WRITE 0x10000000
/* Buffer descriptor INFO bit masks */
#define OWN_MASK (1<<31) /* ownership of buffer, 0 CPU, 1 DMA */
#define BUFF (1<<30) /* buffer invalid, rx */
#define UFLO (1<<29) /* underflow, tx */
#define LTCL (1<<28) /* late collision, tx */
#define RETRY_CT (0xf<<24) /* tx */
#define DROP (1<<23) /* drop, more than 16 retries, tx */
#define DEFER (1<<22) /* traffic on the wire, tx */
#define CARLOSS (1<<21) /* carrier loss while transmission, tx, rx? */
/* 20:19 reserved */
#define ADCR (1<<18) /* add crc, ignored if not disaddcrc */
#define LAST_MASK (1<<17) /* Last buffer in chain */
#define FRST_MASK (1<<16) /* First buffer in chain */
/* 15:11 reserved */
#define LEN_MASK 0x000007FF
#define ERR_MSK_TX 0x3fe00000 /* UFLO | LTCL | RTRY | DROP | DEFER | CRLS */
/* arcvmac private data structures */
struct vmac_buffer_desc {
unsigned int info;
dma_addr_t data;
};
struct dma_fifo {
int head; /* head */
int tail; /* tail */
int size;
};
struct vmac_priv {
struct net_device *dev;
struct platform_device *pdev;
struct net_device_stats stats;
spinlock_t lock; /* TODO revisit */
struct completion mdio_complete;
/* base address of register set */
int *regs;
unsigned int mem_base;
/* DMA ring buffers */
struct vmac_buffer_desc *rxbd;
dma_addr_t rxbd_dma;
struct vmac_buffer_desc *txbd;
dma_addr_t txbd_dma;
/* socket buffers */
struct sk_buff *rx_skbuff[RX_BDT_LEN];
struct sk_buff *tx_skbuff[TX_BDT_LEN];
int rx_skb_size;
/* skb / dma desc managing */
struct dma_fifo rx_ring;
struct dma_fifo tx_ring;
/* descriptor last polled/processed by the VMAC */
unsigned long mac_rxring_head;
/* used when rx skb allocation failed, so we defer rx queue
* refill */
struct timer_list rx_timeout;
/* lock rx_timeout against rx normal operation */
spinlock_t rx_lock;
struct napi_struct napi;
/* rx buffer chaining */
int rx_merge_error;
int tx_timeout_error;
/* PHY stuff */
struct mii_bus *mii_bus;
struct phy_device *phy_dev;
int link;
int speed;
int duplex;
/* debug */
int shutdown;
};
/* DMA ring management */
/* for a fifo with size n,
* - [0..n] fill levels are n + 1 states
* - there are only n different deltas (head - tail) values
* => not all fill levels can be represented with head, tail
* pointers only
* we give up the n fill level, aka fifo full */
/* sacrifice one elt as a sentinel */
static inline int fifo_used(struct dma_fifo *f);
static inline int fifo_inc_ct(int ct, int size);
static inline void fifo_dump(struct dma_fifo *fifo);
static inline int fifo_empty(struct dma_fifo *f)
{
return (f->head == f->tail);
}
static inline int fifo_free(struct dma_fifo *f)
{
int free;
free = f->tail - f->head;
if (free <= 0)
free += f->size;
return free;
}
static inline int fifo_used(struct dma_fifo *f)
{
int used;
used = f->head - f->tail;
if (used < 0)
used += f->size;
return used;
}
static inline int fifo_full(struct dma_fifo *f)
{
return (fifo_used(f) + 1) == f->size;
}
/* manipulate */
static inline void fifo_init(struct dma_fifo *fifo, int size)
{
fifo->size = size;
fifo->head = fifo->tail = 0; /* empty */
}
static inline void fifo_inc_head(struct dma_fifo *fifo)
{
BUG_ON(fifo_full(fifo));
fifo->head = fifo_inc_ct(fifo->head, fifo->size);
}
static inline void fifo_inc_tail(struct dma_fifo *fifo)
{
BUG_ON(fifo_empty(fifo));
fifo->tail = fifo_inc_ct(fifo->tail, fifo->size);
}
/* internal funcs */
static inline void fifo_dump(struct dma_fifo *fifo)
{
printk(KERN_INFO "fifo: head %d, tail %d, size %d\n", fifo->head,
fifo->tail,
fifo->size);
}
static inline int fifo_inc_ct(int ct, int size)
{
return (++ct == size) ? 0 : ct;
}
#endif /* _ARCVMAC_H */