1/* 2 * arch/sh/boards/renesas/r7780rp/psw.c 3 * 4 * push switch support for RDBRP-1/RDBREVRP-1 debug boards. 5 * 6 * Copyright (C) 2006 Paul Mundt 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12#include <linux/io.h> 13#include <linux/module.h> 14#include <linux/interrupt.h> 15#include <linux/platform_device.h> 16#include <mach/highlander.h> 17#include <asm/push-switch.h> 18 19static irqreturn_t psw_irq_handler(int irq, void *arg) 20{ 21 struct platform_device *pdev = arg; 22 struct push_switch *psw = platform_get_drvdata(pdev); 23 struct push_switch_platform_info *psw_info = pdev->dev.platform_data; 24 unsigned int l, mask; 25 int ret = 0; 26 27 l = __raw_readw(PA_DBSW); 28 29 /* Nothing to do if there's no state change */ 30 if (psw->state) { 31 ret = 1; 32 goto out; 33 } 34 35 mask = l & 0x70; 36 /* Figure out who raised it */ 37 if (mask & (1 << psw_info->bit)) { 38 psw->state = !!(mask & (1 << psw_info->bit)); 39 if (psw->state) /* debounce */ 40 mod_timer(&psw->debounce, jiffies + 50); 41 42 ret = 1; 43 } 44 45out: 46 /* Clear the switch IRQs */ 47 l |= (0x7 << 12); 48 __raw_writew(l, PA_DBSW); 49 50 return IRQ_RETVAL(ret); 51} 52 53static struct resource psw_resources[] = { 54 [0] = { 55 .start = IRQ_PSW, 56 .flags = IORESOURCE_IRQ, 57 }, 58}; 59 60static struct push_switch_platform_info s2_platform_data = { 61 .name = "s2", 62 .bit = 6, 63 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 64 IRQF_SHARED, 65 .irq_handler = psw_irq_handler, 66}; 67 68static struct platform_device s2_switch_device = { 69 .name = "push-switch", 70 .id = 0, 71 .num_resources = ARRAY_SIZE(psw_resources), 72 .resource = psw_resources, 73 .dev = { 74 .platform_data = &s2_platform_data, 75 }, 76}; 77 78static struct push_switch_platform_info s3_platform_data = { 79 .name = "s3", 80 .bit = 5, 81 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 82 IRQF_SHARED, 83 .irq_handler = psw_irq_handler, 84}; 85 86static struct platform_device s3_switch_device = { 87 .name = "push-switch", 88 .id = 1, 89 .num_resources = ARRAY_SIZE(psw_resources), 90 .resource = psw_resources, 91 .dev = { 92 .platform_data = &s3_platform_data, 93 }, 94}; 95 96static struct push_switch_platform_info s4_platform_data = { 97 .name = "s4", 98 .bit = 4, 99 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 100 IRQF_SHARED, 101 .irq_handler = psw_irq_handler, 102}; 103 104static struct platform_device s4_switch_device = { 105 .name = "push-switch", 106 .id = 2, 107 .num_resources = ARRAY_SIZE(psw_resources), 108 .resource = psw_resources, 109 .dev = { 110 .platform_data = &s4_platform_data, 111 }, 112}; 113 114static struct platform_device *psw_devices[] = { 115 &s2_switch_device, &s3_switch_device, &s4_switch_device, 116}; 117 118static int __init psw_init(void) 119{ 120 return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices)); 121} 122module_init(psw_init); 123