Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2022 Richtek Technology Corp. * Author: ChiYuan Huang <cy_huang@richtek.com> */ #include <linux/bits.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/regmap.h> #define RT5120_REG_INTSTAT 0x1E #define RT5120_PWRKEYSTAT_MASK BIT(7) struct rt5120_priv { struct regmap *regmap; struct input_dev *input; }; static irqreturn_t rt5120_pwrkey_handler(int irq, void *devid) { struct rt5120_priv *priv = devid; unsigned int stat; int error; error = regmap_read(priv->regmap, RT5120_REG_INTSTAT, &stat); if (error) return IRQ_NONE; input_report_key(priv->input, KEY_POWER, !(stat & RT5120_PWRKEYSTAT_MASK)); input_sync(priv->input); return IRQ_HANDLED; } static int rt5120_pwrkey_probe(struct platform_device *pdev) { struct rt5120_priv *priv; struct device *dev = &pdev->dev; int press_irq, release_irq; int error; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->regmap = dev_get_regmap(dev->parent, NULL); if (!priv->regmap) { dev_err(dev, "Failed to init regmap\n"); return -ENODEV; } press_irq = platform_get_irq_byname(pdev, "pwrkey-press"); if (press_irq < 0) return press_irq; release_irq = platform_get_irq_byname(pdev, "pwrkey-release"); if (release_irq < 0) return release_irq; /* Make input device be device resource managed */ priv->input = devm_input_allocate_device(dev); if (!priv->input) return -ENOMEM; priv->input->name = "rt5120_pwrkey"; priv->input->phys = "rt5120_pwrkey/input0"; priv->input->id.bustype = BUS_I2C; input_set_capability(priv->input, EV_KEY, KEY_POWER); error = input_register_device(priv->input); if (error) { dev_err(dev, "Failed to register input device: %d\n", error); return error; } error = devm_request_threaded_irq(dev, press_irq, NULL, rt5120_pwrkey_handler, 0, "pwrkey-press", priv); if (error) { dev_err(dev, "Failed to register pwrkey press irq: %d\n", error); return error; } error = devm_request_threaded_irq(dev, release_irq, NULL, rt5120_pwrkey_handler, 0, "pwrkey-release", priv); if (error) { dev_err(dev, "Failed to register pwrkey release irq: %d\n", error); return error; } return 0; } static const struct of_device_id r5120_pwrkey_match_table[] = { { .compatible = "richtek,rt5120-pwrkey" }, {} }; MODULE_DEVICE_TABLE(of, r5120_pwrkey_match_table); static struct platform_driver rt5120_pwrkey_driver = { .driver = { .name = "rt5120-pwrkey", .of_match_table = r5120_pwrkey_match_table, }, .probe = rt5120_pwrkey_probe, }; module_platform_driver(rt5120_pwrkey_driver); MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); MODULE_DESCRIPTION("Richtek RT5120 power key driver"); MODULE_LICENSE("GPL"); |