* Re: [PATCH v3 2/4] mfd: max8997: handle IRQs using regmap
From: Chanwoo Choi @ 2014-03-18 9:52 UTC (permalink / raw)
To: Robert Baldyga
Cc: sameo, lee.jones, myungjoo.ham, dmitry.torokhov, cooloney,
rpurdie, dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo,
paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
m.szyprowski, k.kozlowski
In-Reply-To: <5322BEDF.4080408@samsung.com>
On 03/14/2014 05:33 PM, Robert Baldyga wrote:
> On 03/13/2014 11:45 AM, Chanwoo Choi wrote:
>> Hi Robert,
>>
>> On 03/13/2014 06:38 PM, Robert Baldyga wrote:
>>> This patch modifies mfd driver to use regmap for handling interrupts.
>>> It allows to simplify irq handling process. This modifications needed
>>> to make small changes in function drivers, which use interrupts.
>>>
>>> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
>
> (...)
>
>>> @@ -468,8 +560,11 @@ static int max8997_suspend(struct device *dev)
>>> struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
>>> struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>>>
>>> - if (device_may_wakeup(dev))
>>> - irq_set_irq_wake(max8997->irq, 1);
>>> + if (device_may_wakeup(dev)) {
>>> + enable_irq_wake(max8997->irq);
>>> + disable_irq(max8997->irq);
>>
>> irq_set_irq_wake() is same as enable_irq_wake().
>
> It's more intuitive name and makes code reading easier.
>
>> Why is it necessary for disable_irq(max8997->irq)?
>
> It's because we don't want to get interrupts before i2c controller will
> be ready. So we disable irq in drivers suspend, and enable in resume.
>
> If some iqr will come before enable_irq() call, it will be noticed, and
> IRQ_PENDING flag will be set. In this case irq will be handled
> immediately after enable_irq() call.
>
> In previous version there was call of max8997_irq_resume() in resume
> function, which caused forced interrupt handling, which has similar effect.
>
OK,
For extcon part,
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Thanks,
Chanwoo Choi
^ permalink raw reply
* Re: [PATCH v2 3/8] input: misc: Add driver for AXP20x Power Enable Key
From: Maxime Ripard @ 2014-03-18 10:15 UTC (permalink / raw)
To: Lee Jones
Cc: Carlo Caione, linux-arm-kernel, linux-sunxi, hdegoede, emilio,
wens, sameo, devicetree, dmitry.torokhov, linux-input, linux-doc,
lgirdwood, broonie
In-Reply-To: <20140318095002.GM25478@lee--X1>
[-- Attachment #1: Type: text/plain, Size: 2048 bytes --]
On Tue, Mar 18, 2014 at 09:50:02AM +0000, Lee Jones wrote:
> > > This patch add support for the Power Enable Key found on MFD AXP202 and
> > > AXP209. Besides the basic support for the button, the driver adds two
> > > entries in sysfs to configure the time delay for power on/off.
> > >
> > > Signed-off-by: Carlo Caione <carlo@caione.org>
> > > ---
> > > drivers/input/misc/Kconfig | 11 ++
> > > drivers/input/misc/Makefile | 1 +
> > > drivers/input/misc/axp20x-pek.c | 267 ++++++++++++++++++++++++++++++++++++++++
> > > 3 files changed, 279 insertions(+)
> > > create mode 100644 drivers/input/misc/axp20x-pek.c
> >
> > From what I understood of the MFD framework, you usually have a MFD
> > core driver that gets loaded from the DT and instantiate its various
> > functions through sub-devices, that are registered through
> > mfd_add_devices, and the drivers for these sub-devices are supported
> > in sub-drivers that are located in the driver/mfd, alongside the core
> > driver.
> >
> > I believe that such a pattern allows for two interesting things:
> > - You don't have to search around the whole kernel tree to find
> > where a given sub-feature is supported.
> > - You don't have to cripple your DT with instantiation of all the
> > subcomponents, while you only really have one device.
> >
> > Do you have a reason for not following this pattern?
>
> Sorry Maxime, this is not the case.
>
> If an MFD contains Regulators and USB & GPIO Controllers, I'd expect
> to see the device represented in the following way:
>
> drivers/mfd/<id>.c
> drivers/{gpio,pinctrl}/{gpio,pinctrl}-<id>.c
> drivers/regulator/<id>-regulator.c
> drivers/usb/host/<id>.c
Oh, ok. Nevermind then :)
Just out of curiosity, some drivers at least seem to follow that trend
in drivers/mfd, is there any reason for this (other than historical) ?
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH 1/5] drivers: input: keyboard: st-keyscan: add keyscan driver
From: Gabriel Fernandez @ 2014-03-18 10:25 UTC (permalink / raw)
To: Lee Jones
Cc: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely,
devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Giuseppe Condorelli
In-Reply-To: <20140314104222.GB3432@lee--X1>
Hi Lee,
On 03/14/2014 11:42 AM, Lee Jones wrote:
>>> Sorry for the delay. It was a hectic week last week.
>>>
>>> As promised:
>>>
>>>> This patch adds ST Keyscan driver to use the keypad hw a subset
>>>> of ST boards provide. Specific board setup will be put in the
>>>> given dt.
>>>>
>>>> Signed-off-by: Giuseppe Condorelli<giuseppe.condorelli@st.com>
>>>> Signed-off-by: Gabriel Fernandez<gabriel.fernandez@st.com>
>>> Are you sure these are in the correct order?
>> ok i change the order
> I'm not saying they are in the wrong order, I'm just asking. Who wrote
> the patch? Has it changed since?
Sorry...
I wrote the patch, then Guiseppe has changed and tested, and I re-modifiedit
>>>> +- linux,keymap: The keymap for keys as described in the binding document
>>>> + devicetree/bindings/input/matrix-keymap.txt.
>>>> +
>>>> +- keypad,num-rows: Number of row lines connected to the keypad controller.
>>>> +
>>>> +- keypad,num-columns: Number of column lines connected to the keypad
>>>> + controller.
>>>> +
>>>> +- st,debounce_us: Debouncing interval time in microseconds
>>> I'm sure there will be a shared binding for de-bounce.
>>>
>>> If not, there certainly should be.
>> you want to refer to "debounce-interval" ?
> That sounds more generic, but if it's not documented as such, then
> please consider doing so.
>
>>> +Example:
>>> +
>>> +keyscan: keyscan@fe4b0000 {
>>> + compatible = "st,keypad";
>>> Is there any way we can make this more specific to _this_ IP?
>> for my knowledge this IP is the same for stixxxx platform.
> So st,stix-keypad, or st,sti4x-keypad?
>
> I'm just thinking about future proofing the architecture. What if ST
> released stj which has a different keypad IP?
After discussing internally with st "st,sti-keyscan" is better
>>>> +struct keyscan_priv {
>>>> + void __iomem *base;
>>>> + int irq;
>>>> + struct clk *clk;
>>>> + struct input_dev *input_dev;
>>>> + struct keypad_platform_data *config;
>>>> + unsigned int last_state;
>>>> + u32 keycodes[ST_KEYSCAN_MAXKEYS];
>>> Seems odd to limit this. Can't the information come from DT
>>> i.e. keypad,num-rows and keypad,num-columns?
>>>
>> i 'll rename 'num_out_pads' into 'n_rows' and 'num_in_pads' into
>> 'n_cols'
> That's not quite what I meant, I mean can't ST_KEY_MAXKEYS be more
> dynamic and be obtained from (keypad,num-rows * keypad,num-columns)?
ok
^ permalink raw reply
* Re: [PATCH v2 3/8] input: misc: Add driver for AXP20x Power Enable Key
From: Lee Jones @ 2014-03-18 10:58 UTC (permalink / raw)
To: Maxime Ripard
Cc: Carlo Caione, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
hdegoede-H+wXaHxf7aLQT0dZR+AlfA, emilio-0Z03zUJReD5OxF6Tv1QG9Q,
wens-jdAy2FN1RRM, sameo-VuQAYsv1563Yd54FQh9/CA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20140318101554.GZ27873@lukather>
> > > > This patch add support for the Power Enable Key found on MFD AXP202 and
> > > > AXP209. Besides the basic support for the button, the driver adds two
> > > > entries in sysfs to configure the time delay for power on/off.
> > > >
> > > > Signed-off-by: Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
> > > > ---
> > > > drivers/input/misc/Kconfig | 11 ++
> > > > drivers/input/misc/Makefile | 1 +
> > > > drivers/input/misc/axp20x-pek.c | 267 ++++++++++++++++++++++++++++++++++++++++
> > > > 3 files changed, 279 insertions(+)
> > > > create mode 100644 drivers/input/misc/axp20x-pek.c
> > >
> > > From what I understood of the MFD framework, you usually have a MFD
> > > core driver that gets loaded from the DT and instantiate its various
> > > functions through sub-devices, that are registered through
> > > mfd_add_devices, and the drivers for these sub-devices are supported
> > > in sub-drivers that are located in the driver/mfd, alongside the core
> > > driver.
> > >
> > > I believe that such a pattern allows for two interesting things:
> > > - You don't have to search around the whole kernel tree to find
> > > where a given sub-feature is supported.
> > > - You don't have to cripple your DT with instantiation of all the
> > > subcomponents, while you only really have one device.
> > >
> > > Do you have a reason for not following this pattern?
> >
> > Sorry Maxime, this is not the case.
> >
> > If an MFD contains Regulators and USB & GPIO Controllers, I'd expect
> > to see the device represented in the following way:
> >
> > drivers/mfd/<id>.c
> > drivers/{gpio,pinctrl}/{gpio,pinctrl}-<id>.c
> > drivers/regulator/<id>-regulator.c
> > drivers/usb/host/<id>.c
>
> Oh, ok. Nevermind then :)
>
> Just out of curiosity, some drivers at least seem to follow that trend
> in drivers/mfd, is there any reason for this (other than historical) ?
Would you mind providing an example?
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH 1/5] drivers: input: keyboard: st-keyscan: add keyscan driver
From: Lee Jones @ 2014-03-18 11:01 UTC (permalink / raw)
To: Gabriel Fernandez
Cc: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely,
devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Giuseppe Condorelli
In-Reply-To: <53281F1E.7010403@st.com>
> >>>Sorry for the delay. It was a hectic week last week.
> >>>
> >>>As promised:
> >>>
> >>>>This patch adds ST Keyscan driver to use the keypad hw a subset
> >>>>of ST boards provide. Specific board setup will be put in the
> >>>>given dt.
> >>>>
> >>>>Signed-off-by: Giuseppe Condorelli<giuseppe.condorelli@st.com>
> >>>>Signed-off-by: Gabriel Fernandez<gabriel.fernandez@st.com>
> >>>Are you sure these are in the correct order?
> >>ok i change the order
> >I'm not saying they are in the wrong order, I'm just asking. Who wrote
> >the patch? Has it changed since?
> Sorry...
> I wrote the patch, then Guiseppe has changed and tested, and I re-modifiedit
Ah, then it starts to get very complicated. :)
If you wrote the patch, you need to be at the top of the list.
<snip>
> >>>+keyscan: keyscan@fe4b0000 {
> >>>+ compatible = "st,keypad";
> >>>Is there any way we can make this more specific to _this_ IP?
> >>for my knowledge this IP is the same for stixxxx platform.
> >So st,stix-keypad, or st,sti4x-keypad?
> >
> >I'm just thinking about future proofing the architecture. What if ST
> >released stj which has a different keypad IP?
> After discussing internally with st "st,sti-keyscan" is better
Perfect.
<snip>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH] Input: synaptics add manual min/max quirk
From: Benjamin Tissoires @ 2014-03-18 12:59 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Dmitry Torokhov, Christopher Heiny, Andrew Duggan, linux-input,
linux-kernel@vger.kernel.org, Peter Hutterer,
Stephen Chandler Paul, Hans de Goede
In-Reply-To: <1394207364-4235-1-git-send-email-benjamin.tissoires@redhat.com>
On Fri, Mar 7, 2014 at 10:49 AM, Benjamin Tissoires
<benjamin.tissoires@redhat.com> wrote:
> The new Lenovo Haswell series (-40's) contains a new Synaptics touchpad.
> However, these new Synaptics devices report bad axis ranges.
> Under Windows, it is not a problem because the Windows driver uses RMI4
> over SMBus to talk to the device. Under Linux, we are using the PS/2
> fallback interface and it occurs the reported ranges are wrong.
>
> Of course, it would be too easy to have only one range for the whole
> series, each touchpad seems to be calibrated in a different way.
>
> We can not use SMBus to get the actual range because I suspect the firmware
> will switch into the SMBus mode and stop talking through PS/2 (this is the
> case for hybrid HID over I2C / PS/2 Synaptics touchpads).
>
> So as a temporary solution (until RMI4 land into upstream), start a new
> list of quirks with the min/max manually set.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> CC: stable@vger.kernel.org
> ---
>
> Hi Dmitry,
>
> Well, this work is part of a (big) attempt to support the new touchpads
> Lenovo put in its latest series.
> Those new laptops have lost the buttons associated to the trackstick and are
> what we call "clickpad".
> Things would be easy if:
> 1. the PS/2 firmware did not lied about the actual range of the axis
> 2. on some install (mine) the DMI matching in udev would not have been broken
> 3. we did not have to fix a lot of stuff in Xorg / libinput / wayland
>
> This patch fixes 1.
>
> Matthew Garrett fixed 2. -> https://patchwork.kernel.org/patch/3704401/
>
> 3. is heavily working as shown by this tracker bug: https://bugs.freedesktop.org/show_bug.cgi?id=73158
>
> I put the 'stable' marker, feel free to remove it if you don't think it should
> be there, but I really think this should also be backported to have something
> working in current distros.
Dmitry, are there any chances that this one and the one Hans submitted
shortly after [1] will be considered for 3.15?
Cheers,
Benjamin
[1] https://patchwork.kernel.org/patch/3798011/
> drivers/input/mouse/synaptics.c | 43 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 43 insertions(+)
>
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index 26386f9..ff6a4cf 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -67,6 +67,8 @@
> #define X_MAX_POSITIVE 8176
> #define Y_MAX_POSITIVE 8176
>
> +static int *quirk_min_max = NULL;
> +
> /*****************************************************************************
> * Stuff we need even when we do not want native Synaptics support
> ****************************************************************************/
> @@ -302,6 +304,13 @@ static int synaptics_resolution(struct psmouse *psmouse)
> }
> }
>
> + if (quirk_min_max) {
> + priv->x_min = quirk_min_max[0];
> + priv->x_max = quirk_min_max[1];
> + priv->y_min = quirk_min_max[2];
> + priv->y_max = quirk_min_max[3];
> + }
> +
> return 0;
> }
>
> @@ -1485,10 +1494,44 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
> { }
> };
>
> +static const struct dmi_system_id min_max_dmi_table[] __initconst = {
> +#if defined(CONFIG_DMI)
> + {
> + /* Lenovo ThinkPad Helix */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
> + },
> + .driver_data = (int []){1024, 5052, 2258, 4832},
> + },
> + {
> + /* Lenovo ThinkPad T440s */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
> + },
> + .driver_data = (int []){1024, 5112, 2024, 4832},
> + },
> + {
> + /* Lenovo ThinkPad T540p */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
> + },
> + .driver_data = (int []){1024, 5056, 2058, 4832},
> + },
> +#endif
> + { }
> +};
> +
> void __init synaptics_module_init(void)
> {
> + const struct dmi_system_id *min_max_dmi;
> impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
> broken_olpc_ec = dmi_check_system(olpc_dmi_table);
> + min_max_dmi = dmi_first_match(min_max_dmi_table);
> + if (min_max_dmi)
> + quirk_min_max = (int *)min_max_dmi->driver_data;
> }
>
> static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
> --
> 1.8.5.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 3/8] input: misc: Add driver for AXP20x Power Enable Key
From: Maxime Ripard @ 2014-03-18 14:03 UTC (permalink / raw)
To: Lee Jones
Cc: Carlo Caione, linux-arm-kernel, linux-sunxi, hdegoede, emilio,
wens, sameo, devicetree, dmitry.torokhov, linux-input, linux-doc,
lgirdwood, broonie
In-Reply-To: <20140318105851.GO25478@lee--X1>
[-- Attachment #1: Type: text/plain, Size: 2389 bytes --]
On Tue, Mar 18, 2014 at 10:58:51AM +0000, Lee Jones wrote:
> > > > > This patch add support for the Power Enable Key found on MFD AXP202 and
> > > > > AXP209. Besides the basic support for the button, the driver adds two
> > > > > entries in sysfs to configure the time delay for power on/off.
> > > > >
> > > > > Signed-off-by: Carlo Caione <carlo@caione.org>
> > > > > ---
> > > > > drivers/input/misc/Kconfig | 11 ++
> > > > > drivers/input/misc/Makefile | 1 +
> > > > > drivers/input/misc/axp20x-pek.c | 267 ++++++++++++++++++++++++++++++++++++++++
> > > > > 3 files changed, 279 insertions(+)
> > > > > create mode 100644 drivers/input/misc/axp20x-pek.c
> > > >
> > > > From what I understood of the MFD framework, you usually have a MFD
> > > > core driver that gets loaded from the DT and instantiate its various
> > > > functions through sub-devices, that are registered through
> > > > mfd_add_devices, and the drivers for these sub-devices are supported
> > > > in sub-drivers that are located in the driver/mfd, alongside the core
> > > > driver.
> > > >
> > > > I believe that such a pattern allows for two interesting things:
> > > > - You don't have to search around the whole kernel tree to find
> > > > where a given sub-feature is supported.
> > > > - You don't have to cripple your DT with instantiation of all the
> > > > subcomponents, while you only really have one device.
> > > >
> > > > Do you have a reason for not following this pattern?
> > >
> > > Sorry Maxime, this is not the case.
> > >
> > > If an MFD contains Regulators and USB & GPIO Controllers, I'd expect
> > > to see the device represented in the following way:
> > >
> > > drivers/mfd/<id>.c
> > > drivers/{gpio,pinctrl}/{gpio,pinctrl}-<id>.c
> > > drivers/regulator/<id>-regulator.c
> > > drivers/usb/host/<id>.c
> >
> > Oh, ok. Nevermind then :)
> >
> > Just out of curiosity, some drivers at least seem to follow that trend
> > in drivers/mfd, is there any reason for this (other than historical) ?
>
> Would you mind providing an example?
I was under this impression given the naming scheme that they were
using. Looking into it just proved me how wrong I was :)
Sorry for the noise.
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH 0/3] Remove obsolete tnetv107x drivers
From: Arnd Bergmann @ 2014-03-18 14:55 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, davinci-linux-open-source, Sekhar Nori,
Arnd Bergmann, Mark Brown, linux-spi, Samuel Ortiz, Lee Jones,
Dmitry Torokhov, linux-input
I have applied the platform removal patch with the Ack
from Kevin and Sekhar. Please apply these other patches
through the input/mfd/spi trees.
Arnd Bergmann (3):
spi: remove obsolete spi-ti-ssp driver
mfd: remove obsolete ti-ssp driver
input: remove obsolete tnetv107x drivers
drivers/input/keyboard/Kconfig | 10 -
drivers/input/keyboard/Makefile | 1 -
drivers/input/keyboard/tnetv107x-keypad.c | 329 ---------------------
drivers/input/touchscreen/Kconfig | 9 -
drivers/input/touchscreen/Makefile | 1 -
drivers/input/touchscreen/tnetv107x-ts.c | 384 ------------------------
drivers/mfd/Kconfig | 11 -
drivers/mfd/Makefile | 1 -
drivers/mfd/ti-ssp.c | 465 ------------------------------
drivers/spi/Kconfig | 7 -
drivers/spi/Makefile | 1 -
drivers/spi/spi-ti-ssp.c | 378 ------------------------
12 files changed, 1597 deletions(-)
delete mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
delete mode 100644 drivers/input/touchscreen/tnetv107x-ts.c
delete mode 100644 drivers/mfd/ti-ssp.c
delete mode 100644 drivers/spi/spi-ti-ssp.c
Cc: Mark Brown <broonie@kernel.org>
Cc: linux-spi@vger.kernel.org
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org
--
1.8.3.2
^ permalink raw reply
* [PATCH 3/3] input: remove obsolete tnetv107x drivers
From: Arnd Bergmann @ 2014-03-18 14:56 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, davinci-linux-open-source, Sekhar Nori,
Arnd Bergmann, Dmitry Torokhov, linux-input
In-Reply-To: <1395154561-1199121-1-git-send-email-arnd@arndb.de>
The tnetv107x platform is getting removed, so the touchscreen
and keypad drivers for this platform will no longer be needed
either.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Sekhar Nori <nsekhar@ti.com>
Acked-by: Kevin Hilman <khilman@linaro.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org
---
drivers/input/keyboard/Kconfig | 10 -
drivers/input/keyboard/Makefile | 1 -
drivers/input/keyboard/tnetv107x-keypad.c | 329 -------------------------
drivers/input/touchscreen/Kconfig | 9 -
drivers/input/touchscreen/Makefile | 1 -
drivers/input/touchscreen/tnetv107x-ts.c | 384 ------------------------------
6 files changed, 734 deletions(-)
delete mode 100644 drivers/input/keyboard/tnetv107x-keypad.c
delete mode 100644 drivers/input/touchscreen/tnetv107x-ts.c
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a673c9f..935dcaf 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -595,16 +595,6 @@ config KEYBOARD_TC3589X
To compile this driver as a module, choose M here: the
module will be called tc3589x-keypad.
-config KEYBOARD_TNETV107X
- tristate "TI TNETV107X keypad support"
- depends on ARCH_DAVINCI_TNETV107X
- select INPUT_MATRIXKMAP
- help
- Say Y here if you want to use the TNETV107X keypad.
-
- To compile this driver as a module, choose M here: the
- module will be called tnetv107x-keypad.
-
config KEYBOARD_TWL4030
tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
depends on TWL4030_CORE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a699b61..81014d9 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -53,7 +53,6 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
-obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
deleted file mode 100644
index 086511c..0000000
--- a/drivers/input/keyboard/tnetv107x-keypad.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Texas Instruments TNETV107X Keypad Driver
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/module.h>
-
-#define BITS(x) (BIT(x) - 1)
-
-#define KEYPAD_ROWS 9
-#define KEYPAD_COLS 9
-
-#define DEBOUNCE_MIN 0x400ul
-#define DEBOUNCE_MAX 0x3ffffffful
-
-struct keypad_regs {
- u32 rev;
- u32 mode;
- u32 mask;
- u32 pol;
- u32 dclock;
- u32 rclock;
- u32 stable_cnt;
- u32 in_en;
- u32 out;
- u32 out_en;
- u32 in;
- u32 lock;
- u32 pres[3];
-};
-
-#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg)
-#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg)
-
-struct keypad_data {
- struct input_dev *input_dev;
- struct resource *res;
- struct keypad_regs __iomem *regs;
- struct clk *clk;
- struct device *dev;
- spinlock_t lock;
- int irq_press;
- int irq_release;
- int rows, cols, row_shift;
- int debounce_ms, active_low;
- u32 prev_keys[3];
- unsigned short keycodes[];
-};
-
-static irqreturn_t keypad_irq(int irq, void *data)
-{
- struct keypad_data *kp = data;
- int i, bit, val, row, col, code;
- unsigned long flags;
- u32 curr_keys[3];
- u32 change;
-
- spin_lock_irqsave(&kp->lock, flags);
-
- memset(curr_keys, 0, sizeof(curr_keys));
- if (irq == kp->irq_press)
- for (i = 0; i < 3; i++)
- curr_keys[i] = keypad_read(kp, pres[i]);
-
- for (i = 0; i < 3; i++) {
- change = curr_keys[i] ^ kp->prev_keys[i];
-
- while (change) {
- bit = fls(change) - 1;
- change ^= BIT(bit);
- val = curr_keys[i] & BIT(bit);
- bit += i * 32;
- row = bit / KEYPAD_COLS;
- col = bit % KEYPAD_COLS;
-
- code = MATRIX_SCAN_CODE(row, col, kp->row_shift);
- input_event(kp->input_dev, EV_MSC, MSC_SCAN, code);
- input_report_key(kp->input_dev, kp->keycodes[code],
- val);
- }
- }
- input_sync(kp->input_dev);
- memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys));
-
- if (irq == kp->irq_press)
- keypad_write(kp, lock, 0); /* Allow hardware updates */
-
- spin_unlock_irqrestore(&kp->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-static int keypad_start(struct input_dev *dev)
-{
- struct keypad_data *kp = input_get_drvdata(dev);
- unsigned long mask, debounce, clk_rate_khz;
- unsigned long flags;
-
- clk_enable(kp->clk);
- clk_rate_khz = clk_get_rate(kp->clk) / 1000;
-
- spin_lock_irqsave(&kp->lock, flags);
-
- /* Initialize device registers */
- keypad_write(kp, mode, 0);
-
- mask = BITS(kp->rows) << KEYPAD_COLS;
- mask |= BITS(kp->cols);
- keypad_write(kp, mask, ~mask);
-
- keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff);
- keypad_write(kp, stable_cnt, 3);
-
- debounce = kp->debounce_ms * clk_rate_khz;
- debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX);
- keypad_write(kp, dclock, debounce);
- keypad_write(kp, rclock, 4 * debounce);
-
- keypad_write(kp, in_en, 1);
-
- spin_unlock_irqrestore(&kp->lock, flags);
-
- return 0;
-}
-
-static void keypad_stop(struct input_dev *dev)
-{
- struct keypad_data *kp = input_get_drvdata(dev);
-
- synchronize_irq(kp->irq_press);
- synchronize_irq(kp->irq_release);
- clk_disable(kp->clk);
-}
-
-static int keypad_probe(struct platform_device *pdev)
-{
- const struct matrix_keypad_platform_data *pdata;
- const struct matrix_keymap_data *keymap_data;
- struct device *dev = &pdev->dev;
- struct keypad_data *kp;
- int error = 0, sz, row_shift;
- u32 rev = 0;
-
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata) {
- dev_err(dev, "cannot find device data\n");
- return -EINVAL;
- }
-
- keymap_data = pdata->keymap_data;
- if (!keymap_data) {
- dev_err(dev, "cannot find keymap data\n");
- return -EINVAL;
- }
-
- row_shift = get_count_order(pdata->num_col_gpios);
- sz = offsetof(struct keypad_data, keycodes);
- sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]);
- kp = kzalloc(sz, GFP_KERNEL);
- if (!kp) {
- dev_err(dev, "cannot allocate device info\n");
- return -ENOMEM;
- }
-
- kp->dev = dev;
- kp->rows = pdata->num_row_gpios;
- kp->cols = pdata->num_col_gpios;
- kp->row_shift = row_shift;
- platform_set_drvdata(pdev, kp);
- spin_lock_init(&kp->lock);
-
- kp->irq_press = platform_get_irq_byname(pdev, "press");
- kp->irq_release = platform_get_irq_byname(pdev, "release");
- if (kp->irq_press < 0 || kp->irq_release < 0) {
- dev_err(dev, "cannot determine device interrupts\n");
- error = -ENODEV;
- goto error_res;
- }
-
- kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!kp->res) {
- dev_err(dev, "cannot determine register area\n");
- error = -ENODEV;
- goto error_res;
- }
-
- if (!request_mem_region(kp->res->start, resource_size(kp->res),
- pdev->name)) {
- dev_err(dev, "cannot claim register memory\n");
- kp->res = NULL;
- error = -EINVAL;
- goto error_res;
- }
-
- kp->regs = ioremap(kp->res->start, resource_size(kp->res));
- if (!kp->regs) {
- dev_err(dev, "cannot map register memory\n");
- error = -ENOMEM;
- goto error_map;
- }
-
- kp->clk = clk_get(dev, NULL);
- if (IS_ERR(kp->clk)) {
- dev_err(dev, "cannot claim device clock\n");
- error = PTR_ERR(kp->clk);
- goto error_clk;
- }
-
- error = request_threaded_irq(kp->irq_press, NULL, keypad_irq,
- IRQF_ONESHOT, dev_name(dev), kp);
- if (error < 0) {
- dev_err(kp->dev, "Could not allocate keypad press key irq\n");
- goto error_irq_press;
- }
-
- error = request_threaded_irq(kp->irq_release, NULL, keypad_irq,
- IRQF_ONESHOT, dev_name(dev), kp);
- if (error < 0) {
- dev_err(kp->dev, "Could not allocate keypad release key irq\n");
- goto error_irq_release;
- }
-
- kp->input_dev = input_allocate_device();
- if (!kp->input_dev) {
- dev_err(dev, "cannot allocate input device\n");
- error = -ENOMEM;
- goto error_input;
- }
-
- kp->input_dev->name = pdev->name;
- kp->input_dev->dev.parent = &pdev->dev;
- kp->input_dev->open = keypad_start;
- kp->input_dev->close = keypad_stop;
-
- clk_enable(kp->clk);
- rev = keypad_read(kp, rev);
- kp->input_dev->id.bustype = BUS_HOST;
- kp->input_dev->id.product = ((rev >> 8) & 0x07);
- kp->input_dev->id.version = ((rev >> 16) & 0xfff);
- clk_disable(kp->clk);
-
- error = matrix_keypad_build_keymap(keymap_data, NULL,
- kp->rows, kp->cols,
- kp->keycodes, kp->input_dev);
- if (error) {
- dev_err(dev, "Failed to build keymap\n");
- goto error_reg;
- }
-
- if (!pdata->no_autorepeat)
- kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
- input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN);
-
- input_set_drvdata(kp->input_dev, kp);
-
- error = input_register_device(kp->input_dev);
- if (error < 0) {
- dev_err(dev, "Could not register input device\n");
- goto error_reg;
- }
-
- return 0;
-
-
-error_reg:
- input_free_device(kp->input_dev);
-error_input:
- free_irq(kp->irq_release, kp);
-error_irq_release:
- free_irq(kp->irq_press, kp);
-error_irq_press:
- clk_put(kp->clk);
-error_clk:
- iounmap(kp->regs);
-error_map:
- release_mem_region(kp->res->start, resource_size(kp->res));
-error_res:
- kfree(kp);
- return error;
-}
-
-static int keypad_remove(struct platform_device *pdev)
-{
- struct keypad_data *kp = platform_get_drvdata(pdev);
-
- free_irq(kp->irq_press, kp);
- free_irq(kp->irq_release, kp);
- input_unregister_device(kp->input_dev);
- clk_put(kp->clk);
- iounmap(kp->regs);
- release_mem_region(kp->res->start, resource_size(kp->res));
- kfree(kp);
-
- return 0;
-}
-
-static struct platform_driver keypad_driver = {
- .probe = keypad_probe,
- .remove = keypad_remove,
- .driver.name = "tnetv107x-keypad",
- .driver.owner = THIS_MODULE,
-};
-module_platform_driver(keypad_driver);
-
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_DESCRIPTION("TNETV107X Keypad Driver");
-MODULE_ALIAS("platform:tnetv107x-keypad");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 07e9e82..68edc9d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -514,15 +514,6 @@ config TOUCHSCREEN_MIGOR
To compile this driver as a module, choose M here: the
module will be called migor_ts.
-config TOUCHSCREEN_TNETV107X
- tristate "TI TNETV107X touchscreen support"
- depends on ARCH_DAVINCI_TNETV107X
- help
- Say Y here if you want to use the TNETV107X touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called tnetv107x-ts.
-
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 62801f2..4bc954b 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
-obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
deleted file mode 100644
index c47827a..0000000
--- a/drivers/input/touchscreen/tnetv107x-ts.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Texas Instruments TNETV107X Touchscreen Driver
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-
-#include <mach/tnetv107x.h>
-
-#define TSC_PENUP_POLL (HZ / 5)
-#define IDLE_TIMEOUT 100 /* msec */
-
-/*
- * The first and last samples of a touch interval are usually garbage and need
- * to be filtered out with these devices. The following definitions control
- * the number of samples skipped.
- */
-#define TSC_HEAD_SKIP 1
-#define TSC_TAIL_SKIP 1
-#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
-#define TSC_SAMPLES (TSC_SKIP + 1)
-
-/* Register Offsets */
-struct tsc_regs {
- u32 rev;
- u32 tscm;
- u32 bwcm;
- u32 swc;
- u32 adcchnl;
- u32 adcdata;
- u32 chval[4];
-};
-
-/* TSC Mode Configuration Register (tscm) bits */
-#define WMODE BIT(0)
-#define TSKIND BIT(1)
-#define ZMEASURE_EN BIT(2)
-#define IDLE BIT(3)
-#define TSC_EN BIT(4)
-#define STOP BIT(5)
-#define ONE_SHOT BIT(6)
-#define SINGLE BIT(7)
-#define AVG BIT(8)
-#define AVGNUM(x) (((x) & 0x03) << 9)
-#define PVSTC(x) (((x) & 0x07) << 11)
-#define PON BIT(14)
-#define PONBG BIT(15)
-#define AFERST BIT(16)
-
-/* ADC DATA Capture Register bits */
-#define DATA_VALID BIT(16)
-
-/* Register Access Macros */
-#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg)
-#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg);
-#define tsc_set_bits(ts, reg, val) \
- tsc_write(ts, reg, tsc_read(ts, reg) | (val))
-#define tsc_clr_bits(ts, reg, val) \
- tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
-
-struct sample {
- int x, y, p;
-};
-
-struct tsc_data {
- struct input_dev *input_dev;
- struct resource *res;
- struct tsc_regs __iomem *regs;
- struct timer_list timer;
- spinlock_t lock;
- struct clk *clk;
- struct device *dev;
- int sample_count;
- struct sample samples[TSC_SAMPLES];
- int tsc_irq;
-};
-
-static int tsc_read_sample(struct tsc_data *ts, struct sample* sample)
-{
- int x, y, z1, z2, t, p = 0;
- u32 val;
-
- val = tsc_read(ts, chval[0]);
- if (val & DATA_VALID)
- x = val & 0xffff;
- else
- return -EINVAL;
-
- y = tsc_read(ts, chval[1]) & 0xffff;
- z1 = tsc_read(ts, chval[2]) & 0xffff;
- z2 = tsc_read(ts, chval[3]) & 0xffff;
-
- if (z1) {
- t = ((600 * x) * (z2 - z1));
- p = t / (u32) (z1 << 12);
- if (p < 0)
- p = 0;
- }
-
- sample->x = x;
- sample->y = y;
- sample->p = p;
-
- return 0;
-}
-
-static void tsc_poll(unsigned long data)
-{
- struct tsc_data *ts = (struct tsc_data *)data;
- unsigned long flags;
- int i, val, x, y, p;
-
- spin_lock_irqsave(&ts->lock, flags);
-
- if (ts->sample_count >= TSC_SKIP) {
- input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
- input_report_key(ts->input_dev, BTN_TOUCH, 0);
- input_sync(ts->input_dev);
- } else if (ts->sample_count > 0) {
- /*
- * A touch event lasted less than our skip count. Salvage and
- * report anyway.
- */
- for (i = 0, val = 0; i < ts->sample_count; i++)
- val += ts->samples[i].x;
- x = val / ts->sample_count;
-
- for (i = 0, val = 0; i < ts->sample_count; i++)
- val += ts->samples[i].y;
- y = val / ts->sample_count;
-
- for (i = 0, val = 0; i < ts->sample_count; i++)
- val += ts->samples[i].p;
- p = val / ts->sample_count;
-
- input_report_abs(ts->input_dev, ABS_X, x);
- input_report_abs(ts->input_dev, ABS_Y, y);
- input_report_abs(ts->input_dev, ABS_PRESSURE, p);
- input_report_key(ts->input_dev, BTN_TOUCH, 1);
- input_sync(ts->input_dev);
- }
-
- ts->sample_count = 0;
-
- spin_unlock_irqrestore(&ts->lock, flags);
-}
-
-static irqreturn_t tsc_irq(int irq, void *dev_id)
-{
- struct tsc_data *ts = (struct tsc_data *)dev_id;
- struct sample *sample;
- int index;
-
- spin_lock(&ts->lock);
-
- index = ts->sample_count % TSC_SAMPLES;
- sample = &ts->samples[index];
- if (tsc_read_sample(ts, sample) < 0)
- goto out;
-
- if (++ts->sample_count >= TSC_SKIP) {
- index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
- sample = &ts->samples[index];
-
- input_report_abs(ts->input_dev, ABS_X, sample->x);
- input_report_abs(ts->input_dev, ABS_Y, sample->y);
- input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p);
- if (ts->sample_count == TSC_SKIP)
- input_report_key(ts->input_dev, BTN_TOUCH, 1);
- input_sync(ts->input_dev);
- }
- mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
-out:
- spin_unlock(&ts->lock);
- return IRQ_HANDLED;
-}
-
-static int tsc_start(struct input_dev *dev)
-{
- struct tsc_data *ts = input_get_drvdata(dev);
- unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT);
- u32 val;
-
- clk_enable(ts->clk);
-
- /* Go to idle mode, before any initialization */
- while (time_after(timeout, jiffies)) {
- if (tsc_read(ts, tscm) & IDLE)
- break;
- }
-
- if (time_before(timeout, jiffies)) {
- dev_warn(ts->dev, "timeout waiting for idle\n");
- clk_disable(ts->clk);
- return -EIO;
- }
-
- /* Configure TSC Control register*/
- val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
- tsc_write(ts, tscm, val);
-
- /* Bring TSC out of reset: Clear AFE reset bit */
- val &= ~(AFERST);
- tsc_write(ts, tscm, val);
-
- /* Configure all pins for hardware control*/
- tsc_write(ts, bwcm, 0);
-
- /* Finally enable the TSC */
- tsc_set_bits(ts, tscm, TSC_EN);
-
- return 0;
-}
-
-static void tsc_stop(struct input_dev *dev)
-{
- struct tsc_data *ts = input_get_drvdata(dev);
-
- tsc_clr_bits(ts, tscm, TSC_EN);
- synchronize_irq(ts->tsc_irq);
- del_timer_sync(&ts->timer);
- clk_disable(ts->clk);
-}
-
-static int tsc_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct tsc_data *ts;
- int error = 0;
- u32 rev = 0;
-
- ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
- if (!ts) {
- dev_err(dev, "cannot allocate device info\n");
- return -ENOMEM;
- }
-
- ts->dev = dev;
- spin_lock_init(&ts->lock);
- setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
- platform_set_drvdata(pdev, ts);
-
- ts->tsc_irq = platform_get_irq(pdev, 0);
- if (ts->tsc_irq < 0) {
- dev_err(dev, "cannot determine device interrupt\n");
- error = -ENODEV;
- goto error_res;
- }
-
- ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!ts->res) {
- dev_err(dev, "cannot determine register area\n");
- error = -ENODEV;
- goto error_res;
- }
-
- if (!request_mem_region(ts->res->start, resource_size(ts->res),
- pdev->name)) {
- dev_err(dev, "cannot claim register memory\n");
- ts->res = NULL;
- error = -EINVAL;
- goto error_res;
- }
-
- ts->regs = ioremap(ts->res->start, resource_size(ts->res));
- if (!ts->regs) {
- dev_err(dev, "cannot map register memory\n");
- error = -ENOMEM;
- goto error_map;
- }
-
- ts->clk = clk_get(dev, NULL);
- if (IS_ERR(ts->clk)) {
- dev_err(dev, "cannot claim device clock\n");
- error = PTR_ERR(ts->clk);
- goto error_clk;
- }
-
- error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, IRQF_ONESHOT,
- dev_name(dev), ts);
- if (error < 0) {
- dev_err(ts->dev, "Could not allocate ts irq\n");
- goto error_irq;
- }
-
- ts->input_dev = input_allocate_device();
- if (!ts->input_dev) {
- dev_err(dev, "cannot allocate input device\n");
- error = -ENOMEM;
- goto error_input;
- }
- input_set_drvdata(ts->input_dev, ts);
-
- ts->input_dev->name = pdev->name;
- ts->input_dev->id.bustype = BUS_HOST;
- ts->input_dev->dev.parent = &pdev->dev;
- ts->input_dev->open = tsc_start;
- ts->input_dev->close = tsc_stop;
-
- clk_enable(ts->clk);
- rev = tsc_read(ts, rev);
- ts->input_dev->id.product = ((rev >> 8) & 0x07);
- ts->input_dev->id.version = ((rev >> 16) & 0xfff);
- clk_disable(ts->clk);
-
- __set_bit(EV_KEY, ts->input_dev->evbit);
- __set_bit(EV_ABS, ts->input_dev->evbit);
- __set_bit(BTN_TOUCH, ts->input_dev->keybit);
-
- input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0);
- input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0);
- input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
-
- error = input_register_device(ts->input_dev);
- if (error < 0) {
- dev_err(dev, "failed input device registration\n");
- goto error_reg;
- }
-
- return 0;
-
-error_reg:
- input_free_device(ts->input_dev);
-error_input:
- free_irq(ts->tsc_irq, ts);
-error_irq:
- clk_put(ts->clk);
-error_clk:
- iounmap(ts->regs);
-error_map:
- release_mem_region(ts->res->start, resource_size(ts->res));
-error_res:
- kfree(ts);
-
- return error;
-}
-
-static int tsc_remove(struct platform_device *pdev)
-{
- struct tsc_data *ts = platform_get_drvdata(pdev);
-
- input_unregister_device(ts->input_dev);
- free_irq(ts->tsc_irq, ts);
- clk_put(ts->clk);
- iounmap(ts->regs);
- release_mem_region(ts->res->start, resource_size(ts->res));
- kfree(ts);
-
- return 0;
-}
-
-static struct platform_driver tsc_driver = {
- .probe = tsc_probe,
- .remove = tsc_remove,
- .driver.name = "tnetv107x-ts",
- .driver.owner = THIS_MODULE,
-};
-module_platform_driver(tsc_driver);
-
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
-MODULE_ALIAS("platform:tnetv107x-ts");
-MODULE_LICENSE("GPL");
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 1/5] drivers: input: keyboard: st-keyscan: add keyscan driver
From: Gabriel FERNANDEZ @ 2014-03-18 15:00 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Lee Jones, Gabriel Fernandez,
Giuseppe Condorelli
In-Reply-To: <1395154806-2810-1-git-send-email-gabriel.fernandez@st.com>
This patch adds ST Keyscan driver to use the keypad hw a subset
of ST boards provide. Specific board setup will be put in the
given dt.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
---
.../devicetree/bindings/input/st-keyscan.txt | 60 +++++
drivers/input/keyboard/Kconfig | 12 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/st-keyscan.c | 260 +++++++++++++++++++++
4 files changed, 333 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/st-keyscan.txt
create mode 100644 drivers/input/keyboard/st-keyscan.c
diff --git a/Documentation/devicetree/bindings/input/st-keyscan.txt b/Documentation/devicetree/bindings/input/st-keyscan.txt
new file mode 100644
index 0000000..51eb428
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/st-keyscan.txt
@@ -0,0 +1,60 @@
+* ST Keyscan controller Device Tree bindings
+
+The ST keyscan controller Device Tree binding is based on the
+matrix-keymap.
+
+Required properties:
+- compatible: "st,sti-keyscan"
+
+- reg: Register base address and size of st-keyscan controller.
+
+- interrupts: Interrupt number for the st-keyscan controller.
+
+- clocks: Must contain one entry, for the module clock.
+ See ../clocks/clock-bindings.txt for details.
+
+- pinctrl: Should specify pin control groups used for this controller.
+ See ../pinctrl/pinctrl-bindings.txt for details.
+
+- linux,keymap: The keymap for keys as described in the binding document
+ devicetree/bindings/input/matrix-keymap.txt.
+
+- keypad,num-rows: Number of row lines connected to the keypad controller.
+
+- keypad,num-columns: Number of column lines connected to the keypad
+ controller.
+
+Optional property:
+- st,debounce_us: Debouncing interval time in microseconds
+
+Example:
+
+keyscan: keyscan@fe4b0000 {
+ compatible = "st,sti-keyscan";
+ reg = <0xfe4b0000 0x2000>;
+ interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>;
+ clocks = <&CLK_SYSIN>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_keyscan>;
+
+ keypad,num-rows = <4>;
+ keypad,num-columns = <4>;
+ st,debounce_us = <5000>;
+
+ linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_F13)
+ MATRIX_KEY(0x00, 0x01, KEY_F9)
+ MATRIX_KEY(0x00, 0x02, KEY_F5)
+ MATRIX_KEY(0x00, 0x03, KEY_F1)
+ MATRIX_KEY(0x01, 0x00, KEY_F14)
+ MATRIX_KEY(0x01, 0x01, KEY_F10)
+ MATRIX_KEY(0x01, 0x02, KEY_F6)
+ MATRIX_KEY(0x01, 0x03, KEY_F2)
+ MATRIX_KEY(0x02, 0x00, KEY_F15)
+ MATRIX_KEY(0x02, 0x01, KEY_F11)
+ MATRIX_KEY(0x02, 0x02, KEY_F7)
+ MATRIX_KEY(0x02, 0x03, KEY_F3)
+ MATRIX_KEY(0x03, 0x00, KEY_F16)
+ MATRIX_KEY(0x03, 0x01, KEY_F12)
+ MATRIX_KEY(0x03, 0x02, KEY_F8)
+ MATRIX_KEY(0x03, 0x03, KEY_F4) >;
+ };
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a673c9f..06b2c76 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -512,6 +512,18 @@ config KEYBOARD_STOWAWAY
To compile this driver as a module, choose M here: the
module will be called stowaway.
+config KEYBOARD_ST_KEYSCAN
+ tristate "STMicroelectronics keyscan support"
+ depends on ARCH_STI
+ select INPUT_EVDEV
+ select INPUT_MATRIXKMAP
+ help
+ Say Y here if you want to use a keypad attached to the keyscan block
+ on some STMicroelectronics SoC devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called st-keyscan.
+
config KEYBOARD_SUNKBD
tristate "Sun Type 4 and Type 5 keyboard"
select SERIO
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a699b61..5fd020a 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
+obj-$(CONFIG_KEYBOARD_ST_KEYSCAN) += st-keyscan.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
new file mode 100644
index 0000000..65cb3ac
--- /dev/null
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -0,0 +1,260 @@
+/*
+ * STMicroelectronics Key Scanning driver
+ *
+ * Copyright (c) 2014 STMicroelectonics Ltd.
+ * Author: Stuart Menefy <stuart.menefy@st.com>
+ *
+ * Based on sh_keysc.c, copyright 2008 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/input/matrix_keypad.h>
+
+#define ST_KEYSCAN_MAXKEYS 16
+
+#define KEYSCAN_CONFIG_OFF 0x0
+#define KEYSCAN_CONFIG_ENABLE 0x1
+#define KEYSCAN_DEBOUNCE_TIME_OFF 0x4
+#define KEYSCAN_MATRIX_STATE_OFF 0x8
+#define KEYSCAN_MATRIX_DIM_OFF 0xc
+#define KEYSCAN_MATRIX_DIM_X_SHIFT 0x0
+#define KEYSCAN_MATRIX_DIM_Y_SHIFT 0x2
+
+struct st_keyscan {
+ void __iomem *base;
+ int irq;
+ struct clk *clk;
+ struct input_dev *input_dev;
+ unsigned int last_state;
+ unsigned int n_rows;
+ unsigned int n_cols;
+ unsigned int debounce_us;
+};
+
+static irqreturn_t keyscan_isr(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct st_keyscan *keypad = platform_get_drvdata(pdev);
+ unsigned short *keycode = keypad->input_dev->keycode;
+ int state;
+ int change;
+
+ state = readl(keypad->base + KEYSCAN_MATRIX_STATE_OFF) & 0xffff;
+ change = keypad->last_state ^ state;
+
+ while (change) {
+ int scancode = __ffs(change);
+ int down = state & BIT(scancode);
+
+ input_report_key(keypad->input_dev, keycode[scancode], down);
+
+ change ^= BIT(scancode);
+ };
+ input_sync(keypad->input_dev);
+
+ keypad->last_state = state;
+
+ return IRQ_HANDLED;
+}
+
+static int keyscan_start(struct st_keyscan *keypad)
+{
+ clk_enable(keypad->clk);
+
+ writel(keypad->debounce_us * (clk_get_rate(keypad->clk) / 1000000),
+ keypad->base + KEYSCAN_DEBOUNCE_TIME_OFF);
+
+ writel(((keypad->n_cols - 1) << KEYSCAN_MATRIX_DIM_X_SHIFT) |
+ ((keypad->n_rows - 1) << KEYSCAN_MATRIX_DIM_Y_SHIFT),
+ keypad->base + KEYSCAN_MATRIX_DIM_OFF);
+
+ writel(KEYSCAN_CONFIG_ENABLE, keypad->base + KEYSCAN_CONFIG_OFF);
+
+ return 0;
+}
+
+static void keyscan_stop(struct st_keyscan *keypad)
+{
+ writel(0, keypad->base + KEYSCAN_CONFIG_OFF);
+
+ clk_disable(keypad->clk);
+}
+
+static int keyscan_open(struct input_dev *dev)
+{
+ struct st_keyscan *keypad = input_get_drvdata(dev);
+
+ return keyscan_start(keypad);
+}
+
+static void keyscan_close(struct input_dev *dev)
+{
+ struct st_keyscan *keypad = input_get_drvdata(dev);
+
+ keyscan_stop(keypad);
+}
+
+static int keypad_matrix_key_parse_dt(struct st_keyscan *keypad_data)
+{
+ struct device *dev = keypad_data->input_dev->dev.parent;
+ struct device_node *np = dev->of_node;
+ int error;
+
+ error = matrix_keypad_parse_of_params(dev, &keypad_data->n_rows,
+ &keypad_data->n_cols);
+ if (error) {
+ dev_err(dev, "failed to parse keypad params\n");
+ return error;
+ }
+
+ of_property_read_u32(np, "st,debounce_us", &keypad_data->debounce_us);
+
+ dev_info(dev, "n_rows=%d n_col=%d debounce=%d\n",
+ keypad_data->n_rows,
+ keypad_data->n_cols,
+ keypad_data->debounce_us);
+
+ return 0;
+}
+
+static int __init keyscan_probe(struct platform_device *pdev)
+{
+ struct st_keyscan *keypad_data;
+ struct input_dev *input_dev;
+ struct resource *res;
+ int error;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "no keymap defined\n");
+ return -EINVAL;
+ }
+
+ keypad_data = devm_kzalloc(&pdev->dev,
+ sizeof(*keypad_data), GFP_KERNEL);
+ if (!keypad_data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(keypad_data->base))
+ return PTR_ERR(keypad_data->base);
+
+ keypad_data->irq = platform_get_irq(pdev, 0);
+ if (keypad_data->irq < 0) {
+ dev_err(&pdev->dev, "no IRQ specified\n");
+ return -EINVAL;
+ }
+
+ error = devm_request_irq(&pdev->dev, keypad_data->irq, keyscan_isr, 0,
+ pdev->name, pdev);
+ if (error) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+ return error;
+ }
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+
+ if (!input_dev) {
+ dev_err(&pdev->dev, "failed to allocate the input device\n");
+ return -ENOMEM;
+ }
+
+ keypad_data->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(keypad_data->clk)) {
+ dev_err(&pdev->dev, "cannot get clock");
+ return PTR_ERR(keypad_data->clk);
+ }
+
+ keypad_data->input_dev = input_dev;
+
+ input_dev->name = pdev->name;
+ input_dev->phys = "keyscan-keys/input0";
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->open = keyscan_open;
+ input_dev->close = keyscan_close;
+
+ input_dev->id.bustype = BUS_HOST;
+
+ error = keypad_matrix_key_parse_dt(keypad_data);
+ if (error)
+ return error;
+
+ error = matrix_keypad_build_keymap(NULL, NULL,
+ keypad_data->n_rows, keypad_data->n_cols,
+ NULL, input_dev);
+ if (error) {
+ dev_err(&pdev->dev, "failed to build keymap\n");
+ return error;
+ }
+
+ input_set_drvdata(input_dev, keypad_data);
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(&pdev->dev, "failed to register input device\n");
+ return error;
+ }
+
+ platform_set_drvdata(pdev, keypad_data);
+
+ device_set_wakeup_capable(&pdev->dev, 1);
+
+ return 0;
+}
+
+static int keyscan_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct st_keyscan *keypad = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(keypad->irq);
+ else
+ keyscan_stop(keypad);
+
+ return 0;
+}
+
+static int keyscan_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct st_keyscan *keypad = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(keypad->irq);
+ else
+ keyscan_start(keypad);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, keyscan_suspend, keyscan_resume);
+
+static const struct of_device_id keyscan_of_match[] = {
+ { .compatible = "st,sti-keyscan" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, keyscan_of_match);
+
+struct platform_driver keyscan_device_driver = {
+ .probe = keyscan_probe,
+ .driver = {
+ .name = "st-keyscan",
+ .pm = &keyscan_dev_pm_ops,
+ .of_match_table = of_match_ptr(keyscan_of_match),
+ }
+};
+
+module_platform_driver(keyscan_device_driver);
+
+MODULE_AUTHOR("Stuart Menefy <stuart.menefy@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics keyscan device driver");
+MODULE_LICENSE("GPL");
--
1.9.0
^ permalink raw reply related
* [PATCH v2 2/5] ARM: STi: DT: add keyscan for stih415
From: Gabriel FERNANDEZ @ 2014-03-18 15:00 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Lee Jones, Giuseppe CONDORELLI,
Gabriel Fernandez
In-Reply-To: <1395154806-2810-1-git-send-email-gabriel.fernandez@st.com>
From: Giuseppe CONDORELLI <giuseppe.condorelli@st.com>
Add keyscan support for stih415.
It is put disabled by default because it is not enabled on all boards
Also there are PIOs conflict with already claimed lines.
Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
arch/arm/boot/dts/stih415-pinctrl.dtsi | 16 ++++++++++++++++
arch/arm/boot/dts/stih415.dtsi | 10 ++++++++++
2 files changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/stih415-pinctrl.dtsi b/arch/arm/boot/dts/stih415-pinctrl.dtsi
index e56449d..3e5e074 100644
--- a/arch/arm/boot/dts/stih415-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih415-pinctrl.dtsi
@@ -87,6 +87,22 @@
};
};
+ keyscan {
+ pinctrl_keyscan: keyscan {
+ st,pins {
+ keyin0 = <&PIO0 2 ALT2 IN>;
+ keyin1 = <&PIO0 3 ALT2 IN>;
+ keyin2 = <&PIO0 4 ALT2 IN>;
+ keyin3 = <&PIO2 6 ALT2 IN>;
+
+ keyout0 = <&PIO1 6 ALT2 OUT>;
+ keyout1 = <&PIO1 7 ALT2 OUT>;
+ keyout2 = <&PIO0 6 ALT2 OUT>;
+ keyout3 = <&PIO2 7 ALT2 OUT>;
+ };
+ };
+ };
+
sbc_i2c0 {
pinctrl_sbc_i2c0_default: sbc_i2c0-default {
st,pins {
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
index d9c7dd1..bda9e23 100644
--- a/arch/arm/boot/dts/stih415.dtsi
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -136,5 +136,15 @@
status = "disabled";
};
+
+ keyscan: keyscan@fe4b0000 {
+ compatible = "st,sti-keyscan";
+ status = "disabled";
+ reg = <0xfe4b0000 0x2000>;
+ interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>;
+ clocks = <&CLK_SYSIN>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_keyscan>;
+ };
};
};
--
1.9.0
^ permalink raw reply related
* [PATCH v2 3/5] ARM: STi: DT: add keyscan for stih416
From: Gabriel FERNANDEZ @ 2014-03-18 15:00 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Lee Jones, Gabriel Fernandez,
Giuseppe Condorelli
In-Reply-To: <1395154806-2810-1-git-send-email-gabriel.fernandez@st.com>
Add keyscan support for stih416.
It is disabled by default given that it is not enabled on all boards.
Also there are PIOs conflict with already claimed lines.
Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
arch/arm/boot/dts/stih416-pinctrl.dtsi | 16 ++++++++++++++++
arch/arm/boot/dts/stih416.dtsi | 10 ++++++++++
2 files changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/stih416-pinctrl.dtsi b/arch/arm/boot/dts/stih416-pinctrl.dtsi
index b29ff4b..79c036a 100644
--- a/arch/arm/boot/dts/stih416-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih416-pinctrl.dtsi
@@ -98,6 +98,22 @@
};
};
+ keyscan {
+ pinctrl_keyscan: keyscan {
+ st,pins {
+ keyin0 = <&PIO0 2 ALT2 IN>;
+ keyin1 = <&PIO0 3 ALT2 IN>;
+ keyin2 = <&PIO0 4 ALT2 IN>;
+ keyin3 = <&PIO2 6 ALT2 IN>;
+
+ keyout0 = <&PIO1 6 ALT2 OUT>;
+ keyout1 = <&PIO1 7 ALT2 OUT>;
+ keyout2 = <&PIO0 6 ALT2 OUT>;
+ keyout3 = <&PIO2 7 ALT2 OUT>;
+ };
+ };
+ };
+
sbc_i2c0 {
pinctrl_sbc_i2c0_default: sbc_i2c0-default {
st,pins {
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
index b7ab47b..8a695dc 100644
--- a/arch/arm/boot/dts/stih416.dtsi
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -145,5 +145,15 @@
status = "disabled";
};
+
+ keyscan: keyscan@fe4b0000 {
+ compatible = "st,sti-keyscan";
+ status = "disabled";
+ reg = <0xfe4b0000 0x2000>;
+ interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>;
+ clocks = <&CLK_SYSIN>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_keyscan>;
+ };
};
};
--
1.9.0
^ permalink raw reply related
* [PATCH v2 4/5] ARM: STi: DT: add keyscan for stih41x-b2000
From: Gabriel FERNANDEZ @ 2014-03-18 15:00 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Lee Jones, Gabriel Fernandez,
Giuseppe Condorelli
In-Reply-To: <1395154806-2810-1-git-send-email-gabriel.fernandez@st.com>
Add keyscan setup for stih415/h416 b2000.
Both have same raw/column lines number, debounce time and keymap.
Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
arch/arm/boot/dts/stih41x-b2000.dtsi | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm/boot/dts/stih41x-b2000.dtsi b/arch/arm/boot/dts/stih41x-b2000.dtsi
index 1e6aa92..c5f2191 100644
--- a/arch/arm/boot/dts/stih41x-b2000.dtsi
+++ b/arch/arm/boot/dts/stih41x-b2000.dtsi
@@ -6,6 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*/
+#include <dt-bindings/input/input.h>
/ {
memory{
@@ -46,5 +47,27 @@
status = "okay";
};
+
+ keyscan: keyscan@fe4b0000 {
+ keypad,num-rows = <4>;
+ keypad,num-columns = <4>;
+ st,debounce_us = <5000>;
+ linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_F13)
+ MATRIX_KEY(0x00, 0x01, KEY_F9)
+ MATRIX_KEY(0x00, 0x02, KEY_F5)
+ MATRIX_KEY(0x00, 0x03, KEY_F1)
+ MATRIX_KEY(0x01, 0x00, KEY_F14)
+ MATRIX_KEY(0x01, 0x01, KEY_F10)
+ MATRIX_KEY(0x01, 0x02, KEY_F6)
+ MATRIX_KEY(0x01, 0x03, KEY_F2)
+ MATRIX_KEY(0x02, 0x00, KEY_F15)
+ MATRIX_KEY(0x02, 0x01, KEY_F11)
+ MATRIX_KEY(0x02, 0x02, KEY_F7)
+ MATRIX_KEY(0x02, 0x03, KEY_F3)
+ MATRIX_KEY(0x03, 0x00, KEY_F16)
+ MATRIX_KEY(0x03, 0x01, KEY_F12)
+ MATRIX_KEY(0x03, 0x02, KEY_F8)
+ MATRIX_KEY(0x03, 0x03, KEY_F4) >;
+ };
};
};
--
1.9.0
^ permalink raw reply related
* [PATCH v2 5/5] ARM: multi_v7_defconfig: add ST Keyscan driver
From: Gabriel FERNANDEZ @ 2014-03-18 15:00 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Lee Jones, Gabriel Fernandez
In-Reply-To: <1395154806-2810-1-git-send-email-gabriel.fernandez@st.com>
This patch adds KEYBOARD_ST_KEYSCAN config
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index ee69829..5e926981 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -131,6 +131,7 @@ CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TEGRA=y
CONFIG_KEYBOARD_SPEAR=y
+CONFIG_KEYBOARD_ST_KEYSCAN=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_MOUSE_PS2_ELANTECH=y
CONFIG_INPUT_MISC=y
--
1.9.0
^ permalink raw reply related
* [PATCH v2 0/5] Add ST Keyscan driver
From: Gabriel FERNANDEZ @ 2014-03-18 15:00 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, Russell King, Grant Likely
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
linux-input, kernel, Lee Jones, Gabriel Fernandez
Changes in v2:
- use standard format for matrix keymap
- suppress __exit mark for keyscan_remove()
- Call to keyscan_stop() shoudl go into keyscan_close() implementation
- use of SIMPLE_DEV_PM_OPS()
- rename compatibility name into "st,sti-keyscan"
- suppress platform data management
- omit vendor information
- cosmetic change and renaming
The goal of this series is to add ST Keyscan support to ST SoCs.
The DT definition is added for STiH415 and STiH416 SoCs on
B2000 board.
Gabriel Fernandez (4):
drivers: input: keyboard: st-keyscan: add keyscan driver
ARM: STi: DT: add keyscan for stih416
ARM: STi: DT: add keyscan for stih41x-b2000
ARM: multi_v7_defconfig: add ST Keyscan driver
Giuseppe CONDORELLI (1):
ARM: STi: DT: add keyscan for stih415
.../devicetree/bindings/input/st-keyscan.txt | 60 +++++
arch/arm/boot/dts/stih415-pinctrl.dtsi | 16 ++
arch/arm/boot/dts/stih415.dtsi | 10 +
arch/arm/boot/dts/stih416-pinctrl.dtsi | 16 ++
arch/arm/boot/dts/stih416.dtsi | 10 +
arch/arm/boot/dts/stih41x-b2000.dtsi | 23 ++
arch/arm/configs/multi_v7_defconfig | 1 +
drivers/input/keyboard/Kconfig | 12 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/st-keyscan.c | 260 +++++++++++++++++++++
10 files changed, 409 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/st-keyscan.txt
create mode 100644 drivers/input/keyboard/st-keyscan.c
--
1.9.0
^ permalink raw reply
* Re: [PATCH v2 1/8] mfd: AXP20x: Add mfd driver for AXP20x PMIC
From: Lee Jones @ 2014-03-18 15:59 UTC (permalink / raw)
To: Carlo Caione
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
hdegoede-H+wXaHxf7aLQT0dZR+AlfA, emilio-0Z03zUJReD5OxF6Tv1QG9Q,
wens-jdAy2FN1RRM, sameo-VuQAYsv1563Yd54FQh9/CA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <1394898225-28452-2-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
> This patch introduces the preliminary support for PMICs X-Powers AXP202
> and AXP209. The AXP209 and AXP202 are the PMUs (Power Management Unit)
> used by A10, A13 and A20 SoCs and developed by X-Powers, a sister company
> of Allwinner.
>
> The core enables support for two subsystems:
> - PEK (Power Enable Key)
> - Regulators
>
> Signed-off-by: Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
> ---
> drivers/mfd/Kconfig | 12 +++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/axp20x.c | 247 +++++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/axp20x.h | 179 ++++++++++++++++++++++++++++++++
> 4 files changed, 439 insertions(+)
> create mode 100644 drivers/mfd/axp20x.c
> create mode 100644 include/linux/mfd/axp20x.h
[...]
> +/*
> + * axp20x.c - mfd core driver for the X-Powers AXP202 and AXP209
MFD
[...]
> +static struct resource axp20x_pek_resources[] = {
> + {
> + .name = "PEK_DBR",
> + .start = AXP20X_IRQ_PEK_RIS_EDGE,
> + .end = AXP20X_IRQ_PEK_RIS_EDGE,
> + .flags = IORESOURCE_IRQ,
> + },
> + {
> + .name = "PEK_DBF",
> + .start = AXP20X_IRQ_PEK_FAL_EDGE,
> + .end = AXP20X_IRQ_PEK_FAL_EDGE,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
[...]
> +static struct mfd_cell axp20x_cells[] = {
> + {
> + .name = "axp20x-pek",
> + .num_resources = ARRAY_SIZE(axp20x_pek_resources),
> + .resources = axp20x_pek_resources,
> + }, {
> + .name = "axp20x-regulator",
> + },
> +};
nit: The format of these two structs are inconsistent.
[...]
> +static int axp20x_i2c_probe(struct i2c_client *i2c,
> + const struct i2c_device_id *id)
> +{
> + struct axp20x_dev *axp20x;
> + const struct of_device_id *of_id;
> + int ret;
> +
> + axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
> + if (!axp20x)
> + return -ENOMEM;
> +
> + of_id = of_match_device(axp20x_of_match, &i2c->dev);
> + if (!of_id) {
> + dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
> + return -ENODEV;
> + }
> + axp20x->variant = (int) of_id->data;
No need to cast from void *.
> + axp20x->i2c_client = i2c;
> + axp20x->dev = &i2c->dev;
> + dev_set_drvdata(axp20x->dev, axp20x);
> +
> + axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
> + if (IS_ERR(axp20x->regmap)) {
> + ret = PTR_ERR(axp20x->regmap);
> + dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
> + return ret;
> + }
> +
> + axp20x->irq = i2c->irq;
Do you _really_ need this if you have 'axp20x->i2c_client->irq'?
> + ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
> + IRQF_ONESHOT | IRQF_SHARED, -1,
> + &axp20x_regmap_irq_chip,
> + &axp20x->regmap_irqc);
> + if (ret) {
> + dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
> + return ret;
> + }
> +
> + ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
> + ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
> +
> + if (ret) {
> + dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
> + goto mfd_err;
> + }
> +
> + if (!pm_power_off) {
> + axp20x_pm_power_off = axp20x;
> + pm_power_off = axp20x_power_off;
> + }
> +
> + dev_info(&i2c->dev, "AXP20X driver loaded\n");
> +
> + return 0;
> +
> +mfd_err:
> + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
> +
> + return ret;
I'd say the goto is pointless if you're only using it once.
Instead move regmap_del_irq_chip() into mfd_add_devices()'s error
handler and return straight from there.
[...]
> +static const struct i2c_device_id axp20x_i2c_id[] = {
> + { "axp202", AXP202_ID },
> + { "axp209", AXP209_ID },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
Isn't this redundant now that you're using of_id?
[...]
> +#ifndef __LINUX_MFD_AXP20X_H
> +#define __LINUX_MFD_AXP20X_H
> +
> +#define AXP202_ID 0
> +#define AXP209_ID 1
enum?
[...]
> +struct axp20x_dev {
> + struct device *dev;
> + struct i2c_client *i2c_client;
> + struct regmap *regmap;
> + struct regmap_irq_chip_data *regmap_irqc;
> + int variant;
> + int irq;
i2c_client->irq?
> +};
> +
> +#endif /* __LINUX_MFD_AXP20X_H */
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* [PATCH] input: gpio-beeper: Simplify GPIO handling
From: Alexander Shiyan @ 2014-03-18 17:45 UTC (permalink / raw)
To: linux-input; +Cc: Dmitry Torokhov, Alexander Shiyan
This patch simplifies GPIO handling in the driver by using GPIO
functions based on descriptors. As a result this driver now can
be used for boards without DT support.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
drivers/input/misc/Kconfig | 2 +-
drivers/input/misc/gpio-beeper.c | 37 ++++++++++++++-----------------------
2 files changed, 15 insertions(+), 24 deletions(-)
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 762e6d2..0623e99 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -224,7 +224,7 @@ config INPUT_GP2A
config INPUT_GPIO_BEEPER
tristate "Generic GPIO Beeper support"
- depends on OF_GPIO
+ depends on GPIOLIB
help
Say Y here if you have a beeper connected to a GPIO pin.
diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c
index b757435..a57f15e 100644
--- a/drivers/input/misc/gpio-beeper.c
+++ b/drivers/input/misc/gpio-beeper.c
@@ -1,7 +1,7 @@
/*
* Generic GPIO beeper driver
*
- * Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru>
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
#include <linux/input.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
@@ -19,21 +19,15 @@
struct gpio_beeper {
struct work_struct work;
- int gpio;
- bool active_low;
- bool beeping;
+ struct gpio_desc *desc;
+ int beeping;
};
-static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on)
-{
- gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low);
-}
-
static void gpio_beeper_work(struct work_struct *work)
{
struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work);
- gpio_beeper_toggle(beep, beep->beeping);
+ gpiod_set_value_cansleep(beep->desc, beep->beeping);
}
static int gpio_beeper_event(struct input_dev *dev, unsigned int type,
@@ -59,24 +53,24 @@ static void gpio_beeper_close(struct input_dev *input)
struct gpio_beeper *beep = input_get_drvdata(input);
cancel_work_sync(&beep->work);
- gpio_beeper_toggle(beep, false);
+ gpiod_set_value_cansleep(beep->desc, 0);
}
static int gpio_beeper_probe(struct platform_device *pdev)
{
struct gpio_beeper *beep;
- enum of_gpio_flags flags;
struct input_dev *input;
- unsigned long gflags;
int err;
beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL);
if (!beep)
return -ENOMEM;
- beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
- if (!gpio_is_valid(beep->gpio))
- return beep->gpio;
+ beep->desc = devm_gpiod_get(&pdev->dev, NULL);
+ if (!beep->desc)
+ return -EINVAL;
+ if (IS_ERR(beep->desc))
+ return PTR_ERR(beep->desc);
input = devm_input_allocate_device(&pdev->dev);
if (!input)
@@ -94,10 +88,7 @@ static int gpio_beeper_probe(struct platform_device *pdev)
input_set_capability(input, EV_SND, SND_BELL);
- beep->active_low = flags & OF_GPIO_ACTIVE_LOW;
- gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-
- err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name);
+ err = gpiod_direction_output(beep->desc, 0);
if (err)
return err;
@@ -106,7 +97,7 @@ static int gpio_beeper_probe(struct platform_device *pdev)
return input_register_device(input);
}
-static struct of_device_id gpio_beeper_of_match[] = {
+static struct of_device_id __maybe_unused gpio_beeper_of_match[] = {
{ .compatible = BEEPER_MODNAME, },
{ }
};
@@ -116,7 +107,7 @@ static struct platform_driver gpio_beeper_platform_driver = {
.driver = {
.name = BEEPER_MODNAME,
.owner = THIS_MODULE,
- .of_match_table = gpio_beeper_of_match,
+ .of_match_table = of_match_ptr(gpio_beeper_of_match),
},
.probe = gpio_beeper_probe,
};
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH v2 1/5] drivers: input: keyboard: st-keyscan: add keyscan driver
From: Mark Rutland @ 2014-03-18 17:51 UTC (permalink / raw)
To: Gabriel FERNANDEZ
Cc: Dmitry Torokhov, Rob Herring, Pawel Moll, Ian Campbell,
Kumar Gala, Rob Landley, Russell King, grant.likely@linaro.org,
devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-input@vger.kernel.org,
kernel@stlinux.com, Lee Jones, Giuseppe Condorelli
In-Reply-To: <1395154806-2810-2-git-send-email-gabriel.fernandez@st.com>
On Tue, Mar 18, 2014 at 03:00:02PM +0000, Gabriel FERNANDEZ wrote:
> This patch adds ST Keyscan driver to use the keypad hw a subset
> of ST boards provide. Specific board setup will be put in the
> given dt.
>
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
> ---
> .../devicetree/bindings/input/st-keyscan.txt | 60 +++++
> drivers/input/keyboard/Kconfig | 12 +
> drivers/input/keyboard/Makefile | 1 +
> drivers/input/keyboard/st-keyscan.c | 260 +++++++++++++++++++++
> 4 files changed, 333 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/st-keyscan.txt
> create mode 100644 drivers/input/keyboard/st-keyscan.c
>
> diff --git a/Documentation/devicetree/bindings/input/st-keyscan.txt b/Documentation/devicetree/bindings/input/st-keyscan.txt
> new file mode 100644
> index 0000000..51eb428
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/st-keyscan.txt
> @@ -0,0 +1,60 @@
> +* ST Keyscan controller Device Tree bindings
> +
> +The ST keyscan controller Device Tree binding is based on the
> +matrix-keymap.
> +
> +Required properties:
> +- compatible: "st,sti-keyscan"
> +
> +- reg: Register base address and size of st-keyscan controller.
> +
> +- interrupts: Interrupt number for the st-keyscan controller.
> +
> +- clocks: Must contain one entry, for the module clock.
> + See ../clocks/clock-bindings.txt for details.
> +
> +- pinctrl: Should specify pin control groups used for this controller.
> + See ../pinctrl/pinctrl-bindings.txt for details.
> +
> +- linux,keymap: The keymap for keys as described in the binding document
> + devicetree/bindings/input/matrix-keymap.txt.
> +
> +- keypad,num-rows: Number of row lines connected to the keypad controller.
> +
> +- keypad,num-columns: Number of column lines connected to the keypad
> + controller.
> +
> +Optional property:
> +- st,debounce_us: Debouncing interval time in microseconds
s/_/-/ here, please.
Otherwise this looks ok.
Mark.
^ permalink raw reply
* [PATCH v3 1/2] input: Add new driver for ARM CLPS711X keypad
From: Alexander Shiyan @ 2014-03-18 18:02 UTC (permalink / raw)
To: linux-input; +Cc: Dmitry Torokhov, Alexander Shiyan
This patch adds a new driver for keypad for Cirrus Logic CLPS711X CPUs.
Target CPU contain keyboard interface which can scan 8 column lines,
so we can read row GPIOs to read status and determine asserted state.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
drivers/input/keyboard/Kconfig | 12 ++
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/clps711x-keypad.c | 209 +++++++++++++++++++++++++++++++
3 files changed, 222 insertions(+)
create mode 100644 drivers/input/keyboard/clps711x-keypad.c
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a673c9f..45274e3 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -151,6 +151,18 @@ config KEYBOARD_BFIN
To compile this driver as a module, choose M here: the
module will be called bf54x-keys.
+config KEYBOARD_CLPS711X
+ tristate "CLPS711X Keypad support"
+ depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST)
+ select INPUT_MATRIXKMAP
+ select INPUT_POLLDEV
+ help
+ Say Y here to enable the matrix keypad on the Cirrus Logic
+ CLPS711X CPUs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called clps711x-keypad.
+
config KEYBOARD_LKKBD
tristate "DECstation/VAXstation LK201/LK401 keyboard"
select SERIO
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a699b61..f8589fe 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c
new file mode 100644
index 0000000..51c4dd7
--- /dev/null
+++ b/drivers/input/keyboard/clps711x-keypad.c
@@ -0,0 +1,209 @@
+/*
+ * Cirrus Logic CLPS711X Keypad driver
+ *
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/sched.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/clps711x.h>
+
+#define CLPS711X_KEYPAD_COL_COUNT 8
+
+struct clps711x_gpio_data {
+ struct gpio_desc *desc;
+ DECLARE_BITMAP(last_state, CLPS711X_KEYPAD_COL_COUNT);
+};
+
+struct clps711x_keypad_data {
+ struct regmap *syscon;
+ int row_count;
+ unsigned int row_shift;
+ struct clps711x_gpio_data *gpio_data;
+};
+
+static void clps711x_keypad_poll(struct input_polled_dev *dev)
+{
+ const unsigned short *keycodes = dev->input->keycode;
+ struct clps711x_keypad_data *priv = dev->private;
+ bool sync = false;
+ int col, row;
+
+ for (col = 0; col < CLPS711X_KEYPAD_COL_COUNT; col++) {
+ /* Assert column */
+ regmap_update_bits(priv->syscon, SYSCON_OFFSET,
+ SYSCON1_KBDSCAN_MASK,
+ SYSCON1_KBDSCAN(8 + col));
+
+ /* Scan rows */
+ for (row = 0; row < priv->row_count; row++) {
+ struct clps711x_gpio_data *data = &priv->gpio_data[row];
+ bool state, state1;
+
+ /* Read twice for protection against fluctuations */
+ do {
+ state = gpiod_get_value_cansleep(data->desc);
+ cond_resched();
+ state1 = gpiod_get_value_cansleep(data->desc);
+ } while (state != state1);
+
+ if (test_bit(col, data->last_state) != state) {
+ int code = MATRIX_SCAN_CODE(row, col,
+ priv->row_shift);
+
+ if (state) {
+ set_bit(col, data->last_state);
+ input_event(dev->input, EV_MSC,
+ MSC_SCAN, code);
+ } else {
+ clear_bit(col, data->last_state);
+ }
+
+ if (keycodes[code])
+ input_report_key(dev->input,
+ keycodes[code], state);
+ sync = true;
+ }
+ }
+
+ /* Set all columns to low */
+ regmap_update_bits(priv->syscon, SYSCON_OFFSET,
+ SYSCON1_KBDSCAN_MASK, SYSCON1_KBDSCAN(1));
+ }
+
+ if (sync)
+ input_sync(dev->input);
+}
+
+static int clps711x_keypad_probe(struct platform_device *pdev)
+{
+ struct clps711x_keypad_data *priv;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct input_polled_dev *poll_dev;
+ u32 poll_interval;
+ int i, err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->syscon =
+ syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1");
+ if (IS_ERR(priv->syscon))
+ return PTR_ERR(priv->syscon);
+
+ priv->row_count = of_gpio_named_count(np, "row-gpios");
+ if (priv->row_count < 1)
+ return -EINVAL;
+
+ priv->gpio_data = devm_kzalloc(dev, sizeof(*priv->gpio_data) *
+ priv->row_count, GFP_KERNEL);
+ if (!priv->gpio_data)
+ return -ENOMEM;
+
+ priv->row_shift = get_count_order(CLPS711X_KEYPAD_COL_COUNT);
+
+ for (i = 0; i < priv->row_count; i++) {
+ struct clps711x_gpio_data *data = &priv->gpio_data[i];
+
+ data->desc = devm_gpiod_get_index(dev, "row", i);
+ if (!data->desc)
+ return -EINVAL;
+
+ if (IS_ERR(data->desc))
+ return PTR_ERR(data->desc);
+
+ gpiod_direction_input(data->desc);
+ }
+
+ err = of_property_read_u32(np, "poll-interval", &poll_interval);
+ if (err)
+ return err;
+
+ poll_dev = input_allocate_polled_device();
+ if (!poll_dev)
+ return -ENOMEM;
+
+ poll_dev->private = priv;
+ poll_dev->poll = clps711x_keypad_poll;
+ poll_dev->poll_interval = poll_interval;
+ poll_dev->input->name = pdev->name;
+ poll_dev->input->dev.parent = dev;
+ poll_dev->input->id.bustype = BUS_HOST;
+ poll_dev->input->id.vendor = 0x0001;
+ poll_dev->input->id.product = 0x0001;
+ poll_dev->input->id.version = 0x0100;
+
+ err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count,
+ CLPS711X_KEYPAD_COL_COUNT,
+ NULL, poll_dev->input);
+ if (err)
+ goto out_err;
+
+ input_set_capability(poll_dev->input, EV_MSC, MSC_SCAN);
+ if (of_property_read_bool(np, "autorepeat"))
+ __set_bit(EV_REP, poll_dev->input->evbit);
+
+ platform_set_drvdata(pdev, poll_dev);
+
+ /* Set all columns to low */
+ regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK,
+ SYSCON1_KBDSCAN(1));
+
+ err = input_register_polled_device(poll_dev);
+ if (!err) {
+ /* Report initial state */
+ clps711x_keypad_poll(poll_dev);
+
+ return 0;
+ }
+
+out_err:
+ input_free_polled_device(poll_dev);
+
+ return err;
+}
+
+static int clps711x_keypad_remove(struct platform_device *pdev)
+{
+ struct input_polled_dev *poll_dev = platform_get_drvdata(pdev);
+
+ input_unregister_polled_device(poll_dev);
+ input_free_polled_device(poll_dev);
+
+ return 0;
+}
+
+static struct of_device_id clps711x_keypad_of_match[] = {
+ { .compatible = "cirrus,clps711x-keypad", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, clps711x_keypad_of_match);
+
+static struct platform_driver clps711x_keypad_driver = {
+ .driver = {
+ .name = "clps711x-keypad",
+ .owner = THIS_MODULE,
+ .of_match_table = clps711x_keypad_of_match,
+ },
+ .probe = clps711x_keypad_probe,
+ .remove = clps711x_keypad_remove,
+};
+module_platform_driver(clps711x_keypad_driver);
+
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("Cirrus Logic CLPS711X Keypad driver");
+MODULE_LICENSE("GPL");
--
1.8.3.2
^ permalink raw reply related
* [PATCH RESEND] input: dts: Add commonly used event types
From: Alexander Shiyan @ 2014-03-18 18:04 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, devicetree, Rob Herring, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely,
Alexander Shiyan
Patch adds commonly used event types (EV_KEY and EV_SW) to
devicetree bindings header for input subsystem.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
include/dt-bindings/input/input.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/dt-bindings/input/input.h b/include/dt-bindings/input/input.h
index 042e7b3..3a141d92 100644
--- a/include/dt-bindings/input/input.h
+++ b/include/dt-bindings/input/input.h
@@ -9,6 +9,9 @@
#ifndef _DT_BINDINGS_INPUT_INPUT_H
#define _DT_BINDINGS_INPUT_INPUT_H
+#define EV_KEY 0x01
+#define EV_SW 0x05
+
#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_1 2
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 2/2] input: clps711x-keypad: dts: Add bindings documentation
From: Alexander Shiyan @ 2014-03-18 18:04 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, devicetree, Rob Herring, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, Grant Likely,
Alexander Shiyan
In-Reply-To: <1395165888-17434-1-git-send-email-shc_work@mail.ru>
This patch adds the devicetree documentation for the Cirrus Logic
CLPS711X keypad.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
.../devicetree/bindings/input/clps711x-keypad.txt | 27 ++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/clps711x-keypad.txt
diff --git a/Documentation/devicetree/bindings/input/clps711x-keypad.txt b/Documentation/devicetree/bindings/input/clps711x-keypad.txt
new file mode 100644
index 0000000..93fa2c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/clps711x-keypad.txt
@@ -0,0 +1,27 @@
+* Cirrus Logic CLPS711X matrix keypad device tree bindings
+
+Required Properties:
+- compatible: Shall contain "cirrus,clps711x-keypad".
+- row-gpios: List of GPIOs used as row lines.
+- poll-interval: Poll interval time in milliseconds.
+- linux,keymap: The definition can be found at
+ bindings/input/matrix-keymap.txt.
+
+Optional Properties:
+- autorepeat: Enable autorepeat feature.
+
+Example:
+ keypad {
+ compatible = "cirrus,ep7312-keypad", "cirrus,clps711x-keypad";
+ autorepeat;
+ poll-interval = <120>;
+ row-gpios = <&porta 0 0>,
+ <&porta 1 0>;
+
+ linux,keymap = <
+ MATRIX_KEY(0, 0, KEY_UP)
+ MATRIX_KEY(0, 1, KEY_DOWN)
+ MATRIX_KEY(1, 0, KEY_LEFT)
+ MATRIX_KEY(1, 1, KEY_RIGHT)
+ >;
+ };
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH v3 1/4] mfd: max8997: use regmap to access registers
From: Bryan Wu @ 2014-03-18 22:33 UTC (permalink / raw)
To: Robert Baldyga
Cc: Samuel Ortiz, Lee Jones, MyungJoo Ham, cw00.choi, dmitry.torokhov,
rpurdie@rpsys.net, dbaryshkov, David Woodhouse, lgirdwood,
Mark Brown, Alessandro Zummo, Paul Gortmaker, lkml, linux-input,
Linux LED Subsystem, rtc-linux, m.szyprowski, k.kozlowski
In-Reply-To: <1394703532-494-2-git-send-email-r.baldyga@samsung.com>
On Thu, Mar 13, 2014 at 2:38 AM, Robert Baldyga <r.baldyga@samsung.com> wrote:
> This patch modifies max8997 driver and each associated function driver,
> to use regmap instead of operating directly on i2c bus. It will allow to
> simplify IRQ handling using regmap-irq.
>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> ---
> drivers/extcon/extcon-max8997.c | 31 ++++----
> drivers/input/misc/max8997_haptic.c | 34 +++++----
> drivers/leds/leds-max8997.c | 13 ++--
> drivers/mfd/Kconfig | 1 +
> drivers/mfd/max8997-irq.c | 64 +++++++---------
> drivers/mfd/max8997.c | 141 ++++++++++++++++-------------------
> drivers/power/max8997_charger.c | 33 ++++----
> drivers/regulator/max8997.c | 87 +++++++++++----------
> drivers/rtc/rtc-max8997.c | 56 +++++++-------
> include/linux/mfd/max8997-private.h | 17 ++---
> 10 files changed, 228 insertions(+), 249 deletions(-)
>
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index 6a00464..f258c08 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -27,6 +27,7 @@
> #include <linux/mfd/max8997-private.h>
> #include <linux/extcon.h>
> #include <linux/irqdomain.h>
> +#include <linux/regmap.h>
>
> #define DEV_NAME "max8997-muic"
> #define DELAY_MS_DEFAULT 20000 /* unit: millisecond */
> @@ -116,7 +117,7 @@ enum max8997_muic_charger_type {
>
> struct max8997_muic_info {
> struct device *dev;
> - struct i2c_client *muic;
> + struct max8997_dev *max8997;
> struct extcon_dev *edev;
> int prev_cable_type;
> int prev_chg_type;
> @@ -190,10 +191,10 @@ static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
> case ADC_DEBOUNCE_TIME_10MS:
> case ADC_DEBOUNCE_TIME_25MS:
> case ADC_DEBOUNCE_TIME_38_62MS:
> - ret = max8997_update_reg(info->muic,
> + ret = regmap_update_bits(info->max8997->regmap_muic,
> MAX8997_MUIC_REG_CONTROL3,
> - time << CONTROL3_ADCDBSET_SHIFT,
> - CONTROL3_ADCDBSET_MASK);
> + CONTROL3_ADCDBSET_MASK,
> + time << CONTROL3_ADCDBSET_SHIFT);
> if (ret) {
> dev_err(info->dev, "failed to set ADC debounce time\n");
> return ret;
> @@ -228,8 +229,8 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
> else
> ctrl1 = CONTROL1_SW_OPEN;
>
> - ret = max8997_update_reg(info->muic,
> - MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
> + ret = regmap_update_bits(info->max8997->regmap_muic,
> + MAX8997_MUIC_REG_CONTROL1, COMP_SW_MASK, ctrl1);
> if (ret < 0) {
> dev_err(info->dev, "failed to update MUIC register\n");
> return ret;
> @@ -240,9 +241,9 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
> else
> ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
>
> - ret = max8997_update_reg(info->muic,
> - MAX8997_MUIC_REG_CONTROL2, ctrl2,
> - CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
> + ret = regmap_update_bits(info->max8997->regmap_muic,
> + MAX8997_MUIC_REG_CONTROL2,
> + CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
> if (ret < 0) {
> dev_err(info->dev, "failed to update MUIC register\n");
> return ret;
> @@ -543,8 +544,8 @@ static void max8997_muic_irq_work(struct work_struct *work)
> if (info->irq == muic_irqs[i].virq)
> irq_type = muic_irqs[i].irq;
>
> - ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
> - 2, info->status);
> + ret = regmap_bulk_read(info->max8997->regmap_muic,
> + MAX8997_MUIC_REG_STATUS1, info->status, 2);
> if (ret) {
> dev_err(info->dev, "failed to read muic register\n");
> mutex_unlock(&info->mutex);
> @@ -605,8 +606,8 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
> mutex_lock(&info->mutex);
>
> /* Read STATUSx register to detect accessory */
> - ret = max8997_bulk_read(info->muic,
> - MAX8997_MUIC_REG_STATUS1, 2, info->status);
> + ret = regmap_bulk_read(info->max8997->regmap_muic,
> + MAX8997_MUIC_REG_STATUS1, info->status, 2);
> if (ret) {
> dev_err(info->dev, "failed to read MUIC register\n");
> mutex_unlock(&info->mutex);
> @@ -667,7 +668,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
> }
>
> info->dev = &pdev->dev;
> - info->muic = max8997->muic;
> + info->max8997 = max8997;
>
> platform_set_drvdata(pdev, info);
> mutex_init(&info->mutex);
> @@ -721,7 +722,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
>
> /* Initialize registers according to platform data */
> for (i = 0; i < muic_pdata->num_init_data; i++) {
> - max8997_write_reg(info->muic,
> + regmap_write(info->max8997->regmap_muic,
> muic_pdata->init_data[i].addr,
> muic_pdata->init_data[i].data);
> }
> diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
> index 1fea548..d3f7079 100644
> --- a/drivers/input/misc/max8997_haptic.c
> +++ b/drivers/input/misc/max8997_haptic.c
> @@ -31,6 +31,7 @@
> #include <linux/mfd/max8997-private.h>
> #include <linux/mfd/max8997.h>
> #include <linux/regulator/consumer.h>
> +#include <linux/regmap.h>
>
> /* Haptic configuration 2 register */
> #define MAX8997_MOTOR_TYPE_SHIFT 7
> @@ -45,7 +46,7 @@
>
> struct max8997_haptic {
> struct device *dev;
> - struct i2c_client *client;
> + struct max8997_dev *max8997;
> struct input_dev *input_dev;
> struct regulator *regulator;
>
> @@ -86,19 +87,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
> }
> switch (chip->internal_mode_pattern) {
> case 0:
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
> break;
> case 1:
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
> break;
> case 2:
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
> break;
> case 3:
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
> break;
> default:
> @@ -115,50 +116,51 @@ static void max8997_haptic_configure(struct max8997_haptic *chip)
> value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
> chip->enabled << MAX8997_ENABLE_SHIFT |
> chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
> - max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
> + regmap_write(chip->max8997->regmap_haptic,
> + MAX8997_HAPTIC_REG_CONF2, value);
>
> if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
> value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |
> chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
> chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
> chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_DRVCONF, value);
>
> switch (chip->internal_mode_pattern) {
> case 0:
> value = chip->pattern_cycle << 4;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_CYCLECONF1, value);
> value = chip->pattern_signal_period;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGCONF1, value);
> break;
>
> case 1:
> value = chip->pattern_cycle;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_CYCLECONF1, value);
> value = chip->pattern_signal_period;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGCONF2, value);
> break;
>
> case 2:
> value = chip->pattern_cycle << 4;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_CYCLECONF2, value);
> value = chip->pattern_signal_period;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGCONF3, value);
> break;
>
> case 3:
> value = chip->pattern_cycle;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_CYCLECONF2, value);
> value = chip->pattern_signal_period;
> - max8997_write_reg(chip->client,
> + regmap_write(chip->max8997->regmap_haptic,
> MAX8997_HAPTIC_REG_SIGCONF4, value);
> break;
>
> @@ -267,7 +269,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> INIT_WORK(&chip->work, max8997_haptic_play_effect_work);
> mutex_init(&chip->mutex);
>
> - chip->client = iodev->haptic;
> + chip->max8997 = iodev;
> chip->dev = &pdev->dev;
> chip->input_dev = input_dev;
> chip->pwm_period = haptic_pdata->pwm_period;
> diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
> index f449a8b..e2da8f2 100644
> --- a/drivers/leds/leds-max8997.c
> +++ b/drivers/leds/leds-max8997.c
For this leds change, please take my Ack
Acked-by: Bryan Wu <cooloney@gmail.com>
Thanks,
-Bryan
> @@ -18,6 +18,7 @@
> #include <linux/mfd/max8997.h>
> #include <linux/mfd/max8997-private.h>
> #include <linux/platform_device.h>
> +#include <linux/regmap.h>
>
> #define MAX8997_LED_FLASH_SHIFT 3
> #define MAX8997_LED_FLASH_CUR_MASK 0xf8
> @@ -53,7 +54,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
> enum max8997_led_mode mode)
> {
> int ret;
> - struct i2c_client *client = led->iodev->i2c;
> u8 mask = 0, val;
>
> switch (mode) {
> @@ -89,8 +89,8 @@ static void max8997_led_set_mode(struct max8997_led *led,
> }
>
> if (mask) {
> - ret = max8997_update_reg(client, MAX8997_REG_LEN_CNTL, val,
> - mask);
> + ret = regmap_update_bits(led->iodev->regmap,
> + MAX8997_REG_LEN_CNTL, mask, val);
> if (ret)
> dev_err(led->iodev->dev,
> "failed to update register(%d)\n", ret);
> @@ -102,7 +102,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
> static void max8997_led_enable(struct max8997_led *led, bool enable)
> {
> int ret;
> - struct i2c_client *client = led->iodev->i2c;
> u8 val = 0, mask = MAX8997_LED_BOOST_ENABLE_MASK;
>
> if (led->enabled == enable)
> @@ -110,7 +109,8 @@ static void max8997_led_enable(struct max8997_led *led, bool enable)
>
> val = enable ? MAX8997_LED_BOOST_ENABLE_MASK : 0;
>
> - ret = max8997_update_reg(client, MAX8997_REG_BOOST_CNTL, val, mask);
> + ret = regmap_update_bits(led->iodev->regmap,
> + MAX8997_REG_BOOST_CNTL, mask, val);
> if (ret)
> dev_err(led->iodev->dev,
> "failed to update register(%d)\n", ret);
> @@ -122,7 +122,6 @@ static void max8997_led_set_current(struct max8997_led *led,
> enum led_brightness value)
> {
> int ret;
> - struct i2c_client *client = led->iodev->i2c;
> u8 val = 0, mask = 0, reg = 0;
>
> switch (led->led_mode) {
> @@ -143,7 +142,7 @@ static void max8997_led_set_current(struct max8997_led *led,
> }
>
> if (mask) {
> - ret = max8997_update_reg(client, reg, val, mask);
> + ret = regmap_update_bits(led->iodev->regmap, reg, mask, val);
> if (ret)
> dev_err(led->iodev->dev,
> "failed to update register(%d)\n", ret);
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 456a7e7..2871a65 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -387,6 +387,7 @@ config MFD_MAX8997
> bool "Maxim Semiconductor MAX8997/8966 PMIC Support"
> depends on I2C=y
> select MFD_CORE
> + select REGMAP_I2C
> select IRQ_DOMAIN
> help
> Say yes here to add support for Maxim Semiconductor MAX8997/8966.
> diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
> index 43fa614..0e7ff39 100644
> --- a/drivers/mfd/max8997-irq.c
> +++ b/drivers/mfd/max8997-irq.c
> @@ -26,6 +26,7 @@
> #include <linux/interrupt.h>
> #include <linux/mfd/max8997.h>
> #include <linux/mfd/max8997-private.h>
> +#include <linux/regmap.h>
>
> static const u8 max8997_mask_reg[] = {
> [PMIC_INT1] = MAX8997_REG_INT1MSK,
> @@ -41,25 +42,6 @@ static const u8 max8997_mask_reg[] = {
> [FLASH_STATUS] = MAX8997_REG_INVALID,
> };
>
> -static struct i2c_client *get_i2c(struct max8997_dev *max8997,
> - enum max8997_irq_source src)
> -{
> - switch (src) {
> - case PMIC_INT1 ... PMIC_INT4:
> - return max8997->i2c;
> - case FUEL_GAUGE:
> - return NULL;
> - case MUIC_INT1 ... MUIC_INT3:
> - return max8997->muic;
> - case GPIO_LOW ... GPIO_HI:
> - return max8997->i2c;
> - case FLASH_STATUS:
> - return max8997->i2c;
> - default:
> - return ERR_PTR(-EINVAL);
> - }
> -}
> -
> struct max8997_irq_data {
> int mask;
> enum max8997_irq_source group;
> @@ -124,15 +106,20 @@ static void max8997_irq_sync_unlock(struct irq_data *data)
> int i;
>
> for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> + struct regmap *map;
> u8 mask_reg = max8997_mask_reg[i];
> - struct i2c_client *i2c = get_i2c(max8997, i);
> +
> + if (i >= MUIC_INT1 && i <= MUIC_INT3)
> + map = max8997->regmap_muic;
> + else
> + map = max8997->regmap;
>
> if (mask_reg == MAX8997_REG_INVALID ||
> - IS_ERR_OR_NULL(i2c))
> + IS_ERR_OR_NULL(map))
> continue;
> max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
>
> - max8997_write_reg(i2c, max8997_mask_reg[i],
> + regmap_write(map, max8997_mask_reg[i],
> max8997->irq_masks_cur[i]);
> }
>
> @@ -181,11 +168,11 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
> {
> struct max8997_dev *max8997 = data;
> u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
> - u8 irq_src;
> + unsigned int irq_src;
> int ret;
> int i, cur_irq;
>
> - ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
> + ret = regmap_read(max8997->regmap, MAX8997_REG_INTSRC, &irq_src);
> if (ret < 0) {
> dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
> ret);
> @@ -194,8 +181,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>
> if (irq_src & MAX8997_IRQSRC_PMIC) {
> /* PMIC INT1 ~ INT4 */
> - max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
> - &irq_reg[PMIC_INT1]);
> + regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
> + &irq_reg[PMIC_INT1], 4);
> }
> if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
> /*
> @@ -215,8 +202,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
> }
> if (irq_src & MAX8997_IRQSRC_MUIC) {
> /* MUIC INT1 ~ INT3 */
> - max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
> - &irq_reg[MUIC_INT1]);
> + regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
> + &irq_reg[MUIC_INT1], 3);
> }
> if (irq_src & MAX8997_IRQSRC_GPIO) {
> /* GPIO Interrupt */
> @@ -225,8 +212,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
> irq_reg[GPIO_LOW] = 0;
> irq_reg[GPIO_HI] = 0;
>
> - max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
> - MAX8997_NUM_GPIO, gpio_info);
> + regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
> + gpio_info, MAX8997_NUM_GPIO);
> for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> bool interrupt = false;
>
> @@ -260,8 +247,10 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
> }
> if (irq_src & MAX8997_IRQSRC_FLASH) {
> /* Flash Status Interrupt */
> - ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
> - &irq_reg[FLASH_STATUS]);
> + unsigned int data;
> + ret = regmap_read(max8997->regmap,
> + MAX8997_REG_FLASHSTATUS, &data);
> + irq_reg[FLASH_STATUS] = data;
> }
>
> /* Apply masking */
> @@ -312,7 +301,7 @@ int max8997_irq_init(struct max8997_dev *max8997)
> struct irq_domain *domain;
> int i;
> int ret;
> - u8 val;
> + unsigned int val;
>
> if (!max8997->irq) {
> dev_warn(max8997->dev, "No interrupt specified.\n");
> @@ -323,22 +312,19 @@ int max8997_irq_init(struct max8997_dev *max8997)
>
> /* Mask individual interrupt sources */
> for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> - struct i2c_client *i2c;
> -
> max8997->irq_masks_cur[i] = 0xff;
> max8997->irq_masks_cache[i] = 0xff;
> - i2c = get_i2c(max8997, i);
>
> - if (IS_ERR_OR_NULL(i2c))
> + if (IS_ERR_OR_NULL(max8997->regmap))
> continue;
> if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
> continue;
>
> - max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
> + regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
> }
>
> for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> - max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
> + max8997->gpio_status[i] = (regmap_read(max8997->regmap,
> MAX8997_REG_GPIOCNTL1 + i,
> &val)
> & MAX8997_GPIO_DATA_MASK) ?
> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> index 8cf7a01..782d7c9 100644
> --- a/drivers/mfd/max8997.c
> +++ b/drivers/mfd/max8997.c
> @@ -33,6 +33,7 @@
> #include <linux/mfd/core.h>
> #include <linux/mfd/max8997.h>
> #include <linux/mfd/max8997-private.h>
> +#include <linux/regmap.h>
>
> #define I2C_ADDR_PMIC (0xCC >> 1)
> #define I2C_ADDR_MUIC (0x4A >> 1)
> @@ -57,81 +58,29 @@ static struct of_device_id max8997_pmic_dt_match[] = {
> };
> #endif
>
> -int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
> -{
> - struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
> - int ret;
> -
> - mutex_lock(&max8997->iolock);
> - ret = i2c_smbus_read_byte_data(i2c, reg);
> - mutex_unlock(&max8997->iolock);
> - if (ret < 0)
> - return ret;
> -
> - ret &= 0xff;
> - *dest = ret;
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(max8997_read_reg);
> -
> -int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
> -{
> - struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
> - int ret;
> -
> - mutex_lock(&max8997->iolock);
> - ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
> - mutex_unlock(&max8997->iolock);
> - if (ret < 0)
> - return ret;
> -
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(max8997_bulk_read);
> -
> -int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
> -{
> - struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
> - int ret;
> -
> - mutex_lock(&max8997->iolock);
> - ret = i2c_smbus_write_byte_data(i2c, reg, value);
> - mutex_unlock(&max8997->iolock);
> - return ret;
> -}
> -EXPORT_SYMBOL_GPL(max8997_write_reg);
> -
> -int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
> -{
> - struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
> - int ret;
> +static const struct regmap_config max8997_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_REG_PMIC_END,
> +};
>
> - mutex_lock(&max8997->iolock);
> - ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
> - mutex_unlock(&max8997->iolock);
> - if (ret < 0)
> - return ret;
> +static const struct regmap_config max8997_regmap_rtc_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_RTC_REG_END,
> +};
>
> - return 0;
> -}
> -EXPORT_SYMBOL_GPL(max8997_bulk_write);
> +static const struct regmap_config max8997_regmap_haptic_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_HAPTIC_REG_END,
> +};
>
> -int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
> -{
> - struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
> - int ret;
> -
> - mutex_lock(&max8997->iolock);
> - ret = i2c_smbus_read_byte_data(i2c, reg);
> - if (ret >= 0) {
> - u8 old_val = ret & 0xff;
> - u8 new_val = (val & mask) | (old_val & (~mask));
> - ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
> - }
> - mutex_unlock(&max8997->iolock);
> - return ret;
> -}
> -EXPORT_SYMBOL_GPL(max8997_update_reg);
> +static const struct regmap_config max8997_regmap_muic_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_MUIC_REG_END,
> +};
>
> /*
> * Only the common platform data elements for max8997 are parsed here from the
> @@ -230,6 +179,41 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> }
> i2c_set_clientdata(max8997->muic, max8997);
>
> + max8997->regmap = devm_regmap_init_i2c(i2c, &max8997_regmap_config);
> + if (IS_ERR(max8997->regmap)) {
> + ret = PTR_ERR(max8997->regmap);
> + dev_err(max8997->dev,
> + "failed to allocate register map: %d\n", ret);
> + return ret;
> + }
> +
> + max8997->regmap_rtc = devm_regmap_init_i2c(max8997->rtc,
> + &max8997_regmap_rtc_config);
> + if (IS_ERR(max8997->regmap_rtc)) {
> + ret = PTR_ERR(max8997->regmap_rtc);
> + dev_err(max8997->dev,
> + "failed to allocate register map: %d\n", ret);
> + goto err_regmap;
> + }
> +
> + max8997->regmap_haptic = devm_regmap_init_i2c(max8997->haptic,
> + &max8997_regmap_haptic_config);
> + if (IS_ERR(max8997->regmap_haptic)) {
> + ret = PTR_ERR(max8997->regmap_haptic);
> + dev_err(max8997->dev,
> + "failed to allocate register map: %d\n", ret);
> + goto err_regmap;
> + }
> +
> + max8997->regmap_muic = devm_regmap_init_i2c(max8997->muic,
> + &max8997_regmap_muic_config);
> + if (IS_ERR(max8997->regmap_muic)) {
> + ret = PTR_ERR(max8997->regmap_muic);
> + dev_err(max8997->dev,
> + "failed to allocate register map: %d\n", ret);
> + goto err_regmap;
> + }
> +
> pm_runtime_set_active(max8997->dev);
>
> max8997_irq_init(max8997);
> @@ -254,6 +238,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>
> err_mfd:
> mfd_remove_devices(max8997->dev);
> +err_regmap:
> i2c_unregister_device(max8997->muic);
> err_i2c_muic:
> i2c_unregister_device(max8997->haptic);
> @@ -441,15 +426,15 @@ static int max8997_freeze(struct device *dev)
> int i;
>
> for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
> - max8997_read_reg(i2c, max8997_dumpaddr_pmic[i],
> + regmap_read(max8997->regmap, max8997_dumpaddr_pmic[i],
> &max8997->reg_dump[i]);
>
> for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
> - max8997_read_reg(i2c, max8997_dumpaddr_muic[i],
> + regmap_read(max8997->regmap_muic, max8997_dumpaddr_muic[i],
> &max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
>
> for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
> - max8997_read_reg(i2c, max8997_dumpaddr_haptic[i],
> + regmap_read(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
> &max8997->reg_dump[i + MAX8997_REG_PMIC_END +
> MAX8997_MUIC_REG_END]);
>
> @@ -463,15 +448,15 @@ static int max8997_restore(struct device *dev)
> int i;
>
> for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
> - max8997_write_reg(i2c, max8997_dumpaddr_pmic[i],
> + regmap_write(max8997->regmap, max8997_dumpaddr_pmic[i],
> max8997->reg_dump[i]);
>
> for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
> - max8997_write_reg(i2c, max8997_dumpaddr_muic[i],
> + regmap_write(max8997->regmap_muic, max8997_dumpaddr_muic[i],
> max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
>
> for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
> - max8997_write_reg(i2c, max8997_dumpaddr_haptic[i],
> + regmap_write(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
> max8997->reg_dump[i + MAX8997_REG_PMIC_END +
> MAX8997_MUIC_REG_END]);
>
> diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
> index 4bdedfe..43d8481 100644
> --- a/drivers/power/max8997_charger.c
> +++ b/drivers/power/max8997_charger.c
> @@ -26,6 +26,7 @@
> #include <linux/power_supply.h>
> #include <linux/mfd/max8997.h>
> #include <linux/mfd/max8997-private.h>
> +#include <linux/regmap.h>
>
> struct charger_data {
> struct device *dev;
> @@ -46,14 +47,14 @@ static int max8997_battery_get_property(struct power_supply *psy,
> {
> struct charger_data *charger = container_of(psy,
> struct charger_data, battery);
> - struct i2c_client *i2c = charger->iodev->i2c;
> int ret;
> - u8 reg;
> + unsigned int reg;
>
> switch (psp) {
> case POWER_SUPPLY_PROP_STATUS:
> val->intval = 0;
> - ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®);
> + ret = regmap_read(charger->iodev->regmap,
> + MAX8997_REG_STATUS4, ®);
> if (ret)
> return ret;
> if ((reg & (1 << 0)) == 0x1)
> @@ -62,7 +63,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
> break;
> case POWER_SUPPLY_PROP_PRESENT:
> val->intval = 0;
> - ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®);
> + ret = regmap_read(charger->iodev->regmap,
> + MAX8997_REG_STATUS4, ®);
> if (ret)
> return ret;
> if ((reg & (1 << 2)) == 0x0)
> @@ -71,7 +73,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
> break;
> case POWER_SUPPLY_PROP_ONLINE:
> val->intval = 0;
> - ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®);
> + ret = regmap_read(charger->iodev->regmap,
> + MAX8997_REG_STATUS4, ®);
> if (ret)
> return ret;
> /* DCINOK */
> @@ -103,8 +106,8 @@ static int max8997_battery_probe(struct platform_device *pdev)
> if (val > 0xf)
> val = 0xf;
>
> - ret = max8997_update_reg(iodev->i2c,
> - MAX8997_REG_MBCCTRL5, val, 0xf);
> + ret = regmap_update_bits(iodev->regmap,
> + MAX8997_REG_MBCCTRL5, 0xf, val);
> if (ret < 0) {
> dev_err(&pdev->dev, "Cannot use i2c bus.\n");
> return ret;
> @@ -113,20 +116,20 @@ static int max8997_battery_probe(struct platform_device *pdev)
>
> switch (pdata->timeout) {
> case 5:
> - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> - 0x2 << 4, 0x7 << 4);
> + ret = regmap_update_bits(iodev->regmap,
> + MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x2 << 4);
> break;
> case 6:
> - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> - 0x3 << 4, 0x7 << 4);
> + ret = regmap_update_bits(iodev->regmap,
> + MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x3 << 4);
> break;
> case 7:
> - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> - 0x4 << 4, 0x7 << 4);
> + ret = regmap_update_bits(iodev->regmap,
> + MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x4 << 4);
> break;
> case 0:
> - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> - 0x7 << 4, 0x7 << 4);
> + ret = regmap_update_bits(iodev->regmap,
> + MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x7 << 4);
> break;
> default:
> dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
> diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
> index 2d618fc..4001ed7 100644
> --- a/drivers/regulator/max8997.c
> +++ b/drivers/regulator/max8997.c
> @@ -33,6 +33,7 @@
> #include <linux/mfd/max8997.h>
> #include <linux/mfd/max8997-private.h>
> #include <linux/regulator/of_regulator.h>
> +#include <linux/regmap.h>
>
> struct max8997_data {
> struct device *dev;
> @@ -51,7 +52,7 @@ struct max8997_data {
> int buck125_gpioindex;
> bool ignore_gpiodvs_side_effect;
>
> - u8 saved_states[MAX8997_REG_MAX];
> + unsigned int saved_states[MAX8997_REG_MAX];
> };
>
> static const unsigned int safeoutvolt[] = {
> @@ -258,15 +259,14 @@ static int max8997_get_enable_register(struct regulator_dev *rdev,
> static int max8997_reg_is_enabled(struct regulator_dev *rdev)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int ret, reg, mask, pattern;
> - u8 val;
> + unsigned int val;
>
> ret = max8997_get_enable_register(rdev, ®, &mask, &pattern);
> if (ret)
> return ret;
>
> - ret = max8997_read_reg(i2c, reg, &val);
> + ret = regmap_read(max8997->iodev->regmap, reg, &val);
> if (ret)
> return ret;
>
> @@ -276,27 +276,25 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
> static int max8997_reg_enable(struct regulator_dev *rdev)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int ret, reg, mask, pattern;
>
> ret = max8997_get_enable_register(rdev, ®, &mask, &pattern);
> if (ret)
> return ret;
>
> - return max8997_update_reg(i2c, reg, pattern, mask);
> + return regmap_update_bits(max8997->iodev->regmap, reg, mask, pattern);
> }
>
> static int max8997_reg_disable(struct regulator_dev *rdev)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int ret, reg, mask, pattern;
>
> ret = max8997_get_enable_register(rdev, ®, &mask, &pattern);
> if (ret)
> return ret;
>
> - return max8997_update_reg(i2c, reg, ~pattern, mask);
> + return regmap_update_bits(max8997->iodev->regmap, reg, mask, ~pattern);
> }
>
> static int max8997_get_voltage_register(struct regulator_dev *rdev,
> @@ -368,15 +366,14 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
> static int max8997_get_voltage_sel(struct regulator_dev *rdev)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int reg, shift, mask, ret;
> - u8 val;
> + unsigned int val;
>
> ret = max8997_get_voltage_register(rdev, ®, &shift, &mask);
> if (ret)
> return ret;
>
> - ret = max8997_read_reg(i2c, reg, &val);
> + ret = regmap_read(max8997->iodev->regmap, reg, &val);
> if (ret)
> return ret;
>
> @@ -413,7 +410,6 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
> int min_uV, int max_uV, unsigned *selector)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int rid = rdev_get_id(rdev);
> int lb, ub;
> int reg, shift = 0, mask, ret = 0;
> @@ -455,7 +451,8 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
>
> *selector = val;
>
> - ret = max8997_update_reg(i2c, reg, val << shift, mask);
> + ret = regmap_update_bits(max8997->iodev->regmap,
> + reg, mask, val << shift);
>
> return ret;
> }
> @@ -468,7 +465,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
> int min_uV, int max_uV, unsigned *selector)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> const struct voltage_map_desc *desc;
> int rid = rdev_get_id(rdev);
> int i, reg, shift, mask, ret;
> @@ -500,7 +496,8 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
> if (ret)
> return ret;
>
> - ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
> + ret = regmap_update_bits(max8997->iodev->regmap,
> + reg, mask << shift, i << shift);
> *selector = i;
>
> return ret;
> @@ -710,7 +707,6 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
> unsigned selector)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int rid = rdev_get_id(rdev);
> int reg, shift = 0, mask, ret;
>
> @@ -721,13 +717,13 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
> if (ret)
> return ret;
>
> - return max8997_update_reg(i2c, reg, selector << shift, mask << shift);
> + return regmap_update_bits(max8997->iodev->regmap,
> + reg, mask << shift, selector << shift);
> }
>
> static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
> {
> struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> - struct i2c_client *i2c = max8997->iodev->i2c;
> int ret, reg, mask, pattern;
> int rid = rdev_get_id(rdev);
>
> @@ -735,20 +731,22 @@ static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
> if (ret)
> return ret;
>
> - max8997_read_reg(i2c, reg, &max8997->saved_states[rid]);
> + regmap_read(max8997->iodev->regmap,
> + reg, &max8997->saved_states[rid]);
>
> if (rid == MAX8997_LDO1 ||
> rid == MAX8997_LDO10 ||
> rid == MAX8997_LDO21) {
> dev_dbg(&rdev->dev, "Conditional Power-Off for %s\n",
> rdev->desc->name);
> - return max8997_update_reg(i2c, reg, 0x40, mask);
> + return regmap_update_bits(max8997->iodev->regmap,
> + reg, mask, 0x40);
> }
>
> dev_dbg(&rdev->dev, "Full Power-Off for %s (%xh -> %xh)\n",
> rdev->desc->name, max8997->saved_states[rid] & mask,
> (~pattern) & mask);
> - return max8997_update_reg(i2c, reg, ~pattern, mask);
> + return regmap_update_bits(max8997->iodev->regmap, reg, mask, ~pattern);
> }
>
> static struct regulator_ops max8997_ldo_ops = {
> @@ -1032,7 +1030,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
> struct regulator_config config = { };
> struct regulator_dev **rdev;
> struct max8997_data *max8997;
> - struct i2c_client *i2c;
> int i, ret, size, nr_dvs;
> u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
>
> @@ -1062,7 +1059,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
> max8997->iodev = iodev;
> max8997->num_regulators = pdata->num_regulators;
> platform_set_drvdata(pdev, max8997);
> - i2c = max8997->iodev->i2c;
>
> max8997->buck125_gpioindex = pdata->buck125_default_idx;
> max8997->buck1_gpiodvs = pdata->buck1_gpiodvs;
> @@ -1112,25 +1108,25 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>
> /* For the safety, set max voltage before setting up */
> for (i = 0; i < 8; i++) {
> - max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
> - max_buck1, 0x3f);
> - max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
> - max_buck2, 0x3f);
> - max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
> - max_buck5, 0x3f);
> + regmap_update_bits(max8997->iodev->regmap,
> + MAX8997_REG_BUCK1DVS1 + i, 0x3f, max_buck1);
> + regmap_update_bits(max8997->iodev->regmap,
> + MAX8997_REG_BUCK2DVS1 + i, 0x3f, max_buck2);
> + regmap_update_bits(max8997->iodev->regmap,
> + MAX8997_REG_BUCK5DVS1 + i, 0x3f, max_buck5);
> }
>
> /* Initialize all the DVS related BUCK registers */
> for (i = 0; i < nr_dvs; i++) {
> - max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
> - max8997->buck1_vol[i],
> - 0x3f);
> - max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
> - max8997->buck2_vol[i],
> - 0x3f);
> - max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
> - max8997->buck5_vol[i],
> - 0x3f);
> + regmap_update_bits(max8997->iodev->regmap,
> + MAX8997_REG_BUCK1DVS1 + i,
> + 0x3f, max8997->buck1_vol[i]);
> + regmap_update_bits(max8997->iodev->regmap,
> + MAX8997_REG_BUCK2DVS1 + i,
> + 0x3f, max8997->buck2_vol[i]);
> + regmap_update_bits(max8997->iodev->regmap,
> + MAX8997_REG_BUCK5DVS1 + i,
> + 0x3f, max8997->buck5_vol[i]);
> }
>
> /*
> @@ -1174,16 +1170,17 @@ static int max8997_pmic_probe(struct platform_device *pdev)
> }
>
> /* DVS-GPIO disabled */
> - max8997_update_reg(i2c, MAX8997_REG_BUCK1CTRL, (pdata->buck1_gpiodvs) ?
> - (1 << 1) : (0 << 1), 1 << 1);
> - max8997_update_reg(i2c, MAX8997_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ?
> - (1 << 1) : (0 << 1), 1 << 1);
> - max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
> - (1 << 1) : (0 << 1), 1 << 1);
> + regmap_update_bits(max8997->iodev->regmap, MAX8997_REG_BUCK1CTRL,
> + 1 << 1, (pdata->buck1_gpiodvs) ? (1 << 1) : (0 << 1));
> + regmap_update_bits(max8997->iodev->regmap, MAX8997_REG_BUCK2CTRL,
> + 1 << 1, (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
> + regmap_update_bits(max8997->iodev->regmap, MAX8997_REG_BUCK5CTRL,
> + 1 << 1, (pdata->buck5_gpiodvs) ? (1 << 1) : (0 << 1));
>
> /* Misc Settings */
> max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
> - max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
> + regmap_write(max8997->iodev->regmap,
> + MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
>
> for (i = 0; i < pdata->num_regulators; i++) {
> const struct voltage_map_desc *desc;
> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> index 0777c01..b866f7d5 100644
> --- a/drivers/rtc/rtc-max8997.c
> +++ b/drivers/rtc/rtc-max8997.c
> @@ -20,6 +20,7 @@
> #include <linux/platform_device.h>
> #include <linux/mfd/max8997-private.h>
> #include <linux/irqdomain.h>
> +#include <linux/regmap.h>
>
> /* Module parameter for WTSR function control */
> static int wtsr_en = 1;
> @@ -68,7 +69,6 @@ enum {
> struct max8997_rtc_info {
> struct device *dev;
> struct max8997_dev *max8997;
> - struct i2c_client *rtc;
> struct rtc_device *rtc_dev;
> struct mutex lock;
> int virq;
> @@ -118,8 +118,8 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
> {
> int ret;
>
> - ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1,
> - RTC_UDR_MASK);
> + ret = regmap_write(info->max8997->regmap_rtc,
> + MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
> if (ret < 0)
> dev_err(info->dev, "%s: fail to write update reg(%d)\n",
> __func__, ret);
> @@ -140,7 +140,8 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
> int ret;
>
> mutex_lock(&info->lock);
> - ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
> + ret = regmap_bulk_read(info->max8997->regmap_rtc,
> + MAX8997_RTC_SEC, data, RTC_NR_TIME);
> mutex_unlock(&info->lock);
>
> if (ret < 0) {
> @@ -166,7 +167,8 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
>
> mutex_lock(&info->lock);
>
> - ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
> + ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + MAX8997_RTC_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
> ret);
> @@ -183,13 +185,13 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> {
> struct max8997_rtc_info *info = dev_get_drvdata(dev);
> u8 data[RTC_NR_TIME];
> - u8 val;
> + unsigned int val;
> int i, ret;
>
> mutex_lock(&info->lock);
>
> - ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> - data);
> + ret = regmap_bulk_read(info->max8997->regmap_rtc,
> + MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
> __func__, __LINE__, ret);
> @@ -207,7 +209,8 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> }
>
> alrm->pending = 0;
> - ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val);
> + ret = regmap_read(info->max8997->regmap_rtc,
> + MAX8997_REG_STATUS1, &val);
> if (ret < 0) {
> dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
> __func__, __LINE__, ret);
> @@ -230,8 +233,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
> if (!mutex_is_locked(&info->lock))
> dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
>
> - ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> - data);
> + ret = regmap_bulk_read(info->max8997->regmap_rtc,
> + MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
> __func__, ret);
> @@ -241,8 +244,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
> for (i = 0; i < RTC_NR_TIME; i++)
> data[i] &= ~ALARM_ENABLE_MASK;
>
> - ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> - data);
> + ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> __func__, ret);
> @@ -262,8 +265,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
> if (!mutex_is_locked(&info->lock))
> dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
>
> - ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> - data);
> + ret = regmap_bulk_read(info->max8997->regmap_rtc,
> + MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
> __func__, ret);
> @@ -281,8 +284,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
> if (data[RTC_DATE] & 0x1f)
> data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
>
> - ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> - data);
> + ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> __func__, ret);
> @@ -313,8 +316,8 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> if (ret < 0)
> goto out;
>
> - ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> - data);
> + ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> __func__, ret);
> @@ -385,7 +388,8 @@ static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
> dev_info(info->dev, "%s: %s WTSR\n", __func__,
> enable ? "enable" : "disable");
>
> - ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
> + ret = regmap_update_bits(info->max8997->regmap_rtc,
> + MAX8997_RTC_WTSR_SMPL, mask, val);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
> __func__, ret);
> @@ -398,7 +402,7 @@ static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
> static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
> {
> int ret;
> - u8 val, mask;
> + unsigned int val, mask;
>
> if (!smpl_en)
> return;
> @@ -413,7 +417,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
> dev_info(info->dev, "%s: %s SMPL\n", __func__,
> enable ? "enable" : "disable");
>
> - ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
> + ret = regmap_update_bits(info->max8997->regmap_rtc,
> + MAX8997_RTC_WTSR_SMPL, mask, val);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
> __func__, ret);
> @@ -423,7 +428,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
> max8997_rtc_set_update_reg(info);
>
> val = 0;
> - max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val);
> + regmap_read(info->max8997->regmap_rtc,
> + MAX8997_RTC_WTSR_SMPL, &val);
> pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
> }
>
> @@ -438,7 +444,8 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
>
> info->rtc_24hr_mode = 1;
>
> - ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data);
> + ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + MAX8997_RTC_CTRLMASK, data, 2);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
> __func__, ret);
> @@ -463,7 +470,6 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> mutex_init(&info->lock);
> info->dev = &pdev->dev;
> info->max8997 = max8997;
> - info->rtc = max8997->rtc;
>
> platform_set_drvdata(pdev, info);
>
> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
> index 78c76cd..ea80ef8 100644
> --- a/include/linux/mfd/max8997-private.h
> +++ b/include/linux/mfd/max8997-private.h
> @@ -309,6 +309,8 @@ enum max8997_rtc_reg {
> MAX8997_RTC_ALARM2_MONTH = 0x22,
> MAX8997_RTC_ALARM2_YEAR = 0x23,
> MAX8997_RTC_ALARM2_DAY_OF_MONTH = 0x24,
> +
> + MAX8997_RTC_REG_END = 0x25,
> };
>
> enum max8997_irq_source {
> @@ -390,6 +392,11 @@ struct max8997_dev {
> unsigned long type;
> struct platform_device *battery; /* battery control (not fuel gauge) */
>
> + struct regmap *regmap;
> + struct regmap *regmap_rtc;
> + struct regmap *regmap_haptic;
> + struct regmap *regmap_muic;
> +
> int irq;
> int ono;
> struct irq_domain *irq_domain;
> @@ -398,7 +405,7 @@ struct max8997_dev {
> int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
>
> /* For hibernation */
> - u8 reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END +
> + unsigned int reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END +
> MAX8997_HAPTIC_REG_END];
>
> bool gpio_status[MAX8997_NUM_GPIO];
> @@ -413,14 +420,6 @@ extern int max8997_irq_init(struct max8997_dev *max8997);
> extern void max8997_irq_exit(struct max8997_dev *max8997);
> extern int max8997_irq_resume(struct max8997_dev *max8997);
>
> -extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
> -extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count,
> - u8 *buf);
> -extern int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
> -extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count,
> - u8 *buf);
> -extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
> -
> #define MAX8997_GPIO_INT_BOTH (0x3 << 4)
> #define MAX8997_GPIO_INT_RISE (0x2 << 4)
> #define MAX8997_GPIO_INT_FALL (0x1 << 4)
> --
> 1.7.9.5
>
^ permalink raw reply
* [PATCH] input synaptics-rmi4: Correctly configure RMI4 functions during initialization
From: Christopher Heiny @ 2014-03-19 0:21 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Linux Input, Christopher Heiny, Andrew Duggan, Vincent Huang,
Vivian Ly, Daniel Rosenberg, Linus Walleij, Benjamin Tissoires,
David Herrmann, Jiri Kosina, Courtney Cavin
Fix a bug where an RMI4 function handler's config() routine
was not be called during rmi_function_probe().
Reported-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: Linux Walleij <linus.walleij@linaro.org>
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Courtney Cavin <courtney.cavin@sonymobile.com>
---
drivers/input/rmi4/rmi_bus.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 6e0454a..2ed0d32 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -212,7 +212,14 @@ static int rmi_function_probe(struct device *dev)
if (handler->probe) {
error = handler->probe(fn);
- return error;
+ if (error)
+ return error;
+ }
+ if (handler->config) {
+ error = handler->config(fn);
+ if (error)
+ dev_warn(dev, "WARNING: Config for F%02x failed with code %d.\n",
+ handler->func, error);
}
return 0;
^ permalink raw reply related
* Re: [PATCH 03/11] Input: synaptics-rmi4 - do not update configuration in rmi_f01_probe()
From: Christopher Heiny @ 2014-03-19 0:21 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Andrew Duggan, Vincent Huang, Vivian Ly, Daniel Rosenberg,
Linus Walleij, Benjamin Tissoires, Courtney Cavin, Linux Input,
Linux Kernel
In-Reply-To: <1392269277-16391-3-git-send-email-dmitry.torokhov@gmail.com>
On 02/12/2014 09:27 PM, Dmitry Torokhov wrote:
> Do not write configuration data in probe(), we have config() for that.
I've just submitted a patch to correctly call config() after probe().
So this becomes...
Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/rmi4/rmi_f01.c | 18 ------------------
> 1 file changed, 18 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
> index 897d8ac..976aba3 100644
> --- a/drivers/input/rmi4/rmi_f01.c
> +++ b/drivers/input/rmi4/rmi_f01.c
> @@ -303,12 +303,6 @@ static int rmi_f01_initialize(struct rmi_function *fn)
> if (pdata->power_management.doze_interval) {
> data->device_control.doze_interval =
> pdata->power_management.doze_interval;
> - error = rmi_write(rmi_dev, data->doze_interval_addr,
> - data->device_control.doze_interval);
> - if (error < 0) {
> - dev_err(&fn->dev, "Failed to configure F01 doze interval register.\n");
> - return error;
> - }
> } else {
> error = rmi_read(rmi_dev, data->doze_interval_addr,
> &data->device_control.doze_interval);
> @@ -324,12 +318,6 @@ static int rmi_f01_initialize(struct rmi_function *fn)
> if (pdata->power_management.wakeup_threshold) {
> data->device_control.wakeup_threshold =
> pdata->power_management.wakeup_threshold;
> - error = rmi_write(rmi_dev, data->wakeup_threshold_addr,
> - data->device_control.wakeup_threshold);
> - if (error < 0) {
> - dev_err(&fn->dev, "Failed to configure F01 wakeup threshold register.\n");
> - return error;
> - }
> } else {
> error = rmi_read(rmi_dev, data->wakeup_threshold_addr,
> &data->device_control.wakeup_threshold);
> @@ -347,12 +335,6 @@ static int rmi_f01_initialize(struct rmi_function *fn)
> if (pdata->power_management.doze_holdoff) {
> data->device_control.doze_holdoff =
> pdata->power_management.doze_holdoff;
> - error = rmi_write(rmi_dev, data->doze_holdoff_addr,
> - data->device_control.doze_holdoff);
> - if (error < 0) {
> - dev_err(&fn->dev, "Failed to configure F01 doze holdoff register.\n");
> - return error;
> - }
> } else {
> error = rmi_read(rmi_dev, data->doze_holdoff_addr,
> &data->device_control.doze_holdoff);
>
--
Christopher Heiny
Senior Staff Firmware Engineer
Synaptics Incorporated
^ permalink raw reply
* [PATCH 3/3] Input: synaptics-rmi4 - report sensor resolution
From: Christopher Heiny @ 2014-03-19 1:03 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Linux Input, Christopher Heiny, Andrew Duggan, Vincent Huang,
Vivian Ly, Daniel Rosenberg, Linus Walleij, Benjamin Tissoires,
David Herrmann, Jiri Kosina
In-Reply-To: <1395191031-3144-1-git-send-email-cheiny@synaptics.com>
Reports the sensor resolution by reading the size of the sensor
from F11 query registers or from the platform data if the firmware
does not contain the appropriate query registers.
Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Acked-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: Linux Walleij <linus.walleij@linaro.org>
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Jiri Kosina <jkosina@suse.cz>
---
drivers/input/rmi4/rmi_f11.c | 53 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/rmi.h | 2 ++
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index f5b8b71..f2a6f5f 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -408,6 +408,10 @@ struct f11_2d_sensor_queries {
u8 clickpad_props;
u8 mouse_buttons;
bool has_advanced_gestures;
+
+ /* Query 15 - 18 */
+ u16 x_sensor_size_mm;
+ u16 y_sensor_size_mm;
};
/* Defs for Ctrl0. */
@@ -520,6 +524,8 @@ struct f11_2d_sensor {
struct rmi_function *fn;
char input_phys[NAME_BUFFER_SIZE];
char input_phys_mouse[NAME_BUFFER_SIZE];
+ u8 x_mm;
+ u8 y_mm;
u8 report_abs;
u8 report_rel;
};
@@ -1098,6 +1104,20 @@ static int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev,
query_size++;
}
+ if (f11->has_query12 && sensor_query->has_physical_props) {
+ rc = rmi_read_block(rmi_dev, query_base_addr
+ + query_size, query_buf, ARRAY_SIZE(query_buf));
+ if (rc < 0)
+ return rc;
+
+ sensor_query->x_sensor_size_mm =
+ (query_buf[0] | (query_buf[1] << 8)) / 10;
+ sensor_query->y_sensor_size_mm =
+ (query_buf[2] | (query_buf[3] << 8)) / 10;
+
+ query_size += 4;
+ }
+
return query_size;
}
@@ -1119,6 +1139,7 @@ static void f11_set_abs_params(struct rmi_function *fn, struct f11_data *f11)
((f11->dev_controls.ctrl0_9[9] & 0x0F) << 8);
u16 x_min, x_max, y_min, y_max;
unsigned int input_flags;
+ int res_x, res_y;
/* We assume touchscreen unless demonstrably a touchpad or specified
* as a touchpad in the platform data
@@ -1175,6 +1196,18 @@ static void f11_set_abs_params(struct rmi_function *fn, struct f11_data *f11)
x_min, x_max, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y,
y_min, y_max, 0, 0);
+
+ if (sensor->x_mm && sensor->y_mm) {
+ res_x = (x_max - x_min) / sensor->x_mm;
+ res_y = (y_max - y_min) / sensor->y_mm;
+
+ input_abs_set_res(input, ABS_X, res_x);
+ input_abs_set_res(input, ABS_Y, res_y);
+
+ input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
+ input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
+ }
+
if (!sensor->type_a)
input_mt_init_slots(input, sensor->nbr_fingers, input_flags);
if (IS_ENABLED(CONFIG_RMI4_F11_PEN) && sensor->sens_query.has_pen)
@@ -1261,8 +1294,26 @@ static int rmi_f11_initialize(struct rmi_function *fn)
sensor->axis_align =
pdata->f11_sensor_data->axis_align;
sensor->type_a = pdata->f11_sensor_data->type_a;
- sensor->sensor_type =
+
+ if (sensor->sens_query.has_info2) {
+ if (sensor->sens_query.is_clear)
+ sensor->sensor_type =
+ rmi_f11_sensor_touchscreen;
+ else
+ sensor->sensor_type = rmi_f11_sensor_touchpad;
+ } else {
+ sensor->sensor_type =
pdata->f11_sensor_data->sensor_type;
+ }
+
+ if (f11->has_query12
+ && sensor->sens_query.has_physical_props) {
+ sensor->x_mm = sensor->sens_query.x_sensor_size_mm;
+ sensor->y_mm = sensor->sens_query.y_sensor_size_mm;
+ } else {
+ sensor->x_mm = pdata->f11_sensor_data->x_mm;
+ sensor->y_mm = pdata->f11_sensor_data->y_mm;
+ }
if (sensor->sens_query.has_abs)
sensor->report_abs = sensor->report_abs
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index a0d0187..9139873 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -96,6 +96,8 @@ struct rmi_f11_sensor_data {
struct rmi_f11_2d_axis_alignment axis_align;
bool type_a;
enum rmi_f11_sensor_type sensor_type;
+ int x_mm;
+ int y_mm;
int disable_report_mask;
};
--
1.8.3.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox