summaryrefslogtreecommitdiff
path: root/arch/mips/lantiq
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/lantiq')
-rw-r--r--arch/mips/lantiq/falcon/sysctrl.c11
-rw-r--r--arch/mips/lantiq/irq.c56
-rw-r--r--arch/mips/lantiq/prom.c18
-rw-r--r--arch/mips/lantiq/xway/Makefile2
-rw-r--r--arch/mips/lantiq/xway/reset.c70
-rw-r--r--arch/mips/lantiq/xway/vmmc.c69
-rw-r--r--arch/mips/lantiq/xway/xrx200_phy_fw.c23
7 files changed, 207 insertions, 42 deletions
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
index 468ffa043607..7edcd4946fc1 100644
--- a/arch/mips/lantiq/falcon/sysctrl.c
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -49,6 +49,7 @@
/* Activation Status Register */
#define ACTS_ASC0_ACT 0x00001000
+#define ACTS_SSC0 0x00002000
#define ACTS_ASC1_ACT 0x00000800
#define ACTS_I2C_ACT 0x00004000
#define ACTS_P0 0x00010000
@@ -147,12 +148,11 @@ static void falcon_gpe_enable(void)
if (status & (1 << (GPPC_OFFSET + 1)))
return;
- if (status_r32(STATUS_CONFIG) == 0)
+ freq = (status_r32(STATUS_CONFIG) &
+ GPEFREQ_MASK) >>
+ GPEFREQ_OFFSET;
+ if (freq == 0)
freq = 1; /* use 625MHz on unfused chip */
- else
- freq = (status_r32(STATUS_CONFIG) &
- GPEFREQ_MASK) >>
- GPEFREQ_OFFSET;
/* apply new frequency */
sysctl_w32_mask(SYSCTL_SYS1, 7 << (GPPC_OFFSET + 1),
@@ -260,5 +260,6 @@ void __init ltq_soc_init(void)
clkdev_add_sys("1e800600.pad", SYSCTL_SYS1, ACTS_PADCTRL4);
clkdev_add_sys("1e100b00.serial", SYSCTL_SYS1, ACTS_ASC1_ACT);
clkdev_add_sys("1e100c00.serial", SYSCTL_SYS1, ACTS_ASC0_ACT);
+ clkdev_add_sys("1e100d00.spi", SYSCTL_SYS1, ACTS_SSC0);
clkdev_add_sys("1e200000.i2c", SYSCTL_SYS1, ACTS_I2C_ACT);
}
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 030568a70ac4..6ab10573490d 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -70,6 +70,7 @@ static struct resource ltq_eiu_irq[MAX_EIU];
static void __iomem *ltq_icu_membase[MAX_IM];
static void __iomem *ltq_eiu_membase;
static struct irq_domain *ltq_domain;
+static int ltq_perfcount_irq;
int ltq_eiu_get_irq(int exin)
{
@@ -378,30 +379,6 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
panic("Failed to remap icu memory");
}
- /* the external interrupts are optional and xway only */
- eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
- if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
- /* find out how many external irq sources we have */
- exin_avail = of_irq_count(eiu_node);
-
- if (exin_avail > MAX_EIU)
- exin_avail = MAX_EIU;
-
- ret = of_irq_to_resource_table(eiu_node,
- ltq_eiu_irq, exin_avail);
- if (ret != exin_avail)
- panic("failed to load external irq resources");
-
- if (request_mem_region(res.start, resource_size(&res),
- res.name) < 0)
- pr_err("Failed to request eiu memory");
-
- ltq_eiu_membase = ioremap_nocache(res.start,
- resource_size(&res));
- if (!ltq_eiu_membase)
- panic("Failed to remap eiu memory");
- }
-
/* turn off all irqs by default */
for (i = 0; i < MAX_IM; i++) {
/* make sure all irqs are turned off by default */
@@ -449,7 +426,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
#endif
/* tell oprofile which irq to use */
- cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
+ ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
/*
* if the timer irq is not one of the mips irqs we need to
@@ -458,9 +435,38 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
if (MIPS_CPU_TIMER_IRQ != 7)
irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ);
+ /* the external interrupts are optional and xway only */
+ eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
+ if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
+ /* find out how many external irq sources we have */
+ exin_avail = of_irq_count(eiu_node);
+
+ if (exin_avail > MAX_EIU)
+ exin_avail = MAX_EIU;
+
+ ret = of_irq_to_resource_table(eiu_node,
+ ltq_eiu_irq, exin_avail);
+ if (ret != exin_avail)
+ panic("failed to load external irq resources");
+
+ if (request_mem_region(res.start, resource_size(&res),
+ res.name) < 0)
+ pr_err("Failed to request eiu memory");
+
+ ltq_eiu_membase = ioremap_nocache(res.start,
+ resource_size(&res));
+ if (!ltq_eiu_membase)
+ panic("Failed to remap eiu memory");
+ }
+
return 0;
}
+int get_c0_perfcount_int(void)
+{
+ return ltq_perfcount_irq;
+}
+
unsigned int get_c0_compare_int(void)
{
return MIPS_CPU_TIMER_IRQ;
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 7447d322d14e..39ab3e786e59 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -36,6 +36,11 @@ const char *get_system_type(void)
return soc_info.sys_type;
}
+int ltq_soc_type(void)
+{
+ return soc_info.type;
+}
+
void prom_free_prom_memory(void)
{
}
@@ -72,6 +77,8 @@ void __init plat_mem_setup(void)
* parsed resulting in our memory appearing
*/
__dt_setup_arch(__dtb_start);
+
+ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
}
void __init device_tree_init(void)
@@ -97,16 +104,7 @@ void __init prom_init(void)
int __init plat_of_setup(void)
{
- static struct of_device_id of_ids[3];
-
- if (!of_have_populated_dt())
- panic("device tree not present");
-
- strlcpy(of_ids[0].compatible, soc_info.compatible,
- sizeof(of_ids[0].compatible));
- strncpy(of_ids[1].compatible, "simple-bus",
- sizeof(of_ids[1].compatible));
- return of_platform_populate(NULL, of_ids, NULL, NULL);
+ return __dt_register_buses(soc_info.compatible, "simple-bus");
}
arch_initcall(plat_of_setup);
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 087497d97357..a2edc538f477 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,3 +1,5 @@
obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o
+obj-y += vmmc.o
+
obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 1fa0f175357e..fe68f9ae47c1 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
+#include <linux/reset-controller.h>
#include <asm/reboot.h>
@@ -113,10 +114,77 @@ void ltq_reset_once(unsigned int module, ulong u)
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
}
+static int ltq_assert_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ u32 val;
+
+ if (id < 8)
+ return -1;
+
+ val = ltq_rcu_r32(RCU_RST_REQ);
+ val |= BIT(id);
+ ltq_rcu_w32(val, RCU_RST_REQ);
+
+ return 0;
+}
+
+static int ltq_deassert_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ u32 val;
+
+ if (id < 8)
+ return -1;
+
+ val = ltq_rcu_r32(RCU_RST_REQ);
+ val &= ~BIT(id);
+ ltq_rcu_w32(val, RCU_RST_REQ);
+
+ return 0;
+}
+
+static int ltq_reset_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ ltq_assert_device(rcdev, id);
+ return ltq_deassert_device(rcdev, id);
+}
+
+static struct reset_control_ops reset_ops = {
+ .reset = ltq_reset_device,
+ .assert = ltq_assert_device,
+ .deassert = ltq_deassert_device,
+};
+
+static struct reset_controller_dev reset_dev = {
+ .ops = &reset_ops,
+ .owner = THIS_MODULE,
+ .nr_resets = 32,
+ .of_reset_n_cells = 1,
+};
+
+void ltq_rst_init(void)
+{
+ reset_dev.of_node = of_find_compatible_node(NULL, NULL,
+ "lantiq,xway-reset");
+ if (!reset_dev.of_node)
+ pr_err("Failed to find reset controller node");
+ else
+ reset_controller_register(&reset_dev);
+}
+
static void ltq_machine_restart(char *command)
{
+ u32 val = ltq_rcu_r32(RCU_RST_REQ);
+
+ if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
+ val |= RCU_RD_GPHY1_XRX200 | RCU_RD_GPHY0_XRX200;
+
+ val |= RCU_RD_SRST;
+
local_irq_disable();
- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ);
+ ltq_rcu_w32(val, RCU_RST_REQ);
unreachable();
}
diff --git a/arch/mips/lantiq/xway/vmmc.c b/arch/mips/lantiq/xway/vmmc.c
new file mode 100644
index 000000000000..696cd57f6f13
--- /dev/null
+++ b/arch/mips/lantiq/xway/vmmc.c
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/dma-mapping.h>
+
+#include <lantiq_soc.h>
+
+static unsigned int *cp1_base;
+
+unsigned int *ltq_get_cp1_base(void)
+{
+ if (!cp1_base)
+ panic("no cp1 base was set\n");
+
+ return cp1_base;
+}
+EXPORT_SYMBOL(ltq_get_cp1_base);
+
+static int vmmc_probe(struct platform_device *pdev)
+{
+#define CP1_SIZE (1 << 20)
+ int gpio_count;
+ dma_addr_t dma;
+
+ cp1_base =
+ (void *) CPHYSADDR(dma_alloc_coherent(NULL, CP1_SIZE,
+ &dma, GFP_ATOMIC));
+
+ gpio_count = of_gpio_count(pdev->dev.of_node);
+ while (gpio_count > 0) {
+ enum of_gpio_flags flags;
+ int gpio = of_get_gpio_flags(pdev->dev.of_node,
+ --gpio_count, &flags);
+ if (gpio_request(gpio, "vmmc-relay"))
+ continue;
+ dev_info(&pdev->dev, "requested GPIO %d\n", gpio);
+ gpio_direction_output(gpio,
+ (flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1));
+ }
+
+ dev_info(&pdev->dev, "reserved %dMB at 0x%p", CP1_SIZE >> 20, cp1_base);
+
+ return 0;
+}
+
+static const struct of_device_id vmmc_match[] = {
+ { .compatible = "lantiq,vmmc-xway" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, vmmc_match);
+
+static struct platform_driver vmmc_driver = {
+ .probe = vmmc_probe,
+ .driver = {
+ .name = "lantiq,vmmc",
+ .owner = THIS_MODULE,
+ .of_match_table = vmmc_match,
+ },
+};
+
+module_platform_driver(vmmc_driver);
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
index d4d9d31f152e..7c1e54c6a36c 100644
--- a/arch/mips/lantiq/xway/xrx200_phy_fw.c
+++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c
@@ -24,7 +24,28 @@ static dma_addr_t xway_gphy_load(struct platform_device *pdev)
void *fw_addr;
size_t size;
- if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
+ if (of_get_property(pdev->dev.of_node, "firmware1", NULL) ||
+ of_get_property(pdev->dev.of_node, "firmware2", NULL)) {
+ switch (ltq_soc_type()) {
+ case SOC_TYPE_VR9:
+ if (of_property_read_string(pdev->dev.of_node,
+ "firmware1", &fw_name)) {
+ dev_err(&pdev->dev,
+ "failed to load firmware filename\n");
+ return 0;
+ }
+ break;
+ case SOC_TYPE_VR9_2:
+ if (of_property_read_string(pdev->dev.of_node,
+ "firmware2", &fw_name)) {
+ dev_err(&pdev->dev,
+ "failed to load firmware filename\n");
+ return 0;
+ }
+ break;
+ }
+ } else if (of_property_read_string(pdev->dev.of_node,
+ "firmware", &fw_name)) {
dev_err(&pdev->dev, "failed to load firmware filename\n");
return 0;
}