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