diff options
author | yagi <yagi@ke66.alps.lineo.co.jp> | 2012-06-08 19:46:53 +0900 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-07-03 17:15:09 -0400 |
commit | ca1aae2ad0eac8089afebf56da2fdaebd8580213 (patch) | |
tree | e4d126af0204940239f23f63af7bbd6f94e3e533 /arch | |
parent | abc9338fc082ace655c6d418adc5021a53900b84 (diff) |
add: FEC & eDMA
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/mvf_edma.h | 188 | ||||
-rw-r--r-- | arch/arm/include/asm/mvf_edma_regs.h | 313 | ||||
-rw-r--r-- | arch/arm/include/asm/mvf_switch.h | 619 | ||||
-rw-r--r-- | arch/arm/mach-mvf/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-mvf/l2switch.c | 327 | ||||
-rw-r--r-- | arch/arm/mach-mvf/mm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-mvf/mvf_fec.c | 7 |
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; |