diff options
Diffstat (limited to 'arch/mips/lantiq')
-rw-r--r-- | arch/mips/lantiq/falcon/sysctrl.c | 11 | ||||
-rw-r--r-- | arch/mips/lantiq/irq.c | 56 | ||||
-rw-r--r-- | arch/mips/lantiq/prom.c | 18 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/reset.c | 70 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/vmmc.c | 69 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/xrx200_phy_fw.c | 23 |
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; } |