Skip to content

Commit

Permalink
Input: pm8941-pwrkey - abstract register offsets and event code
Browse files Browse the repository at this point in the history
In order to support resin thru the pwrkey driver (they are very
similar in nature) we need to abstract the handling in this driver.

First we abstract pull_up_bit and status_bit along in driver data.
The event code sent for key events is quiried from DT.

Since the device can be child of pon lookup regmap and reg from
parent if lookup fails (we are child).

Reviewed-by: Bjorn Andersson <[email protected]>
Signed-off-by: Vinod Koul <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
  • Loading branch information
vinodkoul authored and dtor committed Jul 31, 2018
1 parent 0b64fa0 commit 2049a9e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ PROPERTIES
Definition: presence of this property indicates that the KPDPWR_N pin
should be configured for pull up.

- linux,code:
Usage: optional
Value type: <u32>
Definition: The input key-code associated with the power key.
Use the linux event codes defined in
include/dt-bindings/input/linux-event-codes.h
When property is omitted KEY_POWER is assumed.

EXAMPLE

pwrkey@800 {
Expand All @@ -40,4 +48,5 @@ EXAMPLE
interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
debounce = <15625>;
bias-pull-up;
linux,code = <KEY_POWER>;
};
62 changes: 49 additions & 13 deletions drivers/input/misc/pm8941-pwrkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
Expand All @@ -42,6 +43,10 @@
#define PON_DBC_CTL 0x71
#define PON_DBC_DELAY_MASK 0x7

struct pm8941_data {
unsigned int pull_up_bit;
unsigned int status_bit;
};

struct pm8941_pwrkey {
struct device *dev;
Expand All @@ -52,6 +57,9 @@ struct pm8941_pwrkey {

unsigned int revision;
struct notifier_block reboot_notifier;

u32 code;
const struct pm8941_data *data;
};

static int pm8941_reboot_notify(struct notifier_block *nb,
Expand Down Expand Up @@ -124,7 +132,8 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
if (error)
return IRQ_HANDLED;

input_report_key(pwrkey->input, KEY_POWER, !!(sts & PON_KPDPWR_N_SET));
input_report_key(pwrkey->input, pwrkey->code,
sts & pwrkey->data->status_bit);
input_sync(pwrkey->input);

return IRQ_HANDLED;
Expand Down Expand Up @@ -157,6 +166,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey;
bool pull_up;
struct device *parent;
u32 req_delay;
int error;

Expand All @@ -175,38 +185,59 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return -ENOMEM;

pwrkey->dev = &pdev->dev;
pwrkey->data = of_device_get_match_data(&pdev->dev);

pwrkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
parent = pdev->dev.parent;
pwrkey->regmap = dev_get_regmap(parent, NULL);
if (!pwrkey->regmap) {
dev_err(&pdev->dev, "failed to locate regmap\n");
return -ENODEV;
/*
* We failed to get regmap for parent. Let's see if we are
* a child of pon node and read regmap and reg from its
* parent.
*/
pwrkey->regmap = dev_get_regmap(parent->parent, NULL);
if (!pwrkey->regmap) {
dev_err(&pdev->dev, "failed to locate regmap\n");
return -ENODEV;
}

error = of_property_read_u32(parent->of_node,
"reg", &pwrkey->baseaddr);
} else {
error = of_property_read_u32(pdev->dev.of_node, "reg",
&pwrkey->baseaddr);
}
if (error)
return error;

pwrkey->irq = platform_get_irq(pdev, 0);
if (pwrkey->irq < 0) {
dev_err(&pdev->dev, "failed to get irq\n");
return pwrkey->irq;
}

error = of_property_read_u32(pdev->dev.of_node, "reg",
&pwrkey->baseaddr);
if (error)
return error;

error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
&pwrkey->revision);
if (error) {
dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
return error;
}

error = of_property_read_u32(pdev->dev.of_node, "linux,code",
&pwrkey->code);
if (error) {
dev_dbg(&pdev->dev,
"no linux,code assuming power (%d)\n", error);
pwrkey->code = KEY_POWER;
}

pwrkey->input = devm_input_allocate_device(&pdev->dev);
if (!pwrkey->input) {
dev_dbg(&pdev->dev, "unable to allocate input device\n");
return -ENOMEM;
}

input_set_capability(pwrkey->input, EV_KEY, KEY_POWER);
input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);

pwrkey->input->name = "pm8941_pwrkey";
pwrkey->input->phys = "pm8941_pwrkey/input0";
Expand All @@ -225,8 +256,8 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)

error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_PULL_CTL,
PON_KPDPWR_PULL_UP,
pull_up ? PON_KPDPWR_PULL_UP : 0);
pwrkey->data->pull_up_bit,
pull_up ? pwrkey->data->pull_up_bit : 0);
if (error) {
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
return error;
Expand Down Expand Up @@ -271,8 +302,13 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
return 0;
}

static const struct pm8941_data pwrkey_data = {
.pull_up_bit = PON_KPDPWR_PULL_UP,
.status_bit = PON_KPDPWR_N_SET,
};

static const struct of_device_id pm8941_pwr_key_id_table[] = {
{ .compatible = "qcom,pm8941-pwrkey" },
{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
{ }
};
MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
Expand Down

0 comments on commit 2049a9e

Please sign in to comment.