provide an early ioremap cookie of the system configuration register
[oweals/openwrt.git] / target / linux / mcs814x / files-3.3 / arch / arm / mach-mcs814x / common.c
index a408e6928765c499217bbcf0d66958debd40cd63..87193a31edd31d91f70e68e8027268c21de815c4 100644 (file)
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/hardware.h>
+#include <mach/mcs814x.h>
 #include <mach/cpu.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 
+void __iomem *mcs814x_sysdbg_base;
+
 static struct map_desc mcs814x_io_desc[] __initdata = {
        {
                .virtual        = MCS814X_IO_BASE,
@@ -30,10 +34,6 @@ static struct map_desc mcs814x_io_desc[] __initdata = {
        },
 };
 
-#define SYSDBG_BS2     0x04
-#define CPU_MODE_SHIFT 23
-#define CPU_MODE_MASK  0x03
-
 struct cpu_mode {
        const char *name;
        int gpio_start;
@@ -63,12 +63,76 @@ static const struct cpu_mode cpu_modes[] = {
        },
 };
 
+static void mcs814x_eth_hardware_filter_set(u8 value)
+{
+       u32 reg;
+
+       reg = __raw_readl(MCS814X_VIRT_BASE + MCS814X_DBGLED);
+       if (value)
+               reg |= 0x80;
+       else
+               reg &= ~0x80;
+       __raw_writel(reg, MCS814X_VIRT_BASE + MCS814X_DBGLED);
+}
+
+static void mcs814x_eth_led_cfg_set(u8 cfg)
+{
+       u32 reg;
+
+       reg = __raw_readl(mcs814x_sysdbg_base + SYSDBG_BS2);
+       reg &= ~LED_CFG_MASK;
+       reg |= cfg;
+       __raw_writel(reg, mcs814x_sysdbg_base + SYSDBG_BS2);
+}
+
+static void mcs814x_eth_buffer_shifting_set(u8 value)
+{
+       u8 reg;
+
+       reg = __raw_readb(mcs814x_sysdbg_base + SYSDBG_SYSCTL_MAC);
+       if (value)
+               reg |= BUF_SHIFT_BIT;
+       else
+               reg &= ~BUF_SHIFT_BIT;
+       __raw_writeb(reg, mcs814x_sysdbg_base + SYSDBG_SYSCTL_MAC);
+}
+
+static struct of_device_id mcs814x_eth_ids[] __initdata = {
+       { .compatible = "moschip,nuport-mac", },
+       { /* sentinel */ },
+};
+
+/* Configure platform specific knobs based on ethernet device node
+ * properties */
+static void mcs814x_eth_init(void)
+{
+       struct device_node *np;
+       const unsigned int *intspec;
+
+       np = of_find_matching_node(NULL, mcs814x_eth_ids);
+       if (!np)
+               return;
+
+       /* hardware filter must always be enabled */
+       mcs814x_eth_hardware_filter_set(1);
+
+       intspec = of_get_property(np, "nuport-mac,buffer-shifting", NULL);
+       if (!intspec)
+               mcs814x_eth_buffer_shifting_set(0);
+       else
+               mcs814x_eth_buffer_shifting_set(1);
+
+       intspec = of_get_property(np, "nuport-mac,link-activity", NULL);
+       if (intspec)
+               mcs814x_eth_led_cfg_set(be32_to_cpup(intspec));
+}
+
 void __init mcs814x_init_machine(void)
 {
        u32 bs2, cpu_mode;
        int gpio;
 
-       bs2 = __raw_readl(_CONFADDR_SYSDBG + SYSDBG_BS2);
+       bs2 = __raw_readl(mcs814x_sysdbg_base + SYSDBG_BS2);
        cpu_mode = (bs2 >> CPU_MODE_SHIFT) & CPU_MODE_MASK;
 
        pr_info("CPU mode: %s\n", cpu_modes[cpu_mode].name);
@@ -79,14 +143,21 @@ void __init mcs814x_init_machine(void)
                if (gpio != -1)
                        gpio_request(gpio, cpu_modes[cpu_mode].name);
        }
+
+       mcs814x_eth_init();
 }
 
 void __init mcs814x_map_io(void)
 {
        iotable_init(mcs814x_io_desc, ARRAY_SIZE(mcs814x_io_desc));
+
+       mcs814x_sysdbg_base = ioremap(MCS814X_IO_START + MCS814X_SYSDBG,
+                                       MCS814X_SYSDBG_SIZE);
+       if (!mcs814x_sysdbg_base)
+               panic("unable to remap sysdbg base");
 }
 
 void mcs814x_restart(char mode, const char *cmd)
 {
-       __raw_writel(~(1 << 31), _CONFADDR_SYSDBG);
+       __raw_writel(~(1 << 31), mcs814x_sysdbg_base);
 }