mach-mr18.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Cisco Meraki MR18 board support
  3. *
  4. * Copyright (C) 2015 Chris Blake <chrisrblake93@gmail.com>
  5. * Copyright (C) 2015 Christian Lamparter <chunkeey@googlemail.com>
  6. * Copyright (C) 2015 Thomas Hebb <tommyhebb@gmail.com>
  7. *
  8. * Based on Cisco Meraki GPL Release r23-20150601 MR18 Device Config
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License version 2 as published
  12. * by the Free Software Foundation.
  13. */
  14. #include <linux/platform_device.h>
  15. #include <linux/ath9k_platform.h>
  16. #include <linux/platform/ar934x_nfc.h>
  17. #include <linux/platform_data/phy-at803x.h>
  18. #include <asm/mach-ath79/ath79.h>
  19. #include <asm/mach-ath79/ar71xx_regs.h>
  20. #include <linux/leds-nu801.h>
  21. #include <linux/pci.h>
  22. #include "common.h"
  23. #include "dev-eth.h"
  24. #include "pci.h"
  25. #include "dev-gpio-buttons.h"
  26. #include "dev-leds-gpio.h"
  27. #include "dev-nfc.h"
  28. #include "dev-wmac.h"
  29. #include "machtypes.h"
  30. #define MR18_GPIO_LED_POWER_WHITE 18
  31. #define MR18_GPIO_LED_POWER_ORANGE 21
  32. #define MR18_GPIO_BTN_RESET 17
  33. #define MR18_KEYS_POLL_INTERVAL 20 /* msecs */
  34. #define MR18_KEYS_DEBOUNCE_INTERVAL (3 * MR18_KEYS_POLL_INTERVAL)
  35. #define MR18_WAN_PHYADDR 3
  36. /* used for eth calibration */
  37. #define MR18_OTP_BASE (AR71XX_APB_BASE + 0x130000)
  38. #define MR18_OTP_SIZE (0x2000) /* just a guess */
  39. #define MR18_OTP_MEM_0_REG (0x0000)
  40. #define MR18_OTP_INTF2_REG (0x1008)
  41. #define MR18_OTP_STATUS0_REG (0x1018)
  42. #define MR18_OTP_STATUS0_EFUSE_VALID BIT(2)
  43. #define MR18_OTP_STATUS1_REG (0x101c)
  44. #define MR18_OTP_LDO_CTRL_REG (0x1024)
  45. #define MR18_OTP_LDO_STATUS_REG (0x102c)
  46. #define MR18_OTP_LDO_STATUS_POWER_ON BIT(0)
  47. static struct gpio_led MR18_leds_gpio[] __initdata = {
  48. {
  49. .name = "mr18:white:power",
  50. .gpio = MR18_GPIO_LED_POWER_WHITE,
  51. .active_low = 1,
  52. }, {
  53. .name = "mr18:orange:power",
  54. .gpio = MR18_GPIO_LED_POWER_ORANGE,
  55. .active_low = 0,
  56. },
  57. };
  58. static struct gpio_keys_button MR18_gpio_keys[] __initdata = {
  59. {
  60. .desc = "reset",
  61. .type = EV_KEY,
  62. .code = KEY_RESTART,
  63. .debounce_interval = MR18_KEYS_DEBOUNCE_INTERVAL,
  64. .gpio = MR18_GPIO_BTN_RESET,
  65. .active_low = 1,
  66. },
  67. };
  68. static struct led_nu801_template tricolor_led_template = {
  69. .device_name = "mr18",
  70. .name = "tricolor",
  71. .num_leds = 1,
  72. .cki = 11,
  73. .sdi = 12,
  74. .lei = -1,
  75. .ndelay = 500,
  76. .init_brightness = {
  77. LED_OFF,
  78. LED_OFF,
  79. LED_OFF,
  80. },
  81. .default_trigger = "none",
  82. .led_colors = { "red", "green", "blue" },
  83. };
  84. static struct led_nu801_platform_data tricolor_led_data = {
  85. .num_controllers = 1,
  86. .template = &tricolor_led_template,
  87. };
  88. static struct platform_device tricolor_leds = {
  89. .name = "leds-nu801",
  90. .id = -1,
  91. .dev.platform_data = &tricolor_led_data,
  92. };
  93. static int mr18_extract_sgmii_res_cal(void)
  94. {
  95. void __iomem *base;
  96. unsigned int reversed_sgmii_value;
  97. unsigned int otp_value, otp_per_val, rbias_per, read_data;
  98. unsigned int rbias_pos_or_neg;
  99. unsigned int sgmii_res_cal_value;
  100. int res_cal_val;
  101. base = ioremap_nocache(MR18_OTP_BASE, MR18_OTP_SIZE);
  102. if (!base)
  103. return -EIO;
  104. __raw_writel(0x7d, base + MR18_OTP_INTF2_REG);
  105. __raw_writel(0x00, base + MR18_OTP_LDO_CTRL_REG);
  106. while (__raw_readl(base + MR18_OTP_LDO_STATUS_REG) &
  107. MR18_OTP_LDO_STATUS_POWER_ON);
  108. __raw_readl(base + MR18_OTP_MEM_0_REG + 4);
  109. while (!(__raw_readl(base + MR18_OTP_STATUS0_REG) &
  110. MR18_OTP_STATUS0_EFUSE_VALID));
  111. read_data = __raw_readl(base + MR18_OTP_STATUS1_REG);
  112. iounmap(base);
  113. if (!(read_data & 0x1fff))
  114. return -ENODEV;
  115. if (read_data & 0x00001000)
  116. otp_value = (read_data & 0xfc0) >> 6;
  117. else
  118. otp_value = read_data & 0x3f;
  119. if (otp_value > 31) {
  120. otp_per_val = 63 - otp_value;
  121. rbias_pos_or_neg = 1;
  122. } else {
  123. otp_per_val = otp_value;
  124. rbias_pos_or_neg = 0;
  125. }
  126. rbias_per = otp_per_val * 15;
  127. if (rbias_pos_or_neg == 1)
  128. res_cal_val = (rbias_per + 34) / 21;
  129. else if (rbias_per > 34)
  130. res_cal_val = -((rbias_per - 34) / 21);
  131. else
  132. res_cal_val = (34 - rbias_per) / 21;
  133. sgmii_res_cal_value = (8 + res_cal_val) & 0xf;
  134. reversed_sgmii_value = (sgmii_res_cal_value & 8) >> 3;
  135. reversed_sgmii_value |= (sgmii_res_cal_value & 4) >> 1;
  136. reversed_sgmii_value |= (sgmii_res_cal_value & 2) << 1;
  137. reversed_sgmii_value |= (sgmii_res_cal_value & 1) << 3;
  138. printk(KERN_INFO "SGMII cal value = 0x%x\n", reversed_sgmii_value);
  139. return reversed_sgmii_value;
  140. }
  141. #define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x004c
  142. #define QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT BIT(2)
  143. #define QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK BIT(1)
  144. #define QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL BIT(0)
  145. #define QCA955X_GMAC_REG_SGMII_SERDES 0x0018
  146. #define QCA955X_SGMII_SERDES_RES_CALIBRATION BIT(23)
  147. #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
  148. #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
  149. #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
  150. static void mr18_setup_qca955x_eth_serdes_cal(unsigned int sgmii_value)
  151. {
  152. void __iomem *ethbase, *pllbase;
  153. u32 t;
  154. ethbase = ioremap_nocache(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE);
  155. pllbase = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE);
  156. /* To Check the locking of the SGMII PLL */
  157. t = __raw_readl(ethbase + QCA955X_GMAC_REG_SGMII_SERDES);
  158. t &= ~(QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK <<
  159. QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT);
  160. t |= (sgmii_value & QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK) <<
  161. QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT;
  162. __raw_writel(t, ethbase + QCA955X_GMAC_REG_SGMII_SERDES);
  163. __raw_writel(QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT |
  164. QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK |
  165. QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL,
  166. pllbase + QCA955X_PLL_ETH_SGMII_SERDES_REG);
  167. ath79_device_reset_clear(QCA955X_RESET_SGMII_ANALOG);
  168. ath79_device_reset_clear(QCA955X_RESET_SGMII);
  169. while (!(__raw_readl(ethbase + QCA955X_GMAC_REG_SGMII_SERDES) &
  170. QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS));
  171. iounmap(ethbase);
  172. iounmap(pllbase);
  173. }
  174. static struct ath9k_platform_data pci_main_wifi_data = {
  175. .led_pin = -1,
  176. };
  177. static struct ath9k_platform_data pci_scan_wifi_data = {
  178. .led_pin = -1,
  179. };
  180. static int mr18_dual_pci_plat_dev_init(struct pci_dev *dev)
  181. {
  182. /* The PCIE devices are attached to different busses but they
  183. * both share the same slot number. Checking the PCI_SLOT vals
  184. * does not work.
  185. */
  186. switch (dev->bus->number) {
  187. case 0:
  188. dev->dev.platform_data = &pci_main_wifi_data;
  189. break;
  190. case 1:
  191. dev->dev.platform_data = &pci_scan_wifi_data;
  192. break;
  193. }
  194. return 0;
  195. }
  196. static void __init mr18_setup(void)
  197. {
  198. int res;
  199. /* NAND */
  200. ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_SOFT_BCH);
  201. ath79_register_nfc();
  202. /* even though, the PHY is connected via RGMII,
  203. * the SGMII/SERDES PLLs need to be calibrated and locked.
  204. * Or else, the PHY won't be working for this platfrom.
  205. *
  206. * Figuring this out took such a long time, that we want to
  207. * point this quirk out, before someone wants to remove it.
  208. */
  209. res = mr18_extract_sgmii_res_cal();
  210. if (res >= 0) {
  211. /* Setup SoC Eth Config */
  212. ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN |
  213. (3 << QCA955X_ETH_CFG_RXD_DELAY_SHIFT) |
  214. (3 << QCA955X_ETH_CFG_RDV_DELAY_SHIFT));
  215. /* MDIO Interface */
  216. ath79_register_mdio(0, 0x0);
  217. mr18_setup_qca955x_eth_serdes_cal(res);
  218. /* GMAC0 is connected to an Atheros AR8035-A */
  219. ath79_init_mac(ath79_eth0_data.mac_addr, NULL, 0);
  220. ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
  221. ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
  222. ath79_eth0_data.phy_mask = BIT(MR18_WAN_PHYADDR);
  223. ath79_eth0_pll_data.pll_1000 = 0xa6000000;
  224. ath79_eth0_pll_data.pll_100 = 0xa0000101;
  225. ath79_eth0_pll_data.pll_10 = 0x80001313;
  226. ath79_register_eth(0);
  227. } else {
  228. printk(KERN_ERR "failed to read EFUSE for ethernet cal\n");
  229. }
  230. /* LEDs and Buttons */
  231. platform_device_register(&tricolor_leds);
  232. ath79_register_leds_gpio(-1, ARRAY_SIZE(MR18_leds_gpio),
  233. MR18_leds_gpio);
  234. ath79_register_gpio_keys_polled(-1, MR18_KEYS_POLL_INTERVAL,
  235. ARRAY_SIZE(MR18_gpio_keys),
  236. MR18_gpio_keys);
  237. /* Clear RTC reset (Needed by SoC WiFi) */
  238. ath79_device_reset_clear(QCA955X_RESET_RTC);
  239. /* WiFi */
  240. ath79_register_wmac_simple();
  241. pci_main_wifi_data.eeprom_name = "pci_wmac0.eeprom";
  242. pci_scan_wifi_data.eeprom_name = "pci_wmac1.eeprom";
  243. ath79_pci_set_plat_dev_init(mr18_dual_pci_plat_dev_init);
  244. ath79_register_pci();
  245. }
  246. MIPS_MACHINE(ATH79_MACH_MR18, "MR18", "Meraki MR18", mr18_setup);