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