Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * OnKey device driver for DA9063, DA9062 and DA9061 PMICs
0004  * Copyright (C) 2015  Dialog Semiconductor Ltd.
0005  */
0006 
0007 #include <linux/devm-helpers.h>
0008 #include <linux/module.h>
0009 #include <linux/errno.h>
0010 #include <linux/input.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/workqueue.h>
0014 #include <linux/regmap.h>
0015 #include <linux/of.h>
0016 #include <linux/mfd/da9063/core.h>
0017 #include <linux/mfd/da9063/registers.h>
0018 #include <linux/mfd/da9062/core.h>
0019 #include <linux/mfd/da9062/registers.h>
0020 
0021 struct da906x_chip_config {
0022     /* REGS */
0023     int onkey_status;
0024     int onkey_pwr_signalling;
0025     int onkey_fault_log;
0026     int onkey_shutdown;
0027     /* MASKS */
0028     int onkey_nonkey_mask;
0029     int onkey_nonkey_lock_mask;
0030     int onkey_key_reset_mask;
0031     int onkey_shutdown_mask;
0032     /* NAMES */
0033     const char *name;
0034 };
0035 
0036 struct da9063_onkey {
0037     struct delayed_work work;
0038     struct input_dev *input;
0039     struct device *dev;
0040     struct regmap *regmap;
0041     const struct da906x_chip_config *config;
0042     char phys[32];
0043     bool key_power;
0044 };
0045 
0046 static const struct da906x_chip_config da9063_regs = {
0047     /* REGS */
0048     .onkey_status = DA9063_REG_STATUS_A,
0049     .onkey_pwr_signalling = DA9063_REG_CONTROL_B,
0050     .onkey_fault_log = DA9063_REG_FAULT_LOG,
0051     .onkey_shutdown = DA9063_REG_CONTROL_F,
0052     /* MASKS */
0053     .onkey_nonkey_mask = DA9063_NONKEY,
0054     .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK,
0055     .onkey_key_reset_mask = DA9063_KEY_RESET,
0056     .onkey_shutdown_mask = DA9063_SHUTDOWN,
0057     /* NAMES */
0058     .name = DA9063_DRVNAME_ONKEY,
0059 };
0060 
0061 static const struct da906x_chip_config da9062_regs = {
0062     /* REGS */
0063     .onkey_status = DA9062AA_STATUS_A,
0064     .onkey_pwr_signalling = DA9062AA_CONTROL_B,
0065     .onkey_fault_log = DA9062AA_FAULT_LOG,
0066     .onkey_shutdown = DA9062AA_CONTROL_F,
0067     /* MASKS */
0068     .onkey_nonkey_mask = DA9062AA_NONKEY_MASK,
0069     .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK,
0070     .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK,
0071     .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK,
0072     /* NAMES */
0073     .name = "da9062-onkey",
0074 };
0075 
0076 static const struct of_device_id da9063_compatible_reg_id_table[] = {
0077     { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
0078     { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
0079     { },
0080 };
0081 MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
0082 
0083 static void da9063_poll_on(struct work_struct *work)
0084 {
0085     struct da9063_onkey *onkey = container_of(work,
0086                         struct da9063_onkey,
0087                         work.work);
0088     const struct da906x_chip_config *config = onkey->config;
0089     unsigned int val;
0090     int fault_log = 0;
0091     bool poll = true;
0092     int error;
0093 
0094     /* Poll to see when the pin is released */
0095     error = regmap_read(onkey->regmap,
0096                 config->onkey_status,
0097                 &val);
0098     if (error) {
0099         dev_err(onkey->dev,
0100             "Failed to read ON status: %d\n", error);
0101         goto err_poll;
0102     }
0103 
0104     if (!(val & config->onkey_nonkey_mask)) {
0105         error = regmap_update_bits(onkey->regmap,
0106                        config->onkey_pwr_signalling,
0107                        config->onkey_nonkey_lock_mask,
0108                        0);
0109         if (error) {
0110             dev_err(onkey->dev,
0111                 "Failed to reset the Key Delay %d\n", error);
0112             goto err_poll;
0113         }
0114 
0115         input_report_key(onkey->input, KEY_POWER, 0);
0116         input_sync(onkey->input);
0117 
0118         poll = false;
0119     }
0120 
0121     /*
0122      * If the fault log KEY_RESET is detected, then clear it
0123      * and shut down the system.
0124      */
0125     error = regmap_read(onkey->regmap,
0126                 config->onkey_fault_log,
0127                 &fault_log);
0128     if (error) {
0129         dev_warn(&onkey->input->dev,
0130              "Cannot read FAULT_LOG: %d\n", error);
0131     } else if (fault_log & config->onkey_key_reset_mask) {
0132         error = regmap_write(onkey->regmap,
0133                      config->onkey_fault_log,
0134                      config->onkey_key_reset_mask);
0135         if (error) {
0136             dev_warn(&onkey->input->dev,
0137                  "Cannot reset KEY_RESET fault log: %d\n",
0138                  error);
0139         } else {
0140             /* at this point we do any S/W housekeeping
0141              * and then send shutdown command
0142              */
0143             dev_dbg(&onkey->input->dev,
0144                 "Sending SHUTDOWN to PMIC ...\n");
0145             error = regmap_write(onkey->regmap,
0146                          config->onkey_shutdown,
0147                          config->onkey_shutdown_mask);
0148             if (error)
0149                 dev_err(&onkey->input->dev,
0150                     "Cannot SHUTDOWN PMIC: %d\n",
0151                     error);
0152         }
0153     }
0154 
0155 err_poll:
0156     if (poll)
0157         schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
0158 }
0159 
0160 static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
0161 {
0162     struct da9063_onkey *onkey = data;
0163     const struct da906x_chip_config *config = onkey->config;
0164     unsigned int val;
0165     int error;
0166 
0167     error = regmap_read(onkey->regmap,
0168                 config->onkey_status,
0169                 &val);
0170     if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
0171         input_report_key(onkey->input, KEY_POWER, 1);
0172         input_sync(onkey->input);
0173         schedule_delayed_work(&onkey->work, 0);
0174         dev_dbg(onkey->dev, "KEY_POWER long press.\n");
0175     } else {
0176         input_report_key(onkey->input, KEY_POWER, 1);
0177         input_sync(onkey->input);
0178         input_report_key(onkey->input, KEY_POWER, 0);
0179         input_sync(onkey->input);
0180         dev_dbg(onkey->dev, "KEY_POWER short press.\n");
0181     }
0182 
0183     return IRQ_HANDLED;
0184 }
0185 
0186 static int da9063_onkey_probe(struct platform_device *pdev)
0187 {
0188     struct da9063_onkey *onkey;
0189     const struct of_device_id *match;
0190     int irq;
0191     int error;
0192 
0193     match = of_match_node(da9063_compatible_reg_id_table,
0194                   pdev->dev.of_node);
0195     if (!match)
0196         return -ENXIO;
0197 
0198     onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
0199                  GFP_KERNEL);
0200     if (!onkey) {
0201         dev_err(&pdev->dev, "Failed to allocate memory.\n");
0202         return -ENOMEM;
0203     }
0204 
0205     onkey->config = match->data;
0206     onkey->dev = &pdev->dev;
0207 
0208     onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
0209     if (!onkey->regmap) {
0210         dev_err(&pdev->dev, "Parent regmap unavailable.\n");
0211         return -ENXIO;
0212     }
0213 
0214     onkey->key_power = !of_property_read_bool(pdev->dev.of_node,
0215                           "dlg,disable-key-power");
0216 
0217     onkey->input = devm_input_allocate_device(&pdev->dev);
0218     if (!onkey->input) {
0219         dev_err(&pdev->dev, "Failed to allocated input device.\n");
0220         return -ENOMEM;
0221     }
0222 
0223     onkey->input->name = onkey->config->name;
0224     snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
0225          onkey->config->name);
0226     onkey->input->phys = onkey->phys;
0227     onkey->input->dev.parent = &pdev->dev;
0228 
0229     input_set_capability(onkey->input, EV_KEY, KEY_POWER);
0230 
0231     error = devm_delayed_work_autocancel(&pdev->dev, &onkey->work,
0232                          da9063_poll_on);
0233     if (error) {
0234         dev_err(&pdev->dev,
0235             "Failed to add cancel poll action: %d\n",
0236             error);
0237         return error;
0238     }
0239 
0240     irq = platform_get_irq_byname(pdev, "ONKEY");
0241     if (irq < 0)
0242         return irq;
0243 
0244     error = devm_request_threaded_irq(&pdev->dev, irq,
0245                       NULL, da9063_onkey_irq_handler,
0246                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0247                       "ONKEY", onkey);
0248     if (error) {
0249         dev_err(&pdev->dev,
0250             "Failed to request IRQ %d: %d\n", irq, error);
0251         return error;
0252     }
0253 
0254     error = input_register_device(onkey->input);
0255     if (error) {
0256         dev_err(&pdev->dev,
0257             "Failed to register input device: %d\n", error);
0258         return error;
0259     }
0260 
0261     return 0;
0262 }
0263 
0264 static struct platform_driver da9063_onkey_driver = {
0265     .probe  = da9063_onkey_probe,
0266     .driver = {
0267         .name   = DA9063_DRVNAME_ONKEY,
0268         .of_match_table = da9063_compatible_reg_id_table,
0269     },
0270 };
0271 module_platform_driver(da9063_onkey_driver);
0272 
0273 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
0274 MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061");
0275 MODULE_LICENSE("GPL");
0276 MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);