The core code calls these once per chip instance, so we can avoid the limitations of the static array and get rid of the sys device. Signed-off-by: Thomas Gleixner --- arch/arm/common/vic.c | 140 ++++++++++++-------------------------------------- 1 file changed, 36 insertions(+), 104 deletions(-) Index: linux-2.6/arch/arm/common/vic.c =================================================================== --- linux-2.6.orig/arch/arm/common/vic.c +++ linux-2.6/arch/arm/common/vic.c @@ -24,42 +24,12 @@ #include #include #include +#include #include #include #include -#if defined(CONFIG_PM) -/** - * struct vic_device - VIC PM device - * @sysdev: The system device which is registered. - * @gc: The generic irq chip for the VIC - * @int_select: Save for VIC_INT_SELECT. - * @int_enable: Save for VIC_INT_ENABLE. - * @soft_int: Save for VIC_INT_SOFT. - * @protect: Save for VIC_PROTECT. - */ -struct vic_device { - struct sys_device sysdev; - - struct irq_chip_generic *gc; - u32 int_select; - u32 int_enable; - u32 soft_int; - u32 protect; -}; - -/* we cannot allocate memory when VICs are initially registered */ -static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; - -static int vic_id; - -static inline struct vic_device *to_vic(struct sys_device *sys) -{ - return container_of(sys, struct vic_device, sysdev); -} -#endif /* CONFIG_PM */ - /** * vic_init2 - common initialisation code * @base: Base of the VIC. @@ -80,10 +50,25 @@ static void vic_init2(void __iomem *base } #if defined(CONFIG_PM) -static int vic_class_resume(struct sys_device *dev) +/** + * struct vic_pm_data - VIC PM data + * @int_select: Save for VIC_INT_SELECT. + * @int_enable: Save for VIC_INT_ENABLE. + * @soft_int: Save for VIC_INT_SOFT. + * @protect: Save for VIC_PROTECT. + */ +struct vic_pm_data { + u32 int_select; + u32 int_enable; + u32 soft_int; + u32 protect; +}; + +static void vic_irq_resume(struct irq_data *d) { - struct vic_device *vic = to_vic(dev); - void __iomem *base = vic->gc->reg_base; + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct vic_pm_data *vic = gc->private; + void __iomem *base = gc->reg_base; printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base); @@ -98,17 +83,15 @@ static int vic_class_resume(struct sys_d writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR); /* and the same for the soft-int register */ - writel(vic->soft_int, base + VIC_INT_SOFT); writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR); - - return 0; } -static int vic_class_suspend(struct sys_device *dev, pm_message_t state) +static void vic_irq_suspend(struct irq_data *d) { - struct vic_device *vic = to_vic(dev); - void __iomem *base = vic->gc->reg_base; + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct vic_pm_data *vic = gc->private; + void __iomem *base = gc->reg_base; printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base); @@ -119,78 +102,27 @@ static int vic_class_suspend(struct sys_ /* set the interrupts (if any) that are used for * resuming the system */ - - writel(vic->gc->wake_active, base + VIC_INT_ENABLE); - writel(~vic->gc->wake_active, base + VIC_INT_ENABLE_CLEAR); - - return 0; -} - -struct sysdev_class vic_class = { - .name = "vic", - .suspend = vic_class_suspend, - .resume = vic_class_resume, -}; - -/** - * vic_pm_init - initicall to register VIC pm - * - * This is called via late_initcall() to register - * the resources for the VICs due to the early - * nature of the VIC's registration. -*/ -static int __init vic_pm_init(void) -{ - struct vic_device *dev = vic_devices; - int err; - int id; - - if (vic_id == 0) - return 0; - - err = sysdev_class_register(&vic_class); - if (err) { - printk(KERN_ERR "%s: cannot register class\n", __func__); - return err; - } - - for (id = 0; id < vic_id; id++, dev++) { - dev->sysdev.id = id; - dev->sysdev.cls = &vic_class; - - err = sysdev_register(&dev->sysdev); - if (err) { - printk(KERN_ERR "%s: failed to register device\n", - __func__); - return err; - } - } - - return 0; + writel(gc->wake_active, base + VIC_INT_ENABLE); + writel(~gc->wake_active, base + VIC_INT_ENABLE_CLEAR); } -late_initcall(vic_pm_init); /** - * vic_pm_register - Register a VIC for later power management control + * vic_pm_init - Initialize the VIC instance for PM * @gc: The generic interrupt chip for the VIC * - * Register the VIC with the system device tree so that it can be notified - * of suspend and resume requests and ensure that the correct actions are - * taken to re-instate the settings on resume. + * Setup gc->private for storing the values which are not available from + * the generic gc cache fields. */ -static void __init vic_pm_register(struct irq_chip_generic *gc) +static void __init vic_pm_init(struct irq_chip_generic *gc) { - struct vic_device *v; - - if (vic_id >= ARRAY_SIZE(vic_devices)) - printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); - else { - v = &vic_devices[vic_id]; - v->gc = gc; - } + gc->private = kzalloc(sizeof(struct vic_pm_data), GFP_KERNEL); + if (!gc->private) + return; + gc->chip_types->chip.irq_suspend = vic_irq_suspend; + gc->chip_types->chip.irq_resume = vic_irq_resume; } #else -static inline void vic_pm_register(struct irq_generic_chip *gc) { } +static inline void vic_pm_init(struct irq_generic_chip *gc) { } #endif /* CONFIG_PM */ static void __init vic_disable(void __iomem *base) @@ -320,5 +252,5 @@ void __init vic_init(void __iomem *base, gc = vic_set_irq_sources(base, irq_start, vic_sources, resume_sources); - vic_pm_register(gc); + vic_pm_init(gc); }