0001
0002
0003
0004
0005
0006
0007
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, ®);
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 { }
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>");