@@ -0,0 +1,196 @@+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.+*Copyright(c)2014,SonyMobileCommunicationsInc.+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2and+*onlyversion2aspublishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*/++#include<linux/module.h>+#include<linux/kernel.h>+#include<linux/errno.h>+#include<linux/slab.h>+#include<linux/input.h>+#include<linux/interrupt.h>+#include<linux/platform_device.h>+#include<linux/regmap.h>+#include<linux/log2.h>+#include<linux/of.h>++#define PON_RT_STS 0x10+#define PON_PULL_CTL 0x70+#define PON_DBC_CTL 0x71++#define PON_DBC_DELAY_MASK 0x7+#define PON_KPDPWR_N_SET BIT(0)+#define PON_KPDPWR_PULL_UP BIT(1)++structpm8941_pwrkey{+intirq;+u32baseaddr;+structregmap*regmap;+structinput_dev*input;+};++staticirqreturn_tpm8941_pwrkey_irq(intirq,void*_data)+{+structpm8941_pwrkey*pwrkey=_data;+unsignedintsts;+intrc;++rc=regmap_read(pwrkey->regmap,pwrkey->baseaddr+PON_RT_STS,&sts);+if(rc)+returnIRQ_HANDLED;++input_report_key(pwrkey->input,KEY_POWER,!!(sts&PON_KPDPWR_N_SET));+input_sync(pwrkey->input);++returnIRQ_HANDLED;+}++#ifdef CONFIG_PM_SLEEP+staticintpm8941_pwrkey_suspend(structdevice*dev)+{+structpm8941_pwrkey*pwrkey=dev_get_drvdata(dev);++if(device_may_wakeup(dev))+enable_irq_wake(pwrkey->irq);++return0;+}++staticintpm8941_pwrkey_resume(structdevice*dev)+{+structpm8941_pwrkey*pwrkey=dev_get_drvdata(dev);++if(device_may_wakeup(dev))+disable_irq_wake(pwrkey->irq);++return0;+}+#endif++staticSIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,+pm8941_pwrkey_suspend,pm8941_pwrkey_resume);++staticintpm8941_pwrkey_probe(structplatform_device*pdev)+{+structpm8941_pwrkey*pwrkey;+boolpull_up;+u32req_delay;+intrc;++if(of_property_read_u32(pdev->dev.of_node,"debounce",&req_delay))+req_delay=15625;++if(req_delay>2000000||req_delay==0){+dev_err(&pdev->dev,"invalid debounce time: %u\n",req_delay);+return-EINVAL;+}++pull_up=of_property_read_bool(pdev->dev.of_node,"bias-pull-up");++pwrkey=devm_kzalloc(&pdev->dev,sizeof(*pwrkey),GFP_KERNEL);+if(!pwrkey)+return-ENOMEM;++pwrkey->regmap=dev_get_regmap(pdev->dev.parent,NULL);+if(!pwrkey->regmap){+dev_err(&pdev->dev,"failed to locate regmap\n");+return-ENODEV;+}++pwrkey->irq=platform_get_irq(pdev,0);+if(pwrkey->irq<0){+dev_err(&pdev->dev,"failed to get irq\n");+returnpwrkey->irq;+}++rc=of_property_read_u32(pdev->dev.of_node,"reg",&pwrkey->baseaddr);+if(rc)+returnrc;++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);++pwrkey->input->name="pm8941_pwrkey";+pwrkey->input->phys="pm8941_pwrkey/input0";++req_delay=(req_delay<<6)/USEC_PER_SEC;+req_delay=ilog2(req_delay);++rc=regmap_update_bits(pwrkey->regmap,pwrkey->baseaddr+PON_DBC_CTL,+PON_DBC_DELAY_MASK,req_delay);+if(rc){+dev_err(&pdev->dev,"failed to set debounce: %d\n",rc);+returnrc;+}++rc=regmap_update_bits(pwrkey->regmap,+pwrkey->baseaddr+PON_PULL_CTL,PON_KPDPWR_PULL_UP,+pull_up?PON_KPDPWR_PULL_UP:0);+if(rc){+dev_err(&pdev->dev,"failed to set pull: %d\n",rc);+returnrc;+}++rc=devm_request_threaded_irq(&pdev->dev,pwrkey->irq,+NULL,pm8941_pwrkey_irq,+IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|+IRQF_ONESHOT,+"pm8941_pwrkey",pwrkey);+if(rc){+dev_err(&pdev->dev,"failed requesting IRQ: %d\n",rc);+returnrc;+}++rc=input_register_device(pwrkey->input);+if(rc){+dev_err(&pdev->dev,"failed to register input device: %d\n",+rc);+returnrc;+}++platform_set_drvdata(pdev,pwrkey);+device_init_wakeup(&pdev->dev,1);++return0;+}++staticintpm8941_pwrkey_remove(structplatform_device*pdev)+{+device_init_wakeup(&pdev->dev,0);++return0;+}++staticconststructof_device_idpm8941_pwr_key_id_table[]={+{.compatible="qcom,pm8941-pwrkey"},+{}+};+MODULE_DEVICE_TABLE(of,pm8941_pwr_key_id_table);++staticstructplatform_driverpm8941_pwrkey_driver={+.probe=pm8941_pwrkey_probe,+.remove=pm8941_pwrkey_remove,+.driver={+.name="pm8941-pwrkey",+.owner=THIS_MODULE,+.pm=&pm8941_pwr_key_pm_ops,+.of_match_table=of_match_ptr(pm8941_pwr_key_id_table),+},+};+module_platform_driver(pm8941_pwrkey_driver);++MODULE_DESCRIPTION("PM8941 Power Key driver");+MODULE_LICENSE("GPL v2");
@@ -0,0 +1,43 @@+Qualcomm PM8941 PMIC Power Key++PROPERTIES++- compatible:+ Usage: required+ Value type: <string>+ Definition: must be one of:+ "qcom,pm8941-pwrkey"++- reg:+ Usage: required+ Value type: <prop-encoded-array>+ Definition: base address of registers for block++- interrupts:+ Usage: required+ Value type: <prop-encoded-array>+ Definition: key change interrupt; The format of the specifier is+ defined by the binding document describing the node's+ interrupt parent.++- debounce:+ Usage: optional+ Value type: <u32>+ Definition: time in microseconds that key must be pressed or released+ for state change interrupt to trigger.++- bias-pull-up:+ Usage: optional+ Value type: <empty>+ Definition: presence of this property indicates that the KPDPWR_N pin+ should be configured for pull up.++EXAMPLE++ pwrkey@800 {+ compatible = "qcom,pm8941-pwrkey";+ reg = <0x800>;+ interrupts = <0x0 0x8 0 0>;+ debounce = <15625>;+ bias-pull-up;+ };
Do we need to hard-code IRQ flags like this? I'd rather we respect DT
data.
We could "move" it to DT but I don't think there's any other combination of
these flags would make sense. If you insist I can remove it though.
Regards,
Bjorn
On Tue 07 Oct 02:01 PDT 2014, Ivan T. Ivanov wrote:
Hi Bjorn,
On Mon, 2014-10-06 at 18:11 -0700, Bjorn Andersson wrote:
quoted
These patches add dt bindings and a device driver for the power key block in
the Qualcomm PM8941 pmic.
Courtney Cavin (2):
input: Add Qualcomm PM8941 power key driver
input: pm8941-pwrkey: Add DT binding documentation
.../bindings/input/qcom,pm8941-pwrkey.txt | 43 +++++
drivers/input/misc/Kconfig | 12 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/pm8941-pwrkey.c | 196 ++++++++++++++++++++
4 files changed, 252 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
create mode 100644 drivers/input/misc/pm8941-pwrkey.c
Any reason why we cannot reuse pm8xxx-pwrkey driver? It have been
converted to regmap already.
The boilerplate code is the same, but configuration registers have different
layout and values written in them are different. The pm8xxx block have separate
interrupts for press and release events while pm8941 have one interrupt for
both, so the pm8941 must read out the irq status bits to figure out which event
it was.
Maybe if we introduce some vagueness related to interrupts in the dt binding
documentation for pm8xxx we could simply reuse that binding.
Regards,
Bjorn
@@ -0,0 +1,43 @@+Qualcomm PM8941 PMIC Power Key++PROPERTIES++- compatible:+ Usage: required+ Value type: <string>+ Definition: must be one of:+ "qcom,pm8941-pwrkey"++- reg:+ Usage: required+ Value type: <prop-encoded-array>+ Definition: base address of registers for block++- interrupts:+ Usage: required+ Value type: <prop-encoded-array>+ Definition: key change interrupt; The format of the specifier is+ defined by the binding document describing the node's+ interrupt parent.++- debounce:+ Usage: optional+ Value type: <u32>+ Definition: time in microseconds that key must be pressed or released+ for state change interrupt to trigger.++- bias-pull-up:+ Usage: optional+ Value type: <empty>
boolean, is probably better than <empty> here.
+ Definition: presence of this property indicates that the KPDPWR_N pin
+ should be configured for pull up.
+
+EXAMPLE
+
+ pwrkey@800 {
+ compatible = "qcom,pm8941-pwrkey";
+ reg = <0x800>;
+ interrupts = <0x0 0x8 0 0>;
+ debounce = <15625>;
+ bias-pull-up;
+ };
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
It's allocated with devm_input_allocate_device() so I assumed that it goes away
upon the device being removed. Looking at input_register_device() seems to
confirm that.
Courtney based this driver on the skeleton from pmic8xxx-pwrkey, so I don't
think it's right to say that there's any particular author. And you have the
git log...
Regards,
Bjorn
It's allocated with devm_input_allocate_device() so I assumed that it goes away
upon the device being removed. Looking at input_register_device() seems to
confirm that.
Yes, devices allocated with devm_input_allocate_device() will be
unregistered and freed automatically.
Thanks.
--
Dmitry
From: Ivan T. Ivanov <hidden> Date: 2014-10-08 09:50:05
On Tue, 2014-10-07 at 11:46 -0700, Bjorn Andersson wrote:
On Tue 07 Oct 02:01 PDT 2014, Ivan T. Ivanov wrote:
quoted
Hi Bjorn,
On Mon, 2014-10-06 at 18:11 -0700, Bjorn Andersson wrote:
quoted
These patches add dt bindings and a device driver for the power key block in
the Qualcomm PM8941 pmic.
Courtney Cavin (2):
input: Add Qualcomm PM8941 power key driver
input: pm8941-pwrkey: Add DT binding documentation
.../bindings/input/qcom,pm8941-pwrkey.txt | 43 +++++
drivers/input/misc/Kconfig | 12 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/pm8941-pwrkey.c | 196 ++++++++++++++++++++
4 files changed, 252 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
create mode 100644 drivers/input/misc/pm8941-pwrkey.c
Any reason why we cannot reuse pm8xxx-pwrkey driver? It have been
converted to regmap already.
The boilerplate code is the same,
The boilerplate code is almost 100% :-)
but configuration registers have different
layout and values written in them are different.
We talk about 3 registers and 2 bit defines. struct regmap_field
should be able to help here.
The pm8xxx block have separate
interrupts for press and release events while pm8941 have one interrupt for
both, so the pm8941 must read out the irq status bits to figure out which event
it was.
Optional interrupt property? If both are defined hook old ISR, if its
only one hook pm8941 ISR?
Maybe if we introduce some vagueness related to interrupts in the dt binding
documentation for pm8xxx we could simply reuse that binding.
I would not say vagueness, we just can say that pm8941 did not have
second interrupt?
Regards,
Ivan
Any reason why we cannot reuse pm8xxx-pwrkey driver? It have been
converted to regmap already.
The boilerplate code is the same,
The boilerplate code is almost 100% :-)
quoted
but configuration registers have different
layout and values written in them are different.
We talk about 3 registers and 2 bit defines. struct regmap_field
should be able to help here.
You're totally right, we could rewrite the driver to use regmap_field and make
the rest of the differences conditional. In my eyes we end up with two drivers
in one file - but it can be done.
A difference however is that in pm8941 the ps hold behavious (reboot vs power
off) is controlled by this same block. So I have an additional patch that adds
a restart handler here that sets the pmic in the right state before we pull
pshold (but I haven't been able to test it properly).
In pm8xxx this is handled in the pmic misc block and does not belong in this
driver.
[..]
quoted
Maybe if we introduce some vagueness related to interrupts in the dt binding
documentation for pm8xxx we could simply reuse that binding.
I would not say vagueness, we just can say that pm8941 did not have
second interrupt?
I don't like having conditional documentation - it's not only that the second
interrupt is missing, the first one have different meaning. But you're right
that it's a minor thing and can be done.
Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Any reason why we cannot reuse pm8xxx-pwrkey driver? It have been
converted to regmap already.
The boilerplate code is the same,
The boilerplate code is almost 100% :-)
quoted
but configuration registers have different
layout and values written in them are different.
We talk about 3 registers and 2 bit defines. struct regmap_field
should be able to help here.
You're totally right, we could rewrite the driver to use regmap_field and make
the rest of the differences conditional. In my eyes we end up with two drivers
in one file - but it can be done.
A difference however is that in pm8941 the ps hold behavious (reboot vs power
off) is controlled by this same block. So I have an additional patch that adds
a restart handler here that sets the pmic in the right state before we pull
pshold (but I haven't been able to test it properly).
In pm8xxx this is handled in the pmic misc block and does not belong in this
driver.
Ok, Your plan is to bring up support for QPNP power-on PMIC sub function into this
driver. In this case, I agree, it will be cleaner to have separate driver for this.
Regards,
Ivan
On Tue, Oct 7, 2014 at 4:42 PM, Dmitry Torokhov
[off-list ref] wrote:
On Tue, Oct 07, 2014 at 04:30:46PM -0700, Bjorn Andersson wrote:
quoted
On Tue 07 Oct 02:54 PDT 2014, Kiran Padwal wrote:
[..]
quoted
quoted
Shouldn't we unregister input device?
It's allocated with devm_input_allocate_device() so I assumed that it goes away
upon the device being removed. Looking at input_register_device() seems to
confirm that.
Yes, devices allocated with devm_input_allocate_device() will be
unregistered and freed automatically.
Thanks.
Hi Dmitry,
Will you pick this up? (couldn't find it in linux-next...)
Or is there anything else you need from me?
Regards,
Bjorn