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