xref: /linux/arch/xtensa/platforms/xtfpga/setup.c (revision 0d456bad36d42d16022be045c8a53ddbb59ee478)
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 = &ethoc_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 	&ethoc_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 */
270