summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authoryagi <yagi@ke66.alps.lineo.co.jp>2012-06-08 19:46:53 +0900
committerJustin Waters <justin.waters@timesys.com>2012-07-03 17:15:09 -0400
commitca1aae2ad0eac8089afebf56da2fdaebd8580213 (patch)
treee4d126af0204940239f23f63af7bbd6f94e3e533 /arch
parentabc9338fc082ace655c6d418adc5021a53900b84 (diff)
add: FEC & eDMA
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/mvf_edma.h188
-rw-r--r--arch/arm/include/asm/mvf_edma_regs.h313
-rw-r--r--arch/arm/include/asm/mvf_switch.h619
-rw-r--r--arch/arm/mach-mvf/Makefile1
-rw-r--r--arch/arm/mach-mvf/l2switch.c327
-rw-r--r--arch/arm/mach-mvf/mm.c2
-rw-r--r--arch/arm/mach-mvf/mvf_fec.c7
7 files changed, 1454 insertions, 3 deletions
diff --git a/arch/arm/include/asm/mvf_edma.h b/arch/arm/include/asm/mvf_edma.h
new file mode 100644
index 000000000000..4d8e2523753e
--- /dev/null
+++ b/arch/arm/include/asm/mvf_edma.h
@@ -0,0 +1,188 @@
+ /*
+ * mvf_edma.h - mvf eDMA driver header file.
+ *
+ * Copyright 2008-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Add support for mvf platform (Lanttor.Guo@freescale.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _MCF_EDMA_H
+#define _MCF_EDMA_H
+
+#include <linux/interrupt.h>
+#include <asm/mvf_edma_regs.h>
+#include <linux/scatterlist.h>
+
+#define MCF_EDMA_INT0_CHANNEL_BASE (8)
+#define MCF_EDMA_INT0_CONTROLLER_BASE (64)
+#define MCF_EDMA_INT0_BASE (MCF_EDMA_INT0_CHANNEL_BASE + MCF_EDMA_INT0_CONTROLLER_BASE)
+#define MCF_EDMA_INT0_NUM (16)
+#define MCF_EDMA_INT0_END (MCF_EDMA_INT0_NUM)
+
+#define MCF_EDMA_INT1_CHANNEL_BASE (8)
+#define MCF_EDMA_INT1_CONTROLLER_BASE (128)
+#define MCF_EDMA_INT1_BASE (MCF_EDMA_INT1_CHANNEL_BASE + MCF_EDMA_INT1_CONTROLLER_BASE)
+#define MCF_EDMA_INT1_NUM (40)
+#define MCF_EDMA_INT1_END (MCF_EDMA_INT0_END + MCF_EDMA_INT1_NUM)
+
+#define MCF_EDMA_INT2_CHANNEL_BASE (0)
+#define MCF_EDMA_INT2_CONTROLLER_BASE (192)
+#define MCF_EDMA_INT2_BASE (MCF_EDMA_INT2_CHANNEL_BASE + MCF_EDMA_INT2_CONTROLLER_BASE)
+#define MCF_EDMA_INT2_NUM (8)
+#define MCF_EDMA_INT2_END (MCF_EDMA_INT1_END + MCF_EDMA_INT2_NUM)
+
+#define MCF_EDMA_CHANNEL_ANY (0xFF)
+#define MCF_EDMA_INT_ERR (16) /* edma error interrupt */
+
+#define MCF_EDMA_TCD_PER_CHAN 256
+#define MVF_EACH_DMA_CHANNEL 32
+
+/* Setup transfer control descriptor (TCD)
+ * channel - descriptor number
+ * source - source address
+ * dest - destination address
+ * attr - attributes
+ * soff - source offset
+ * nbytes - number of bytes to be transfered in minor loop
+ * slast - last source address adjustment
+ * citer - major loop count
+ * biter - begining minor loop count
+ * doff - destination offset
+ * dlast_sga - last destination address adjustment
+ * major_int - generate interrupt after each major loop
+ * disable_req - disable DMA request after major loop
+ */
+#if 0
+void mvf_edma_set_tcd_params(int channel, u32 source, u32 dest,
+ u32 attr, u32 soff, u32 nbytes, u32 slast,
+ u32 citer, u32 biter, u32 doff, u32 dlast_sga,
+ int major_int, int disable_req);
+#endif
+
+/* Setup transfer control descriptor (TCD) and enable halfway irq
+ * channel - descriptor number
+ * source - source address
+ * dest - destination address
+ * attr - attributes
+ * soff - source offset
+ * nbytes - number of bytes to be transfered in minor loop
+ * slast - last source address adjustment
+ * biter - major loop count
+ * doff - destination offset
+ * dlast_sga - last destination address adjustment
+ * disable_req - disable DMA request after major loop
+ */
+void mvf_edma_set_tcd_params_halfirq(int channel, u32 source, u32 dest,
+ u32 attr, u32 soff, u32 nbytes, u32 slast,
+ u32 biter, u32 doff, u32 dlast_sga,
+ int disable_req);
+
+/* check if dma is done
+ * channel - descriptor number
+ * return 1 if done
+ */
+int mvf_edma_check_done(int channel);
+
+#if 0
+
+/* Starts eDMA transfer on specified channel
+ * channel - eDMA TCD number
+ */
+static inline void
+mvf_edma_start_transfer(int channel)
+{
+ MCF_EDMA_SERQ = channel;
+ MCF_EDMA_SSRT = channel;
+}
+
+/* Restart eDMA transfer from halfirq
+ * channel - eDMA TCD number
+ */
+static inline void
+mvf_edma_confirm_halfirq(int channel)
+{
+ /*MCF_EDMA_TCD_CSR(channel) = 7;*/
+ MCF_EDMA_SSRT = channel;
+}
+
+/* Starts eDMA transfer on specified channel based on peripheral request
+ * channel - eDMA TCD number
+ */
+static inline void mvf_edma_enable_transfer(int channel)
+{
+ MCF_EDMA_SERQ = channel;
+}
+
+
+/* Stops eDMA transfer
+ * channel - eDMA TCD number
+ */
+static inline void
+mvf_edma_stop_transfer(int channel)
+{
+ MCF_EDMA_CINT = channel;
+ MCF_EDMA_CERQ = channel;
+}
+
+/* Confirm that interrupt has been handled
+ * channel - eDMA TCD number
+ */
+static inline void
+mvf_edma_confirm_interrupt_handled(int channel)
+{
+ MCF_EDMA_CINT = channel;
+}
+#endif
+
+
+/**
+ * mvf_edma_request_channel - Request an eDMA channel
+ * @channel: channel number. In case it is equal to EDMA_CHANNEL_ANY
+ * it will be allocated a first free eDMA channel.
+ * @handler: dma handler
+ * @error_handler: dma error handler
+ * @irq_level: irq level for the dma handler
+ * @arg: argument to pass back
+ * @lock: optional spinlock to hold over interrupt
+ * @device_id: device id
+ *
+ * Returns allocatedd channel number if success or
+ * a negative value if failure.
+ */
+int mvf_edma_request_channel(int channel,
+ irqreturn_t(*handler) (int, void *),
+ void (*error_handler) (int, void *),
+ u8 irq_level,
+ void *arg,
+ spinlock_t *lock, const char *device_id);
+
+/**
+ * Update the channel callback/arg
+ * @channel: channel number
+ * @handler: dma handler
+ * @error_handler: dma error handler
+ * @arg: argument to pass back
+ *
+ * Returns 0 if success or a negative value if failure
+ */
+int mvf_edma_set_callback(int channel,
+ irqreturn_t(*handler) (int, void *),
+ void (*error_handler) (int, void *), void *arg);
+
+/**
+ * Free the edma channel
+ * @channel: channel number
+ * @arg: argument created with
+ *
+ * Returns 0 if success or a negative value if failure
+ */
+int mvf_edma_free_channel(int channel, void *arg);
+
+void mvf_edma_dump_channel(int channel);
+
+#endif /* _MCF_EDMA_H */
diff --git a/arch/arm/include/asm/mvf_edma_regs.h b/arch/arm/include/asm/mvf_edma_regs.h
new file mode 100644
index 000000000000..d5d2f253df07
--- /dev/null
+++ b/arch/arm/include/asm/mvf_edma_regs.h
@@ -0,0 +1,313 @@
+/* mvf_edma_regs.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ * Lanttor.Guo@freescale.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _MVF_EDMA_REG_H__
+#define _MVF_EDMA_REG_H__
+
+#define MVF_REG32(x) *((unsigned long *)x)
+#define MVF_REG16(x) *((unsigned short *)x)
+#define MVF_REG08(x) *((unsigned char *)x)
+
+
+/*
+ * Enhanced DMA (EDMA)
+ */
+
+/* Channels */
+#define MVF_EDMA_CHAN_DREQ0 0 /* External DMA request 0 */
+#define MVF_EDMA_CHAN_DREQ1 1 /* External DMA request 1 */
+#define MVF_EDMA_CHAN_UART0_RX 2 /* UART0 Receive */
+#define MVF_EDMA_CHAN_UART0_TX 3 /* UART0 Transmit */
+#define MVF_EDMA_CHAN_UART1_RX 4 /* UART1 Receive */
+#define MVF_EDMA_CHAN_UART1_TX 5 /* UART1 Transmit */
+#define MVF_EDMA_CHAN_UART2_RX 6 /* UART2 Receive */
+#define MVF_EDMA_CHAN_UART2_TX 7 /* UART2 Transmit */
+#define MVF_EDMA_CHAN_TIMER0 8 /* Timer 0 / SSI0 Rx */
+#define MVF_EDMA_CHAN_TIMER1 9 /* Timer 1 / SSI1 Rx */
+#define MVF_EDMA_CHAN_TIMER2 10 /* Timer 2 / SSI0 Tx */
+#define MVF_EDMA_CHAN_TIMER3 11 /* Timer 3 / SSI1 Tx */
+#define MVF_EDMA_CHAN_DSPI0_RX 12 /* DSPI0 Receive */
+#define MVF_EDMA_CHAN_DSPI0_TX 13 /* DSPI0 Transmit */
+#define MVF_EDMA_CHAN_DSPI1_RX 14 /* DSPI1 Receive */
+#define MVF_EDMA_CHAN_DSPI1_TX 15 /* DSPI1 Transmit */
+#define MVF_EDMA_CHAN_UART3_RX 16 /* UART3 Receive */
+#define MVF_EDMA_CHAN_UART3_TX 17 /* UART3 Transmit */
+#define MVF_EDMA_CHAN_UART4_RX 18 /* UART4 Receive */
+#define MVF_EDMA_CHAN_UART4_TX 19 /* UART4 Transmit */
+#define MVF_EDMA_CHAN_UART5_RX 20 /* UART5 Receive */
+#define MVF_EDMA_CHAN_UART5_TX 21 /* UART5 Transmit */
+#define MVF_EDMA_CHAN_UART6_RX 22 /* UART6 Receive */
+#define MVF_EDMA_CHAN_UART6_TX 23 /* UART6 Transmit */
+#define MVF_EDMA_CHAN_I2C0 24 /* I2C0 */
+#define MVF_EDMA_CHAN_I2C1 25 /* I2C1 */
+#define MVF_EDMA_CHAN_I2C2 26 /* I2C2 */
+#define MVF_EDMA_CHAN_I2C3 27 /* I2C3 */
+#define MVF_EDMA_CHAN_DSPI2_RX 28 /* DSPI2 Receive */
+#define MVF_EDMA_CHAN_DSPI2_TX 29 /* DSPI2 Transmit */
+#define MVF_EDMA_CHAN_N0 30 /* Available for software */
+#define MVF_EDMA_CHAN_N1 31 /* Available for software */
+#define MVF_EDMA_CHAN_UART7_RX 32 /* UART7 Receive */
+#define MVF_EDMA_CHAN_UART7_TX 33 /* UART7 Transmit */
+#define MVF_EDMA_CHAN_UART8_RX 34 /* UART8 Receive */
+#define MVF_EDMA_CHAN_UART8_TX 35 /* UART8 Transmit */
+#define MVF_EDMA_CHAN_UART9_RX 36 /* UART9 Receive */
+#define MVF_EDMA_CHAN_UART9_TX 37 /* UART9 Transmit */
+#define MVF_EDMA_CHAN_OW 38 /* 1-Wire */
+#define MVF_EDMA_CHAN_RESERVED 39 /* Reserved */
+#define MVF_EDMA_CHAN_I2C4 40 /* I2C4 */
+#define MVF_EDMA_CHAN_I2C5 41 /* I2C5 */
+#define MVF_EDMA_CHAN_N2 42 /* Available for software */
+#define MVF_EDMA_CHAN_N3 43 /* Available for software */
+#define MVF_EDMA_CHAN_DSPI3_RX 44 /* DSPI3 Receive */
+#define MVF_EDMA_CHAN_DSPI3_TX 45 /* DSPI3 Transmit */
+#define MVF_EDMA_CHAN_SSI0_RX0 48 /* SSI0 Receive 0 */
+#define MVF_EDMA_CHAN_SSI0_RX1 49 /* SSI0 Receive 1 */
+#define MVF_EDMA_CHAN_SSI0_TX0 50 /* SSI0 Transmit 0 */
+#define MVF_EDMA_CHAN_SSI0_TX1 51 /* SSI0 Transmit 1 */
+#define MVF_EDMA_CHAN_SSI1_RX0 52 /* SSI1 Receive 0 */
+#define MVF_EDMA_CHAN_SSI1_RX1 53 /* SSI1 Receive 1 */
+#define MVF_EDMA_CHAN_SSI1_TX0 54 /* SSI1 Transmit 0 */
+#define MVF_EDMA_CHAN_SSI1_TX1 55 /* SSI1 Transmit 1 */
+#define MVF_EDMA_CHAN_PWM_CAP 56 /* PWM Capture */
+#define MVF_EDMA_CHAN_PWM_VAL 57 /* PWM Value */
+#define MVF_EDMA_CHAN_RESERVED2 58 /* Reserved */
+#define MVF_EDMA_CHAN_ESDHC 59 /* eSDHC */
+#define MVF_EDMA_CHAN_ADC0 60 /* ADC 0 */
+#define MVF_EDMA_CHAN_ADC1 61 /* ADC 1 */
+#define MVF_EDMA_CHAN_DAC0 62 /* DAC 0 */
+#define MVF_EDMA_CHAN_DAC1 63 /* DAC 1 */
+
+/* Register read/write macros */
+/* offset 0x0000_0000 - 0x0000_00ff main dma control area */
+#define MVF_EDMA_CR(base) MVF_REG32((long)(base) + 0x00000000)
+#define MVF_EDMA_ES(base) MVF_REG32((long)(base) + 0x00000004)
+//#define MVF_EDMA_ERQH(base) MVF_REG32((long)(base) + 0x00000008)
+#define MVF_EDMA_ERQ(base) MVF_REG32((long)(base) + 0x0000000C)
+//#define MVF_EDMA_EEIH(base) MVF_REG32((long)(base) + 0x00000010)
+#define MVF_EDMA_EEI(base) MVF_REG32((long)(base) + 0x00000014)
+#define MVF_EDMA_SERQ(base) MVF_REG08((long)(base) + 0x00000008)
+#define MVF_EDMA_CERQ(base) MVF_REG08((long)(base) + 0x00000019)
+#define MVF_EDMA_SEEI(base) MVF_REG08((long)(base) + 0x0000001A)
+#define MVF_EDMA_CEEI(base) MVF_REG08((long)(base) + 0x0000001B)
+#define MVF_EDMA_CINT(base) MVF_REG08((long)(base) + 0x0000001C)
+#define MVF_EDMA_CERR(base) MVF_REG08((long)(base) + 0x0000001D)
+#define MVF_EDMA_SSRT(base) MVF_REG08((long)(base) + 0x0000001E)
+#define MVF_EDMA_CDNE(base) MVF_REG08((long)(base) + 0x0000001F)
+//#define MVF_EDMA_INTH(base) MVF_REG32((long)(base) + 0x00000020)
+#define MVF_EDMA_INT(base) MVF_REG32((long)(base) + 0x00000024)
+//#define MVF_EDMA_ERRH(base) MVF_REG32((long)(base) + 0x00000028)
+#define MVF_EDMA_ERR(base) MVF_REG32((long)(base) + 0x0000002C)
+//#define MVF_EDMA_RSH(base) MVF_REG32((long)(base) + 0x00000030)
+#define MVF_EDMA_RS(base) MVF_REG32((long)(base) + 0x00000034)
+
+/* Parameterized register read/write macros for multiple registers */
+/* offset 0x0000_0100 - 0x0000_011f dma channel priority area */
+#define MVF_EDMA_DCHPRI(base,x) MVF_REG08((long)(base) + 0x00000100 +((x)*0x001))
+
+
+/* offset 0x0000_1000 - 0x0000_13ff tcd area */
+#define MVF_EDMA_TCD_SADDR(base,x) MVF_REG32((long)(base) + 0x00001000 +((x)*0x020))
+#define MVF_EDMA_TCD_ATTR(base,x) MVF_REG16((long)(base) + 0x00001004 +((x)*0x020))
+#define MVF_EDMA_TCD_SOFF(base,x) MVF_REG16((long)(base) + 0x00001006 +((x)*0x020))
+#define MVF_EDMA_TCD_NBYTES(base,x) MVF_REG32((long)(base) + 0x00001008 +((x)*0x020))
+#define MVF_EDMA_TCD_SLAST(base,x) MVF_REG32((long)(base) + 0x0000100C +((x)*0x020))
+#define MVF_EDMA_TCD_DADDR(base,x) MVF_REG32((long)(base) + 0x00001010 +((x)*0x020))
+#define MVF_EDMA_TCD_CITER_ELINK(base,x) MVF_REG16((long)(base) + 0x00001014 +((x)*0x020))
+#define MVF_EDMA_TCD_CITER(base, x) MVF_REG16((long)(base) + 0x00001014 +((x)*0x020))
+#define MVF_EDMA_TCD_DOFF(base,x) MVF_REG16((long)(base) + 0x00001016 +((x)*0x020))
+#define MVF_EDMA_TCD_DLAST_SGA(base, x) MVF_REG32((long)(base) + 0x00001018 +((x)*0x020))
+#define MVF_EDMA_TCD_BITER_ELINK(base,x) MVF_REG16((long)(base) + 0x0000101C +((x)*0x020))
+#define MVF_EDMA_TCD_BITER(base, x) MVF_REG16((long)(base) + 0x0000101C +((x)*0x020))
+#define MVF_EDMA_TCD_CSR(base,x) MVF_REG16((long)(base) + 0x0000101e +((x)*0x020))
+
+/* Bit definitions and macros for CR */
+#define MVF_EDMA_CR_EDBG (0x00000002)
+#define MVF_EDMA_CR_ERCA (0x00000004)
+#define MVF_EDMA_CR_ERGA (0x00000008)
+#define MVF_EDMA_CR_HOE (0x00000010)
+#define MVF_EDMA_CR_HALT (0x00000020)
+#define MVF_EDMA_CR_CLM (0x00000040)
+#define MVF_EDMA_CR_EMLM (0x00000080)
+#define MVF_EDMA_CR_GRP0PRI(x) (((x)&0x03)<<8)
+#define MVF_EDMA_CR_GRP1PRI(x) (((x)&0x03)<<10)
+#define MVF_EDMA_CR_GRP2PRI(x) (((x)&0x03)<<12)
+#define MVF_EDMA_CR_GRP3PRI(x) (((x)&0x03)<<14)
+#define MVF_EDMA_CR_ECX (0x00010000)
+#define MVF_EDMA_CR_CX (0x00020000)
+
+/* Bit definitions and macros for ES */
+#define MVF_EDMA_ES_DBE (0x00000001)
+#define MVF_EDMA_ES_SBE (0x00000002)
+#define MVF_EDMA_ES_SGE (0x00000004)
+#define MVF_EDMA_ES_NCE (0x00000008)
+#define MVF_EDMA_ES_DOE (0x00000010)
+#define MVF_EDMA_ES_DAE (0x00000020)
+#define MVF_EDMA_ES_SOE (0x00000040)
+#define MVF_EDMA_ES_SAE (0x00000080)
+#define MVF_EDMA_ES_ERRCHN(x) (((x)&0x0000003F)<<8)
+#define MVF_EDMA_ES_CPE (0x00004000)
+#define MVF_EDMA_ES_GPE (0x00008000)
+#define MVF_EDMA_ES_ECX (0x00010000)
+#define MVF_EDMA_ES_VLD (0x80000000)
+
+/* Bit definitions and macros for ERQ: 0~63 bits */
+#define MVF_EDMA_ERQ_ERQH(x) (0x01<<x) /*32~63*/
+#define MVF_EDMA_ERQ_ERQL(x) (0x01<<x) /*0~31*/
+
+/* Bit definitions and macros for EEI: 0~63 bits */
+#define MVF_EDMA_EEI_EEIH(x) (0x01<<x) /*32~63*/
+#define MVF_EDMA_EEI_EEIL(x) (0x01<<x) /*0~31*/
+
+/* Bit definitions and macros for SERQ */
+#define MVF_EDMA_SERQ_SERQ(x) (((x)&0x3F))
+#define MVF_EDMA_SERQ_SAER (0x40)
+#define MVF_EDMA_SERQ_NOP (0x80)
+
+/* Bit definitions and macros for CERQ */
+#define MVF_EDMA_CERQ_CERQ(x) (((x)&0x3F))
+#define MVF_EDMA_CERQ_CAER (0x40)
+#define MVF_EDMA_CERQ_NOP (0x80)
+
+/* Bit definitions and macros for SEEI */
+#define MVF_EDMA_SEEI_SEEI(x) (((x)&0x3F))
+#define MVF_EDMA_SEEI_SAEE (0x40)
+#define MVF_EDMA_SEEI_NOP (0x80)
+
+/* Bit definitions and macros for CEEI */
+#define MVF_EDMA_CEEI_CEEI(x) (((x)&0x3F))
+#define MVF_EDMA_CEEI_CAEE (0x40)
+#define MVF_EDMA_CEEI_NOP (0x80)
+
+/* Bit definitions and macros for CINT */
+#define MVF_EDMA_CINT_CINT(x) (((x)&0x3F))
+#define MVF_EDMA_CINT_CAIR (0x40)
+#define MVF_EDMA_CINT_NOP (0x80)
+
+/* Bit definitions and macros for CERR */
+#define MVF_EDMA_CERR_CERR(x) (((x)&0x3F))
+#define MVF_EDMA_CERR_CAER (0x40)
+#define MVF_EDMA_CERR_NOP (0x80)
+
+/* Bit definitions and macros for SSRT */
+#define MVF_EDMA_SSRT_SSRT(x) (((x)&0x3F))
+#define MVF_EDMA_SSRT_SAST (0x40)
+#define MVF_EDMA_SSRT_NOP (0x80)
+
+/* Bit definitions and macros for CDNE */
+#define MVF_EDMA_CDNE_CDNE(x) (((x)&0x3F))
+#define MVF_EDMA_CDNE_CADN (0x40)
+#define MVF_EDMA_CDNE_NOP (0x80)
+
+/* Bit definitions and macros for INTR: 0~63 bits */
+#define MVF_EDMA_INTR_INTH(x) (0x01<<x) /*32~63*/
+#define MVF_EDMA_INTR_INTL(x) (0x01<<x) /*0~31*/
+
+/* Bit definitions and macros for ERR: 0~63 bits */
+#define MVF_EDMA_ERR_ERRH(x) (0x01<<x) /*32~63*/
+#define MVF_EDMA_ERR_ERRL(x) (0x01<<x) /*0~31*/
+
+/* Bit defineitions and macros for HRSH/HRSL */
+#define MVF_EDMA_HRS_HRSH(x) (0x01<<x) /*32~63*/
+#define MVF_EDMA_HRS_HRSL(x) (0x01<<x) /*0~31*/
+
+/* Bit definitions and macros for DCHPRI group */
+#define MVF_EDMA_DCHPRI_CHPRI(x) (((x)&0x0F))
+#define MVF_EDMA_DCHPRI_GRPPRI(x) (((x)&0x03) << 4)
+#define MVF_EDMA_DCHPRI_DPA (0x40)
+#define MVF_EDMA_DCHPRI_ECP (0x80)
+
+/* Bit definitions and macros for TCD_SADDR group */
+#define MVF_EDMA_TCD_SADDR_SADDR(x) (x)
+
+/* Bit definitions and macros for TCD_ATTR group */
+#define MVF_EDMA_TCD_ATTR_DSIZE(x) (((x)&0x0007))
+#define MVF_EDMA_TCD_ATTR_DMOD(x) (((x)&0x001F)<<3)
+#define MVF_EDMA_TCD_ATTR_SSIZE(x) (((x)&0x0007)<<8)
+#define MVF_EDMA_TCD_ATTR_SMOD(x) (((x)&0x001F)<<11)
+#define MVF_EDMA_TCD_ATTR_SSIZE_8BIT (0x0000)
+#define MVF_EDMA_TCD_ATTR_SSIZE_16BIT (0x0100)
+#define MVF_EDMA_TCD_ATTR_SSIZE_32BIT (0x0200)
+#define MVF_EDMA_TCD_ATTR_SSIZE_16BYTE (0x0400)
+#define MVF_EDMA_TCD_ATTR_DSIZE_8BIT (0x0000)
+#define MVF_EDMA_TCD_ATTR_DSIZE_16BIT (0x0001)
+#define MVF_EDMA_TCD_ATTR_DSIZE_32BIT (0x0002)
+#define MVF_EDMA_TCD_ATTR_DSIZE_16BYTE (0x0004)
+
+/* Bit definitions and macros for TCD_SOFF group */
+#define MVF_EDMA_TCD_SOFF_SOFF(x) (x)
+
+/* Bit definitions and macros for TCD_NBYTES group */
+#define MVF_EDMA_TCD_NBYTES_NBYTES(x) (x)
+#define MVF_EDMA_TCD_NBYTES_SMLOE (0x80000000)
+#define MVF_EDMA_TCD_NBYTES_DMLOE (0x40000000)
+#define MVF_EDMA_TCD_NBYTES_MLOFF(x) (((x)&0xFFFFF)<<20)
+#define MVF_EDMA_TCD_NBYTES_9BITS ((x)&0x1FF)
+
+/* Bit definitions and macros for TCD_SLAST group */
+#define MVF_EDMA_TCD_SLAST_SLAST(x) (x)
+
+/* Bit definitions and macros for TCD_DADDR group */
+#define MVF_EDMA_TCD_DADDR_DADDR(x) (x)
+
+/* Bit definitions and macros for TCD_CITER_ELINK group */
+#define MVF_EDMA_TCD_CITER_ELINK_CITER(x) (((x)&0x01FF))
+#define MVF_EDMA_TCD_CITER_ELINK_LINKCH(x) (((x)&0x003F)<<9)
+#define MVF_EDMA_TCD_CITER_ELINK_E_LINK (0x8000)
+
+/* Bit definitions and macros for TCD_CITER group */
+#define MVF_EDMA_TCD_CITER_CITER(x) (((x)&0x7FFF))
+#define MVF_EDMA_TCD_CITER_E_LINK (0x8000)
+
+/* Bit definitions and macros for TCD_DOFF group */
+#define MVF_EDMA_TCD_DOFF_DOFF(x) (x)
+
+/* Bit definitions and macros for TCD_DLAST_SGA group */
+#define MVF_EDMA_TCD_DLAST_SGA_DLAST_SGA(x) (x)
+
+/* Bit definitions and macros for TCD_BITER_ELINK group */
+#define MVF_EDMA_TCD_BITER_ELINK_BITER(x) (((x)&0x01FF))
+#define MVF_EDMA_TCD_BITER_ELINK_LINKCH(x) (((x)&0x003F)<<9)
+#define MVF_EDMA_TCD_BITER_ELINK_E_LINK (0x8000)
+
+/* Bit definitions and macros for TCD_BITER group */
+#define MVF_EDMA_TCD_BITER_BITER(x) (((x)&0x7FFF))
+#define MVF_EDMA_TCD_BITER_E_LINK (0x8000)
+
+/* Bit definitions and macros for TCD_CSR group */
+#define MVF_EDMA_TCD_CSR_START (0x0001)
+#define MVF_EDMA_TCD_CSR_INT_MAJOR (0x0002)
+#define MVF_EDMA_TCD_CSR_INT_HALF (0x0004)
+#define MVF_EDMA_TCD_CSR_D_REQ (0x0008)
+#define MVF_EDMA_TCD_CSR_E_SG (0x0010)
+#define MVF_EDMA_TCD_CSR_E_LINK (0x0020)
+#define MVF_EDMA_TCD_CSR_ACTIVE (0x0040)
+#define MVF_EDMA_TCD_CSR_DONE (0x0080)
+#define MVF_EDMA_TCD_CSR_LINKCH(x) (((x)&0x003F)<<8)
+#define MVF_EDMA_TCD_CSR_BWC(x) (((x)&0x0003)<<14)
+#define MVF_EDMA_TCD_CSR_BWC_NO_STALL (0x0000)
+#define MVF_EDMA_TCD_CSR_BWC_4CYC_STALL (0x8000)
+#define MVF_EDMA_TCD_CSR_BWC_8CYC_STALL (0xC000)
+
+/* Bit definitions and macros for TCD0_CSR */
+#define MVF_EDMA_TCD0_CSR_START (0x0001)
+#define MVF_EDMA_TCD0_CSR_INT_MAJOR (0x0002)
+#define MVF_EDMA_TCD0_CSR_INT_HALF (0x0004)
+#define MVF_EDMA_TCD0_CSR_D_REQ (0x0008)
+#define MVF_EDMA_TCD0_CSR_E_SG (0x0010)
+#define MVF_EDMA_TCD0_CSR_E_LINK (0x0020)
+#define MVF_EDMA_TCD0_CSR_ACTIVE (0x0040)
+#define MVF_EDMA_TCD0_CSR_DONE (0x0080)
+#define MVF_EDMA_TCD0_CSR_LINKCH(x) (((x)&0x003F)<<8)
+#define MVF_EDMA_TCD0_CSR_BWC(x) (((x)&0x0003)<<14)
+#define MVF_EDMA_TCD0_CSR_BWC_NO_STALL (0x0000)
+#define MVF_EDMA_TCD0_CSR_BWC_4CYC_STALL (0x8000)
+#define MVF_EDMA_TCD0_CSR_BWC_8CYC_STALL (0xC000)
+
+#endif
diff --git a/arch/arm/include/asm/mvf_switch.h b/arch/arm/include/asm/mvf_switch.h
new file mode 100644
index 000000000000..a9ddbfcd1635
--- /dev/null
+++ b/arch/arm/include/asm/mvf_switch.h
@@ -0,0 +1,619 @@
+/****************************************************************************/
+/*
+ * L2 switch Controller (Etheren switch) driver for VF600.
+ * based on L2 switch Controller for MCF5441x.
+ * processors.
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. 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
+ */
+
+/****************************************************************************/
+#ifndef MVF_SWITCH_H
+#define MVF_SWITCH_H
+/****************************************************************************/
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <asm/pgtable.h>
+
+/*
+ * Some hardware gets it MAC address out of local flash memory.
+ * if this is non-zero then assume it is the address to get MAC from.
+ */
+#define FEC_FLASHMAC 0
+
+#ifdef CONFIG_SWITCH_DMA_USE_SRAM
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+#else
+#define TX_RING_SIZE 16 /* Must be power of two */
+#define TX_RING_MOD_MASK 15 /* for this to work */
+#endif
+
+#define SWITCH_EPORT_NUMBER 2
+
+#define MVF_MII_SWITCH_SPEED 0x09
+
+
+// register offset for fec
+#define FEC_R_CNTRL 0x084 /* Receive control reg */
+#define FEC_X_CNTRL 0x0c4 /* Transmit Control reg */
+#define FEC_IEVENT 0x004 /* Interrupt event reg */
+#define FEC_IMASK 0x008
+#define FEC_MII_DATA 0x040 /* MII manage frame reg */
+#define FEC_MII_SPEED 0x044 /* MII speed control reg */
+#define FEC_ECNTRL 0x024 /* Ethernet control reg */
+
+/*-----------------------------------------------------------------------*/
+typedef struct l2switch_output_queue_status {
+ unsigned long ESW_MMSR;
+ unsigned long ESW_LMT;
+ unsigned long ESW_LFC;
+ unsigned long ESW_PCSR;
+ unsigned long ESW_IOSR;
+ unsigned long ESW_QWT;
+ unsigned long esw_reserved;
+ unsigned long ESW_P0BCT;
+} esw_output_queue_status;
+
+typedef struct l2switch_statistics_status {
+ /*
+ * Total number of incoming frames processed
+ * but discarded in switch
+ */
+ unsigned long ESW_DISCN;
+ /*Sum of bytes of frames counted in ESW_DISCN*/
+ unsigned long ESW_DISCB;
+ /*
+ * Total number of incoming frames processed
+ * but not discarded in switch
+ */
+ unsigned long ESW_NDISCN;
+ /*Sum of bytes of frames counted in ESW_NDISCN*/
+ unsigned long ESW_NDISCB;
+} esw_statistics_status;
+
+typedef struct l2switch_port_statistics_status {
+ /*outgoing frames discarded due to transmit queue congestion*/
+ unsigned long MCF_ESW_POQC;
+ /*incoming frames discarded due to VLAN domain mismatch*/
+ unsigned long MCF_ESW_PMVID;
+ /*incoming frames discarded due to untagged discard*/
+ unsigned long MCF_ESW_PMVTAG;
+ /*incoming frames discarded due port is in blocking state*/
+ unsigned long MCF_ESW_PBL;
+} esw_port_statistics_status;
+
+typedef struct l2switch {
+ // 0x00-0x34
+ unsigned long ESW_REVISION;
+ unsigned long ESW_SCRATCH;
+ unsigned long ESW_PER;
+ unsigned long reserved0[1];
+ unsigned long ESW_VLANV;
+ unsigned long ESW_DBCR;
+ unsigned long ESW_DMCR;
+ unsigned long ESW_BKLR;
+ unsigned long ESW_BMPC;
+ unsigned long ESW_MODE;
+ unsigned long ESW_VIMSEL;
+ unsigned long ESW_VOMSEL;
+ unsigned long ESW_VIMEN;
+ unsigned long ESW_VID;
+ /*from 0x38 0x3C*/
+ unsigned long esw_reserved0[2];
+ unsigned long ESW_MCR;/*0x40*/
+ unsigned long ESW_EGMAP;
+ unsigned long ESW_INGMAP;
+ unsigned long ESW_INGSAL;
+ unsigned long ESW_INGSAH;
+ unsigned long ESW_INGDAL;
+ unsigned long ESW_INGDAH;
+ unsigned long ESW_ENGSAL;
+ unsigned long ESW_ENGSAH;
+ unsigned long ESW_ENGDAL;
+ unsigned long ESW_ENGDAH;
+ unsigned long ESW_MCVAL;/*0x6C*/
+ /*from 0x70--0x7C*/
+ unsigned long esw_reserved1[4];
+ unsigned long ESW_MMSR;/*0x80*/
+ unsigned long ESW_LMT;
+ unsigned long ESW_LFC;
+ unsigned long ESW_PCSR;
+ unsigned long ESW_IOSR;
+ unsigned long ESW_QWT;/*0x94*/
+ unsigned long esw_reserved2[1];/*0x98*/
+ unsigned long ESW_P0BCT;/*0x9C*/
+ /*from 0xA0-0xB8*/
+ unsigned long esw_reserved3[7];
+ unsigned long ESW_P0FFEN;/*0xBC*/
+ /*MCF_ESW_PSNP(x) 0xFC0DC0C0+((x-1)*0x004))) 0xC0-0xDC*/
+ /*#define MCF_ESW_PSNP(x) \
+ (*(volatile unsigned long*)(0xFC0DC0C0+((x-1)*0x004)))*/
+ unsigned long ESW_PSNP[8];
+ /*MCF_ESW_IPSNP(x) 0xFC0DC0E0+((x-1)*0x004) 0xE0-0xFC*/
+ /*#define MCF_ESW_IPSNP(x) \
+ (*(volatile unsigned long*)(0xFC0DC0E0+((x-1)*0x004)))*/
+ unsigned long ESW_IPSNP[8];
+ /*port0-port2 VLAN Priority resolution map 0xFC0D_C100-C108*/
+ /*#define MCF_ESW_PVRES(x) \
+ (*(volatile unsigned long*)(0xFC0DC100+((x)*0x004)))*/
+ unsigned long ESW_PVRES[3];
+ /*from 0x10C-0x13C*/
+ unsigned long esw_reserved4[13];
+ unsigned long ESW_IPRES;/*0x140*/
+ /*from 0x144-0x17C*/
+ unsigned long esw_reserved5[15];
+
+ /*port0-port2 Priority Configuration 0xFC0D_C180-C188*/
+ /*#define MCF_ESW_PRES(x) \
+ (*(volatile unsigned long*)(0xFC0DC180+((x)*0x004)))*/
+ unsigned long ESW_PRES[3];
+ /*from 0x18C-0x1FC*/
+ unsigned long esw_reserved6[29];
+
+ /*port0-port2 VLAN ID 0xFC0D_C200-C208*/
+ /*#define MCF_ESW_PID(x) \
+ (*(volatile unsigned long*)(0xFC0DC200+((x)*0x004)))*/
+ unsigned long ESW_PID[3];
+ /*from 0x20C-0x27C*/
+ unsigned long esw_reserved7[29];
+
+ /*port0-port2 VLAN domain resolution entry 0xFC0D_C280-C2FC*/
+ /*#define MCF_ESW_VRES(x) \
+ (*(volatile unsigned long*)(0xFC0DC280+((x)*0x004)))*/
+ unsigned long ESW_VRES[32];
+
+ unsigned long ESW_DISCN;/*0x300*/
+ unsigned long ESW_DISCB;
+ unsigned long ESW_NDISCN;
+ unsigned long ESW_NDISCB;/*0xFC0DC30C*/
+ /*per port statistics 0xFC0DC310_C33C*/
+ /*#define MCF_ESW_POQC(x) \
+ (*(volatile unsigned long*)(0xFC0DC310+((x)*0x010)))
+ #define MCF_ESW_PMVID(x) \
+ (*(volatile unsigned long*)(0xFC0DC314+((x)*0x010)))
+ #define MCF_ESW_PMVTAG(x) \
+ (*(volatile unsigned long*)(0xFC0DC318+((x)*0x010)))
+ #define MCF_ESW_PBL(x) \
+ (*(volatile unsigned long*)(0xFC0DC31C+((x)*0x010)))
+ */
+ esw_port_statistics_status port_statistics_status[3];
+ /*from 0x340-0x400*/
+ unsigned long esw_reserved8[48];
+
+ /*0xFC0DC400---0xFC0DC418*/
+ /*unsigned long MCF_ESW_ISR;*/
+ unsigned long switch_ievent; /* Interrupt event reg */
+ /*unsigned long MCF_ESW_IMR;*/
+ unsigned long switch_imask; /* Interrupt mask reg */
+ /*unsigned long MCF_ESW_RDSR;*/
+ unsigned long fec_r_des_start; /* Receive descriptor ring */
+ /*unsigned long MCF_ESW_TDSR;*/
+ unsigned long fec_x_des_start; /* Transmit descriptor ring */
+ /*unsigned long MCF_ESW_MRBR;*/
+ unsigned long fec_r_buff_size; /* Maximum receive buff size */
+ /*unsigned long MCF_ESW_RDAR;*/
+ unsigned long fec_r_des_active; /* Receive descriptor reg */
+ /*unsigned long MCF_ESW_TDAR;*/
+ unsigned long fec_x_des_active; /* Transmit descriptor reg */
+ /*from 0x420-0x4FC*/
+ unsigned long esw_reserved9[57];
+
+ /*0xFC0DC500---0xFC0DC508*/
+ unsigned long ESW_LREC0;
+ unsigned long ESW_LREC1;
+ unsigned long ESW_LSR;
+} switch_t;
+
+typedef struct _64bTableEntry {
+ unsigned int lo; /* lower 32 bits */
+ unsigned int hi; /* upper 32 bits */
+} AddrTable64bEntry;
+
+typedef struct l2switchaddrtable {
+ AddrTable64bEntry eswTable64bEntry[2048];
+} eswAddrTable_t;
+
+
+#define MCF_FEC_RCR_PROM (0x00000008)
+#define MCF_FEC_RCR_RMII_MODE (0x00000100)
+#define MCF_FEC_RCR_MAX_FL(x) (((x)&0x00003FFF)<<16)
+#define MCF_FEC_RCR_CRC_FWD (0x00004000)
+#define MCF_FEC_TCR_FDEN (0x00000004)
+#define MCF_FEC_ECR_ETHER_EN (0x00000002)
+#define MCF_FEC_ECR_ENA_1588 (0x00000010)
+
+typedef struct _eswIOCTL_PORT_CONF {
+ int port;
+ int enable;
+} eswIoctlPortConfig;
+
+typedef struct _eswIOCTL_PORT_EN_CONF {
+ int port;
+ int tx_enable;
+ int rx_enable;
+} eswIoctlPortEnableConfig;
+
+typedef struct _eswIOCTL_IP_SNOOP_CONF {
+ int mode;
+ unsigned long ip_header_protocol;
+} eswIoctlIpsnoopConfig;
+
+typedef struct _eswIOCTL_P0_FORCED_FORWARD_CONF {
+ int port1;
+ int port2;
+ int enable;
+} eswIoctlP0ForcedForwardConfig;
+
+typedef struct _eswIOCTL_PORT_SNOOP_CONF {
+ int mode;
+ unsigned short compare_port;
+ int compare_num;
+} eswIoctlPortsnoopConfig;
+
+typedef struct _eswIOCTL_PORT_Mirror_CONF {
+ int mirror_port;
+ int port;
+ int egress_en;
+ int ingress_en;
+ int egress_mac_src_en;
+ int egress_mac_des_en;
+ int ingress_mac_src_en;
+ int ingress_mac_des_en;
+ unsigned char *src_mac;
+ unsigned char *des_mac;
+ int mirror_enable;
+} eswIoctlPortMirrorConfig;
+
+struct eswIoctlMirrorCfgPortMatch {
+ int mirror_port;
+ int port_match_en;
+ int port;
+};
+
+struct eswIoctlMirrorCfgAddrMatch {
+ int mirror_port;
+ int addr_match_en;
+ unsigned char *mac_addr;
+};
+
+typedef struct _eswIOCTL_PRIORITY_VLAN_CONF {
+ int port;
+ int func_enable;
+ int vlan_pri_table_num;
+ int vlan_pri_table_value;
+} eswIoctlPriorityVlanConfig;
+
+typedef struct _eswIOCTL_PRIORITY_IP_CONF {
+ int port;
+ int func_enable;
+ int ipv4_en;
+ int ip_priority_num;
+ int ip_priority_value;
+} eswIoctlPriorityIPConfig;
+
+typedef struct _eswIOCTL_PRIORITY_MAC_CONF {
+ int port;
+} eswIoctlPriorityMacConfig;
+
+typedef struct _eswIOCTL_PRIORITY_DEFAULT_CONF {
+ int port;
+ unsigned char priority_value;
+} eswIoctlPriorityDefaultConfig;
+
+typedef struct _eswIOCTL_IRQ_STATUS {
+ unsigned long isr;
+ unsigned long imr;
+ unsigned long rx_buf_pointer;
+ unsigned long tx_buf_pointer;
+ unsigned long rx_max_size;
+ unsigned long rx_buf_active;
+ unsigned long tx_buf_active;
+} eswIoctlIrqStatus;
+
+typedef struct _eswIOCTL_PORT_Mirror_STATUS {
+ unsigned long ESW_MCR;
+ unsigned long ESW_EGMAP;
+ unsigned long ESW_INGMAP;
+ unsigned long ESW_INGSAL;
+ unsigned long ESW_INGSAH;
+ unsigned long ESW_INGDAL;
+ unsigned long ESW_INGDAH;
+ unsigned long ESW_ENGSAL;
+ unsigned long ESW_ENGSAH;
+ unsigned long ESW_ENGDAL;
+ unsigned long ESW_ENGDAH;
+ unsigned long ESW_MCVAL;
+} eswIoctlPortMirrorStatus;
+
+typedef struct _eswIOCTL_VLAN_OUTPUT_CONF {
+ int port;
+ int mode;
+} eswIoctlVlanOutputConfig;
+
+typedef struct _eswIOCTL_VLAN_INPUT_CONF {
+ int port;
+ int mode;
+ unsigned short port_vlanid;
+} eswIoctlVlanInputConfig;
+
+typedef struct _eswIOCTL_VLAN_DOMAIN_VERIFY_CONF {
+ int port;
+ int vlan_domain_verify_en;
+ int vlan_discard_unknown_en;
+} eswIoctlVlanVerificationConfig;
+
+typedef struct _eswIOCTL_VLAN_RESOULATION_TABLE {
+ unsigned short port_vlanid;
+ unsigned char vlan_domain_port;
+ unsigned char vlan_domain_num;
+} eswIoctlVlanResoultionTable;
+
+struct eswVlanTableItem {
+ eswIoctlVlanResoultionTable table[32];
+ unsigned char valid_num;
+};
+
+typedef struct _eswIOCTL_VLAN_INPUT_STATUS {
+ unsigned long ESW_VLANV;
+ unsigned long ESW_PID[3];
+ unsigned long ESW_VIMSEL;
+ unsigned long ESW_VIMEN;
+ unsigned long ESW_VRES[32];
+} eswIoctlVlanInputStatus;
+
+typedef struct _eswIOCTL_Static_MACTable {
+ unsigned char *mac_addr;
+ int port;
+ int priority;
+} eswIoctlUpdateStaticMACtable;
+
+typedef struct _eswIOCTL_OUTPUT_QUEUE{
+ int fun_num;
+ esw_output_queue_status sOutputQueue;
+} eswIoctlOutputQueue;
+/*
+ * Info received from Hardware Learning FIFO,
+ * holding MAC address and corresponding Hash Value and
+ * port number where the frame was received (disassembled).
+ */
+typedef struct _eswPortInfo {
+ /* MAC lower 32 bits (first byte is 7:0). */
+ unsigned int maclo;
+ /* MAC upper 16 bits (47:32). */
+ unsigned int machi;
+ /* the hash value for this MAC address. */
+ unsigned int hash;
+ /* the port number this MAC address is associated with. */
+ unsigned int port;
+} eswPortInfo;
+
+/*
+ * Hardware Look up Address Table 64-bit element.
+ */
+typedef volatile struct _64bitTableEntry {
+ unsigned int lo; /* lower 32 bits */
+ unsigned int hi; /* upper 32 bits */
+} eswTable64bitEntry;
+
+struct eswAddrTableEntryExample {
+ /* the entry number */
+ unsigned short entrynum;
+ /* mac address array */
+ unsigned char mac_addr[6];
+ unsigned char item1;
+ unsigned short item2;
+};
+
+/*
+ * Define the buffer descriptor structure.
+ */
+#if defined(CONFIG_ARCH_MXC)
+typedef struct bufdesc {
+ unsigned short cbd_datlen; /* Data length */
+ unsigned short cbd_sc; /* Control and status info */
+ unsigned long cbd_bufaddr; /* Buffer address */
+#if defined(CONFIG_FEC_1588)
+ unsigned long ebd_status;
+ unsigned long cbd_prot;
+ unsigned long bdu;
+ unsigned long timestamp;
+ unsigned long reserverd_word1;
+ unsigned long reserverd_word2;
+#endif
+} cbd_t;
+#else
+typedef struct bufdesc {
+ unsigned short cbd_sc; /* Control and status info */
+ unsigned short cbd_datlen; /* Data length */
+ unsigned long cbd_bufaddr; /* Buffer address */
+#if defined(CONFIG_FEC_1588)
+ unsigned long ebd_status;
+ unsigned short length_proto_type;
+ unsigned short payload_checksum;
+ unsigned long bdu;
+ unsigned long timestamp;
+ unsigned long reserverd_word1;
+ unsigned long reserverd_word2;
+#endif
+} cbd_t;
+#endif
+
+/* Forward declarations of some structures to support different PHYs
+ */
+typedef struct {
+ uint mii_data;
+ void (*funct)(uint mii_reg, struct net_device *dev);
+} phy_cmd_t;
+
+typedef struct {
+ uint id;
+ char *name;
+
+ const phy_cmd_t *config;
+ const phy_cmd_t *startup;
+ const phy_cmd_t *ack_int;
+ const phy_cmd_t *shutdown;
+} phy_info_t;
+
+struct port_status {
+ /* 1: link is up, 0: link is down */
+ int port1_link_status;
+ int port2_link_status;
+ /* 1: blocking, 0: unblocking */
+ int port0_block_status;
+ int port1_block_status;
+ int port2_block_status;
+};
+
+struct port_all_status {
+ /* 1: link is up, 0: link is down */
+ int link_status;
+ /* 1: blocking, 0: unblocking */
+ int block_status;
+ /* 1: unlearning, 0: learning */
+ int learn_status;
+ /* vlan domain verify 1: enable 0: disable */
+ int vlan_verify;
+ /* discard unknow 1: enable 0: disable */
+ int discard_unknown;
+ /* multicast resolution 1: enable 0: disable */
+ int multi_reso;
+ /* broadcast resolution 1: enable 0: disalbe */
+ int broad_reso;
+ /* transmit 1: enable 0: disable */
+ int ftransmit;
+ /* receive 1: enable 0: disable */
+ int freceive;
+};
+
+/* The switch buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct switch_enet_private {
+ /* Hardware registers of the switch device */
+ volatile switch_t *hwp;
+ volatile eswAddrTable_t *hwentry;
+
+ void __iomem *fec[2];
+
+ struct net_device *netdev;
+ struct platform_device *pdev;
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ unsigned char *tx_bounce[TX_RING_SIZE];
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ uint tx_full;
+ /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
+ spinlock_t hw_lock;
+
+ /* hold while accessing the mii_list_t() elements */
+ spinlock_t mii_lock;
+ struct mii_bus *mdio_bus;
+ struct phy_device *phydev[SWITCH_EPORT_NUMBER];
+
+ uint phy_id;
+ uint phy_id_done;
+ uint phy_status;
+ uint phy_speed;
+ phy_info_t const *phy;
+ struct work_struct phy_task;
+ volatile switch_t *phy_hwp;
+
+ uint sequence_done;
+ uint mii_phy_task_queued;
+
+ uint phy_addr;
+
+ int index;
+ int opened;
+ int full_duplex;
+ int msg_enable;
+ int phy1_link;
+ int phy1_old_link;
+ int phy1_duplex;
+ int phy1_speed;
+
+ int phy2_link;
+ int phy2_old_link;
+ int phy2_duplex;
+ int phy2_speed;
+ /* --------------Statistics--------------------------- */
+ /* when a new element deleted a element with in
+ * a block due to lack of space */
+ int atBlockOverflows;
+ /* Peak number of valid entries in the address table */
+ int atMaxEntries;
+ /* current number of valid entries in the address table */
+ int atCurrEntries;
+ /* maximum entries within a block found
+ * (updated within ageing)*/
+ int atMaxEntriesPerBlock;
+
+ /* -------------------ageing function------------------ */
+ /* maximum age allowed for an entry */
+ int ageMax;
+ /* last LUT entry to block that was
+ * inspected by the Ageing task*/
+ int ageLutIdx;
+ /* last element within block inspected by the Ageing task */
+ int ageBlockElemIdx;
+ /* complete table has been processed by ageing process */
+ int ageCompleted;
+ /* delay setting */
+ int ageDelay;
+ /* current delay Counter */
+ int ageDelayCnt;
+
+ /* ----------------timer related---------------------------- */
+ /* current time (for timestamping) */
+ int currTime;
+ /* flag set by timer when currTime changed
+ * and cleared by serving function*/
+ int timeChanged;
+
+ /**/
+ /* Timer for Aging */
+ struct timer_list timer_aging;
+ int learning_irqhandle_enable;
+};
+
+struct switch_platform_private {
+ struct platform_device *pdev;
+
+ unsigned long quirks;
+ int num_slots; /* Slots on controller */
+ struct switch_enet_private *fep_host[0]; /* Pointers to hosts */
+};
+#endif
diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile
index a96c70307259..1362c8551aea 100644
--- a/arch/arm/mach-mvf/Makefile
+++ b/arch/arm/mach-mvf/Makefile
@@ -6,3 +6,4 @@
obj-y := cpu.o mm.o devices.o irq.o clock.o bus_freq.o system.o mvf_fec.o
obj-$(CONFIG_MACH_TWR_VF600) += board-twr_vf600.o
+obj-$(CONFIG_MVF_ETHER_SWITCH) += l2switch.o
diff --git a/arch/arm/mach-mvf/l2switch.c b/arch/arm/mach-mvf/l2switch.c
new file mode 100644
index 000000000000..06599fb8cd04
--- /dev/null
+++ b/arch/arm/mach-mvf/l2switch.c
@@ -0,0 +1,327 @@
+/*
+ * l2switch.c
+ *
+ * Sub-architcture dependant initialization code for the Freescale
+ * MVF family L2 Switch module.
+ *
+ * based on 5441X.
+ *
+ * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * ShrekWu B16972@freescale.com
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/traps.h>
+#include <asm/mvf_switch.h>
+
+#if (defined(CONFIG_SOC_IMX28) || defined(CONFIG_ARCH_MX6)) || defined(CONFIG_ARCH_MVF) \
+ && defined(CONFIG_FEC_1588)
+#define CONFIG_ENHANCED_BD
+#endif
+
+
+// base address
+#define FEC_ETH0 0x400D0000
+#define FEC_ETH1 0x400D1000
+#define L2SWITCH_1 0x400E8000
+
+#pragma message "need fix!!!!! L2SWITCH_ATBL"
+#define L2SWITCH_ATBL 0x400F0000
+
+static unsigned char switch_mac_default[] = {
+ 0x00, 0x04, 0x9F, 0x00, 0xB3, 0x49,
+};
+
+static unsigned char switch_mac_addr[6];
+
+static void switch_request_intrs(struct net_device *dev,
+ irqreturn_t switch_net_irq_handler(int irq, void *private),
+ void *irq_privatedata)
+{
+ struct switch_enet_private *fep;
+ int b;
+ static const struct idesc {
+ char *name;
+ unsigned short irq;
+ } *idp, id[] = {
+ /*{ "esw_isr(EBERR)", 38 },*/
+ { "esw_isr(RxBuffer)", 39 },
+ { "esw_isr(RxFrame)", 40 },
+ { "esw_isr(TxBuffer)", 41 },
+ { "esw_isr(TxFrame)", 42 },
+ { "esw_isr(QM)", 43 },
+ { "esw_isr(P0OutputDiscard)", 44 },
+ { "esw_isr(P1OutputDiscard)", 45 },
+ { "esw_isr(P2OutputDiscard)", 46 },
+ { "esw_isr(LearningRecord)", 47 },
+ { NULL },
+ };
+
+ fep = netdev_priv(dev);
+ /*intrruption L2 ethernet SWITCH */
+ b = 64 + 64 + 64;
+
+ /* Setup interrupt handlers. */
+ for (idp = id; idp->name; idp++) {
+ if (request_irq(b+idp->irq,
+ switch_net_irq_handler, IRQF_DISABLED,
+ idp->name, irq_privatedata) != 0)
+ printk(KERN_ERR "FEC: Could not alloc %s IRQ(%d)!\n",
+ idp->name, b+idp->irq);
+ }
+
+ /* Configure RMII */
+// #if 0
+// // set in u-boot
+// MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
+// MCF_GPIO_PAR_FEC_FEC_MASK) |
+// MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
+//
+// MCF_GPIO_PAR_FEC =
+// (MCF_GPIO_PAR_FEC &
+// MCF_GPIO_PAR_FEC_FEC_MASK) |
+// MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
+//
+// MCF_GPIO_SRCR_FEC = 0x0F;
+//
+// MCF_GPIO_PAR_SIMP0H =
+// (MCF_GPIO_PAR_SIMP0H &
+// MCF_GPIO_PAR_SIMP0H_DAT_MASK) |
+// MCF_GPIO_PAR_SIMP0H_DAT_GPIO;
+//
+// MCF_GPIO_PDDR_G =
+// (MCF_GPIO_PDDR_G &
+// MCF_GPIO_PDDR_G4_MASK) |
+// MCF_GPIO_PDDR_G4_OUTPUT;
+//
+// MCF_GPIO_PODR_G =
+// (MCF_GPIO_PODR_G &
+// MCF_GPIO_PODR_G4_MASK);
+// #endif
+}
+
+static void switch_set_mii(struct net_device *dev)
+{
+ struct switch_enet_private *fep = netdev_priv(dev);
+ volatile switch_t *fecp;
+
+// #if 0
+// fecp = fep->hwp;
+//
+// MCF_FEC_RCR0 = (MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
+// MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD);
+// MCF_FEC_RCR1 = (MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
+// MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD);
+// /* TCR */
+// MCF_FEC_TCR0 = MCF_FEC_TCR_FDEN;
+// MCF_FEC_TCR1 = MCF_FEC_TCR_FDEN;
+// /* ECR */
+// #ifdef ENHANCE_BUFFER
+// MCF_FEC_ECR0 = MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588;
+// MCF_FEC_ECR1 = MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588;
+// #else /*legac buffer*/
+// MCF_FEC_ECR0 = MCF_FEC_ECR_ETHER_EN;
+// MCF_FEC_ECR1 = MCF_FEC_ECR_ETHER_EN;
+// #endif
+// /*
+// * Set MII speed to 2.5 MHz
+// */
+// MCF_FEC_MSCR0 = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
+// MCF_FEC_MSCR1 = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
+// #endif
+//
+
+ writel((MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE | MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD), fep->fec[0] + FEC_R_CNTRL);
+ writel((MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE | MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD), fep->fec[1] + FEC_R_CNTRL);
+
+ writel(MCF_FEC_TCR_FDEN, fep->fec[0] + FEC_X_CNTRL);
+ writel(MCF_FEC_TCR_FDEN, fep->fec[1] + FEC_X_CNTRL);
+
+#ifdef CONFIG_ENHANCED_BD
+ writel(MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588, fep->fec[0] + FEC_ECNTRL);
+ writel(MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588, fep->fec[1] + FEC_ECNTRL);
+#else
+ writel(MCF_FEC_ECR_ETHER_EN , fep->fec[0] + FEC_ECNTRL);
+ writel(MCF_FEC_ECR_ETHER_EN , fep->fec[1] + FEC_ECNTRL);
+#endif
+ writel( MVF_MII_SWITCH_SPEED, fep->fec[0] + FEC_MII_SPEED);
+ writel( MVF_MII_SWITCH_SPEED, fep->fec[1] + FEC_MII_SPEED);
+
+}
+
+static void switch_get_mac(struct net_device *dev)
+{
+ struct switch_enet_private *fep = netdev_priv(dev);
+ volatile switch_t *fecp;
+ unsigned char *iap;
+
+ fecp = fep->hwp;
+
+ if (FEC_FLASHMAC) {
+ /*
+ * Get MAC address from FLASH.
+ * If it is all 1's or 0's, use the default.
+ */
+ iap = FEC_FLASHMAC;
+ if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
+ (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
+ iap = switch_mac_default;
+ if ((iap[0] == 0xff) && (iap[1] == 0xff) &&
+ (iap[2] == 0xff) && (iap[3] == 0xff) &&
+ (iap[4] == 0xff) && (iap[5] == 0xff))
+ iap = switch_mac_default;
+
+ } else {
+ iap = &switch_mac_addr[0];
+
+ if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
+ (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
+ iap = switch_mac_default;
+ if ((iap[0] == 0xff) && (iap[1] == 0xff) &&
+ (iap[2] == 0xff) && (iap[3] == 0xff) &&
+ (iap[4] == 0xff) && (iap[5] == 0xff))
+ iap = switch_mac_default;
+ }
+
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
+ /* Adjust MAC if using default MAC address */
+ if (iap == switch_mac_default)
+ dev->dev_addr[ETH_ALEN-1] = switch_mac_default[ETH_ALEN-1] +
+ fep->index;
+}
+
+static void switch_enable_phy_intr(void)
+{
+}
+
+static void switch_disable_phy_intr(void)
+{
+}
+
+static void switch_phy_ack_intr(void)
+{
+}
+
+static void switch_localhw_setup(void)
+{
+}
+
+static void switch_uncache(unsigned long addr)
+{
+}
+
+static void switch_platform_flush_cache(void)
+{
+}
+
+/*
+ * Define the fixed address of the FEC hardware.
+ */
+static unsigned int switch_platform_hw[] = {
+ L2SWITCH_1,
+ L2SWITCH_ATBL,
+};
+
+static unsigned int fec_platform_hw[] = {
+ FEC_ETH0,
+ FEC_ETH1,
+};
+
+static struct mvf_switch_platform_data mvf_switch_data = {
+ .hash_table = 0,
+ .fec_hw = fec_platform_hw,
+ .switch_hw = switch_platform_hw,
+ .request_intrs = switch_request_intrs,
+ .set_mii = switch_set_mii,
+ .get_mac = switch_get_mac,
+ .enable_phy_intr = switch_enable_phy_intr,
+ .disable_phy_intr = switch_disable_phy_intr,
+ .phy_ack_intr = switch_phy_ack_intr,
+ .localhw_setup = switch_localhw_setup,
+ .uncache = switch_uncache,
+ .platform_flush_cache = switch_platform_flush_cache,
+};
+
+// non-used-structure
+static struct resource l2switch_resources[] = {
+ [0] = {
+ .start = 0xFC0DC000,
+ .end = 0xFC0DC508,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = (64 + 64 + 64 + 38),
+ .end = (64 + 64 + 64 + 48),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = 0xFC0E0000,
+ .end = 0xFC0E3FFC,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device l2switch_mvf_device = {
+ .name = "mvf-switch",
+ .id = 0,
+ .resource = l2switch_resources,
+ .num_resources = ARRAY_SIZE(l2switch_resources),
+ .dev = {
+ .platform_data = &mvf_switch_data,
+ .coherent_dma_mask = ~0, /* $$$ REVISIT */
+ }
+};
+
+
+static int __init mvf_switch_dev_init(void)
+{
+ int retval = 0;
+
+ retval = platform_device_register(&l2switch_mvf_device);
+
+ if (retval < 0) {
+ printk(KERN_ERR "MVF L2Switch: platform_device_register"
+ " failed with code=%d\n", retval);
+ }
+
+ return retval;
+}
+
+static int __init param_switch_addr_setup(char *str)
+{
+ char *end;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ switch_mac_addr[i] = str ? simple_strtoul(str, &end, 16) : 0;
+ if (str)
+ str = (*end ) ? end + 1 : end;
+ }
+ return 0;
+}
+__setup("switchaddr=", param_switch_addr_setup);
+
+arch_initcall(mvf_switch_dev_init);
diff --git a/arch/arm/mach-mvf/mm.c b/arch/arm/mach-mvf/mm.c
index 62afa4ab92d3..8ad09f606888 100644
--- a/arch/arm/mach-mvf/mm.c
+++ b/arch/arm/mach-mvf/mm.c
@@ -31,7 +31,7 @@
#include <asm/hardware/cache-l2x0.h>
/*!
- * This structure defines the Faraday memory map.
+ * This structure defines the MVF memory map.
*/
static struct map_desc mvf_io_desc[] __initdata = {
imx_map_entry(MVF, AIPS0, MT_DEVICE),
diff --git a/arch/arm/mach-mvf/mvf_fec.c b/arch/arm/mach-mvf/mvf_fec.c
index 83a92feac2dc..009dbc168a96 100644
--- a/arch/arm/mach-mvf/mvf_fec.c
+++ b/arch/arm/mach-mvf/mvf_fec.c
@@ -33,12 +33,15 @@ static int fec_get_mac_addr(unsigned char *mac)
{
unsigned int value;
- value = readl(MVF_IO_ADDRESS(MVF_OTP_CTRL_BASE_ADDR) + HW_OCOTP_MACn(0));
+#if 1
+ value = 0x01;
+#endif
+ //value = readl(MVF_IO_ADDRESS(MVF_OTP_CTRL_BASE_ADDR) + HW_OCOTP_MACn(0));
mac[5] = value & 0xff;
mac[4] = (value >> 8) & 0xff;
mac[3] = (value >> 16) & 0xff;
mac[2] = (value >> 24) & 0xff;
- value = readl(MVF_IO_ADDRESS(MVF_OTP_CTRL_BASE_ADDR) + HW_OCOTP_MACn(1));
+ //value = readl(MVF_IO_ADDRESS(MVF_OTP_CTRL_BASE_ADDR) + HW_OCOTP_MACn(1));
mac[1] = value & 0xff;
mac[0] = (value >> 8) & 0xff;