0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/acpi.h>
0017 #include <linux/errno.h>
0018 #include <linux/irq.h>
0019 #include <linux/init.h>
0020 #include <linux/input.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/kernel.h>
0023 #include <linux/mfd/axp20x.h>
0024 #include <linux/module.h>
0025 #include <linux/platform_data/x86/soc.h>
0026 #include <linux/platform_device.h>
0027 #include <linux/regmap.h>
0028 #include <linux/slab.h>
0029
0030 #define AXP20X_PEK_STARTUP_MASK (0xc0)
0031 #define AXP20X_PEK_SHUTDOWN_MASK (0x03)
0032
0033 struct axp20x_info {
0034 const struct axp20x_time *startup_time;
0035 unsigned int startup_mask;
0036 const struct axp20x_time *shutdown_time;
0037 unsigned int shutdown_mask;
0038 };
0039
0040 struct axp20x_pek {
0041 struct axp20x_dev *axp20x;
0042 struct input_dev *input;
0043 struct axp20x_info *info;
0044 int irq_dbr;
0045 int irq_dbf;
0046 };
0047
0048 struct axp20x_time {
0049 unsigned int time;
0050 unsigned int idx;
0051 };
0052
0053 static const struct axp20x_time startup_time[] = {
0054 { .time = 128, .idx = 0 },
0055 { .time = 1000, .idx = 2 },
0056 { .time = 3000, .idx = 1 },
0057 { .time = 2000, .idx = 3 },
0058 };
0059
0060 static const struct axp20x_time axp221_startup_time[] = {
0061 { .time = 128, .idx = 0 },
0062 { .time = 1000, .idx = 1 },
0063 { .time = 2000, .idx = 2 },
0064 { .time = 3000, .idx = 3 },
0065 };
0066
0067 static const struct axp20x_time shutdown_time[] = {
0068 { .time = 4000, .idx = 0 },
0069 { .time = 6000, .idx = 1 },
0070 { .time = 8000, .idx = 2 },
0071 { .time = 10000, .idx = 3 },
0072 };
0073
0074 static const struct axp20x_info axp20x_info = {
0075 .startup_time = startup_time,
0076 .startup_mask = AXP20X_PEK_STARTUP_MASK,
0077 .shutdown_time = shutdown_time,
0078 .shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK,
0079 };
0080
0081 static const struct axp20x_info axp221_info = {
0082 .startup_time = axp221_startup_time,
0083 .startup_mask = AXP20X_PEK_STARTUP_MASK,
0084 .shutdown_time = shutdown_time,
0085 .shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK,
0086 };
0087
0088 static ssize_t axp20x_show_attr(struct device *dev,
0089 const struct axp20x_time *time,
0090 unsigned int mask, char *buf)
0091 {
0092 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0093 unsigned int val;
0094 int ret, i;
0095
0096 ret = regmap_read(axp20x_pek->axp20x->regmap, AXP20X_PEK_KEY, &val);
0097 if (ret != 0)
0098 return ret;
0099
0100 val &= mask;
0101 val >>= ffs(mask) - 1;
0102
0103 for (i = 0; i < 4; i++)
0104 if (val == time[i].idx)
0105 val = time[i].time;
0106
0107 return sprintf(buf, "%u\n", val);
0108 }
0109
0110 static ssize_t axp20x_show_attr_startup(struct device *dev,
0111 struct device_attribute *attr,
0112 char *buf)
0113 {
0114 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0115
0116 return axp20x_show_attr(dev, axp20x_pek->info->startup_time,
0117 axp20x_pek->info->startup_mask, buf);
0118 }
0119
0120 static ssize_t axp20x_show_attr_shutdown(struct device *dev,
0121 struct device_attribute *attr,
0122 char *buf)
0123 {
0124 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0125
0126 return axp20x_show_attr(dev, axp20x_pek->info->shutdown_time,
0127 axp20x_pek->info->shutdown_mask, buf);
0128 }
0129
0130 static ssize_t axp20x_store_attr(struct device *dev,
0131 const struct axp20x_time *time,
0132 unsigned int mask, const char *buf,
0133 size_t count)
0134 {
0135 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0136 char val_str[20];
0137 size_t len;
0138 int ret, i;
0139 unsigned int val, idx = 0;
0140 unsigned int best_err = UINT_MAX;
0141
0142 val_str[sizeof(val_str) - 1] = '\0';
0143 strncpy(val_str, buf, sizeof(val_str) - 1);
0144 len = strlen(val_str);
0145
0146 if (len && val_str[len - 1] == '\n')
0147 val_str[len - 1] = '\0';
0148
0149 ret = kstrtouint(val_str, 10, &val);
0150 if (ret)
0151 return ret;
0152
0153 for (i = 3; i >= 0; i--) {
0154 unsigned int err;
0155
0156 err = abs(time[i].time - val);
0157 if (err < best_err) {
0158 best_err = err;
0159 idx = time[i].idx;
0160 }
0161
0162 if (!err)
0163 break;
0164 }
0165
0166 idx <<= ffs(mask) - 1;
0167 ret = regmap_update_bits(axp20x_pek->axp20x->regmap, AXP20X_PEK_KEY,
0168 mask, idx);
0169 if (ret != 0)
0170 return -EINVAL;
0171
0172 return count;
0173 }
0174
0175 static ssize_t axp20x_store_attr_startup(struct device *dev,
0176 struct device_attribute *attr,
0177 const char *buf, size_t count)
0178 {
0179 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0180
0181 return axp20x_store_attr(dev, axp20x_pek->info->startup_time,
0182 axp20x_pek->info->startup_mask, buf, count);
0183 }
0184
0185 static ssize_t axp20x_store_attr_shutdown(struct device *dev,
0186 struct device_attribute *attr,
0187 const char *buf, size_t count)
0188 {
0189 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0190
0191 return axp20x_store_attr(dev, axp20x_pek->info->shutdown_time,
0192 axp20x_pek->info->shutdown_mask, buf, count);
0193 }
0194
0195 static DEVICE_ATTR(startup, 0644, axp20x_show_attr_startup,
0196 axp20x_store_attr_startup);
0197 static DEVICE_ATTR(shutdown, 0644, axp20x_show_attr_shutdown,
0198 axp20x_store_attr_shutdown);
0199
0200 static struct attribute *axp20x_attrs[] = {
0201 &dev_attr_startup.attr,
0202 &dev_attr_shutdown.attr,
0203 NULL,
0204 };
0205 ATTRIBUTE_GROUPS(axp20x);
0206
0207 static irqreturn_t axp20x_pek_irq(int irq, void *pwr)
0208 {
0209 struct input_dev *idev = pwr;
0210 struct axp20x_pek *axp20x_pek = input_get_drvdata(idev);
0211
0212
0213
0214
0215
0216 if (irq == axp20x_pek->irq_dbf)
0217 input_report_key(idev, KEY_POWER, true);
0218 else if (irq == axp20x_pek->irq_dbr)
0219 input_report_key(idev, KEY_POWER, false);
0220
0221 input_sync(idev);
0222
0223 return IRQ_HANDLED;
0224 }
0225
0226 static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
0227 struct platform_device *pdev)
0228 {
0229 struct axp20x_dev *axp20x = axp20x_pek->axp20x;
0230 struct input_dev *idev;
0231 int error;
0232
0233 axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR");
0234 if (axp20x_pek->irq_dbr < 0)
0235 return axp20x_pek->irq_dbr;
0236 axp20x_pek->irq_dbr = regmap_irq_get_virq(axp20x->regmap_irqc,
0237 axp20x_pek->irq_dbr);
0238
0239 axp20x_pek->irq_dbf = platform_get_irq_byname(pdev, "PEK_DBF");
0240 if (axp20x_pek->irq_dbf < 0)
0241 return axp20x_pek->irq_dbf;
0242 axp20x_pek->irq_dbf = regmap_irq_get_virq(axp20x->regmap_irqc,
0243 axp20x_pek->irq_dbf);
0244
0245 axp20x_pek->input = devm_input_allocate_device(&pdev->dev);
0246 if (!axp20x_pek->input)
0247 return -ENOMEM;
0248
0249 idev = axp20x_pek->input;
0250
0251 idev->name = "axp20x-pek";
0252 idev->phys = "m1kbd/input2";
0253 idev->dev.parent = &pdev->dev;
0254
0255 input_set_capability(idev, EV_KEY, KEY_POWER);
0256
0257 input_set_drvdata(idev, axp20x_pek);
0258
0259 error = devm_request_any_context_irq(&pdev->dev, axp20x_pek->irq_dbr,
0260 axp20x_pek_irq, 0,
0261 "axp20x-pek-dbr", idev);
0262 if (error < 0) {
0263 dev_err(&pdev->dev, "Failed to request dbr IRQ#%d: %d\n",
0264 axp20x_pek->irq_dbr, error);
0265 return error;
0266 }
0267
0268 error = devm_request_any_context_irq(&pdev->dev, axp20x_pek->irq_dbf,
0269 axp20x_pek_irq, 0,
0270 "axp20x-pek-dbf", idev);
0271 if (error < 0) {
0272 dev_err(&pdev->dev, "Failed to request dbf IRQ#%d: %d\n",
0273 axp20x_pek->irq_dbf, error);
0274 return error;
0275 }
0276
0277 error = input_register_device(idev);
0278 if (error) {
0279 dev_err(&pdev->dev, "Can't register input device: %d\n",
0280 error);
0281 return error;
0282 }
0283
0284 device_init_wakeup(&pdev->dev, true);
0285
0286 return 0;
0287 }
0288
0289 static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek)
0290 {
0291 if (IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY) &&
0292 axp20x_pek->axp20x->variant == AXP288_ID) {
0293
0294
0295
0296
0297
0298
0299 if (soc_intel_is_cht() &&
0300 (acpi_dev_present("INTCFD9", NULL, -1) ||
0301 acpi_dev_present("ACPI0011", NULL, -1)))
0302 return false;
0303 }
0304
0305 return true;
0306 }
0307
0308 static int axp20x_pek_probe(struct platform_device *pdev)
0309 {
0310 struct axp20x_pek *axp20x_pek;
0311 const struct platform_device_id *match = platform_get_device_id(pdev);
0312 int error;
0313
0314 if (!match) {
0315 dev_err(&pdev->dev, "Failed to get platform_device_id\n");
0316 return -EINVAL;
0317 }
0318
0319 axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
0320 GFP_KERNEL);
0321 if (!axp20x_pek)
0322 return -ENOMEM;
0323
0324 axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);
0325
0326 if (axp20x_pek_should_register_input(axp20x_pek)) {
0327 error = axp20x_pek_probe_input_device(axp20x_pek, pdev);
0328 if (error)
0329 return error;
0330 }
0331
0332 axp20x_pek->info = (struct axp20x_info *)match->driver_data;
0333
0334 platform_set_drvdata(pdev, axp20x_pek);
0335
0336 return 0;
0337 }
0338
0339 static int __maybe_unused axp20x_pek_suspend(struct device *dev)
0340 {
0341 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0342
0343
0344
0345
0346
0347 if (device_may_wakeup(dev)) {
0348 enable_irq_wake(axp20x_pek->irq_dbf);
0349 enable_irq_wake(axp20x_pek->irq_dbr);
0350 } else {
0351 disable_irq(axp20x_pek->irq_dbf);
0352 disable_irq(axp20x_pek->irq_dbr);
0353 }
0354
0355 return 0;
0356 }
0357
0358 static int __maybe_unused axp20x_pek_resume(struct device *dev)
0359 {
0360 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0361
0362 if (device_may_wakeup(dev)) {
0363 disable_irq_wake(axp20x_pek->irq_dbf);
0364 disable_irq_wake(axp20x_pek->irq_dbr);
0365 } else {
0366 enable_irq(axp20x_pek->irq_dbf);
0367 enable_irq(axp20x_pek->irq_dbr);
0368 }
0369
0370 return 0;
0371 }
0372
0373 static int __maybe_unused axp20x_pek_resume_noirq(struct device *dev)
0374 {
0375 struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
0376
0377 if (axp20x_pek->axp20x->variant != AXP288_ID)
0378 return 0;
0379
0380
0381
0382
0383
0384 regmap_write(axp20x_pek->axp20x->regmap,
0385 AXP20X_IRQ1_STATE + AXP288_IRQ_POKN / 8,
0386 BIT(AXP288_IRQ_POKN % 8));
0387
0388 return 0;
0389 }
0390
0391 static const struct dev_pm_ops axp20x_pek_pm_ops = {
0392 SET_SYSTEM_SLEEP_PM_OPS(axp20x_pek_suspend, axp20x_pek_resume)
0393 #ifdef CONFIG_PM_SLEEP
0394 .resume_noirq = axp20x_pek_resume_noirq,
0395 #endif
0396 };
0397
0398 static const struct platform_device_id axp_pek_id_match[] = {
0399 {
0400 .name = "axp20x-pek",
0401 .driver_data = (kernel_ulong_t)&axp20x_info,
0402 },
0403 {
0404 .name = "axp221-pek",
0405 .driver_data = (kernel_ulong_t)&axp221_info,
0406 },
0407 { }
0408 };
0409 MODULE_DEVICE_TABLE(platform, axp_pek_id_match);
0410
0411 static struct platform_driver axp20x_pek_driver = {
0412 .probe = axp20x_pek_probe,
0413 .id_table = axp_pek_id_match,
0414 .driver = {
0415 .name = "axp20x-pek",
0416 .pm = &axp20x_pek_pm_ops,
0417 .dev_groups = axp20x_groups,
0418 },
0419 };
0420 module_platform_driver(axp20x_pek_driver);
0421
0422 MODULE_DESCRIPTION("axp20x Power Button");
0423 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
0424 MODULE_LICENSE("GPL");