diff options
author | Joshua Kinard <kumba@gentoo.org> | 2015-04-16 22:49:09 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 16:04:11 +0300 |
commit | 15beb694c66146e1133b9ff81d54e3ef3daa1d7c (patch) | |
tree | de69c469d7f6260c51f8d22a6e0492c7f58f12f2 /arch/mips/sgi-ip32/ip32-reset.c | |
parent | 9e522c0d28d1418c2983ffbc3903f7bed3354180 (diff) | |
download | linux-15beb694c66146e1133b9ff81d54e3ef3daa1d7c.tar.xz |
mips: ip32: add platform data hooks to use DS1685 driver
This modifies the IP32 (SGI O2) platform and reset code to utilize the new
rtc-ds1685 driver. The old mc146818rtc.h header is removed and ip32_defconfig
is updated as well.
Signed-off-by: Joshua Kinard <kumba@gentoo.org>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/mips/sgi-ip32/ip32-reset.c')
-rw-r--r-- | arch/mips/sgi-ip32/ip32-reset.c | 131 |
1 files changed, 39 insertions, 92 deletions
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 44b3470a0bbb..8bd415c8729f 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -11,10 +11,11 @@ #include <linux/compiler.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/notifier.h> #include <linux/delay.h> -#include <linux/ds17287rtc.h> +#include <linux/rtc/ds1685.h> #include <linux/interrupt.h> #include <linux/pm.h> @@ -33,53 +34,40 @@ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) -static struct timer_list power_timer, blink_timer, debounce_timer; -static int has_panicked, shuting_down; +extern struct platform_device ip32_rtc_device; -static void ip32_machine_restart(char *command) __noreturn; -static void ip32_machine_halt(void) __noreturn; -static void ip32_machine_power_off(void) __noreturn; +static struct timer_list power_timer, blink_timer; +static int has_panicked, shutting_down; -static void ip32_machine_restart(char *cmd) +static __noreturn void ip32_poweroff(void *data) { - crime->control = CRIME_CONTROL_HARD_RESET; - while (1); -} + void (*poweroff_func)(struct platform_device *) = + symbol_get(ds1685_rtc_poweroff); + +#ifdef CONFIG_MODULES + /* If the first __symbol_get failed, our module wasn't loaded. */ + if (!poweroff_func) { + request_module("rtc-ds1685"); + poweroff_func = symbol_get(ds1685_rtc_poweroff); + } +#endif -static inline void ip32_machine_halt(void) -{ - ip32_machine_power_off(); -} + if (!poweroff_func) + pr_emerg("RTC not available for power-off. Spinning forever ...\n"); + else { + (*poweroff_func)((struct platform_device *)data); + symbol_put(ds1685_rtc_poweroff); + } -static void ip32_machine_power_off(void) -{ - unsigned char reg_a, xctrl_a, xctrl_b; - - disable_irq(MACEISA_RTC_IRQ); - reg_a = CMOS_READ(RTC_REG_A); - - /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */ - reg_a &= ~DS_REGA_DV2; - reg_a |= DS_REGA_DV1; - - CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); - wbflush(); - xctrl_b = CMOS_READ(DS_B1_XCTRL4B) - | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE; - CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B); - xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS; - CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A); - wbflush(); - /* adios amigos... */ - CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A); - CMOS_WRITE(reg_a, RTC_REG_A); - wbflush(); - while (1); + unreachable(); } -static void power_timeout(unsigned long data) +static void ip32_machine_restart(char *cmd) __noreturn; +static void ip32_machine_restart(char *cmd) { - ip32_machine_power_off(); + msleep(20); + crime->control = CRIME_CONTROL_HARD_RESET; + unreachable(); } static void blink_timeout(unsigned long data) @@ -89,44 +77,27 @@ static void blink_timeout(unsigned long data) mod_timer(&blink_timer, jiffies + data); } -static void debounce(unsigned long data) +static void ip32_machine_halt(void) { - unsigned char reg_a, reg_c, xctrl_a; - - reg_c = CMOS_READ(RTC_INTR_FLAGS); - reg_a = CMOS_READ(RTC_REG_A); - CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); - wbflush(); - xctrl_a = CMOS_READ(DS_B1_XCTRL4A); - if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) { - /* Interrupt still being sent. */ - debounce_timer.expires = jiffies + 50; - add_timer(&debounce_timer); - - /* clear interrupt source */ - CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A); - CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - return; - } - CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - - if (has_panicked) - ip32_machine_restart(NULL); + ip32_poweroff(&ip32_rtc_device); +} - enable_irq(MACEISA_RTC_IRQ); +static void power_timeout(unsigned long data) +{ + ip32_poweroff(&ip32_rtc_device); } -static inline void ip32_power_button(void) +void ip32_prepare_poweroff(void) { if (has_panicked) return; - if (shuting_down || kill_cad_pid(SIGINT, 1)) { + if (shutting_down || kill_cad_pid(SIGINT, 1)) { /* No init process or button pressed twice. */ - ip32_machine_power_off(); + ip32_poweroff(&ip32_rtc_device); } - shuting_down = 1; + shutting_down = 1; blink_timer.data = POWERDOWN_FREQ; blink_timeout(POWERDOWN_FREQ); @@ -136,27 +107,6 @@ static inline void ip32_power_button(void) add_timer(&power_timer); } -static irqreturn_t ip32_rtc_int(int irq, void *dev_id) -{ - unsigned char reg_c; - - reg_c = CMOS_READ(RTC_INTR_FLAGS); - if (!(reg_c & RTC_IRQF)) { - printk(KERN_WARNING - "%s: RTC IRQ without RTC_IRQF\n", __func__); - } - /* Wait until interrupt goes away */ - disable_irq_nosync(MACEISA_RTC_IRQ); - init_timer(&debounce_timer); - debounce_timer.function = debounce; - debounce_timer.expires = jiffies + 50; - add_timer(&debounce_timer); - - printk(KERN_DEBUG "Power button pressed\n"); - ip32_power_button(); - return IRQ_HANDLED; -} - static int panic_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -190,15 +140,12 @@ static __init int ip32_reboot_setup(void) _machine_restart = ip32_machine_restart; _machine_halt = ip32_machine_halt; - pm_power_off = ip32_machine_power_off; + pm_power_off = ip32_machine_halt; init_timer(&blink_timer); blink_timer.function = blink_timeout; atomic_notifier_chain_register(&panic_notifier_list, &panic_block); - if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL)) - panic("Can't allocate MACEISA RTC IRQ"); - return 0; } |