[MIPS] Put an end to <asm/serial.h>'s long and annyoing existence
[firefly-linux-kernel-4.4.55.git] / arch / mips / momentum / ocelot_3 / platform.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2006, 07 Ralf Baechle (ralf@linux-mips.org)
7  * Copyright (C) 2007 Dale Farnsworth (dale@farnsworth.org)
8  */
9 #include <linux/delay.h>
10 #include <linux/if_ether.h>
11 #include <linux/init.h>
12 #include <linux/ioport.h>
13 #include <linux/module.h>
14 #include <linux/mv643xx.h>
15 #include <linux/platform_device.h>
16 #include <linux/serial_8250.h>
17
18 #include "ocelot_3_fpga.h"
19
20 #if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
21
22 static struct resource mv643xx_eth_shared_resources[] = {
23         [0] = {
24                 .name   = "ethernet shared base",
25                 .start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
26                 .end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
27                                        MV643XX_ETH_SHARED_REGS_SIZE - 1,
28                 .flags  = IORESOURCE_MEM,
29         },
30 };
31
32 static struct platform_device mv643xx_eth_shared_device = {
33         .name           = MV643XX_ETH_SHARED_NAME,
34         .id             = 0,
35         .num_resources  = ARRAY_SIZE(mv643xx_eth_shared_resources),
36         .resource       = mv643xx_eth_shared_resources,
37 };
38
39 #define MV_SRAM_BASE                    0xfe000000UL
40 #define MV_SRAM_SIZE                    (256 * 1024)
41
42 #define MV_SRAM_RXRING_SIZE             (MV_SRAM_SIZE / 4)
43 #define MV_SRAM_TXRING_SIZE             (MV_SRAM_SIZE / 4)
44
45 #define MV_SRAM_BASE_ETH0               MV_SRAM_BASE
46 #define MV_SRAM_BASE_ETH1               (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
47
48 #define MV64x60_IRQ_ETH_0 48
49 #define MV64x60_IRQ_ETH_1 49
50 #define MV64x60_IRQ_ETH_2 50
51
52 static struct resource mv64x60_eth0_resources[] = {
53         [0] = {
54                 .name   = "eth0 irq",
55                 .start  = MV64x60_IRQ_ETH_0,
56                 .end    = MV64x60_IRQ_ETH_0,
57                 .flags  = IORESOURCE_IRQ,
58         },
59 };
60
61 static struct mv643xx_eth_platform_data eth0_pd = {
62         .port_number    = 0,
63
64         .tx_sram_addr   = MV_SRAM_BASE_ETH0,
65         .tx_sram_size   = MV_SRAM_TXRING_SIZE,
66         .tx_queue_size  = MV_SRAM_TXRING_SIZE / 16,
67
68         .rx_sram_addr   = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
69         .rx_sram_size   = MV_SRAM_RXRING_SIZE,
70         .rx_queue_size  = MV_SRAM_RXRING_SIZE / 16,
71 };
72
73 static struct platform_device eth0_device = {
74         .name           = MV643XX_ETH_NAME,
75         .id             = 0,
76         .num_resources  = ARRAY_SIZE(mv64x60_eth0_resources),
77         .resource       = mv64x60_eth0_resources,
78         .dev = {
79                 .platform_data = &eth0_pd,
80         },
81 };
82
83 static struct resource mv64x60_eth1_resources[] = {
84         [0] = {
85                 .name   = "eth1 irq",
86                 .start  = MV64x60_IRQ_ETH_1,
87                 .end    = MV64x60_IRQ_ETH_1,
88                 .flags  = IORESOURCE_IRQ,
89         },
90 };
91
92 static struct mv643xx_eth_platform_data eth1_pd = {
93         .port_number    = 1,
94
95         .tx_sram_addr   = MV_SRAM_BASE_ETH1,
96         .tx_sram_size   = MV_SRAM_TXRING_SIZE,
97         .tx_queue_size  = MV_SRAM_TXRING_SIZE / 16,
98
99         .rx_sram_addr   = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
100         .rx_sram_size   = MV_SRAM_RXRING_SIZE,
101         .rx_queue_size  = MV_SRAM_RXRING_SIZE / 16,
102 };
103
104 static struct platform_device eth1_device = {
105         .name           = MV643XX_ETH_NAME,
106         .id             = 1,
107         .num_resources  = ARRAY_SIZE(mv64x60_eth1_resources),
108         .resource       = mv64x60_eth1_resources,
109         .dev = {
110                 .platform_data = &eth1_pd,
111         },
112 };
113
114 static struct resource mv64x60_eth2_resources[] = {
115         [0] = {
116                 .name   = "eth2 irq",
117                 .start  = MV64x60_IRQ_ETH_2,
118                 .end    = MV64x60_IRQ_ETH_2,
119                 .flags  = IORESOURCE_IRQ,
120         },
121 };
122
123 static struct mv643xx_eth_platform_data eth2_pd = {
124         .port_number    = 2,
125 };
126
127 static struct platform_device eth2_device = {
128         .name           = MV643XX_ETH_NAME,
129         .id             = 2,
130         .num_resources  = ARRAY_SIZE(mv64x60_eth2_resources),
131         .resource       = mv64x60_eth2_resources,
132         .dev = {
133                 .platform_data = &eth2_pd,
134         },
135 };
136
137 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
138         &mv643xx_eth_shared_device,
139         &eth0_device,
140         &eth1_device,
141         &eth2_device,
142 };
143
144 static u8 __init exchange_bit(u8 val, u8 cs)
145 {
146         /* place the data */
147         OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
148         udelay(1);
149
150         /* turn the clock on */
151         OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
152         udelay(1);
153
154         /* turn the clock off and read-strobe */
155         OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
156
157         /* return the data */
158         return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
159 }
160
161 static void __init get_mac(char dest[6])
162 {
163         u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
164         int i,j;
165
166         for (i = 0; i < 12; i++)
167                 exchange_bit(read_opcode[i], 1);
168
169         for (j = 0; j < 6; j++) {
170                 dest[j] = 0;
171                 for (i = 0; i < 8; i++) {
172                         dest[j] <<= 1;
173                         dest[j] |= exchange_bit(0, 1);
174                 }
175         }
176
177         /* turn off CS */
178         exchange_bit(0,0);
179 }
180
181 /*
182  * Copy and increment ethernet MAC address by a small value.
183  *
184  * This is useful for systems where the only one MAC address is stored in
185  * non-volatile memory for multiple ports.
186  */
187 static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
188         unsigned int add)
189 {
190         int i;
191
192         BUG_ON(add >= 256);
193
194         for (i = ETH_ALEN; i >= 0; i--) {
195                 dst[i] = src[i] + add;
196                 add = dst[i] < src[i];          /* compute carry */
197         }
198
199         WARN_ON(add);
200 }
201
202 static int __init mv643xx_eth_add_pds(void)
203 {
204         unsigned char mac[ETH_ALEN];
205         int ret;
206
207         get_mac(mac);
208         eth_mac_add(eth0_pd.mac_addr, mac, 0);
209         eth_mac_add(eth1_pd.mac_addr, mac, 1);
210         eth_mac_add(eth2_pd.mac_addr, mac, 2);
211         ret = platform_add_devices(mv643xx_eth_pd_devs,
212                         ARRAY_SIZE(mv643xx_eth_pd_devs));
213
214         return ret;
215 }
216
217 device_initcall(mv643xx_eth_add_pds);
218
219 #endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
220
221 #define OCELOT3_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST)
222
223 static struct plat_serial8250_port uart8250_data[] = {
224         {
225                 .membase        = (signed long) 0xfd000020,
226                 .irq            = 6,
227                 .uartclk        = 20000000,
228                 .iotype         = UPIO_MEM,
229                 .flags          = OCELOT3_UART_FLAGS,
230                 .regshift       = 2,
231         },
232         { },
233 };
234
235 static struct platform_device uart8250_device = {
236         .name                   = "serial8250",
237         .id                     = PLAT8250_DEV_PLATFORM,
238         .dev                    = {
239                 .platform_data  = uart8250_data,
240         },
241 };
242
243 static int __init uart8250_init(void)
244 {
245         return platform_device_register(&uart8250_device);
246 }
247
248 module_init(uart8250_init);
249
250 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
251 MODULE_LICENSE("GPL");
252 MODULE_DESCRIPTION("8250 UART probe driver for the Ocelot 3");