0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/kernel.h>
0022 #include <linux/module.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/i2c.h>
0025 #include <linux/input.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/mfd/max8925.h>
0028 #include <linux/slab.h>
0029 #include <linux/device.h>
0030
0031 #define SW_INPUT (1 << 7)
0032 #define HARDRESET_EN (1 << 7)
0033 #define PWREN_EN (1 << 7)
0034
0035 struct max8925_onkey_info {
0036 struct input_dev *idev;
0037 struct i2c_client *i2c;
0038 struct device *dev;
0039 unsigned int irq[2];
0040 };
0041
0042
0043
0044
0045
0046
0047 static irqreturn_t max8925_onkey_handler(int irq, void *data)
0048 {
0049 struct max8925_onkey_info *info = data;
0050 int state;
0051
0052 state = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS);
0053
0054 input_report_key(info->idev, KEY_POWER, state & SW_INPUT);
0055 input_sync(info->idev);
0056
0057 dev_dbg(info->dev, "onkey state:%d\n", state);
0058
0059
0060 max8925_set_bits(info->i2c, MAX8925_SYSENSEL,
0061 HARDRESET_EN, HARDRESET_EN);
0062
0063 return IRQ_HANDLED;
0064 }
0065
0066 static int max8925_onkey_probe(struct platform_device *pdev)
0067 {
0068 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
0069 struct max8925_onkey_info *info;
0070 struct input_dev *input;
0071 int irq[2], error;
0072
0073 irq[0] = platform_get_irq(pdev, 0);
0074 if (irq[0] < 0)
0075 return -EINVAL;
0076
0077 irq[1] = platform_get_irq(pdev, 1);
0078 if (irq[1] < 0)
0079 return -EINVAL;
0080
0081 info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_onkey_info),
0082 GFP_KERNEL);
0083 if (!info)
0084 return -ENOMEM;
0085
0086 input = devm_input_allocate_device(&pdev->dev);
0087 if (!input)
0088 return -ENOMEM;
0089
0090 info->idev = input;
0091 info->i2c = chip->i2c;
0092 info->dev = &pdev->dev;
0093 info->irq[0] = irq[0];
0094 info->irq[1] = irq[1];
0095
0096 input->name = "max8925_on";
0097 input->phys = "max8925_on/input0";
0098 input->id.bustype = BUS_I2C;
0099 input->dev.parent = &pdev->dev;
0100 input_set_capability(input, EV_KEY, KEY_POWER);
0101
0102 error = devm_request_threaded_irq(&pdev->dev, irq[0], NULL,
0103 max8925_onkey_handler, IRQF_ONESHOT,
0104 "onkey-down", info);
0105 if (error < 0) {
0106 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
0107 irq[0], error);
0108 return error;
0109 }
0110
0111 error = devm_request_threaded_irq(&pdev->dev, irq[1], NULL,
0112 max8925_onkey_handler, IRQF_ONESHOT,
0113 "onkey-up", info);
0114 if (error < 0) {
0115 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
0116 irq[1], error);
0117 return error;
0118 }
0119
0120 error = input_register_device(info->idev);
0121 if (error) {
0122 dev_err(chip->dev, "Can't register input device: %d\n", error);
0123 return error;
0124 }
0125
0126 platform_set_drvdata(pdev, info);
0127 device_init_wakeup(&pdev->dev, 1);
0128
0129 return 0;
0130 }
0131
0132 static int __maybe_unused max8925_onkey_suspend(struct device *dev)
0133 {
0134 struct platform_device *pdev = to_platform_device(dev);
0135 struct max8925_onkey_info *info = platform_get_drvdata(pdev);
0136 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
0137
0138 if (device_may_wakeup(dev)) {
0139 chip->wakeup_flag |= 1 << info->irq[0];
0140 chip->wakeup_flag |= 1 << info->irq[1];
0141 }
0142
0143 return 0;
0144 }
0145
0146 static int __maybe_unused max8925_onkey_resume(struct device *dev)
0147 {
0148 struct platform_device *pdev = to_platform_device(dev);
0149 struct max8925_onkey_info *info = platform_get_drvdata(pdev);
0150 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
0151
0152 if (device_may_wakeup(dev)) {
0153 chip->wakeup_flag &= ~(1 << info->irq[0]);
0154 chip->wakeup_flag &= ~(1 << info->irq[1]);
0155 }
0156
0157 return 0;
0158 }
0159
0160 static SIMPLE_DEV_PM_OPS(max8925_onkey_pm_ops, max8925_onkey_suspend, max8925_onkey_resume);
0161
0162 static struct platform_driver max8925_onkey_driver = {
0163 .driver = {
0164 .name = "max8925-onkey",
0165 .pm = &max8925_onkey_pm_ops,
0166 },
0167 .probe = max8925_onkey_probe,
0168 };
0169 module_platform_driver(max8925_onkey_driver);
0170
0171 MODULE_DESCRIPTION("Maxim MAX8925 ONKEY driver");
0172 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
0173 MODULE_LICENSE("GPL");