162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Copyright 2010 Ben Dooks <ben-linux@fluff.org>
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Support for wakeup mask interrupts on newer SoCs
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/spinlock.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/types.h>
1162306a36Sopenharmony_ci#include <linux/irq.h>
1262306a36Sopenharmony_ci#include <linux/io.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "wakeup-mask.h"
1562306a36Sopenharmony_ci#include "pm.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_civoid samsung_sync_wakemask(void __iomem *reg,
1862306a36Sopenharmony_ci			   const struct samsung_wakeup_mask *mask, int nr_mask)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	struct irq_data *data;
2162306a36Sopenharmony_ci	u32 val;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	val = __raw_readl(reg);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	for (; nr_mask > 0; nr_mask--, mask++) {
2662306a36Sopenharmony_ci		if (mask->irq == NO_WAKEUP_IRQ) {
2762306a36Sopenharmony_ci			val |= mask->bit;
2862306a36Sopenharmony_ci			continue;
2962306a36Sopenharmony_ci		}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci		data = irq_get_irq_data(mask->irq);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci		/* bit of a liberty to read this directly from irq_data. */
3462306a36Sopenharmony_ci		if (irqd_is_wakeup_set(data))
3562306a36Sopenharmony_ci			val &= ~mask->bit;
3662306a36Sopenharmony_ci		else
3762306a36Sopenharmony_ci			val |= mask->bit;
3862306a36Sopenharmony_ci	}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	printk(KERN_INFO "wakemask %08x => %08x\n", __raw_readl(reg), val);
4162306a36Sopenharmony_ci	__raw_writel(val, reg);
4262306a36Sopenharmony_ci}
43