setup.c 6.5 KB

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