2
0

0017-MIPS-ath79-add-support-for-qca956x-soc.patch 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. From 6aeb24b9508bbe91f89cd4eb21d0d7582d971146 Mon Sep 17 00:00:00 2001
  2. From: Weijie Gao <[email protected]>
  3. Date: Tue, 6 Mar 2018 08:48:31 +0100
  4. Subject: [PATCH 17/27] MIPS: ath79: add support for qca956x soc
  5. This patch adds soc support for QCA9561 and TP9343.
  6. TP9343 is a reduced version of QCA9561, which can be found in TP-LINK routers in China.
  7. The qca956x_wmac has not yet been supported by ath9k.
  8. tested on TL-WDR6500 and TL-WR882N v1 (Chinese version)
  9. Signed-off-by: Weijie Gao <[email protected]>
  10. ---
  11. arch/mips/ath79/Kconfig | 2 +-
  12. arch/mips/ath79/clock.c | 96 ++++++++++++++++++++++++++++++++
  13. arch/mips/ath79/common.c | 4 ++
  14. arch/mips/ath79/dev-common.c | 7 ++-
  15. arch/mips/ath79/early_printk.c | 2 +
  16. arch/mips/ath79/irq.c | 87 ++++++++++++++++++++++++++++-
  17. arch/mips/ath79/pci.c | 12 ++++
  18. arch/mips/ath79/setup.c | 17 +++++-
  19. arch/mips/include/asm/mach-ath79/ath79.h | 22 ++++++++
  20. 9 files changed, 245 insertions(+), 4 deletions(-)
  21. diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
  22. index b03f5c8b9d1e..ad56cdbc8abd 100644
  23. --- a/arch/mips/ath79/Kconfig
  24. +++ b/arch/mips/ath79/Kconfig
  25. @@ -119,7 +119,7 @@ config ATH79_DEV_USB
  26. def_bool n
  27. config ATH79_DEV_WMAC
  28. - depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA953X || SOC_QCA955X)
  29. + depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA953X || SOC_QCA955X || SOC_QCA956X)
  30. def_bool n
  31. endif
  32. diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c
  33. index b9595b2d1b65..65701b45fb1b 100644
  34. --- a/arch/mips/ath79/clock.c
  35. +++ b/arch/mips/ath79/clock.c
  36. @@ -525,6 +525,100 @@ static void __init qca955x_clocks_init(void)
  37. clk_add_alias("uart", NULL, "ref", NULL);
  38. }
  39. +static void __init qca956x_clocks_init(void)
  40. +{
  41. + unsigned long ref_rate;
  42. + unsigned long cpu_rate;
  43. + unsigned long ddr_rate;
  44. + unsigned long ahb_rate;
  45. + u32 pll, out_div, ref_div, nint, hfrac, lfrac, clk_ctrl, postdiv;
  46. + u32 cpu_pll, ddr_pll;
  47. + u32 bootstrap;
  48. +
  49. + bootstrap = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP);
  50. + if (bootstrap & QCA956X_BOOTSTRAP_REF_CLK_40)
  51. + ref_rate = 40 * 1000 * 1000;
  52. + else
  53. + ref_rate = 25 * 1000 * 1000;
  54. +
  55. + pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG_REG);
  56. + out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
  57. + QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
  58. + ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
  59. + QCA956X_PLL_CPU_CONFIG_REFDIV_MASK;
  60. +
  61. + pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG1_REG);
  62. + nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) &
  63. + QCA956X_PLL_CPU_CONFIG1_NINT_MASK;
  64. + hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) &
  65. + QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK;
  66. + lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) &
  67. + QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK;
  68. +
  69. + cpu_pll = nint * ref_rate / ref_div;
  70. + cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
  71. + cpu_pll += (hfrac >> 13) * ref_rate / ref_div;
  72. + cpu_pll /= (1 << out_div);
  73. +
  74. + pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG_REG);
  75. + out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
  76. + QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK;
  77. + ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
  78. + QCA956X_PLL_DDR_CONFIG_REFDIV_MASK;
  79. + pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG1_REG);
  80. + nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) &
  81. + QCA956X_PLL_DDR_CONFIG1_NINT_MASK;
  82. + hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) &
  83. + QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK;
  84. + lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) &
  85. + QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK;
  86. +
  87. + ddr_pll = nint * ref_rate / ref_div;
  88. + ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
  89. + ddr_pll += (hfrac >> 13) * ref_rate / ref_div;
  90. + ddr_pll /= (1 << out_div);
  91. +
  92. + clk_ctrl = ath79_pll_rr(QCA956X_PLL_CLK_CTRL_REG);
  93. +
  94. + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
  95. + QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
  96. +
  97. + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
  98. + cpu_rate = ref_rate;
  99. + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL)
  100. + cpu_rate = ddr_pll / (postdiv + 1);
  101. + else
  102. + cpu_rate = cpu_pll / (postdiv + 1);
  103. +
  104. + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
  105. + QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
  106. +
  107. + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
  108. + ddr_rate = ref_rate;
  109. + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL)
  110. + ddr_rate = cpu_pll / (postdiv + 1);
  111. + else
  112. + ddr_rate = ddr_pll / (postdiv + 1);
  113. +
  114. + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
  115. + QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
  116. +
  117. + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
  118. + ahb_rate = ref_rate;
  119. + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
  120. + ahb_rate = ddr_pll / (postdiv + 1);
  121. + else
  122. + ahb_rate = cpu_pll / (postdiv + 1);
  123. +
  124. + ath79_add_sys_clkdev("ref", ref_rate);
  125. + ath79_add_sys_clkdev("cpu", cpu_rate);
  126. + ath79_add_sys_clkdev("ddr", ddr_rate);
  127. + ath79_add_sys_clkdev("ahb", ahb_rate);
  128. +
  129. + clk_add_alias("wdt", NULL, "ref", NULL);
  130. + clk_add_alias("uart", NULL, "ref", NULL);
  131. +}
  132. +
  133. void __init ath79_clocks_init(void)
  134. {
  135. if (soc_is_ar71xx())
  136. @@ -539,6 +633,8 @@ void __init ath79_clocks_init(void)
  137. qca953x_clocks_init();
  138. else if (soc_is_qca955x())
  139. qca955x_clocks_init();
  140. + else if (soc_is_qca956x() || soc_is_tp9343())
  141. + qca956x_clocks_init();
  142. else
  143. BUG();
  144. }
  145. diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c
  146. index a485a7c35b9b..fc3438150b3e 100644
  147. --- a/arch/mips/ath79/common.c
  148. +++ b/arch/mips/ath79/common.c
  149. @@ -107,6 +107,8 @@ void ath79_device_reset_set(u32 mask)
  150. reg = QCA953X_RESET_REG_RESET_MODULE;
  151. else if (soc_is_qca955x())
  152. reg = QCA955X_RESET_REG_RESET_MODULE;
  153. + else if (soc_is_qca956x() || soc_is_tp9343())
  154. + reg = QCA956X_RESET_REG_RESET_MODULE;
  155. else
  156. panic("Reset register not defined for this SOC");
  157. @@ -137,6 +139,8 @@ void ath79_device_reset_clear(u32 mask)
  158. reg = QCA953X_RESET_REG_RESET_MODULE;
  159. else if (soc_is_qca955x())
  160. reg = QCA955X_RESET_REG_RESET_MODULE;
  161. + else if (soc_is_qca956x() || soc_is_tp9343())
  162. + reg = QCA956X_RESET_REG_RESET_MODULE;
  163. else
  164. panic("Reset register not defined for this SOC");
  165. diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
  166. index 99d8b88f1e6d..ac8bfe86b656 100644
  167. --- a/arch/mips/ath79/dev-common.c
  168. +++ b/arch/mips/ath79/dev-common.c
  169. @@ -86,7 +86,9 @@ void __init ath79_register_uart(void)
  170. soc_is_ar913x() ||
  171. soc_is_ar934x() ||
  172. soc_is_qca953x() ||
  173. - soc_is_qca955x()) {
  174. + soc_is_qca955x() ||
  175. + soc_is_qca956x() ||
  176. + soc_is_tp9343()) {
  177. ath79_uart_data[0].uartclk = uart_clk_rate;
  178. platform_device_register(&ath79_uart_device);
  179. } else if (soc_is_ar933x()) {
  180. @@ -155,6 +157,9 @@ void __init ath79_gpio_init(void)
  181. } else if (soc_is_qca955x()) {
  182. ath79_gpio_pdata.ngpios = QCA955X_GPIO_COUNT;
  183. ath79_gpio_pdata.oe_inverted = 1;
  184. + } else if (soc_is_qca956x() || soc_is_tp9343()) {
  185. + ath79_gpio_pdata.ngpios = QCA956X_GPIO_COUNT;
  186. + ath79_gpio_pdata.oe_inverted = 1;
  187. } else {
  188. BUG();
  189. }
  190. diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c
  191. index cc00839b7181..2024a0bb9144 100644
  192. --- a/arch/mips/ath79/early_printk.c
  193. +++ b/arch/mips/ath79/early_printk.c
  194. @@ -120,6 +120,8 @@ static void prom_putchar_init(void)
  195. case REV_ID_MAJOR_QCA9533_V2:
  196. case REV_ID_MAJOR_QCA9556:
  197. case REV_ID_MAJOR_QCA9558:
  198. + case REV_ID_MAJOR_TP9343:
  199. + case REV_ID_MAJOR_QCA956X:
  200. _prom_putchar = prom_putchar_ar71xx;
  201. break;
  202. diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
  203. index 756b5aee3500..58d17ef6f58f 100644
  204. --- a/arch/mips/ath79/irq.c
  205. +++ b/arch/mips/ath79/irq.c
  206. @@ -156,6 +156,87 @@ static void qca955x_irq_init(void)
  207. irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
  208. }
  209. +static void qca956x_ip2_irq_dispatch(struct irq_desc *desc)
  210. +{
  211. + u32 status;
  212. +
  213. + status = ath79_reset_rr(QCA956X_RESET_REG_EXT_INT_STATUS);
  214. + status &= QCA956X_EXT_INT_PCIE_RC1_ALL | QCA956X_EXT_INT_WMAC_ALL;
  215. +
  216. + if (status == 0) {
  217. + spurious_interrupt();
  218. + return;
  219. + }
  220. +
  221. + if (status & QCA956X_EXT_INT_PCIE_RC1_ALL) {
  222. + /* TODO: flush DDR? */
  223. + generic_handle_irq(ATH79_IP2_IRQ(0));
  224. + }
  225. +
  226. + if (status & QCA956X_EXT_INT_WMAC_ALL) {
  227. + /* TODO: flsuh DDR? */
  228. + generic_handle_irq(ATH79_IP2_IRQ(1));
  229. + }
  230. +}
  231. +
  232. +static void qca956x_ip3_irq_dispatch(struct irq_desc *desc)
  233. +{
  234. + u32 status;
  235. +
  236. + status = ath79_reset_rr(QCA956X_RESET_REG_EXT_INT_STATUS);
  237. + status &= QCA956X_EXT_INT_PCIE_RC2_ALL |
  238. + QCA956X_EXT_INT_USB1 | QCA956X_EXT_INT_USB2;
  239. +
  240. + if (status == 0) {
  241. + spurious_interrupt();
  242. + return;
  243. + }
  244. +
  245. + if (status & QCA956X_EXT_INT_USB1) {
  246. + /* TODO: flush DDR? */
  247. + generic_handle_irq(ATH79_IP3_IRQ(0));
  248. + }
  249. +
  250. + if (status & QCA956X_EXT_INT_USB2) {
  251. + /* TODO: flush DDR? */
  252. + generic_handle_irq(ATH79_IP3_IRQ(1));
  253. + }
  254. +
  255. + if (status & QCA956X_EXT_INT_PCIE_RC2_ALL) {
  256. + /* TODO: flush DDR? */
  257. + generic_handle_irq(ATH79_IP3_IRQ(2));
  258. + }
  259. +}
  260. +
  261. +static void qca956x_enable_timer_cb(void) {
  262. + u32 misc;
  263. +
  264. + misc = ath79_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
  265. + misc |= MISC_INT_MIPS_SI_TIMERINT_MASK;
  266. + ath79_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, misc);
  267. +}
  268. +
  269. +static void qca956x_irq_init(void)
  270. +{
  271. + int i;
  272. +
  273. + for (i = ATH79_IP2_IRQ_BASE;
  274. + i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
  275. + irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq);
  276. +
  277. + irq_set_chained_handler(ATH79_CPU_IRQ(2), qca956x_ip2_irq_dispatch);
  278. +
  279. + for (i = ATH79_IP3_IRQ_BASE;
  280. + i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++)
  281. + irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq);
  282. +
  283. + irq_set_chained_handler(ATH79_CPU_IRQ(3), qca956x_ip3_irq_dispatch);
  284. +
  285. + /* QCA956x timer init workaround has to be applied right before setting
  286. + * up the clock. Else, there will be no jiffies */
  287. + late_time_init = &qca956x_enable_timer_cb;
  288. +}
  289. +
  290. void __init arch_init_irq(void)
  291. {
  292. unsigned irq_wb_chan2 = -1;
  293. @@ -183,7 +264,9 @@ void __init arch_init_irq(void)
  294. soc_is_ar933x() ||
  295. soc_is_ar934x() ||
  296. soc_is_qca953x() ||
  297. - soc_is_qca955x())
  298. + soc_is_qca955x() ||
  299. + soc_is_qca956x() ||
  300. + soc_is_tp9343())
  301. misc_is_ar71xx = false;
  302. else
  303. BUG();
  304. @@ -197,4 +280,6 @@ void __init arch_init_irq(void)
  305. qca953x_irq_init();
  306. else if (soc_is_qca955x())
  307. qca955x_irq_init();
  308. + else if (soc_is_qca956x() || soc_is_tp9343())
  309. + qca956x_irq_init();
  310. }
  311. diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
  312. index b816cb4a25ff..d905a67e1a07 100644
  313. --- a/arch/mips/ath79/pci.c
  314. +++ b/arch/mips/ath79/pci.c
  315. @@ -82,6 +82,9 @@ int pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
  316. } else if (soc_is_qca955x()) {
  317. ath79_pci_irq_map = qca955x_pci_irq_map;
  318. ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map);
  319. + } else if (soc_is_qca956x()) {
  320. + ath79_pci_irq_map = qca956x_pci_irq_map;
  321. + ath79_pci_nr_irqs = ARRAY_SIZE(qca956x_pci_irq_map);
  322. } else {
  323. pr_crit("pci %s: invalid irq map\n",
  324. pci_name((struct pci_dev *) dev));
  325. @@ -261,6 +264,15 @@ int __init ath79_register_pci(void)
  326. QCA955X_PCI_MEM_SIZE,
  327. 1,
  328. ATH79_IP3_IRQ(2));
  329. + } else if (soc_is_qca956x()) {
  330. + pdev = ath79_register_pci_ar724x(0,
  331. + QCA956X_PCI_CFG_BASE1,
  332. + QCA956X_PCI_CTRL_BASE1,
  333. + QCA956X_PCI_CRP_BASE1,
  334. + QCA956X_PCI_MEM_BASE1,
  335. + QCA956X_PCI_MEM_SIZE,
  336. + 1,
  337. + ATH79_IP3_IRQ(2));
  338. } else {
  339. /* No PCI support */
  340. return -ENODEV;
  341. diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
  342. index f782ae6c77d6..4c7a93f4039a 100644
  343. --- a/arch/mips/ath79/setup.c
  344. +++ b/arch/mips/ath79/setup.c
  345. @@ -176,6 +176,18 @@ static void __init ath79_detect_sys_type(void)
  346. rev = id & QCA955X_REV_ID_REVISION_MASK;
  347. break;
  348. + case REV_ID_MAJOR_QCA956X:
  349. + ath79_soc = ATH79_SOC_QCA956X;
  350. + chip = "956X";
  351. + rev = id & QCA956X_REV_ID_REVISION_MASK;
  352. + break;
  353. +
  354. + case REV_ID_MAJOR_TP9343:
  355. + ath79_soc = ATH79_SOC_TP9343;
  356. + chip = "9343";
  357. + rev = id & QCA956X_REV_ID_REVISION_MASK;
  358. + break;
  359. +
  360. default:
  361. panic("ath79: unknown SoC, id:0x%08x", id);
  362. }
  363. @@ -183,9 +195,12 @@ static void __init ath79_detect_sys_type(void)
  364. if (ver == 1)
  365. ath79_soc_rev = rev;
  366. - if (soc_is_qca953x() || soc_is_qca955x())
  367. + if (soc_is_qca953x() || soc_is_qca955x() || soc_is_qca956x())
  368. sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s ver %u rev %u",
  369. chip, ver, rev);
  370. + else if (soc_is_tp9343())
  371. + sprintf(ath79_sys_type, "Qualcomm Atheros TP%s rev %u",
  372. + chip, rev);
  373. else
  374. sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
  375. pr_info("SoC: %s\n", ath79_sys_type);
  376. diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h
  377. index 98a7ccf3d358..73dcd63b8243 100644
  378. --- a/arch/mips/include/asm/mach-ath79/ath79.h
  379. +++ b/arch/mips/include/asm/mach-ath79/ath79.h
  380. @@ -35,6 +35,8 @@ enum ath79_soc_type {
  381. ATH79_SOC_QCA9533,
  382. ATH79_SOC_QCA9556,
  383. ATH79_SOC_QCA9558,
  384. + ATH79_SOC_TP9343,
  385. + ATH79_SOC_QCA956X,
  386. };
  387. extern enum ath79_soc_type ath79_soc;
  388. @@ -126,6 +128,26 @@ static inline int soc_is_qca955x(void)
  389. return soc_is_qca9556() || soc_is_qca9558();
  390. }
  391. +static inline int soc_is_tp9343(void)
  392. +{
  393. + return ath79_soc == ATH79_SOC_TP9343;
  394. +}
  395. +
  396. +static inline int soc_is_qca9561(void)
  397. +{
  398. + return ath79_soc == ATH79_SOC_QCA956X;
  399. +}
  400. +
  401. +static inline int soc_is_qca9563(void)
  402. +{
  403. + return ath79_soc == ATH79_SOC_QCA956X;
  404. +}
  405. +
  406. +static inline int soc_is_qca956x(void)
  407. +{
  408. + return soc_is_qca9561() || soc_is_qca9563();
  409. +}
  410. +
  411. void ath79_ddr_wb_flush(unsigned int reg);
  412. void ath79_ddr_set_pci_windows(void);
  413. --
  414. 2.11.0