|  | @@ -140,3 +140,188 @@ static void wakeupgen_mask(struct irq_data *d)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  | + * Architecture specific Unmask extension
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static void wakeupgen_unmask(struct irq_data *d)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long flags;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	spin_lock_irqsave(&wakeupgen_lock, flags);
 | 
	
		
			
				|  |  | +	_wakeupgen_set(d->irq, irq_target_cpu[d->irq]);
 | 
	
		
			
				|  |  | +	spin_unlock_irqrestore(&wakeupgen_lock, flags);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef CONFIG_HOTPLUG_CPU
 | 
	
		
			
				|  |  | +static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void _wakeupgen_save_masks(unsigned int cpu)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u8 i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < irq_banks; i++)
 | 
	
		
			
				|  |  | +		per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void _wakeupgen_restore_masks(unsigned int cpu)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u8 i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < irq_banks; i++)
 | 
	
		
			
				|  |  | +		wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u8 i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < irq_banks; i++)
 | 
	
		
			
				|  |  | +		wakeupgen_writel(reg, i, cpu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Mask or unmask all interrupts on given CPU.
 | 
	
		
			
				|  |  | + *	0 = Mask all interrupts on the 'cpu'
 | 
	
		
			
				|  |  | + *	1 = Unmask all interrupts on the 'cpu'
 | 
	
		
			
				|  |  | + * Ensure that the initial mask is maintained. This is faster than
 | 
	
		
			
				|  |  | + * iterating through GIC registers to arrive at the correct masks.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long flags;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	spin_lock_irqsave(&wakeupgen_lock, flags);
 | 
	
		
			
				|  |  | +	if (set) {
 | 
	
		
			
				|  |  | +		_wakeupgen_save_masks(cpu);
 | 
	
		
			
				|  |  | +		_wakeupgen_set_all(cpu, WKG_MASK_ALL);
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +		_wakeupgen_set_all(cpu, WKG_UNMASK_ALL);
 | 
	
		
			
				|  |  | +		_wakeupgen_restore_masks(cpu);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	spin_unlock_irqrestore(&wakeupgen_lock, flags);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef CONFIG_CPU_PM
 | 
	
		
			
				|  |  | +static inline void omap4_irq_save_context(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 i, val;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (omap_rev() == OMAP4430_REV_ES1_0)
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < irq_banks; i++) {
 | 
	
		
			
				|  |  | +		/* Save the CPUx interrupt mask for IRQ 0 to 127 */
 | 
	
		
			
				|  |  | +		val = wakeupgen_readl(i, 0);
 | 
	
		
			
				|  |  | +		sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
 | 
	
		
			
				|  |  | +		val = wakeupgen_readl(i, 1);
 | 
	
		
			
				|  |  | +		sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * Disable the secure interrupts for CPUx. The restore
 | 
	
		
			
				|  |  | +		 * code blindly restores secure and non-secure interrupt
 | 
	
		
			
				|  |  | +		 * masks from SAR RAM. Secure interrupts are not suppose
 | 
	
		
			
				|  |  | +		 * to be enabled from HLOS. So overwrite the SAR location
 | 
	
		
			
				|  |  | +		 * so that the secure interrupt remains disabled.
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
 | 
	
		
			
				|  |  | +		sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Save AuxBoot* registers */
 | 
	
		
			
				|  |  | +	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
 | 
	
		
			
				|  |  | +	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_1);
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Save SyncReq generation logic */
 | 
	
		
			
				|  |  | +	val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET);
 | 
	
		
			
				|  |  | +	val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Set the Backup Bit Mask status */
 | 
	
		
			
				|  |  | +	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
 | 
	
		
			
				|  |  | +	val |= SAR_BACKUP_STATUS_WAKEUPGEN;
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static inline void omap5_irq_save_context(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 i, val;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < irq_banks; i++) {
 | 
	
		
			
				|  |  | +		/* Save the CPUx interrupt mask for IRQ 0 to 159 */
 | 
	
		
			
				|  |  | +		val = wakeupgen_readl(i, 0);
 | 
	
		
			
				|  |  | +		sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i);
 | 
	
		
			
				|  |  | +		val = wakeupgen_readl(i, 1);
 | 
	
		
			
				|  |  | +		sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i);
 | 
	
		
			
				|  |  | +		sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
 | 
	
		
			
				|  |  | +		sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Save AuxBoot* registers */
 | 
	
		
			
				|  |  | +	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET);
 | 
	
		
			
				|  |  | +	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Set the Backup Bit Mask status */
 | 
	
		
			
				|  |  | +	val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
 | 
	
		
			
				|  |  | +	val |= SAR_BACKUP_STATUS_WAKEUPGEN;
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
 | 
	
		
			
				|  |  | + * ROM code. WakeupGen IP is integrated along with GIC to manage the
 | 
	
		
			
				|  |  | + * interrupt wakeups from CPU low power states. It manages
 | 
	
		
			
				|  |  | + * masking/unmasking of Shared peripheral interrupts(SPI). So the
 | 
	
		
			
				|  |  | + * interrupt enable/disable control should be in sync and consistent
 | 
	
		
			
				|  |  | + * at WakeupGen and GIC so that interrupts are not lost.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static void irq_save_context(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (!sar_base)
 | 
	
		
			
				|  |  | +		sar_base = omap4_get_sar_ram_base();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (soc_is_omap54xx())
 | 
	
		
			
				|  |  | +		omap5_irq_save_context();
 | 
	
		
			
				|  |  | +	else
 | 
	
		
			
				|  |  | +		omap4_irq_save_context();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Clear WakeupGen SAR backup status.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static void irq_sar_clear(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 val;
 | 
	
		
			
				|  |  | +	u32 offset = SAR_BACKUP_STATUS_OFFSET;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (soc_is_omap54xx())
 | 
	
		
			
				|  |  | +		offset = OMAP5_SAR_BACKUP_STATUS_OFFSET;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	val = __raw_readl(sar_base + offset);
 | 
	
		
			
				|  |  | +	val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
 | 
	
		
			
				|  |  | +	__raw_writel(val, sar_base + offset);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Save GIC and Wakeupgen interrupt context using secure API
 | 
	
		
			
				|  |  | + * for HS/EMU devices.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static void irq_save_secure_context(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 ret;
 | 
	
		
			
				|  |  | +	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
 | 
	
		
			
				|  |  | +				FLAG_START_CRITICAL,
 | 
	
		
			
				|  |  | +				0, 0, 0, 0, 0);
 | 
	
		
			
				|  |  | +	if (ret != API_HAL_RET_VALUE_OK)
 | 
	
		
			
				|  |  | +		pr_err("GIC and Wakeupgen context save failed\n");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef CONFIG_HOTPLUG_CPU
 | 
	
		
			
				|  |  | +static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
 |