1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * OnKey device driver for DA9063, DA9062 and DA9061 PMICs 4 * Copyright (C) 2015 Dialog Semiconductor Ltd. 5 */ 6 7 #include <linux/devm-helpers.h> 8 #include <linux/module.h> 9 #include <linux/errno.h> 10 #include <linux/input.h> 11 #include <linux/interrupt.h> 12 #include <linux/platform_device.h> 13 #include <linux/pm_wakeirq.h> 14 #include <linux/workqueue.h> 15 #include <linux/regmap.h> 16 #include <linux/of.h> 17 #include <linux/mfd/da9063/core.h> 18 #include <linux/mfd/da9063/registers.h> 19 #include <linux/mfd/da9062/core.h> 20 #include <linux/mfd/da9062/registers.h> 21 22 struct da906x_chip_config { 23 /* REGS */ 24 int onkey_status; 25 int onkey_pwr_signalling; 26 int onkey_fault_log; 27 int onkey_shutdown; 28 /* MASKS */ 29 int onkey_nonkey_mask; 30 int onkey_nonkey_lock_mask; 31 int onkey_key_reset_mask; 32 int onkey_shutdown_mask; 33 /* NAMES */ 34 const char *name; 35 }; 36 37 struct da9063_onkey { 38 struct delayed_work work; 39 struct input_dev *input; 40 struct device *dev; 41 struct regmap *regmap; 42 const struct da906x_chip_config *config; 43 char phys[32]; 44 bool key_power; 45 }; 46 47 static const struct da906x_chip_config da9063_regs = { 48 /* REGS */ 49 .onkey_status = DA9063_REG_STATUS_A, 50 .onkey_pwr_signalling = DA9063_REG_CONTROL_B, 51 .onkey_fault_log = DA9063_REG_FAULT_LOG, 52 .onkey_shutdown = DA9063_REG_CONTROL_F, 53 /* MASKS */ 54 .onkey_nonkey_mask = DA9063_NONKEY, 55 .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK, 56 .onkey_key_reset_mask = DA9063_KEY_RESET, 57 .onkey_shutdown_mask = DA9063_SHUTDOWN, 58 /* NAMES */ 59 .name = DA9063_DRVNAME_ONKEY, 60 }; 61 62 static const struct da906x_chip_config da9062_regs = { 63 /* REGS */ 64 .onkey_status = DA9062AA_STATUS_A, 65 .onkey_pwr_signalling = DA9062AA_CONTROL_B, 66 .onkey_fault_log = DA9062AA_FAULT_LOG, 67 .onkey_shutdown = DA9062AA_CONTROL_F, 68 /* MASKS */ 69 .onkey_nonkey_mask = DA9062AA_NONKEY_MASK, 70 .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK, 71 .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK, 72 .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK, 73 /* NAMES */ 74 .name = "da9062-onkey", 75 }; 76 77 static const struct of_device_id da9063_compatible_reg_id_table[] = { 78 { .compatible = "dlg,da9063-onkey", .data = &da9063_regs }, 79 { .compatible = "dlg,da9062-onkey", .data = &da9062_regs }, 80 { }, 81 }; 82 MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table); 83 84 static void da9063_poll_on(struct work_struct *work) 85 { 86 struct da9063_onkey *onkey = container_of(work, 87 struct da9063_onkey, 88 work.work); 89 const struct da906x_chip_config *config = onkey->config; 90 unsigned int val; 91 int fault_log = 0; 92 bool poll = true; 93 int error; 94 95 /* Poll to see when the pin is released */ 96 error = regmap_read(onkey->regmap, 97 config->onkey_status, 98 &val); 99 if (error) { 100 dev_err(onkey->dev, 101 "Failed to read ON status: %d\n", error); 102 goto err_poll; 103 } 104 105 if (!(val & config->onkey_nonkey_mask)) { 106 error = regmap_update_bits(onkey->regmap, 107 config->onkey_pwr_signalling, 108 config->onkey_nonkey_lock_mask, 109 0); 110 if (error) { 111 dev_err(onkey->dev, 112 "Failed to reset the Key Delay %d\n", error); 113 goto err_poll; 114 } 115 116 input_report_key(onkey->input, KEY_POWER, 0); 117 input_sync(onkey->input); 118 119 poll = false; 120 } 121 122 /* 123 * If the fault log KEY_RESET is detected, then clear it 124 * and shut down the system. 125 */ 126 error = regmap_read(onkey->regmap, 127 config->onkey_fault_log, 128 &fault_log); 129 if (error) { 130 dev_warn(&onkey->input->dev, 131 "Cannot read FAULT_LOG: %d\n", error); 132 } else if (fault_log & config->onkey_key_reset_mask) { 133 error = regmap_write(onkey->regmap, 134 config->onkey_fault_log, 135 config->onkey_key_reset_mask); 136 if (error) { 137 dev_warn(&onkey->input->dev, 138 "Cannot reset KEY_RESET fault log: %d\n", 139 error); 140 } else { 141 /* at this point we do any S/W housekeeping 142 * and then send shutdown command 143 */ 144 dev_dbg(&onkey->input->dev, 145 "Sending SHUTDOWN to PMIC ...\n"); 146 error = regmap_write(onkey->regmap, 147 config->onkey_shutdown, 148 config->onkey_shutdown_mask); 149 if (error) 150 dev_err(&onkey->input->dev, 151 "Cannot SHUTDOWN PMIC: %d\n", 152 error); 153 } 154 } 155 156 err_poll: 157 if (poll) 158 schedule_delayed_work(&onkey->work, msecs_to_jiffies(50)); 159 } 160 161 static irqreturn_t da9063_onkey_irq_handler(int irq, void *data) 162 { 163 struct da9063_onkey *onkey = data; 164 const struct da906x_chip_config *config = onkey->config; 165 unsigned int val; 166 int error; 167 168 error = regmap_read(onkey->regmap, 169 config->onkey_status, 170 &val); 171 if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) { 172 input_report_key(onkey->input, KEY_POWER, 1); 173 input_sync(onkey->input); 174 schedule_delayed_work(&onkey->work, 0); 175 dev_dbg(onkey->dev, "KEY_POWER long press.\n"); 176 } else { 177 input_report_key(onkey->input, KEY_POWER, 1); 178 input_sync(onkey->input); 179 input_report_key(onkey->input, KEY_POWER, 0); 180 input_sync(onkey->input); 181 dev_dbg(onkey->dev, "KEY_POWER short press.\n"); 182 } 183 184 return IRQ_HANDLED; 185 } 186 187 static int da9063_onkey_probe(struct platform_device *pdev) 188 { 189 struct da9063_onkey *onkey; 190 const struct of_device_id *match; 191 int irq; 192 int error; 193 194 match = of_match_node(da9063_compatible_reg_id_table, 195 pdev->dev.of_node); 196 if (!match) 197 return -ENXIO; 198 199 onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey), 200 GFP_KERNEL); 201 if (!onkey) { 202 dev_err(&pdev->dev, "Failed to allocate memory.\n"); 203 return -ENOMEM; 204 } 205 206 onkey->config = match->data; 207 onkey->dev = &pdev->dev; 208 209 onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL); 210 if (!onkey->regmap) { 211 dev_err(&pdev->dev, "Parent regmap unavailable.\n"); 212 return -ENXIO; 213 } 214 215 onkey->key_power = !of_property_read_bool(pdev->dev.of_node, 216 "dlg,disable-key-power"); 217 218 onkey->input = devm_input_allocate_device(&pdev->dev); 219 if (!onkey->input) { 220 dev_err(&pdev->dev, "Failed to allocated input device.\n"); 221 return -ENOMEM; 222 } 223 224 onkey->input->name = onkey->config->name; 225 snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0", 226 onkey->config->name); 227 onkey->input->phys = onkey->phys; 228 onkey->input->dev.parent = &pdev->dev; 229 230 input_set_capability(onkey->input, EV_KEY, KEY_POWER); 231 232 error = devm_delayed_work_autocancel(&pdev->dev, &onkey->work, 233 da9063_poll_on); 234 if (error) { 235 dev_err(&pdev->dev, 236 "Failed to add cancel poll action: %d\n", 237 error); 238 return error; 239 } 240 241 irq = platform_get_irq_byname(pdev, "ONKEY"); 242 if (irq < 0) 243 return irq; 244 245 error = devm_request_threaded_irq(&pdev->dev, irq, 246 NULL, da9063_onkey_irq_handler, 247 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 248 "ONKEY", onkey); 249 if (error) { 250 dev_err(&pdev->dev, 251 "Failed to request IRQ %d: %d\n", irq, error); 252 return error; 253 } 254 255 error = dev_pm_set_wake_irq(&pdev->dev, irq); 256 if (error) 257 dev_warn(&pdev->dev, 258 "Failed to set IRQ %d as a wake IRQ: %d\n", 259 irq, error); 260 else 261 device_init_wakeup(&pdev->dev, true); 262 263 error = input_register_device(onkey->input); 264 if (error) { 265 dev_err(&pdev->dev, 266 "Failed to register input device: %d\n", error); 267 return error; 268 } 269 270 return 0; 271 } 272 273 static struct platform_driver da9063_onkey_driver = { 274 .probe = da9063_onkey_probe, 275 .driver = { 276 .name = DA9063_DRVNAME_ONKEY, 277 .of_match_table = da9063_compatible_reg_id_table, 278 }, 279 }; 280 module_platform_driver(da9063_onkey_driver); 281 282 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); 283 MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061"); 284 MODULE_LICENSE("GPL"); 285 MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY); 286