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 */ 270