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