diff options
Diffstat (limited to 'arch/xtensa/platforms/xtfpga/setup.c')
-rw-r--r-- | arch/xtensa/platforms/xtfpga/setup.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c new file mode 100644 index 000000000000..71d61ca6a4af --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/setup.c | |||
@@ -0,0 +1,269 @@ | |||
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> | ||
29 | |||
30 | #include <asm/timex.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/platform.h> | ||
33 | #include <asm/bootparam.h> | ||
34 | #include <platform/lcd.h> | ||
35 | |||
36 | void platform_halt(void) | ||
37 | { | ||
38 | lcd_disp_at_pos(" HALT ", 0); | ||
39 | local_irq_disable(); | ||
40 | while (1) | ||
41 | cpu_relax(); | ||
42 | } | ||
43 | |||
44 | void platform_power_off(void) | ||
45 | { | ||
46 | lcd_disp_at_pos("POWEROFF", 0); | ||
47 | local_irq_disable(); | ||
48 | while (1) | ||
49 | cpu_relax(); | ||
50 | } | ||
51 | |||
52 | void platform_restart(void) | ||
53 | { | ||
54 | /* Flush and reset the mmu, simulate a processor reset, and | ||
55 | * jump to the reset vector. */ | ||
56 | |||
57 | |||
58 | __asm__ __volatile__ ("movi a2, 15\n\t" | ||
59 | "wsr a2, icountlevel\n\t" | ||
60 | "movi a2, 0\n\t" | ||
61 | "wsr a2, icount\n\t" | ||
62 | "wsr a2, ibreakenable\n\t" | ||
63 | "wsr a2, lcount\n\t" | ||
64 | "movi a2, 0x1f\n\t" | ||
65 | "wsr a2, ps\n\t" | ||
66 | "isync\n\t" | ||
67 | "jx %0\n\t" | ||
68 | : | ||
69 | : "a" (XCHAL_RESET_VECTOR_VADDR) | ||
70 | : "a2" | ||
71 | ); | ||
72 | |||
73 | /* control never gets here */ | ||
74 | } | ||
75 | |||
76 | void __init platform_setup(char **cmdline) | ||
77 | { | ||
78 | } | ||
79 | |||
80 | #ifdef CONFIG_OF | ||
81 | |||
82 | static void __init update_clock_frequency(struct device_node *node) | ||
83 | { | ||
84 | struct property *newfreq; | ||
85 | u32 freq; | ||
86 | |||
87 | if (!of_property_read_u32(node, "clock-frequency", &freq) && | ||
88 | freq != 0) | ||
89 | return; | ||
90 | |||
91 | newfreq = kzalloc(sizeof(*newfreq) + sizeof(u32), GFP_KERNEL); | ||
92 | if (!newfreq) | ||
93 | return; | ||
94 | newfreq->value = newfreq + 1; | ||
95 | newfreq->length = sizeof(freq); | ||
96 | newfreq->name = kstrdup("clock-frequency", GFP_KERNEL); | ||
97 | if (!newfreq->name) { | ||
98 | kfree(newfreq); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | *(u32 *)newfreq->value = cpu_to_be32(*(u32 *)XTFPGA_CLKFRQ_VADDR); | ||
103 | prom_update_property(node, newfreq); | ||
104 | } | ||
105 | |||
106 | static int __init machine_setup(void) | ||
107 | { | ||
108 | struct device_node *serial = NULL; | ||
109 | |||
110 | while ((serial = of_find_compatible_node(serial, NULL, "ns16550a"))) | ||
111 | update_clock_frequency(serial); | ||
112 | return 0; | ||
113 | } | ||
114 | arch_initcall(machine_setup); | ||
115 | |||
116 | #endif | ||
117 | |||
118 | /* early initialization */ | ||
119 | |||
120 | void __init platform_init(bp_tag_t *first) | ||
121 | { | ||
122 | } | ||
123 | |||
124 | /* Heartbeat. */ | ||
125 | |||
126 | void platform_heartbeat(void) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | ||
131 | |||
132 | void platform_calibrate_ccount(void) | ||
133 | { | ||
134 | long clk_freq = 0; | ||
135 | #ifdef CONFIG_OF | ||
136 | struct device_node *cpu = | ||
137 | of_find_compatible_node(NULL, NULL, "xtensa,cpu"); | ||
138 | if (cpu) { | ||
139 | u32 freq; | ||
140 | update_clock_frequency(cpu); | ||
141 | if (!of_property_read_u32(cpu, "clock-frequency", &freq)) | ||
142 | clk_freq = freq; | ||
143 | } | ||
144 | #endif | ||
145 | if (!clk_freq) | ||
146 | clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; | ||
147 | |||
148 | ccount_per_jiffy = clk_freq / HZ; | ||
149 | nsec_per_ccount = 1000000000UL / clk_freq; | ||
150 | } | ||
151 | |||
152 | #endif | ||
153 | |||
154 | #ifndef CONFIG_OF | ||
155 | |||
156 | #include <linux/serial_8250.h> | ||
157 | #include <linux/if.h> | ||
158 | #include <net/ethoc.h> | ||
159 | |||
160 | /*---------------------------------------------------------------------------- | ||
161 | * Ethernet -- OpenCores Ethernet MAC (ethoc driver) | ||
162 | */ | ||
163 | |||
164 | static struct resource ethoc_res[] __initdata = { | ||
165 | [0] = { /* register space */ | ||
166 | .start = OETH_REGS_PADDR, | ||
167 | .end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1, | ||
168 | .flags = IORESOURCE_MEM, | ||
169 | }, | ||
170 | [1] = { /* buffer space */ | ||
171 | .start = OETH_SRAMBUFF_PADDR, | ||
172 | .end = OETH_SRAMBUFF_PADDR + OETH_SRAMBUFF_SIZE - 1, | ||
173 | .flags = IORESOURCE_MEM, | ||
174 | }, | ||
175 | [2] = { /* IRQ number */ | ||
176 | .start = OETH_IRQ, | ||
177 | .end = OETH_IRQ, | ||
178 | .flags = IORESOURCE_IRQ, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static struct ethoc_platform_data ethoc_pdata __initdata = { | ||
183 | /* | ||
184 | * The MAC address for these boards is 00:50:c2:13:6f:xx. | ||
185 | * The last byte (here as zero) is read from the DIP switches on the | ||
186 | * board. | ||
187 | */ | ||
188 | .hwaddr = { 0x00, 0x50, 0xc2, 0x13, 0x6f, 0 }, | ||
189 | .phy_id = -1, | ||
190 | }; | ||
191 | |||
192 | static struct platform_device ethoc_device __initdata = { | ||
193 | .name = "ethoc", | ||
194 | .id = -1, | ||
195 | .num_resources = ARRAY_SIZE(ethoc_res), | ||
196 | .resource = ethoc_res, | ||
197 | .dev = { | ||
198 | .platform_data = ðoc_pdata, | ||
199 | }, | ||
200 | }; | ||
201 | |||
202 | /*---------------------------------------------------------------------------- | ||
203 | * UART | ||
204 | */ | ||
205 | |||
206 | static struct resource serial_resource __initdata = { | ||
207 | .start = DUART16552_PADDR, | ||
208 | .end = DUART16552_PADDR + 0x1f, | ||
209 | .flags = IORESOURCE_MEM, | ||
210 | }; | ||
211 | |||
212 | static struct plat_serial8250_port serial_platform_data[] __initdata = { | ||
213 | [0] = { | ||
214 | .mapbase = DUART16552_PADDR, | ||
215 | .irq = DUART16552_INTNUM, | ||
216 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | | ||
217 | UPF_IOREMAP, | ||
218 | .iotype = UPIO_MEM32, | ||
219 | .regshift = 2, | ||
220 | .uartclk = 0, /* set in xtavnet_init() */ | ||
221 | }, | ||
222 | { }, | ||
223 | }; | ||
224 | |||
225 | static struct platform_device xtavnet_uart __initdata = { | ||
226 | .name = "serial8250", | ||
227 | .id = PLAT8250_DEV_PLATFORM, | ||
228 | .dev = { | ||
229 | .platform_data = serial_platform_data, | ||
230 | }, | ||
231 | .num_resources = 1, | ||
232 | .resource = &serial_resource, | ||
233 | }; | ||
234 | |||
235 | /* platform devices */ | ||
236 | static struct platform_device *platform_devices[] __initdata = { | ||
237 | ðoc_device, | ||
238 | &xtavnet_uart, | ||
239 | }; | ||
240 | |||
241 | |||
242 | static int __init xtavnet_init(void) | ||
243 | { | ||
244 | /* Ethernet MAC address. */ | ||
245 | ethoc_pdata.hwaddr[5] = *(u32 *)DIP_SWITCHES_VADDR; | ||
246 | |||
247 | /* Clock rate varies among FPGA bitstreams; board specific FPGA register | ||
248 | * reports the actual clock rate. | ||
249 | */ | ||
250 | serial_platform_data[0].uartclk = *(long *)XTFPGA_CLKFRQ_VADDR; | ||
251 | |||
252 | |||
253 | /* register platform devices */ | ||
254 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | ||
255 | |||
256 | /* ETHOC driver is a bit quiet; at least display Ethernet MAC, so user | ||
257 | * knows whether they set it correctly on the DIP switches. | ||
258 | */ | ||
259 | pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Register to be done during do_initcalls(). | ||
266 | */ | ||
267 | arch_initcall(xtavnet_init); | ||
268 | |||
269 | #endif /* CONFIG_OF */ | ||