MIPS: Alchemy: add sysdev for IRQ PM.
PATCH v4 1/1 MIPS: Alchemy: add sysdev for IRQ PM.
Use a sysdev to implement PM methods for the Au1000 interrupt controllers.
Signed-off-by Manuel Lauss <[email protected]>
---
v4: need slab.h for kzalloc
v3: fix odd formatting
v2: register a sysdev for each of the 2 controllers (instead of a single one
handling both).
arch/mips/alchemy/common/irq.c | 197 ++++++++++++++++------------ arch/mips/alchemy/common/power.c | 5 - arch/mips/include/asm/mach-au1x00/au1000.h | 2 - 3 files changed, 113 insertions(+), 91 deletions(-)
arch/mips/alchemy/common/irq.c +113 -84
@@ -29,6 +29,8 @@#include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/slab.h> +#include <linux/sysdev.h> #include <asm/irq_cpu.h> #include <asm/mipsregs.h>
@@ -216,90 +218,6 @@ struct au1xxx_irqmap au1200_irqmap[] __initdata = { }; -#ifdef CONFIG_PM - -/* -* Save/restore the interrupt controller state. -* Called from the save/restore core registers as part of the -* au_sleep function in power.c.....maybe I should just pm_register() -* them instead? -*/ -static unsigned int sleep_intctl_config0[2 ]; -static unsigned int sleep_intctl_config1[2 ]; -static unsigned int sleep_intctl_config2[2 ]; -static unsigned int sleep_intctl_src[2 ]; -static unsigned int sleep_intctl_assign[2 ]; -static unsigned int sleep_intctl_wake[2 ]; -static unsigned int sleep_intctl_mask[2 ]; - -void save_au1xxx_intctl (void ) -{ - sleep_intctl_config0[0 ] =au_readl (IC0_CFG0RD ); - sleep_intctl_config1[0 ] =au_readl (IC0_CFG1RD ); - sleep_intctl_config2[0 ] =au_readl (IC0_CFG2RD ); - sleep_intctl_src[0 ] =au_readl (IC0_SRCRD ); - sleep_intctl_assign[0 ] =au_readl (IC0_ASSIGNRD ); - sleep_intctl_wake[0 ] =au_readl (IC0_WAKERD ); - sleep_intctl_mask[0 ] =au_readl (IC0_MASKRD ); - - sleep_intctl_config0[1 ] =au_readl (IC1_CFG0RD ); - sleep_intctl_config1[1 ] =au_readl (IC1_CFG1RD ); - sleep_intctl_config2[1 ] =au_readl (IC1_CFG2RD ); - sleep_intctl_src[1 ] =au_readl (IC1_SRCRD ); - sleep_intctl_assign[1 ] =au_readl (IC1_ASSIGNRD ); - sleep_intctl_wake[1 ] =au_readl (IC1_WAKERD ); - sleep_intctl_mask[1 ] =au_readl (IC1_MASKRD ); -} - -/* -* For most restore operations, we clear the entire register and -* then set the bits we found during the save. -*/ -void restore_au1xxx_intctl (void ) -{ -au_writel (0xffffffff ,IC0_MASKCLR );au_sync (); - -au_writel (0xffffffff ,IC0_CFG0CLR );au_sync (); -au_writel (sleep_intctl_config0[0 ],IC0_CFG0SET );au_sync (); -au_writel (0xffffffff ,IC0_CFG1CLR );au_sync (); -au_writel (sleep_intctl_config1[0 ],IC0_CFG1SET );au_sync (); -au_writel (0xffffffff ,IC0_CFG2CLR );au_sync (); -au_writel (sleep_intctl_config2[0 ],IC0_CFG2SET );au_sync (); -au_writel (0xffffffff ,IC0_SRCCLR );au_sync (); -au_writel (sleep_intctl_src[0 ],IC0_SRCSET );au_sync (); -au_writel (0xffffffff ,IC0_ASSIGNCLR );au_sync (); -au_writel (sleep_intctl_assign[0 ],IC0_ASSIGNSET );au_sync (); -au_writel (0xffffffff ,IC0_WAKECLR );au_sync (); -au_writel (sleep_intctl_wake[0 ],IC0_WAKESET );au_sync (); -au_writel (0xffffffff ,IC0_RISINGCLR );au_sync (); -au_writel (0xffffffff ,IC0_FALLINGCLR );au_sync (); -au_writel (0x00000000 ,IC0_TESTBIT );au_sync (); - -au_writel (0xffffffff ,IC1_MASKCLR );au_sync (); - -au_writel (0xffffffff ,IC1_CFG0CLR );au_sync (); -au_writel (sleep_intctl_config0[1 ],IC1_CFG0SET );au_sync (); -au_writel (0xffffffff ,IC1_CFG1CLR );au_sync (); -au_writel (sleep_intctl_config1[1 ],IC1_CFG1SET );au_sync (); -au_writel (0xffffffff ,IC1_CFG2CLR );au_sync (); -au_writel (sleep_intctl_config2[1 ],IC1_CFG2SET );au_sync (); -au_writel (0xffffffff ,IC1_SRCCLR );au_sync (); -au_writel (sleep_intctl_src[1 ],IC1_SRCSET );au_sync (); -au_writel (0xffffffff ,IC1_ASSIGNCLR );au_sync (); -au_writel (sleep_intctl_assign[1 ],IC1_ASSIGNSET );au_sync (); -au_writel (0xffffffff ,IC1_WAKECLR );au_sync (); -au_writel (sleep_intctl_wake[1 ],IC1_WAKESET );au_sync (); -au_writel (0xffffffff ,IC1_RISINGCLR );au_sync (); -au_writel (0xffffffff ,IC1_FALLINGCLR );au_sync (); -au_writel (0x00000000 ,IC1_TESTBIT );au_sync (); - -au_writel (sleep_intctl_mask[1 ],IC1_MASKSET );au_sync (); - -au_writel (sleep_intctl_mask[0 ],IC0_MASKSET );au_sync (); -} -#endif /* CONFIG_PM */ - -static void au1x_ic0_unmask (unsigned int irq_nr) {unsigned int bit = irq_nr -AU1000_INTC0_INT_BASE ;
@@ -635,3 +553,114 @@ void __init arch_init_irq(void)break ; } } + +struct alchemy_ic_sysdev { +struct sys_device sysdev; +unsigned long pmdata[7 *2 ]; +}; + +static int alchemy_ic_suspend (struct sys_device *dev,pm_message_t state) +{ +struct alchemy_ic_sysdev *icdev = + container_of(dev, struct alchemy_ic_sysdev, sysdev); + + icdev->pmdata[0 ] =au_readl (IC0_CFG0RD ); + icdev->pmdata[1 ] =au_readl (IC0_CFG1RD ); + icdev->pmdata[2 ] =au_readl (IC0_CFG2RD ); + icdev->pmdata[3 ] =au_readl (IC0_SRCRD ); + icdev->pmdata[4 ] =au_readl (IC0_ASSIGNRD ); + icdev->pmdata[5 ] =au_readl (IC0_WAKERD ); + icdev->pmdata[6 ] =au_readl (IC0_MASKRD ); + + icdev->pmdata[7 ] =au_readl (IC1_CFG0RD ); + icdev->pmdata[8 ] =au_readl (IC1_CFG1RD ); + icdev->pmdata[9 ] =au_readl (IC1_CFG2RD ); + icdev->pmdata[10 ] =au_readl (IC1_SRCRD ); + icdev->pmdata[11 ] =au_readl (IC1_ASSIGNRD ); + icdev->pmdata[12 ] =au_readl (IC1_WAKERD ); + icdev->pmdata[13 ] =au_readl (IC1_MASKRD ); + +return 0 ; +} + +static int alchemy_ic_resume (struct sys_device *dev) +{ +struct alchemy_ic_sysdev *icdev = + container_of(dev, struct alchemy_ic_sysdev, sysdev); + +au_writel (0xffffffff ,IC0_MASKCLR ); +au_writel (0xffffffff ,IC0_CFG0CLR ); +au_writel (0xffffffff ,IC0_CFG1CLR ); +au_writel (0xffffffff ,IC0_CFG2CLR ); +au_writel (0xffffffff ,IC0_SRCCLR ); +au_writel (0xffffffff ,IC0_ASSIGNCLR ); +au_writel (0xffffffff ,IC0_WAKECLR ); +au_writel (0xffffffff ,IC0_RISINGCLR ); +au_writel (0xffffffff ,IC0_FALLINGCLR ); +au_writel (0x00000000 ,IC0_TESTBIT ); +au_sync (); +au_writel (icdev->pmdata[0 ],IC0_CFG0SET ); +au_writel (icdev->pmdata[1 ],IC0_CFG1SET ); +au_writel (icdev->pmdata[2 ],IC0_CFG2SET ); +au_writel (icdev->pmdata[3 ],IC0_SRCSET ); +au_writel (icdev->pmdata[4 ],IC0_ASSIGNSET ); +au_writel (icdev->pmdata[5 ],IC0_WAKESET ); +au_sync (); + +au_writel (0xffffffff ,IC1_MASKCLR ); +au_writel (0xffffffff ,IC1_CFG0CLR ); +au_writel (0xffffffff ,IC1_CFG1CLR ); +au_writel (0xffffffff ,IC1_CFG2CLR ); +au_writel (0xffffffff ,IC1_SRCCLR ); +au_writel (0xffffffff ,IC1_ASSIGNCLR ); +au_writel (0xffffffff ,IC1_WAKECLR ); +au_writel (0xffffffff ,IC1_RISINGCLR ); +au_writel (0xffffffff ,IC1_FALLINGCLR ); +au_writel (0x00000000 ,IC1_TESTBIT ); +au_sync (); +au_writel (icdev->pmdata[7 ],IC1_CFG0SET ); +au_writel (icdev->pmdata[8 ],IC1_CFG1SET ); +au_writel (icdev->pmdata[9 ],IC1_CFG2SET ); +au_writel (icdev->pmdata[10 ],IC1_SRCSET ); +au_writel (icdev->pmdata[11 ],IC1_ASSIGNSET ); +au_writel (icdev->pmdata[12 ],IC1_WAKESET ); +au_sync (); + +au_writel (icdev->pmdata[13 ],IC1_MASKSET ); +au_sync (); +au_writel (icdev->pmdata[6 ],IC0_MASKSET ); +au_sync (); + +return 0 ; +} + +static struct sysdev_class alchemy_ic_sysdev_class = { + .name ="ic" , + .suspend = alchemy_ic_suspend, + .resume = alchemy_ic_resume, +}; + +static int __init alchemy_ic_sysdev_init (void ) +{ +struct alchemy_ic_sysdev *icdev; +int err; + + icdev =kzalloc (sizeof (struct alchemy_ic_sysdev ),GFP_KERNEL ); +if (!icdev) +return -ENOMEM ; + + err =sysdev_class_register (&alchemy_ic_sysdev_class); +if (err) { +kfree (icdev); +return err; + } + + icdev->sysdev.id =0 ; + icdev->sysdev.cls = &alchemy_ic_sysdev_class; + err =sysdev_register (&icdev->sysdev); +if (err) +kfree (icdev); + +return err; +} +device_initcall (alchemy_ic_sysdev_init);
arch/mips/alchemy/common/power.c +0 -5
@@ -106,9 +106,6 @@ static void save_core_regs(void) sleep_usb[1 ] =au_readl (0xb4020024 );/* OTG_MUX */ #endif -/* Save interrupt controller state. */ -save_au1xxx_intctl (); -/* Clocks and PLLs. */ sleep_sys_clocks[0 ] =au_readl (SYS_FREQCTRL0 ); sleep_sys_clocks[1 ] =au_readl (SYS_FREQCTRL1 );
@@ -200,8 +197,6 @@ static void restore_core_regs(void)au_writel (sleep_uart0_clkdiv,UART0_ADDR +UART_CLK );au_sync (); } -restore_au1xxx_intctl (); -#if defined(CONFIG_SOC_AU1550 ) || defined(CONFIG_SOC_AU1200 )au1xxx_dbdma_resume ();#endif
arch/mips/include/asm/mach-au1x00/au1000.h +0 -2
@@ -191,8 +191,6 @@ extern unsigned long au1xxx_calc_clock(void);void alchemy_sleep_au1000 (void );void alchemy_sleep_au1550 (void );void au_sleep (void ); -void save_au1xxx_intctl (void ); -void restore_au1xxx_intctl (void );/* SOC Interrupt numbers */
Signature · 1 line
1.7.0.3
Whoa, ignore this one, it's and old version (again).
Manuel