]>
Commit | Line | Data |
---|---|---|
0d456bad MF |
1 | /* |
2 | * | |
3 | * arch/xtensa/platform/xtavnet/setup.c | |
4 | * | |
5 | * ... | |
6 | * | |
7 | * Authors: Chris Zankel <chris@zankel.net> | |
8 | * Joe Taylor <joe@tensilica.com> | |
9 | * | |
10 | * Copyright 2001 - 2006 Tensilica Inc. | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. | |
16 | * | |
17 | */ | |
18 | #include <linux/stddef.h> | |
19 | #include <linux/kernel.h> | |
20 | #include <linux/init.h> | |
21 | #include <linux/errno.h> | |
22 | #include <linux/reboot.h> | |
23 | #include <linux/kdev_t.h> | |
24 | #include <linux/types.h> | |
25 | #include <linux/major.h> | |
26 | #include <linux/console.h> | |
27 | #include <linux/delay.h> | |
28 | #include <linux/of.h> | |
58c3e3ac MF |
29 | #include <linux/clk-provider.h> |
30 | #include <linux/of_address.h> | |
0d456bad MF |
31 | |
32 | #include <asm/timex.h> | |
33 | #include <asm/processor.h> | |
34 | #include <asm/platform.h> | |
35 | #include <asm/bootparam.h> | |
36 | #include <platform/lcd.h> | |
33c760fb | 37 | #include <platform/hardware.h> |
0d456bad MF |
38 | |
39 | void platform_halt(void) | |
40 | { | |
41 | lcd_disp_at_pos(" HALT ", 0); | |
42 | local_irq_disable(); | |
43 | while (1) | |
44 | cpu_relax(); | |
45 | } | |
46 | ||
47 | void platform_power_off(void) | |
48 | { | |
49 | lcd_disp_at_pos("POWEROFF", 0); | |
50 | local_irq_disable(); | |
51 | while (1) | |
52 | cpu_relax(); | |
53 | } | |
54 | ||
55 | void platform_restart(void) | |
56 | { | |
57 | /* Flush and reset the mmu, simulate a processor reset, and | |
58 | * jump to the reset vector. */ | |
4f205687 | 59 | cpu_reset(); |
0d456bad MF |
60 | /* control never gets here */ |
61 | } | |
62 | ||
63 | void __init platform_setup(char **cmdline) | |
64 | { | |
65 | } | |
66 | ||
70feca71 MF |
67 | /* early initialization */ |
68 | ||
69 | void __init platform_init(bp_tag_t *first) | |
70 | { | |
71 | } | |
72 | ||
73 | /* Heartbeat. */ | |
74 | ||
75 | void platform_heartbeat(void) | |
76 | { | |
77 | } | |
78 | ||
79 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | |
80 | ||
81 | void __init platform_calibrate_ccount(void) | |
82 | { | |
83 | ccount_freq = *(long *)XTFPGA_CLKFRQ_VADDR; | |
84 | } | |
85 | ||
86 | #endif | |
87 | ||
0d456bad MF |
88 | #ifdef CONFIG_OF |
89 | ||
58c3e3ac MF |
90 | static void __init xtfpga_clk_setup(struct device_node *np) |
91 | { | |
92 | void __iomem *base = of_iomap(np, 0); | |
93 | struct clk *clk; | |
94 | u32 freq; | |
95 | ||
96 | if (!base) { | |
97 | pr_err("%s: invalid address\n", np->name); | |
98 | return; | |
99 | } | |
100 | ||
101 | freq = __raw_readl(base); | |
102 | iounmap(base); | |
103 | clk = clk_register_fixed_rate(NULL, np->name, NULL, 0, freq); | |
104 | ||
105 | if (IS_ERR(clk)) { | |
106 | pr_err("%s: clk registration failed\n", np->name); | |
107 | return; | |
108 | } | |
109 | ||
110 | if (of_clk_add_provider(np, of_clk_src_simple_get, clk)) { | |
111 | pr_err("%s: clk provider registration failed\n", np->name); | |
112 | return; | |
113 | } | |
114 | } | |
115 | CLK_OF_DECLARE(xtfpga_clk, "cdns,xtfpga-clock", xtfpga_clk_setup); | |
116 | ||
33c760fb CZ |
117 | #define MAC_LEN 6 |
118 | static void __init update_local_mac(struct device_node *node) | |
119 | { | |
120 | struct property *newmac; | |
121 | const u8* macaddr; | |
122 | int prop_len; | |
123 | ||
124 | macaddr = of_get_property(node, "local-mac-address", &prop_len); | |
125 | if (macaddr == NULL || prop_len != MAC_LEN) | |
126 | return; | |
127 | ||
128 | newmac = kzalloc(sizeof(*newmac) + MAC_LEN, GFP_KERNEL); | |
129 | if (newmac == NULL) | |
130 | return; | |
131 | ||
132 | newmac->value = newmac + 1; | |
133 | newmac->length = MAC_LEN; | |
134 | newmac->name = kstrdup("local-mac-address", GFP_KERNEL); | |
135 | if (newmac->name == NULL) { | |
136 | kfree(newmac); | |
137 | return; | |
138 | } | |
139 | ||
140 | memcpy(newmac->value, macaddr, MAC_LEN); | |
141 | ((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f; | |
127bc79e | 142 | of_update_property(node, newmac); |
33c760fb CZ |
143 | } |
144 | ||
0d456bad MF |
145 | static int __init machine_setup(void) |
146 | { | |
33c760fb | 147 | struct device_node *eth = NULL; |
0d456bad | 148 | |
33c760fb CZ |
149 | if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc"))) |
150 | update_local_mac(eth); | |
0d456bad MF |
151 | return 0; |
152 | } | |
153 | arch_initcall(machine_setup); | |
154 | ||
70feca71 | 155 | #else |
0d456bad MF |
156 | |
157 | #include <linux/serial_8250.h> | |
158 | #include <linux/if.h> | |
159 | #include <net/ethoc.h> | |
e0bf6c5c | 160 | #include <linux/usb/c67x00.h> |
0d456bad MF |
161 | |
162 | /*---------------------------------------------------------------------------- | |
163 | * Ethernet -- OpenCores Ethernet MAC (ethoc driver) | |
164 | */ | |
165 | ||
a558d992 | 166 | static struct resource ethoc_res[] = { |
0d456bad MF |
167 | [0] = { /* register space */ |
168 | .start = OETH_REGS_PADDR, | |
169 | .end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1, | |
170 | .flags = IORESOURCE_MEM, | |
171 | }, | |
172 | [1] = { /* buffer space */ | |
173 | .start = OETH_SRAMBUFF_PADDR, | |
174 | .end = OETH_SRAMBUFF_PADDR + OETH_SRAMBUFF_SIZE - 1, | |
175 | .flags = IORESOURCE_MEM, | |
176 | }, | |
177 | [2] = { /* IRQ number */ | |
178 | .start = OETH_IRQ, | |
179 | .end = OETH_IRQ, | |
180 | .flags = IORESOURCE_IRQ, | |
181 | }, | |
182 | }; | |
183 | ||
a558d992 | 184 | static struct ethoc_platform_data ethoc_pdata = { |
0d456bad MF |
185 | /* |
186 | * The MAC address for these boards is 00:50:c2:13:6f:xx. | |
187 | * The last byte (here as zero) is read from the DIP switches on the | |
188 | * board. | |
189 | */ | |
190 | .hwaddr = { 0x00, 0x50, 0xc2, 0x13, 0x6f, 0 }, | |
191 | .phy_id = -1, | |
d99434e1 | 192 | .big_endian = XCHAL_HAVE_BE, |
0d456bad MF |
193 | }; |
194 | ||
a558d992 | 195 | static struct platform_device ethoc_device = { |
0d456bad MF |
196 | .name = "ethoc", |
197 | .id = -1, | |
198 | .num_resources = ARRAY_SIZE(ethoc_res), | |
199 | .resource = ethoc_res, | |
200 | .dev = { | |
201 | .platform_data = ðoc_pdata, | |
202 | }, | |
203 | }; | |
204 | ||
e0bf6c5c MF |
205 | /*---------------------------------------------------------------------------- |
206 | * USB Host/Device -- Cypress CY7C67300 | |
207 | */ | |
208 | ||
209 | static struct resource c67x00_res[] = { | |
210 | [0] = { /* register space */ | |
211 | .start = C67X00_PADDR, | |
212 | .end = C67X00_PADDR + C67X00_SIZE - 1, | |
213 | .flags = IORESOURCE_MEM, | |
214 | }, | |
215 | [1] = { /* IRQ number */ | |
216 | .start = C67X00_IRQ, | |
217 | .end = C67X00_IRQ, | |
218 | .flags = IORESOURCE_IRQ, | |
219 | }, | |
220 | }; | |
221 | ||
222 | static struct c67x00_platform_data c67x00_pdata = { | |
223 | .sie_config = C67X00_SIE1_HOST | C67X00_SIE2_UNUSED, | |
224 | .hpi_regstep = 4, | |
225 | }; | |
226 | ||
227 | static struct platform_device c67x00_device = { | |
228 | .name = "c67x00", | |
229 | .id = -1, | |
230 | .num_resources = ARRAY_SIZE(c67x00_res), | |
231 | .resource = c67x00_res, | |
232 | .dev = { | |
233 | .platform_data = &c67x00_pdata, | |
234 | }, | |
235 | }; | |
236 | ||
0d456bad MF |
237 | /*---------------------------------------------------------------------------- |
238 | * UART | |
239 | */ | |
240 | ||
a558d992 | 241 | static struct resource serial_resource = { |
0d456bad MF |
242 | .start = DUART16552_PADDR, |
243 | .end = DUART16552_PADDR + 0x1f, | |
244 | .flags = IORESOURCE_MEM, | |
245 | }; | |
246 | ||
a558d992 | 247 | static struct plat_serial8250_port serial_platform_data[] = { |
0d456bad MF |
248 | [0] = { |
249 | .mapbase = DUART16552_PADDR, | |
250 | .irq = DUART16552_INTNUM, | |
251 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | | |
252 | UPF_IOREMAP, | |
abfbd895 | 253 | .iotype = XCHAL_HAVE_BE ? UPIO_MEM32BE : UPIO_MEM32, |
0d456bad MF |
254 | .regshift = 2, |
255 | .uartclk = 0, /* set in xtavnet_init() */ | |
256 | }, | |
257 | { }, | |
258 | }; | |
259 | ||
a558d992 | 260 | static struct platform_device xtavnet_uart = { |
0d456bad MF |
261 | .name = "serial8250", |
262 | .id = PLAT8250_DEV_PLATFORM, | |
263 | .dev = { | |
264 | .platform_data = serial_platform_data, | |
265 | }, | |
266 | .num_resources = 1, | |
267 | .resource = &serial_resource, | |
268 | }; | |
269 | ||
270 | /* platform devices */ | |
271 | static struct platform_device *platform_devices[] __initdata = { | |
272 | ðoc_device, | |
e0bf6c5c | 273 | &c67x00_device, |
0d456bad MF |
274 | &xtavnet_uart, |
275 | }; | |
276 | ||
277 | ||
278 | static int __init xtavnet_init(void) | |
279 | { | |
280 | /* Ethernet MAC address. */ | |
281 | ethoc_pdata.hwaddr[5] = *(u32 *)DIP_SWITCHES_VADDR; | |
282 | ||
283 | /* Clock rate varies among FPGA bitstreams; board specific FPGA register | |
284 | * reports the actual clock rate. | |
285 | */ | |
286 | serial_platform_data[0].uartclk = *(long *)XTFPGA_CLKFRQ_VADDR; | |
287 | ||
288 | ||
289 | /* register platform devices */ | |
290 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | |
291 | ||
292 | /* ETHOC driver is a bit quiet; at least display Ethernet MAC, so user | |
293 | * knows whether they set it correctly on the DIP switches. | |
294 | */ | |
295 | pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr); | |
2bc2fde6 | 296 | ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR; |
0d456bad MF |
297 | |
298 | return 0; | |
299 | } | |
300 | ||
301 | /* | |
302 | * Register to be done during do_initcalls(). | |
303 | */ | |
304 | arch_initcall(xtavnet_init); | |
305 | ||
306 | #endif /* CONFIG_OF */ |