openwrt/target/linux/ar71xx/files/arch/mips/ath79/mach-rb750.c
Gabor Juhos 6ff973bdda ar71xx: Routerboard 751 Mac Address Offset Fix
We utilize many Routerboard 751's and discovered that our latest batch
of RB751's would not initialize the wireless radio. We have determined
Mikrotik has changed where the mac address was located inside hardconfig.
As such we utilize "routerboot_find_tag" to find the location of the mac
address. We should remove "RB751_MAC_ADDRESS_OFFSET" as it is ambiguous
by machine manufacturing date. The newer batch of RB751's that we received
had a RB751_MAC_ADDRESS_OFFSET 0x10.

Signed-off-by: Davey Hutchison <dhutchison@bluemesh.net>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

SVN-Revision: 35519
2013-02-08 09:34:53 +00:00

347 lines
8.7 KiB
C

/*
* MikroTik RouterBOARD 750/750GL support
*
* Copyright (C) 2010-2012 Gabor Juhos <juhosg@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/export.h>
#include <linux/pci.h>
#include <linux/ath9k_platform.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
#include <linux/ar8216_platform.h>
#include <linux/rle.h>
#include <linux/routerboot.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/irq.h>
#include <asm/mach-ath79/mach-rb750.h>
#include "common.h"
#include "dev-ap9x-pci.h"
#include "dev-usb.h"
#include "dev-eth.h"
#include "machtypes.h"
#include "routerboot.h"
static struct rb750_led_data rb750_leds[] = {
{
.name = "rb750:green:act",
.mask = RB750_LED_ACT,
.active_low = 1,
}, {
.name = "rb750:green:port1",
.mask = RB750_LED_PORT5,
.active_low = 1,
}, {
.name = "rb750:green:port2",
.mask = RB750_LED_PORT4,
.active_low = 1,
}, {
.name = "rb750:green:port3",
.mask = RB750_LED_PORT3,
.active_low = 1,
}, {
.name = "rb750:green:port4",
.mask = RB750_LED_PORT2,
.active_low = 1,
}, {
.name = "rb750:green:port5",
.mask = RB750_LED_PORT1,
.active_low = 1,
}
};
static struct rb750_led_data rb750gr3_leds[] = {
{
.name = "rb750:green:act",
.mask = RB7XX_LED_ACT,
.active_low = 1,
},
};
static struct rb750_led_platform_data rb750_leds_data;
static struct platform_device rb750_leds_device = {
.name = "leds-rb750",
.dev = {
.platform_data = &rb750_leds_data,
}
};
static struct rb7xx_nand_platform_data rb750_nand_data;
static struct platform_device rb750_nand_device = {
.name = "rb750-nand",
.id = -1,
.dev = {
.platform_data = &rb750_nand_data,
}
};
static void rb750_latch_change(u32 mask_clr, u32 mask_set)
{
static DEFINE_SPINLOCK(lock);
static u32 latch_set = RB750_LED_BITS | RB750_LVC573_LE;
static u32 latch_oe;
static u32 latch_clr;
unsigned long flags;
u32 t;
spin_lock_irqsave(&lock, flags);
if ((mask_clr & BIT(31)) != 0 &&
(latch_set & RB750_LVC573_LE) == 0) {
goto unlock;
}
latch_set = (latch_set | mask_set) & ~mask_clr;
latch_clr = (latch_clr | mask_clr) & ~mask_set;
if (latch_oe == 0)
latch_oe = __raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_OE);
if (likely(latch_set & RB750_LVC573_LE)) {
void __iomem *base = ath79_gpio_base;
t = __raw_readl(base + AR71XX_GPIO_REG_OE);
t |= mask_clr | latch_oe | mask_set;
__raw_writel(t, base + AR71XX_GPIO_REG_OE);
__raw_writel(latch_clr, base + AR71XX_GPIO_REG_CLEAR);
__raw_writel(latch_set, base + AR71XX_GPIO_REG_SET);
} else if (mask_clr & RB750_LVC573_LE) {
void __iomem *base = ath79_gpio_base;
latch_oe = __raw_readl(base + AR71XX_GPIO_REG_OE);
__raw_writel(RB750_LVC573_LE, base + AR71XX_GPIO_REG_CLEAR);
/* flush write */
__raw_readl(base + AR71XX_GPIO_REG_CLEAR);
}
unlock:
spin_unlock_irqrestore(&lock, flags);
}
static void rb750_nand_enable_pins(void)
{
rb750_latch_change(RB750_LVC573_LE, 0);
ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE,
AR724X_GPIO_FUNC_SPI_EN);
}
static void rb750_nand_disable_pins(void)
{
ath79_gpio_function_setup(AR724X_GPIO_FUNC_SPI_EN,
AR724X_GPIO_FUNC_JTAG_DISABLE);
rb750_latch_change(0, RB750_LVC573_LE);
}
static void __init rb750_setup(void)
{
ath79_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN |
AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN |
AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN |
AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN |
AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN);
ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0);
ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1);
ath79_register_mdio(0, 0x0);
/* LAN ports */
ath79_register_eth(1);
/* WAN port */
ath79_register_eth(0);
rb750_leds_data.num_leds = ARRAY_SIZE(rb750_leds);
rb750_leds_data.leds = rb750_leds;
rb750_leds_data.latch_change = rb750_latch_change;
platform_device_register(&rb750_leds_device);
rb750_nand_data.nce_line = RB750_NAND_NCE;
rb750_nand_data.enable_pins = rb750_nand_enable_pins;
rb750_nand_data.disable_pins = rb750_nand_disable_pins;
rb750_nand_data.latch_change = rb750_latch_change;
platform_device_register(&rb750_nand_device);
}
MIPS_MACHINE(ATH79_MACH_RB_750, "750i", "MikroTik RouterBOARD 750",
rb750_setup);
static struct ar8327_pad_cfg rb750gr3_ar8327_pad0_cfg = {
.mode = AR8327_PAD_MAC_RGMII,
.txclk_delay_en = true,
.rxclk_delay_en = true,
.txclk_delay_sel = AR8327_CLK_DELAY_SEL1,
.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2,
};
static struct ar8327_platform_data rb750gr3_ar8327_data = {
.pad0_cfg = &rb750gr3_ar8327_pad0_cfg,
.port0_cfg = {
.force_link = 1,
.speed = AR8327_PORT_SPEED_1000,
.duplex = 1,
.txpause = 1,
.rxpause = 1,
}
};
static struct mdio_board_info rb750g3_mdio_info[] = {
{
.bus_id = "ag71xx-mdio.0",
.phy_addr = 0,
.platform_data = &rb750gr3_ar8327_data,
},
};
static void rb750gr3_nand_enable_pins(void)
{
ath79_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE,
AR724X_GPIO_FUNC_SPI_EN |
AR724X_GPIO_FUNC_SPI_CS_EN2);
}
static void rb750gr3_nand_disable_pins(void)
{
ath79_gpio_function_setup(AR724X_GPIO_FUNC_SPI_EN |
AR724X_GPIO_FUNC_SPI_CS_EN2,
AR724X_GPIO_FUNC_JTAG_DISABLE);
}
static void rb750gr3_latch_change(u32 mask_clr, u32 mask_set)
{
static DEFINE_SPINLOCK(lock);
static u32 latch_set = RB7XX_LED_ACT;
static u32 latch_clr;
void __iomem *base = ath79_gpio_base;
unsigned long flags;
u32 t;
spin_lock_irqsave(&lock, flags);
latch_set = (latch_set | mask_set) & ~mask_clr;
latch_clr = (latch_clr | mask_clr) & ~mask_set;
mask_set = latch_set & (RB7XX_USB_POWERON | RB7XX_MONITOR);
mask_clr = latch_clr & (RB7XX_USB_POWERON | RB7XX_MONITOR);
if ((latch_set ^ RB7XX_LED_ACT) & RB7XX_LED_ACT) {
/* enable output mode */
t = __raw_readl(base + AR71XX_GPIO_REG_OE);
t |= RB7XX_LED_ACT;
__raw_writel(t, base + AR71XX_GPIO_REG_OE);
mask_clr |= RB7XX_LED_ACT;
} else {
/* disable output mode */
t = __raw_readl(base + AR71XX_GPIO_REG_OE);
t &= ~RB7XX_LED_ACT;
__raw_writel(t, base + AR71XX_GPIO_REG_OE);
}
__raw_writel(mask_set, base + AR71XX_GPIO_REG_SET);
__raw_writel(mask_clr, base + AR71XX_GPIO_REG_CLEAR);
spin_unlock_irqrestore(&lock, flags);
}
static void __init rb750gr3_setup(void)
{
ath79_register_mdio(0, 0x0);
mdiobus_register_board_info(rb750g3_mdio_info,
ARRAY_SIZE(rb750g3_mdio_info));
ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0);
ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
ath79_eth0_data.phy_mask = BIT(0);
ath79_eth0_pll_data.pll_1000 = 0x62000000;
ath79_register_eth(0);
rb750_leds_data.num_leds = ARRAY_SIZE(rb750gr3_leds);
rb750_leds_data.leds = rb750gr3_leds;
rb750_leds_data.latch_change = rb750gr3_latch_change;
platform_device_register(&rb750_leds_device);
rb750_nand_data.nce_line = RB7XX_NAND_NCE;
rb750_nand_data.enable_pins = rb750gr3_nand_enable_pins;
rb750_nand_data.disable_pins = rb750gr3_nand_disable_pins;
rb750_nand_data.latch_change = rb750gr3_latch_change;
platform_device_register(&rb750_nand_device);
}
MIPS_MACHINE(ATH79_MACH_RB_750G_R3, "750Gr3", "MikroTik RouterBOARD 750GL",
rb750gr3_setup);
#define RB751_HARDCONFIG 0x1f00b000
#define RB751_HARDCONFIG_SIZE 0x1000
static void __init rb751_wlan_setup(void)
{
u8 *hardconfig = (u8 *) KSEG1ADDR(RB751_HARDCONFIG);
struct ath9k_platform_data *wmac_data;
u16 tag_len;
u8 *tag;
u16 mac_len;
u8 *mac;
int err;
wmac_data = ap9x_pci_get_wmac_data(0);
if (!wmac_data) {
pr_err("rb75x: unable to get address of wlan data\n");
return;
}
ap9x_pci_setup_wmac_led_pin(0, 9);
err = routerboot_find_tag(hardconfig, RB751_HARDCONFIG_SIZE,
RB_ID_WLAN_DATA, &tag, &tag_len);
if (err) {
pr_err("rb75x: no calibration data found\n");
return;
}
err = rle_decode(tag, tag_len, (unsigned char *) wmac_data->eeprom_data,
sizeof(wmac_data->eeprom_data), NULL, NULL);
if (err) {
pr_err("rb75x: unable to decode wlan eeprom data\n");
return;
}
err = routerboot_find_tag(hardconfig, RB751_HARDCONFIG_SIZE,
RB_ID_MAC_ADDRESS_PACK, &mac, &mac_len);
if (err) {
pr_err("rb75x: no mac address found\n");
return;
}
ap91_pci_init(NULL, mac);
}
static void __init rb751_setup(void)
{
rb750_setup();
ath79_register_usb();
rb751_wlan_setup();
}
MIPS_MACHINE(ATH79_MACH_RB_751, "751", "MikroTik RouterBOARD 751",
rb751_setup);
static void __init rb751g_setup(void)
{
rb750gr3_setup();
ath79_register_usb();
rb751_wlan_setup();
}
MIPS_MACHINE(ATH79_MACH_RB_751G, "751g", "MikroTik RouterBOARD 751G",
rb751g_setup);