162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/sh/boards/renesas/r7780rp/psw.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * push switch support for RDBRP-1/RDBREVRP-1 debug boards.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2006  Paul Mundt
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <linux/io.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/interrupt.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <mach/highlander.h>
1462306a36Sopenharmony_ci#include <asm/push-switch.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic irqreturn_t psw_irq_handler(int irq, void *arg)
1762306a36Sopenharmony_ci{
1862306a36Sopenharmony_ci	struct platform_device *pdev = arg;
1962306a36Sopenharmony_ci	struct push_switch *psw = platform_get_drvdata(pdev);
2062306a36Sopenharmony_ci	struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
2162306a36Sopenharmony_ci	unsigned int l, mask;
2262306a36Sopenharmony_ci	int ret = 0;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	l = __raw_readw(PA_DBSW);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	/* Nothing to do if there's no state change */
2762306a36Sopenharmony_ci	if (psw->state) {
2862306a36Sopenharmony_ci		ret = 1;
2962306a36Sopenharmony_ci		goto out;
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	mask = l & 0x70;
3362306a36Sopenharmony_ci	/* Figure out who raised it */
3462306a36Sopenharmony_ci	if (mask & (1 << psw_info->bit)) {
3562306a36Sopenharmony_ci		psw->state = !!(mask & (1 << psw_info->bit));
3662306a36Sopenharmony_ci		if (psw->state)	/* debounce */
3762306a36Sopenharmony_ci			mod_timer(&psw->debounce, jiffies + 50);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		ret = 1;
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciout:
4362306a36Sopenharmony_ci	/* Clear the switch IRQs */
4462306a36Sopenharmony_ci	l |= (0x7 << 12);
4562306a36Sopenharmony_ci	__raw_writew(l, PA_DBSW);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	return IRQ_RETVAL(ret);
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic struct resource psw_resources[] = {
5162306a36Sopenharmony_ci	[0] = {
5262306a36Sopenharmony_ci		.start	= IRQ_PSW,
5362306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
5462306a36Sopenharmony_ci	},
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic struct push_switch_platform_info s2_platform_data = {
5862306a36Sopenharmony_ci	.name		= "s2",
5962306a36Sopenharmony_ci	.bit		= 6,
6062306a36Sopenharmony_ci	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
6162306a36Sopenharmony_ci			  IRQF_SHARED,
6262306a36Sopenharmony_ci	.irq_handler	= psw_irq_handler,
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic struct platform_device s2_switch_device = {
6662306a36Sopenharmony_ci	.name		= "push-switch",
6762306a36Sopenharmony_ci	.id		= 0,
6862306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(psw_resources),
6962306a36Sopenharmony_ci	.resource	= psw_resources,
7062306a36Sopenharmony_ci	.dev		= {
7162306a36Sopenharmony_ci		.platform_data = &s2_platform_data,
7262306a36Sopenharmony_ci	},
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic struct push_switch_platform_info s3_platform_data = {
7662306a36Sopenharmony_ci	.name		= "s3",
7762306a36Sopenharmony_ci	.bit		= 5,
7862306a36Sopenharmony_ci	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
7962306a36Sopenharmony_ci			  IRQF_SHARED,
8062306a36Sopenharmony_ci	.irq_handler	= psw_irq_handler,
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic struct platform_device s3_switch_device = {
8462306a36Sopenharmony_ci	.name		= "push-switch",
8562306a36Sopenharmony_ci	.id		= 1,
8662306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(psw_resources),
8762306a36Sopenharmony_ci	.resource	= psw_resources,
8862306a36Sopenharmony_ci	.dev		= {
8962306a36Sopenharmony_ci		.platform_data = &s3_platform_data,
9062306a36Sopenharmony_ci	},
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic struct push_switch_platform_info s4_platform_data = {
9462306a36Sopenharmony_ci	.name		= "s4",
9562306a36Sopenharmony_ci	.bit		= 4,
9662306a36Sopenharmony_ci	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
9762306a36Sopenharmony_ci			  IRQF_SHARED,
9862306a36Sopenharmony_ci	.irq_handler	= psw_irq_handler,
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic struct platform_device s4_switch_device = {
10262306a36Sopenharmony_ci	.name		= "push-switch",
10362306a36Sopenharmony_ci	.id		= 2,
10462306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(psw_resources),
10562306a36Sopenharmony_ci	.resource	= psw_resources,
10662306a36Sopenharmony_ci	.dev		= {
10762306a36Sopenharmony_ci		.platform_data = &s4_platform_data,
10862306a36Sopenharmony_ci	},
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic struct platform_device *psw_devices[] = {
11262306a36Sopenharmony_ci	&s2_switch_device, &s3_switch_device, &s4_switch_device,
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic int __init psw_init(void)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_cimodule_init(psw_init);
120