1/*
2 *  Senao EAP7660D board support
3 *
4 *  Copyright (C) 2010 Daniel Golle <daniel.golle@gmail.com>
5 *  Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
6 *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7 *
8 *  This program is free software; you can redistribute it and/or modify it
9 *  under the terms of the GNU General Public License version 2 as published
10 *  by the Free Software Foundation.
11 */
12
13#include <linux/pci.h>
14#include <linux/ath5k_platform.h>
15#include <linux/delay.h>
16
17#include <asm/mach-ath79/ath79.h>
18
19#include "dev-eth.h"
20#include "dev-gpio-buttons.h"
21#include "dev-leds-gpio.h"
22#include "dev-m25p80.h"
23#include "machtypes.h"
24#include "pci.h"
25
26#define EAP7660D_KEYS_POLL_INTERVAL	20	/* msecs */
27#define EAP7660D_KEYS_DEBOUNCE_INTERVAL	(3 * EAP7660D_KEYS_POLL_INTERVAL)
28
29#define EAP7660D_GPIO_DS4		7
30#define EAP7660D_GPIO_DS5		2
31#define EAP7660D_GPIO_DS7		0
32#define EAP7660D_GPIO_DS8		4
33#define EAP7660D_GPIO_SW1		3
34#define EAP7660D_GPIO_SW3		8
35#define EAP7660D_PHYMASK		BIT(20)
36#define EAP7660D_BOARDCONFIG		0x1F7F0000
37#define EAP7660D_GBIC_MAC_OFFSET	0x1000
38#define EAP7660D_WMAC0_MAC_OFFSET	0x1010
39#define EAP7660D_WMAC1_MAC_OFFSET	0x1016
40#define EAP7660D_WMAC0_CALDATA_OFFSET	0x2000
41#define EAP7660D_WMAC1_CALDATA_OFFSET	0x3000
42
43#ifdef CONFIG_PCI
44static struct ath5k_platform_data eap7660d_wmac0_data;
45static struct ath5k_platform_data eap7660d_wmac1_data;
46static char eap7660d_wmac0_mac[6];
47static char eap7660d_wmac1_mac[6];
48static u16 eap7660d_wmac0_eeprom[ATH5K_PLAT_EEP_MAX_WORDS];
49static u16 eap7660d_wmac1_eeprom[ATH5K_PLAT_EEP_MAX_WORDS];
50
51static int eap7660d_pci_plat_dev_init(struct pci_dev *dev)
52{
53	switch (PCI_SLOT(dev->devfn)) {
54	case 17:
55		dev->dev.platform_data = &eap7660d_wmac0_data;
56		break;
57
58	case 18:
59		dev->dev.platform_data = &eap7660d_wmac1_data;
60		break;
61	}
62
63	return 0;
64}
65
66void __init eap7660d_pci_init(u8 *cal_data0, u8 *mac_addr0,
67			      u8 *cal_data1, u8 *mac_addr1)
68{
69	if (cal_data0 && *cal_data0 == 0xa55a) {
70		memcpy(eap7660d_wmac0_eeprom, cal_data0,
71			ATH5K_PLAT_EEP_MAX_WORDS);
72		eap7660d_wmac0_data.eeprom_data = eap7660d_wmac0_eeprom;
73	}
74
75	if (cal_data1 && *cal_data1 == 0xa55a) {
76		memcpy(eap7660d_wmac1_eeprom, cal_data1,
77			ATH5K_PLAT_EEP_MAX_WORDS);
78		eap7660d_wmac1_data.eeprom_data = eap7660d_wmac1_eeprom;
79	}
80
81	if (mac_addr0) {
82		memcpy(eap7660d_wmac0_mac, mac_addr0,
83			sizeof(eap7660d_wmac0_mac));
84		eap7660d_wmac0_data.macaddr = eap7660d_wmac0_mac;
85	}
86
87	if (mac_addr1) {
88		memcpy(eap7660d_wmac1_mac, mac_addr1,
89			sizeof(eap7660d_wmac1_mac));
90		eap7660d_wmac1_data.macaddr = eap7660d_wmac1_mac;
91	}
92
93	ath79_pci_set_plat_dev_init(eap7660d_pci_plat_dev_init);
94	ath79_register_pci();
95}
96#else
97static inline void eap7660d_pci_init(u8 *cal_data0, u8 *mac_addr0,
98				     u8 *cal_data1, u8 *mac_addr1)
99{
100}
101#endif /* CONFIG_PCI */
102
103static struct gpio_led eap7660d_leds_gpio[] __initdata = {
104	{
105		.name		= "eap7660d:green:ds8",
106		.gpio		= EAP7660D_GPIO_DS8,
107		.active_low	= 0,
108	},
109	{
110		.name		= "eap7660d:green:ds5",
111		.gpio		= EAP7660D_GPIO_DS5,
112		.active_low	= 0,
113	},
114	{
115		.name		= "eap7660d:green:ds7",
116		.gpio		= EAP7660D_GPIO_DS7,
117		.active_low	= 0,
118	},
119	{
120		.name		= "eap7660d:green:ds4",
121		.gpio		= EAP7660D_GPIO_DS4,
122		.active_low	= 0,
123	}
124};
125
126static struct gpio_keys_button eap7660d_gpio_keys[] __initdata = {
127	{
128		.desc		= "reset",
129		.type		= EV_KEY,
130		.code		= KEY_RESTART,
131		.debounce_interval = EAP7660D_KEYS_DEBOUNCE_INTERVAL,
132		.gpio		= EAP7660D_GPIO_SW1,
133		.active_low	= 1,
134	},
135	{
136		.desc		= "wps",
137		.type		= EV_KEY,
138		.code		= KEY_WPS_BUTTON,
139		.debounce_interval = EAP7660D_KEYS_DEBOUNCE_INTERVAL,
140		.gpio		= EAP7660D_GPIO_SW3,
141		.active_low	= 1,
142	}
143};
144
145static const char *eap7660d_part_probes[] = {
146	"RedBoot",
147	NULL,
148};
149
150static struct flash_platform_data eap7660d_flash_data = {
151	.part_probes	= eap7660d_part_probes,
152};
153
154static void __init eap7660d_setup(void)
155{
156	u8 *boardconfig = (u8 *) KSEG1ADDR(EAP7660D_BOARDCONFIG);
157
158	ath79_register_mdio(0, ~EAP7660D_PHYMASK);
159
160	ath79_init_mac(ath79_eth0_data.mac_addr,
161			boardconfig + EAP7660D_GBIC_MAC_OFFSET, 0);
162	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
163	ath79_eth0_data.phy_mask = EAP7660D_PHYMASK;
164	ath79_register_eth(0);
165	ath79_register_m25p80(&eap7660d_flash_data);
166	ath79_register_leds_gpio(-1, ARRAY_SIZE(eap7660d_leds_gpio),
167					eap7660d_leds_gpio);
168	ath79_register_gpio_keys_polled(-1, EAP7660D_KEYS_POLL_INTERVAL,
169					 ARRAY_SIZE(eap7660d_gpio_keys),
170					 eap7660d_gpio_keys);
171	eap7660d_pci_init(boardconfig + EAP7660D_WMAC0_CALDATA_OFFSET,
172			  boardconfig + EAP7660D_WMAC0_MAC_OFFSET,
173			  boardconfig + EAP7660D_WMAC1_CALDATA_OFFSET,
174			  boardconfig + EAP7660D_WMAC1_MAC_OFFSET);
175};
176
177MIPS_MACHINE(ATH79_MACH_EAP7660D, "EAP7660D", "Senao EAP7660D",
178	     eap7660d_setup);
179
180MIPS_MACHINE(ATH79_MACH_ALL0305, "ALL0305", "Allnet ALL0305",
181	     eap7660d_setup);
182