/*
* MikroTik SPI-NOR RouterBOARDs support
*
+ * - MikroTik RouterBOARD mAP 2nD
* - MikroTik RouterBOARD mAP L-2nD
+ * - MikroTik RouterBOARD 911-2Hn (911 Lite2)
+ * - MikroTik RouterBOARD 911-5Hn (911 Lite5)
* - MikroTik RouterBOARD 941L-2nD
* - MikroTik RouterBOARD 951Ui-2nD
* - MikroTik RouterBOARD 952Ui-5ac2nD
* - MikroTik RouterBOARD 750 r2
* - MikroTik RouterBOARD LHG 5nD
* - MikroTik RouterBOARD wAP2nD
+ * - MikroTik RouterBOARD wAP G-5HacT2HnDwAP (wAP AC)
*
* Preliminary support for the following hardware
* - MikroTik RouterBOARD cAP2nD
- * - MikroTik RouterBOARD mAP2nD
* Furthermore, the cAP lite (cAPL2nD) appears to feature the exact same
* hardware as the mAP L-2nD. It is unknown if they share the same board
* identifier.
#include <linux/mtd/partitions.h>
#include <linux/ar8216_platform.h>
+#include <linux/platform_data/phy-at803x.h>
+#include <linux/platform_data/mdio-gpio.h>
#include <asm/prom.h>
#include <asm/mach-ath79/ar71xx_regs.h>
.nr_parts = ARRAY_SIZE(rbspi_spi_partitions),
};
-/* Several boards only have a single reset button wired to GPIO 16 */
-#define RBSPI_GPIO_BTN_RESET16 16
-#define RBSPI_GPIO_BTN_RESET20 20
-
-static struct gpio_keys_button rbspi_gpio_keys_reset16[] __initdata = {
- {
- .desc = "Reset button",
- .type = EV_KEY,
- .code = KEY_RESTART,
- .debounce_interval = RBSPI_KEYS_DEBOUNCE_INTERVAL,
- .gpio = RBSPI_GPIO_BTN_RESET16,
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_button rbspi_gpio_keys_reset20[] __initdata = {
+/*
+ * Several boards only have a single reset button, use a common
+ * structure for that.
+ */
+static struct gpio_keys_button rbspi_gpio_keys_reset[] __initdata = {
{
.desc = "Reset button",
.type = EV_KEY,
.code = KEY_RESTART,
.debounce_interval = RBSPI_KEYS_DEBOUNCE_INTERVAL,
- .gpio = RBSPI_GPIO_BTN_RESET20,
+ .gpio = -ENOENT, /* filled dynamically */
.active_low = 1,
},
};
#define RBMAPL_GPIO_LED_USER 14
#define RBMAPL_GPIO_LED_ETH 4
#define RBMAPL_GPIO_LED_WLAN 11
+#define RBMAPL_GPIO_BTN_RESET 16
static struct gpio_led rbmapl_leds[] __initdata = {
{
/* RB 941L-2nD gpios */
#define RBHAPL_GPIO_LED_USER 14
+#define RBHAPL_GPIO_BTN_RESET 16
+
static struct gpio_led rbhapl_leds[] __initdata = {
{
.name = "rb:green:user",
#define RB952_GPIO_LED_USER 4
#define RB952_GPIO_POE_POWER 14
#define RB952_GPIO_POE_STATUS 12
+#define RB952_GPIO_BTN_RESET 16
#define RB952_GPIO_USB_POWER RBSPI_SSR_GPIO(RB952_SSR_BIT_USB_POWER)
#define RB952_GPIO_LED_LAN1 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN1)
#define RB952_GPIO_LED_LAN2 RBSPI_SSR_GPIO(RB952_SSR_BIT_LED_LAN2)
#define RB962_GPIO_POE_POWER 3
#define RB962_GPIO_LED_USER 12
#define RB962_GPIO_USB_POWER 13
+#define RB962_GPIO_BTN_RESET 20
static struct gpio_led rb962_leds_gpio[] __initdata = {
{
/* RB wAP-2nD gpios */
#define RBWAP_GPIO_LED_USER 14
#define RBWAP_GPIO_LED_WLAN 11
+#define RBWAP_GPIO_BTN_RESET 16
static struct gpio_led rbwap_leds[] __initdata = {
{
#define RBMAP_SSR_BIT_LED_WLAN 4
#define RBMAP_SSR_BIT_USB_POWER 5
#define RBMAP_SSR_BIT_LED_APCAP 6
+#define RBMAP_GPIO_BTN_RESET 16
#define RBMAP_GPIO_SSR_CS 11
#define RBMAP_GPIO_LED_POWER 4
#define RBMAP_GPIO_POE_POWER 14
.active_low = 1,
}, {
.name = "rb:green:eth2",
- .gpio = RBMAP_GPIO_LED_WLAN,
+ .gpio = RBMAP_GPIO_LED_LAN2,
.active_low = 1,
}, {
.name = "rb:red:poe_out",
},
};
-static struct gpio_keys_button rblhg_gpio_keys[] __initdata = {
+/* RB w APG-5HacT2HnD (wAP AC) gpios*/
+#define RBWAPGSC_LED1 1
+#define RBWAPGSC_LED2 8
+#define RBWAPGSC_LED3 9
+#define RBWAPGSC_POWERLED 16
+#define RBWAPGSC_GPIO_BTN_RESET 1
+#define RBWAPGSC_GPIO_MDIO_MDC 12
+#define RBWAPGSC_GPIO_MDIO_DATA 11
+#define RBWAPGSC_MDIO_PHYADDR 0
+
+static struct gpio_led rbwapgsc_leds[] __initdata = {
{
- .desc = "Reset button",
- .type = EV_KEY,
- .code = KEY_RESTART,
- .debounce_interval = RBSPI_KEYS_DEBOUNCE_INTERVAL,
- .gpio = RBLHG_GPIO_BTN_RESET,
+ .name = "rb:green:led1",
+ .gpio = RBWAPGSC_LED1,
+ .active_low = 1,
+ },{
+ .name = "rb:blue:power",
+ .gpio = RBWAPGSC_POWERLED,
.active_low = 1,
},
};
+static struct mdio_gpio_platform_data rbwapgsc_mdio_data = {
+ .mdc = RBWAPGSC_GPIO_MDIO_MDC,
+ .mdio = RBWAPGSC_GPIO_MDIO_DATA,
+ .phy_mask = ~BIT(RBWAPGSC_MDIO_PHYADDR),
+};
+
+static struct platform_device rbwapgsc_phy_device = {
+ .name = "mdio-gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &rbwapgsc_mdio_data
+ },
+};
+
+/* RB911L GPIOs */
+#define RB911L_GPIO_BTN_RESET 15
+#define RB911L_GPIO_LED_1 13
+#define RB911L_GPIO_LED_2 12
+#define RB911L_GPIO_LED_3 4
+#define RB911L_GPIO_LED_4 21
+#define RB911L_GPIO_LED_5 18
+#define RB911L_GPIO_LED_ETH 20
+#define RB911L_GPIO_LED_POWER 11
+#define RB911L_GPIO_LED_USER 3
+#define RB911L_GPIO_PIN_HOLE 14 /* for reference */
+
+static struct gpio_led rb911l_leds[] __initdata = {
+ {
+ .name = "rb:green:eth",
+ .gpio = RB911L_GPIO_LED_ETH,
+ .active_low = 1,
+ }, {
+ .name = "rb:green:led1",
+ .gpio = RB911L_GPIO_LED_1,
+ .active_low = 1,
+ }, {
+ .name = "rb:green:led2",
+ .gpio = RB911L_GPIO_LED_2,
+ .active_low = 1,
+ }, {
+ .name = "rb:green:led3",
+ .gpio = RB911L_GPIO_LED_3,
+ .active_low = 1,
+ }, {
+ .name = "rb:green:led4",
+ .gpio = RB911L_GPIO_LED_4,
+ .active_low = 1,
+ }, {
+ .name = "rb:green:led5",
+ .gpio = RB911L_GPIO_LED_5,
+ .active_low = 1,
+ }, {
+ .name = "rb:green:power",
+ .gpio = RB911L_GPIO_LED_POWER,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ .open_drain = 1,
+ }, {
+ .name = "rb:green:user",
+ .gpio = RB911L_GPIO_LED_USER,
+ .active_low = 1,
+ .open_drain = 1,
+ },
+};
static struct gen_74x164_chip_platform_data rbspi_ssr_data = {
.base = RBSPI_SSR_GPIO_BASE,
}
#define RBSPI_MACH_BUFLEN 64
-/*
+/*
* Common platform init routine for all SPI NOR devices.
*/
-static int __init rbspi_platform_setup(void)
+static __init const struct rb_info *rbspi_platform_setup(void)
{
const struct rb_info *info;
char buf[RBSPI_MACH_BUFLEN] = "MikroTik ";
info = rb_init_info((void *)(KSEG1ADDR(AR71XX_SPI_BASE)), 0x20000);
if (!info)
- return -ENODEV;
+ return NULL;
if (info->board_name) {
str = "RouterBOARD ";
/* fix partitions based on flash parsing */
rbspi_init_partitions(info);
- return 0;
+ return info;
}
/*
rbspi_wlan_init(1, wmac1_offset);
}
-/*
+static __init void rbspi_register_reset_button(int gpio)
+{
+ rbspi_gpio_keys_reset[0].gpio = gpio;
+ ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
+ ARRAY_SIZE(rbspi_gpio_keys_reset),
+ rbspi_gpio_keys_reset);
+}
+
+/*
* Init the mAP lite hardware (QCA953x).
* The mAP L-2nD (mAP lite) has a single ethernet port, connected to PHY0.
* Trying to use GMAC0 in direct mode was unsucessful, so we're
{
u32 flags = RBSPI_HAS_WLAN0;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_peripherals_setup(flags);
ath79_register_leds_gpio(-1, ARRAY_SIZE(rbmapl_leds), rbmapl_leds);
/* mAP lite has a single reset button as gpio 16 */
- ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
- ARRAY_SIZE(rbspi_gpio_keys_reset16),
- rbspi_gpio_keys_reset16);
+ rbspi_register_reset_button(RBMAPL_GPIO_BTN_RESET);
/* clear internal multiplexing */
ath79_gpio_output_select(RBMAPL_GPIO_LED_ETH, AR934X_GPIO_OUT_GPIO);
{
u32 flags = RBSPI_HAS_WLAN0;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_peripherals_setup(flags);
ath79_register_leds_gpio(-1, ARRAY_SIZE(rbhapl_leds), rbhapl_leds);
/* hAP lite has a single reset button as gpio 16 */
- ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
- ARRAY_SIZE(rbspi_gpio_keys_reset16),
- rbspi_gpio_keys_reset16);
+ rbspi_register_reset_button(RBHAPL_GPIO_BTN_RESET);
}
/*
ath79_register_leds_gpio(-1, ARRAY_SIZE(rb952_leds), rb952_leds);
/* These devices have a single reset button as gpio 16 */
- ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
- ARRAY_SIZE(rbspi_gpio_keys_reset16),
- rbspi_gpio_keys_reset16);
+ rbspi_register_reset_button(RB952_GPIO_BTN_RESET);
}
/*
u32 flags = RBSPI_HAS_WAN4 | RBSPI_HAS_USB |
RBSPI_HAS_SSR | RBSPI_HAS_POE;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
/* differentiate the hAP from the hAP ac lite */
{
u32 flags = RBSPI_HAS_WAN4 | RBSPI_HAS_SSR;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
/* differentiate the hEX lite from the hEX PoE lite */
{
u32 flags = RBSPI_HAS_USB | RBSPI_HAS_POE | RBSPI_HAS_PCI;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_peripherals_setup(flags);
rb962_leds_gpio);
/* This device has a single reset button as gpio 20 */
- ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
- ARRAY_SIZE(rbspi_gpio_keys_reset20),
- rbspi_gpio_keys_reset20);
+ rbspi_register_reset_button(RB962_GPIO_BTN_RESET);
}
/*
{
u32 flags = RBSPI_HAS_WLAN1 | RBSPI_HAS_MDIO1;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_peripherals_setup(flags);
ath79_register_leds_gpio(-1, ARRAY_SIZE(rblhg_leds), rblhg_leds);
- ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
- ARRAY_SIZE(rblhg_gpio_keys),
- rblhg_gpio_keys);
+ rbspi_register_reset_button(RBLHG_GPIO_BTN_RESET);
}
/*
{
u32 flags = RBSPI_HAS_WLAN0;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_peripherals_setup(flags);
ath79_register_leds_gpio(-1, ARRAY_SIZE(rbwap_leds), rbwap_leds);
/* wAP has a single reset button as GPIO 16 */
- ath79_register_gpio_keys_polled(-1, RBSPI_KEYS_POLL_INTERVAL,
- ARRAY_SIZE(rbspi_gpio_keys_reset16),
- rbspi_gpio_keys_reset16);
+ rbspi_register_reset_button(RBWAP_GPIO_BTN_RESET);
}
/*
{
u32 flags = RBSPI_HAS_WLAN0;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_peripherals_setup(flags);
}
/*
- * Init the mAP hardware (EXPERIMENTAL).
- * The mAP 2nD has two ethernet ports, PoE output and an SSR for LED
- * multiplexing.
+ * Init the mAP hardware.
+ * The mAP 2nD has two ethernet ports, PoE output, SSR for LED
+ * multiplexing and USB port.
*/
static void __init rbmap_setup(void)
{
- u32 flags = RBSPI_HAS_WLAN0 | RBSPI_HAS_SSR | RBSPI_HAS_POE;
+ u32 flags = RBSPI_HAS_USB | RBSPI_HAS_WLAN0 |
+ RBSPI_HAS_SSR | RBSPI_HAS_POE;
- if (rbspi_platform_setup())
+ if (!rbspi_platform_setup())
return;
rbspi_spi_cs_gpios[1] = RBMAP_GPIO_SSR_CS;
if (flags & RBSPI_HAS_POE)
gpio_request_one(RBMAP_GPIO_POE_POWER,
- GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED,
+ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED,
"POE power");
+ /* USB power GPIO is inverted, set GPIOF_ACTIVE_LOW for consistency */
+ if (flags & RBSPI_HAS_USB)
+ gpio_request_one(RBMAP_GPIO_USB_POWER,
+ GPIOF_OUT_INIT_HIGH | GPIOF_ACTIVE_LOW |
+ GPIOF_EXPORT_DIR_FIXED,
+ "USB power");
+
ath79_register_leds_gpio(-1, ARRAY_SIZE(rbmap_leds), rbmap_leds);
+
+ /* mAP 2nD has a single reset button as gpio 16 */
+ rbspi_register_reset_button(RBMAP_GPIO_BTN_RESET);
}
+/*
+ * Init the wAPGSC (RB wAPG-5HacT2HnD // wAP AC) hardware.
+ * The wAPGSC has one Ethernet port via AR8033 with PoE input, dual radio (SoC
+ * 2.4 GHz and external QCA9880) and a ZT2046Q temperature and voltage sensor
+ * (currently not supported).
+ */
+static void __init rbwapgsc_setup(void)
+{
+ u32 flags = RBSPI_HAS_PCI;
+
+ if (!rbspi_platform_setup())
+ return;
+
+ rbspi_peripherals_setup(flags);
+
+ platform_device_register(&rbwapgsc_phy_device);
+
+ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0);
+ ath79_eth1_data.mii_bus_dev = &rbwapgsc_phy_device.dev;
+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII;
+ ath79_eth1_data.phy_mask = BIT(RBWAPGSC_MDIO_PHYADDR);
+ ath79_eth1_pll_data.pll_1000 = 0x03000101;
+ ath79_eth1_pll_data.pll_100 = 0x80000101;
+ ath79_eth1_pll_data.pll_10 = 0x80001313;
+ ath79_eth1_data.speed = SPEED_1000;
+ ath79_eth1_data.duplex = DUPLEX_FULL;
+ ath79_register_eth(1);
+
+ rbspi_wlan_init(1, 2);
+
+ rbspi_register_reset_button(RBWAPGSC_GPIO_BTN_RESET);
+
+ ath79_gpio_function_enable(QCA955X_GPIO_FUNC_JTAG_DISABLE|
+ QCA955X_GPIO_REG_OUT_FUNC4|
+ QCA955X_GPIO_REG_OUT_FUNC3);
+
+ ath79_register_leds_gpio(-1, ARRAY_SIZE(rbwapgsc_leds),
+ rbwapgsc_leds);
+}
+
+/*
+ * Setup the 911L hardware (AR9344).
+ */
+static void __init rb911l_setup(void)
+{
+ const struct rb_info *info;
+
+ info = rbspi_platform_setup();
+ if (!info)
+ return;
+
+ if (!rb_has_hw_option(info, RB_HW_OPT_NO_NAND)) {
+ /*
+ * Old hardware revisions might be equipped with a NAND flash
+ * chip instead of the 16MiB SPI NOR device. Those boards are
+ * not supported at the moment, so throw a warning and skip
+ * the peripheral setup to avoid messing up the data in the
+ * flash chip.
+ */
+ WARN(1, "The NAND flash on this board is not supported.\n");
+ } else {
+ rbspi_peripherals_setup(0);
+ }
+
+ ath79_register_mdio(1, 0x0);
+
+ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 0);
+
+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII;
+ ath79_eth1_data.speed = SPEED_1000;
+ ath79_eth1_data.duplex = DUPLEX_FULL;
+
+ ath79_register_eth(1);
+
+ rbspi_wlan_init(0, 1);
+
+ rbspi_register_reset_button(RB911L_GPIO_BTN_RESET);
+
+ /* Make the eth LED controllable by software. */
+ ath79_gpio_output_select(RB911L_GPIO_LED_ETH, AR934X_GPIO_OUT_GPIO);
+
+ ath79_register_leds_gpio(-1, ARRAY_SIZE(rb911l_leds), rb911l_leds);
+}
MIPS_MACHINE_NONAME(ATH79_MACH_RB_MAPL, "map-hb", rbmapl_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_941, "H951L", rbhapl_setup);
+MIPS_MACHINE_NONAME(ATH79_MACH_RB_911L, "911L", rb911l_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_952, "952-hb", rb952_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_962, "962", rb962_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_750UPR2, "750-hb", rb750upr2_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAP, "wap-hb", rbwap_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_CAP, "cap-hb", rbcap_setup);
MIPS_MACHINE_NONAME(ATH79_MACH_RB_MAP, "map2-hb", rbmap_setup);
+MIPS_MACHINE_NONAME(ATH79_MACH_RB_WAPAC, "wapg-sc", rbwapgsc_setup);