diff options
author | Maxime Bizon <mbizon@freebox.fr> | 2013-06-04 17:53:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-10 17:28:28 -0400 |
commit | 6f00a0229627ca189529cad3f9154ac2f9e5c7db (patch) | |
tree | 20b010b5faa5fca26951f3f3575da92a9cf317fc /arch/mips | |
parent | 0ae99b5fede6f3a8d252d50bb4aba29544295219 (diff) |
bcm63xx_enet: add support for Broadcom BCM63xx integrated gigabit switch
Newer Broadcom BCM63xx SoCs: 6328, 6362 and 6368 have an integrated switch
which needs to be driven slightly differently from the traditional
external switches. This patch introduces changes in arch/mips/bcm63xx in order
to:
- register a bcm63xx_enetsw driver instead of bcm63xx_enet driver
- update DMA channels configuration & state RAM base addresses
- add a new platform data configuration knob to define the number of
ports per switch/device and force link on some ports
- define the required switch registers
On the driver side, the following changes are required:
- the switch ports need to be polled to ensure the link is up and
running and RX/TX can properly work
- basic switch configuration needs to be performed for the switch to
forward packets to the CPU
- update the MIB counters since the integrated
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 | ||||
-rw-r--r-- | arch/mips/bcm63xx/dev-enet.c | 113 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 28 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 50 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 2 |
5 files changed, 179 insertions, 18 deletions
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index a9505c4867e8..9c0ddafafb6c 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c | |||
@@ -845,6 +845,10 @@ int __init board_register_devices(void) | |||
845 | !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr)) | 845 | !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr)) |
846 | bcm63xx_enet_register(1, &board.enet1); | 846 | bcm63xx_enet_register(1, &board.enet1); |
847 | 847 | ||
848 | if (board.has_enetsw && | ||
849 | !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr)) | ||
850 | bcm63xx_enetsw_register(&board.enetsw); | ||
851 | |||
848 | if (board.has_usbd) | 852 | if (board.has_usbd) |
849 | bcm63xx_usbd_register(&board.usbd); | 853 | bcm63xx_usbd_register(&board.usbd); |
850 | 854 | ||
diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c index df5bf6686942..6cbaee0f6d70 100644 --- a/arch/mips/bcm63xx/dev-enet.c +++ b/arch/mips/bcm63xx/dev-enet.c | |||
@@ -104,6 +104,64 @@ static struct platform_device bcm63xx_enet1_device = { | |||
104 | }, | 104 | }, |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static struct resource enetsw_res[] = { | ||
108 | { | ||
109 | /* start & end filled at runtime */ | ||
110 | .flags = IORESOURCE_MEM, | ||
111 | }, | ||
112 | { | ||
113 | /* start filled at runtime */ | ||
114 | .flags = IORESOURCE_IRQ, | ||
115 | }, | ||
116 | { | ||
117 | /* start filled at runtime */ | ||
118 | .flags = IORESOURCE_IRQ, | ||
119 | }, | ||
120 | }; | ||
121 | |||
122 | static struct bcm63xx_enetsw_platform_data enetsw_pd; | ||
123 | |||
124 | static struct platform_device bcm63xx_enetsw_device = { | ||
125 | .name = "bcm63xx_enetsw", | ||
126 | .num_resources = ARRAY_SIZE(enetsw_res), | ||
127 | .resource = enetsw_res, | ||
128 | .dev = { | ||
129 | .platform_data = &enetsw_pd, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static int __init register_shared(void) | ||
134 | { | ||
135 | int ret, chan_count; | ||
136 | |||
137 | if (shared_device_registered) | ||
138 | return 0; | ||
139 | |||
140 | shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); | ||
141 | shared_res[0].end = shared_res[0].start; | ||
142 | shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; | ||
143 | |||
144 | if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) | ||
145 | chan_count = 32; | ||
146 | else | ||
147 | chan_count = 16; | ||
148 | |||
149 | shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); | ||
150 | shared_res[1].end = shared_res[1].start; | ||
151 | shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1; | ||
152 | |||
153 | shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); | ||
154 | shared_res[2].end = shared_res[2].start; | ||
155 | shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1; | ||
156 | |||
157 | ret = platform_device_register(&bcm63xx_enet_shared_device); | ||
158 | if (ret) | ||
159 | return ret; | ||
160 | shared_device_registered = 1; | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
107 | int __init bcm63xx_enet_register(int unit, | 165 | int __init bcm63xx_enet_register(int unit, |
108 | const struct bcm63xx_enet_platform_data *pd) | 166 | const struct bcm63xx_enet_platform_data *pd) |
109 | { | 167 | { |
@@ -117,24 +175,9 @@ int __init bcm63xx_enet_register(int unit, | |||
117 | if (unit == 1 && BCMCPU_IS_6338()) | 175 | if (unit == 1 && BCMCPU_IS_6338()) |
118 | return -ENODEV; | 176 | return -ENODEV; |
119 | 177 | ||
120 | if (!shared_device_registered) { | 178 | ret = register_shared(); |
121 | shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); | 179 | if (ret) |
122 | shared_res[0].end = shared_res[0].start; | 180 | return ret; |
123 | shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; | ||
124 | |||
125 | shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); | ||
126 | shared_res[1].end = shared_res[1].start; | ||
127 | shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1; | ||
128 | |||
129 | shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); | ||
130 | shared_res[2].end = shared_res[2].start; | ||
131 | shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1; | ||
132 | |||
133 | ret = platform_device_register(&bcm63xx_enet_shared_device); | ||
134 | if (ret) | ||
135 | return ret; | ||
136 | shared_device_registered = 1; | ||
137 | } | ||
138 | 181 | ||
139 | if (unit == 0) { | 182 | if (unit == 0) { |
140 | enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0); | 183 | enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0); |
@@ -175,3 +218,37 @@ int __init bcm63xx_enet_register(int unit, | |||
175 | return ret; | 218 | return ret; |
176 | return 0; | 219 | return 0; |
177 | } | 220 | } |
221 | |||
222 | int __init | ||
223 | bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd) | ||
224 | { | ||
225 | int ret; | ||
226 | |||
227 | if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368()) | ||
228 | return -ENODEV; | ||
229 | |||
230 | ret = register_shared(); | ||
231 | if (ret) | ||
232 | return ret; | ||
233 | |||
234 | enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW); | ||
235 | enetsw_res[0].end = enetsw_res[0].start; | ||
236 | enetsw_res[0].end += RSET_ENETSW_SIZE - 1; | ||
237 | enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0); | ||
238 | enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0); | ||
239 | if (!enetsw_res[2].start) | ||
240 | enetsw_res[2].start = -1; | ||
241 | |||
242 | memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd)); | ||
243 | |||
244 | if (BCMCPU_IS_6328()) | ||
245 | enetsw_pd.num_ports = ENETSW_PORTS_6328; | ||
246 | else if (BCMCPU_IS_6362() || BCMCPU_IS_6368()) | ||
247 | enetsw_pd.num_ports = ENETSW_PORTS_6368; | ||
248 | |||
249 | ret = platform_device_register(&bcm63xx_enetsw_device); | ||
250 | if (ret) | ||
251 | return ret; | ||
252 | |||
253 | return 0; | ||
254 | } | ||
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h index d53f611184b9..118e3c938841 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | |||
@@ -39,7 +39,35 @@ struct bcm63xx_enet_platform_data { | |||
39 | int phy_id, int reg, int val)); | 39 | int phy_id, int reg, int val)); |
40 | }; | 40 | }; |
41 | 41 | ||
42 | /* | ||
43 | * on board ethernet switch platform data | ||
44 | */ | ||
45 | #define ENETSW_MAX_PORT 8 | ||
46 | #define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */ | ||
47 | #define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */ | ||
48 | |||
49 | #define ENETSW_RGMII_PORT0 4 | ||
50 | |||
51 | struct bcm63xx_enetsw_port { | ||
52 | int used; | ||
53 | int phy_id; | ||
54 | |||
55 | int bypass_link; | ||
56 | int force_speed; | ||
57 | int force_duplex_full; | ||
58 | |||
59 | const char *name; | ||
60 | }; | ||
61 | |||
62 | struct bcm63xx_enetsw_platform_data { | ||
63 | char mac_addr[ETH_ALEN]; | ||
64 | int num_ports; | ||
65 | struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT]; | ||
66 | }; | ||
67 | |||
42 | int __init bcm63xx_enet_register(int unit, | 68 | int __init bcm63xx_enet_register(int unit, |
43 | const struct bcm63xx_enet_platform_data *pd); | 69 | const struct bcm63xx_enet_platform_data *pd); |
44 | 70 | ||
71 | int bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd); | ||
72 | |||
45 | #endif /* ! BCM63XX_DEV_ENET_H_ */ | 73 | #endif /* ! BCM63XX_DEV_ENET_H_ */ |
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 3203fe49b34d..0a2121abb1a6 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | |||
@@ -830,10 +830,60 @@ | |||
830 | * _REG relative to RSET_ENETSW | 830 | * _REG relative to RSET_ENETSW |
831 | *************************************************************************/ | 831 | *************************************************************************/ |
832 | 832 | ||
833 | /* Port traffic control */ | ||
834 | #define ENETSW_PTCTRL_REG(x) (0x0 + (x)) | ||
835 | #define ENETSW_PTCTRL_RXDIS_MASK (1 << 0) | ||
836 | #define ENETSW_PTCTRL_TXDIS_MASK (1 << 1) | ||
837 | |||
838 | /* Switch mode register */ | ||
839 | #define ENETSW_SWMODE_REG (0xb) | ||
840 | #define ENETSW_SWMODE_FWD_EN_MASK (1 << 1) | ||
841 | |||
842 | /* IMP override Register */ | ||
843 | #define ENETSW_IMPOV_REG (0xe) | ||
844 | #define ENETSW_IMPOV_FORCE_MASK (1 << 7) | ||
845 | #define ENETSW_IMPOV_TXFLOW_MASK (1 << 5) | ||
846 | #define ENETSW_IMPOV_RXFLOW_MASK (1 << 4) | ||
847 | #define ENETSW_IMPOV_1000_MASK (1 << 3) | ||
848 | #define ENETSW_IMPOV_100_MASK (1 << 2) | ||
849 | #define ENETSW_IMPOV_FDX_MASK (1 << 1) | ||
850 | #define ENETSW_IMPOV_LINKUP_MASK (1 << 0) | ||
851 | |||
852 | /* Port override Register */ | ||
853 | #define ENETSW_PORTOV_REG(x) (0x58 + (x)) | ||
854 | #define ENETSW_PORTOV_ENABLE_MASK (1 << 6) | ||
855 | #define ENETSW_PORTOV_TXFLOW_MASK (1 << 5) | ||
856 | #define ENETSW_PORTOV_RXFLOW_MASK (1 << 4) | ||
857 | #define ENETSW_PORTOV_1000_MASK (1 << 3) | ||
858 | #define ENETSW_PORTOV_100_MASK (1 << 2) | ||
859 | #define ENETSW_PORTOV_FDX_MASK (1 << 1) | ||
860 | #define ENETSW_PORTOV_LINKUP_MASK (1 << 0) | ||
861 | |||
862 | /* MDIO control register */ | ||
863 | #define ENETSW_MDIOC_REG (0xb0) | ||
864 | #define ENETSW_MDIOC_EXT_MASK (1 << 16) | ||
865 | #define ENETSW_MDIOC_REG_SHIFT 20 | ||
866 | #define ENETSW_MDIOC_PHYID_SHIFT 25 | ||
867 | #define ENETSW_MDIOC_RD_MASK (1 << 30) | ||
868 | #define ENETSW_MDIOC_WR_MASK (1 << 31) | ||
869 | |||
870 | /* MDIO data register */ | ||
871 | #define ENETSW_MDIOD_REG (0xb4) | ||
872 | |||
873 | /* Global Management Configuration Register */ | ||
874 | #define ENETSW_GMCR_REG (0x200) | ||
875 | #define ENETSW_GMCR_RST_MIB_MASK (1 << 0) | ||
876 | |||
833 | /* MIB register */ | 877 | /* MIB register */ |
834 | #define ENETSW_MIB_REG(x) (0x2800 + (x) * 4) | 878 | #define ENETSW_MIB_REG(x) (0x2800 + (x) * 4) |
835 | #define ENETSW_MIB_REG_COUNT 47 | 879 | #define ENETSW_MIB_REG_COUNT 47 |
836 | 880 | ||
881 | /* Jumbo control register port mask register */ | ||
882 | #define ENETSW_JMBCTL_PORT_REG (0x4004) | ||
883 | |||
884 | /* Jumbo control mib good frame register */ | ||
885 | #define ENETSW_JMBCTL_MAXSIZE_REG (0x4008) | ||
886 | |||
837 | 887 | ||
838 | /************************************************************************* | 888 | /************************************************************************* |
839 | * _REG relative to RSET_OHCI_PRIV | 889 | * _REG relative to RSET_OHCI_PRIV |
diff --git a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h index 682bcf3b492a..d9aee1a833f3 100644 --- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h +++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | |||
@@ -24,6 +24,7 @@ struct board_info { | |||
24 | /* enabled feature/device */ | 24 | /* enabled feature/device */ |
25 | unsigned int has_enet0:1; | 25 | unsigned int has_enet0:1; |
26 | unsigned int has_enet1:1; | 26 | unsigned int has_enet1:1; |
27 | unsigned int has_enetsw:1; | ||
27 | unsigned int has_pci:1; | 28 | unsigned int has_pci:1; |
28 | unsigned int has_pccard:1; | 29 | unsigned int has_pccard:1; |
29 | unsigned int has_ohci0:1; | 30 | unsigned int has_ohci0:1; |
@@ -36,6 +37,7 @@ struct board_info { | |||
36 | /* ethernet config */ | 37 | /* ethernet config */ |
37 | struct bcm63xx_enet_platform_data enet0; | 38 | struct bcm63xx_enet_platform_data enet0; |
38 | struct bcm63xx_enet_platform_data enet1; | 39 | struct bcm63xx_enet_platform_data enet1; |
40 | struct bcm63xx_enetsw_platform_data enetsw; | ||
39 | 41 | ||
40 | /* USB config */ | 42 | /* USB config */ |
41 | struct bcm63xx_usbd_platform_data usbd; | 43 | struct bcm63xx_usbd_platform_data usbd; |