2 * Cisco Meraki MR18 board support
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>
8 * Based on Cisco Meraki GPL Release r23-20150601 MR18 Device Config
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.
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>
19 #include <asm/mach-ath79/ath79.h>
20 #include <asm/mach-ath79/ar71xx_regs.h>
22 #include <linux/leds-nu801.h>
23 #include <linux/pci.h>
28 #include "dev-gpio-buttons.h"
29 #include "dev-leds-gpio.h"
32 #include "machtypes.h"
34 #define MR18_GPIO_LED_POWER_WHITE 18
35 #define MR18_GPIO_LED_POWER_ORANGE 21
37 #define MR18_GPIO_BTN_RESET 17
38 #define MR18_KEYS_POLL_INTERVAL 20 /* msecs */
39 #define MR18_KEYS_DEBOUNCE_INTERVAL (3 * MR18_KEYS_POLL_INTERVAL)
41 #define MR18_WAN_PHYADDR 3
43 /* used for eth calibration */
44 #define MR18_OTP_BASE (AR71XX_APB_BASE + 0x130000)
45 #define MR18_OTP_SIZE (0x2000) /* just a guess */
46 #define MR18_OTP_MEM_0_REG (0x0000)
47 #define MR18_OTP_INTF2_REG (0x1008)
48 #define MR18_OTP_STATUS0_REG (0x1018)
49 #define MR18_OTP_STATUS0_EFUSE_VALID BIT(2)
51 #define MR18_OTP_STATUS1_REG (0x101c)
52 #define MR18_OTP_LDO_CTRL_REG (0x1024)
53 #define MR18_OTP_LDO_STATUS_REG (0x102c)
54 #define MR18_OTP_LDO_STATUS_POWER_ON BIT(0)
56 static struct gpio_led MR18_leds_gpio
[] __initdata
= {
58 .name
= "mr18:white:power",
59 .gpio
= MR18_GPIO_LED_POWER_WHITE
,
62 .name
= "mr18:orange:power",
63 .gpio
= MR18_GPIO_LED_POWER_ORANGE
,
68 static struct gpio_keys_button MR18_gpio_keys
[] __initdata
= {
73 .debounce_interval
= MR18_KEYS_DEBOUNCE_INTERVAL
,
74 .gpio
= MR18_GPIO_BTN_RESET
,
79 static struct led_nu801_template tricolor_led_template
= {
80 .device_name
= "mr18",
92 .default_trigger
= "none",
93 .led_colors
= { "red", "green", "blue" },
96 static struct led_nu801_platform_data tricolor_led_data
= {
98 .template = &tricolor_led_template
,
101 static struct platform_device tricolor_leds
= {
102 .name
= "leds-nu801",
104 .dev
.platform_data
= &tricolor_led_data
,
107 static int mr18_extract_sgmii_res_cal(void)
110 unsigned int reversed_sgmii_value
;
112 unsigned int otp_value
, otp_per_val
, rbias_per
, read_data
;
113 unsigned int rbias_pos_or_neg
;
114 unsigned int sgmii_res_cal_value
;
117 base
= ioremap_nocache(MR18_OTP_BASE
, MR18_OTP_SIZE
);
121 __raw_writel(0x7d, base
+ MR18_OTP_INTF2_REG
);
122 __raw_writel(0x00, base
+ MR18_OTP_LDO_CTRL_REG
);
124 while (__raw_readl(base
+ MR18_OTP_LDO_STATUS_REG
) &
125 MR18_OTP_LDO_STATUS_POWER_ON
);
127 __raw_readl(base
+ MR18_OTP_MEM_0_REG
+ 4);
129 while (!(__raw_readl(base
+ MR18_OTP_STATUS0_REG
) &
130 MR18_OTP_STATUS0_EFUSE_VALID
));
132 read_data
= __raw_readl(base
+ MR18_OTP_STATUS1_REG
);
136 if (!(read_data
& 0x1fff))
139 if (read_data
& 0x00001000)
140 otp_value
= (read_data
& 0xfc0) >> 6;
142 otp_value
= read_data
& 0x3f;
144 if (otp_value
> 31) {
145 otp_per_val
= 63 - otp_value
;
146 rbias_pos_or_neg
= 1;
148 otp_per_val
= otp_value
;
149 rbias_pos_or_neg
= 0;
152 rbias_per
= otp_per_val
* 15;
154 if (rbias_pos_or_neg
== 1)
155 res_cal_val
= (rbias_per
+ 34) / 21;
156 else if (rbias_per
> 34)
157 res_cal_val
= -((rbias_per
- 34) / 21);
159 res_cal_val
= (34 - rbias_per
) / 21;
161 sgmii_res_cal_value
= (8 + res_cal_val
) & 0xf;
163 reversed_sgmii_value
= (sgmii_res_cal_value
& 8) >> 3;
164 reversed_sgmii_value
|= (sgmii_res_cal_value
& 4) >> 1;
165 reversed_sgmii_value
|= (sgmii_res_cal_value
& 2) << 1;
166 reversed_sgmii_value
|= (sgmii_res_cal_value
& 1) << 3;
167 printk(KERN_INFO
"SGMII cal value = 0x%x\n", reversed_sgmii_value
);
168 return reversed_sgmii_value
;
171 #define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x004c
172 #define QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT BIT(2)
173 #define QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK BIT(1)
174 #define QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL BIT(0)
176 #define QCA955X_GMAC_REG_SGMII_SERDES 0x0018
177 #define QCA955X_SGMII_SERDES_RES_CALIBRATION BIT(23)
178 #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
179 #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
180 #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
182 static void mr18_setup_qca955x_eth_serdes_cal(unsigned int sgmii_value
)
184 void __iomem
*ethbase
, *pllbase
;
187 ethbase
= ioremap_nocache(QCA955X_GMAC_BASE
, QCA955X_GMAC_SIZE
);
188 pllbase
= ioremap_nocache(AR71XX_PLL_BASE
, AR71XX_PLL_SIZE
);
190 /* To Check the locking of the SGMII PLL */
191 t
= __raw_readl(ethbase
+ QCA955X_GMAC_REG_SGMII_SERDES
);
192 t
&= ~(QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK
<<
193 QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT
);
194 t
|= (sgmii_value
& QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK
) <<
195 QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT
;
196 __raw_writel(t
, ethbase
+ QCA955X_GMAC_REG_SGMII_SERDES
);
198 __raw_writel(QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT
|
199 QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK
|
200 QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL
,
201 pllbase
+ QCA955X_PLL_ETH_SGMII_SERDES_REG
);
203 ath79_device_reset_clear(QCA955X_RESET_SGMII_ANALOG
);
204 ath79_device_reset_clear(QCA955X_RESET_SGMII
);
206 while (!(__raw_readl(ethbase
+ QCA955X_GMAC_REG_SGMII_SERDES
) &
207 QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS
));
213 static struct ath9k_platform_data pci_main_wifi_data
= {
216 static struct ath9k_platform_data pci_scan_wifi_data
= {
220 static int mr18_dual_pci_plat_dev_init(struct pci_dev
*dev
)
222 /* The PCIE devices are attached to different busses but they
223 * both share the same slot number. Checking the PCI_SLOT vals
226 switch (dev
->bus
->number
) {
228 dev
->dev
.platform_data
= &pci_main_wifi_data
;
231 dev
->dev
.platform_data
= &pci_scan_wifi_data
;
238 static void __init
mr18_setup(void)
243 ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_SOFT_BCH
);
244 ath79_register_nfc();
246 /* even though, the PHY is connected via RGMII,
247 * the SGMII/SERDES PLLs need to be calibrated and locked.
248 * Or else, the PHY won't be working for this platfrom.
250 * Figuring this out took such a long time, that we want to
251 * point this quirk out, before someone wants to remove it.
253 res
= mr18_extract_sgmii_res_cal();
255 /* Setup SoC Eth Config */
256 ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN
, 3, 3, 0,
260 ath79_register_mdio(0, 0x0);
262 mr18_setup_qca955x_eth_serdes_cal(res
);
264 /* GMAC0 is connected to an Atheros AR8035-A */
265 ath79_init_mac(ath79_eth0_data
.mac_addr
, NULL
, 0);
266 ath79_eth0_data
.mii_bus_dev
= &ath79_mdio0_device
.dev
;
267 ath79_eth0_data
.phy_if_mode
= PHY_INTERFACE_MODE_RGMII
;
268 ath79_eth0_data
.phy_mask
= BIT(MR18_WAN_PHYADDR
);
269 ath79_eth0_pll_data
.pll_1000
= 0xa6000000;
270 ath79_eth0_pll_data
.pll_100
= 0xa0000101;
271 ath79_eth0_pll_data
.pll_10
= 0x80001313;
272 ath79_register_eth(0);
274 printk(KERN_ERR
"failed to read EFUSE for ethernet cal\n");
277 /* LEDs and Buttons */
278 platform_device_register(&tricolor_leds
);
279 ath79_register_leds_gpio(-1, ARRAY_SIZE(MR18_leds_gpio
),
281 ath79_register_gpio_keys_polled(-1, MR18_KEYS_POLL_INTERVAL
,
282 ARRAY_SIZE(MR18_gpio_keys
),
285 /* Clear RTC reset (Needed by SoC WiFi) */
286 ath79_device_reset_clear(QCA955X_RESET_RTC
);
289 ath79_register_wmac_simple();
291 pci_main_wifi_data
.eeprom_name
= "pci_wmac0.eeprom";
292 pci_scan_wifi_data
.eeprom_name
= "pci_wmac1.eeprom";
293 ath79_pci_set_plat_dev_init(mr18_dual_pci_plat_dev_init
);
294 ath79_register_pci();
296 MIPS_MACHINE(ATH79_MACH_MR18
, "MR18", "Meraki MR18", mr18_setup
);