Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

microblaze: Switch to standard restart handler

The microblaze uses the legacy APIs to dig out a GPIO pin
defined in the root of the device tree to issue a hard
reset of the platform.

Asserting a hard reset should be done using the standard
DT-enabled and fully GPIO descriptor aware driver in
drivers/power/reset/gpio-restart.c using the bindings
from Documentation/devicetree/bindings/power/reset/gpio-restart.txt

To achieve this, first make sure microblaze makes use of
the standard kernel restart path utilizing do_kernel_restart()
from <linux/reboot.h>. Put in some grace time and an
emergency print if the restart does not properly assert.

As this is basic platform functionality we patch the DTS
file and defconfig in one go for a lockstep change.

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Michal Simek <monstr@monstr.eu>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
[ Michal: Move machine_restart back to reset.c ]
Signed-off-by: Michal Simek <michal.simek@xilinx.com>

authored by

Linus Walleij and committed by
Michal Simek
7cca9b8b 1c62ed90

+30 -77
+15 -1
arch/microblaze/boot/dts/system.dts
··· 18 18 #address-cells = <1>; 19 19 #size-cells = <1>; 20 20 compatible = "xlnx,microblaze"; 21 - hard-reset-gpios = <&LEDs_8Bit 2 1>; 22 21 model = "testing"; 23 22 DDR2_SDRAM: memory@90000000 { 24 23 device_type = "memory"; ··· 280 281 gpios = <&LEDs_8Bit 7 1>; 281 282 }; 282 283 } ; 284 + 285 + gpio-restart { 286 + compatible = "gpio-restart"; 287 + /* 288 + * FIXME: is this active low or active high? 289 + * the current flag (1) indicates active low. 290 + * delay measures are templates, should be adjusted 291 + * to datasheet or trial-and-error with real hardware. 292 + */ 293 + gpios = <&LEDs_8Bit 2 1>; 294 + active-delay = <100>; 295 + inactive-delay = <10>; 296 + wait-delay = <100>; 297 + }; 298 + 283 299 RS232_Uart_1: serial@84000000 { 284 300 clock-frequency = <125000000>; 285 301 compatible = "xlnx,xps-uartlite-1.00.a";
+2
arch/microblaze/configs/mmu_defconfig
··· 60 60 CONFIG_GPIOLIB=y 61 61 CONFIG_GPIO_SYSFS=y 62 62 CONFIG_GPIO_XILINX=y 63 + CONFIG_POWER_RESET=y 64 + CONFIG_POWER_RESET_GPIO_RESTART=y 63 65 # CONFIG_HWMON is not set 64 66 CONFIG_WATCHDOG=y 65 67 CONFIG_XILINX_WATCHDOG=y
+2
arch/microblaze/configs/nommu_defconfig
··· 62 62 CONFIG_GPIOLIB=y 63 63 CONFIG_GPIO_SYSFS=y 64 64 CONFIG_GPIO_XILINX=y 65 + CONFIG_POWER_RESET=y 66 + CONFIG_POWER_RESET_GPIO_RESTART=y 65 67 # CONFIG_HWMON is not set 66 68 CONFIG_WATCHDOG=y 67 69 CONFIG_XILINX_WATCHDOG=y
+11 -76
arch/microblaze/kernel/reset.c
··· 8 8 */ 9 9 10 10 #include <linux/init.h> 11 + #include <linux/delay.h> 11 12 #include <linux/of_platform.h> 12 - 13 - /* Trigger specific functions */ 14 - #ifdef CONFIG_GPIOLIB 15 - 16 - #include <linux/of_gpio.h> 17 - 18 - static int handle; /* reset pin handle */ 19 - static unsigned int reset_val; 20 - 21 - static int of_platform_reset_gpio_probe(void) 22 - { 23 - int ret; 24 - handle = of_get_named_gpio(of_find_node_by_path("/"), 25 - "hard-reset-gpios", 0); 26 - 27 - if (!gpio_is_valid(handle)) { 28 - pr_info("Skipping unavailable RESET gpio %d (%s)\n", 29 - handle, "reset"); 30 - return -ENODEV; 31 - } 32 - 33 - ret = gpio_request(handle, "reset"); 34 - if (ret < 0) { 35 - pr_info("GPIO pin is already allocated\n"); 36 - return ret; 37 - } 38 - 39 - /* get current setup value */ 40 - reset_val = gpio_get_value(handle); 41 - /* FIXME maybe worth to perform any action */ 42 - pr_debug("Reset: Gpio output state: 0x%x\n", reset_val); 43 - 44 - /* Setup GPIO as output */ 45 - ret = gpio_direction_output(handle, 0); 46 - if (ret < 0) 47 - goto err; 48 - 49 - /* Setup output direction */ 50 - gpio_set_value(handle, 0); 51 - 52 - pr_info("RESET: Registered gpio device: %d, current val: %d\n", 53 - handle, reset_val); 54 - return 0; 55 - err: 56 - gpio_free(handle); 57 - return ret; 58 - } 59 - device_initcall(of_platform_reset_gpio_probe); 60 - 61 - 62 - static void gpio_system_reset(void) 63 - { 64 - if (gpio_is_valid(handle)) 65 - gpio_set_value(handle, 1 - reset_val); 66 - else 67 - pr_notice("Reset GPIO unavailable - halting!\n"); 68 - } 69 - #else 70 - static void gpio_system_reset(void) 71 - { 72 - pr_notice("No reset GPIO present - halting!\n"); 73 - } 74 - 75 - void of_platform_reset_gpio_probe(void) 76 - { 77 - return; 78 - } 79 - #endif 80 - 81 - void machine_restart(char *cmd) 82 - { 83 - pr_notice("Machine restart...\n"); 84 - gpio_system_reset(); 85 - while (1) 86 - ; 87 - } 13 + #include <linux/reboot.h> 88 14 89 15 void machine_shutdown(void) 90 16 { ··· 31 105 pr_notice("Machine power off...\n"); 32 106 while (1) 33 107 ; 108 + } 109 + 110 + void machine_restart(char *cmd) 111 + { 112 + do_kernel_restart(cmd); 113 + /* Give the restart hook 1 s to take us down */ 114 + mdelay(1000); 115 + pr_emerg("Reboot failed -- System halted\n"); 116 + while (1); 34 117 }