* Re: [PATCH 1/5] drivers: input: keyboard: st-keyscan: add keyscan driver
From: Gabriel Fernandez @ 2014-03-14 10:13 UTC (permalink / raw)
To: Lee Jones
Cc: Mark Rutland, devicetree, Russell King, kernel, Pawel Moll,
Ian Campbell, Dmitry Torokhov, linux-doc, linux-kernel,
Rob Herring, Giuseppe Condorelli, Rob Landley, Kumar Gala,
Grant Likely, linux-input, linux-arm-kernel
In-Reply-To: <20140310114819.GO14976@lee--X1>
Hi Lee,
On 03/10/2014 12:48 PM, Lee Jones wrote:
> Hi Gabi,
>
> 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
>> +- 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" ?
>
> +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.
>
>> + To compile this driver as a module, choose M here: the
>> + module will be called stm-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..606cc19
>> --- /dev/null
>> +++ b/drivers/input/keyboard/st-keyscan.c
>> @@ -0,0 +1,323 @@
>> +/*
>> + * 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
> Did sh_keysc.c ever exist in Mainline?
i think no, i 'll suppress "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 0x000
>> +#define KEYSCAN_CONFIG_ENABLE 1
> 0x001?
>
>> +#define KEYSCAN_DEBOUNCE_TIME_OFF 0x004
>> +#define KEYSCAN_MATRIX_STATE_OFF 0x008
>> +#define KEYSCAN_MATRIX_DIM_OFF 0x00c
> Odd that these are 3 digit padded? Is there a reason for that?
no reason for the padded, i will change that.
>> +struct keypad_platform_data {
>> + const struct matrix_keymap_data *keymap_data;
>> + unsigned int num_out_pads;
>> + unsigned int num_in_pads;
>> + unsigned int debounce_us;
>> +};
>> +
>> +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'
> Nit: It's pretty unusual to use this for a standard error handling
> variable. Consider 'ret' or 'err' as a replacement.
>
>> + }
>> +
>> + of_property_read_u32(np, "st,debounce_us", &pdata->debounce_us);
> Isn't this a required property? Might be worth checking the return
> value if so.
no mandatory property, i will update the dt binding.
>
>> + st_kp->config = pdata;
>> +
>> + dev_info(dev, "rows=%d col=%d debounce=%d\n",
>> + pdata->num_out_pads,
>> + pdata->num_in_pads,
>> + pdata->debounce_us);
> Might be worth moving this down passed the final point of failure.
>
>> + error = of_property_read_u32_array(np, "linux,keymap",
>> + st_kp->keycodes, ST_KEYSCAN_MAXKEYS);
>> + if (error) {
>> + dev_err(dev, "failed to parse keymap\n");
>> + return error;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int __init keyscan_probe(struct platform_device *pdev)
>> +{
>> + struct keypad_platform_data *pdata =
>> + dev_get_platdata(&pdev->dev);
> Do we really support platform data still?
no, i will remove that.
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(dev, "no I/O memory specified\n");
> + return -ENXIO;
> + }
> +
> + len = resource_size(res);
> + if (!devm_request_mem_region(dev, res->start, len, pdev->name)) {
> + dev_err(dev, "failed to reserve I/O memory\n");
> + return -EBUSY;
> + }
> +
> + st_kp->base = devm_ioremap_nocache(dev, res->start, len);
> + if (st_kp->base == NULL) {
> + dev_err(dev, "failed to remap I/O memory\n");
> + return -ENXIO;
> + }
> Replace the two above with devm_ioremap_resource().
>
> Make sure the IORESOURCE_CACHEABLE is set.
ok, we are in no cacheable use case.
>
>> + }
>> +
>> + error = devm_request_irq(dev, st_kp->irq, keyscan_isr, 0,
>> + pdev->name, pdev);
>> + if (error) {
>> + dev_err(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;
>> + }
>> +
>> + st_kp->clk = devm_clk_get(dev, NULL);
>> + if (IS_ERR(st_kp->clk)) {
>> + dev_err(dev, "cannot get clock");
>> + return PTR_ERR(st_kp->clk);
>> + }
>> +
>> + input_dev = input_allocate_device();
>> + if (!input_dev) {
>> + dev_err(dev, "failed to allocate input device\n");
>> + return -ENOMEM;
>> + }
> Wasn't this done already?
yes, crap these lines.
>> + st_kp->input_dev = input_dev;
>> +
>> + input_dev->name = pdev->name;
>> + input_dev->phys = "keyscan-keys/input0";
>> + input_dev->dev.parent = dev;
>> +
>> + input_dev->id.bustype = BUS_HOST;
>> + input_dev->id.vendor = 0x0001;
>> + input_dev->id.product = 0x0001;
>> + input_dev->id.version = 0x0100;
> Any chance we can #define these?
i will follow Dmitry remark (omit these information)
>
>> + if (!pdata) {
>> + error = keypad_matrix_key_parse_dt(st_kp);
>> + if (error)
>> + return error;
>> + pdata = st_kp->config;
> Is pdata used after this?
no, i will remove platform data support
Thanks
^ permalink raw reply
* Re: [PATCH v3 2/4] mfd: max8997: handle IRQs using regmap
From: Robert Baldyga @ 2014-03-14 8:33 UTC (permalink / raw)
To: Chanwoo Choi
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: <53218C30.9000707@samsung.com>
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.
>
>> + }
>> +
>> return 0;
>> }
>>
>> @@ -478,9 +573,12 @@ static int max8997_resume(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, 0);
>> - return max8997_irq_resume(max8997);
>> + if (device_may_wakeup(dev)) {
>> + disable_irq_wake(max8997->irq);
>> + enable_irq(max8997->irq);
>
> ditto.
>
>> + }
>> +
>> + return 0;
>> }
>>
Thanks,
Robert Baldyga
^ permalink raw reply
* [PATCH] HID: hid-lg4ff: Support new version of G27
From: Simon Wood @ 2014-03-13 18:42 UTC (permalink / raw)
To: linux-input; +Cc: Jiri Kosina, linux-kernel, simon, Ivan Baldo, evilcow
It has been reported that there is a new hardware version of the G27
in the 'wild'. This patch add's this new revision so that it can be
sent the command to switch to native mode.
Reported-by: "Ivan Baldo" <ibaldo@adinet.com.uy>
Tested-by: "evilcow" <evilcow93@yahoo.com>
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index befe0e3..24883b4 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -43,6 +43,7 @@
#define G25_REV_MIN 0x22
#define G27_REV_MAJ 0x12
#define G27_REV_MIN 0x38
+#define G27_2_REV_MIN 0x39
#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
@@ -130,6 +131,7 @@ static const struct lg4ff_usb_revision lg4ff_revs[] = {
{DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */
{G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */
{G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */
+ {G27_REV_MAJ, G27_2_REV_MIN, &native_g27}, /* G27 v2 */
};
/* Recalculates X axis value accordingly to currently selected range */
--
1.8.1.2
^ permalink raw reply related
* Re: [PATCH v2 6/8] HID: sony: Add an IDA allocator to assign unique device ids
From: Frank Praznik @ 2014-03-13 14:30 UTC (permalink / raw)
To: Antonio Ospite, Frank Praznik; +Cc: linux-input, jkosina, dh.herrmann
In-Reply-To: <20140310232526.4dde47de732f8498a58fb731@ao2.it>
On 3/10/2014 18:25, Antonio Ospite wrote:
> Hi Frank,
>
> On Thu, 6 Mar 2014 17:32:54 -0500
> Frank Praznik <frank.praznik@oh.rr.com> wrote:
>
>> Add an IDA id allocator to assign unique, sequential device ids to Sixaxis and
>> DualShock 4 controllers.
>>
>> Use explicit module init and exit functions since the IDA allocator must be
>> manually destroyed when the module is unloaded.
>>
>> Use the device id as the unique number for the battery identification string.
>>
> Have you thought about using the bdaddr as the battery id?
>
> I think that decoupling led numbers (from the following patch) and
> battery ids would be saner. For instance in a scenario when userspace
> decided that the _second_ sixaxis has LEDs saying "controller
> 3" (because of different kind of joypads, remember?) we would have
> battery still saying "2" because the battery id is assigned at probe
> time while LEDs can change at any time. This mismatch may become
> confusing.
>
That's a good idea and it will match the naming scheme of the wiimote
battery device, which I think is the only other game controller that
reports battery status. I'll make the change for v3.
^ permalink raw reply
* Re: [PATCH v2 7/8] HID: sony: Initialize the controller LEDs with the device ID value
From: Frank Praznik @ 2014-03-13 14:24 UTC (permalink / raw)
To: Antonio Ospite, Frank Praznik; +Cc: linux-input, jkosina, dh.herrmann
In-Reply-To: <20140310235902.e09d0855b9c848a098b7ca36@ao2.it>
On 3/10/2014 18:59, Antonio Ospite wrote:
> On Thu, 6 Mar 2014 17:32:55 -0500
> Frank Praznik<frank.praznik@oh.rr.com> wrote:
>
>> Use the device ID to initialize the Sixaxis and DualShock 4 controller LEDs to
>> default values. The number or color of the controller is set relative to other
>> connected Sony controllers.
>>
> You already know I am not a huge fan of this idea for the sixaxis and I
> found another reason why: the Sixaxis requires the user to press the PS
> button before it starts to actually send events and the all-blink
> pattern is there to tell the user:
>
> "Look, even if the device is connected, it isn't fully functional yet,
> some action is required".
>
> That's also why the BlueZ sixaxis plugin waits for events before
> actually setting the LEDs via USB.
>
> Furthermore I still seem to get the all-blink pattern even with the
> patch applied, it seems to start _after_ the kernel driver set the
> default as per your patch; do you also experience this?
> And I still need a recent BLueZ with the sixaxis plugin to use the
> controller via BT so I don't see the benefits of defaults over BT
> either, but I am obviously biased.
Yeah, without the BlueZ plugin it keeps blinking on USB unless the PS
button is pressed almost immediately since the controller overrides the
initial settings and a new output report isn't sent until there is a
reason to do so (a rumble event or the LEDs changing in sysfs). I'm not
really sure how to fix that in the driver without some hack-ish
workarounds that may interfere with settings made in userland. It's
just an unavoidable quirk of the controller and no different from the
existing behavior in that specific case.
I can still see setting the defaults in the driver being of some use on
the Bluetooth side since there are a lot of distros that are still using
BlueZ 4.x which doesn't have the plugin (everything Debian based for
instance). You need a third party program like sixpair to do the
initial pairing, but it's still usable.
> Just please, if you can, test your changes in conjunction with the
> BlueZ sixaxis plugin in order to make sure the two don't step on each
> other toes too much.
I've tested it against the BlueZ plugin and there are no conflicts that
I've experienced. Like I've said before, the LEDs are only set to
defaults during initialization and then never touched by the driver once
the device is exposed to the system so the driver will never "step on
the toes" of userland settings. The driver has actually been setting
the LEDs to default values since someone else added the LED controls for
the Sixaxis in 3.14 and it doesn't seem to cause any problems. The only
difference this patch makes is that the LEDs are set to some meaningful
default instead of "all-off".
^ permalink raw reply
* Re: [PATCH v3 4/4] mfd: max8997: move regmap handling to function drivers
From: Mark Brown @ 2014-03-13 14:09 UTC (permalink / raw)
To: Lee Jones
Cc: Chanwoo Choi, Robert Baldyga, sameo, myungjoo.ham,
dmitry.torokhov, cooloney, rpurdie, dbaryshkov, dwmw2, lgirdwood,
a.zummo, paul.gortmaker, linux-kernel, linux-input, linux-leds,
rtc-linux, m.szyprowski, k.kozlowski
In-Reply-To: <20140313125504.GA10356@lee--X1>
[-- Attachment #1: Type: text/plain, Size: 743 bytes --]
On Thu, Mar 13, 2014 at 12:55:04PM +0000, Lee Jones wrote:
> > Is it necessary? If previous mfd driver has various i2c line, previous mfd driver
> > initialize regmap/i2c setting on mfd driver.
> > I'm not sure that regmap/i2c setting code move from mfd driver to each driver.
> >
> > Dear Lee Jones,
> > I need your opinion about moving regmap/i2c code from mfd driver to each driver.
> I'd rather take advice from Mark on this one.
I don't really case that much; I'm having a hard time seeing it as
particularly useful to do the refactoring but if it makes people
happy... Keeping things in the core would help promote reusability I
guess but I'm not sure that's likely to actually happen with this sort
of driver/device.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH v3 4/4] mfd: max8997: move regmap handling to function drivers
From: Lee Jones @ 2014-03-13 12:55 UTC (permalink / raw)
To: Chanwoo Choi
Cc: Robert Baldyga, sameo, 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: <532191E6.6080108@samsung.com>
> Is it necessary? If previous mfd driver has various i2c line, previous mfd driver
> initialize regmap/i2c setting on mfd driver.
> I'm not sure that regmap/i2c setting code move from mfd driver to each driver.
>
> Dear Lee Jones,
> I need your opinion about moving regmap/i2c code from mfd driver to each driver.
I'd rather take advice from Mark on this one.
> On 03/13/2014 06:38 PM, Robert Baldyga wrote:
> > This patch moves code creating new i2c clients and regmaps to function
> > drivers which use them. It allows to avoid creating this instances when
> > individual function drivers are not enabled.
I think this can be done with if()s, no?
<end>
> > Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> > ---
> > drivers/extcon/extcon-max8997.c | 131 +++++++++++++++++++++++++--
> > drivers/input/misc/max8997_haptic.c | 117 +++++++++++++++++++-----
> > drivers/mfd/max8997.c | 169 +----------------------------------
> > drivers/rtc/rtc-max8997.c | 78 +++++++++++-----
> > include/linux/mfd/max8997-private.h | 14 +--
> > 5 files changed, 284 insertions(+), 225 deletions(-)
> >
> > diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> > index 15fc5c0..51c2781 100644
> > --- a/drivers/extcon/extcon-max8997.c
> > +++ b/drivers/extcon/extcon-max8997.c
> > @@ -118,6 +118,9 @@ enum max8997_muic_charger_type {
> > struct max8997_muic_info {
> > struct device *dev;
> > struct max8997_dev *max8997;
> > + struct i2c_client *i2c;
> > + struct regmap *regmap;
> > + struct regmap_irq_chip_data *irq_data;
> > struct extcon_dev *edev;
> > int prev_cable_type;
> > int prev_chg_type;
> > @@ -144,6 +147,39 @@ struct max8997_muic_info {
> > */
> > int path_usb;
> > int path_uart;
> > +
> > + unsigned int reg_dump[MAX8997_MUIC_REG_END];
> > +};
> > +
> > +static const struct regmap_config max8997_muic_regmap_config = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = MAX8997_MUIC_REG_END,
> > +};
> > +
> > +static const struct regmap_irq max8997_irqs_muic[] = {
> > + /* MUIC_INT1 interrupts */
> > + { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
> > + { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
> > + { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
> > + /* MUIC_INT2 interrupts */
> > + { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
> > + { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
> > + { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
> > + { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
> > + { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
> > + /* MUIC_INT3 interrupts */
> > + { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
> > +};
> > +
> > +static const struct regmap_irq_chip max8997_muic_irq_chip = {
> > + .name = "max8997-muic",
> > + .status_base = MAX8997_MUIC_REG_INT1,
> > + .mask_base = MAX8997_MUIC_REG_INTMASK1,
> > + .mask_invert = true,
> > + .num_regs = 3,
> > + .irqs = max8997_irqs_muic,
> > + .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
> > };
> >
> > enum {
> > @@ -191,7 +227,7 @@ 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 = regmap_update_bits(info->max8997->regmap_muic,
> > + ret = regmap_update_bits(info->regmap,
> > MAX8997_MUIC_REG_CONTROL3,
> > CONTROL3_ADCDBSET_MASK,
> > time << CONTROL3_ADCDBSET_SHIFT);
> > @@ -229,7 +265,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
> > else
> > ctrl1 = CONTROL1_SW_OPEN;
> >
> > - ret = regmap_update_bits(info->max8997->regmap_muic,
> > + ret = regmap_update_bits(info->regmap,
> > MAX8997_MUIC_REG_CONTROL1, COMP_SW_MASK, ctrl1);
> > if (ret < 0) {
> > dev_err(info->dev, "failed to update MUIC register\n");
> > @@ -241,7 +277,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
> > else
> > ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
> >
> > - ret = regmap_update_bits(info->max8997->regmap_muic,
> > + ret = regmap_update_bits(info->regmap,
> > MAX8997_MUIC_REG_CONTROL2,
> > CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
> > if (ret < 0) {
> > @@ -544,7 +580,7 @@ static void max8997_muic_irq_work(struct work_struct *work)
> > if (info->irq == muic_irqs[i].virq)
> > irq_type = muic_irqs[i].irq;
> >
> > - ret = regmap_bulk_read(info->max8997->regmap_muic,
> > + ret = regmap_bulk_read(info->regmap,
> > MAX8997_MUIC_REG_STATUS1, info->status, 2);
> > if (ret) {
> > dev_err(info->dev, "failed to read muic register\n");
> > @@ -606,7 +642,7 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
> > mutex_lock(&info->mutex);
> >
> > /* Read STATUSx register to detect accessory */
> > - ret = regmap_bulk_read(info->max8997->regmap_muic,
> > + ret = regmap_bulk_read(info->regmap,
> > MAX8997_MUIC_REG_STATUS1, info->status, 2);
> > if (ret) {
> > dev_err(info->dev, "failed to read MUIC register\n");
> > @@ -670,6 +706,31 @@ static int max8997_muic_probe(struct platform_device *pdev)
> > info->dev = &pdev->dev;
> > info->max8997 = max8997;
> >
> > + info->i2c = i2c_new_dummy(max8997->i2c->adapter, MAX8997_I2C_ADDR_MUIC);
> > + if (!info->i2c) {
> > + dev_err(info->dev, "failed to allocate I2C device\n");
> > + return -ENODEV;
> > + }
> > +
> > + info->regmap = devm_regmap_init_i2c(info->i2c,
> > + &max8997_muic_regmap_config);
> > + if (IS_ERR(info->regmap)) {
> > + ret = PTR_ERR(info->regmap);
> > + dev_err(info->dev,
> > + "failed to allocate register map: %d\n", ret);
> > + goto err_regmap;
> > + }
> > +
> > + ret = regmap_add_irq_chip(info->regmap, max8997->irq,
> > + IRQF_ONESHOT | IRQF_SHARED |
> > + IRQF_TRIGGER_FALLING, 0,
> > + &max8997_muic_irq_chip,
> > + &info->irq_data);
> > + if (ret) {
> > + dev_err(info->dev, "failed to add irq chip: %d\n", ret);
> > + goto err_regmap;
> > + }
> > +
> > platform_set_drvdata(pdev, info);
> > mutex_init(&info->mutex);
> >
> > @@ -679,8 +740,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
> > struct max8997_muic_irq *muic_irq = &muic_irqs[i];
> > unsigned int virq = 0;
> >
> > - virq = regmap_irq_get_virq(max8997->irq_data_muic,
> > - muic_irq->irq);
> > + virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
> > if (!virq) {
> > ret = -EINVAL;
> > goto err_irq;
> > @@ -723,7 +783,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++) {
> > - regmap_write(info->max8997->regmap_muic,
> > + regmap_write(info->regmap,
> > muic_pdata->init_data[i].addr,
> > muic_pdata->init_data[i].data);
> > }
> > @@ -779,6 +839,9 @@ static int max8997_muic_probe(struct platform_device *pdev)
> > err_irq:
> > while (--i >= 0)
> > free_irq(muic_irqs[i].virq, info);
> > + regmap_del_irq_chip(info->max8997->irq, info->irq_data);
> > +err_regmap:
> > + i2c_unregister_device(info->i2c);
> > return ret;
> > }
> >
> > @@ -789,6 +852,9 @@ static int max8997_muic_remove(struct platform_device *pdev)
> >
> > for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
> > free_irq(muic_irqs[i].virq, info);
> > +
> > + regmap_del_irq_chip(info->max8997->irq, info->irq_data);
> > +
> > cancel_work_sync(&info->irq_work);
> >
> > extcon_dev_unregister(info->edev);
> > @@ -796,10 +862,59 @@ static int max8997_muic_remove(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static u8 max8997_muic_dumpaddr[] = {
> > + MAX8997_MUIC_REG_INTMASK1,
> > + MAX8997_MUIC_REG_INTMASK2,
> > + MAX8997_MUIC_REG_INTMASK3,
> > + MAX8997_MUIC_REG_CDETCTRL,
> > + MAX8997_MUIC_REG_CONTROL1,
> > + MAX8997_MUIC_REG_CONTROL2,
> > + MAX8997_MUIC_REG_CONTROL3,
> > +};
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int max8997_muic_freeze(struct device *dev)
> > +{
> > + struct platform_device *pdev =
> > + container_of(dev, struct platform_device, dev);
> > + struct max8997_muic_info *info = platform_get_drvdata(pdev);
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(max8997_muic_dumpaddr); i++)
> > + regmap_read(info->regmap, max8997_muic_dumpaddr[i],
> > + &info->reg_dump[i]);
> > +
> > + return 0;
> > +}
> > +
> > +static int max8997_muic_restore(struct device *dev)
> > +{
> > + struct platform_device *pdev =
> > + container_of(dev, struct platform_device, dev);
> > + struct max8997_muic_info *info = platform_get_drvdata(pdev);
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(max8997_muic_dumpaddr); i++)
> > + regmap_write(info->regmap, max8997_muic_dumpaddr[i],
> > + info->reg_dump[i]);
> > +
> > + return 0;
> > +}
> > +#endif
> > +
> > +static const struct dev_pm_ops max8997_muic_pm = {
> > +#ifdef CONFIG_PM_SLEEP
> > + .freeze = max8997_muic_freeze,
> > + .restore = max8997_muic_restore,
> > +#endif
> > +
> > +};
> > +
> > static struct platform_driver max8997_muic_driver = {
> > .driver = {
> > .name = DEV_NAME,
> > .owner = THIS_MODULE,
> > + .pm = &max8997_muic_pm,
> > },
> > .probe = max8997_muic_probe,
> > .remove = max8997_muic_remove,
> > diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
> > index d3f7079..9952eb2 100644
> > --- a/drivers/input/misc/max8997_haptic.c
> > +++ b/drivers/input/misc/max8997_haptic.c
> > @@ -47,6 +47,8 @@
> > struct max8997_haptic {
> > struct device *dev;
> > struct max8997_dev *max8997;
> > + struct i2c_client *i2c;
> > + struct regmap *regmap;
> > struct input_dev *input_dev;
> > struct regulator *regulator;
> >
> > @@ -66,6 +68,14 @@ struct max8997_haptic {
> > unsigned int internal_mode_pattern;
> > unsigned int pattern_cycle;
> > unsigned int pattern_signal_period;
> > +
> > + unsigned int reg_dump[MAX8997_HAPTIC_REG_END];
> > +};
> > +
> > +static const struct regmap_config max8997_haptic_regmap_config = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = MAX8997_HAPTIC_REG_END,
> > };
> >
> > static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
> > @@ -87,19 +97,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
> > }
> > switch (chip->internal_mode_pattern) {
> > case 0:
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
> > break;
> > case 1:
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
> > break;
> > case 2:
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
> > break;
> > case 3:
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
> > break;
> > default:
> > @@ -116,51 +126,49 @@ 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;
> > - regmap_write(chip->max8997->regmap_haptic,
> > - MAX8997_HAPTIC_REG_CONF2, value);
> > + regmap_write(chip->regmap, 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;
> > - regmap_write(chip->max8997->regmap_haptic,
> > - MAX8997_HAPTIC_REG_DRVCONF, value);
> > + regmap_write(chip->regmap, MAX8997_HAPTIC_REG_DRVCONF, value);
> >
> > switch (chip->internal_mode_pattern) {
> > case 0:
> > value = chip->pattern_cycle << 4;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_CYCLECONF1, value);
> > value = chip->pattern_signal_period;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGCONF1, value);
> > break;
> >
> > case 1:
> > value = chip->pattern_cycle;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_CYCLECONF1, value);
> > value = chip->pattern_signal_period;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGCONF2, value);
> > break;
> >
> > case 2:
> > value = chip->pattern_cycle << 4;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_CYCLECONF2, value);
> > value = chip->pattern_signal_period;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGCONF3, value);
> > break;
> >
> > case 3:
> > value = chip->pattern_cycle;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_CYCLECONF2, value);
> > value = chip->pattern_signal_period;
> > - regmap_write(chip->max8997->regmap_haptic,
> > + regmap_write(chip->regmap,
> > MAX8997_HAPTIC_REG_SIGCONF4, value);
> > break;
> >
> > @@ -277,6 +285,21 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> > chip->mode = haptic_pdata->mode;
> > chip->pwm_divisor = haptic_pdata->pwm_divisor;
> >
> > + chip->i2c = i2c_new_dummy(iodev->i2c->adapter, MAX8997_I2C_ADDR_HAPTIC);
> > + if (!chip->i2c) {
> > + dev_err(info->dev, "failed to allocate I2C device\n");
> > + return -ENODEV;
> > + }
> > +
> > + chip->regmap = devm_regmap_init_i2c(chip->i2c,
> > + &max8997_haptic_regmap_config);
> > + if (IS_ERR(chip->regmap)) {
> > + error = PTR_ERR(chip->regmap);
> > + dev_err(chip->dev,
> > + "failed to allocate register map: %d\n", error);
> > + goto err_free_i2c;
> > + }
> > +
> > switch (chip->mode) {
> > case MAX8997_INTERNAL_MODE:
> > chip->internal_mode_pattern =
> > @@ -294,7 +317,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> > dev_err(&pdev->dev,
> > "unable to request PWM for haptic, error: %d\n",
> > error);
> > - goto err_free_mem;
> > + goto err_free_i2c;
> > }
> > break;
> >
> > @@ -302,7 +325,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> > dev_err(&pdev->dev,
> > "Invalid chip mode specified (%d)\n", chip->mode);
> > error = -EINVAL;
> > - goto err_free_mem;
> > + goto err_free_i2c;
> > }
> >
> > chip->regulator = regulator_get(&pdev->dev, "inmotor");
> > @@ -348,6 +371,8 @@ err_put_regulator:
> > err_free_pwm:
> > if (chip->mode == MAX8997_EXTERNAL_MODE)
> > pwm_free(chip->pwm);
> > +err_free_i2c:
> > + i2c_unregister_device(chip->i2c);
> > err_free_mem:
> > input_free_device(input_dev);
> > kfree(chip);
> > @@ -370,6 +395,24 @@ static int max8997_haptic_remove(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static u8 max8997_haptic_dumpaddr[] = {
> > + MAX8997_HAPTIC_REG_CONF1,
> > + MAX8997_HAPTIC_REG_CONF2,
> > + MAX8997_HAPTIC_REG_DRVCONF,
> > + MAX8997_HAPTIC_REG_CYCLECONF1,
> > + MAX8997_HAPTIC_REG_CYCLECONF2,
> > + MAX8997_HAPTIC_REG_SIGCONF1,
> > + MAX8997_HAPTIC_REG_SIGCONF2,
> > + MAX8997_HAPTIC_REG_SIGCONF3,
> > + MAX8997_HAPTIC_REG_SIGCONF4,
> > + MAX8997_HAPTIC_REG_SIGDC1,
> > + MAX8997_HAPTIC_REG_SIGDC2,
> > + MAX8997_HAPTIC_REG_SIGPWMDC1,
> > + MAX8997_HAPTIC_REG_SIGPWMDC2,
> > + MAX8997_HAPTIC_REG_SIGPWMDC3,
> > + MAX8997_HAPTIC_REG_SIGPWMDC4,
> > +};
> > +
> > #ifdef CONFIG_PM_SLEEP
> > static int max8997_haptic_suspend(struct device *dev)
> > {
> > @@ -380,9 +423,43 @@ static int max8997_haptic_suspend(struct device *dev)
> >
> > return 0;
> > }
> > +
> > +static int max8997_haptic_freeze(struct device *dev)
> > +{
> > + struct platform_device *pdev =
> > + container_of(dev, struct platform_device, dev);
> > + struct max8997_haptic *chip = platform_get_drvdata(pdev);
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(max8997_haptic_dumpaddr); i++)
> > + regmap_read(chip->regmap, max8997_haptic_dumpaddr[i],
> > + &chip->reg_dump[i]);
> > +
> > + return 0;
> > +}
> > +
> > +static int max8997_haptic_restore(struct device *dev)
> > +{
> > + struct platform_device *pdev =
> > + container_of(dev, struct platform_device, dev);
> > + struct max8997_haptic *chip = platform_get_drvdata(pdev);
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(max8997_haptic_dumpaddr); i++)
> > + regmap_write(chip->regmap, max8997_haptic_dumpaddr[i],
> > + chip->reg_dump[i]);
> > +
> > + return 0;
> > +}
> > #endif
> >
> > -static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
> > +static const struct dev_pm_ops max8997_haptic_pm = {
> > +#ifdef CONFIG_PM_SLEEP
> > + .suspend = max8997_haptic_suspend,
> > + .freeze = max8997_haptic_freeze,
> > + .restore = max8997_haptic_restore,
> > +#endif
> > +};
> >
> > static const struct platform_device_id max8997_haptic_id[] = {
> > { "max8997-haptic", 0 },
> > @@ -394,7 +471,7 @@ static struct platform_driver max8997_haptic_driver = {
> > .driver = {
> > .name = "max8997-haptic",
> > .owner = THIS_MODULE,
> > - .pm = &max8997_haptic_pm_ops,
> > + .pm = &max8997_haptic_pm,
> > },
> > .probe = max8997_haptic_probe,
> > .remove = max8997_haptic_remove,
> > diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> > index 5a35b3f..e4f37d3 100644
> > --- a/drivers/mfd/max8997.c
> > +++ b/drivers/mfd/max8997.c
> > @@ -35,12 +35,6 @@
> > #include <linux/mfd/max8997-private.h>
> > #include <linux/regmap.h>
> >
> > -#define I2C_ADDR_PMIC (0xCC >> 1)
> > -#define I2C_ADDR_MUIC (0x4A >> 1)
> > -#define I2C_ADDR_BATTERY (0x6C >> 1)
> > -#define I2C_ADDR_RTC (0x0C >> 1)
> > -#define I2C_ADDR_HAPTIC (0x90 >> 1)
> > -
> > static const struct mfd_cell max8997_devs[] = {
> > { .name = "max8997-pmic", },
> > { .name = "max8997-rtc", },
> > @@ -107,48 +101,6 @@ static const struct regmap_irq_chip max8997_irq_chip = {
> > .num_irqs = ARRAY_SIZE(max8997_irqs),
> > };
> >
> > -static const struct regmap_config max8997_regmap_rtc_config = {
> > - .reg_bits = 8,
> > - .val_bits = 8,
> > - .max_register = MAX8997_RTC_REG_END,
> > -};
> > -
> > -static const struct regmap_config max8997_regmap_haptic_config = {
> > - .reg_bits = 8,
> > - .val_bits = 8,
> > - .max_register = MAX8997_HAPTIC_REG_END,
> > -};
> > -
> > -static const struct regmap_config max8997_regmap_muic_config = {
> > - .reg_bits = 8,
> > - .val_bits = 8,
> > - .max_register = MAX8997_MUIC_REG_END,
> > -};
> > -
> > -static const struct regmap_irq max8997_irqs_muic[] = {
> > - /* MUIC_INT1 interrupts */
> > - { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
> > - { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
> > - { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
> > - /* MUIC_INT2 interrupts */
> > - { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
> > - { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
> > - { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
> > - { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
> > - { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
> > - /* MUIC_INT3 interrupts */
> > - { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
> > -};
> > -
> > -static const struct regmap_irq_chip max8997_irq_chip_muic = {
> > - .name = "max8997-muic",
> > - .status_base = MAX8997_MUIC_REG_INT1,
> > - .mask_base = MAX8997_MUIC_REG_INTMASK1,
> > - .mask_invert = true,
> > - .num_regs = 3,
> > - .irqs = max8997_irqs_muic,
> > - .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
> > -};
> >
> > /*
> > * Only the common platform data elements for max8997 are parsed here from the
> > @@ -224,29 +176,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> >
> > mutex_init(&max8997->iolock);
> >
> > - max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
> > - if (!max8997->rtc) {
> > - dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n");
> > - return -ENODEV;
> > - }
> > - i2c_set_clientdata(max8997->rtc, max8997);
> > -
> > - max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
> > - if (!max8997->haptic) {
> > - dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n");
> > - ret = -ENODEV;
> > - goto err_i2c_haptic;
> > - }
> > - i2c_set_clientdata(max8997->haptic, max8997);
> > -
> > - max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
> > - if (!max8997->muic) {
> > - dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n");
> > - ret = -ENODEV;
> > - goto err_i2c_muic;
> > - }
> > - 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);
> > @@ -255,50 +184,13 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> > 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;
> > - }
> > -
> > ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
> > IRQF_ONESHOT | IRQF_SHARED |
> > IRQF_TRIGGER_FALLING, 0,
> > &max8997_irq_chip, &max8997->irq_data);
> > if (ret) {
> > dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> > - goto err_regmap;
> > - }
> > -
> > - ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
> > - IRQF_ONESHOT | IRQF_SHARED |
> > - IRQF_TRIGGER_FALLING, 0,
> > - &max8997_irq_chip_muic,
> > - &max8997->irq_data_muic);
> > - if (ret) {
> > - dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> > - goto err_irq_muic;
> > + return ret;
> > }
> >
> > pm_runtime_set_active(max8997->dev);
> > @@ -323,15 +215,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> >
> > err_mfd:
> > mfd_remove_devices(max8997->dev);
> > - regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> > -err_irq_muic:
> > regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> > -err_regmap:
> > - i2c_unregister_device(max8997->muic);
> > -err_i2c_muic:
> > - i2c_unregister_device(max8997->haptic);
> > -err_i2c_haptic:
> > - i2c_unregister_device(max8997->rtc);
> > return ret;
> > }
> >
> > @@ -341,13 +225,8 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
> >
> > mfd_remove_devices(max8997->dev);
> >
> > - regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> > regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> >
> > - i2c_unregister_device(max8997->muic);
> > - i2c_unregister_device(max8997->haptic);
> > - i2c_unregister_device(max8997->rtc);
> > -
> > return 0;
> > }
> >
> > @@ -483,34 +362,6 @@ static u8 max8997_dumpaddr_pmic[] = {
> > MAX8997_REG_DVSOKTIMER5,
> > };
> >
> > -static u8 max8997_dumpaddr_muic[] = {
> > - MAX8997_MUIC_REG_INTMASK1,
> > - MAX8997_MUIC_REG_INTMASK2,
> > - MAX8997_MUIC_REG_INTMASK3,
> > - MAX8997_MUIC_REG_CDETCTRL,
> > - MAX8997_MUIC_REG_CONTROL1,
> > - MAX8997_MUIC_REG_CONTROL2,
> > - MAX8997_MUIC_REG_CONTROL3,
> > -};
> > -
> > -static u8 max8997_dumpaddr_haptic[] = {
> > - MAX8997_HAPTIC_REG_CONF1,
> > - MAX8997_HAPTIC_REG_CONF2,
> > - MAX8997_HAPTIC_REG_DRVCONF,
> > - MAX8997_HAPTIC_REG_CYCLECONF1,
> > - MAX8997_HAPTIC_REG_CYCLECONF2,
> > - MAX8997_HAPTIC_REG_SIGCONF1,
> > - MAX8997_HAPTIC_REG_SIGCONF2,
> > - MAX8997_HAPTIC_REG_SIGCONF3,
> > - MAX8997_HAPTIC_REG_SIGCONF4,
> > - MAX8997_HAPTIC_REG_SIGDC1,
> > - MAX8997_HAPTIC_REG_SIGDC2,
> > - MAX8997_HAPTIC_REG_SIGPWMDC1,
> > - MAX8997_HAPTIC_REG_SIGPWMDC2,
> > - MAX8997_HAPTIC_REG_SIGPWMDC3,
> > - MAX8997_HAPTIC_REG_SIGPWMDC4,
> > -};
> > -
> > static int max8997_freeze(struct device *dev)
> > {
> > struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
> > @@ -521,15 +372,6 @@ static int max8997_freeze(struct device *dev)
> > regmap_read(max8997->regmap, max8997_dumpaddr_pmic[i],
> > &max8997->reg_dump[i]);
> >
> > - for (i = 0; i < ARRAY_SIZE(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++)
> > - regmap_read(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
> > - &max8997->reg_dump[i + MAX8997_REG_PMIC_END +
> > - MAX8997_MUIC_REG_END]);
> > -
> > return 0;
> > }
> >
> > @@ -543,15 +385,6 @@ static int max8997_restore(struct device *dev)
> > regmap_write(max8997->regmap, max8997_dumpaddr_pmic[i],
> > max8997->reg_dump[i]);
> >
> > - for (i = 0; i < ARRAY_SIZE(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++)
> > - regmap_write(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
> > - max8997->reg_dump[i + MAX8997_REG_PMIC_END +
> > - MAX8997_MUIC_REG_END]);
> > -
> > return 0;
> > }
> >
> > diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> > index 22769ea..57fab040 100644
> > --- a/drivers/rtc/rtc-max8997.c
> > +++ b/drivers/rtc/rtc-max8997.c
> > @@ -69,12 +69,20 @@ enum {
> > struct max8997_rtc_info {
> > struct device *dev;
> > struct max8997_dev *max8997;
> > + struct i2c_client *i2c;
> > + struct regmap *regmap;
> > struct rtc_device *rtc_dev;
> > struct mutex lock;
> > int virq;
> > int rtc_24hr_mode;
> > };
> >
> > +static const struct regmap_config max8997_rtc_regmap_config = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = MAX8997_RTC_REG_END,
> > +};
> > +
> > static void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
> > int rtc_24hr_mode)
> > {
> > @@ -118,8 +126,7 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
> > {
> > int ret;
> >
> > - ret = regmap_write(info->max8997->regmap_rtc,
> > - MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
> > + ret = regmap_write(info->regmap, 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 +147,7 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
> > int ret;
> >
> > mutex_lock(&info->lock);
> > - ret = regmap_bulk_read(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_read(info->regmap,
> > MAX8997_RTC_SEC, data, RTC_NR_TIME);
> > mutex_unlock(&info->lock);
> >
> > @@ -167,7 +174,7 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
> >
> > mutex_lock(&info->lock);
> >
> > - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_write(info->regmap,
> > MAX8997_RTC_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
> > @@ -190,7 +197,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> >
> > mutex_lock(&info->lock);
> >
> > - ret = regmap_bulk_read(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_read(info->regmap,
> > MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
> > @@ -209,8 +216,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > }
> >
> > alrm->pending = 0;
> > - ret = regmap_read(info->max8997->regmap_rtc,
> > - MAX8997_REG_STATUS1, &val);
> > + ret = regmap_read(info->regmap, MAX8997_REG_STATUS1, &val);
> > if (ret < 0) {
> > dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
> > __func__, __LINE__, ret);
> > @@ -233,7 +239,7 @@ 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 = regmap_bulk_read(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_read(info->regmap,
> > MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
> > @@ -244,7 +250,7 @@ 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 = regmap_bulk_write(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_write(info->regmap,
> > MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> > @@ -265,7 +271,7 @@ 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 = regmap_bulk_read(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_read(info->regmap,
> > MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
> > @@ -284,7 +290,7 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
> > if (data[RTC_DATE] & 0x1f)
> > data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
> >
> > - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_write(info->regmap,
> > MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> > @@ -316,7 +322,7 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > if (ret < 0)
> > goto out;
> >
> > - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_write(info->regmap,
> > MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> > @@ -388,7 +394,7 @@ 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 = regmap_update_bits(info->max8997->regmap_rtc,
> > + ret = regmap_update_bits(info->regmap,
> > MAX8997_RTC_WTSR_SMPL, mask, val);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
> > @@ -417,7 +423,7 @@ 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 = regmap_update_bits(info->max8997->regmap_rtc,
> > + ret = regmap_update_bits(info->regmap,
> > MAX8997_RTC_WTSR_SMPL, mask, val);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
> > @@ -428,8 +434,7 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
> > max8997_rtc_set_update_reg(info);
> >
> > val = 0;
> > - regmap_read(info->max8997->regmap_rtc,
> > - MAX8997_RTC_WTSR_SMPL, &val);
> > + regmap_read(info->regmap, MAX8997_RTC_WTSR_SMPL, &val);
> > pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
> > }
> >
> > @@ -444,7 +449,7 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
> >
> > info->rtc_24hr_mode = 1;
> >
> > - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> > + ret = regmap_bulk_write(info->regmap,
> > MAX8997_RTC_CTRLMASK, data, 2);
> > if (ret < 0) {
> > dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
> > @@ -471,13 +476,28 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> > info->dev = &pdev->dev;
> > info->max8997 = max8997;
> >
> > + info->i2c = i2c_new_dummy(max8997->i2c->adapter, MAX8997_I2C_ADDR_RTC);
> > + if (!info->i2c) {
> > + dev_err(info->dev, "failed to allocate I2C device\n");
> > + return -ENODEV;
> > + }
> > +
> > + info->regmap = devm_regmap_init_i2c(info->i2c,
> > + &max8997_rtc_regmap_config);
> > + if (IS_ERR(info->regmap)) {
> > + ret = PTR_ERR(info->regmap);
> > + dev_err(info->dev,
> > + "failed to allocate register map: %d\n", ret);
> > + goto err_regmap;
> > + }
> > +
> > platform_set_drvdata(pdev, info);
> >
> > ret = max8997_rtc_init_reg(info);
> >
> > if (ret < 0) {
> > dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
> > - return ret;
> > + goto err_regmap;
> > }
> >
> > max8997_rtc_enable_wtsr(info, true);
> > @@ -491,28 +511,41 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> > if (IS_ERR(info->rtc_dev)) {
> > ret = PTR_ERR(info->rtc_dev);
> > dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
> > - return ret;
> > + goto err_regmap;
> > }
> >
> > virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
> > if (!virq) {
> > dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
> > ret = -ENXIO;
> > - goto err_out;
> > + goto err_regmap;
> > }
> > info->virq = virq;
> >
> > ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
> > max8997_rtc_alarm_irq, 0,
> > "rtc-alarm0", info);
> > - if (ret < 0)
> > + if (ret < 0) {
> > dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
> > info->virq, ret);
> > + goto err_regmap;
> > + }
> > +
> > + return ret;
> >
> > -err_out:
> > +err_regmap:
> > + i2c_unregister_device(info->i2c);
> > return ret;
> > }
> >
> > +static int max8997_rtc_remove(struct platform_device *pdev)
> > +{
> > + struct max8997_rtc_info *info = platform_get_drvdata(pdev);
> > + i2c_unregister_device(info->i2c);
> > +
> > + return 0;
> > +}
> > +
> > static void max8997_rtc_shutdown(struct platform_device *pdev)
> > {
> > struct max8997_rtc_info *info = platform_get_drvdata(pdev);
> > @@ -532,6 +565,7 @@ static struct platform_driver max8997_rtc_driver = {
> > .owner = THIS_MODULE,
> > },
> > .probe = max8997_rtc_probe,
> > + .remove = max8997_rtc_remove,
> > .shutdown = max8997_rtc_shutdown,
> > .id_table = rtc_id,
> > };
> > diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
> > index 2817fa6..c2458c3 100644
> > --- a/include/linux/mfd/max8997-private.h
> > +++ b/include/linux/mfd/max8997-private.h
> > @@ -26,6 +26,13 @@
> > #include <linux/export.h>
> > #include <linux/irqdomain.h>
> >
> > +#define MAX8997_I2C_ADDR_PMIC (0xCC >> 1)
> > +#define MAX8997_I2C_ADDR_MUIC (0x4A >> 1)
> > +#define MAX8997_I2C_ADDR_BATTERY (0x6C >> 1)
> > +#define MAX8997_I2C_ADDR_RTC (0x0C >> 1)
> > +#define MAX8997_I2C_ADDR_HAPTIC (0x90 >> 1)
> > +
> > +
> > #define MAX8997_REG_INVALID (0xff)
> >
> > enum max8997_pmic_reg {
> > @@ -430,21 +437,14 @@ struct max8997_dev {
> > struct device *dev;
> > struct max8997_platform_data *pdata;
> > struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
> > - struct i2c_client *rtc; /* slave addr 0x0c */
> > - struct i2c_client *haptic; /* slave addr 0x90 */
> > - struct i2c_client *muic; /* slave addr 0x4a */
> > struct mutex iolock;
> >
> > 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;
> >
> > struct regmap_irq_chip_data *irq_data;
> > - struct regmap_irq_chip_data *irq_data_muic;
> > int irq;
> > int ono;
> > struct mutex irqlock;
> >
>
--
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 v3 4/4] mfd: max8997: move regmap handling to function drivers
From: Chanwoo Choi @ 2014-03-13 11:09 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: <1394703532-494-5-git-send-email-r.baldyga@samsung.com>
Hi Robert,
Is it necessary? If previous mfd driver has various i2c line, previous mfd driver
initialize regmap/i2c setting on mfd driver.
I'm not sure that regmap/i2c setting code move from mfd driver to each driver.
Dear Lee Jones,
I need your opinion about moving regmap/i2c code from mfd driver to each driver.
Best Regards,
Chanwoo Choi
On 03/13/2014 06:38 PM, Robert Baldyga wrote:
> This patch moves code creating new i2c clients and regmaps to function
> drivers which use them. It allows to avoid creating this instances when
> individual function drivers are not enabled.
>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
> drivers/extcon/extcon-max8997.c | 131 +++++++++++++++++++++++++--
> drivers/input/misc/max8997_haptic.c | 117 +++++++++++++++++++-----
> drivers/mfd/max8997.c | 169 +----------------------------------
> drivers/rtc/rtc-max8997.c | 78 +++++++++++-----
> include/linux/mfd/max8997-private.h | 14 +--
> 5 files changed, 284 insertions(+), 225 deletions(-)
>
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index 15fc5c0..51c2781 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -118,6 +118,9 @@ enum max8997_muic_charger_type {
> struct max8997_muic_info {
> struct device *dev;
> struct max8997_dev *max8997;
> + struct i2c_client *i2c;
> + struct regmap *regmap;
> + struct regmap_irq_chip_data *irq_data;
> struct extcon_dev *edev;
> int prev_cable_type;
> int prev_chg_type;
> @@ -144,6 +147,39 @@ struct max8997_muic_info {
> */
> int path_usb;
> int path_uart;
> +
> + unsigned int reg_dump[MAX8997_MUIC_REG_END];
> +};
> +
> +static const struct regmap_config max8997_muic_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_MUIC_REG_END,
> +};
> +
> +static const struct regmap_irq max8997_irqs_muic[] = {
> + /* MUIC_INT1 interrupts */
> + { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
> + { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
> + { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
> + /* MUIC_INT2 interrupts */
> + { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
> + /* MUIC_INT3 interrupts */
> + { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
> +};
> +
> +static const struct regmap_irq_chip max8997_muic_irq_chip = {
> + .name = "max8997-muic",
> + .status_base = MAX8997_MUIC_REG_INT1,
> + .mask_base = MAX8997_MUIC_REG_INTMASK1,
> + .mask_invert = true,
> + .num_regs = 3,
> + .irqs = max8997_irqs_muic,
> + .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
> };
>
> enum {
> @@ -191,7 +227,7 @@ 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 = regmap_update_bits(info->max8997->regmap_muic,
> + ret = regmap_update_bits(info->regmap,
> MAX8997_MUIC_REG_CONTROL3,
> CONTROL3_ADCDBSET_MASK,
> time << CONTROL3_ADCDBSET_SHIFT);
> @@ -229,7 +265,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
> else
> ctrl1 = CONTROL1_SW_OPEN;
>
> - ret = regmap_update_bits(info->max8997->regmap_muic,
> + ret = regmap_update_bits(info->regmap,
> MAX8997_MUIC_REG_CONTROL1, COMP_SW_MASK, ctrl1);
> if (ret < 0) {
> dev_err(info->dev, "failed to update MUIC register\n");
> @@ -241,7 +277,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
> else
> ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
>
> - ret = regmap_update_bits(info->max8997->regmap_muic,
> + ret = regmap_update_bits(info->regmap,
> MAX8997_MUIC_REG_CONTROL2,
> CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
> if (ret < 0) {
> @@ -544,7 +580,7 @@ static void max8997_muic_irq_work(struct work_struct *work)
> if (info->irq == muic_irqs[i].virq)
> irq_type = muic_irqs[i].irq;
>
> - ret = regmap_bulk_read(info->max8997->regmap_muic,
> + ret = regmap_bulk_read(info->regmap,
> MAX8997_MUIC_REG_STATUS1, info->status, 2);
> if (ret) {
> dev_err(info->dev, "failed to read muic register\n");
> @@ -606,7 +642,7 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
> mutex_lock(&info->mutex);
>
> /* Read STATUSx register to detect accessory */
> - ret = regmap_bulk_read(info->max8997->regmap_muic,
> + ret = regmap_bulk_read(info->regmap,
> MAX8997_MUIC_REG_STATUS1, info->status, 2);
> if (ret) {
> dev_err(info->dev, "failed to read MUIC register\n");
> @@ -670,6 +706,31 @@ static int max8997_muic_probe(struct platform_device *pdev)
> info->dev = &pdev->dev;
> info->max8997 = max8997;
>
> + info->i2c = i2c_new_dummy(max8997->i2c->adapter, MAX8997_I2C_ADDR_MUIC);
> + if (!info->i2c) {
> + dev_err(info->dev, "failed to allocate I2C device\n");
> + return -ENODEV;
> + }
> +
> + info->regmap = devm_regmap_init_i2c(info->i2c,
> + &max8997_muic_regmap_config);
> + if (IS_ERR(info->regmap)) {
> + ret = PTR_ERR(info->regmap);
> + dev_err(info->dev,
> + "failed to allocate register map: %d\n", ret);
> + goto err_regmap;
> + }
> +
> + ret = regmap_add_irq_chip(info->regmap, max8997->irq,
> + IRQF_ONESHOT | IRQF_SHARED |
> + IRQF_TRIGGER_FALLING, 0,
> + &max8997_muic_irq_chip,
> + &info->irq_data);
> + if (ret) {
> + dev_err(info->dev, "failed to add irq chip: %d\n", ret);
> + goto err_regmap;
> + }
> +
> platform_set_drvdata(pdev, info);
> mutex_init(&info->mutex);
>
> @@ -679,8 +740,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
> struct max8997_muic_irq *muic_irq = &muic_irqs[i];
> unsigned int virq = 0;
>
> - virq = regmap_irq_get_virq(max8997->irq_data_muic,
> - muic_irq->irq);
> + virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
> if (!virq) {
> ret = -EINVAL;
> goto err_irq;
> @@ -723,7 +783,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++) {
> - regmap_write(info->max8997->regmap_muic,
> + regmap_write(info->regmap,
> muic_pdata->init_data[i].addr,
> muic_pdata->init_data[i].data);
> }
> @@ -779,6 +839,9 @@ static int max8997_muic_probe(struct platform_device *pdev)
> err_irq:
> while (--i >= 0)
> free_irq(muic_irqs[i].virq, info);
> + regmap_del_irq_chip(info->max8997->irq, info->irq_data);
> +err_regmap:
> + i2c_unregister_device(info->i2c);
> return ret;
> }
>
> @@ -789,6 +852,9 @@ static int max8997_muic_remove(struct platform_device *pdev)
>
> for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
> free_irq(muic_irqs[i].virq, info);
> +
> + regmap_del_irq_chip(info->max8997->irq, info->irq_data);
> +
> cancel_work_sync(&info->irq_work);
>
> extcon_dev_unregister(info->edev);
> @@ -796,10 +862,59 @@ static int max8997_muic_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static u8 max8997_muic_dumpaddr[] = {
> + MAX8997_MUIC_REG_INTMASK1,
> + MAX8997_MUIC_REG_INTMASK2,
> + MAX8997_MUIC_REG_INTMASK3,
> + MAX8997_MUIC_REG_CDETCTRL,
> + MAX8997_MUIC_REG_CONTROL1,
> + MAX8997_MUIC_REG_CONTROL2,
> + MAX8997_MUIC_REG_CONTROL3,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int max8997_muic_freeze(struct device *dev)
> +{
> + struct platform_device *pdev =
> + container_of(dev, struct platform_device, dev);
> + struct max8997_muic_info *info = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(max8997_muic_dumpaddr); i++)
> + regmap_read(info->regmap, max8997_muic_dumpaddr[i],
> + &info->reg_dump[i]);
> +
> + return 0;
> +}
> +
> +static int max8997_muic_restore(struct device *dev)
> +{
> + struct platform_device *pdev =
> + container_of(dev, struct platform_device, dev);
> + struct max8997_muic_info *info = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(max8997_muic_dumpaddr); i++)
> + regmap_write(info->regmap, max8997_muic_dumpaddr[i],
> + info->reg_dump[i]);
> +
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops max8997_muic_pm = {
> +#ifdef CONFIG_PM_SLEEP
> + .freeze = max8997_muic_freeze,
> + .restore = max8997_muic_restore,
> +#endif
> +
> +};
> +
> static struct platform_driver max8997_muic_driver = {
> .driver = {
> .name = DEV_NAME,
> .owner = THIS_MODULE,
> + .pm = &max8997_muic_pm,
> },
> .probe = max8997_muic_probe,
> .remove = max8997_muic_remove,
> diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
> index d3f7079..9952eb2 100644
> --- a/drivers/input/misc/max8997_haptic.c
> +++ b/drivers/input/misc/max8997_haptic.c
> @@ -47,6 +47,8 @@
> struct max8997_haptic {
> struct device *dev;
> struct max8997_dev *max8997;
> + struct i2c_client *i2c;
> + struct regmap *regmap;
> struct input_dev *input_dev;
> struct regulator *regulator;
>
> @@ -66,6 +68,14 @@ struct max8997_haptic {
> unsigned int internal_mode_pattern;
> unsigned int pattern_cycle;
> unsigned int pattern_signal_period;
> +
> + unsigned int reg_dump[MAX8997_HAPTIC_REG_END];
> +};
> +
> +static const struct regmap_config max8997_haptic_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_HAPTIC_REG_END,
> };
>
> static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
> @@ -87,19 +97,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
> }
> switch (chip->internal_mode_pattern) {
> case 0:
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
> break;
> case 1:
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
> break;
> case 2:
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
> break;
> case 3:
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
> break;
> default:
> @@ -116,51 +126,49 @@ 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;
> - regmap_write(chip->max8997->regmap_haptic,
> - MAX8997_HAPTIC_REG_CONF2, value);
> + regmap_write(chip->regmap, 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;
> - regmap_write(chip->max8997->regmap_haptic,
> - MAX8997_HAPTIC_REG_DRVCONF, value);
> + regmap_write(chip->regmap, MAX8997_HAPTIC_REG_DRVCONF, value);
>
> switch (chip->internal_mode_pattern) {
> case 0:
> value = chip->pattern_cycle << 4;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_CYCLECONF1, value);
> value = chip->pattern_signal_period;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGCONF1, value);
> break;
>
> case 1:
> value = chip->pattern_cycle;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_CYCLECONF1, value);
> value = chip->pattern_signal_period;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGCONF2, value);
> break;
>
> case 2:
> value = chip->pattern_cycle << 4;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_CYCLECONF2, value);
> value = chip->pattern_signal_period;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGCONF3, value);
> break;
>
> case 3:
> value = chip->pattern_cycle;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_CYCLECONF2, value);
> value = chip->pattern_signal_period;
> - regmap_write(chip->max8997->regmap_haptic,
> + regmap_write(chip->regmap,
> MAX8997_HAPTIC_REG_SIGCONF4, value);
> break;
>
> @@ -277,6 +285,21 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> chip->mode = haptic_pdata->mode;
> chip->pwm_divisor = haptic_pdata->pwm_divisor;
>
> + chip->i2c = i2c_new_dummy(iodev->i2c->adapter, MAX8997_I2C_ADDR_HAPTIC);
> + if (!chip->i2c) {
> + dev_err(info->dev, "failed to allocate I2C device\n");
> + return -ENODEV;
> + }
> +
> + chip->regmap = devm_regmap_init_i2c(chip->i2c,
> + &max8997_haptic_regmap_config);
> + if (IS_ERR(chip->regmap)) {
> + error = PTR_ERR(chip->regmap);
> + dev_err(chip->dev,
> + "failed to allocate register map: %d\n", error);
> + goto err_free_i2c;
> + }
> +
> switch (chip->mode) {
> case MAX8997_INTERNAL_MODE:
> chip->internal_mode_pattern =
> @@ -294,7 +317,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> dev_err(&pdev->dev,
> "unable to request PWM for haptic, error: %d\n",
> error);
> - goto err_free_mem;
> + goto err_free_i2c;
> }
> break;
>
> @@ -302,7 +325,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
> dev_err(&pdev->dev,
> "Invalid chip mode specified (%d)\n", chip->mode);
> error = -EINVAL;
> - goto err_free_mem;
> + goto err_free_i2c;
> }
>
> chip->regulator = regulator_get(&pdev->dev, "inmotor");
> @@ -348,6 +371,8 @@ err_put_regulator:
> err_free_pwm:
> if (chip->mode == MAX8997_EXTERNAL_MODE)
> pwm_free(chip->pwm);
> +err_free_i2c:
> + i2c_unregister_device(chip->i2c);
> err_free_mem:
> input_free_device(input_dev);
> kfree(chip);
> @@ -370,6 +395,24 @@ static int max8997_haptic_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static u8 max8997_haptic_dumpaddr[] = {
> + MAX8997_HAPTIC_REG_CONF1,
> + MAX8997_HAPTIC_REG_CONF2,
> + MAX8997_HAPTIC_REG_DRVCONF,
> + MAX8997_HAPTIC_REG_CYCLECONF1,
> + MAX8997_HAPTIC_REG_CYCLECONF2,
> + MAX8997_HAPTIC_REG_SIGCONF1,
> + MAX8997_HAPTIC_REG_SIGCONF2,
> + MAX8997_HAPTIC_REG_SIGCONF3,
> + MAX8997_HAPTIC_REG_SIGCONF4,
> + MAX8997_HAPTIC_REG_SIGDC1,
> + MAX8997_HAPTIC_REG_SIGDC2,
> + MAX8997_HAPTIC_REG_SIGPWMDC1,
> + MAX8997_HAPTIC_REG_SIGPWMDC2,
> + MAX8997_HAPTIC_REG_SIGPWMDC3,
> + MAX8997_HAPTIC_REG_SIGPWMDC4,
> +};
> +
> #ifdef CONFIG_PM_SLEEP
> static int max8997_haptic_suspend(struct device *dev)
> {
> @@ -380,9 +423,43 @@ static int max8997_haptic_suspend(struct device *dev)
>
> return 0;
> }
> +
> +static int max8997_haptic_freeze(struct device *dev)
> +{
> + struct platform_device *pdev =
> + container_of(dev, struct platform_device, dev);
> + struct max8997_haptic *chip = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(max8997_haptic_dumpaddr); i++)
> + regmap_read(chip->regmap, max8997_haptic_dumpaddr[i],
> + &chip->reg_dump[i]);
> +
> + return 0;
> +}
> +
> +static int max8997_haptic_restore(struct device *dev)
> +{
> + struct platform_device *pdev =
> + container_of(dev, struct platform_device, dev);
> + struct max8997_haptic *chip = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(max8997_haptic_dumpaddr); i++)
> + regmap_write(chip->regmap, max8997_haptic_dumpaddr[i],
> + chip->reg_dump[i]);
> +
> + return 0;
> +}
> #endif
>
> -static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
> +static const struct dev_pm_ops max8997_haptic_pm = {
> +#ifdef CONFIG_PM_SLEEP
> + .suspend = max8997_haptic_suspend,
> + .freeze = max8997_haptic_freeze,
> + .restore = max8997_haptic_restore,
> +#endif
> +};
>
> static const struct platform_device_id max8997_haptic_id[] = {
> { "max8997-haptic", 0 },
> @@ -394,7 +471,7 @@ static struct platform_driver max8997_haptic_driver = {
> .driver = {
> .name = "max8997-haptic",
> .owner = THIS_MODULE,
> - .pm = &max8997_haptic_pm_ops,
> + .pm = &max8997_haptic_pm,
> },
> .probe = max8997_haptic_probe,
> .remove = max8997_haptic_remove,
> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> index 5a35b3f..e4f37d3 100644
> --- a/drivers/mfd/max8997.c
> +++ b/drivers/mfd/max8997.c
> @@ -35,12 +35,6 @@
> #include <linux/mfd/max8997-private.h>
> #include <linux/regmap.h>
>
> -#define I2C_ADDR_PMIC (0xCC >> 1)
> -#define I2C_ADDR_MUIC (0x4A >> 1)
> -#define I2C_ADDR_BATTERY (0x6C >> 1)
> -#define I2C_ADDR_RTC (0x0C >> 1)
> -#define I2C_ADDR_HAPTIC (0x90 >> 1)
> -
> static const struct mfd_cell max8997_devs[] = {
> { .name = "max8997-pmic", },
> { .name = "max8997-rtc", },
> @@ -107,48 +101,6 @@ static const struct regmap_irq_chip max8997_irq_chip = {
> .num_irqs = ARRAY_SIZE(max8997_irqs),
> };
>
> -static const struct regmap_config max8997_regmap_rtc_config = {
> - .reg_bits = 8,
> - .val_bits = 8,
> - .max_register = MAX8997_RTC_REG_END,
> -};
> -
> -static const struct regmap_config max8997_regmap_haptic_config = {
> - .reg_bits = 8,
> - .val_bits = 8,
> - .max_register = MAX8997_HAPTIC_REG_END,
> -};
> -
> -static const struct regmap_config max8997_regmap_muic_config = {
> - .reg_bits = 8,
> - .val_bits = 8,
> - .max_register = MAX8997_MUIC_REG_END,
> -};
> -
> -static const struct regmap_irq max8997_irqs_muic[] = {
> - /* MUIC_INT1 interrupts */
> - { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
> - { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
> - { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
> - /* MUIC_INT2 interrupts */
> - { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
> - { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
> - { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
> - { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
> - { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
> - /* MUIC_INT3 interrupts */
> - { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
> -};
> -
> -static const struct regmap_irq_chip max8997_irq_chip_muic = {
> - .name = "max8997-muic",
> - .status_base = MAX8997_MUIC_REG_INT1,
> - .mask_base = MAX8997_MUIC_REG_INTMASK1,
> - .mask_invert = true,
> - .num_regs = 3,
> - .irqs = max8997_irqs_muic,
> - .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
> -};
>
> /*
> * Only the common platform data elements for max8997 are parsed here from the
> @@ -224,29 +176,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>
> mutex_init(&max8997->iolock);
>
> - max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
> - if (!max8997->rtc) {
> - dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n");
> - return -ENODEV;
> - }
> - i2c_set_clientdata(max8997->rtc, max8997);
> -
> - max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
> - if (!max8997->haptic) {
> - dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n");
> - ret = -ENODEV;
> - goto err_i2c_haptic;
> - }
> - i2c_set_clientdata(max8997->haptic, max8997);
> -
> - max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
> - if (!max8997->muic) {
> - dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n");
> - ret = -ENODEV;
> - goto err_i2c_muic;
> - }
> - 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);
> @@ -255,50 +184,13 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> 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;
> - }
> -
> ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
> IRQF_ONESHOT | IRQF_SHARED |
> IRQF_TRIGGER_FALLING, 0,
> &max8997_irq_chip, &max8997->irq_data);
> if (ret) {
> dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> - goto err_regmap;
> - }
> -
> - ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
> - IRQF_ONESHOT | IRQF_SHARED |
> - IRQF_TRIGGER_FALLING, 0,
> - &max8997_irq_chip_muic,
> - &max8997->irq_data_muic);
> - if (ret) {
> - dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> - goto err_irq_muic;
> + return ret;
> }
>
> pm_runtime_set_active(max8997->dev);
> @@ -323,15 +215,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>
> err_mfd:
> mfd_remove_devices(max8997->dev);
> - regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> -err_irq_muic:
> regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> -err_regmap:
> - i2c_unregister_device(max8997->muic);
> -err_i2c_muic:
> - i2c_unregister_device(max8997->haptic);
> -err_i2c_haptic:
> - i2c_unregister_device(max8997->rtc);
> return ret;
> }
>
> @@ -341,13 +225,8 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
>
> mfd_remove_devices(max8997->dev);
>
> - regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> regmap_del_irq_chip(max8997->irq, max8997->irq_data);
>
> - i2c_unregister_device(max8997->muic);
> - i2c_unregister_device(max8997->haptic);
> - i2c_unregister_device(max8997->rtc);
> -
> return 0;
> }
>
> @@ -483,34 +362,6 @@ static u8 max8997_dumpaddr_pmic[] = {
> MAX8997_REG_DVSOKTIMER5,
> };
>
> -static u8 max8997_dumpaddr_muic[] = {
> - MAX8997_MUIC_REG_INTMASK1,
> - MAX8997_MUIC_REG_INTMASK2,
> - MAX8997_MUIC_REG_INTMASK3,
> - MAX8997_MUIC_REG_CDETCTRL,
> - MAX8997_MUIC_REG_CONTROL1,
> - MAX8997_MUIC_REG_CONTROL2,
> - MAX8997_MUIC_REG_CONTROL3,
> -};
> -
> -static u8 max8997_dumpaddr_haptic[] = {
> - MAX8997_HAPTIC_REG_CONF1,
> - MAX8997_HAPTIC_REG_CONF2,
> - MAX8997_HAPTIC_REG_DRVCONF,
> - MAX8997_HAPTIC_REG_CYCLECONF1,
> - MAX8997_HAPTIC_REG_CYCLECONF2,
> - MAX8997_HAPTIC_REG_SIGCONF1,
> - MAX8997_HAPTIC_REG_SIGCONF2,
> - MAX8997_HAPTIC_REG_SIGCONF3,
> - MAX8997_HAPTIC_REG_SIGCONF4,
> - MAX8997_HAPTIC_REG_SIGDC1,
> - MAX8997_HAPTIC_REG_SIGDC2,
> - MAX8997_HAPTIC_REG_SIGPWMDC1,
> - MAX8997_HAPTIC_REG_SIGPWMDC2,
> - MAX8997_HAPTIC_REG_SIGPWMDC3,
> - MAX8997_HAPTIC_REG_SIGPWMDC4,
> -};
> -
> static int max8997_freeze(struct device *dev)
> {
> struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
> @@ -521,15 +372,6 @@ static int max8997_freeze(struct device *dev)
> regmap_read(max8997->regmap, max8997_dumpaddr_pmic[i],
> &max8997->reg_dump[i]);
>
> - for (i = 0; i < ARRAY_SIZE(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++)
> - regmap_read(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
> - &max8997->reg_dump[i + MAX8997_REG_PMIC_END +
> - MAX8997_MUIC_REG_END]);
> -
> return 0;
> }
>
> @@ -543,15 +385,6 @@ static int max8997_restore(struct device *dev)
> regmap_write(max8997->regmap, max8997_dumpaddr_pmic[i],
> max8997->reg_dump[i]);
>
> - for (i = 0; i < ARRAY_SIZE(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++)
> - regmap_write(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
> - max8997->reg_dump[i + MAX8997_REG_PMIC_END +
> - MAX8997_MUIC_REG_END]);
> -
> return 0;
> }
>
> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> index 22769ea..57fab040 100644
> --- a/drivers/rtc/rtc-max8997.c
> +++ b/drivers/rtc/rtc-max8997.c
> @@ -69,12 +69,20 @@ enum {
> struct max8997_rtc_info {
> struct device *dev;
> struct max8997_dev *max8997;
> + struct i2c_client *i2c;
> + struct regmap *regmap;
> struct rtc_device *rtc_dev;
> struct mutex lock;
> int virq;
> int rtc_24hr_mode;
> };
>
> +static const struct regmap_config max8997_rtc_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = MAX8997_RTC_REG_END,
> +};
> +
> static void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
> int rtc_24hr_mode)
> {
> @@ -118,8 +126,7 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
> {
> int ret;
>
> - ret = regmap_write(info->max8997->regmap_rtc,
> - MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
> + ret = regmap_write(info->regmap, 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 +147,7 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
> int ret;
>
> mutex_lock(&info->lock);
> - ret = regmap_bulk_read(info->max8997->regmap_rtc,
> + ret = regmap_bulk_read(info->regmap,
> MAX8997_RTC_SEC, data, RTC_NR_TIME);
> mutex_unlock(&info->lock);
>
> @@ -167,7 +174,7 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
>
> mutex_lock(&info->lock);
>
> - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + ret = regmap_bulk_write(info->regmap,
> MAX8997_RTC_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
> @@ -190,7 +197,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>
> mutex_lock(&info->lock);
>
> - ret = regmap_bulk_read(info->max8997->regmap_rtc,
> + ret = regmap_bulk_read(info->regmap,
> MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
> @@ -209,8 +216,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> }
>
> alrm->pending = 0;
> - ret = regmap_read(info->max8997->regmap_rtc,
> - MAX8997_REG_STATUS1, &val);
> + ret = regmap_read(info->regmap, MAX8997_REG_STATUS1, &val);
> if (ret < 0) {
> dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
> __func__, __LINE__, ret);
> @@ -233,7 +239,7 @@ 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 = regmap_bulk_read(info->max8997->regmap_rtc,
> + ret = regmap_bulk_read(info->regmap,
> MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
> @@ -244,7 +250,7 @@ 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 = regmap_bulk_write(info->max8997->regmap_rtc,
> + ret = regmap_bulk_write(info->regmap,
> MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> @@ -265,7 +271,7 @@ 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 = regmap_bulk_read(info->max8997->regmap_rtc,
> + ret = regmap_bulk_read(info->regmap,
> MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
> @@ -284,7 +290,7 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
> if (data[RTC_DATE] & 0x1f)
> data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
>
> - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + ret = regmap_bulk_write(info->regmap,
> MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> @@ -316,7 +322,7 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> if (ret < 0)
> goto out;
>
> - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + ret = regmap_bulk_write(info->regmap,
> MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
> @@ -388,7 +394,7 @@ 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 = regmap_update_bits(info->max8997->regmap_rtc,
> + ret = regmap_update_bits(info->regmap,
> MAX8997_RTC_WTSR_SMPL, mask, val);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
> @@ -417,7 +423,7 @@ 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 = regmap_update_bits(info->max8997->regmap_rtc,
> + ret = regmap_update_bits(info->regmap,
> MAX8997_RTC_WTSR_SMPL, mask, val);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
> @@ -428,8 +434,7 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
> max8997_rtc_set_update_reg(info);
>
> val = 0;
> - regmap_read(info->max8997->regmap_rtc,
> - MAX8997_RTC_WTSR_SMPL, &val);
> + regmap_read(info->regmap, MAX8997_RTC_WTSR_SMPL, &val);
> pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
> }
>
> @@ -444,7 +449,7 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
>
> info->rtc_24hr_mode = 1;
>
> - ret = regmap_bulk_write(info->max8997->regmap_rtc,
> + ret = regmap_bulk_write(info->regmap,
> MAX8997_RTC_CTRLMASK, data, 2);
> if (ret < 0) {
> dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
> @@ -471,13 +476,28 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> info->dev = &pdev->dev;
> info->max8997 = max8997;
>
> + info->i2c = i2c_new_dummy(max8997->i2c->adapter, MAX8997_I2C_ADDR_RTC);
> + if (!info->i2c) {
> + dev_err(info->dev, "failed to allocate I2C device\n");
> + return -ENODEV;
> + }
> +
> + info->regmap = devm_regmap_init_i2c(info->i2c,
> + &max8997_rtc_regmap_config);
> + if (IS_ERR(info->regmap)) {
> + ret = PTR_ERR(info->regmap);
> + dev_err(info->dev,
> + "failed to allocate register map: %d\n", ret);
> + goto err_regmap;
> + }
> +
> platform_set_drvdata(pdev, info);
>
> ret = max8997_rtc_init_reg(info);
>
> if (ret < 0) {
> dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
> - return ret;
> + goto err_regmap;
> }
>
> max8997_rtc_enable_wtsr(info, true);
> @@ -491,28 +511,41 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> if (IS_ERR(info->rtc_dev)) {
> ret = PTR_ERR(info->rtc_dev);
> dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
> - return ret;
> + goto err_regmap;
> }
>
> virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
> if (!virq) {
> dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
> ret = -ENXIO;
> - goto err_out;
> + goto err_regmap;
> }
> info->virq = virq;
>
> ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
> max8997_rtc_alarm_irq, 0,
> "rtc-alarm0", info);
> - if (ret < 0)
> + if (ret < 0) {
> dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
> info->virq, ret);
> + goto err_regmap;
> + }
> +
> + return ret;
>
> -err_out:
> +err_regmap:
> + i2c_unregister_device(info->i2c);
> return ret;
> }
>
> +static int max8997_rtc_remove(struct platform_device *pdev)
> +{
> + struct max8997_rtc_info *info = platform_get_drvdata(pdev);
> + i2c_unregister_device(info->i2c);
> +
> + return 0;
> +}
> +
> static void max8997_rtc_shutdown(struct platform_device *pdev)
> {
> struct max8997_rtc_info *info = platform_get_drvdata(pdev);
> @@ -532,6 +565,7 @@ static struct platform_driver max8997_rtc_driver = {
> .owner = THIS_MODULE,
> },
> .probe = max8997_rtc_probe,
> + .remove = max8997_rtc_remove,
> .shutdown = max8997_rtc_shutdown,
> .id_table = rtc_id,
> };
> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
> index 2817fa6..c2458c3 100644
> --- a/include/linux/mfd/max8997-private.h
> +++ b/include/linux/mfd/max8997-private.h
> @@ -26,6 +26,13 @@
> #include <linux/export.h>
> #include <linux/irqdomain.h>
>
> +#define MAX8997_I2C_ADDR_PMIC (0xCC >> 1)
> +#define MAX8997_I2C_ADDR_MUIC (0x4A >> 1)
> +#define MAX8997_I2C_ADDR_BATTERY (0x6C >> 1)
> +#define MAX8997_I2C_ADDR_RTC (0x0C >> 1)
> +#define MAX8997_I2C_ADDR_HAPTIC (0x90 >> 1)
> +
> +
> #define MAX8997_REG_INVALID (0xff)
>
> enum max8997_pmic_reg {
> @@ -430,21 +437,14 @@ struct max8997_dev {
> struct device *dev;
> struct max8997_platform_data *pdata;
> struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
> - struct i2c_client *rtc; /* slave addr 0x0c */
> - struct i2c_client *haptic; /* slave addr 0x90 */
> - struct i2c_client *muic; /* slave addr 0x4a */
> struct mutex iolock;
>
> 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;
>
> struct regmap_irq_chip_data *irq_data;
> - struct regmap_irq_chip_data *irq_data_muic;
> int irq;
> int ono;
> struct mutex irqlock;
>
^ permalink raw reply
* Re: [PATCH v3 0/4] mfd: max8997: add regmap support
From: Robert Baldyga @ 2014-03-13 10:52 UTC (permalink / raw)
To: Chanwoo Choi
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: <53218786.7010208@samsung.com>
Hi,
On 03/13/2014 11:25 AM, Chanwoo Choi wrote:
> Hi Robert,
>
> On 03/13/2014 06:38 PM, Robert Baldyga wrote:
>> Hi,
>>
>> This patchset modifies max8997 driver and associated function drivers to use
>> register maps instead of operating directly on i2c bus. This change allowed
>> to simplify irq handling, and to move some initializations to individual
>> function drivers. Hence now when some functions are not enabled, their i2c
>> clients, regmaps and irqs are not registered.
>>
>> Best regards
>> Robert Baldyga
>> Samsung R&D Institute Poland
>>
>> Changelog:
>>
>> v3:
>> - fix error handling
>> - fix deinitializations order
>> - move muic irq enum values renaming to separate patch
>>
>> v2: https://lkml.org/lkml/2014/3/12/237
>> - rebase patches on Lee Jones' MFD tree
>> - add missing selects in Kconfig
>> - add missing deinitializations
>> - add interrupt disabling when suspend
>> - few minor changes and typo fixes
>>
>> v1: https://lkml.org/lkml/2014/3/11/291
>>
>> Robert Baldyga (4):
>> mfd: max8997: use regmap to access registers
>> mfd: max8997: handle IRQs using regmap
>> mfd: max8997: change irq names to upper case
>> mfd: max8997: move regmap handling to function drivers
>>
>> drivers/extcon/extcon-max8997.c | 181 +++++++++++++---
>> drivers/input/misc/max8997_haptic.c | 121 +++++++++--
>> drivers/leds/leds-max8997.c | 13 +-
>> drivers/mfd/Kconfig | 3 +-
>> drivers/mfd/Makefile | 2 +-
>> drivers/mfd/max8997-irq.c | 387 -----------------------------------
>> drivers/mfd/max8997.c | 236 +++++++--------------
>> drivers/power/max8997_charger.c | 33 +--
>> drivers/regulator/max8997.c | 87 ++++----
>> drivers/rtc/rtc-max8997.c | 102 ++++++---
>> include/linux/mfd/max8997-private.h | 88 ++++++--
>> 11 files changed, 532 insertions(+), 721 deletions(-)
>> delete mode 100644 drivers/mfd/max8997-irq.c
>>
>
> This patch fix many parts of previous max8997.
> When I testd kernel build, it is ok.
>
> But, I have a question.
> The max8997 is used on trats board based on exynos4210.
> Did you test this patchset?
Yes, I have tested it on this board. Some function drivers requiring
platform data would not work yet, but it's not related to this patchset.
They didn't work before.
I'm actually working on patches for extcon-max8997.
Best regards
Robert Baldyga
^ permalink raw reply
* Re: [PATCH v3 2/4] mfd: max8997: handle IRQs using regmap
From: Chanwoo Choi @ 2014-03-13 10:45 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: <1394703532-494-3-git-send-email-r.baldyga@samsung.com>
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>
> ---
> drivers/extcon/extcon-max8997.c | 3 +-
> drivers/mfd/Kconfig | 2 +-
> drivers/mfd/Makefile | 2 +-
> drivers/mfd/max8997-irq.c | 373 -----------------------------------
> drivers/mfd/max8997.c | 112 ++++++++++-
> drivers/rtc/rtc-max8997.c | 2 +-
> include/linux/mfd/max8997-private.h | 63 +++++-
> 7 files changed, 165 insertions(+), 392 deletions(-)
> delete mode 100644 drivers/mfd/max8997-irq.c
>
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index f258c08..5948061 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -679,7 +679,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
> struct max8997_muic_irq *muic_irq = &muic_irqs[i];
> unsigned int virq = 0;
>
> - virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
> + virq = regmap_irq_get_virq(max8997->irq_data_muic,
> + muic_irq->irq);
> if (!virq) {
> ret = -EINVAL;
> goto err_irq;
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 2871a65..2273574 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -388,7 +388,7 @@ config MFD_MAX8997
> depends on I2C=y
> select MFD_CORE
> select REGMAP_I2C
> - select IRQ_DOMAIN
> + select REGMAP_IRQ
> help
> Say yes here to add support for Maxim Semiconductor MAX8997/8966.
> This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index f5a7b2c..4cec8ad 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -119,7 +119,7 @@ obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
> obj-$(CONFIG_MFD_MAX8907) += max8907.o
> max8925-objs := max8925-core.o max8925-i2c.o
> obj-$(CONFIG_MFD_MAX8925) += max8925.o
> -obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
> +obj-$(CONFIG_MFD_MAX8997) += max8997.o
> obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
>
> pcf50633-objs := pcf50633-core.o pcf50633-irq.o
> diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
> deleted file mode 100644
> index 0e7ff39..0000000
> --- a/drivers/mfd/max8997-irq.c
> +++ /dev/null
> @@ -1,373 +0,0 @@
> -/*
> - * max8997-irq.c - Interrupt controller support for MAX8997
> - *
> - * Copyright (C) 2011 Samsung Electronics Co.Ltd
> - * MyungJoo Ham <myungjoo.ham@samsung.com>
> - *
> - * 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.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> - *
> - * This driver is based on max8998-irq.c
> - */
> -
> -#include <linux/err.h>
> -#include <linux/irq.h>
> -#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,
> - [PMIC_INT2] = MAX8997_REG_INT2MSK,
> - [PMIC_INT3] = MAX8997_REG_INT3MSK,
> - [PMIC_INT4] = MAX8997_REG_INT4MSK,
> - [FUEL_GAUGE] = MAX8997_REG_INVALID,
> - [MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
> - [MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
> - [MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
> - [GPIO_LOW] = MAX8997_REG_INVALID,
> - [GPIO_HI] = MAX8997_REG_INVALID,
> - [FLASH_STATUS] = MAX8997_REG_INVALID,
> -};
> -
> -struct max8997_irq_data {
> - int mask;
> - enum max8997_irq_source group;
> -};
> -
> -#define DECLARE_IRQ(idx, _group, _mask) \
> - [(idx)] = { .group = (_group), .mask = (_mask) }
> -static const struct max8997_irq_data max8997_irqs[] = {
> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR, PMIC_INT1, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF, PMIC_INT1, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC, PMIC_INT1, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR, PMIC_INT1, 1 << 4),
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF, PMIC_INT1, 1 << 5),
> - DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2, PMIC_INT1, 1 << 6),
> - DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1, PMIC_INT1, 1 << 7),
> -
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGR, PMIC_INT2, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGF, PMIC_INT2, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_MR, PMIC_INT2, 1 << 2),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK, PMIC_INT2, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK, PMIC_INT2, 1 << 4),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK, PMIC_INT2, 1 << 5),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK, PMIC_INT2, 1 << 6),
> -
> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS, PMIC_INT3, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM, PMIC_INT3, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP, PMIC_INT3, 1 << 2),
> - DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR, PMIC_INT3, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF, PMIC_INT3, 1 << 5),
> - DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD, PMIC_INT3, 1 << 7),
> -
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S, PMIC_INT4, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1, PMIC_INT4, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2, PMIC_INT4, 1 << 2),
> - DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT, PMIC_INT4, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S, PMIC_INT4, 1 << 4),
> - DECLARE_IRQ(MAX8997_PMICIRQ_WTSR, PMIC_INT4, 1 << 5),
> -
> - DECLARE_IRQ(MAX8997_MUICIRQ_ADCError, MUIC_INT1, 1 << 2),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow, MUIC_INT1, 1 << 1),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ADC, MUIC_INT1, 1 << 0),
> -
> - DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt, MUIC_INT2, 1 << 4),
> - DECLARE_IRQ(MAX8997_MUICIRQ_DBChg, MUIC_INT2, 1 << 3),
> - DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr, MUIC_INT2, 1 << 2),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun, MUIC_INT2, 1 << 1),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp, MUIC_INT2, 1 << 0),
> -
> - DECLARE_IRQ(MAX8997_MUICIRQ_OVP, MUIC_INT3, 1 << 2),
> -};
> -
> -static void max8997_irq_lock(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> -
> - mutex_lock(&max8997->irqlock);
> -}
> -
> -static void max8997_irq_sync_unlock(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> - int i;
> -
> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> - struct regmap *map;
> - u8 mask_reg = max8997_mask_reg[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(map))
> - continue;
> - max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
> -
> - regmap_write(map, max8997_mask_reg[i],
> - max8997->irq_masks_cur[i]);
> - }
> -
> - mutex_unlock(&max8997->irqlock);
> -}
> -
> -static const inline struct max8997_irq_data *
> -irq_to_max8997_irq(struct max8997_dev *max8997, int irq)
> -{
> - struct irq_data *data = irq_get_irq_data(irq);
> - return &max8997_irqs[data->hwirq];
> -}
> -
> -static void max8997_irq_mask(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> - const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
> - data->irq);
> -
> - max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
> -}
> -
> -static void max8997_irq_unmask(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> - const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
> - data->irq);
> -
> - max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
> -}
> -
> -static struct irq_chip max8997_irq_chip = {
> - .name = "max8997",
> - .irq_bus_lock = max8997_irq_lock,
> - .irq_bus_sync_unlock = max8997_irq_sync_unlock,
> - .irq_mask = max8997_irq_mask,
> - .irq_unmask = max8997_irq_unmask,
> -};
> -
> -#define MAX8997_IRQSRC_PMIC (1 << 1)
> -#define MAX8997_IRQSRC_FUELGAUGE (1 << 2)
> -#define MAX8997_IRQSRC_MUIC (1 << 3)
> -#define MAX8997_IRQSRC_GPIO (1 << 4)
> -#define MAX8997_IRQSRC_FLASH (1 << 5)
> -static irqreturn_t max8997_irq_thread(int irq, void *data)
> -{
> - struct max8997_dev *max8997 = data;
> - u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
> - unsigned int irq_src;
> - int ret;
> - int i, cur_irq;
> -
> - 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);
> - return IRQ_NONE;
> - }
> -
> - if (irq_src & MAX8997_IRQSRC_PMIC) {
> - /* PMIC INT1 ~ INT4 */
> - regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
> - &irq_reg[PMIC_INT1], 4);
> - }
> - if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
> - /*
> - * TODO: FUEL GAUGE
> - *
> - * This is to be supported by Max17042 driver. When
> - * an interrupt incurs here, it should be relayed to a
> - * Max17042 device that is connected (probably by
> - * platform-data). However, we do not have interrupt
> - * handling in Max17042 driver currently. The Max17042 IRQ
> - * driver should be ready to be used as a stand-alone device and
> - * a Max8997-dependent device. Because it is not ready in
> - * Max17042-side and it is not too critical in operating
> - * Max8997, we do not implement this in initial releases.
> - */
> - irq_reg[FUEL_GAUGE] = 0;
> - }
> - if (irq_src & MAX8997_IRQSRC_MUIC) {
> - /* MUIC INT1 ~ INT3 */
> - regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
> - &irq_reg[MUIC_INT1], 3);
> - }
> - if (irq_src & MAX8997_IRQSRC_GPIO) {
> - /* GPIO Interrupt */
> - u8 gpio_info[MAX8997_NUM_GPIO];
> -
> - irq_reg[GPIO_LOW] = 0;
> - irq_reg[GPIO_HI] = 0;
> -
> - regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
> - gpio_info, MAX8997_NUM_GPIO);
> - for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> - bool interrupt = false;
> -
> - switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
> - case MAX8997_GPIO_INT_BOTH:
> - if (max8997->gpio_status[i] != gpio_info[i])
> - interrupt = true;
> - break;
> - case MAX8997_GPIO_INT_RISE:
> - if ((max8997->gpio_status[i] != gpio_info[i]) &&
> - (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
> - interrupt = true;
> - break;
> - case MAX8997_GPIO_INT_FALL:
> - if ((max8997->gpio_status[i] != gpio_info[i]) &&
> - !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
> - interrupt = true;
> - break;
> - default:
> - break;
> - }
> -
> - if (interrupt) {
> - if (i < 8)
> - irq_reg[GPIO_LOW] |= (1 << i);
> - else
> - irq_reg[GPIO_HI] |= (1 << (i - 8));
> - }
> -
> - }
> - }
> - if (irq_src & MAX8997_IRQSRC_FLASH) {
> - /* Flash Status Interrupt */
> - unsigned int data;
> - ret = regmap_read(max8997->regmap,
> - MAX8997_REG_FLASHSTATUS, &data);
> - irq_reg[FLASH_STATUS] = data;
> - }
> -
> - /* Apply masking */
> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
> - irq_reg[i] &= ~max8997->irq_masks_cur[i];
> -
> - /* Report */
> - for (i = 0; i < MAX8997_IRQ_NR; i++) {
> - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
> - cur_irq = irq_find_mapping(max8997->irq_domain, i);
> - if (cur_irq)
> - handle_nested_irq(cur_irq);
> - }
> - }
> -
> - return IRQ_HANDLED;
> -}
> -
> -int max8997_irq_resume(struct max8997_dev *max8997)
> -{
> - if (max8997->irq && max8997->irq_domain)
> - max8997_irq_thread(0, max8997);
> - return 0;
> -}
> -
> -static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq,
> - irq_hw_number_t hw)
> -{
> - struct max8997_dev *max8997 = d->host_data;
> -
> - irq_set_chip_data(irq, max8997);
> - irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq);
> - irq_set_nested_thread(irq, 1);
> -#ifdef CONFIG_ARM
> - set_irq_flags(irq, IRQF_VALID);
> -#else
> - irq_set_noprobe(irq);
> -#endif
> - return 0;
> -}
> -
> -static struct irq_domain_ops max8997_irq_domain_ops = {
> - .map = max8997_irq_domain_map,
> -};
> -
> -int max8997_irq_init(struct max8997_dev *max8997)
> -{
> - struct irq_domain *domain;
> - int i;
> - int ret;
> - unsigned int val;
> -
> - if (!max8997->irq) {
> - dev_warn(max8997->dev, "No interrupt specified.\n");
> - return 0;
> - }
> -
> - mutex_init(&max8997->irqlock);
> -
> - /* Mask individual interrupt sources */
> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> - max8997->irq_masks_cur[i] = 0xff;
> - max8997->irq_masks_cache[i] = 0xff;
> -
> - if (IS_ERR_OR_NULL(max8997->regmap))
> - continue;
> - if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
> - continue;
> -
> - regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
> - }
> -
> - for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> - max8997->gpio_status[i] = (regmap_read(max8997->regmap,
> - MAX8997_REG_GPIOCNTL1 + i,
> - &val)
> - & MAX8997_GPIO_DATA_MASK) ?
> - true : false;
> - }
> -
> - domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
> - &max8997_irq_domain_ops, max8997);
> - if (!domain) {
> - dev_err(max8997->dev, "could not create irq domain\n");
> - return -ENODEV;
> - }
> - max8997->irq_domain = domain;
> -
> - ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
> - IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> - "max8997-irq", max8997);
> -
> - if (ret) {
> - dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
> - max8997->irq, ret);
> - return ret;
> - }
> -
> - if (!max8997->ono)
> - return 0;
> -
> - ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
> - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
> - IRQF_ONESHOT, "max8997-ono", max8997);
> -
> - if (ret)
> - dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
> - max8997->ono, ret);
> -
> - return 0;
> -}
> -
> -void max8997_irq_exit(struct max8997_dev *max8997)
> -{
> - if (max8997->ono)
> - free_irq(max8997->ono, max8997);
> -
> - if (max8997->irq)
> - free_irq(max8997->irq, max8997);
> -}
> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> index 782d7c9..5a35b3f 100644
> --- a/drivers/mfd/max8997.c
> +++ b/drivers/mfd/max8997.c
> @@ -64,6 +64,49 @@ static const struct regmap_config max8997_regmap_config = {
> .max_register = MAX8997_REG_PMIC_END,
> };
>
> +static const struct regmap_irq max8997_irqs[] = {
> + /* PMIC_INT1 interrupts */
> + { .reg_offset = 0, .mask = PMIC_INT1_PWRONR_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_PWRONF_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_PWRON1SEC_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_JIGONR_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_JIGONF_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT2_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT1_MASK, },
> + /* PMIC_INT2 interrupts */
> + { .reg_offset = 1, .mask = PMIC_INT2_JIGR_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_JIGF_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_MR_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS1OK_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS2OK_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS3OK_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS4OK_MASK, },
> + /* PMIC_INT3 interrupts */
> + { .reg_offset = 2, .mask = PMIC_INT3_CHGINS_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_CHGRM_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_DCINOVP_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_TOPOFFR_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_CHGRSTF_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_MBCHGTMEXPD_MASK, },
> + /* PMIC_INT4 interrupts */
> + { .reg_offset = 3, .mask = PMIC_INT4_RTC60S_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_RTCA1_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_RTCA2_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_SMPL_INT_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_RTC1S_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_WTSR_MASK, },
> +};
> +
> +static const struct regmap_irq_chip max8997_irq_chip = {
> + .name = "max8997",
> + .status_base = MAX8997_REG_INT1,
> + .mask_base = MAX8997_REG_INT1MSK,
> + .mask_invert = false,
> + .num_regs = 4,
> + .irqs = max8997_irqs,
> + .num_irqs = ARRAY_SIZE(max8997_irqs),
> +};
> +
> static const struct regmap_config max8997_regmap_rtc_config = {
> .reg_bits = 8,
> .val_bits = 8,
> @@ -82,6 +125,31 @@ static const struct regmap_config max8997_regmap_muic_config = {
> .max_register = MAX8997_MUIC_REG_END,
> };
>
> +static const struct regmap_irq max8997_irqs_muic[] = {
> + /* MUIC_INT1 interrupts */
> + { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
> + { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
> + { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
> + /* MUIC_INT2 interrupts */
> + { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
> + /* MUIC_INT3 interrupts */
> + { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
> +};
> +
> +static const struct regmap_irq_chip max8997_irq_chip_muic = {
> + .name = "max8997-muic",
> + .status_base = MAX8997_MUIC_REG_INT1,
> + .mask_base = MAX8997_MUIC_REG_INTMASK1,
> + .mask_invert = true,
> + .num_regs = 3,
> + .irqs = max8997_irqs_muic,
> + .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
> +};
> +
> /*
> * Only the common platform data elements for max8997 are parsed here from the
> * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
> @@ -214,9 +282,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> goto err_regmap;
> }
>
> - pm_runtime_set_active(max8997->dev);
> + ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
> + IRQF_ONESHOT | IRQF_SHARED |
> + IRQF_TRIGGER_FALLING, 0,
> + &max8997_irq_chip, &max8997->irq_data);
> + if (ret) {
> + dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> + goto err_regmap;
> + }
>
> - max8997_irq_init(max8997);
> + ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
> + IRQF_ONESHOT | IRQF_SHARED |
> + IRQF_TRIGGER_FALLING, 0,
> + &max8997_irq_chip_muic,
> + &max8997->irq_data_muic);
> + if (ret) {
> + dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> + goto err_irq_muic;
> + }
> +
> + pm_runtime_set_active(max8997->dev);
>
> ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
> ARRAY_SIZE(max8997_devs),
> @@ -238,6 +323,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>
> err_mfd:
> mfd_remove_devices(max8997->dev);
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> +err_irq_muic:
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> err_regmap:
> i2c_unregister_device(max8997->muic);
> err_i2c_muic:
> @@ -252,6 +340,10 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
> struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>
> mfd_remove_devices(max8997->dev);
> +
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> +
> i2c_unregister_device(max8997->muic);
> i2c_unregister_device(max8997->haptic);
> i2c_unregister_device(max8997->rtc);
> @@ -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().
Why is it necessary for disable_irq(max8997->irq)?
> + }
> +
> return 0;
> }
>
> @@ -478,9 +573,12 @@ static int max8997_resume(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, 0);
> - return max8997_irq_resume(max8997);
> + if (device_may_wakeup(dev)) {
> + disable_irq_wake(max8997->irq);
> + enable_irq(max8997->irq);
ditto.
> + }
> +
> + return 0;
> }
>
> static const struct dev_pm_ops max8997_pm = {
> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> index b866f7d5..22769ea 100644
> --- a/drivers/rtc/rtc-max8997.c
> +++ b/drivers/rtc/rtc-max8997.c
> @@ -494,7 +494,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> return ret;
> }
>
> - virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1);
> + virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
> if (!virq) {
> dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
> ret = -ENXIO;
> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
> index ea80ef8..f42ea22 100644
> --- a/include/linux/mfd/max8997-private.h
> +++ b/include/linux/mfd/max8997-private.h
> @@ -333,6 +333,48 @@ enum max8997_irq_source {
> MAX8997_IRQ_GROUP_NR,
> };
>
> +#define PMIC_INT1_PWRONR_MASK (0x1 << 0)
> +#define PMIC_INT1_PWRONF_MASK (0x1 << 1)
> +#define PMIC_INT1_PWRON1SEC_MASK (0x1 << 3)
> +#define PMIC_INT1_JIGONR_MASK (0x1 << 4)
> +#define PMIC_INT1_JIGONF_MASK (0x1 << 5)
> +#define PMIC_INT1_LOWBAT2_MASK (0x1 << 6)
> +#define PMIC_INT1_LOWBAT1_MASK (0x1 << 7)
> +
> +#define PMIC_INT2_JIGR_MASK (0x1 << 0)
> +#define PMIC_INT2_JIGF_MASK (0x1 << 1)
> +#define PMIC_INT2_MR_MASK (0x1 << 2)
> +#define PMIC_INT2_DVS1OK_MASK (0x1 << 3)
> +#define PMIC_INT2_DVS2OK_MASK (0x1 << 4)
> +#define PMIC_INT2_DVS3OK_MASK (0x1 << 5)
> +#define PMIC_INT2_DVS4OK_MASK (0x1 << 6)
> +
> +#define PMIC_INT3_CHGINS_MASK (0x1 << 0)
> +#define PMIC_INT3_CHGRM_MASK (0x1 << 1)
> +#define PMIC_INT3_DCINOVP_MASK (0x1 << 2)
> +#define PMIC_INT3_TOPOFFR_MASK (0x1 << 3)
> +#define PMIC_INT3_CHGRSTF_MASK (0x1 << 5)
> +#define PMIC_INT3_MBCHGTMEXPD_MASK (0x1 << 7)
> +
> +#define PMIC_INT4_RTC60S_MASK (0x1 << 0)
> +#define PMIC_INT4_RTCA1_MASK (0x1 << 1)
> +#define PMIC_INT4_RTCA2_MASK (0x1 << 2)
> +#define PMIC_INT4_SMPL_INT_MASK (0x1 << 3)
> +#define PMIC_INT4_RTC1S_MASK (0x1 << 4)
> +#define PMIC_INT4_WTSR_MASK (0x1 << 5)
> +
> +#define MUIC_INT1_ADC_MASK (0x1 << 0)
> +#define MUIC_INT1_ADCLOW_MASK (0x1 << 1)
> +#define MUIC_INT1_ADCERROR_MASK (0x1 << 2)
> +
> +#define MUIC_INT2_CHGTYP_MASK (0x1 << 0)
> +#define MUIC_INT2_CHGDETRUN_MASK (0x1 << 1)
> +#define MUIC_INT2_DCDTMR_MASK (0x1 << 2)
> +#define MUIC_INT2_DBCHG_MASK (0x1 << 3)
> +#define MUIC_INT2_VBVOLT_MASK (0x1 << 4)
> +
> +#define MUIC_INT3_OVP_MASK (0x1 << 2)
> +
> enum max8997_irq {
> MAX8997_PMICIRQ_PWRONR,
> MAX8997_PMICIRQ_PWRONF,
> @@ -364,19 +406,23 @@ enum max8997_irq {
> MAX8997_PMICIRQ_RTC1S,
> MAX8997_PMICIRQ_WTSR,
>
> - MAX8997_MUICIRQ_ADCError,
> - MAX8997_MUICIRQ_ADCLow,
> + MAX8997_PMICIRQ_NR,
> +};
> +
> +enum max8997_irq_muic {
> MAX8997_MUICIRQ_ADC,
> + MAX8997_MUICIRQ_ADCLow,
> + MAX8997_MUICIRQ_ADCError,
>
> - MAX8997_MUICIRQ_VBVolt,
> - MAX8997_MUICIRQ_DBChg,
> - MAX8997_MUICIRQ_DCDTmr,
> - MAX8997_MUICIRQ_ChgDetRun,
> MAX8997_MUICIRQ_ChgTyp,
> + MAX8997_MUICIRQ_ChgDetRun,
> + MAX8997_MUICIRQ_DCDTmr,
> + MAX8997_MUICIRQ_DBChg,
> + MAX8997_MUICIRQ_VBVolt,
>
> MAX8997_MUICIRQ_OVP,
>
> - MAX8997_IRQ_NR,
> + MAX8997_MUCIRQ_NR,
> };
>
> #define MAX8997_NUM_GPIO 12
> @@ -397,9 +443,10 @@ struct max8997_dev {
> struct regmap *regmap_haptic;
> struct regmap *regmap_muic;
>
> + struct regmap_irq_chip_data *irq_data;
> + struct regmap_irq_chip_data *irq_data_muic;
> int irq;
> int ono;
> - struct irq_domain *irq_domain;
> struct mutex irqlock;
> int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
> int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
>
Thanks,
Chanwoo Choi
^ permalink raw reply
* Re: [PATCH v3 0/4] mfd: max8997: add regmap support
From: Chanwoo Choi @ 2014-03-13 10:25 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: <1394703532-494-1-git-send-email-r.baldyga@samsung.com>
Hi Robert,
On 03/13/2014 06:38 PM, Robert Baldyga wrote:
> Hi,
>
> This patchset modifies max8997 driver and associated function drivers to use
> register maps instead of operating directly on i2c bus. This change allowed
> to simplify irq handling, and to move some initializations to individual
> function drivers. Hence now when some functions are not enabled, their i2c
> clients, regmaps and irqs are not registered.
>
> Best regards
> Robert Baldyga
> Samsung R&D Institute Poland
>
> Changelog:
>
> v3:
> - fix error handling
> - fix deinitializations order
> - move muic irq enum values renaming to separate patch
>
> v2: https://lkml.org/lkml/2014/3/12/237
> - rebase patches on Lee Jones' MFD tree
> - add missing selects in Kconfig
> - add missing deinitializations
> - add interrupt disabling when suspend
> - few minor changes and typo fixes
>
> v1: https://lkml.org/lkml/2014/3/11/291
>
> Robert Baldyga (4):
> mfd: max8997: use regmap to access registers
> mfd: max8997: handle IRQs using regmap
> mfd: max8997: change irq names to upper case
> mfd: max8997: move regmap handling to function drivers
>
> drivers/extcon/extcon-max8997.c | 181 +++++++++++++---
> drivers/input/misc/max8997_haptic.c | 121 +++++++++--
> drivers/leds/leds-max8997.c | 13 +-
> drivers/mfd/Kconfig | 3 +-
> drivers/mfd/Makefile | 2 +-
> drivers/mfd/max8997-irq.c | 387 -----------------------------------
> drivers/mfd/max8997.c | 236 +++++++--------------
> drivers/power/max8997_charger.c | 33 +--
> drivers/regulator/max8997.c | 87 ++++----
> drivers/rtc/rtc-max8997.c | 102 ++++++---
> include/linux/mfd/max8997-private.h | 88 ++++++--
> 11 files changed, 532 insertions(+), 721 deletions(-)
> delete mode 100644 drivers/mfd/max8997-irq.c
>
This patch fix many parts of previous max8997.
When I testd kernel build, it is ok.
But, I have a question.
The max8997 is used on trats board based on exynos4210.
Did you test this patchset?
Best Regards,
Chanwoo Choi
^ permalink raw reply
* Re: [PATCH v3 3/4] mfd: max8997: change irq names to upper case
From: Chanwoo Choi @ 2014-03-13 10:18 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: <1394703532-494-4-git-send-email-r.baldyga@samsung.com>
On 03/13/2014 06:38 PM, Robert Baldyga wrote:
> This patch changes naming convention of MUIC interrupts form CamelCase
> to upper case. It makes names more readable and consistent with another
> interrupt names in max8997 driver.
>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
> drivers/extcon/extcon-max8997.c | 32 ++++++++++++++++----------------
> include/linux/mfd/max8997-private.h | 16 ++++++++--------
> 2 files changed, 24 insertions(+), 24 deletions(-)
>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Thanks,
Chanwoo Choi
^ permalink raw reply
* Re: [PATCH v3 4/4] mfd: max8997: move regmap handling to function drivers
From: Krzysztof Kozlowski @ 2014-03-13 9:50 UTC (permalink / raw)
To: Robert Baldyga
Cc: sameo, lee.jones, myungjoo.ham, cw00.choi, dmitry.torokhov,
cooloney, rpurdie, dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo,
paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
m.szyprowski
In-Reply-To: <1394703532-494-5-git-send-email-r.baldyga@samsung.com>
On Thu, 2014-03-13 at 10:38 +0100, Robert Baldyga wrote:
> This patch moves code creating new i2c clients and regmaps to function
> drivers which use them. It allows to avoid creating this instances when
> individual function drivers are not enabled.
>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
> drivers/extcon/extcon-max8997.c | 131 +++++++++++++++++++++++++--
> drivers/input/misc/max8997_haptic.c | 117 +++++++++++++++++++-----
> drivers/mfd/max8997.c | 169 +----------------------------------
> drivers/rtc/rtc-max8997.c | 78 +++++++++++-----
> include/linux/mfd/max8997-private.h | 14 +--
> 5 files changed, 284 insertions(+), 225 deletions(-)
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 3/4] mfd: max8997: change irq names to upper case
From: Krzysztof Kozlowski @ 2014-03-13 9:44 UTC (permalink / raw)
To: Robert Baldyga
Cc: sameo, lee.jones, myungjoo.ham, cw00.choi, dmitry.torokhov,
cooloney, rpurdie, dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo,
paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
m.szyprowski
In-Reply-To: <1394703532-494-4-git-send-email-r.baldyga@samsung.com>
On Thu, 2014-03-13 at 10:38 +0100, Robert Baldyga wrote:
> This patch changes naming convention of MUIC interrupts form CamelCase
> to upper case. It makes names more readable and consistent with another
> interrupt names in max8997 driver.
>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
> drivers/extcon/extcon-max8997.c | 32 ++++++++++++++++----------------
> include/linux/mfd/max8997-private.h | 16 ++++++++--------
> 2 files changed, 24 insertions(+), 24 deletions(-)
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Best regards,
Krzysztof Kozlowski
^ permalink raw reply
* Re: [PATCH v3 2/4] mfd: max8997: handle IRQs using regmap
From: Krzysztof Kozlowski @ 2014-03-13 9:44 UTC (permalink / raw)
To: Robert Baldyga
Cc: sameo, lee.jones, myungjoo.ham, cw00.choi, dmitry.torokhov,
cooloney, rpurdie, dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo,
paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
m.szyprowski
In-Reply-To: <1394703532-494-3-git-send-email-r.baldyga@samsung.com>
On Thu, 2014-03-13 at 10:38 +0100, 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>
> ---
> drivers/extcon/extcon-max8997.c | 3 +-
> drivers/mfd/Kconfig | 2 +-
> drivers/mfd/Makefile | 2 +-
> drivers/mfd/max8997-irq.c | 373 -----------------------------------
> drivers/mfd/max8997.c | 112 ++++++++++-
> drivers/rtc/rtc-max8997.c | 2 +-
> include/linux/mfd/max8997-private.h | 63 +++++-
> 7 files changed, 165 insertions(+), 392 deletions(-)
> delete mode 100644 drivers/mfd/max8997-irq.c
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Best regards,
Krzysztof Kozlowski
^ permalink raw reply
* [PATCH v3 0/4] mfd: max8997: add regmap support
From: Robert Baldyga @ 2014-03-13 9:38 UTC (permalink / raw)
To: sameo, lee.jones
Cc: myungjoo.ham, cw00.choi, dmitry.torokhov, cooloney, rpurdie,
dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
k.kozlowski, Robert Baldyga
Hi,
This patchset modifies max8997 driver and associated function drivers to use
register maps instead of operating directly on i2c bus. This change allowed
to simplify irq handling, and to move some initializations to individual
function drivers. Hence now when some functions are not enabled, their i2c
clients, regmaps and irqs are not registered.
Best regards
Robert Baldyga
Samsung R&D Institute Poland
Changelog:
v3:
- fix error handling
- fix deinitializations order
- move muic irq enum values renaming to separate patch
v2: https://lkml.org/lkml/2014/3/12/237
- rebase patches on Lee Jones' MFD tree
- add missing selects in Kconfig
- add missing deinitializations
- add interrupt disabling when suspend
- few minor changes and typo fixes
v1: https://lkml.org/lkml/2014/3/11/291
Robert Baldyga (4):
mfd: max8997: use regmap to access registers
mfd: max8997: handle IRQs using regmap
mfd: max8997: change irq names to upper case
mfd: max8997: move regmap handling to function drivers
drivers/extcon/extcon-max8997.c | 181 +++++++++++++---
drivers/input/misc/max8997_haptic.c | 121 +++++++++--
drivers/leds/leds-max8997.c | 13 +-
drivers/mfd/Kconfig | 3 +-
drivers/mfd/Makefile | 2 +-
drivers/mfd/max8997-irq.c | 387 -----------------------------------
drivers/mfd/max8997.c | 236 +++++++--------------
drivers/power/max8997_charger.c | 33 +--
drivers/regulator/max8997.c | 87 ++++----
drivers/rtc/rtc-max8997.c | 102 ++++++---
include/linux/mfd/max8997-private.h | 88 ++++++--
11 files changed, 532 insertions(+), 721 deletions(-)
delete mode 100644 drivers/mfd/max8997-irq.c
--
1.7.9.5
^ permalink raw reply
* [PATCH v3 4/4] mfd: max8997: move regmap handling to function drivers
From: Robert Baldyga @ 2014-03-13 9:38 UTC (permalink / raw)
To: sameo, lee.jones
Cc: myungjoo.ham, cw00.choi, dmitry.torokhov, cooloney, rpurdie,
dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
k.kozlowski, Robert Baldyga
In-Reply-To: <1394703532-494-1-git-send-email-r.baldyga@samsung.com>
This patch moves code creating new i2c clients and regmaps to function
drivers which use them. It allows to avoid creating this instances when
individual function drivers are not enabled.
Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
drivers/extcon/extcon-max8997.c | 131 +++++++++++++++++++++++++--
drivers/input/misc/max8997_haptic.c | 117 +++++++++++++++++++-----
drivers/mfd/max8997.c | 169 +----------------------------------
drivers/rtc/rtc-max8997.c | 78 +++++++++++-----
include/linux/mfd/max8997-private.h | 14 +--
5 files changed, 284 insertions(+), 225 deletions(-)
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 15fc5c0..51c2781 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -118,6 +118,9 @@ enum max8997_muic_charger_type {
struct max8997_muic_info {
struct device *dev;
struct max8997_dev *max8997;
+ struct i2c_client *i2c;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_data;
struct extcon_dev *edev;
int prev_cable_type;
int prev_chg_type;
@@ -144,6 +147,39 @@ struct max8997_muic_info {
*/
int path_usb;
int path_uart;
+
+ unsigned int reg_dump[MAX8997_MUIC_REG_END];
+};
+
+static const struct regmap_config max8997_muic_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX8997_MUIC_REG_END,
+};
+
+static const struct regmap_irq max8997_irqs_muic[] = {
+ /* MUIC_INT1 interrupts */
+ { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
+ { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
+ { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
+ /* MUIC_INT2 interrupts */
+ { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
+ /* MUIC_INT3 interrupts */
+ { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
+};
+
+static const struct regmap_irq_chip max8997_muic_irq_chip = {
+ .name = "max8997-muic",
+ .status_base = MAX8997_MUIC_REG_INT1,
+ .mask_base = MAX8997_MUIC_REG_INTMASK1,
+ .mask_invert = true,
+ .num_regs = 3,
+ .irqs = max8997_irqs_muic,
+ .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
};
enum {
@@ -191,7 +227,7 @@ 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 = regmap_update_bits(info->max8997->regmap_muic,
+ ret = regmap_update_bits(info->regmap,
MAX8997_MUIC_REG_CONTROL3,
CONTROL3_ADCDBSET_MASK,
time << CONTROL3_ADCDBSET_SHIFT);
@@ -229,7 +265,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
else
ctrl1 = CONTROL1_SW_OPEN;
- ret = regmap_update_bits(info->max8997->regmap_muic,
+ ret = regmap_update_bits(info->regmap,
MAX8997_MUIC_REG_CONTROL1, COMP_SW_MASK, ctrl1);
if (ret < 0) {
dev_err(info->dev, "failed to update MUIC register\n");
@@ -241,7 +277,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
else
ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
- ret = regmap_update_bits(info->max8997->regmap_muic,
+ ret = regmap_update_bits(info->regmap,
MAX8997_MUIC_REG_CONTROL2,
CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
if (ret < 0) {
@@ -544,7 +580,7 @@ static void max8997_muic_irq_work(struct work_struct *work)
if (info->irq == muic_irqs[i].virq)
irq_type = muic_irqs[i].irq;
- ret = regmap_bulk_read(info->max8997->regmap_muic,
+ ret = regmap_bulk_read(info->regmap,
MAX8997_MUIC_REG_STATUS1, info->status, 2);
if (ret) {
dev_err(info->dev, "failed to read muic register\n");
@@ -606,7 +642,7 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
mutex_lock(&info->mutex);
/* Read STATUSx register to detect accessory */
- ret = regmap_bulk_read(info->max8997->regmap_muic,
+ ret = regmap_bulk_read(info->regmap,
MAX8997_MUIC_REG_STATUS1, info->status, 2);
if (ret) {
dev_err(info->dev, "failed to read MUIC register\n");
@@ -670,6 +706,31 @@ static int max8997_muic_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->max8997 = max8997;
+ info->i2c = i2c_new_dummy(max8997->i2c->adapter, MAX8997_I2C_ADDR_MUIC);
+ if (!info->i2c) {
+ dev_err(info->dev, "failed to allocate I2C device\n");
+ return -ENODEV;
+ }
+
+ info->regmap = devm_regmap_init_i2c(info->i2c,
+ &max8997_muic_regmap_config);
+ if (IS_ERR(info->regmap)) {
+ ret = PTR_ERR(info->regmap);
+ dev_err(info->dev,
+ "failed to allocate register map: %d\n", ret);
+ goto err_regmap;
+ }
+
+ ret = regmap_add_irq_chip(info->regmap, max8997->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max8997_muic_irq_chip,
+ &info->irq_data);
+ if (ret) {
+ dev_err(info->dev, "failed to add irq chip: %d\n", ret);
+ goto err_regmap;
+ }
+
platform_set_drvdata(pdev, info);
mutex_init(&info->mutex);
@@ -679,8 +740,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
struct max8997_muic_irq *muic_irq = &muic_irqs[i];
unsigned int virq = 0;
- virq = regmap_irq_get_virq(max8997->irq_data_muic,
- muic_irq->irq);
+ virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
if (!virq) {
ret = -EINVAL;
goto err_irq;
@@ -723,7 +783,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++) {
- regmap_write(info->max8997->regmap_muic,
+ regmap_write(info->regmap,
muic_pdata->init_data[i].addr,
muic_pdata->init_data[i].data);
}
@@ -779,6 +839,9 @@ static int max8997_muic_probe(struct platform_device *pdev)
err_irq:
while (--i >= 0)
free_irq(muic_irqs[i].virq, info);
+ regmap_del_irq_chip(info->max8997->irq, info->irq_data);
+err_regmap:
+ i2c_unregister_device(info->i2c);
return ret;
}
@@ -789,6 +852,9 @@ static int max8997_muic_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
free_irq(muic_irqs[i].virq, info);
+
+ regmap_del_irq_chip(info->max8997->irq, info->irq_data);
+
cancel_work_sync(&info->irq_work);
extcon_dev_unregister(info->edev);
@@ -796,10 +862,59 @@ static int max8997_muic_remove(struct platform_device *pdev)
return 0;
}
+static u8 max8997_muic_dumpaddr[] = {
+ MAX8997_MUIC_REG_INTMASK1,
+ MAX8997_MUIC_REG_INTMASK2,
+ MAX8997_MUIC_REG_INTMASK3,
+ MAX8997_MUIC_REG_CDETCTRL,
+ MAX8997_MUIC_REG_CONTROL1,
+ MAX8997_MUIC_REG_CONTROL2,
+ MAX8997_MUIC_REG_CONTROL3,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int max8997_muic_freeze(struct device *dev)
+{
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct max8997_muic_info *info = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8997_muic_dumpaddr); i++)
+ regmap_read(info->regmap, max8997_muic_dumpaddr[i],
+ &info->reg_dump[i]);
+
+ return 0;
+}
+
+static int max8997_muic_restore(struct device *dev)
+{
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct max8997_muic_info *info = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8997_muic_dumpaddr); i++)
+ regmap_write(info->regmap, max8997_muic_dumpaddr[i],
+ info->reg_dump[i]);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops max8997_muic_pm = {
+#ifdef CONFIG_PM_SLEEP
+ .freeze = max8997_muic_freeze,
+ .restore = max8997_muic_restore,
+#endif
+
+};
+
static struct platform_driver max8997_muic_driver = {
.driver = {
.name = DEV_NAME,
.owner = THIS_MODULE,
+ .pm = &max8997_muic_pm,
},
.probe = max8997_muic_probe,
.remove = max8997_muic_remove,
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index d3f7079..9952eb2 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -47,6 +47,8 @@
struct max8997_haptic {
struct device *dev;
struct max8997_dev *max8997;
+ struct i2c_client *i2c;
+ struct regmap *regmap;
struct input_dev *input_dev;
struct regulator *regulator;
@@ -66,6 +68,14 @@ struct max8997_haptic {
unsigned int internal_mode_pattern;
unsigned int pattern_cycle;
unsigned int pattern_signal_period;
+
+ unsigned int reg_dump[MAX8997_HAPTIC_REG_END];
+};
+
+static const struct regmap_config max8997_haptic_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX8997_HAPTIC_REG_END,
};
static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
@@ -87,19 +97,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
}
switch (chip->internal_mode_pattern) {
case 0:
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
break;
case 1:
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
break;
case 2:
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
break;
case 3:
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
break;
default:
@@ -116,51 +126,49 @@ 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;
- regmap_write(chip->max8997->regmap_haptic,
- MAX8997_HAPTIC_REG_CONF2, value);
+ regmap_write(chip->regmap, 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;
- regmap_write(chip->max8997->regmap_haptic,
- MAX8997_HAPTIC_REG_DRVCONF, value);
+ regmap_write(chip->regmap, MAX8997_HAPTIC_REG_DRVCONF, value);
switch (chip->internal_mode_pattern) {
case 0:
value = chip->pattern_cycle << 4;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_CYCLECONF1, value);
value = chip->pattern_signal_period;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGCONF1, value);
break;
case 1:
value = chip->pattern_cycle;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_CYCLECONF1, value);
value = chip->pattern_signal_period;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGCONF2, value);
break;
case 2:
value = chip->pattern_cycle << 4;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_CYCLECONF2, value);
value = chip->pattern_signal_period;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGCONF3, value);
break;
case 3:
value = chip->pattern_cycle;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_CYCLECONF2, value);
value = chip->pattern_signal_period;
- regmap_write(chip->max8997->regmap_haptic,
+ regmap_write(chip->regmap,
MAX8997_HAPTIC_REG_SIGCONF4, value);
break;
@@ -277,6 +285,21 @@ static int max8997_haptic_probe(struct platform_device *pdev)
chip->mode = haptic_pdata->mode;
chip->pwm_divisor = haptic_pdata->pwm_divisor;
+ chip->i2c = i2c_new_dummy(iodev->i2c->adapter, MAX8997_I2C_ADDR_HAPTIC);
+ if (!chip->i2c) {
+ dev_err(info->dev, "failed to allocate I2C device\n");
+ return -ENODEV;
+ }
+
+ chip->regmap = devm_regmap_init_i2c(chip->i2c,
+ &max8997_haptic_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ error = PTR_ERR(chip->regmap);
+ dev_err(chip->dev,
+ "failed to allocate register map: %d\n", error);
+ goto err_free_i2c;
+ }
+
switch (chip->mode) {
case MAX8997_INTERNAL_MODE:
chip->internal_mode_pattern =
@@ -294,7 +317,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"unable to request PWM for haptic, error: %d\n",
error);
- goto err_free_mem;
+ goto err_free_i2c;
}
break;
@@ -302,7 +325,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Invalid chip mode specified (%d)\n", chip->mode);
error = -EINVAL;
- goto err_free_mem;
+ goto err_free_i2c;
}
chip->regulator = regulator_get(&pdev->dev, "inmotor");
@@ -348,6 +371,8 @@ err_put_regulator:
err_free_pwm:
if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_free(chip->pwm);
+err_free_i2c:
+ i2c_unregister_device(chip->i2c);
err_free_mem:
input_free_device(input_dev);
kfree(chip);
@@ -370,6 +395,24 @@ static int max8997_haptic_remove(struct platform_device *pdev)
return 0;
}
+static u8 max8997_haptic_dumpaddr[] = {
+ MAX8997_HAPTIC_REG_CONF1,
+ MAX8997_HAPTIC_REG_CONF2,
+ MAX8997_HAPTIC_REG_DRVCONF,
+ MAX8997_HAPTIC_REG_CYCLECONF1,
+ MAX8997_HAPTIC_REG_CYCLECONF2,
+ MAX8997_HAPTIC_REG_SIGCONF1,
+ MAX8997_HAPTIC_REG_SIGCONF2,
+ MAX8997_HAPTIC_REG_SIGCONF3,
+ MAX8997_HAPTIC_REG_SIGCONF4,
+ MAX8997_HAPTIC_REG_SIGDC1,
+ MAX8997_HAPTIC_REG_SIGDC2,
+ MAX8997_HAPTIC_REG_SIGPWMDC1,
+ MAX8997_HAPTIC_REG_SIGPWMDC2,
+ MAX8997_HAPTIC_REG_SIGPWMDC3,
+ MAX8997_HAPTIC_REG_SIGPWMDC4,
+};
+
#ifdef CONFIG_PM_SLEEP
static int max8997_haptic_suspend(struct device *dev)
{
@@ -380,9 +423,43 @@ static int max8997_haptic_suspend(struct device *dev)
return 0;
}
+
+static int max8997_haptic_freeze(struct device *dev)
+{
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct max8997_haptic *chip = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8997_haptic_dumpaddr); i++)
+ regmap_read(chip->regmap, max8997_haptic_dumpaddr[i],
+ &chip->reg_dump[i]);
+
+ return 0;
+}
+
+static int max8997_haptic_restore(struct device *dev)
+{
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct max8997_haptic *chip = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8997_haptic_dumpaddr); i++)
+ regmap_write(chip->regmap, max8997_haptic_dumpaddr[i],
+ chip->reg_dump[i]);
+
+ return 0;
+}
#endif
-static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
+static const struct dev_pm_ops max8997_haptic_pm = {
+#ifdef CONFIG_PM_SLEEP
+ .suspend = max8997_haptic_suspend,
+ .freeze = max8997_haptic_freeze,
+ .restore = max8997_haptic_restore,
+#endif
+};
static const struct platform_device_id max8997_haptic_id[] = {
{ "max8997-haptic", 0 },
@@ -394,7 +471,7 @@ static struct platform_driver max8997_haptic_driver = {
.driver = {
.name = "max8997-haptic",
.owner = THIS_MODULE,
- .pm = &max8997_haptic_pm_ops,
+ .pm = &max8997_haptic_pm,
},
.probe = max8997_haptic_probe,
.remove = max8997_haptic_remove,
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 5a35b3f..e4f37d3 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -35,12 +35,6 @@
#include <linux/mfd/max8997-private.h>
#include <linux/regmap.h>
-#define I2C_ADDR_PMIC (0xCC >> 1)
-#define I2C_ADDR_MUIC (0x4A >> 1)
-#define I2C_ADDR_BATTERY (0x6C >> 1)
-#define I2C_ADDR_RTC (0x0C >> 1)
-#define I2C_ADDR_HAPTIC (0x90 >> 1)
-
static const struct mfd_cell max8997_devs[] = {
{ .name = "max8997-pmic", },
{ .name = "max8997-rtc", },
@@ -107,48 +101,6 @@ static const struct regmap_irq_chip max8997_irq_chip = {
.num_irqs = ARRAY_SIZE(max8997_irqs),
};
-static const struct regmap_config max8997_regmap_rtc_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = MAX8997_RTC_REG_END,
-};
-
-static const struct regmap_config max8997_regmap_haptic_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = MAX8997_HAPTIC_REG_END,
-};
-
-static const struct regmap_config max8997_regmap_muic_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = MAX8997_MUIC_REG_END,
-};
-
-static const struct regmap_irq max8997_irqs_muic[] = {
- /* MUIC_INT1 interrupts */
- { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
- { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
- { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
- /* MUIC_INT2 interrupts */
- { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
- { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
- { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
- { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
- { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
- /* MUIC_INT3 interrupts */
- { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
-};
-
-static const struct regmap_irq_chip max8997_irq_chip_muic = {
- .name = "max8997-muic",
- .status_base = MAX8997_MUIC_REG_INT1,
- .mask_base = MAX8997_MUIC_REG_INTMASK1,
- .mask_invert = true,
- .num_regs = 3,
- .irqs = max8997_irqs_muic,
- .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
-};
/*
* Only the common platform data elements for max8997 are parsed here from the
@@ -224,29 +176,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
mutex_init(&max8997->iolock);
- max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
- if (!max8997->rtc) {
- dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n");
- return -ENODEV;
- }
- i2c_set_clientdata(max8997->rtc, max8997);
-
- max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
- if (!max8997->haptic) {
- dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n");
- ret = -ENODEV;
- goto err_i2c_haptic;
- }
- i2c_set_clientdata(max8997->haptic, max8997);
-
- max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
- if (!max8997->muic) {
- dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n");
- ret = -ENODEV;
- goto err_i2c_muic;
- }
- 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);
@@ -255,50 +184,13 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
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;
- }
-
ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
&max8997_irq_chip, &max8997->irq_data);
if (ret) {
dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
- goto err_regmap;
- }
-
- ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
- IRQF_ONESHOT | IRQF_SHARED |
- IRQF_TRIGGER_FALLING, 0,
- &max8997_irq_chip_muic,
- &max8997->irq_data_muic);
- if (ret) {
- dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
- goto err_irq_muic;
+ return ret;
}
pm_runtime_set_active(max8997->dev);
@@ -323,15 +215,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
err_mfd:
mfd_remove_devices(max8997->dev);
- regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
-err_irq_muic:
regmap_del_irq_chip(max8997->irq, max8997->irq_data);
-err_regmap:
- i2c_unregister_device(max8997->muic);
-err_i2c_muic:
- i2c_unregister_device(max8997->haptic);
-err_i2c_haptic:
- i2c_unregister_device(max8997->rtc);
return ret;
}
@@ -341,13 +225,8 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
mfd_remove_devices(max8997->dev);
- regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
regmap_del_irq_chip(max8997->irq, max8997->irq_data);
- i2c_unregister_device(max8997->muic);
- i2c_unregister_device(max8997->haptic);
- i2c_unregister_device(max8997->rtc);
-
return 0;
}
@@ -483,34 +362,6 @@ static u8 max8997_dumpaddr_pmic[] = {
MAX8997_REG_DVSOKTIMER5,
};
-static u8 max8997_dumpaddr_muic[] = {
- MAX8997_MUIC_REG_INTMASK1,
- MAX8997_MUIC_REG_INTMASK2,
- MAX8997_MUIC_REG_INTMASK3,
- MAX8997_MUIC_REG_CDETCTRL,
- MAX8997_MUIC_REG_CONTROL1,
- MAX8997_MUIC_REG_CONTROL2,
- MAX8997_MUIC_REG_CONTROL3,
-};
-
-static u8 max8997_dumpaddr_haptic[] = {
- MAX8997_HAPTIC_REG_CONF1,
- MAX8997_HAPTIC_REG_CONF2,
- MAX8997_HAPTIC_REG_DRVCONF,
- MAX8997_HAPTIC_REG_CYCLECONF1,
- MAX8997_HAPTIC_REG_CYCLECONF2,
- MAX8997_HAPTIC_REG_SIGCONF1,
- MAX8997_HAPTIC_REG_SIGCONF2,
- MAX8997_HAPTIC_REG_SIGCONF3,
- MAX8997_HAPTIC_REG_SIGCONF4,
- MAX8997_HAPTIC_REG_SIGDC1,
- MAX8997_HAPTIC_REG_SIGDC2,
- MAX8997_HAPTIC_REG_SIGPWMDC1,
- MAX8997_HAPTIC_REG_SIGPWMDC2,
- MAX8997_HAPTIC_REG_SIGPWMDC3,
- MAX8997_HAPTIC_REG_SIGPWMDC4,
-};
-
static int max8997_freeze(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -521,15 +372,6 @@ static int max8997_freeze(struct device *dev)
regmap_read(max8997->regmap, max8997_dumpaddr_pmic[i],
&max8997->reg_dump[i]);
- for (i = 0; i < ARRAY_SIZE(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++)
- regmap_read(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
- &max8997->reg_dump[i + MAX8997_REG_PMIC_END +
- MAX8997_MUIC_REG_END]);
-
return 0;
}
@@ -543,15 +385,6 @@ static int max8997_restore(struct device *dev)
regmap_write(max8997->regmap, max8997_dumpaddr_pmic[i],
max8997->reg_dump[i]);
- for (i = 0; i < ARRAY_SIZE(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++)
- regmap_write(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
- max8997->reg_dump[i + MAX8997_REG_PMIC_END +
- MAX8997_MUIC_REG_END]);
-
return 0;
}
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index 22769ea..57fab040 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -69,12 +69,20 @@ enum {
struct max8997_rtc_info {
struct device *dev;
struct max8997_dev *max8997;
+ struct i2c_client *i2c;
+ struct regmap *regmap;
struct rtc_device *rtc_dev;
struct mutex lock;
int virq;
int rtc_24hr_mode;
};
+static const struct regmap_config max8997_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX8997_RTC_REG_END,
+};
+
static void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode)
{
@@ -118,8 +126,7 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
{
int ret;
- ret = regmap_write(info->max8997->regmap_rtc,
- MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
+ ret = regmap_write(info->regmap, 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 +147,7 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
int ret;
mutex_lock(&info->lock);
- ret = regmap_bulk_read(info->max8997->regmap_rtc,
+ ret = regmap_bulk_read(info->regmap,
MAX8997_RTC_SEC, data, RTC_NR_TIME);
mutex_unlock(&info->lock);
@@ -167,7 +174,7 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
mutex_lock(&info->lock);
- ret = regmap_bulk_write(info->max8997->regmap_rtc,
+ ret = regmap_bulk_write(info->regmap,
MAX8997_RTC_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
@@ -190,7 +197,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
mutex_lock(&info->lock);
- ret = regmap_bulk_read(info->max8997->regmap_rtc,
+ ret = regmap_bulk_read(info->regmap,
MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
@@ -209,8 +216,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
alrm->pending = 0;
- ret = regmap_read(info->max8997->regmap_rtc,
- MAX8997_REG_STATUS1, &val);
+ ret = regmap_read(info->regmap, MAX8997_REG_STATUS1, &val);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
__func__, __LINE__, ret);
@@ -233,7 +239,7 @@ 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 = regmap_bulk_read(info->max8997->regmap_rtc,
+ ret = regmap_bulk_read(info->regmap,
MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
@@ -244,7 +250,7 @@ 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 = regmap_bulk_write(info->max8997->regmap_rtc,
+ ret = regmap_bulk_write(info->regmap,
MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
@@ -265,7 +271,7 @@ 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 = regmap_bulk_read(info->max8997->regmap_rtc,
+ ret = regmap_bulk_read(info->regmap,
MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
@@ -284,7 +290,7 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
if (data[RTC_DATE] & 0x1f)
data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
- ret = regmap_bulk_write(info->max8997->regmap_rtc,
+ ret = regmap_bulk_write(info->regmap,
MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
@@ -316,7 +322,7 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (ret < 0)
goto out;
- ret = regmap_bulk_write(info->max8997->regmap_rtc,
+ ret = regmap_bulk_write(info->regmap,
MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
@@ -388,7 +394,7 @@ 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 = regmap_update_bits(info->max8997->regmap_rtc,
+ ret = regmap_update_bits(info->regmap,
MAX8997_RTC_WTSR_SMPL, mask, val);
if (ret < 0) {
dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
@@ -417,7 +423,7 @@ 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 = regmap_update_bits(info->max8997->regmap_rtc,
+ ret = regmap_update_bits(info->regmap,
MAX8997_RTC_WTSR_SMPL, mask, val);
if (ret < 0) {
dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
@@ -428,8 +434,7 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
max8997_rtc_set_update_reg(info);
val = 0;
- regmap_read(info->max8997->regmap_rtc,
- MAX8997_RTC_WTSR_SMPL, &val);
+ regmap_read(info->regmap, MAX8997_RTC_WTSR_SMPL, &val);
pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
}
@@ -444,7 +449,7 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
info->rtc_24hr_mode = 1;
- ret = regmap_bulk_write(info->max8997->regmap_rtc,
+ ret = regmap_bulk_write(info->regmap,
MAX8997_RTC_CTRLMASK, data, 2);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
@@ -471,13 +476,28 @@ static int max8997_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->max8997 = max8997;
+ info->i2c = i2c_new_dummy(max8997->i2c->adapter, MAX8997_I2C_ADDR_RTC);
+ if (!info->i2c) {
+ dev_err(info->dev, "failed to allocate I2C device\n");
+ return -ENODEV;
+ }
+
+ info->regmap = devm_regmap_init_i2c(info->i2c,
+ &max8997_rtc_regmap_config);
+ if (IS_ERR(info->regmap)) {
+ ret = PTR_ERR(info->regmap);
+ dev_err(info->dev,
+ "failed to allocate register map: %d\n", ret);
+ goto err_regmap;
+ }
+
platform_set_drvdata(pdev, info);
ret = max8997_rtc_init_reg(info);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
- return ret;
+ goto err_regmap;
}
max8997_rtc_enable_wtsr(info, true);
@@ -491,28 +511,41 @@ static int max8997_rtc_probe(struct platform_device *pdev)
if (IS_ERR(info->rtc_dev)) {
ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
- return ret;
+ goto err_regmap;
}
virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
if (!virq) {
dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
ret = -ENXIO;
- goto err_out;
+ goto err_regmap;
}
info->virq = virq;
ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
max8997_rtc_alarm_irq, 0,
"rtc-alarm0", info);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->virq, ret);
+ goto err_regmap;
+ }
+
+ return ret;
-err_out:
+err_regmap:
+ i2c_unregister_device(info->i2c);
return ret;
}
+static int max8997_rtc_remove(struct platform_device *pdev)
+{
+ struct max8997_rtc_info *info = platform_get_drvdata(pdev);
+ i2c_unregister_device(info->i2c);
+
+ return 0;
+}
+
static void max8997_rtc_shutdown(struct platform_device *pdev)
{
struct max8997_rtc_info *info = platform_get_drvdata(pdev);
@@ -532,6 +565,7 @@ static struct platform_driver max8997_rtc_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_rtc_probe,
+ .remove = max8997_rtc_remove,
.shutdown = max8997_rtc_shutdown,
.id_table = rtc_id,
};
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index 2817fa6..c2458c3 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -26,6 +26,13 @@
#include <linux/export.h>
#include <linux/irqdomain.h>
+#define MAX8997_I2C_ADDR_PMIC (0xCC >> 1)
+#define MAX8997_I2C_ADDR_MUIC (0x4A >> 1)
+#define MAX8997_I2C_ADDR_BATTERY (0x6C >> 1)
+#define MAX8997_I2C_ADDR_RTC (0x0C >> 1)
+#define MAX8997_I2C_ADDR_HAPTIC (0x90 >> 1)
+
+
#define MAX8997_REG_INVALID (0xff)
enum max8997_pmic_reg {
@@ -430,21 +437,14 @@ struct max8997_dev {
struct device *dev;
struct max8997_platform_data *pdata;
struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
- struct i2c_client *rtc; /* slave addr 0x0c */
- struct i2c_client *haptic; /* slave addr 0x90 */
- struct i2c_client *muic; /* slave addr 0x4a */
struct mutex iolock;
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;
struct regmap_irq_chip_data *irq_data;
- struct regmap_irq_chip_data *irq_data_muic;
int irq;
int ono;
struct mutex irqlock;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 3/4] mfd: max8997: change irq names to upper case
From: Robert Baldyga @ 2014-03-13 9:38 UTC (permalink / raw)
To: sameo, lee.jones
Cc: myungjoo.ham, cw00.choi, dmitry.torokhov, cooloney, rpurdie,
dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
k.kozlowski, Robert Baldyga
In-Reply-To: <1394703532-494-1-git-send-email-r.baldyga@samsung.com>
This patch changes naming convention of MUIC interrupts form CamelCase
to upper case. It makes names more readable and consistent with another
interrupt names in max8997 driver.
Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
drivers/extcon/extcon-max8997.c | 32 ++++++++++++++++----------------
include/linux/mfd/max8997-private.h | 16 ++++++++--------
2 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 5948061..15fc5c0 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -46,15 +46,15 @@ struct max8997_muic_irq {
};
static struct max8997_muic_irq muic_irqs[] = {
- { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
- { MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
- { MAX8997_MUICIRQ_ADC, "muic-ADC" },
- { MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
- { MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
- { MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
- { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
- { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
- { MAX8997_MUICIRQ_OVP, "muic-OVP" },
+ { MAX8997_MUICIRQ_ADCERROR, "MUIC-ADCERROR" },
+ { MAX8997_MUICIRQ_ADCLOW, "MUIC-ADCLOW" },
+ { MAX8997_MUICIRQ_ADC, "MUIC-ADC" },
+ { MAX8997_MUICIRQ_VBVOLT, "MUIC-VBVOLT" },
+ { MAX8997_MUICIRQ_DBCHG, "MUIC-DBCHG" },
+ { MAX8997_MUICIRQ_DCDTMR, "MUIC-DCDTMR" },
+ { MAX8997_MUICIRQ_CHGDETRUN, "MUIC-CHGDETRUN" },
+ { MAX8997_MUICIRQ_CHGTYP, "MUIC-CHGTYP" },
+ { MAX8997_MUICIRQ_OVP, "MUIC-OVP" },
};
/* Define supported cable type */
@@ -553,17 +553,17 @@ static void max8997_muic_irq_work(struct work_struct *work)
}
switch (irq_type) {
- case MAX8997_MUICIRQ_ADCError:
- case MAX8997_MUICIRQ_ADCLow:
+ case MAX8997_MUICIRQ_ADCERROR:
+ case MAX8997_MUICIRQ_ADCLOW:
case MAX8997_MUICIRQ_ADC:
/* Handle all of cable except for charger cable */
ret = max8997_muic_adc_handler(info);
break;
- case MAX8997_MUICIRQ_VBVolt:
- case MAX8997_MUICIRQ_DBChg:
- case MAX8997_MUICIRQ_DCDTmr:
- case MAX8997_MUICIRQ_ChgDetRun:
- case MAX8997_MUICIRQ_ChgTyp:
+ case MAX8997_MUICIRQ_VBVOLT:
+ case MAX8997_MUICIRQ_DBCHG:
+ case MAX8997_MUICIRQ_DCDTMR:
+ case MAX8997_MUICIRQ_CHGDETRUN:
+ case MAX8997_MUICIRQ_CHGTYP:
/* Handle charger cable */
ret = max8997_muic_chg_handler(info);
break;
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index f42ea22..2817fa6 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -411,14 +411,14 @@ enum max8997_irq {
enum max8997_irq_muic {
MAX8997_MUICIRQ_ADC,
- MAX8997_MUICIRQ_ADCLow,
- MAX8997_MUICIRQ_ADCError,
-
- MAX8997_MUICIRQ_ChgTyp,
- MAX8997_MUICIRQ_ChgDetRun,
- MAX8997_MUICIRQ_DCDTmr,
- MAX8997_MUICIRQ_DBChg,
- MAX8997_MUICIRQ_VBVolt,
+ MAX8997_MUICIRQ_ADCLOW,
+ MAX8997_MUICIRQ_ADCERROR,
+
+ MAX8997_MUICIRQ_CHGTYP,
+ MAX8997_MUICIRQ_CHGDETRUN,
+ MAX8997_MUICIRQ_DCDTMR,
+ MAX8997_MUICIRQ_DBCHG,
+ MAX8997_MUICIRQ_VBVOLT,
MAX8997_MUICIRQ_OVP,
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 2/4] mfd: max8997: handle IRQs using regmap
From: Robert Baldyga @ 2014-03-13 9:38 UTC (permalink / raw)
To: sameo, lee.jones
Cc: myungjoo.ham, cw00.choi, dmitry.torokhov, cooloney, rpurdie,
dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
k.kozlowski, Robert Baldyga
In-Reply-To: <1394703532-494-1-git-send-email-r.baldyga@samsung.com>
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>
---
drivers/extcon/extcon-max8997.c | 3 +-
drivers/mfd/Kconfig | 2 +-
drivers/mfd/Makefile | 2 +-
drivers/mfd/max8997-irq.c | 373 -----------------------------------
drivers/mfd/max8997.c | 112 ++++++++++-
drivers/rtc/rtc-max8997.c | 2 +-
include/linux/mfd/max8997-private.h | 63 +++++-
7 files changed, 165 insertions(+), 392 deletions(-)
delete mode 100644 drivers/mfd/max8997-irq.c
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index f258c08..5948061 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -679,7 +679,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
struct max8997_muic_irq *muic_irq = &muic_irqs[i];
unsigned int virq = 0;
- virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
+ virq = regmap_irq_get_virq(max8997->irq_data_muic,
+ muic_irq->irq);
if (!virq) {
ret = -EINVAL;
goto err_irq;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2871a65..2273574 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -388,7 +388,7 @@ config MFD_MAX8997
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
- select IRQ_DOMAIN
+ select REGMAP_IRQ
help
Say yes here to add support for Maxim Semiconductor MAX8997/8966.
This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f5a7b2c..4cec8ad 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -119,7 +119,7 @@ obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
max8925-objs := max8925-core.o max8925-i2c.o
obj-$(CONFIG_MFD_MAX8925) += max8925.o
-obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
+obj-$(CONFIG_MFD_MAX8997) += max8997.o
obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
pcf50633-objs := pcf50633-core.o pcf50633-irq.o
diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
deleted file mode 100644
index 0e7ff39..0000000
--- a/drivers/mfd/max8997-irq.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * max8997-irq.c - Interrupt controller support for MAX8997
- *
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * MyungJoo Ham <myungjoo.ham@samsung.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This driver is based on max8998-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#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,
- [PMIC_INT2] = MAX8997_REG_INT2MSK,
- [PMIC_INT3] = MAX8997_REG_INT3MSK,
- [PMIC_INT4] = MAX8997_REG_INT4MSK,
- [FUEL_GAUGE] = MAX8997_REG_INVALID,
- [MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
- [MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
- [MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
- [GPIO_LOW] = MAX8997_REG_INVALID,
- [GPIO_HI] = MAX8997_REG_INVALID,
- [FLASH_STATUS] = MAX8997_REG_INVALID,
-};
-
-struct max8997_irq_data {
- int mask;
- enum max8997_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask) \
- [(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max8997_irq_data max8997_irqs[] = {
- DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR, PMIC_INT1, 1 << 0),
- DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF, PMIC_INT1, 1 << 1),
- DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC, PMIC_INT1, 1 << 3),
- DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR, PMIC_INT1, 1 << 4),
- DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF, PMIC_INT1, 1 << 5),
- DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2, PMIC_INT1, 1 << 6),
- DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1, PMIC_INT1, 1 << 7),
-
- DECLARE_IRQ(MAX8997_PMICIRQ_JIGR, PMIC_INT2, 1 << 0),
- DECLARE_IRQ(MAX8997_PMICIRQ_JIGF, PMIC_INT2, 1 << 1),
- DECLARE_IRQ(MAX8997_PMICIRQ_MR, PMIC_INT2, 1 << 2),
- DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK, PMIC_INT2, 1 << 3),
- DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK, PMIC_INT2, 1 << 4),
- DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK, PMIC_INT2, 1 << 5),
- DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK, PMIC_INT2, 1 << 6),
-
- DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS, PMIC_INT3, 1 << 0),
- DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM, PMIC_INT3, 1 << 1),
- DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP, PMIC_INT3, 1 << 2),
- DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR, PMIC_INT3, 1 << 3),
- DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF, PMIC_INT3, 1 << 5),
- DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD, PMIC_INT3, 1 << 7),
-
- DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S, PMIC_INT4, 1 << 0),
- DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1, PMIC_INT4, 1 << 1),
- DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2, PMIC_INT4, 1 << 2),
- DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT, PMIC_INT4, 1 << 3),
- DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S, PMIC_INT4, 1 << 4),
- DECLARE_IRQ(MAX8997_PMICIRQ_WTSR, PMIC_INT4, 1 << 5),
-
- DECLARE_IRQ(MAX8997_MUICIRQ_ADCError, MUIC_INT1, 1 << 2),
- DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow, MUIC_INT1, 1 << 1),
- DECLARE_IRQ(MAX8997_MUICIRQ_ADC, MUIC_INT1, 1 << 0),
-
- DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt, MUIC_INT2, 1 << 4),
- DECLARE_IRQ(MAX8997_MUICIRQ_DBChg, MUIC_INT2, 1 << 3),
- DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr, MUIC_INT2, 1 << 2),
- DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun, MUIC_INT2, 1 << 1),
- DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp, MUIC_INT2, 1 << 0),
-
- DECLARE_IRQ(MAX8997_MUICIRQ_OVP, MUIC_INT3, 1 << 2),
-};
-
-static void max8997_irq_lock(struct irq_data *data)
-{
- struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
-
- mutex_lock(&max8997->irqlock);
-}
-
-static void max8997_irq_sync_unlock(struct irq_data *data)
-{
- struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
- int i;
-
- for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
- struct regmap *map;
- u8 mask_reg = max8997_mask_reg[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(map))
- continue;
- max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
-
- regmap_write(map, max8997_mask_reg[i],
- max8997->irq_masks_cur[i]);
- }
-
- mutex_unlock(&max8997->irqlock);
-}
-
-static const inline struct max8997_irq_data *
-irq_to_max8997_irq(struct max8997_dev *max8997, int irq)
-{
- struct irq_data *data = irq_get_irq_data(irq);
- return &max8997_irqs[data->hwirq];
-}
-
-static void max8997_irq_mask(struct irq_data *data)
-{
- struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
- const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
- data->irq);
-
- max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
-}
-
-static void max8997_irq_unmask(struct irq_data *data)
-{
- struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
- const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
- data->irq);
-
- max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-}
-
-static struct irq_chip max8997_irq_chip = {
- .name = "max8997",
- .irq_bus_lock = max8997_irq_lock,
- .irq_bus_sync_unlock = max8997_irq_sync_unlock,
- .irq_mask = max8997_irq_mask,
- .irq_unmask = max8997_irq_unmask,
-};
-
-#define MAX8997_IRQSRC_PMIC (1 << 1)
-#define MAX8997_IRQSRC_FUELGAUGE (1 << 2)
-#define MAX8997_IRQSRC_MUIC (1 << 3)
-#define MAX8997_IRQSRC_GPIO (1 << 4)
-#define MAX8997_IRQSRC_FLASH (1 << 5)
-static irqreturn_t max8997_irq_thread(int irq, void *data)
-{
- struct max8997_dev *max8997 = data;
- u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
- unsigned int irq_src;
- int ret;
- int i, cur_irq;
-
- 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);
- return IRQ_NONE;
- }
-
- if (irq_src & MAX8997_IRQSRC_PMIC) {
- /* PMIC INT1 ~ INT4 */
- regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
- &irq_reg[PMIC_INT1], 4);
- }
- if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
- /*
- * TODO: FUEL GAUGE
- *
- * This is to be supported by Max17042 driver. When
- * an interrupt incurs here, it should be relayed to a
- * Max17042 device that is connected (probably by
- * platform-data). However, we do not have interrupt
- * handling in Max17042 driver currently. The Max17042 IRQ
- * driver should be ready to be used as a stand-alone device and
- * a Max8997-dependent device. Because it is not ready in
- * Max17042-side and it is not too critical in operating
- * Max8997, we do not implement this in initial releases.
- */
- irq_reg[FUEL_GAUGE] = 0;
- }
- if (irq_src & MAX8997_IRQSRC_MUIC) {
- /* MUIC INT1 ~ INT3 */
- regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
- &irq_reg[MUIC_INT1], 3);
- }
- if (irq_src & MAX8997_IRQSRC_GPIO) {
- /* GPIO Interrupt */
- u8 gpio_info[MAX8997_NUM_GPIO];
-
- irq_reg[GPIO_LOW] = 0;
- irq_reg[GPIO_HI] = 0;
-
- regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
- gpio_info, MAX8997_NUM_GPIO);
- for (i = 0; i < MAX8997_NUM_GPIO; i++) {
- bool interrupt = false;
-
- switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
- case MAX8997_GPIO_INT_BOTH:
- if (max8997->gpio_status[i] != gpio_info[i])
- interrupt = true;
- break;
- case MAX8997_GPIO_INT_RISE:
- if ((max8997->gpio_status[i] != gpio_info[i]) &&
- (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
- interrupt = true;
- break;
- case MAX8997_GPIO_INT_FALL:
- if ((max8997->gpio_status[i] != gpio_info[i]) &&
- !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
- interrupt = true;
- break;
- default:
- break;
- }
-
- if (interrupt) {
- if (i < 8)
- irq_reg[GPIO_LOW] |= (1 << i);
- else
- irq_reg[GPIO_HI] |= (1 << (i - 8));
- }
-
- }
- }
- if (irq_src & MAX8997_IRQSRC_FLASH) {
- /* Flash Status Interrupt */
- unsigned int data;
- ret = regmap_read(max8997->regmap,
- MAX8997_REG_FLASHSTATUS, &data);
- irq_reg[FLASH_STATUS] = data;
- }
-
- /* Apply masking */
- for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
- irq_reg[i] &= ~max8997->irq_masks_cur[i];
-
- /* Report */
- for (i = 0; i < MAX8997_IRQ_NR; i++) {
- if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
- cur_irq = irq_find_mapping(max8997->irq_domain, i);
- if (cur_irq)
- handle_nested_irq(cur_irq);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-int max8997_irq_resume(struct max8997_dev *max8997)
-{
- if (max8997->irq && max8997->irq_domain)
- max8997_irq_thread(0, max8997);
- return 0;
-}
-
-static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hw)
-{
- struct max8997_dev *max8997 = d->host_data;
-
- irq_set_chip_data(irq, max8997);
- irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq);
- irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
- return 0;
-}
-
-static struct irq_domain_ops max8997_irq_domain_ops = {
- .map = max8997_irq_domain_map,
-};
-
-int max8997_irq_init(struct max8997_dev *max8997)
-{
- struct irq_domain *domain;
- int i;
- int ret;
- unsigned int val;
-
- if (!max8997->irq) {
- dev_warn(max8997->dev, "No interrupt specified.\n");
- return 0;
- }
-
- mutex_init(&max8997->irqlock);
-
- /* Mask individual interrupt sources */
- for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
- max8997->irq_masks_cur[i] = 0xff;
- max8997->irq_masks_cache[i] = 0xff;
-
- if (IS_ERR_OR_NULL(max8997->regmap))
- continue;
- if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
- continue;
-
- regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
- }
-
- for (i = 0; i < MAX8997_NUM_GPIO; i++) {
- max8997->gpio_status[i] = (regmap_read(max8997->regmap,
- MAX8997_REG_GPIOCNTL1 + i,
- &val)
- & MAX8997_GPIO_DATA_MASK) ?
- true : false;
- }
-
- domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
- &max8997_irq_domain_ops, max8997);
- if (!domain) {
- dev_err(max8997->dev, "could not create irq domain\n");
- return -ENODEV;
- }
- max8997->irq_domain = domain;
-
- ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "max8997-irq", max8997);
-
- if (ret) {
- dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
- max8997->irq, ret);
- return ret;
- }
-
- if (!max8997->ono)
- return 0;
-
- ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
- IRQF_ONESHOT, "max8997-ono", max8997);
-
- if (ret)
- dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
- max8997->ono, ret);
-
- return 0;
-}
-
-void max8997_irq_exit(struct max8997_dev *max8997)
-{
- if (max8997->ono)
- free_irq(max8997->ono, max8997);
-
- if (max8997->irq)
- free_irq(max8997->irq, max8997);
-}
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 782d7c9..5a35b3f 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -64,6 +64,49 @@ static const struct regmap_config max8997_regmap_config = {
.max_register = MAX8997_REG_PMIC_END,
};
+static const struct regmap_irq max8997_irqs[] = {
+ /* PMIC_INT1 interrupts */
+ { .reg_offset = 0, .mask = PMIC_INT1_PWRONR_MASK, },
+ { .reg_offset = 0, .mask = PMIC_INT1_PWRONF_MASK, },
+ { .reg_offset = 0, .mask = PMIC_INT1_PWRON1SEC_MASK, },
+ { .reg_offset = 0, .mask = PMIC_INT1_JIGONR_MASK, },
+ { .reg_offset = 0, .mask = PMIC_INT1_JIGONF_MASK, },
+ { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT2_MASK, },
+ { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT1_MASK, },
+ /* PMIC_INT2 interrupts */
+ { .reg_offset = 1, .mask = PMIC_INT2_JIGR_MASK, },
+ { .reg_offset = 1, .mask = PMIC_INT2_JIGF_MASK, },
+ { .reg_offset = 1, .mask = PMIC_INT2_MR_MASK, },
+ { .reg_offset = 1, .mask = PMIC_INT2_DVS1OK_MASK, },
+ { .reg_offset = 1, .mask = PMIC_INT2_DVS2OK_MASK, },
+ { .reg_offset = 1, .mask = PMIC_INT2_DVS3OK_MASK, },
+ { .reg_offset = 1, .mask = PMIC_INT2_DVS4OK_MASK, },
+ /* PMIC_INT3 interrupts */
+ { .reg_offset = 2, .mask = PMIC_INT3_CHGINS_MASK, },
+ { .reg_offset = 2, .mask = PMIC_INT3_CHGRM_MASK, },
+ { .reg_offset = 2, .mask = PMIC_INT3_DCINOVP_MASK, },
+ { .reg_offset = 2, .mask = PMIC_INT3_TOPOFFR_MASK, },
+ { .reg_offset = 2, .mask = PMIC_INT3_CHGRSTF_MASK, },
+ { .reg_offset = 2, .mask = PMIC_INT3_MBCHGTMEXPD_MASK, },
+ /* PMIC_INT4 interrupts */
+ { .reg_offset = 3, .mask = PMIC_INT4_RTC60S_MASK, },
+ { .reg_offset = 3, .mask = PMIC_INT4_RTCA1_MASK, },
+ { .reg_offset = 3, .mask = PMIC_INT4_RTCA2_MASK, },
+ { .reg_offset = 3, .mask = PMIC_INT4_SMPL_INT_MASK, },
+ { .reg_offset = 3, .mask = PMIC_INT4_RTC1S_MASK, },
+ { .reg_offset = 3, .mask = PMIC_INT4_WTSR_MASK, },
+};
+
+static const struct regmap_irq_chip max8997_irq_chip = {
+ .name = "max8997",
+ .status_base = MAX8997_REG_INT1,
+ .mask_base = MAX8997_REG_INT1MSK,
+ .mask_invert = false,
+ .num_regs = 4,
+ .irqs = max8997_irqs,
+ .num_irqs = ARRAY_SIZE(max8997_irqs),
+};
+
static const struct regmap_config max8997_regmap_rtc_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -82,6 +125,31 @@ static const struct regmap_config max8997_regmap_muic_config = {
.max_register = MAX8997_MUIC_REG_END,
};
+static const struct regmap_irq max8997_irqs_muic[] = {
+ /* MUIC_INT1 interrupts */
+ { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
+ { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
+ { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
+ /* MUIC_INT2 interrupts */
+ { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
+ { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
+ /* MUIC_INT3 interrupts */
+ { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
+};
+
+static const struct regmap_irq_chip max8997_irq_chip_muic = {
+ .name = "max8997-muic",
+ .status_base = MAX8997_MUIC_REG_INT1,
+ .mask_base = MAX8997_MUIC_REG_INTMASK1,
+ .mask_invert = true,
+ .num_regs = 3,
+ .irqs = max8997_irqs_muic,
+ .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
+};
+
/*
* Only the common platform data elements for max8997 are parsed here from the
* device tree. Other sub-modules of max8997 such as pmic, rtc and others have
@@ -214,9 +282,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
goto err_regmap;
}
- pm_runtime_set_active(max8997->dev);
+ ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max8997_irq_chip, &max8997->irq_data);
+ if (ret) {
+ dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
+ goto err_regmap;
+ }
- max8997_irq_init(max8997);
+ ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max8997_irq_chip_muic,
+ &max8997->irq_data_muic);
+ if (ret) {
+ dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
+ goto err_irq_muic;
+ }
+
+ pm_runtime_set_active(max8997->dev);
ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
ARRAY_SIZE(max8997_devs),
@@ -238,6 +323,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
err_mfd:
mfd_remove_devices(max8997->dev);
+ regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
+err_irq_muic:
+ regmap_del_irq_chip(max8997->irq, max8997->irq_data);
err_regmap:
i2c_unregister_device(max8997->muic);
err_i2c_muic:
@@ -252,6 +340,10 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
mfd_remove_devices(max8997->dev);
+
+ regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
+ regmap_del_irq_chip(max8997->irq, max8997->irq_data);
+
i2c_unregister_device(max8997->muic);
i2c_unregister_device(max8997->haptic);
i2c_unregister_device(max8997->rtc);
@@ -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);
+ }
+
return 0;
}
@@ -478,9 +573,12 @@ static int max8997_resume(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, 0);
- return max8997_irq_resume(max8997);
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(max8997->irq);
+ enable_irq(max8997->irq);
+ }
+
+ return 0;
}
static const struct dev_pm_ops max8997_pm = {
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index b866f7d5..22769ea 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -494,7 +494,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
return ret;
}
- virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1);
+ virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
if (!virq) {
dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
ret = -ENXIO;
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index ea80ef8..f42ea22 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -333,6 +333,48 @@ enum max8997_irq_source {
MAX8997_IRQ_GROUP_NR,
};
+#define PMIC_INT1_PWRONR_MASK (0x1 << 0)
+#define PMIC_INT1_PWRONF_MASK (0x1 << 1)
+#define PMIC_INT1_PWRON1SEC_MASK (0x1 << 3)
+#define PMIC_INT1_JIGONR_MASK (0x1 << 4)
+#define PMIC_INT1_JIGONF_MASK (0x1 << 5)
+#define PMIC_INT1_LOWBAT2_MASK (0x1 << 6)
+#define PMIC_INT1_LOWBAT1_MASK (0x1 << 7)
+
+#define PMIC_INT2_JIGR_MASK (0x1 << 0)
+#define PMIC_INT2_JIGF_MASK (0x1 << 1)
+#define PMIC_INT2_MR_MASK (0x1 << 2)
+#define PMIC_INT2_DVS1OK_MASK (0x1 << 3)
+#define PMIC_INT2_DVS2OK_MASK (0x1 << 4)
+#define PMIC_INT2_DVS3OK_MASK (0x1 << 5)
+#define PMIC_INT2_DVS4OK_MASK (0x1 << 6)
+
+#define PMIC_INT3_CHGINS_MASK (0x1 << 0)
+#define PMIC_INT3_CHGRM_MASK (0x1 << 1)
+#define PMIC_INT3_DCINOVP_MASK (0x1 << 2)
+#define PMIC_INT3_TOPOFFR_MASK (0x1 << 3)
+#define PMIC_INT3_CHGRSTF_MASK (0x1 << 5)
+#define PMIC_INT3_MBCHGTMEXPD_MASK (0x1 << 7)
+
+#define PMIC_INT4_RTC60S_MASK (0x1 << 0)
+#define PMIC_INT4_RTCA1_MASK (0x1 << 1)
+#define PMIC_INT4_RTCA2_MASK (0x1 << 2)
+#define PMIC_INT4_SMPL_INT_MASK (0x1 << 3)
+#define PMIC_INT4_RTC1S_MASK (0x1 << 4)
+#define PMIC_INT4_WTSR_MASK (0x1 << 5)
+
+#define MUIC_INT1_ADC_MASK (0x1 << 0)
+#define MUIC_INT1_ADCLOW_MASK (0x1 << 1)
+#define MUIC_INT1_ADCERROR_MASK (0x1 << 2)
+
+#define MUIC_INT2_CHGTYP_MASK (0x1 << 0)
+#define MUIC_INT2_CHGDETRUN_MASK (0x1 << 1)
+#define MUIC_INT2_DCDTMR_MASK (0x1 << 2)
+#define MUIC_INT2_DBCHG_MASK (0x1 << 3)
+#define MUIC_INT2_VBVOLT_MASK (0x1 << 4)
+
+#define MUIC_INT3_OVP_MASK (0x1 << 2)
+
enum max8997_irq {
MAX8997_PMICIRQ_PWRONR,
MAX8997_PMICIRQ_PWRONF,
@@ -364,19 +406,23 @@ enum max8997_irq {
MAX8997_PMICIRQ_RTC1S,
MAX8997_PMICIRQ_WTSR,
- MAX8997_MUICIRQ_ADCError,
- MAX8997_MUICIRQ_ADCLow,
+ MAX8997_PMICIRQ_NR,
+};
+
+enum max8997_irq_muic {
MAX8997_MUICIRQ_ADC,
+ MAX8997_MUICIRQ_ADCLow,
+ MAX8997_MUICIRQ_ADCError,
- MAX8997_MUICIRQ_VBVolt,
- MAX8997_MUICIRQ_DBChg,
- MAX8997_MUICIRQ_DCDTmr,
- MAX8997_MUICIRQ_ChgDetRun,
MAX8997_MUICIRQ_ChgTyp,
+ MAX8997_MUICIRQ_ChgDetRun,
+ MAX8997_MUICIRQ_DCDTmr,
+ MAX8997_MUICIRQ_DBChg,
+ MAX8997_MUICIRQ_VBVolt,
MAX8997_MUICIRQ_OVP,
- MAX8997_IRQ_NR,
+ MAX8997_MUCIRQ_NR,
};
#define MAX8997_NUM_GPIO 12
@@ -397,9 +443,10 @@ struct max8997_dev {
struct regmap *regmap_haptic;
struct regmap *regmap_muic;
+ struct regmap_irq_chip_data *irq_data;
+ struct regmap_irq_chip_data *irq_data_muic;
int irq;
int ono;
- struct irq_domain *irq_domain;
struct mutex irqlock;
int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 1/4] mfd: max8997: use regmap to access registers
From: Robert Baldyga @ 2014-03-13 9:38 UTC (permalink / raw)
To: sameo, lee.jones
Cc: myungjoo.ham, cw00.choi, dmitry.torokhov, cooloney, rpurdie,
dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
k.kozlowski, Robert Baldyga
In-Reply-To: <1394703532-494-1-git-send-email-r.baldyga@samsung.com>
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
@@ -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 related
* Re: [PATCH v2 2/3] mfd: max8997: handle IRQs using regmap
From: Chanwoo Choi @ 2014-03-13 8:03 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: <53216272.7050304@samsung.com>
Hi Robert,
On 03/13/2014 04:46 PM, Robert Baldyga wrote:
> Hi,
> On 03/13/2014 03:03 AM, Chanwoo Choi wrote:
>> Hi Robert,
>>
>> On 03/12/2014 10:37 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>
>>> ---
>>> drivers/extcon/extcon-max8997.c | 35 ++--
>>> drivers/mfd/Kconfig | 2 +-
>>> drivers/mfd/Makefile | 2 +-
>>> drivers/mfd/max8997-irq.c | 373 -----------------------------------
>>> drivers/mfd/max8997.c | 113 ++++++++++-
>>> drivers/rtc/rtc-max8997.c | 2 +-
>>> include/linux/mfd/max8997-private.h | 65 +++++-
>>> 7 files changed, 183 insertions(+), 409 deletions(-)
>>> delete mode 100644 drivers/mfd/max8997-irq.c
>>>
>>> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
>>> index f258c08..15fc5c0 100644
>>> --- a/drivers/extcon/extcon-max8997.c
>>> +++ b/drivers/extcon/extcon-max8997.c
>>> @@ -46,15 +46,15 @@ struct max8997_muic_irq {
>>> };
>>>
>>> static struct max8997_muic_irq muic_irqs[] = {
>>> - { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
>>> - { MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
>>> - { MAX8997_MUICIRQ_ADC, "muic-ADC" },
>>> - { MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
>>> - { MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
>>> - { MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
>>> - { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
>>> - { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
>>> - { MAX8997_MUICIRQ_OVP, "muic-OVP" },
>>> + { MAX8997_MUICIRQ_ADCERROR, "MUIC-ADCERROR" },
>>> + { MAX8997_MUICIRQ_ADCLOW, "MUIC-ADCLOW" },
>>> + { MAX8997_MUICIRQ_ADC, "MUIC-ADC" },
>>> + { MAX8997_MUICIRQ_VBVOLT, "MUIC-VBVOLT" },
>>> + { MAX8997_MUICIRQ_DBCHG, "MUIC-DBCHG" },
>>> + { MAX8997_MUICIRQ_DCDTMR, "MUIC-DCDTMR" },
>>> + { MAX8997_MUICIRQ_CHGDETRUN, "MUIC-CHGDETRUN" },
>>> + { MAX8997_MUICIRQ_CHGTYP, "MUIC-CHGTYP" },
>>> + { MAX8997_MUICIRQ_OVP, "MUIC-OVP" },
>>> };
>>
>>
>> Why did you modify interrput name? Did you have some reason?
>> I think this modification don't need it.
>
> I did it to have one naming convention in max8997-private.h file. Any
> other interrupt names uses upper case, but MUIC iqr's from some reason
> uses CamelCase. I think it's much better to have consistent style in
> entire file.
If you want to modify interrupt name, I think you better separate patch for
this modification. This patch handle only regmap according to the title of this patch.
Thanks,
Chanwoo Choi
^ permalink raw reply
* Re: [PATCH v2 2/3] mfd: max8997: handle IRQs using regmap
From: Lee Jones @ 2014-03-13 8:00 UTC (permalink / raw)
To: Robert Baldyga
Cc: Chanwoo Choi, sameo, 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: <53216272.7050304@samsung.com>
Guys, when replying please cut out all of the unnecessary text. Paging
down though unmodified/unreviewed code is tiresome.
> >> 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>
> >> ---
> >> drivers/extcon/extcon-max8997.c | 35 ++--
> >> drivers/mfd/Kconfig | 2 +-
> >> drivers/mfd/Makefile | 2 +-
> >> drivers/mfd/max8997-irq.c | 373 -----------------------------------
> >> drivers/mfd/max8997.c | 113 ++++++++++-
> >> drivers/rtc/rtc-max8997.c | 2 +-
> >> include/linux/mfd/max8997-private.h | 65 +++++-
> >> 7 files changed, 183 insertions(+), 409 deletions(-)
> >> delete mode 100644 drivers/mfd/max8997-irq.c
> >>
> >> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> >> index f258c08..15fc5c0 100644
> >> --- a/drivers/extcon/extcon-max8997.c
> >> +++ b/drivers/extcon/extcon-max8997.c
> >> @@ -46,15 +46,15 @@ struct max8997_muic_irq {
> >> };
> >>
> >> static struct max8997_muic_irq muic_irqs[] = {
> >> - { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
> >> - { MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
> >> - { MAX8997_MUICIRQ_ADC, "muic-ADC" },
> >> - { MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
> >> - { MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
> >> - { MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
> >> - { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
> >> - { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
> >> - { MAX8997_MUICIRQ_OVP, "muic-OVP" },
> >> + { MAX8997_MUICIRQ_ADCERROR, "MUIC-ADCERROR" },
> >> + { MAX8997_MUICIRQ_ADCLOW, "MUIC-ADCLOW" },
> >> + { MAX8997_MUICIRQ_ADC, "MUIC-ADC" },
> >> + { MAX8997_MUICIRQ_VBVOLT, "MUIC-VBVOLT" },
> >> + { MAX8997_MUICIRQ_DBCHG, "MUIC-DBCHG" },
> >> + { MAX8997_MUICIRQ_DCDTMR, "MUIC-DCDTMR" },
> >> + { MAX8997_MUICIRQ_CHGDETRUN, "MUIC-CHGDETRUN" },
> >> + { MAX8997_MUICIRQ_CHGTYP, "MUIC-CHGTYP" },
> >> + { MAX8997_MUICIRQ_OVP, "MUIC-OVP" },
> >> };
> >
> >
> > Why did you modify interrput name? Did you have some reason?
> > I think this modification don't need it.
>
> I did it to have one naming convention in max8997-private.h file. Any
> other interrupt names uses upper case, but MUIC iqr's from some reason
> uses CamelCase. I think it's much better to have consistent style in
> entire file.
I agree with the modification. CamelCase #defines/enums are hard to
read and look awful.
<snip>
> >> +enum max8997_irq_muic {
> >> MAX8997_MUICIRQ_ADC,
> >> + MAX8997_MUICIRQ_ADCLOW,
> >> + MAX8997_MUICIRQ_ADCERROR,
> >>
> >> - MAX8997_MUICIRQ_VBVolt,
> >> - MAX8997_MUICIRQ_DBChg,
> >> - MAX8997_MUICIRQ_DCDTmr,
> >> - MAX8997_MUICIRQ_ChgDetRun,
> >> - MAX8997_MUICIRQ_ChgTyp,
> >> + MAX8997_MUICIRQ_CHGTYP,
> >> + MAX8997_MUICIRQ_CHGDETRUN,
> >> + MAX8997_MUICIRQ_DCDTMR,
> >> + MAX8997_MUICIRQ_DBCHG,
> >> + MAX8997_MUICIRQ_VBVOLT,
> >
> > ditto.
> > I don't understand why do you modify interrnut name/macro.
... because the old ones are ugly and hard to read.
> >> MAX8997_MUICIRQ_OVP,
> >>
> >> - MAX8997_IRQ_NR,
> >> + MAX8997_MUCIRQ_NR,
> >
> > ditto.
>
> Here I have splitted enum into few enums, each for single interrupt
> source, to make it easier to use with regmap irq handling. So I changed
> MAX8997_IRQ_NR name to MAX8997_MUCIRQ_NR because now it's not number of
> all interrupts but number of interrupts coming form MUIC.
The new name is more inline with the remaining enums, thus is better.
<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 v2 2/3] mfd: max8997: handle IRQs using regmap
From: Robert Baldyga @ 2014-03-13 7:46 UTC (permalink / raw)
To: Chanwoo Choi
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: <532111FA.2010706@samsung.com>
Hi,
On 03/13/2014 03:03 AM, Chanwoo Choi wrote:
> Hi Robert,
>
> On 03/12/2014 10:37 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>
>> ---
>> drivers/extcon/extcon-max8997.c | 35 ++--
>> drivers/mfd/Kconfig | 2 +-
>> drivers/mfd/Makefile | 2 +-
>> drivers/mfd/max8997-irq.c | 373 -----------------------------------
>> drivers/mfd/max8997.c | 113 ++++++++++-
>> drivers/rtc/rtc-max8997.c | 2 +-
>> include/linux/mfd/max8997-private.h | 65 +++++-
>> 7 files changed, 183 insertions(+), 409 deletions(-)
>> delete mode 100644 drivers/mfd/max8997-irq.c
>>
>> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
>> index f258c08..15fc5c0 100644
>> --- a/drivers/extcon/extcon-max8997.c
>> +++ b/drivers/extcon/extcon-max8997.c
>> @@ -46,15 +46,15 @@ struct max8997_muic_irq {
>> };
>>
>> static struct max8997_muic_irq muic_irqs[] = {
>> - { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
>> - { MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
>> - { MAX8997_MUICIRQ_ADC, "muic-ADC" },
>> - { MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
>> - { MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
>> - { MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
>> - { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
>> - { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
>> - { MAX8997_MUICIRQ_OVP, "muic-OVP" },
>> + { MAX8997_MUICIRQ_ADCERROR, "MUIC-ADCERROR" },
>> + { MAX8997_MUICIRQ_ADCLOW, "MUIC-ADCLOW" },
>> + { MAX8997_MUICIRQ_ADC, "MUIC-ADC" },
>> + { MAX8997_MUICIRQ_VBVOLT, "MUIC-VBVOLT" },
>> + { MAX8997_MUICIRQ_DBCHG, "MUIC-DBCHG" },
>> + { MAX8997_MUICIRQ_DCDTMR, "MUIC-DCDTMR" },
>> + { MAX8997_MUICIRQ_CHGDETRUN, "MUIC-CHGDETRUN" },
>> + { MAX8997_MUICIRQ_CHGTYP, "MUIC-CHGTYP" },
>> + { MAX8997_MUICIRQ_OVP, "MUIC-OVP" },
>> };
>
>
> Why did you modify interrput name? Did you have some reason?
> I think this modification don't need it.
I did it to have one naming convention in max8997-private.h file. Any
other interrupt names uses upper case, but MUIC iqr's from some reason
uses CamelCase. I think it's much better to have consistent style in
entire file.
>
>>
>> /* Define supported cable type */
>> @@ -553,17 +553,17 @@ static void max8997_muic_irq_work(struct work_struct *work)
>> }
>>
>> switch (irq_type) {
>> - case MAX8997_MUICIRQ_ADCError:
>> - case MAX8997_MUICIRQ_ADCLow:
>> + case MAX8997_MUICIRQ_ADCERROR:
>> + case MAX8997_MUICIRQ_ADCLOW:
>> case MAX8997_MUICIRQ_ADC:
>> /* Handle all of cable except for charger cable */
>> ret = max8997_muic_adc_handler(info);
>> break;
>> - case MAX8997_MUICIRQ_VBVolt:
>> - case MAX8997_MUICIRQ_DBChg:
>> - case MAX8997_MUICIRQ_DCDTmr:
>> - case MAX8997_MUICIRQ_ChgDetRun:
>> - case MAX8997_MUICIRQ_ChgTyp:
>> + case MAX8997_MUICIRQ_VBVOLT:
>> + case MAX8997_MUICIRQ_DBCHG:
>> + case MAX8997_MUICIRQ_DCDTMR:
>> + case MAX8997_MUICIRQ_CHGDETRUN:
>> + case MAX8997_MUICIRQ_CHGTYP:
>
> I don't agree the modification of MUIC itnerrput.
>
>> /* Handle charger cable */
>> ret = max8997_muic_chg_handler(info);
>> break;
>> @@ -679,7 +679,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
>> struct max8997_muic_irq *muic_irq = &muic_irqs[i];
>> unsigned int virq = 0;
>>
>> - virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
>> + virq = regmap_irq_get_virq(max8997->irq_data_muic,
>> + muic_irq->irq);
>> if (!virq) {
>> ret = -EINVAL;
>> goto err_irq;
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>> index 2871a65..2273574 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -388,7 +388,7 @@ config MFD_MAX8997
>> depends on I2C=y
>> select MFD_CORE
>> select REGMAP_I2C
>> - select IRQ_DOMAIN
>> + select REGMAP_IRQ
>> help
>> Say yes here to add support for Maxim Semiconductor MAX8997/8966.
>> This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
>> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
>> index f5a7b2c..4cec8ad 100644
>> --- a/drivers/mfd/Makefile
>> +++ b/drivers/mfd/Makefile
>> @@ -119,7 +119,7 @@ obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
>> obj-$(CONFIG_MFD_MAX8907) += max8907.o
>> max8925-objs := max8925-core.o max8925-i2c.o
>> obj-$(CONFIG_MFD_MAX8925) += max8925.o
>> -obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
>> +obj-$(CONFIG_MFD_MAX8997) += max8997.o
>> obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
>>
>> pcf50633-objs := pcf50633-core.o pcf50633-irq.o
>> diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
>> deleted file mode 100644
>> index 0e7ff39..0000000
>> --- a/drivers/mfd/max8997-irq.c
>> +++ /dev/null
>> @@ -1,373 +0,0 @@
>> -/*
>> - * max8997-irq.c - Interrupt controller support for MAX8997
>> - *
>> - * Copyright (C) 2011 Samsung Electronics Co.Ltd
>> - * MyungJoo Ham <myungjoo.ham@samsung.com>
>> - *
>> - * 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.
>> - *
>> - * This program is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> - * GNU General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>> - *
>> - * This driver is based on max8998-irq.c
>> - */
>> -
>> -#include <linux/err.h>
>> -#include <linux/irq.h>
>> -#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,
>> - [PMIC_INT2] = MAX8997_REG_INT2MSK,
>> - [PMIC_INT3] = MAX8997_REG_INT3MSK,
>> - [PMIC_INT4] = MAX8997_REG_INT4MSK,
>> - [FUEL_GAUGE] = MAX8997_REG_INVALID,
>> - [MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
>> - [MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
>> - [MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
>> - [GPIO_LOW] = MAX8997_REG_INVALID,
>> - [GPIO_HI] = MAX8997_REG_INVALID,
>> - [FLASH_STATUS] = MAX8997_REG_INVALID,
>> -};
>> -
>> -struct max8997_irq_data {
>> - int mask;
>> - enum max8997_irq_source group;
>> -};
>> -
>> -#define DECLARE_IRQ(idx, _group, _mask) \
>> - [(idx)] = { .group = (_group), .mask = (_mask) }
>> -static const struct max8997_irq_data max8997_irqs[] = {
>> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR, PMIC_INT1, 1 << 0),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF, PMIC_INT1, 1 << 1),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC, PMIC_INT1, 1 << 3),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR, PMIC_INT1, 1 << 4),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF, PMIC_INT1, 1 << 5),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2, PMIC_INT1, 1 << 6),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1, PMIC_INT1, 1 << 7),
>> -
>> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGR, PMIC_INT2, 1 << 0),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGF, PMIC_INT2, 1 << 1),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_MR, PMIC_INT2, 1 << 2),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK, PMIC_INT2, 1 << 3),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK, PMIC_INT2, 1 << 4),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK, PMIC_INT2, 1 << 5),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK, PMIC_INT2, 1 << 6),
>> -
>> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS, PMIC_INT3, 1 << 0),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM, PMIC_INT3, 1 << 1),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP, PMIC_INT3, 1 << 2),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR, PMIC_INT3, 1 << 3),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF, PMIC_INT3, 1 << 5),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD, PMIC_INT3, 1 << 7),
>> -
>> - DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S, PMIC_INT4, 1 << 0),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1, PMIC_INT4, 1 << 1),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2, PMIC_INT4, 1 << 2),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT, PMIC_INT4, 1 << 3),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S, PMIC_INT4, 1 << 4),
>> - DECLARE_IRQ(MAX8997_PMICIRQ_WTSR, PMIC_INT4, 1 << 5),
>> -
>> - DECLARE_IRQ(MAX8997_MUICIRQ_ADCError, MUIC_INT1, 1 << 2),
>> - DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow, MUIC_INT1, 1 << 1),
>> - DECLARE_IRQ(MAX8997_MUICIRQ_ADC, MUIC_INT1, 1 << 0),
>> -
>> - DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt, MUIC_INT2, 1 << 4),
>> - DECLARE_IRQ(MAX8997_MUICIRQ_DBChg, MUIC_INT2, 1 << 3),
>> - DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr, MUIC_INT2, 1 << 2),
>> - DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun, MUIC_INT2, 1 << 1),
>> - DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp, MUIC_INT2, 1 << 0),
>> -
>> - DECLARE_IRQ(MAX8997_MUICIRQ_OVP, MUIC_INT3, 1 << 2),
>> -};
>> -
>> -static void max8997_irq_lock(struct irq_data *data)
>> -{
>> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
>> -
>> - mutex_lock(&max8997->irqlock);
>> -}
>> -
>> -static void max8997_irq_sync_unlock(struct irq_data *data)
>> -{
>> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
>> - int i;
>> -
>> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
>> - struct regmap *map;
>> - u8 mask_reg = max8997_mask_reg[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(map))
>> - continue;
>> - max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
>> -
>> - regmap_write(map, max8997_mask_reg[i],
>> - max8997->irq_masks_cur[i]);
>> - }
>> -
>> - mutex_unlock(&max8997->irqlock);
>> -}
>> -
>> -static const inline struct max8997_irq_data *
>> -irq_to_max8997_irq(struct max8997_dev *max8997, int irq)
>> -{
>> - struct irq_data *data = irq_get_irq_data(irq);
>> - return &max8997_irqs[data->hwirq];
>> -}
>> -
>> -static void max8997_irq_mask(struct irq_data *data)
>> -{
>> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
>> - const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
>> - data->irq);
>> -
>> - max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
>> -}
>> -
>> -static void max8997_irq_unmask(struct irq_data *data)
>> -{
>> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
>> - const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
>> - data->irq);
>> -
>> - max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
>> -}
>> -
>> -static struct irq_chip max8997_irq_chip = {
>> - .name = "max8997",
>> - .irq_bus_lock = max8997_irq_lock,
>> - .irq_bus_sync_unlock = max8997_irq_sync_unlock,
>> - .irq_mask = max8997_irq_mask,
>> - .irq_unmask = max8997_irq_unmask,
>> -};
>> -
>> -#define MAX8997_IRQSRC_PMIC (1 << 1)
>> -#define MAX8997_IRQSRC_FUELGAUGE (1 << 2)
>> -#define MAX8997_IRQSRC_MUIC (1 << 3)
>> -#define MAX8997_IRQSRC_GPIO (1 << 4)
>> -#define MAX8997_IRQSRC_FLASH (1 << 5)
>> -static irqreturn_t max8997_irq_thread(int irq, void *data)
>> -{
>> - struct max8997_dev *max8997 = data;
>> - u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
>> - unsigned int irq_src;
>> - int ret;
>> - int i, cur_irq;
>> -
>> - 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);
>> - return IRQ_NONE;
>> - }
>> -
>> - if (irq_src & MAX8997_IRQSRC_PMIC) {
>> - /* PMIC INT1 ~ INT4 */
>> - regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
>> - &irq_reg[PMIC_INT1], 4);
>> - }
>> - if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
>> - /*
>> - * TODO: FUEL GAUGE
>> - *
>> - * This is to be supported by Max17042 driver. When
>> - * an interrupt incurs here, it should be relayed to a
>> - * Max17042 device that is connected (probably by
>> - * platform-data). However, we do not have interrupt
>> - * handling in Max17042 driver currently. The Max17042 IRQ
>> - * driver should be ready to be used as a stand-alone device and
>> - * a Max8997-dependent device. Because it is not ready in
>> - * Max17042-side and it is not too critical in operating
>> - * Max8997, we do not implement this in initial releases.
>> - */
>> - irq_reg[FUEL_GAUGE] = 0;
>> - }
>> - if (irq_src & MAX8997_IRQSRC_MUIC) {
>> - /* MUIC INT1 ~ INT3 */
>> - regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
>> - &irq_reg[MUIC_INT1], 3);
>> - }
>> - if (irq_src & MAX8997_IRQSRC_GPIO) {
>> - /* GPIO Interrupt */
>> - u8 gpio_info[MAX8997_NUM_GPIO];
>> -
>> - irq_reg[GPIO_LOW] = 0;
>> - irq_reg[GPIO_HI] = 0;
>> -
>> - regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
>> - gpio_info, MAX8997_NUM_GPIO);
>> - for (i = 0; i < MAX8997_NUM_GPIO; i++) {
>> - bool interrupt = false;
>> -
>> - switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
>> - case MAX8997_GPIO_INT_BOTH:
>> - if (max8997->gpio_status[i] != gpio_info[i])
>> - interrupt = true;
>> - break;
>> - case MAX8997_GPIO_INT_RISE:
>> - if ((max8997->gpio_status[i] != gpio_info[i]) &&
>> - (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
>> - interrupt = true;
>> - break;
>> - case MAX8997_GPIO_INT_FALL:
>> - if ((max8997->gpio_status[i] != gpio_info[i]) &&
>> - !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
>> - interrupt = true;
>> - break;
>> - default:
>> - break;
>> - }
>> -
>> - if (interrupt) {
>> - if (i < 8)
>> - irq_reg[GPIO_LOW] |= (1 << i);
>> - else
>> - irq_reg[GPIO_HI] |= (1 << (i - 8));
>> - }
>> -
>> - }
>> - }
>> - if (irq_src & MAX8997_IRQSRC_FLASH) {
>> - /* Flash Status Interrupt */
>> - unsigned int data;
>> - ret = regmap_read(max8997->regmap,
>> - MAX8997_REG_FLASHSTATUS, &data);
>> - irq_reg[FLASH_STATUS] = data;
>> - }
>> -
>> - /* Apply masking */
>> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
>> - irq_reg[i] &= ~max8997->irq_masks_cur[i];
>> -
>> - /* Report */
>> - for (i = 0; i < MAX8997_IRQ_NR; i++) {
>> - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
>> - cur_irq = irq_find_mapping(max8997->irq_domain, i);
>> - if (cur_irq)
>> - handle_nested_irq(cur_irq);
>> - }
>> - }
>> -
>> - return IRQ_HANDLED;
>> -}
>> -
>> -int max8997_irq_resume(struct max8997_dev *max8997)
>> -{
>> - if (max8997->irq && max8997->irq_domain)
>> - max8997_irq_thread(0, max8997);
>> - return 0;
>> -}
>> -
>> -static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq,
>> - irq_hw_number_t hw)
>> -{
>> - struct max8997_dev *max8997 = d->host_data;
>> -
>> - irq_set_chip_data(irq, max8997);
>> - irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq);
>> - irq_set_nested_thread(irq, 1);
>> -#ifdef CONFIG_ARM
>> - set_irq_flags(irq, IRQF_VALID);
>> -#else
>> - irq_set_noprobe(irq);
>> -#endif
>> - return 0;
>> -}
>> -
>> -static struct irq_domain_ops max8997_irq_domain_ops = {
>> - .map = max8997_irq_domain_map,
>> -};
>> -
>> -int max8997_irq_init(struct max8997_dev *max8997)
>> -{
>> - struct irq_domain *domain;
>> - int i;
>> - int ret;
>> - unsigned int val;
>> -
>> - if (!max8997->irq) {
>> - dev_warn(max8997->dev, "No interrupt specified.\n");
>> - return 0;
>> - }
>> -
>> - mutex_init(&max8997->irqlock);
>> -
>> - /* Mask individual interrupt sources */
>> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
>> - max8997->irq_masks_cur[i] = 0xff;
>> - max8997->irq_masks_cache[i] = 0xff;
>> -
>> - if (IS_ERR_OR_NULL(max8997->regmap))
>> - continue;
>> - if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
>> - continue;
>> -
>> - regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
>> - }
>> -
>> - for (i = 0; i < MAX8997_NUM_GPIO; i++) {
>> - max8997->gpio_status[i] = (regmap_read(max8997->regmap,
>> - MAX8997_REG_GPIOCNTL1 + i,
>> - &val)
>> - & MAX8997_GPIO_DATA_MASK) ?
>> - true : false;
>> - }
>> -
>> - domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
>> - &max8997_irq_domain_ops, max8997);
>> - if (!domain) {
>> - dev_err(max8997->dev, "could not create irq domain\n");
>> - return -ENODEV;
>> - }
>> - max8997->irq_domain = domain;
>> -
>> - ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
>> - IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>> - "max8997-irq", max8997);
>> -
>> - if (ret) {
>> - dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
>> - max8997->irq, ret);
>> - return ret;
>> - }
>> -
>> - if (!max8997->ono)
>> - return 0;
>> -
>> - ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
>> - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
>> - IRQF_ONESHOT, "max8997-ono", max8997);
>> -
>> - if (ret)
>> - dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
>> - max8997->ono, ret);
>> -
>> - return 0;
>> -}
>> -
>> -void max8997_irq_exit(struct max8997_dev *max8997)
>> -{
>> - if (max8997->ono)
>> - free_irq(max8997->ono, max8997);
>> -
>> - if (max8997->irq)
>> - free_irq(max8997->irq, max8997);
>> -}
>> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
>> index 782d7c9..26a360d 100644
>> --- a/drivers/mfd/max8997.c
>> +++ b/drivers/mfd/max8997.c
>> @@ -64,6 +64,49 @@ static const struct regmap_config max8997_regmap_config = {
>> .max_register = MAX8997_REG_PMIC_END,
>> };
>>
>> +static const struct regmap_irq max8997_irqs[] = {
>> + /* PMIC_INT1 interrupts */
>> + { .reg_offset = 0, .mask = PMIC_INT1_PWRONR_MASK, },
>> + { .reg_offset = 0, .mask = PMIC_INT1_PWRONF_MASK, },
>> + { .reg_offset = 0, .mask = PMIC_INT1_PWRON1SEC_MASK, },
>> + { .reg_offset = 0, .mask = PMIC_INT1_JIGONR_MASK, },
>> + { .reg_offset = 0, .mask = PMIC_INT1_JIGONF_MASK, },
>> + { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT2_MASK, },
>> + { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT1_MASK, },
>> + /* PMIC_INT2 interrupts */
>> + { .reg_offset = 1, .mask = PMIC_INT2_JIGR_MASK, },
>> + { .reg_offset = 1, .mask = PMIC_INT2_JIGF_MASK, },
>> + { .reg_offset = 1, .mask = PMIC_INT2_MR_MASK, },
>> + { .reg_offset = 1, .mask = PMIC_INT2_DVS1OK_MASK, },
>> + { .reg_offset = 1, .mask = PMIC_INT2_DVS2OK_MASK, },
>> + { .reg_offset = 1, .mask = PMIC_INT2_DVS3OK_MASK, },
>> + { .reg_offset = 1, .mask = PMIC_INT2_DVS4OK_MASK, },
>> + /* PMIC_INT3 interrupts */
>> + { .reg_offset = 2, .mask = PMIC_INT3_CHGINS_MASK, },
>> + { .reg_offset = 2, .mask = PMIC_INT3_CHGRM_MASK, },
>> + { .reg_offset = 2, .mask = PMIC_INT3_DCINOVP_MASK, },
>> + { .reg_offset = 2, .mask = PMIC_INT3_TOPOFFR_MASK, },
>> + { .reg_offset = 2, .mask = PMIC_INT3_CHGRSTF_MASK, },
>> + { .reg_offset = 2, .mask = PMIC_INT3_MBCHGTMEXPD_MASK, },
>> + /* PMIC_INT4 interrupts */
>> + { .reg_offset = 3, .mask = PMIC_INT4_RTC60S_MASK, },
>> + { .reg_offset = 3, .mask = PMIC_INT4_RTCA1_MASK, },
>> + { .reg_offset = 3, .mask = PMIC_INT4_RTCA2_MASK, },
>> + { .reg_offset = 3, .mask = PMIC_INT4_SMPL_INT_MASK, },
>> + { .reg_offset = 3, .mask = PMIC_INT4_RTC1S_MASK, },
>> + { .reg_offset = 3, .mask = PMIC_INT4_WTSR_MASK, },
>> +};
>> +
>> +static const struct regmap_irq_chip max8997_irq_chip = {
>> + .name = "max8997",
>> + .status_base = MAX8997_REG_INT1,
>> + .mask_base = MAX8997_REG_INT1MSK,
>> + .mask_invert = false,
>> + .num_regs = 4,
>> + .irqs = max8997_irqs,
>> + .num_irqs = ARRAY_SIZE(max8997_irqs),
>> +};
>> +
>> static const struct regmap_config max8997_regmap_rtc_config = {
>> .reg_bits = 8,
>> .val_bits = 8,
>> @@ -82,6 +125,31 @@ static const struct regmap_config max8997_regmap_muic_config = {
>> .max_register = MAX8997_MUIC_REG_END,
>> };
>>
>> +static const struct regmap_irq max8997_irqs_muic[] = {
>> + /* MUIC_INT1 interrupts */
>> + { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
>> + { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
>> + { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
>> + /* MUIC_INT2 interrupts */
>> + { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
>> + { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
>> + { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
>> + { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
>> + { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
>> + /* MUIC_INT3 interrupts */
>> + { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
>> +};
>> +
>> +static const struct regmap_irq_chip max8997_irq_chip_muic = {
>> + .name = "max8997-muic",
>> + .status_base = MAX8997_MUIC_REG_INT1,
>> + .mask_base = MAX8997_MUIC_REG_INTMASK1,
>> + .mask_invert = true,
>> + .num_regs = 3,
>> + .irqs = max8997_irqs_muic,
>> + .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
>> +};
>> +
>> /*
>> * Only the common platform data elements for max8997 are parsed here from the
>> * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
>> @@ -214,9 +282,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>> goto err_regmap;
>> }
>>
>> - pm_runtime_set_active(max8997->dev);
>> + ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
>> + IRQF_ONESHOT | IRQF_SHARED |
>> + IRQF_TRIGGER_FALLING, 0,
>> + &max8997_irq_chip, &max8997->irq_data);
>> + if (ret) {
>> + dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
>> + goto err_irq;
>> + }
>>
>> - max8997_irq_init(max8997);
>> + ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
>> + IRQF_ONESHOT | IRQF_SHARED |
>> + IRQF_TRIGGER_FALLING, 0,
>> + &max8997_irq_chip_muic,
>> + &max8997->irq_data_muic);
>> + if (ret) {
>> + dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
>> + goto err_irq_muic;
>> + }
>> +
>> + pm_runtime_set_active(max8997->dev);
>>
>> ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
>> ARRAY_SIZE(max8997_devs),
>> @@ -238,6 +323,10 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>>
>> err_mfd:
>> mfd_remove_devices(max8997->dev);
>> +err_irq_muic:
>> + regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
>> +err_irq:
>> + regmap_del_irq_chip(max8997->irq, max8997->irq_data);
>> err_regmap:
>> i2c_unregister_device(max8997->muic);
>> err_i2c_muic:
>> @@ -252,6 +341,10 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
>> struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>>
>> mfd_remove_devices(max8997->dev);
>> +
>> + regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
>> + regmap_del_irq_chip(max8997->irq, max8997->irq_data);
>> +
>> i2c_unregister_device(max8997->muic);
>> i2c_unregister_device(max8997->haptic);
>> i2c_unregister_device(max8997->rtc);
>> @@ -468,8 +561,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);
>> + }
>> +
>> return 0;
>> }
>>
>> @@ -478,9 +574,12 @@ static int max8997_resume(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, 0);
>> - return max8997_irq_resume(max8997);
>> + if (device_may_wakeup(dev)) {
>> + disable_irq_wake(max8997->irq);
>> + enable_irq(max8997->irq);
>> + }
>> +
>> + return 0;
>> }
>>
>> static const struct dev_pm_ops max8997_pm = {
>> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
>> index b866f7d5..22769ea 100644
>> --- a/drivers/rtc/rtc-max8997.c
>> +++ b/drivers/rtc/rtc-max8997.c
>> @@ -494,7 +494,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
>> return ret;
>> }
>>
>> - virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1);
>> + virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
>> if (!virq) {
>> dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
>> ret = -ENXIO;
>> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
>> index ea80ef8..2817fa6 100644
>> --- a/include/linux/mfd/max8997-private.h
>> +++ b/include/linux/mfd/max8997-private.h
>> @@ -333,6 +333,48 @@ enum max8997_irq_source {
>> MAX8997_IRQ_GROUP_NR,
>> };
>>
>> +#define PMIC_INT1_PWRONR_MASK (0x1 << 0)
>> +#define PMIC_INT1_PWRONF_MASK (0x1 << 1)
>> +#define PMIC_INT1_PWRON1SEC_MASK (0x1 << 3)
>> +#define PMIC_INT1_JIGONR_MASK (0x1 << 4)
>> +#define PMIC_INT1_JIGONF_MASK (0x1 << 5)
>> +#define PMIC_INT1_LOWBAT2_MASK (0x1 << 6)
>> +#define PMIC_INT1_LOWBAT1_MASK (0x1 << 7)
>> +
>> +#define PMIC_INT2_JIGR_MASK (0x1 << 0)
>> +#define PMIC_INT2_JIGF_MASK (0x1 << 1)
>> +#define PMIC_INT2_MR_MASK (0x1 << 2)
>> +#define PMIC_INT2_DVS1OK_MASK (0x1 << 3)
>> +#define PMIC_INT2_DVS2OK_MASK (0x1 << 4)
>> +#define PMIC_INT2_DVS3OK_MASK (0x1 << 5)
>> +#define PMIC_INT2_DVS4OK_MASK (0x1 << 6)
>> +
>> +#define PMIC_INT3_CHGINS_MASK (0x1 << 0)
>> +#define PMIC_INT3_CHGRM_MASK (0x1 << 1)
>> +#define PMIC_INT3_DCINOVP_MASK (0x1 << 2)
>> +#define PMIC_INT3_TOPOFFR_MASK (0x1 << 3)
>> +#define PMIC_INT3_CHGRSTF_MASK (0x1 << 5)
>> +#define PMIC_INT3_MBCHGTMEXPD_MASK (0x1 << 7)
>> +
>> +#define PMIC_INT4_RTC60S_MASK (0x1 << 0)
>> +#define PMIC_INT4_RTCA1_MASK (0x1 << 1)
>> +#define PMIC_INT4_RTCA2_MASK (0x1 << 2)
>> +#define PMIC_INT4_SMPL_INT_MASK (0x1 << 3)
>> +#define PMIC_INT4_RTC1S_MASK (0x1 << 4)
>> +#define PMIC_INT4_WTSR_MASK (0x1 << 5)
>> +
>> +#define MUIC_INT1_ADC_MASK (0x1 << 0)
>> +#define MUIC_INT1_ADCLOW_MASK (0x1 << 1)
>> +#define MUIC_INT1_ADCERROR_MASK (0x1 << 2)
>> +
>> +#define MUIC_INT2_CHGTYP_MASK (0x1 << 0)
>> +#define MUIC_INT2_CHGDETRUN_MASK (0x1 << 1)
>> +#define MUIC_INT2_DCDTMR_MASK (0x1 << 2)
>> +#define MUIC_INT2_DBCHG_MASK (0x1 << 3)
>> +#define MUIC_INT2_VBVOLT_MASK (0x1 << 4)
>> +
>> +#define MUIC_INT3_OVP_MASK (0x1 << 2)
>> +
>> enum max8997_irq {
>> MAX8997_PMICIRQ_PWRONR,
>> MAX8997_PMICIRQ_PWRONF,
>> @@ -364,19 +406,23 @@ enum max8997_irq {
>> MAX8997_PMICIRQ_RTC1S,
>> MAX8997_PMICIRQ_WTSR,
>>
>> - MAX8997_MUICIRQ_ADCError,
>> - MAX8997_MUICIRQ_ADCLow,
>> + MAX8997_PMICIRQ_NR,
>> +};
>> +
>> +enum max8997_irq_muic {
>> MAX8997_MUICIRQ_ADC,
>> + MAX8997_MUICIRQ_ADCLOW,
>> + MAX8997_MUICIRQ_ADCERROR,
>>
>> - MAX8997_MUICIRQ_VBVolt,
>> - MAX8997_MUICIRQ_DBChg,
>> - MAX8997_MUICIRQ_DCDTmr,
>> - MAX8997_MUICIRQ_ChgDetRun,
>> - MAX8997_MUICIRQ_ChgTyp,
>> + MAX8997_MUICIRQ_CHGTYP,
>> + MAX8997_MUICIRQ_CHGDETRUN,
>> + MAX8997_MUICIRQ_DCDTMR,
>> + MAX8997_MUICIRQ_DBCHG,
>> + MAX8997_MUICIRQ_VBVOLT,
>
> ditto.
> I don't understand why do you modify interrnut name/macro.
>
>>
>> MAX8997_MUICIRQ_OVP,
>>
>> - MAX8997_IRQ_NR,
>> + MAX8997_MUCIRQ_NR,
>
> ditto.
>
Here I have splitted enum into few enums, each for single interrupt
source, to make it easier to use with regmap irq handling. So I changed
MAX8997_IRQ_NR name to MAX8997_MUCIRQ_NR because now it's not number of
all interrupts but number of interrupts coming form MUIC.
>> };
>>
>> #define MAX8997_NUM_GPIO 12
>> @@ -397,9 +443,10 @@ struct max8997_dev {
>> struct regmap *regmap_haptic;
>> struct regmap *regmap_muic;
>>
>> + struct regmap_irq_chip_data *irq_data;
>> + struct regmap_irq_chip_data *irq_data_muic;
>> int irq;
>> int ono;
>> - struct irq_domain *irq_domain;
>> struct mutex irqlock;
>> int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
>> int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
>>
>
Thanks,
Robert Baldyga
^ permalink raw reply
* Re: [patch] Input: remove a duplicative NULL test
From: Benson Leung @ 2014-03-13 4:24 UTC (permalink / raw)
To: fugang.duan@freescale.com, Nick Dyer
Cc: Dan Carpenter, Dmitry Torokhov, Paul Gortmaker, Jingoo Han,
Daniel Kurtz, linux-input@vger.kernel.org,
kernel-janitors@vger.kernel.org
In-Reply-To: <e1cf3227a1484c3b931abb61b97391a6@BLUPR03MB373.namprd03.prod.outlook.com>
On Fri, Feb 21, 2014 at 1:14 AM, fugang.duan@freescale.com
<fugang.duan@freescale.com> wrote:
>
> Agree, it is redundant. And if you have free time, you can convert the driver to support devicetree.
Please check with Nick Dyer before you convert this driver to support
devicetree. Much of the platform data this driver uses has been
eliminated or consolidated in a patch series that he's been working
on.
--
Benson Leung
Software Engineer, Chrom* OS
bleung@chromium.org
^ permalink raw reply
* Re: [PATCH v2 2/3] mfd: max8997: handle IRQs using regmap
From: Chanwoo Choi @ 2014-03-13 2:03 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: <1394631466-6429-3-git-send-email-r.baldyga@samsung.com>
Hi Robert,
On 03/12/2014 10:37 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>
> ---
> drivers/extcon/extcon-max8997.c | 35 ++--
> drivers/mfd/Kconfig | 2 +-
> drivers/mfd/Makefile | 2 +-
> drivers/mfd/max8997-irq.c | 373 -----------------------------------
> drivers/mfd/max8997.c | 113 ++++++++++-
> drivers/rtc/rtc-max8997.c | 2 +-
> include/linux/mfd/max8997-private.h | 65 +++++-
> 7 files changed, 183 insertions(+), 409 deletions(-)
> delete mode 100644 drivers/mfd/max8997-irq.c
>
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index f258c08..15fc5c0 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -46,15 +46,15 @@ struct max8997_muic_irq {
> };
>
> static struct max8997_muic_irq muic_irqs[] = {
> - { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
> - { MAX8997_MUICIRQ_ADCLow, "muic-ADCLOW" },
> - { MAX8997_MUICIRQ_ADC, "muic-ADC" },
> - { MAX8997_MUICIRQ_VBVolt, "muic-VBVOLT" },
> - { MAX8997_MUICIRQ_DBChg, "muic-DBCHG" },
> - { MAX8997_MUICIRQ_DCDTmr, "muic-DCDTMR" },
> - { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
> - { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
> - { MAX8997_MUICIRQ_OVP, "muic-OVP" },
> + { MAX8997_MUICIRQ_ADCERROR, "MUIC-ADCERROR" },
> + { MAX8997_MUICIRQ_ADCLOW, "MUIC-ADCLOW" },
> + { MAX8997_MUICIRQ_ADC, "MUIC-ADC" },
> + { MAX8997_MUICIRQ_VBVOLT, "MUIC-VBVOLT" },
> + { MAX8997_MUICIRQ_DBCHG, "MUIC-DBCHG" },
> + { MAX8997_MUICIRQ_DCDTMR, "MUIC-DCDTMR" },
> + { MAX8997_MUICIRQ_CHGDETRUN, "MUIC-CHGDETRUN" },
> + { MAX8997_MUICIRQ_CHGTYP, "MUIC-CHGTYP" },
> + { MAX8997_MUICIRQ_OVP, "MUIC-OVP" },
> };
Why did you modify interrput name? Did you have some reason?
I think this modification don't need it.
>
> /* Define supported cable type */
> @@ -553,17 +553,17 @@ static void max8997_muic_irq_work(struct work_struct *work)
> }
>
> switch (irq_type) {
> - case MAX8997_MUICIRQ_ADCError:
> - case MAX8997_MUICIRQ_ADCLow:
> + case MAX8997_MUICIRQ_ADCERROR:
> + case MAX8997_MUICIRQ_ADCLOW:
> case MAX8997_MUICIRQ_ADC:
> /* Handle all of cable except for charger cable */
> ret = max8997_muic_adc_handler(info);
> break;
> - case MAX8997_MUICIRQ_VBVolt:
> - case MAX8997_MUICIRQ_DBChg:
> - case MAX8997_MUICIRQ_DCDTmr:
> - case MAX8997_MUICIRQ_ChgDetRun:
> - case MAX8997_MUICIRQ_ChgTyp:
> + case MAX8997_MUICIRQ_VBVOLT:
> + case MAX8997_MUICIRQ_DBCHG:
> + case MAX8997_MUICIRQ_DCDTMR:
> + case MAX8997_MUICIRQ_CHGDETRUN:
> + case MAX8997_MUICIRQ_CHGTYP:
I don't agree the modification of MUIC itnerrput.
> /* Handle charger cable */
> ret = max8997_muic_chg_handler(info);
> break;
> @@ -679,7 +679,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
> struct max8997_muic_irq *muic_irq = &muic_irqs[i];
> unsigned int virq = 0;
>
> - virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
> + virq = regmap_irq_get_virq(max8997->irq_data_muic,
> + muic_irq->irq);
> if (!virq) {
> ret = -EINVAL;
> goto err_irq;
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 2871a65..2273574 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -388,7 +388,7 @@ config MFD_MAX8997
> depends on I2C=y
> select MFD_CORE
> select REGMAP_I2C
> - select IRQ_DOMAIN
> + select REGMAP_IRQ
> help
> Say yes here to add support for Maxim Semiconductor MAX8997/8966.
> This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index f5a7b2c..4cec8ad 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -119,7 +119,7 @@ obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
> obj-$(CONFIG_MFD_MAX8907) += max8907.o
> max8925-objs := max8925-core.o max8925-i2c.o
> obj-$(CONFIG_MFD_MAX8925) += max8925.o
> -obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
> +obj-$(CONFIG_MFD_MAX8997) += max8997.o
> obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
>
> pcf50633-objs := pcf50633-core.o pcf50633-irq.o
> diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
> deleted file mode 100644
> index 0e7ff39..0000000
> --- a/drivers/mfd/max8997-irq.c
> +++ /dev/null
> @@ -1,373 +0,0 @@
> -/*
> - * max8997-irq.c - Interrupt controller support for MAX8997
> - *
> - * Copyright (C) 2011 Samsung Electronics Co.Ltd
> - * MyungJoo Ham <myungjoo.ham@samsung.com>
> - *
> - * 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.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> - *
> - * This driver is based on max8998-irq.c
> - */
> -
> -#include <linux/err.h>
> -#include <linux/irq.h>
> -#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,
> - [PMIC_INT2] = MAX8997_REG_INT2MSK,
> - [PMIC_INT3] = MAX8997_REG_INT3MSK,
> - [PMIC_INT4] = MAX8997_REG_INT4MSK,
> - [FUEL_GAUGE] = MAX8997_REG_INVALID,
> - [MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
> - [MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
> - [MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
> - [GPIO_LOW] = MAX8997_REG_INVALID,
> - [GPIO_HI] = MAX8997_REG_INVALID,
> - [FLASH_STATUS] = MAX8997_REG_INVALID,
> -};
> -
> -struct max8997_irq_data {
> - int mask;
> - enum max8997_irq_source group;
> -};
> -
> -#define DECLARE_IRQ(idx, _group, _mask) \
> - [(idx)] = { .group = (_group), .mask = (_mask) }
> -static const struct max8997_irq_data max8997_irqs[] = {
> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR, PMIC_INT1, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF, PMIC_INT1, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC, PMIC_INT1, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR, PMIC_INT1, 1 << 4),
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF, PMIC_INT1, 1 << 5),
> - DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2, PMIC_INT1, 1 << 6),
> - DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1, PMIC_INT1, 1 << 7),
> -
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGR, PMIC_INT2, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_JIGF, PMIC_INT2, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_MR, PMIC_INT2, 1 << 2),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK, PMIC_INT2, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK, PMIC_INT2, 1 << 4),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK, PMIC_INT2, 1 << 5),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK, PMIC_INT2, 1 << 6),
> -
> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS, PMIC_INT3, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM, PMIC_INT3, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP, PMIC_INT3, 1 << 2),
> - DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR, PMIC_INT3, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF, PMIC_INT3, 1 << 5),
> - DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD, PMIC_INT3, 1 << 7),
> -
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S, PMIC_INT4, 1 << 0),
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1, PMIC_INT4, 1 << 1),
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2, PMIC_INT4, 1 << 2),
> - DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT, PMIC_INT4, 1 << 3),
> - DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S, PMIC_INT4, 1 << 4),
> - DECLARE_IRQ(MAX8997_PMICIRQ_WTSR, PMIC_INT4, 1 << 5),
> -
> - DECLARE_IRQ(MAX8997_MUICIRQ_ADCError, MUIC_INT1, 1 << 2),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow, MUIC_INT1, 1 << 1),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ADC, MUIC_INT1, 1 << 0),
> -
> - DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt, MUIC_INT2, 1 << 4),
> - DECLARE_IRQ(MAX8997_MUICIRQ_DBChg, MUIC_INT2, 1 << 3),
> - DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr, MUIC_INT2, 1 << 2),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun, MUIC_INT2, 1 << 1),
> - DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp, MUIC_INT2, 1 << 0),
> -
> - DECLARE_IRQ(MAX8997_MUICIRQ_OVP, MUIC_INT3, 1 << 2),
> -};
> -
> -static void max8997_irq_lock(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> -
> - mutex_lock(&max8997->irqlock);
> -}
> -
> -static void max8997_irq_sync_unlock(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> - int i;
> -
> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> - struct regmap *map;
> - u8 mask_reg = max8997_mask_reg[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(map))
> - continue;
> - max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
> -
> - regmap_write(map, max8997_mask_reg[i],
> - max8997->irq_masks_cur[i]);
> - }
> -
> - mutex_unlock(&max8997->irqlock);
> -}
> -
> -static const inline struct max8997_irq_data *
> -irq_to_max8997_irq(struct max8997_dev *max8997, int irq)
> -{
> - struct irq_data *data = irq_get_irq_data(irq);
> - return &max8997_irqs[data->hwirq];
> -}
> -
> -static void max8997_irq_mask(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> - const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
> - data->irq);
> -
> - max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
> -}
> -
> -static void max8997_irq_unmask(struct irq_data *data)
> -{
> - struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
> - const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
> - data->irq);
> -
> - max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
> -}
> -
> -static struct irq_chip max8997_irq_chip = {
> - .name = "max8997",
> - .irq_bus_lock = max8997_irq_lock,
> - .irq_bus_sync_unlock = max8997_irq_sync_unlock,
> - .irq_mask = max8997_irq_mask,
> - .irq_unmask = max8997_irq_unmask,
> -};
> -
> -#define MAX8997_IRQSRC_PMIC (1 << 1)
> -#define MAX8997_IRQSRC_FUELGAUGE (1 << 2)
> -#define MAX8997_IRQSRC_MUIC (1 << 3)
> -#define MAX8997_IRQSRC_GPIO (1 << 4)
> -#define MAX8997_IRQSRC_FLASH (1 << 5)
> -static irqreturn_t max8997_irq_thread(int irq, void *data)
> -{
> - struct max8997_dev *max8997 = data;
> - u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
> - unsigned int irq_src;
> - int ret;
> - int i, cur_irq;
> -
> - 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);
> - return IRQ_NONE;
> - }
> -
> - if (irq_src & MAX8997_IRQSRC_PMIC) {
> - /* PMIC INT1 ~ INT4 */
> - regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
> - &irq_reg[PMIC_INT1], 4);
> - }
> - if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
> - /*
> - * TODO: FUEL GAUGE
> - *
> - * This is to be supported by Max17042 driver. When
> - * an interrupt incurs here, it should be relayed to a
> - * Max17042 device that is connected (probably by
> - * platform-data). However, we do not have interrupt
> - * handling in Max17042 driver currently. The Max17042 IRQ
> - * driver should be ready to be used as a stand-alone device and
> - * a Max8997-dependent device. Because it is not ready in
> - * Max17042-side and it is not too critical in operating
> - * Max8997, we do not implement this in initial releases.
> - */
> - irq_reg[FUEL_GAUGE] = 0;
> - }
> - if (irq_src & MAX8997_IRQSRC_MUIC) {
> - /* MUIC INT1 ~ INT3 */
> - regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
> - &irq_reg[MUIC_INT1], 3);
> - }
> - if (irq_src & MAX8997_IRQSRC_GPIO) {
> - /* GPIO Interrupt */
> - u8 gpio_info[MAX8997_NUM_GPIO];
> -
> - irq_reg[GPIO_LOW] = 0;
> - irq_reg[GPIO_HI] = 0;
> -
> - regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
> - gpio_info, MAX8997_NUM_GPIO);
> - for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> - bool interrupt = false;
> -
> - switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
> - case MAX8997_GPIO_INT_BOTH:
> - if (max8997->gpio_status[i] != gpio_info[i])
> - interrupt = true;
> - break;
> - case MAX8997_GPIO_INT_RISE:
> - if ((max8997->gpio_status[i] != gpio_info[i]) &&
> - (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
> - interrupt = true;
> - break;
> - case MAX8997_GPIO_INT_FALL:
> - if ((max8997->gpio_status[i] != gpio_info[i]) &&
> - !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
> - interrupt = true;
> - break;
> - default:
> - break;
> - }
> -
> - if (interrupt) {
> - if (i < 8)
> - irq_reg[GPIO_LOW] |= (1 << i);
> - else
> - irq_reg[GPIO_HI] |= (1 << (i - 8));
> - }
> -
> - }
> - }
> - if (irq_src & MAX8997_IRQSRC_FLASH) {
> - /* Flash Status Interrupt */
> - unsigned int data;
> - ret = regmap_read(max8997->regmap,
> - MAX8997_REG_FLASHSTATUS, &data);
> - irq_reg[FLASH_STATUS] = data;
> - }
> -
> - /* Apply masking */
> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
> - irq_reg[i] &= ~max8997->irq_masks_cur[i];
> -
> - /* Report */
> - for (i = 0; i < MAX8997_IRQ_NR; i++) {
> - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
> - cur_irq = irq_find_mapping(max8997->irq_domain, i);
> - if (cur_irq)
> - handle_nested_irq(cur_irq);
> - }
> - }
> -
> - return IRQ_HANDLED;
> -}
> -
> -int max8997_irq_resume(struct max8997_dev *max8997)
> -{
> - if (max8997->irq && max8997->irq_domain)
> - max8997_irq_thread(0, max8997);
> - return 0;
> -}
> -
> -static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq,
> - irq_hw_number_t hw)
> -{
> - struct max8997_dev *max8997 = d->host_data;
> -
> - irq_set_chip_data(irq, max8997);
> - irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq);
> - irq_set_nested_thread(irq, 1);
> -#ifdef CONFIG_ARM
> - set_irq_flags(irq, IRQF_VALID);
> -#else
> - irq_set_noprobe(irq);
> -#endif
> - return 0;
> -}
> -
> -static struct irq_domain_ops max8997_irq_domain_ops = {
> - .map = max8997_irq_domain_map,
> -};
> -
> -int max8997_irq_init(struct max8997_dev *max8997)
> -{
> - struct irq_domain *domain;
> - int i;
> - int ret;
> - unsigned int val;
> -
> - if (!max8997->irq) {
> - dev_warn(max8997->dev, "No interrupt specified.\n");
> - return 0;
> - }
> -
> - mutex_init(&max8997->irqlock);
> -
> - /* Mask individual interrupt sources */
> - for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> - max8997->irq_masks_cur[i] = 0xff;
> - max8997->irq_masks_cache[i] = 0xff;
> -
> - if (IS_ERR_OR_NULL(max8997->regmap))
> - continue;
> - if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
> - continue;
> -
> - regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
> - }
> -
> - for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> - max8997->gpio_status[i] = (regmap_read(max8997->regmap,
> - MAX8997_REG_GPIOCNTL1 + i,
> - &val)
> - & MAX8997_GPIO_DATA_MASK) ?
> - true : false;
> - }
> -
> - domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
> - &max8997_irq_domain_ops, max8997);
> - if (!domain) {
> - dev_err(max8997->dev, "could not create irq domain\n");
> - return -ENODEV;
> - }
> - max8997->irq_domain = domain;
> -
> - ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
> - IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> - "max8997-irq", max8997);
> -
> - if (ret) {
> - dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
> - max8997->irq, ret);
> - return ret;
> - }
> -
> - if (!max8997->ono)
> - return 0;
> -
> - ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
> - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
> - IRQF_ONESHOT, "max8997-ono", max8997);
> -
> - if (ret)
> - dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
> - max8997->ono, ret);
> -
> - return 0;
> -}
> -
> -void max8997_irq_exit(struct max8997_dev *max8997)
> -{
> - if (max8997->ono)
> - free_irq(max8997->ono, max8997);
> -
> - if (max8997->irq)
> - free_irq(max8997->irq, max8997);
> -}
> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> index 782d7c9..26a360d 100644
> --- a/drivers/mfd/max8997.c
> +++ b/drivers/mfd/max8997.c
> @@ -64,6 +64,49 @@ static const struct regmap_config max8997_regmap_config = {
> .max_register = MAX8997_REG_PMIC_END,
> };
>
> +static const struct regmap_irq max8997_irqs[] = {
> + /* PMIC_INT1 interrupts */
> + { .reg_offset = 0, .mask = PMIC_INT1_PWRONR_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_PWRONF_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_PWRON1SEC_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_JIGONR_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_JIGONF_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT2_MASK, },
> + { .reg_offset = 0, .mask = PMIC_INT1_LOWBAT1_MASK, },
> + /* PMIC_INT2 interrupts */
> + { .reg_offset = 1, .mask = PMIC_INT2_JIGR_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_JIGF_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_MR_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS1OK_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS2OK_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS3OK_MASK, },
> + { .reg_offset = 1, .mask = PMIC_INT2_DVS4OK_MASK, },
> + /* PMIC_INT3 interrupts */
> + { .reg_offset = 2, .mask = PMIC_INT3_CHGINS_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_CHGRM_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_DCINOVP_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_TOPOFFR_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_CHGRSTF_MASK, },
> + { .reg_offset = 2, .mask = PMIC_INT3_MBCHGTMEXPD_MASK, },
> + /* PMIC_INT4 interrupts */
> + { .reg_offset = 3, .mask = PMIC_INT4_RTC60S_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_RTCA1_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_RTCA2_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_SMPL_INT_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_RTC1S_MASK, },
> + { .reg_offset = 3, .mask = PMIC_INT4_WTSR_MASK, },
> +};
> +
> +static const struct regmap_irq_chip max8997_irq_chip = {
> + .name = "max8997",
> + .status_base = MAX8997_REG_INT1,
> + .mask_base = MAX8997_REG_INT1MSK,
> + .mask_invert = false,
> + .num_regs = 4,
> + .irqs = max8997_irqs,
> + .num_irqs = ARRAY_SIZE(max8997_irqs),
> +};
> +
> static const struct regmap_config max8997_regmap_rtc_config = {
> .reg_bits = 8,
> .val_bits = 8,
> @@ -82,6 +125,31 @@ static const struct regmap_config max8997_regmap_muic_config = {
> .max_register = MAX8997_MUIC_REG_END,
> };
>
> +static const struct regmap_irq max8997_irqs_muic[] = {
> + /* MUIC_INT1 interrupts */
> + { .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
> + { .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
> + { .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
> + /* MUIC_INT2 interrupts */
> + { .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
> + { .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
> + /* MUIC_INT3 interrupts */
> + { .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
> +};
> +
> +static const struct regmap_irq_chip max8997_irq_chip_muic = {
> + .name = "max8997-muic",
> + .status_base = MAX8997_MUIC_REG_INT1,
> + .mask_base = MAX8997_MUIC_REG_INTMASK1,
> + .mask_invert = true,
> + .num_regs = 3,
> + .irqs = max8997_irqs_muic,
> + .num_irqs = ARRAY_SIZE(max8997_irqs_muic),
> +};
> +
> /*
> * Only the common platform data elements for max8997 are parsed here from the
> * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
> @@ -214,9 +282,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
> goto err_regmap;
> }
>
> - pm_runtime_set_active(max8997->dev);
> + ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
> + IRQF_ONESHOT | IRQF_SHARED |
> + IRQF_TRIGGER_FALLING, 0,
> + &max8997_irq_chip, &max8997->irq_data);
> + if (ret) {
> + dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> + goto err_irq;
> + }
>
> - max8997_irq_init(max8997);
> + ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
> + IRQF_ONESHOT | IRQF_SHARED |
> + IRQF_TRIGGER_FALLING, 0,
> + &max8997_irq_chip_muic,
> + &max8997->irq_data_muic);
> + if (ret) {
> + dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
> + goto err_irq_muic;
> + }
> +
> + pm_runtime_set_active(max8997->dev);
>
> ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
> ARRAY_SIZE(max8997_devs),
> @@ -238,6 +323,10 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>
> err_mfd:
> mfd_remove_devices(max8997->dev);
> +err_irq_muic:
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> +err_irq:
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> err_regmap:
> i2c_unregister_device(max8997->muic);
> err_i2c_muic:
> @@ -252,6 +341,10 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
> struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>
> mfd_remove_devices(max8997->dev);
> +
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
> + regmap_del_irq_chip(max8997->irq, max8997->irq_data);
> +
> i2c_unregister_device(max8997->muic);
> i2c_unregister_device(max8997->haptic);
> i2c_unregister_device(max8997->rtc);
> @@ -468,8 +561,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);
> + }
> +
> return 0;
> }
>
> @@ -478,9 +574,12 @@ static int max8997_resume(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, 0);
> - return max8997_irq_resume(max8997);
> + if (device_may_wakeup(dev)) {
> + disable_irq_wake(max8997->irq);
> + enable_irq(max8997->irq);
> + }
> +
> + return 0;
> }
>
> static const struct dev_pm_ops max8997_pm = {
> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> index b866f7d5..22769ea 100644
> --- a/drivers/rtc/rtc-max8997.c
> +++ b/drivers/rtc/rtc-max8997.c
> @@ -494,7 +494,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
> return ret;
> }
>
> - virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1);
> + virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
> if (!virq) {
> dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
> ret = -ENXIO;
> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
> index ea80ef8..2817fa6 100644
> --- a/include/linux/mfd/max8997-private.h
> +++ b/include/linux/mfd/max8997-private.h
> @@ -333,6 +333,48 @@ enum max8997_irq_source {
> MAX8997_IRQ_GROUP_NR,
> };
>
> +#define PMIC_INT1_PWRONR_MASK (0x1 << 0)
> +#define PMIC_INT1_PWRONF_MASK (0x1 << 1)
> +#define PMIC_INT1_PWRON1SEC_MASK (0x1 << 3)
> +#define PMIC_INT1_JIGONR_MASK (0x1 << 4)
> +#define PMIC_INT1_JIGONF_MASK (0x1 << 5)
> +#define PMIC_INT1_LOWBAT2_MASK (0x1 << 6)
> +#define PMIC_INT1_LOWBAT1_MASK (0x1 << 7)
> +
> +#define PMIC_INT2_JIGR_MASK (0x1 << 0)
> +#define PMIC_INT2_JIGF_MASK (0x1 << 1)
> +#define PMIC_INT2_MR_MASK (0x1 << 2)
> +#define PMIC_INT2_DVS1OK_MASK (0x1 << 3)
> +#define PMIC_INT2_DVS2OK_MASK (0x1 << 4)
> +#define PMIC_INT2_DVS3OK_MASK (0x1 << 5)
> +#define PMIC_INT2_DVS4OK_MASK (0x1 << 6)
> +
> +#define PMIC_INT3_CHGINS_MASK (0x1 << 0)
> +#define PMIC_INT3_CHGRM_MASK (0x1 << 1)
> +#define PMIC_INT3_DCINOVP_MASK (0x1 << 2)
> +#define PMIC_INT3_TOPOFFR_MASK (0x1 << 3)
> +#define PMIC_INT3_CHGRSTF_MASK (0x1 << 5)
> +#define PMIC_INT3_MBCHGTMEXPD_MASK (0x1 << 7)
> +
> +#define PMIC_INT4_RTC60S_MASK (0x1 << 0)
> +#define PMIC_INT4_RTCA1_MASK (0x1 << 1)
> +#define PMIC_INT4_RTCA2_MASK (0x1 << 2)
> +#define PMIC_INT4_SMPL_INT_MASK (0x1 << 3)
> +#define PMIC_INT4_RTC1S_MASK (0x1 << 4)
> +#define PMIC_INT4_WTSR_MASK (0x1 << 5)
> +
> +#define MUIC_INT1_ADC_MASK (0x1 << 0)
> +#define MUIC_INT1_ADCLOW_MASK (0x1 << 1)
> +#define MUIC_INT1_ADCERROR_MASK (0x1 << 2)
> +
> +#define MUIC_INT2_CHGTYP_MASK (0x1 << 0)
> +#define MUIC_INT2_CHGDETRUN_MASK (0x1 << 1)
> +#define MUIC_INT2_DCDTMR_MASK (0x1 << 2)
> +#define MUIC_INT2_DBCHG_MASK (0x1 << 3)
> +#define MUIC_INT2_VBVOLT_MASK (0x1 << 4)
> +
> +#define MUIC_INT3_OVP_MASK (0x1 << 2)
> +
> enum max8997_irq {
> MAX8997_PMICIRQ_PWRONR,
> MAX8997_PMICIRQ_PWRONF,
> @@ -364,19 +406,23 @@ enum max8997_irq {
> MAX8997_PMICIRQ_RTC1S,
> MAX8997_PMICIRQ_WTSR,
>
> - MAX8997_MUICIRQ_ADCError,
> - MAX8997_MUICIRQ_ADCLow,
> + MAX8997_PMICIRQ_NR,
> +};
> +
> +enum max8997_irq_muic {
> MAX8997_MUICIRQ_ADC,
> + MAX8997_MUICIRQ_ADCLOW,
> + MAX8997_MUICIRQ_ADCERROR,
>
> - MAX8997_MUICIRQ_VBVolt,
> - MAX8997_MUICIRQ_DBChg,
> - MAX8997_MUICIRQ_DCDTmr,
> - MAX8997_MUICIRQ_ChgDetRun,
> - MAX8997_MUICIRQ_ChgTyp,
> + MAX8997_MUICIRQ_CHGTYP,
> + MAX8997_MUICIRQ_CHGDETRUN,
> + MAX8997_MUICIRQ_DCDTMR,
> + MAX8997_MUICIRQ_DBCHG,
> + MAX8997_MUICIRQ_VBVOLT,
ditto.
I don't understand why do you modify interrnut name/macro.
>
> MAX8997_MUICIRQ_OVP,
>
> - MAX8997_IRQ_NR,
> + MAX8997_MUCIRQ_NR,
ditto.
> };
>
> #define MAX8997_NUM_GPIO 12
> @@ -397,9 +443,10 @@ struct max8997_dev {
> struct regmap *regmap_haptic;
> struct regmap *regmap_muic;
>
> + struct regmap_irq_chip_data *irq_data;
> + struct regmap_irq_chip_data *irq_data_muic;
> int irq;
> int ono;
> - struct irq_domain *irq_domain;
> struct mutex irqlock;
> int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
> int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
>
Thanks,
Chanwoo Choi
^ permalink raw reply
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