diff options
-rw-r--r-- | arch/microblaze/include/asm/setup.h | 2 | ||||
-rw-r--r-- | arch/microblaze/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/microblaze/kernel/reset.c | 138 | ||||
-rw-r--r-- | arch/microblaze/kernel/setup.c | 29 | ||||
-rw-r--r-- | arch/microblaze/platform/generic/system.dts | 28 | ||||
-rw-r--r-- | arch/microblaze/platform/platform.c | 2 |
6 files changed, 171 insertions, 30 deletions
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index ed67c9e..7f31394 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h @@ -35,6 +35,8 @@ extern void mmu_reset(void); extern void early_console_reg_tlb_alloc(unsigned int addr); # endif /* CONFIG_MMU */ +extern void of_platform_reset_gpio_probe(void); + void time_init(void); void init_IRQ(void); void machine_early_init(const char *cmdline, unsigned int ram, diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index d487729..fddd0c4 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds obj-y += exceptions.o \ hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ of_platform.o process.o prom.o prom_parse.o ptrace.o \ - setup.o signal.o sys_microblaze.o timer.o traps.o + setup.o signal.o sys_microblaze.o timer.o traps.o reset.o obj-y += cpu/ diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c new file mode 100644 index 0000000..ce74a6f --- /dev/null +++ b/arch/microblaze/kernel/reset.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2009 PetaLogix + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/init.h> +#include <linux/of_platform.h> +#include <asm/prom.h> + +/* Trigger specific functions */ +#ifdef CONFIG_GPIOLIB + +#include <linux/of_gpio.h> + +static int handle; /* reset pin handle */ + +static int of_reset_gpio_handle(void) +{ + int ret; /* variable which stored handle reset gpio pin */ + struct device_node *root; /* root node */ + struct device_node *gpio; /* gpio node */ + struct of_gpio_chip *of_gc = NULL; + enum of_gpio_flags flags ; + const void *gpio_spec; + + /* find out root node */ + root = of_find_node_by_path("/"); + + /* give me handle for gpio node to be possible allocate pin */ + ret = of_parse_phandles_with_args(root, "hard-reset-gpios", + "#gpio-cells", 0, &gpio, &gpio_spec); + if (ret) { + pr_debug("%s: can't parse gpios property\n", __func__); + goto err0; + } + + of_gc = gpio->data; + if (!of_gc) { + pr_debug("%s: gpio controller %s isn't registered\n", + root->full_name, gpio->full_name); + ret = -ENODEV; + goto err1; + } + + ret = of_gc->xlate(of_gc, root, gpio_spec, &flags); + if (ret < 0) + goto err1; + + ret += of_gc->gc.base; +err1: + of_node_put(gpio); +err0: + pr_debug("%s exited with status %d\n", __func__, ret); + return ret; +} + +void of_platform_reset_gpio_probe(void) +{ + int ret; + handle = of_reset_gpio_handle(); + + if (!gpio_is_valid(handle)) { + printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n", + handle, "reset"); + } + + ret = gpio_request(handle, "reset"); + if (ret < 0) { + printk(KERN_INFO "GPIO pin is already allocated\n"); + return; + } + + /* get current setup value */ + ret = gpio_get_value(handle); + /* FIXME maybe worth to perform any action */ + pr_debug("Reset: Gpio output state: 0x%x\n", ret); + + /* Setup GPIO as output */ + ret = gpio_direction_output(handle, 0); + if (ret < 0) + goto err; + + /* Setup output direction */ + gpio_set_value(handle, 0); + + printk(KERN_INFO "Registered reset device: %d\n", handle); + return; +err: + gpio_free(handle); + return; +} + + +static void gpio_system_reset(void) +{ + gpio_set_value(handle, 1); +} +#else +#define gpio_system_reset() do {} while (0) +void of_platform_reset_gpio_probe(void) +{ + return; +} +#endif + +void machine_restart(char *cmd) +{ + printk(KERN_NOTICE "Machine restart...\n"); + gpio_system_reset(); + dump_stack(); + while (1) + ; +} + +void machine_shutdown(void) +{ + printk(KERN_NOTICE "Machine shutdown...\n"); + while (1) + ; +} + +void machine_halt(void) +{ + printk(KERN_NOTICE "Machine halt...\n"); + while (1) + ; +} + +void machine_power_off(void) +{ + printk(KERN_NOTICE "Machine power off...\n"); + while (1) + ; +} diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 8c1e0f4..367ad33 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -186,32 +186,3 @@ static int microblaze_debugfs_init(void) } arch_initcall(microblaze_debugfs_init); #endif - -void machine_restart(char *cmd) -{ - printk(KERN_NOTICE "Machine restart...\n"); - dump_stack(); - while (1) - ; -} - -void machine_shutdown(void) -{ - printk(KERN_NOTICE "Machine shutdown...\n"); - while (1) - ; -} - -void machine_halt(void) -{ - printk(KERN_NOTICE "Machine halt...\n"); - while (1) - ; -} - -void machine_power_off(void) -{ - printk(KERN_NOTICE "Machine power off...\n"); - while (1) - ; -} diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts index 29993f6..e00da89 100644 --- a/arch/microblaze/platform/generic/system.dts +++ b/arch/microblaze/platform/generic/system.dts @@ -32,6 +32,7 @@ #address-cells = <1>; #size-cells = <1>; compatible = "xlnx,microblaze"; + hard-reset-gpios = <&LEDs_8Bit 2 1>; model = "testing"; DDR2_SDRAM: memory@90000000 { device_type = "memory"; @@ -261,6 +262,33 @@ xlnx,is-dual = <0x0>; xlnx,tri-default = <0xffffffff>; xlnx,tri-default-2 = <0xffffffff>; + #gpio-cells = <2>; + gpio-controller; + } ; + + gpio-leds { + compatible = "gpio-leds"; + + heartbeat { + label = "Heartbeat"; + gpios = <&LEDs_8Bit 4 1>; + linux,default-trigger = "heartbeat"; + }; + + yellow { + label = "Yellow"; + gpios = <&LEDs_8Bit 5 1>; + }; + + red { + label = "Red"; + gpios = <&LEDs_8Bit 6 1>; + }; + + green { + label = "Green"; + gpios = <&LEDs_8Bit 7 1>; + }; } ; RS232_Uart_1: serial@84000000 { clock-frequency = <125000000>; diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index 56e0234..5b89b58 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/of_platform.h> #include <asm/prom.h> +#include <asm/setup.h> static struct of_device_id xilinx_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, @@ -26,6 +27,7 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = { static int __init microblaze_device_probe(void) { of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); + of_platform_reset_gpio_probe(); return 0; } device_initcall(microblaze_device_probe); |