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