setup.c 6.5 KB

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