1/* 2 * arch/sh/boards/landisk/psw.c 3 * 4 * push switch support for LANDISK and USL-5P 5 * 6 * Copyright (C) 2006-2007 Paul Mundt 7 * Copyright (C) 2007 kogiidena 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 */ 13#include <linux/io.h> 14#include <linux/init.h> 15#include <linux/interrupt.h> 16#include <linux/platform_device.h> 17#include <mach-landisk/mach/iodata_landisk.h> 18#include <asm/push-switch.h> 19 20static irqreturn_t psw_irq_handler(int irq, void *arg) 21{ 22 struct platform_device *pdev = arg; 23 struct push_switch *psw = platform_get_drvdata(pdev); 24 struct push_switch_platform_info *psw_info = pdev->dev.platform_data; 25 unsigned int sw_value; 26 int ret = 0; 27 28 sw_value = (0x0ff & (~__raw_readb(PA_STATUS))); 29 30 /* Nothing to do if there's no state change */ 31 if (psw->state) { 32 ret = 1; 33 goto out; 34 } 35 36 /* Figure out who raised it */ 37 if (sw_value & (1 << psw_info->bit)) { 38 psw->state = 1; 39 mod_timer(&psw->debounce, jiffies + 50); 40 ret = 1; 41 } 42 43out: 44 /* Clear the switch IRQs */ 45 __raw_writeb(0x00, PA_PWRINT_CLR); 46 47 return IRQ_RETVAL(ret); 48} 49 50static struct resource psw_power_resources[] = { 51 [0] = { 52 .start = IRQ_POWER, 53 .flags = IORESOURCE_IRQ, 54 }, 55}; 56 57static struct resource psw_usl5p_resources[] = { 58 [0] = { 59 .start = IRQ_BUTTON, 60 .flags = IORESOURCE_IRQ, 61 }, 62}; 63 64static struct push_switch_platform_info psw_power_platform_data = { 65 .name = "psw_power", 66 .bit = 4, 67 .irq_flags = IRQF_SHARED, 68 .irq_handler = psw_irq_handler, 69}; 70 71static struct push_switch_platform_info psw1_platform_data = { 72 .name = "psw1", 73 .bit = 0, 74 .irq_flags = IRQF_SHARED, 75 .irq_handler = psw_irq_handler, 76}; 77 78static struct push_switch_platform_info psw2_platform_data = { 79 .name = "psw2", 80 .bit = 2, 81 .irq_flags = IRQF_SHARED, 82 .irq_handler = psw_irq_handler, 83}; 84 85static struct push_switch_platform_info psw3_platform_data = { 86 .name = "psw3", 87 .bit = 1, 88 .irq_flags = IRQF_SHARED, 89 .irq_handler = psw_irq_handler, 90}; 91 92static struct platform_device psw_power_switch_device = { 93 .name = "push-switch", 94 .id = 0, 95 .num_resources = ARRAY_SIZE(psw_power_resources), 96 .resource = psw_power_resources, 97 .dev = { 98 .platform_data = &psw_power_platform_data, 99 }, 100}; 101 102static struct platform_device psw1_switch_device = { 103 .name = "push-switch", 104 .id = 1, 105 .num_resources = ARRAY_SIZE(psw_usl5p_resources), 106 .resource = psw_usl5p_resources, 107 .dev = { 108 .platform_data = &psw1_platform_data, 109 }, 110}; 111 112static struct platform_device psw2_switch_device = { 113 .name = "push-switch", 114 .id = 2, 115 .num_resources = ARRAY_SIZE(psw_usl5p_resources), 116 .resource = psw_usl5p_resources, 117 .dev = { 118 .platform_data = &psw2_platform_data, 119 }, 120}; 121 122static struct platform_device psw3_switch_device = { 123 .name = "push-switch", 124 .id = 3, 125 .num_resources = ARRAY_SIZE(psw_usl5p_resources), 126 .resource = psw_usl5p_resources, 127 .dev = { 128 .platform_data = &psw3_platform_data, 129 }, 130}; 131 132static struct platform_device *psw_devices[] = { 133 &psw_power_switch_device, 134 &psw1_switch_device, 135 &psw2_switch_device, 136 &psw3_switch_device, 137}; 138 139static int __init psw_init(void) 140{ 141 return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices)); 142} 143module_init(psw_init); 144