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