Merge ../linux-2.6-watchdog-mm
[linux-drm-fsl-dcu.git] / arch / mips / momentum / ocelot_c / platform.c
1 #include <linux/delay.h>
2 #include <linux/if_ether.h>
3 #include <linux/ioport.h>
4 #include <linux/mv643xx.h>
5 #include <linux/platform_device.h>
6
7 #include "ocelot_c_fpga.h"
8
9 #if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
10
11 static struct resource mv643xx_eth_shared_resources[] = {
12         [0] = {
13                 .name   = "ethernet shared base",
14                 .start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
15                 .end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
16                                        MV643XX_ETH_SHARED_REGS_SIZE - 1,
17                 .flags  = IORESOURCE_MEM,
18         },
19 };
20
21 static struct platform_device mv643xx_eth_shared_device = {
22         .name           = MV643XX_ETH_SHARED_NAME,
23         .id             = 0,
24         .num_resources  = ARRAY_SIZE(mv643xx_eth_shared_resources),
25         .resource       = mv643xx_eth_shared_resources,
26 };
27
28 #define MV_SRAM_BASE                    0xfe000000UL
29 #define MV_SRAM_SIZE                    (256 * 1024)
30
31 #define MV_SRAM_RXRING_SIZE             (MV_SRAM_SIZE / 4)
32 #define MV_SRAM_TXRING_SIZE             (MV_SRAM_SIZE / 4)
33
34 #define MV_SRAM_BASE_ETH0               MV_SRAM_BASE
35 #define MV_SRAM_BASE_ETH1               (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
36
37 #define MV64x60_IRQ_ETH_0 48
38 #define MV64x60_IRQ_ETH_1 49
39
40 #ifdef CONFIG_MV643XX_ETH_0
41
42 static struct resource mv64x60_eth0_resources[] = {
43         [0] = {
44                 .name   = "eth0 irq",
45                 .start  = MV64x60_IRQ_ETH_0,
46                 .end    = MV64x60_IRQ_ETH_0,
47                 .flags  = IORESOURCE_IRQ,
48         },
49 };
50
51 static char eth0_mac_addr[ETH_ALEN];
52
53 static struct mv643xx_eth_platform_data eth0_pd = {
54         .mac_addr       = eth0_mac_addr,
55
56         .tx_sram_addr   = MV_SRAM_BASE_ETH0,
57         .tx_sram_size   = MV_SRAM_TXRING_SIZE,
58         .tx_queue_size  = MV_SRAM_TXRING_SIZE / 16,
59
60         .rx_sram_addr   = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
61         .rx_sram_size   = MV_SRAM_RXRING_SIZE,
62         .rx_queue_size  = MV_SRAM_RXRING_SIZE / 16,
63 };
64
65 static struct platform_device eth0_device = {
66         .name           = MV643XX_ETH_NAME,
67         .id             = 0,
68         .num_resources  = ARRAY_SIZE(mv64x60_eth0_resources),
69         .resource       = mv64x60_eth0_resources,
70         .dev = {
71                 .platform_data = &eth0_pd,
72         },
73 };
74 #endif /* CONFIG_MV643XX_ETH_0 */
75
76 #ifdef CONFIG_MV643XX_ETH_1
77
78 static struct resource mv64x60_eth1_resources[] = {
79         [0] = {
80                 .name   = "eth1 irq",
81                 .start  = MV64x60_IRQ_ETH_1,
82                 .end    = MV64x60_IRQ_ETH_1,
83                 .flags  = IORESOURCE_IRQ,
84         },
85 };
86
87 static char eth1_mac_addr[ETH_ALEN];
88
89 static struct mv643xx_eth_platform_data eth1_pd = {
90         .mac_addr       = eth1_mac_addr,
91
92         .tx_sram_addr   = MV_SRAM_BASE_ETH1,
93         .tx_sram_size   = MV_SRAM_TXRING_SIZE,
94         .tx_queue_size  = MV_SRAM_TXRING_SIZE / 16,
95
96         .rx_sram_addr   = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
97         .rx_sram_size   = MV_SRAM_RXRING_SIZE,
98         .rx_queue_size  = MV_SRAM_RXRING_SIZE / 16,
99 };
100
101 static struct platform_device eth1_device = {
102         .name           = MV643XX_ETH_NAME,
103         .id             = 1,
104         .num_resources  = ARRAY_SIZE(mv64x60_eth1_resources),
105         .resource       = mv64x60_eth1_resources,
106         .dev = {
107                 .platform_data = &eth1_pd,
108         },
109 };
110 #endif /* CONFIG_MV643XX_ETH_1 */
111
112 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
113         &mv643xx_eth_shared_device,
114 #ifdef CONFIG_MV643XX_ETH_0
115         &eth0_device,
116 #endif
117 #ifdef CONFIG_MV643XX_ETH_1
118         &eth1_device,
119 #endif
120         /* The third port is not wired up on the Ocelot C */
121 };
122
123 static u8 __init exchange_bit(u8 val, u8 cs)
124 {
125         /* place the data */
126         OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
127         udelay(1);
128
129         /* turn the clock on */
130         OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
131         udelay(1);
132
133         /* turn the clock off and read-strobe */
134         OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
135
136         /* return the data */
137         return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
138 }
139
140 static void __init get_mac(char dest[6])
141 {
142         u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
143         int i,j;
144
145         for (i = 0; i < 12; i++)
146                 exchange_bit(read_opcode[i], 1);
147
148         for (j = 0; j < 6; j++) {
149                 dest[j] = 0;
150                 for (i = 0; i < 8; i++) {
151                         dest[j] <<= 1;
152                         dest[j] |= exchange_bit(0, 1);
153                 }
154         }
155
156         /* turn off CS */
157         exchange_bit(0,0);
158 }
159
160 /*
161  * Copy and increment ethernet MAC address by a small value.
162  *
163  * This is useful for systems where the only one MAC address is stored in
164  * non-volatile memory for multiple ports.
165  */
166 static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
167         unsigned int add)
168 {
169         int i;
170
171         BUG_ON(add >= 256);
172
173         for (i = ETH_ALEN; i >= 0; i--) {
174                 dst[i] = src[i] + add;
175                 add = dst[i] < src[i];          /* compute carry */
176         }
177
178         WARN_ON(add);
179 }
180
181 static int __init mv643xx_eth_add_pds(void)
182 {
183         unsigned char mac[ETH_ALEN];
184         int ret;
185
186         get_mac(mac);
187 #ifdef CONFIG_MV643XX_ETH_0
188         eth_mac_add(eth1_mac_addr, mac, 0);
189 #endif
190 #ifdef CONFIG_MV643XX_ETH_1
191         eth_mac_add(eth1_mac_addr, mac, 1);
192 #endif
193         ret = platform_add_devices(mv643xx_eth_pd_devs,
194                         ARRAY_SIZE(mv643xx_eth_pd_devs));
195
196         return ret;
197 }
198
199 device_initcall(mv643xx_eth_add_pds);
200
201 #endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */