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