Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add DA9062 OnKey capability to DA9063 OnKey driver

Add DA9062 OnKey support into the existing DA9063 OnKey driver component by
using generic access tables for common register and bit mask definitions.

The following change will add generic register and bit mask support to the
DA9063 OnKey.

The following alterations have been made to the DA9063 OnKey:

- Addition of a da906x_chip_config structure to hold all
generic registers and bitmasks for this type of OnKey component.
- Addition of an struct of_device_id table for DA9063 and DA9062
defaults
- Refactoring functions to use struct da9063_onkey accesses to generic
registers/masks instead of using defines from registers.h
- Re-work of da9063_onkey_probe() to use of_match_node() and
dev_get_regmap() to provide initialisation of generic registers and
masks and access to regmap

Signed-off-by: Steve Twiss <stwiss.opensource@diasemi.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

S Twiss and committed by
Dmitry Torokhov
a27b5e0a 8f697e57

+140 -29
+32
Documentation/devicetree/bindings/input/da9062-onkey.txt
··· 1 + * Dialog DA9062/63 OnKey Module 2 + 3 + This module is part of the DA9062/DA9063. For more details about entire 4 + chips see Documentation/devicetree/bindings/mfd/da9062.txt and 5 + Documentation/devicetree/bindings/mfd/da9063.txt 6 + 7 + This module provides KEY_POWER, KEY_SLEEP and events. 8 + 9 + Required properties: 10 + 11 + - compatible: should be one of: 12 + dlg,da9062-onkey 13 + dlg,da9063-onkey 14 + 15 + Optional properties: 16 + 17 + - dlg,disable-key-power : Disable power-down using a long key-press. If this 18 + entry exists the OnKey driver will remove support for the KEY_POWER key 19 + press. If this entry does not exist then by default the key-press 20 + triggered power down is enabled and the OnKey will support both KEY_POWER 21 + and KEY_SLEEP. 22 + 23 + Example: 24 + 25 + pmic0: da9062@58 { 26 + 27 + onkey { 28 + compatible = "dlg,da9063-onkey"; 29 + dlg,disable-key-power; 30 + }; 31 + 32 + };
+4 -4
drivers/input/misc/Kconfig
··· 599 599 will be called da9055_onkey. 600 600 601 601 config INPUT_DA9063_ONKEY 602 - tristate "Dialog DA9063 OnKey" 603 - depends on MFD_DA9063 602 + tristate "Dialog DA9062/63 OnKey" 603 + depends on MFD_DA9063 || MFD_DA9062 604 604 help 605 - Support the ONKEY of Dialog DA9063 Power Management IC as an 606 - input device reporting power button statue. 605 + Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs 606 + as an input device capable of reporting the power button status. 607 607 608 608 To compile this driver as a module, choose M here: the module 609 609 will be called da9063_onkey.
+104 -25
drivers/input/misc/da9063_onkey.c
··· 1 1 /* 2 - * OnKey device driver for DA9063 2 + * OnKey device driver for DA9063 and DA9062 PMICs 3 3 * Copyright (C) 2015 Dialog Semiconductor Ltd. 4 4 * 5 5 * This program is free software; you can redistribute it and/or ··· 24 24 #include <linux/mfd/da9063/core.h> 25 25 #include <linux/mfd/da9063/pdata.h> 26 26 #include <linux/mfd/da9063/registers.h> 27 + #include <linux/mfd/da9062/core.h> 28 + #include <linux/mfd/da9062/registers.h> 29 + 30 + struct da906x_chip_config { 31 + /* REGS */ 32 + int onkey_status; 33 + int onkey_pwr_signalling; 34 + int onkey_fault_log; 35 + int onkey_shutdown; 36 + /* MASKS */ 37 + int onkey_nonkey_mask; 38 + int onkey_nonkey_lock_mask; 39 + int onkey_key_reset_mask; 40 + int onkey_shutdown_mask; 41 + /* NAMES */ 42 + const char *name; 43 + }; 27 44 28 45 struct da9063_onkey { 29 - struct da9063 *hw; 30 46 struct delayed_work work; 31 47 struct input_dev *input; 32 48 struct device *dev; 49 + struct regmap *regmap; 50 + const struct da906x_chip_config *config; 51 + char phys[32]; 33 52 bool key_power; 53 + }; 54 + 55 + static const struct da906x_chip_config da9063_regs = { 56 + /* REGS */ 57 + .onkey_status = DA9063_REG_STATUS_A, 58 + .onkey_pwr_signalling = DA9063_REG_CONTROL_B, 59 + .onkey_fault_log = DA9063_REG_FAULT_LOG, 60 + .onkey_shutdown = DA9063_REG_CONTROL_F, 61 + /* MASKS */ 62 + .onkey_nonkey_mask = DA9063_NONKEY, 63 + .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK, 64 + .onkey_key_reset_mask = DA9063_KEY_RESET, 65 + .onkey_shutdown_mask = DA9063_SHUTDOWN, 66 + /* NAMES */ 67 + .name = DA9063_DRVNAME_ONKEY, 68 + }; 69 + 70 + static const struct da906x_chip_config da9062_regs = { 71 + /* REGS */ 72 + .onkey_status = DA9062AA_STATUS_A, 73 + .onkey_pwr_signalling = DA9062AA_CONTROL_B, 74 + .onkey_fault_log = DA9062AA_FAULT_LOG, 75 + .onkey_shutdown = DA9062AA_CONTROL_F, 76 + /* MASKS */ 77 + .onkey_nonkey_mask = DA9062AA_NONKEY_MASK, 78 + .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK, 79 + .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK, 80 + .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK, 81 + /* NAMES */ 82 + .name = "da9062-onkey", 83 + }; 84 + 85 + static const struct of_device_id da9063_compatible_reg_id_table[] = { 86 + { .compatible = "dlg,da9063-onkey", .data = &da9063_regs }, 87 + { .compatible = "dlg,da9062-onkey", .data = &da9062_regs }, 88 + { }, 34 89 }; 35 90 36 91 static void da9063_poll_on(struct work_struct *work) 37 92 { 38 - struct da9063_onkey *onkey = container_of(work, struct da9063_onkey, 39 - work.work); 93 + struct da9063_onkey *onkey = container_of(work, 94 + struct da9063_onkey, 95 + work.work); 96 + const struct da906x_chip_config *config = onkey->config; 40 97 unsigned int val; 41 98 int fault_log = 0; 42 99 bool poll = true; 43 100 int error; 44 101 45 102 /* Poll to see when the pin is released */ 46 - error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); 103 + error = regmap_read(onkey->regmap, 104 + config->onkey_status, 105 + &val); 47 106 if (error) { 48 107 dev_err(onkey->dev, 49 108 "Failed to read ON status: %d\n", error); 50 109 goto err_poll; 51 110 } 52 111 53 - if (!(val & DA9063_NONKEY)) { 54 - error = regmap_update_bits(onkey->hw->regmap, 55 - DA9063_REG_CONTROL_B, 56 - DA9063_NONKEY_LOCK, 0); 112 + if (!(val & config->onkey_nonkey_mask)) { 113 + error = regmap_update_bits(onkey->regmap, 114 + config->onkey_pwr_signalling, 115 + config->onkey_nonkey_lock_mask, 116 + 0); 57 117 if (error) { 58 118 dev_err(onkey->dev, 59 119 "Failed to reset the Key Delay %d\n", error); ··· 130 70 * If the fault log KEY_RESET is detected, then clear it 131 71 * and shut down the system. 132 72 */ 133 - error = regmap_read(onkey->hw->regmap, 134 - DA9063_REG_FAULT_LOG, &fault_log); 73 + error = regmap_read(onkey->regmap, 74 + config->onkey_fault_log, 75 + &fault_log); 135 76 if (error) { 136 77 dev_warn(&onkey->input->dev, 137 78 "Cannot read FAULT_LOG: %d\n", error); 138 - } else if (fault_log & DA9063_KEY_RESET) { 139 - error = regmap_write(onkey->hw->regmap, 140 - DA9063_REG_FAULT_LOG, 141 - DA9063_KEY_RESET); 79 + } else if (fault_log & config->onkey_key_reset_mask) { 80 + error = regmap_write(onkey->regmap, 81 + config->onkey_fault_log, 82 + config->onkey_key_reset_mask); 142 83 if (error) { 143 84 dev_warn(&onkey->input->dev, 144 85 "Cannot reset KEY_RESET fault log: %d\n", ··· 149 88 * and then send shutdown command 150 89 */ 151 90 dev_dbg(&onkey->input->dev, 152 - "Sending SHUTDOWN to DA9063 ...\n"); 153 - error = regmap_write(onkey->hw->regmap, 154 - DA9063_REG_CONTROL_F, 155 - DA9063_SHUTDOWN); 91 + "Sending SHUTDOWN to DA9063 ...\n"); 92 + error = regmap_write(onkey->regmap, 93 + config->onkey_shutdown, 94 + config->onkey_shutdown_mask); 156 95 if (error) 157 96 dev_err(&onkey->input->dev, 158 97 "Cannot SHUTDOWN DA9063: %d\n", ··· 168 107 static irqreturn_t da9063_onkey_irq_handler(int irq, void *data) 169 108 { 170 109 struct da9063_onkey *onkey = data; 110 + const struct da906x_chip_config *config = onkey->config; 171 111 unsigned int val; 172 112 int error; 173 113 174 - error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); 175 - if (onkey->key_power && !error && (val & DA9063_NONKEY)) { 114 + error = regmap_read(onkey->regmap, 115 + config->onkey_status, 116 + &val); 117 + if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) { 176 118 input_report_key(onkey->input, KEY_POWER, 1); 177 119 input_sync(onkey->input); 178 120 schedule_delayed_work(&onkey->work, 0); ··· 203 139 struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); 204 140 struct da9063_pdata *pdata = dev_get_platdata(da9063->dev); 205 141 struct da9063_onkey *onkey; 142 + const struct of_device_id *match; 206 143 int irq; 207 144 int error; 145 + 146 + match = of_match_node(da9063_compatible_reg_id_table, 147 + pdev->dev.of_node); 148 + if (!match) 149 + return -ENXIO; 208 150 209 151 onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey), 210 152 GFP_KERNEL); ··· 219 149 return -ENOMEM; 220 150 } 221 151 152 + onkey->config = match->data; 222 153 onkey->dev = &pdev->dev; 223 - onkey->hw = da9063; 154 + 155 + onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL); 156 + if (!onkey->regmap) { 157 + dev_err(&pdev->dev, "Parent regmap unavailable.\n"); 158 + return -ENXIO; 159 + } 224 160 225 161 if (pdata) 226 162 onkey->key_power = pdata->key_power; ··· 241 165 return -ENOMEM; 242 166 } 243 167 244 - onkey->input->name = DA9063_DRVNAME_ONKEY; 245 - onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0"; 168 + onkey->input->name = onkey->config->name; 169 + snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0", 170 + onkey->config->name); 171 + onkey->input->phys = onkey->phys; 246 172 onkey->input->dev.parent = &pdev->dev; 247 173 248 174 if (onkey->key_power) ··· 294 216 .probe = da9063_onkey_probe, 295 217 .driver = { 296 218 .name = DA9063_DRVNAME_ONKEY, 219 + .of_match_table = da9063_compatible_reg_id_table, 297 220 }, 298 221 }; 299 222 module_platform_driver(da9063_onkey_driver); 300 223 301 224 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); 302 - MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063"); 225 + MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062"); 303 226 MODULE_LICENSE("GPL"); 304 227 MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);