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
19#include <asm/mach-ath79/ath79.h>
20#include <asm/mach-ath79/ar71xx_regs.h>
21
22#include <linux/leds-nu801.h>
23#include <linux/pci.h>
24
25#include "common.h"
26#include "dev-eth.h"
27#include "pci.h"
28#include "dev-gpio-buttons.h"
29#include "dev-leds-gpio.h"
30#include "dev-nfc.h"
31#include "dev-wmac.h"
32#include "machtypes.h"
33
34#define MR18_GPIO_LED_POWER_WHITE    18
35#define MR18_GPIO_LED_POWER_ORANGE    21
36
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)
40
41#define MR18_WAN_PHYADDR    3
42
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)
50
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)
55
56static struct gpio_led MR18_leds_gpio[] __initdata = {
57	{
58		.name = "mr18:white:power",
59		.gpio = MR18_GPIO_LED_POWER_WHITE,
60		.active_low  = 1,
61	}, {
62		.name = "mr18:orange:power",
63		.gpio = MR18_GPIO_LED_POWER_ORANGE,
64		.active_low  = 0,
65	},
66};
67
68static struct gpio_keys_button MR18_gpio_keys[] __initdata = {
69	{
70		.desc = "reset",
71		.type = EV_KEY,
72		.code = KEY_RESTART,
73		.debounce_interval = MR18_KEYS_DEBOUNCE_INTERVAL,
74		.gpio    = MR18_GPIO_BTN_RESET,
75		.active_low  = 1,
76	},
77};
78
79static struct led_nu801_template tricolor_led_template = {
80	.device_name = "mr18",
81	.name = "tricolor",
82	.num_leds = 1,
83	.cki = 11,
84	.sdi = 12,
85	.lei = -1,
86	.ndelay = 500,
87	.init_brightness = {
88		LED_OFF,
89		LED_OFF,
90		LED_OFF,
91	},
92	.default_trigger = "none",
93	.led_colors = { "red", "green", "blue" },
94};
95
96static struct led_nu801_platform_data tricolor_led_data = {
97	.num_controllers = 1,
98	.template = &tricolor_led_template,
99};
100
101static struct platform_device tricolor_leds = {
102	.name = "leds-nu801",
103	.id = -1,
104	.dev.platform_data = &tricolor_led_data,
105};
106
107static int mr18_extract_sgmii_res_cal(void)
108{
109	void __iomem *base;
110	unsigned int reversed_sgmii_value;
111
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;
115	int res_cal_val;
116
117	base = ioremap_nocache(MR18_OTP_BASE, MR18_OTP_SIZE);
118	if (!base)
119		return -EIO;
120
121	__raw_writel(0x7d, base + MR18_OTP_INTF2_REG);
122	__raw_writel(0x00, base + MR18_OTP_LDO_CTRL_REG);
123
124	while (__raw_readl(base + MR18_OTP_LDO_STATUS_REG) &
125		MR18_OTP_LDO_STATUS_POWER_ON);
126
127	__raw_readl(base + MR18_OTP_MEM_0_REG + 4);
128
129	while (!(__raw_readl(base + MR18_OTP_STATUS0_REG) &
130		MR18_OTP_STATUS0_EFUSE_VALID));
131
132	read_data = __raw_readl(base + MR18_OTP_STATUS1_REG);
133
134	iounmap(base);
135
136	if (!(read_data & 0x1fff))
137		return -ENODEV;
138
139	if (read_data & 0x00001000)
140		otp_value = (read_data & 0xfc0) >> 6;
141	else
142		otp_value = read_data & 0x3f;
143
144	if (otp_value > 31) {
145		otp_per_val = 63 - otp_value;
146		rbias_pos_or_neg = 1;
147	} else {
148		otp_per_val = otp_value;
149		rbias_pos_or_neg = 0;
150	}
151
152	rbias_per = otp_per_val * 15;
153
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);
158	else
159		res_cal_val = (34 - rbias_per) / 21;
160
161	sgmii_res_cal_value = (8 + res_cal_val) & 0xf;
162
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;
169}
170
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)
175
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)
181
182static void mr18_setup_qca955x_eth_serdes_cal(unsigned int sgmii_value)
183{
184	void __iomem *ethbase, *pllbase;
185	u32 t;
186
187	ethbase = ioremap_nocache(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE);
188	pllbase = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE);
189
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);
197
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);
202
203	ath79_device_reset_clear(QCA955X_RESET_SGMII_ANALOG);
204	ath79_device_reset_clear(QCA955X_RESET_SGMII);
205
206	while (!(__raw_readl(ethbase + QCA955X_GMAC_REG_SGMII_SERDES) &
207		QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS));
208
209	iounmap(ethbase);
210	iounmap(pllbase);
211}
212
213static struct ath9k_platform_data pci_main_wifi_data = {
214	.led_pin = -1,
215};
216static struct ath9k_platform_data pci_scan_wifi_data = {
217	.led_pin = -1,
218};
219
220static int mr18_dual_pci_plat_dev_init(struct pci_dev *dev)
221{
222	/* The PCIE devices are attached to different busses but they
223	 * both share the same slot number. Checking the PCI_SLOT vals
224	 * does not work.
225	 */
226	switch (dev->bus->number) {
227	case 0:
228		dev->dev.platform_data = &pci_main_wifi_data;
229		break;
230	case 1:
231		dev->dev.platform_data = &pci_scan_wifi_data;
232		break;
233	}
234
235	return 0;
236}
237
238static void __init mr18_setup(void)
239{
240	int res;
241
242	/* NAND */
243	ath79_nfc_set_ecc_mode(AR934X_NFC_ECC_SOFT_BCH);
244	ath79_register_nfc();
245
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.
249	 *
250	 * Figuring this out took such a long time, that we want to
251	 * point this quirk out, before someone wants to remove it.
252	 */
253	res = mr18_extract_sgmii_res_cal();
254	if (res >= 0) {
255		/* Setup SoC Eth Config */
256		ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN |
257			(3 << QCA955X_ETH_CFG_RXD_DELAY_SHIFT) |
258			(3 << QCA955X_ETH_CFG_RDV_DELAY_SHIFT));
259
260		/* MDIO Interface */
261		ath79_register_mdio(0, 0x0);
262
263		mr18_setup_qca955x_eth_serdes_cal(res);
264
265		/* GMAC0 is connected to an Atheros AR8035-A */
266		ath79_init_mac(ath79_eth0_data.mac_addr, NULL, 0);
267		ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
268		ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
269		ath79_eth0_data.phy_mask = BIT(MR18_WAN_PHYADDR);
270		ath79_eth0_pll_data.pll_1000 = 0xa6000000;
271		ath79_eth0_pll_data.pll_100 = 0xa0000101;
272		ath79_eth0_pll_data.pll_10 = 0x80001313;
273		ath79_register_eth(0);
274	} else {
275		printk(KERN_ERR "failed to read EFUSE for ethernet cal\n");
276	}
277
278	/* LEDs and Buttons */
279	platform_device_register(&tricolor_leds);
280	ath79_register_leds_gpio(-1, ARRAY_SIZE(MR18_leds_gpio),
281				 MR18_leds_gpio);
282	ath79_register_gpio_keys_polled(-1, MR18_KEYS_POLL_INTERVAL,
283					ARRAY_SIZE(MR18_gpio_keys),
284					MR18_gpio_keys);
285
286	/* Clear RTC reset (Needed by SoC WiFi) */
287	ath79_device_reset_clear(QCA955X_RESET_RTC);
288
289	/* WiFi */
290	ath79_register_wmac_simple();
291
292	pci_main_wifi_data.eeprom_name = "pci_wmac0.eeprom";
293	pci_scan_wifi_data.eeprom_name = "pci_wmac1.eeprom";
294	ath79_pci_set_plat_dev_init(mr18_dual_pci_plat_dev_init);
295	ath79_register_pci();
296}
297MIPS_MACHINE(ATH79_MACH_MR18, "MR18", "Meraki MR18", mr18_setup);
298