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