platform.c 8.0 KB

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