pf1550-onkey.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for the PF1550 ONKEY
  4. * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
  5. *
  6. * Portions Copyright (c) 2025 Savoir-faire Linux Inc.
  7. * Samuel Kayode <samuel.kayode@savoirfairelinux.com>
  8. */
  9. #include <linux/err.h>
  10. #include <linux/input.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/mfd/pf1550.h>
  15. #include <linux/platform_device.h>
  16. #define PF1550_ONKEY_IRQ_NR 6
  17. struct onkey_drv_data {
  18. struct device *dev;
  19. const struct pf1550_ddata *pf1550;
  20. bool wakeup;
  21. struct input_dev *input;
  22. };
  23. static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
  24. {
  25. struct onkey_drv_data *onkey = data;
  26. struct platform_device *pdev = to_platform_device(onkey->dev);
  27. int i, state, irq_type = -1;
  28. for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++)
  29. if (irq == platform_get_irq(pdev, i))
  30. irq_type = i;
  31. switch (irq_type) {
  32. case PF1550_ONKEY_IRQ_PUSHI:
  33. state = 0;
  34. break;
  35. case PF1550_ONKEY_IRQ_1SI:
  36. case PF1550_ONKEY_IRQ_2SI:
  37. case PF1550_ONKEY_IRQ_3SI:
  38. case PF1550_ONKEY_IRQ_4SI:
  39. case PF1550_ONKEY_IRQ_8SI:
  40. state = 1;
  41. break;
  42. default:
  43. dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
  44. irq_type);
  45. return IRQ_HANDLED;
  46. }
  47. input_event(onkey->input, EV_KEY, KEY_POWER, state);
  48. input_sync(onkey->input);
  49. return IRQ_HANDLED;
  50. }
  51. static int pf1550_onkey_probe(struct platform_device *pdev)
  52. {
  53. struct onkey_drv_data *onkey;
  54. struct input_dev *input;
  55. bool key_power = false;
  56. int i, irq, error;
  57. onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
  58. if (!onkey)
  59. return -ENOMEM;
  60. onkey->dev = &pdev->dev;
  61. onkey->pf1550 = dev_get_drvdata(pdev->dev.parent);
  62. if (!onkey->pf1550->regmap)
  63. return dev_err_probe(&pdev->dev, -ENODEV,
  64. "failed to get regmap\n");
  65. onkey->wakeup = device_property_read_bool(pdev->dev.parent,
  66. "wakeup-source");
  67. if (device_property_read_bool(pdev->dev.parent,
  68. "nxp,disable-key-power")) {
  69. error = regmap_clear_bits(onkey->pf1550->regmap,
  70. PF1550_PMIC_REG_PWRCTRL1,
  71. PF1550_ONKEY_RST_EN);
  72. if (error)
  73. return dev_err_probe(&pdev->dev, error,
  74. "failed: disable turn system off");
  75. } else {
  76. key_power = true;
  77. }
  78. input = devm_input_allocate_device(&pdev->dev);
  79. if (!input)
  80. return dev_err_probe(&pdev->dev, -ENOMEM,
  81. "failed to allocate the input device\n");
  82. input->name = pdev->name;
  83. input->phys = "pf1550-onkey/input0";
  84. input->id.bustype = BUS_HOST;
  85. if (key_power)
  86. input_set_capability(input, EV_KEY, KEY_POWER);
  87. onkey->input = input;
  88. platform_set_drvdata(pdev, onkey);
  89. for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
  90. irq = platform_get_irq(pdev, i);
  91. if (irq < 0)
  92. return irq;
  93. error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
  94. pf1550_onkey_irq_handler,
  95. IRQF_NO_SUSPEND,
  96. "pf1550-onkey", onkey);
  97. if (error)
  98. return dev_err_probe(&pdev->dev, error,
  99. "failed: irq request (IRQ: %d)\n",
  100. i);
  101. }
  102. error = input_register_device(input);
  103. if (error)
  104. return dev_err_probe(&pdev->dev, error,
  105. "failed to register input device\n");
  106. device_init_wakeup(&pdev->dev, onkey->wakeup);
  107. return 0;
  108. }
  109. static int pf1550_onkey_suspend(struct device *dev)
  110. {
  111. struct platform_device *pdev = to_platform_device(dev);
  112. struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
  113. int i, irq;
  114. if (!device_may_wakeup(&pdev->dev))
  115. regmap_write(onkey->pf1550->regmap,
  116. PF1550_PMIC_REG_ONKEY_INT_MASK0,
  117. ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
  118. ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
  119. else
  120. for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
  121. irq = platform_get_irq(pdev, i);
  122. if (irq > 0)
  123. enable_irq_wake(irq);
  124. }
  125. return 0;
  126. }
  127. static int pf1550_onkey_resume(struct device *dev)
  128. {
  129. struct platform_device *pdev = to_platform_device(dev);
  130. struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
  131. int i, irq;
  132. if (!device_may_wakeup(&pdev->dev))
  133. regmap_write(onkey->pf1550->regmap,
  134. PF1550_PMIC_REG_ONKEY_INT_MASK0,
  135. ~((u8)(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI |
  136. ONKEY_IRQ_2SI | ONKEY_IRQ_3SI | ONKEY_IRQ_4SI |
  137. ONKEY_IRQ_8SI)));
  138. else
  139. for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
  140. irq = platform_get_irq(pdev, i);
  141. if (irq > 0)
  142. disable_irq_wake(irq);
  143. }
  144. return 0;
  145. }
  146. static DEFINE_SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
  147. pf1550_onkey_resume);
  148. static const struct platform_device_id pf1550_onkey_id[] = {
  149. { "pf1550-onkey", },
  150. { /* sentinel */ }
  151. };
  152. MODULE_DEVICE_TABLE(platform, pf1550_onkey_id);
  153. static struct platform_driver pf1550_onkey_driver = {
  154. .driver = {
  155. .name = "pf1550-onkey",
  156. .pm = pm_sleep_ptr(&pf1550_onkey_pm_ops),
  157. },
  158. .probe = pf1550_onkey_probe,
  159. .id_table = pf1550_onkey_id,
  160. };
  161. module_platform_driver(pf1550_onkey_driver);
  162. MODULE_AUTHOR("Freescale Semiconductor");
  163. MODULE_DESCRIPTION("PF1550 onkey Driver");
  164. MODULE_LICENSE("GPL");