Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Texas Instruments' TPS65217 and TPS65218 Power Button Input Driver
0004  *
0005  * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
0006  * Author: Felipe Balbi <balbi@ti.com>
0007  * Author: Marcin Niestroj <m.niestroj@grinn-global.com>
0008  */
0009 
0010 #include <linux/init.h>
0011 #include <linux/input.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mfd/tps65217.h>
0015 #include <linux/mfd/tps65218.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/regmap.h>
0020 #include <linux/slab.h>
0021 
0022 struct tps6521x_data {
0023     unsigned int reg_status;
0024     unsigned int pb_mask;
0025     const char *name;
0026 };
0027 
0028 static const struct tps6521x_data tps65217_data = {
0029     .reg_status = TPS65217_REG_STATUS,
0030     .pb_mask = TPS65217_STATUS_PB,
0031     .name = "tps65217_pwrbutton",
0032 };
0033 
0034 static const struct tps6521x_data tps65218_data = {
0035     .reg_status = TPS65218_REG_STATUS,
0036     .pb_mask = TPS65218_STATUS_PB_STATE,
0037     .name = "tps65218_pwrbutton",
0038 };
0039 
0040 struct tps6521x_pwrbutton {
0041     struct device *dev;
0042     struct regmap *regmap;
0043     struct input_dev *idev;
0044     const struct tps6521x_data *data;
0045     char phys[32];
0046 };
0047 
0048 static const struct of_device_id of_tps6521x_pb_match[] = {
0049     { .compatible = "ti,tps65217-pwrbutton", .data = &tps65217_data },
0050     { .compatible = "ti,tps65218-pwrbutton", .data = &tps65218_data },
0051     { },
0052 };
0053 MODULE_DEVICE_TABLE(of, of_tps6521x_pb_match);
0054 
0055 static irqreturn_t tps6521x_pb_irq(int irq, void *_pwr)
0056 {
0057     struct tps6521x_pwrbutton *pwr = _pwr;
0058     const struct tps6521x_data *tps_data = pwr->data;
0059     unsigned int reg;
0060     int error;
0061 
0062     error = regmap_read(pwr->regmap, tps_data->reg_status, &reg);
0063     if (error) {
0064         dev_err(pwr->dev, "can't read register: %d\n", error);
0065         goto out;
0066     }
0067 
0068     if (reg & tps_data->pb_mask) {
0069         input_report_key(pwr->idev, KEY_POWER, 1);
0070         pm_wakeup_event(pwr->dev, 0);
0071     } else {
0072         input_report_key(pwr->idev, KEY_POWER, 0);
0073     }
0074 
0075     input_sync(pwr->idev);
0076 
0077 out:
0078     return IRQ_HANDLED;
0079 }
0080 
0081 static int tps6521x_pb_probe(struct platform_device *pdev)
0082 {
0083     struct device *dev = &pdev->dev;
0084     struct tps6521x_pwrbutton *pwr;
0085     struct input_dev *idev;
0086     const struct of_device_id *match;
0087     int error;
0088     int irq;
0089 
0090     match = of_match_node(of_tps6521x_pb_match, dev->of_node);
0091     if (!match)
0092         return -ENXIO;
0093 
0094     pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL);
0095     if (!pwr)
0096         return -ENOMEM;
0097 
0098     pwr->data = match->data;
0099 
0100     idev = devm_input_allocate_device(dev);
0101     if (!idev)
0102         return -ENOMEM;
0103 
0104     idev->name = pwr->data->name;
0105     snprintf(pwr->phys, sizeof(pwr->phys), "%s/input0",
0106         pwr->data->name);
0107     idev->phys = pwr->phys;
0108     idev->dev.parent = dev;
0109     idev->id.bustype = BUS_I2C;
0110 
0111     input_set_capability(idev, EV_KEY, KEY_POWER);
0112 
0113     pwr->regmap = dev_get_regmap(dev->parent, NULL);
0114     pwr->dev = dev;
0115     pwr->idev = idev;
0116     device_init_wakeup(dev, true);
0117 
0118     irq = platform_get_irq(pdev, 0);
0119     if (irq < 0)
0120         return -EINVAL;
0121 
0122     error = devm_request_threaded_irq(dev, irq, NULL, tps6521x_pb_irq,
0123                       IRQF_TRIGGER_RISING |
0124                         IRQF_TRIGGER_FALLING |
0125                         IRQF_ONESHOT,
0126                       pwr->data->name, pwr);
0127     if (error) {
0128         dev_err(dev, "failed to request IRQ #%d: %d\n", irq, error);
0129         return error;
0130     }
0131 
0132     error= input_register_device(idev);
0133     if (error) {
0134         dev_err(dev, "Can't register power button: %d\n", error);
0135         return error;
0136     }
0137 
0138     return 0;
0139 }
0140 
0141 static const struct platform_device_id tps6521x_pwrbtn_id_table[] = {
0142     { "tps65218-pwrbutton", },
0143     { "tps65217-pwrbutton", },
0144     { /* sentinel */ }
0145 };
0146 MODULE_DEVICE_TABLE(platform, tps6521x_pwrbtn_id_table);
0147 
0148 static struct platform_driver tps6521x_pb_driver = {
0149     .probe  = tps6521x_pb_probe,
0150     .driver = {
0151         .name   = "tps6521x_pwrbutton",
0152         .of_match_table = of_tps6521x_pb_match,
0153     },
0154     .id_table = tps6521x_pwrbtn_id_table,
0155 };
0156 module_platform_driver(tps6521x_pb_driver);
0157 
0158 MODULE_DESCRIPTION("TPS6521X Power Button");
0159 MODULE_LICENSE("GPL v2");
0160 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");