platform.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. */
  9. #include <linux/clk.h>
  10. #include <linux/dma-mapping.h>
  11. #include <linux/err.h>
  12. #include <linux/mtd/partitions.h>
  13. #include <linux/sizes.h>
  14. #include <linux/phy.h>
  15. #include <linux/serial_8250.h>
  16. #include <linux/stmmac.h>
  17. #include <linux/usb/ehci_pdriver.h>
  18. #include <platform.h>
  19. #include <loongson1.h>
  20. #include <cpufreq.h>
  21. #include <dma.h>
  22. #include <nand.h>
  23. /* 8250/16550 compatible UART */
  24. #define LS1X_UART(_id) \
  25. { \
  26. .mapbase = LS1X_UART ## _id ## _BASE, \
  27. .irq = LS1X_UART ## _id ## _IRQ, \
  28. .iotype = UPIO_MEM, \
  29. .flags = UPF_IOREMAP | UPF_FIXED_TYPE, \
  30. .type = PORT_16550A, \
  31. }
  32. static struct plat_serial8250_port ls1x_serial8250_pdata[] = {
  33. LS1X_UART(0),
  34. LS1X_UART(1),
  35. LS1X_UART(2),
  36. LS1X_UART(3),
  37. {},
  38. };
  39. struct platform_device ls1x_uart_pdev = {
  40. .name = "serial8250",
  41. .id = PLAT8250_DEV_PLATFORM,
  42. .dev = {
  43. .platform_data = ls1x_serial8250_pdata,
  44. },
  45. };
  46. void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
  47. {
  48. struct clk *clk;
  49. struct plat_serial8250_port *p;
  50. clk = clk_get(&pdev->dev, pdev->name);
  51. if (IS_ERR(clk)) {
  52. pr_err("unable to get %s clock, err=%ld",
  53. pdev->name, PTR_ERR(clk));
  54. return;
  55. }
  56. clk_prepare_enable(clk);
  57. for (p = pdev->dev.platform_data; p->flags != 0; ++p)
  58. p->uartclk = clk_get_rate(clk);
  59. }
  60. /* CPUFreq */
  61. static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
  62. .clk_name = "cpu_clk",
  63. .osc_clk_name = "osc_clk",
  64. .max_freq = 266 * 1000,
  65. .min_freq = 33 * 1000,
  66. };
  67. struct platform_device ls1x_cpufreq_pdev = {
  68. .name = "ls1x-cpufreq",
  69. .dev = {
  70. .platform_data = &ls1x_cpufreq_pdata,
  71. },
  72. };
  73. /* DMA */
  74. static struct resource ls1x_dma_resources[] = {
  75. [0] = {
  76. .start = LS1X_DMAC_BASE,
  77. .end = LS1X_DMAC_BASE + SZ_4 - 1,
  78. .flags = IORESOURCE_MEM,
  79. },
  80. [1] = {
  81. .start = LS1X_DMA0_IRQ,
  82. .end = LS1X_DMA0_IRQ,
  83. .flags = IORESOURCE_IRQ,
  84. },
  85. [2] = {
  86. .start = LS1X_DMA1_IRQ,
  87. .end = LS1X_DMA1_IRQ,
  88. .flags = IORESOURCE_IRQ,
  89. },
  90. [3] = {
  91. .start = LS1X_DMA2_IRQ,
  92. .end = LS1X_DMA2_IRQ,
  93. .flags = IORESOURCE_IRQ,
  94. },
  95. };
  96. struct platform_device ls1x_dma_pdev = {
  97. .name = "ls1x-dma",
  98. .id = -1,
  99. .num_resources = ARRAY_SIZE(ls1x_dma_resources),
  100. .resource = ls1x_dma_resources,
  101. };
  102. void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata)
  103. {
  104. ls1x_dma_pdev.dev.platform_data = pdata;
  105. }
  106. /* Synopsys Ethernet GMAC */
  107. static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
  108. .phy_mask = 0,
  109. };
  110. static struct stmmac_dma_cfg ls1x_eth_dma_cfg = {
  111. .pbl = 1,
  112. };
  113. int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
  114. {
  115. struct plat_stmmacenet_data *plat_dat = NULL;
  116. u32 val;
  117. val = __raw_readl(LS1X_MUX_CTRL1);
  118. #if defined(CONFIG_LOONGSON1_LS1B)
  119. plat_dat = dev_get_platdata(&pdev->dev);
  120. if (plat_dat->bus_id) {
  121. __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
  122. GMAC1_USE_UART0, LS1X_MUX_CTRL0);
  123. switch (plat_dat->interface) {
  124. case PHY_INTERFACE_MODE_RGMII:
  125. val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
  126. break;
  127. case PHY_INTERFACE_MODE_MII:
  128. val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
  129. break;
  130. default:
  131. pr_err("unsupported mii mode %d\n",
  132. plat_dat->interface);
  133. return -ENOTSUPP;
  134. }
  135. val &= ~GMAC1_SHUT;
  136. } else {
  137. switch (plat_dat->interface) {
  138. case PHY_INTERFACE_MODE_RGMII:
  139. val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
  140. break;
  141. case PHY_INTERFACE_MODE_MII:
  142. val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
  143. break;
  144. default:
  145. pr_err("unsupported mii mode %d\n",
  146. plat_dat->interface);
  147. return -ENOTSUPP;
  148. }
  149. val &= ~GMAC0_SHUT;
  150. }
  151. __raw_writel(val, LS1X_MUX_CTRL1);
  152. #elif defined(CONFIG_LOONGSON1_LS1C)
  153. plat_dat = dev_get_platdata(&pdev->dev);
  154. val &= ~PHY_INTF_SELI;
  155. if (plat_dat->interface == PHY_INTERFACE_MODE_RMII)
  156. val |= 0x4 << PHY_INTF_SELI_SHIFT;
  157. __raw_writel(val, LS1X_MUX_CTRL1);
  158. val = __raw_readl(LS1X_MUX_CTRL0);
  159. __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0);
  160. #endif
  161. return 0;
  162. }
  163. static struct plat_stmmacenet_data ls1x_eth0_pdata = {
  164. .bus_id = 0,
  165. .phy_addr = -1,
  166. #if defined(CONFIG_LOONGSON1_LS1B)
  167. .interface = PHY_INTERFACE_MODE_MII,
  168. #elif defined(CONFIG_LOONGSON1_LS1C)
  169. .interface = PHY_INTERFACE_MODE_RMII,
  170. #endif
  171. .mdio_bus_data = &ls1x_mdio_bus_data,
  172. .dma_cfg = &ls1x_eth_dma_cfg,
  173. .has_gmac = 1,
  174. .tx_coe = 1,
  175. .rx_queues_to_use = 1,
  176. .tx_queues_to_use = 1,
  177. .init = ls1x_eth_mux_init,
  178. };
  179. static struct resource ls1x_eth0_resources[] = {
  180. [0] = {
  181. .start = LS1X_GMAC0_BASE,
  182. .end = LS1X_GMAC0_BASE + SZ_64K - 1,
  183. .flags = IORESOURCE_MEM,
  184. },
  185. [1] = {
  186. .name = "macirq",
  187. .start = LS1X_GMAC0_IRQ,
  188. .flags = IORESOURCE_IRQ,
  189. },
  190. };
  191. struct platform_device ls1x_eth0_pdev = {
  192. .name = "stmmaceth",
  193. .id = 0,
  194. .num_resources = ARRAY_SIZE(ls1x_eth0_resources),
  195. .resource = ls1x_eth0_resources,
  196. .dev = {
  197. .platform_data = &ls1x_eth0_pdata,
  198. },
  199. };
  200. #ifdef CONFIG_LOONGSON1_LS1B
  201. static struct plat_stmmacenet_data ls1x_eth1_pdata = {
  202. .bus_id = 1,
  203. .phy_addr = -1,
  204. .interface = PHY_INTERFACE_MODE_MII,
  205. .mdio_bus_data = &ls1x_mdio_bus_data,
  206. .dma_cfg = &ls1x_eth_dma_cfg,
  207. .has_gmac = 1,
  208. .tx_coe = 1,
  209. .rx_queues_to_use = 1,
  210. .tx_queues_to_use = 1,
  211. .init = ls1x_eth_mux_init,
  212. };
  213. static struct resource ls1x_eth1_resources[] = {
  214. [0] = {
  215. .start = LS1X_GMAC1_BASE,
  216. .end = LS1X_GMAC1_BASE + SZ_64K - 1,
  217. .flags = IORESOURCE_MEM,
  218. },
  219. [1] = {
  220. .name = "macirq",
  221. .start = LS1X_GMAC1_IRQ,
  222. .flags = IORESOURCE_IRQ,
  223. },
  224. };
  225. struct platform_device ls1x_eth1_pdev = {
  226. .name = "stmmaceth",
  227. .id = 1,
  228. .num_resources = ARRAY_SIZE(ls1x_eth1_resources),
  229. .resource = ls1x_eth1_resources,
  230. .dev = {
  231. .platform_data = &ls1x_eth1_pdata,
  232. },
  233. };
  234. #endif /* CONFIG_LOONGSON1_LS1B */
  235. /* GPIO */
  236. static struct resource ls1x_gpio0_resources[] = {
  237. [0] = {
  238. .start = LS1X_GPIO0_BASE,
  239. .end = LS1X_GPIO0_BASE + SZ_4 - 1,
  240. .flags = IORESOURCE_MEM,
  241. },
  242. };
  243. struct platform_device ls1x_gpio0_pdev = {
  244. .name = "ls1x-gpio",
  245. .id = 0,
  246. .num_resources = ARRAY_SIZE(ls1x_gpio0_resources),
  247. .resource = ls1x_gpio0_resources,
  248. };
  249. static struct resource ls1x_gpio1_resources[] = {
  250. [0] = {
  251. .start = LS1X_GPIO1_BASE,
  252. .end = LS1X_GPIO1_BASE + SZ_4 - 1,
  253. .flags = IORESOURCE_MEM,
  254. },
  255. };
  256. struct platform_device ls1x_gpio1_pdev = {
  257. .name = "ls1x-gpio",
  258. .id = 1,
  259. .num_resources = ARRAY_SIZE(ls1x_gpio1_resources),
  260. .resource = ls1x_gpio1_resources,
  261. };
  262. /* NAND Flash */
  263. static struct resource ls1x_nand_resources[] = {
  264. [0] = {
  265. .start = LS1X_NAND_BASE,
  266. .end = LS1X_NAND_BASE + SZ_32 - 1,
  267. .flags = IORESOURCE_MEM,
  268. },
  269. [1] = {
  270. /* DMA channel 0 is dedicated to NAND */
  271. .start = LS1X_DMA_CHANNEL0,
  272. .end = LS1X_DMA_CHANNEL0,
  273. .flags = IORESOURCE_DMA,
  274. },
  275. };
  276. struct platform_device ls1x_nand_pdev = {
  277. .name = "ls1x-nand",
  278. .id = -1,
  279. .num_resources = ARRAY_SIZE(ls1x_nand_resources),
  280. .resource = ls1x_nand_resources,
  281. };
  282. void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata)
  283. {
  284. ls1x_nand_pdev.dev.platform_data = pdata;
  285. }
  286. /* USB EHCI */
  287. static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
  288. static struct resource ls1x_ehci_resources[] = {
  289. [0] = {
  290. .start = LS1X_EHCI_BASE,
  291. .end = LS1X_EHCI_BASE + SZ_32K - 1,
  292. .flags = IORESOURCE_MEM,
  293. },
  294. [1] = {
  295. .start = LS1X_EHCI_IRQ,
  296. .flags = IORESOURCE_IRQ,
  297. },
  298. };
  299. static struct usb_ehci_pdata ls1x_ehci_pdata = {
  300. };
  301. struct platform_device ls1x_ehci_pdev = {
  302. .name = "ehci-platform",
  303. .id = -1,
  304. .num_resources = ARRAY_SIZE(ls1x_ehci_resources),
  305. .resource = ls1x_ehci_resources,
  306. .dev = {
  307. .dma_mask = &ls1x_ehci_dmamask,
  308. .platform_data = &ls1x_ehci_pdata,
  309. },
  310. };
  311. /* Real Time Clock */
  312. void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
  313. {
  314. u32 val = __raw_readl(LS1X_RTC_CTRL);
  315. if (!(val & RTC_EXTCLK_OK))
  316. __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
  317. }
  318. struct platform_device ls1x_rtc_pdev = {
  319. .name = "ls1x-rtc",
  320. .id = -1,
  321. };
  322. /* Watchdog */
  323. static struct resource ls1x_wdt_resources[] = {
  324. {
  325. .start = LS1X_WDT_BASE,
  326. .end = LS1X_WDT_BASE + SZ_16 - 1,
  327. .flags = IORESOURCE_MEM,
  328. },
  329. };
  330. struct platform_device ls1x_wdt_pdev = {
  331. .name = "ls1x-wdt",
  332. .id = -1,
  333. .num_resources = ARRAY_SIZE(ls1x_wdt_resources),
  334. .resource = ls1x_wdt_resources,
  335. };