1/* 2 * Power key driver for SiRF PrimaII 3 * 4 * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group 5 * company. 6 * 7 * Licensed under GPLv2 or later. 8 */ 9 10#include <linux/module.h> 11#include <linux/interrupt.h> 12#include <linux/delay.h> 13#include <linux/platform_device.h> 14#include <linux/input.h> 15#include <linux/rtc/sirfsoc_rtciobrg.h> 16#include <linux/of.h> 17#include <linux/workqueue.h> 18 19struct sirfsoc_pwrc_drvdata { 20 u32 pwrc_base; 21 struct input_dev *input; 22 struct delayed_work work; 23}; 24 25#define PWRC_ON_KEY_BIT (1 << 0) 26 27#define PWRC_INT_STATUS 0xc 28#define PWRC_INT_MASK 0x10 29#define PWRC_PIN_STATUS 0x14 30#define PWRC_KEY_DETECT_UP_TIME 20 /* ms*/ 31 32static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv) 33{ 34 u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + 35 PWRC_PIN_STATUS); 36 return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */ 37} 38 39static void sirfsoc_pwrc_report_event(struct work_struct *work) 40{ 41 struct sirfsoc_pwrc_drvdata *pwrcdrv = 42 container_of(work, struct sirfsoc_pwrc_drvdata, work.work); 43 44 if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) { 45 schedule_delayed_work(&pwrcdrv->work, 46 msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); 47 } else { 48 input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0); 49 input_sync(pwrcdrv->input); 50 } 51} 52 53static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) 54{ 55 struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_id; 56 u32 int_status; 57 58 int_status = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + 59 PWRC_INT_STATUS); 60 sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, 61 pwrcdrv->pwrc_base + PWRC_INT_STATUS); 62 63 input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1); 64 input_sync(pwrcdrv->input); 65 schedule_delayed_work(&pwrcdrv->work, 66 msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); 67 68 return IRQ_HANDLED; 69} 70 71static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv, 72 bool enable) 73{ 74 u32 int_mask; 75 76 int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK); 77 if (enable) 78 int_mask |= PWRC_ON_KEY_BIT; 79 else 80 int_mask &= ~PWRC_ON_KEY_BIT; 81 sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK); 82} 83 84static int sirfsoc_pwrc_open(struct input_dev *input) 85{ 86 struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); 87 88 sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); 89 90 return 0; 91} 92 93static void sirfsoc_pwrc_close(struct input_dev *input) 94{ 95 struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); 96 97 sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); 98 cancel_delayed_work_sync(&pwrcdrv->work); 99} 100 101static const struct of_device_id sirfsoc_pwrc_of_match[] = { 102 { .compatible = "sirf,prima2-pwrc" }, 103 {}, 104} 105MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match); 106 107static int sirfsoc_pwrc_probe(struct platform_device *pdev) 108{ 109 struct device_node *np = pdev->dev.of_node; 110 struct sirfsoc_pwrc_drvdata *pwrcdrv; 111 int irq; 112 int error; 113 114 pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(struct sirfsoc_pwrc_drvdata), 115 GFP_KERNEL); 116 if (!pwrcdrv) { 117 dev_info(&pdev->dev, "Not enough memory for the device data\n"); 118 return -ENOMEM; 119 } 120 121 /* 122 * We can't use of_iomap because pwrc is not mapped in memory, 123 * the so-called base address is only offset in rtciobrg 124 */ 125 error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); 126 if (error) { 127 dev_err(&pdev->dev, 128 "unable to find base address of pwrc node in dtb\n"); 129 return error; 130 } 131 132 pwrcdrv->input = devm_input_allocate_device(&pdev->dev); 133 if (!pwrcdrv->input) 134 return -ENOMEM; 135 136 pwrcdrv->input->name = "sirfsoc pwrckey"; 137 pwrcdrv->input->phys = "pwrc/input0"; 138 pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY); 139 input_set_capability(pwrcdrv->input, EV_KEY, KEY_POWER); 140 141 INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event); 142 143 pwrcdrv->input->open = sirfsoc_pwrc_open; 144 pwrcdrv->input->close = sirfsoc_pwrc_close; 145 146 input_set_drvdata(pwrcdrv->input, pwrcdrv); 147 148 /* Make sure the device is quiesced */ 149 sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); 150 151 irq = platform_get_irq(pdev, 0); 152 error = devm_request_irq(&pdev->dev, irq, 153 sirfsoc_pwrc_isr, 0, 154 "sirfsoc_pwrc_int", pwrcdrv); 155 if (error) { 156 dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", 157 irq, error); 158 return error; 159 } 160 161 error = input_register_device(pwrcdrv->input); 162 if (error) { 163 dev_err(&pdev->dev, 164 "unable to register input device, error: %d\n", 165 error); 166 return error; 167 } 168 169 dev_set_drvdata(&pdev->dev, pwrcdrv); 170 device_init_wakeup(&pdev->dev, 1); 171 172 return 0; 173} 174 175static int sirfsoc_pwrc_remove(struct platform_device *pdev) 176{ 177 device_init_wakeup(&pdev->dev, 0); 178 179 return 0; 180} 181 182static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev) 183{ 184 struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev); 185 struct input_dev *input = pwrcdrv->input; 186 187 /* 188 * Do not mask pwrc interrupt as we want pwrc work as a wakeup source 189 * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c 190 */ 191 mutex_lock(&input->mutex); 192 if (input->users) 193 sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); 194 mutex_unlock(&input->mutex); 195 196 return 0; 197} 198 199static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume); 200 201static struct platform_driver sirfsoc_pwrc_driver = { 202 .probe = sirfsoc_pwrc_probe, 203 .remove = sirfsoc_pwrc_remove, 204 .driver = { 205 .name = "sirfsoc-pwrc", 206 .pm = &sirfsoc_pwrc_pm_ops, 207 .of_match_table = sirfsoc_pwrc_of_match, 208 } 209}; 210 211module_platform_driver(sirfsoc_pwrc_driver); 212 213MODULE_LICENSE("GPL v2"); 214MODULE_AUTHOR("Binghua Duan <Binghua.Duan@csr.com>, Xianglong Du <Xianglong.Du@csr.com>"); 215MODULE_DESCRIPTION("CSR Prima2 PWRC Driver"); 216MODULE_ALIAS("platform:sirfsoc-pwrc"); 217