summaryrefslogtreecommitdiffstats
path: root/kernel/arch/sh/boards/mach-highlander/psw.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/arch/sh/boards/mach-highlander/psw.c')
-rw-r--r--kernel/arch/sh/boards/mach-highlander/psw.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/kernel/arch/sh/boards/mach-highlander/psw.c b/kernel/arch/sh/boards/mach-highlander/psw.c
new file mode 100644
index 000000000..522786318
--- /dev/null
+++ b/kernel/arch/sh/boards/mach-highlander/psw.c
@@ -0,0 +1,122 @@
+/*
+ * arch/sh/boards/renesas/r7780rp/psw.c
+ *
+ * push switch support for RDBRP-1/RDBREVRP-1 debug boards.
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <mach/highlander.h>
+#include <asm/push-switch.h>
+
+static irqreturn_t psw_irq_handler(int irq, void *arg)
+{
+ struct platform_device *pdev = arg;
+ struct push_switch *psw = platform_get_drvdata(pdev);
+ struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
+ unsigned int l, mask;
+ int ret = 0;
+
+ l = __raw_readw(PA_DBSW);
+
+ /* Nothing to do if there's no state change */
+ if (psw->state) {
+ ret = 1;
+ goto out;
+ }
+
+ mask = l & 0x70;
+ /* Figure out who raised it */
+ if (mask & (1 << psw_info->bit)) {
+ psw->state = !!(mask & (1 << psw_info->bit));
+ if (psw->state) /* debounce */
+ mod_timer(&psw->debounce, jiffies + 50);
+
+ ret = 1;
+ }
+
+out:
+ /* Clear the switch IRQs */
+ l |= (0x7 << 12);
+ __raw_writew(l, PA_DBSW);
+
+ return IRQ_RETVAL(ret);
+}
+
+static struct resource psw_resources[] = {
+ [0] = {
+ .start = IRQ_PSW,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct push_switch_platform_info s2_platform_data = {
+ .name = "s2",
+ .bit = 6,
+ .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_SHARED,
+ .irq_handler = psw_irq_handler,
+};
+
+static struct platform_device s2_switch_device = {
+ .name = "push-switch",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(psw_resources),
+ .resource = psw_resources,
+ .dev = {
+ .platform_data = &s2_platform_data,
+ },
+};
+
+static struct push_switch_platform_info s3_platform_data = {
+ .name = "s3",
+ .bit = 5,
+ .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_SHARED,
+ .irq_handler = psw_irq_handler,
+};
+
+static struct platform_device s3_switch_device = {
+ .name = "push-switch",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(psw_resources),
+ .resource = psw_resources,
+ .dev = {
+ .platform_data = &s3_platform_data,
+ },
+};
+
+static struct push_switch_platform_info s4_platform_data = {
+ .name = "s4",
+ .bit = 4,
+ .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_SHARED,
+ .irq_handler = psw_irq_handler,
+};
+
+static struct platform_device s4_switch_device = {
+ .name = "push-switch",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(psw_resources),
+ .resource = psw_resources,
+ .dev = {
+ .platform_data = &s4_platform_data,
+ },
+};
+
+static struct platform_device *psw_devices[] = {
+ &s2_switch_device, &s3_switch_device, &s4_switch_device,
+};
+
+static int __init psw_init(void)
+{
+ return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
+}
+module_init(psw_init);