Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2010-07-19 Thread Michael Trimarchi

Hi all

Janakiram Sistla wrote:

On Mon, Jul 19, 2010 at 10:46 AM, Michael Trimarchi 
mich...@panicking.kicks-ass.org wrote:

Janakiram Sistla wrote:

 drivers/mfd/Kconfig  |   21 ++
 drivers/mfd/Makefile |3 +-
 drivers/mfd/twl4030-madc.c   |  548
++
 include/linux/i2c/twl4030-madc.h |  126 +
 4 files changed, 697 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mfd/twl4030-madc.c
 create mode 100644 include/linux/i2c/twl4030-madc.h


We have just tried to adopt this driver to our custom OMAP3 board, but
were unable to get any interrupts.
Any ideas on what is missing? We've checked whole TRM and found
nothing wrong yet :(


we tried the same driver for Omap zoom platform ,I too dont see any
interrupts from this driver.I also observe that duing bluetooth file
transfer i see the below crash from twl4030-madc driver.

Once i disable the madc driver in kernel configuration my Bluetooth
works fine,while Bluetooth has nothing to do with i2c or madc driver.A
similar crash is also observed during GFX operation

Regards,
Ram.

here is the log:
i2c_omap i2c_omap.1: controller timed out waiting for start condition to
finish
twl: i2c_write failed to transfer all messages
Unable to handle kernel NULL pointer dereference at virtual address
0044
pgd = c0004000
[0044] *pgd=
Internal error: Oops: 17 [#1] PREEMPT
last sysfs file: /sys/devices/platform/kim/firmware/kim/loading
Modules linked in: bt_drv st_drv
CPU: 0Not tainted  (2.6.32-14922-g86eec44 #1)
PC is at dev_driver_string+0x0/0x38
LR is at twl4030_madc_write+0x2c/0x4c
pc : [c01f2bc0]lr : [c01fede0]psr: a013
sp : cf02bf08  ip : 738f  fp : 
r10: cf002cc8  r9 : c038a839  r8 : 
r7 : cf02bf3c  r6 : c04edff8  r5 : 0007  r4 : cf227a00
r3 : 0007  r2 : 02070002  r1 : 0007  r0 : 
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387d  Table: 8d23c019  DAC: 0017
Process events/0 (pid: 5, stack limit = 0xcf02a2e8)
Stack: (0xcf02bf08 to 0xcf02c000)
bf00:   0006 0002 c04edff8 c01fef6c cf179680
cf179680
bf20: cf02a000 cf002cc0 c028a5a8  cf002cc8 c028a5dc 
0200
bf40: cf020001  cf020d40 0017 cf0213c0 c007f1dc 
cd277e40
bf60: cf02bf94 c036e58c cd0bac9c cf020ed4 6013 cf002cc0 cf002cbc
cf02a000
bf80: cf002cc0 c01dcc00 cf002cc0  cf179684 c0076ff4 cf02bfcc

bfa0: cf020d40 c007a660 cf02bfa8 cf02bfa8 cf023f60 cf02bfd4 cf023f60
cf002cc0
bfc0: c0076e8c   c007a334   cf02bfd8
cf02bfd8
bfe0:      c0035f80 

[c01f2bc0] (dev_driver_string+0x0/0x38) from [c01fede0]
(twl4030_madc_write+
0x2c/0x4c)
[c01fede0] (twl4030_madc_write+0x2c/0x4c) from [c01fef6c]
(twl4030_madc_conv
ersion+0x74/0x288)
[c01fef6c] (twl4030_madc_conversion+0x74/0x288) from [c028a5dc]
(twl4030_bk_
bci_battery_work+0x34/0x60)
[c028a5dc] (twl4030_bk_bci_battery_work+0x34/0x60) from [c0076ff4]
(worker_t
hread+0x168/0x214)
[c0076ff4] (worker_thread+0x168/0x214) from [c007a334]
(kthread+0x7c/0x84)
[c007a334] (kthread+0x7c/0x84) from [c0035f80]
(kernel_thread_exit+0x0/0x8)
Code: c04edd3c c04eddcc c042bef5 c040d709 (e5903044)
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 2d2aa87..e12ac1a 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -478,6 +478,7 @@ static int __init twl4030_madc_probe(struct
platform_device
  madc-imr = (pdata-irq_line == 1) ? TWL4030_MADC_IMR1 :
TWL4030_MADC_IM
  madc-isr = (pdata-irq_line == 1) ? TWL4030_MADC_ISR1 :
TWL4030_MADC_IS
+   madc-dev = pdev-dev;

  ret = misc_register(twl4030_madc_device);
  if (ret) {

This is the reason of the crash

Michael Trimarchi






I think its fixed already.. ..



I'm testing in overo and I have notice varius issue:

+#if 0
   if (dev-rev = OMAP_I2C_REV_ON_3430) {
   while (!(stat  OMAP_I2C_STAT_XU
   if (stat  (OMAP_I2C_STA
@@ -826,7 +826,7 @@ complete:
   stat = omap_i2c_read_reg
   }
   }
-
+#endif

I need to comment out this code, because it loop and it doesn't have an exit 
condition. This couse
the kernel to stuck, but after comment out this I have every 5sec/10 seconds 
some error on i2c bus
during write

Michael

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2010-01-25 Thread Janakiram Sistla
   drivers/mfd/Kconfig  |   21 ++
   drivers/mfd/Makefile |3 +-
   drivers/mfd/twl4030-madc.c   |  548 
  ++
   include/linux/i2c/twl4030-madc.h |  126 +
   4 files changed, 697 insertions(+), 1 deletions(-)
   create mode 100644 drivers/mfd/twl4030-madc.c
   create mode 100644 include/linux/i2c/twl4030-madc.h
 

 We have just tried to adopt this driver to our custom OMAP3 board, but
 were unable to get any interrupts.
 Any ideas on what is missing? We've checked whole TRM and found
 nothing wrong yet :(

we tried the same driver for Omap zoom platform ,I too dont see any
interrupts from this driver.I also observe that duing bluetooth file
transfer i see the below crash from twl4030-madc driver.

Once i disable the madc driver in kernel configuration my Bluetooth
works fine,while Bluetooth has nothing to do with i2c or madc driver.A
similar crash is also observed during GFX operation

Regards,
Ram.

here is the log:
i2c_omap i2c_omap.1: controller timed out waiting for start condition to finish
twl: i2c_write failed to transfer all messages
Unable to handle kernel NULL pointer dereference at virtual address 0044
pgd = c0004000
[0044] *pgd=
Internal error: Oops: 17 [#1] PREEMPT
last sysfs file: /sys/devices/platform/kim/firmware/kim/loading
Modules linked in: bt_drv st_drv
CPU: 0Not tainted  (2.6.32-14922-g86eec44 #1)
PC is at dev_driver_string+0x0/0x38
LR is at twl4030_madc_write+0x2c/0x4c
pc : [c01f2bc0]lr : [c01fede0]psr: a013
sp : cf02bf08  ip : 738f  fp : 
r10: cf002cc8  r9 : c038a839  r8 : 
r7 : cf02bf3c  r6 : c04edff8  r5 : 0007  r4 : cf227a00
r3 : 0007  r2 : 02070002  r1 : 0007  r0 : 
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387d  Table: 8d23c019  DAC: 0017
Process events/0 (pid: 5, stack limit = 0xcf02a2e8)
Stack: (0xcf02bf08 to 0xcf02c000)
bf00:   0006 0002 c04edff8 c01fef6c cf179680 cf179680
bf20: cf02a000 cf002cc0 c028a5a8  cf002cc8 c028a5dc  0200
bf40: cf020001  cf020d40 0017 cf0213c0 c007f1dc  cd277e40
bf60: cf02bf94 c036e58c cd0bac9c cf020ed4 6013 cf002cc0 cf002cbc cf02a000
bf80: cf002cc0 c01dcc00 cf002cc0  cf179684 c0076ff4 cf02bfcc 
bfa0: cf020d40 c007a660 cf02bfa8 cf02bfa8 cf023f60 cf02bfd4 cf023f60 cf002cc0
bfc0: c0076e8c   c007a334   cf02bfd8 cf02bfd8
bfe0:      c0035f80  
[c01f2bc0] (dev_driver_string+0x0/0x38) from [c01fede0] (twl4030_madc_write+
0x2c/0x4c)
[c01fede0] (twl4030_madc_write+0x2c/0x4c) from [c01fef6c] (twl4030_madc_conv
ersion+0x74/0x288)
[c01fef6c] (twl4030_madc_conversion+0x74/0x288) from [c028a5dc] (twl4030_bk_
bci_battery_work+0x34/0x60)
[c028a5dc] (twl4030_bk_bci_battery_work+0x34/0x60) from [c0076ff4] (worker_t
hread+0x168/0x214)
[c0076ff4] (worker_thread+0x168/0x214) from [c007a334] (kthread+0x7c/0x84)
[c007a334] (kthread+0x7c/0x84) from [c0035f80] (kernel_thread_exit+0x0/0x8)
Code: c04edd3c c04eddcc c042bef5 c040d709 (e5903044)
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2010-01-20 Thread Sergey Lapin
Hi, all!

On Wed, Nov 25, 2009 at 1:47 PM, Amit Kucheria
amit.kuche...@verdurent.com wrote:
 From: Mikko Ylinen mikko.k.yli...@nokia.com

 This ADC allows monitoring of analog signals such as battery levels,
 temperatures, etc.

 Several people have contributed to this driver on the linux-omap list.

 Signed-off-by: Amit Kucheria amit.kuche...@verdurent.com
 ---
  drivers/mfd/Kconfig              |   21 ++
  drivers/mfd/Makefile             |    3 +-
  drivers/mfd/twl4030-madc.c       |  548 
 ++
  include/linux/i2c/twl4030-madc.h |  126 +
  4 files changed, 697 insertions(+), 1 deletions(-)
  create mode 100644 drivers/mfd/twl4030-madc.c
  create mode 100644 include/linux/i2c/twl4030-madc.h


We have just tried to adopt this driver to our custom OMAP3 board, but
were unable to get any interrupts.
Any ideas on what is missing? We've checked whole TRM and found
nothing wrong yet :(

Thanks a lot.
S.
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2009-12-01 Thread Samuel Ortiz
Hi Amit,

On Mon, Nov 30, 2009 at 03:58:39PM +0200, Amit Kucheria wrote:
  + * drivers/i2c/chips/twl4030-madc.c
  drivers/mfd/twl4030-madc.c
  By the way, have you considered moving this one to drivers/hwmon ?
 
 I haven't. I moved it from i2c/chips/ to the most obvious place I
 could think of - drivers/mfd. But wasn't this the point of mfd - that
 various subcomponents drivers could live there instead of being
 scattered across the driver tree?
Not really. Most of the drivers in mfd/ are for the core parts of the
corresponding chip (chip init and setup, subdevices definitions and
declarations, API export, IRQ setups, etc...).
I can take this driver for now, but converting it to a proper hwmon driver
would make sense because that's what it is after all.


  +static struct twl4030_madc_data *the_madc;
  I dont particularly enjoy that. All of the twl4030 drivers have this bad 
  habit
  of assuming they will be alone on a platform. Although it's certainly very
  likely, I still think having this kind of design is not so nice.
 
 I agree. Unfortunately, twl4030-core.c is unable to handle multiple
 devices currently. See note from line 779 in twl4030-core below:
Oh, I know about that. That's also something the code maintainers (Nokia I
assume) of that driver should start looking at.

 
  +static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
  +{
  +     int ret;
  +     u8 val;
  +
  +     ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, val, reg);
  +     if (ret) {
  +             dev_dbg(madc-dev, unable to read register 0x%X\n, reg);
  +             return ret;
  +     }
  +
  +     return val;
  +}
  FWIW, you're not checking the return value on any of the madc_read calls
  below.
 
 I've changed the dev_dbg above to dev_err now. If we see those error
 messages, then anything that follows from the higher level functions
 is overhead IMHO.
I usually expect code to check for function return values :) And also exit if
a IO fails.


 The higher level functions in this case aren't adding any more useful
 information to the error. E.g. I could check the return value again in
 twl4030_madc_channel_raw_read() below. But if would simply repeat the
 same error message we show in twl4030_madc_read().
The error message matter less than the code flow itself. For example if
twl4030_madc_start_conversion() fails because of your i2c failing, you will
still busy loop (Yes, only for 5ms, but still) waiting for a register bit to
toggle.
 
 Hmm, perhaps twl4030_madc_read should return void?
That would be weird, imho. In fact, your write routine returning void is
already weird.


  +static void twl4030_madc_work(struct work_struct *ws)
  +{
  +     const struct twl4030_madc_conversion_method *method;
  +     struct twl4030_madc_data *madc;
  +     struct twl4030_madc_request *r;
  +     int len, i;
  +
  +     madc = container_of(ws, struct twl4030_madc_data, ws);
  +     mutex_lock(madc-lock);
  +
  +     for (i = 0; i  TWL4030_MADC_NUM_METHODS; i++) {
  +
  +             r = madc-requests[i];
  +
  +             /* No pending results for this method, move to next one */
  +             if (!r-result_pending)
  +                     continue;
  +
  +             method = twl4030_conversion_methods[r-method];
  +
  +             /* Read results */
  +             len = twl4030_madc_read_channels(madc, method-rbase,
  +                                              r-channels, r-rbuf);
  +
  +             /* Return results to caller */
  +             if (r-func_cb != NULL) {
  +                     r-func_cb(len, r-channels, r-rbuf);
  +                     r-func_cb = NULL;
  +             }
  +
  +             /* Free request */
  +             r-result_pending = 0;
  +             r-active         = 0;
  +     }
  +
  +     mutex_unlock(madc-lock);
  +}
  I think you may want to consider using a threaded irq here, see
  request_threaded_irq().
 
 I am working on moving the entire twl* driver set to use threaded irqs
 on the side. Will you consider merging this code with the work_struct
 since it is known to work while I work on the conversion?
That's fine, yes. Thanks in advance for the conversion.

 
  +static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on);
  +int twl4030_madc_conversion(struct twl4030_madc_request *req)
  +{
  +     const struct twl4030_madc_conversion_method *method;
  +     u8 ch_msb, ch_lsb;
  +     int ret;
  +
  +     if (unlikely(!req))
  +             return -EINVAL;
  +
  +     mutex_lock(the_madc-lock);
  +
  +     twl4030_madc_set_power(the_madc, 1);
  +
  +     /* Do we have a conversion request ongoing */
  +     if (the_madc-requests[req-method].active) {
  +             ret = -EBUSY;
  +             goto out;
  +     }
  +
  +     ch_msb = (req-channels  8)  0xff;
  +     ch_lsb = req-channels  0xff;
  +
  +     method = twl4030_conversion_methods[req-method];
  +
  +     /* Select channels to be converted */
  +     twl4030_madc_write(the_madc, method-sel 

Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2009-11-30 Thread Amit Kucheria
Hi Samuel,

On Fri, Nov 27, 2009 at 9:36 PM, Samuel Ortiz sa...@linux.intel.com wrote:
 Hi Amit,

 On Wed, Nov 25, 2009 at 12:47:51PM +0200, Amit Kucheria wrote:
 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
 index af0fc90..df1897b 100644
 --- a/drivers/mfd/Makefile
 +++ b/drivers/mfd/Makefile
 @@ -25,8 +25,9 @@ obj-$(CONFIG_TPS65010)              += tps65010.o
  obj-$(CONFIG_MENELAUS)               += menelaus.o

  obj-$(CONFIG_TWL4030_CORE)   += twl4030-core.o twl4030-irq.o
 -obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 +obj-$(CONFIG_TWL4030_POWER)  += twl4030-power.o
  obj-$(CONFIG_TWL4030_CODEC)  += twl4030-codec.o
 +obj-$(CONFIG_TWL4030_MADC)   += twl4030-madc.o

  obj-$(CONFIG_MFD_MC13783)    += mc13783-core.o

 diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
 new file mode 100644
 index 000..90ce99a
 --- /dev/null
 +++ b/drivers/mfd/twl4030-madc.c
 @@ -0,0 +1,548 @@
 +/*
 + * drivers/i2c/chips/twl4030-madc.c
 drivers/mfd/twl4030-madc.c
 By the way, have you considered moving this one to drivers/hwmon ?

I haven't. I moved it from i2c/chips/ to the most obvious place I
could think of - drivers/mfd. But wasn't this the point of mfd - that
various subcomponents drivers could live there instead of being
scattered across the driver tree?

Adding Jean to CC, if he would consider taking this driver in drivers/hwmon.

 + * TWL4030 MADC module driver
 + *
 + * Copyright (C) 2008 Nokia Corporation
 + * Mikko Ylinen mikko.k.yli...@nokia.com
 + *
 + * 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.
 + *
 + * 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., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include linux/init.h
 +#include linux/interrupt.h
 +#include linux/kernel.h
 +#include linux/types.h
 +#include linux/module.h
 +#include linux/delay.h
 +#include linux/fs.h
 +#include linux/platform_device.h
 +#include linux/miscdevice.h
 +#include linux/i2c/twl4030.h
 +#include linux/i2c/twl4030-madc.h
 +
 +#include asm/uaccess.h
 +
 +#define TWL4030_MADC_PFX     twl4030-madc: 
 +
 +struct twl4030_madc_data {
 +     struct device           *dev;
 +     struct mutex            lock;
 +     struct work_struct      ws;
 +     struct twl4030_madc_request     requests[TWL4030_MADC_NUM_METHODS];
 Typically, I'd expect to have a list (limited in length) of requests here, but
 I guess you're happy with that array .



 +     int imr;
 +     int isr;
 +};
 +
 +static struct twl4030_madc_data *the_madc;
 I dont particularly enjoy that. All of the twl4030 drivers have this bad habit
 of assuming they will be alone on a platform. Although it's certainly very
 likely, I still think having this kind of design is not so nice.

I agree. Unfortunately, twl4030-core.c is unable to handle multiple
devices currently. See note from line 779 in twl4030-core below:

/* NOTE:  this driver only handles a single twl4030/tps659x0 chip */
static int
twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)

 +static int twl4030_madc_set_current_generator(struct twl4030_madc_data 
 *madc, int chan, int on);
 +
 +static
 +const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
 +     [TWL4030_MADC_RT] = {
 +             .sel    = TWL4030_MADC_RTSELECT_LSB,
 +             .avg    = TWL4030_MADC_RTAVERAGE_LSB,
 +             .rbase  = TWL4030_MADC_RTCH0_LSB,
 +     },
 +     [TWL4030_MADC_SW1] = {
 +             .sel    = TWL4030_MADC_SW1SELECT_LSB,
 +             .avg    = TWL4030_MADC_SW1AVERAGE_LSB,
 +             .rbase  = TWL4030_MADC_GPCH0_LSB,
 +             .ctrl   = TWL4030_MADC_CTRL_SW1,
 +     },
 +     [TWL4030_MADC_SW2] = {
 +             .sel    = TWL4030_MADC_SW2SELECT_LSB,
 +             .avg    = TWL4030_MADC_SW2AVERAGE_LSB,
 +             .rbase  = TWL4030_MADC_GPCH0_LSB,
 +             .ctrl   = TWL4030_MADC_CTRL_SW2,
 +     },
 +};
 +
 +static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
 +{
 +     int ret;
 +     u8 val;
 +
 +     ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, val, reg);
 +     if (ret) {
 +             dev_dbg(madc-dev, unable to read register 0x%X\n, reg);
 +             return ret;
 +     }
 +
 +     return val;
 +}
 FWIW, you're not checking the return value on any of the madc_read calls
 below.

I've changed the dev_dbg above to dev_err now. If we see those error
messages, then anything that follows from the higher level functions
is overhead IMHO.
The higher level functions in 

Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2009-11-30 Thread Jean Delvare
On Mon, 30 Nov 2009 15:58:39 +0200, Amit Kucheria wrote:
 On Fri, Nov 27, 2009 at 9:36 PM, Samuel Ortiz sa...@linux.intel.com wrote:
  By the way, have you considered moving this one to drivers/hwmon ?
 
 I haven't. I moved it from i2c/chips/ to the most obvious place I
 could think of - drivers/mfd. But wasn't this the point of mfd - that
 various subcomponents drivers could live there instead of being
 scattered across the driver tree?
 
 Adding Jean to CC, if he would consider taking this driver in drivers/hwmon..

In its current form, no. This driver doesn't implement the sysfs
interface described in Documentation/hwmon/sysfs-interface. It doesn't
even register a hwmon class device. So it doesn't belong in
drivers/hwmon.

-- 
Jean Delvare
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mfd: twl4030: Driver for twl4030 madc module

2009-11-27 Thread Samuel Ortiz
Hi Amit,

On Wed, Nov 25, 2009 at 12:47:51PM +0200, Amit Kucheria wrote:
 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
 index af0fc90..df1897b 100644
 --- a/drivers/mfd/Makefile
 +++ b/drivers/mfd/Makefile
 @@ -25,8 +25,9 @@ obj-$(CONFIG_TPS65010)  += tps65010.o
  obj-$(CONFIG_MENELAUS)   += menelaus.o
  
  obj-$(CONFIG_TWL4030_CORE)   += twl4030-core.o twl4030-irq.o
 -obj-$(CONFIG_TWL4030_POWER)+= twl4030-power.o
 +obj-$(CONFIG_TWL4030_POWER)  += twl4030-power.o
  obj-$(CONFIG_TWL4030_CODEC)  += twl4030-codec.o
 +obj-$(CONFIG_TWL4030_MADC)   += twl4030-madc.o
  
  obj-$(CONFIG_MFD_MC13783)+= mc13783-core.o
  
 diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
 new file mode 100644
 index 000..90ce99a
 --- /dev/null
 +++ b/drivers/mfd/twl4030-madc.c
 @@ -0,0 +1,548 @@
 +/*
 + * drivers/i2c/chips/twl4030-madc.c
drivers/mfd/twl4030-madc.c
By the way, have you considered moving this one to drivers/hwmon ?


 + * TWL4030 MADC module driver
 + *
 + * Copyright (C) 2008 Nokia Corporation
 + * Mikko Ylinen mikko.k.yli...@nokia.com
 + *
 + * 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.
 + *
 + * 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., 51 Franklin St, Fifth Floor, Boston, MA
 + * 02110-1301 USA
 + *
 + */
 +
 +#include linux/init.h
 +#include linux/interrupt.h
 +#include linux/kernel.h
 +#include linux/types.h
 +#include linux/module.h
 +#include linux/delay.h
 +#include linux/fs.h
 +#include linux/platform_device.h
 +#include linux/miscdevice.h
 +#include linux/i2c/twl4030.h
 +#include linux/i2c/twl4030-madc.h
 +
 +#include asm/uaccess.h
 +
 +#define TWL4030_MADC_PFX twl4030-madc: 
 +
 +struct twl4030_madc_data {
 + struct device   *dev;
 + struct mutexlock;
 + struct work_struct  ws;
 + struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
Typically, I'd expect to have a list (limited in length) of requests here, but
I guess you're happy with that array .



 + int imr;
 + int isr;
 +};
 +
 +static struct twl4030_madc_data *the_madc;
I dont particularly enjoy that. All of the twl4030 drivers have this bad habit
of assuming they will be alone on a platform. Although it's certainly very
likely, I still think having this kind of design is not so nice.


 +static int twl4030_madc_set_current_generator(struct twl4030_madc_data 
 *madc, int chan, int on);
 +
 +static
 +const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
 + [TWL4030_MADC_RT] = {
 + .sel= TWL4030_MADC_RTSELECT_LSB,
 + .avg= TWL4030_MADC_RTAVERAGE_LSB,
 + .rbase  = TWL4030_MADC_RTCH0_LSB,
 + },
 + [TWL4030_MADC_SW1] = {
 + .sel= TWL4030_MADC_SW1SELECT_LSB,
 + .avg= TWL4030_MADC_SW1AVERAGE_LSB,
 + .rbase  = TWL4030_MADC_GPCH0_LSB,
 + .ctrl   = TWL4030_MADC_CTRL_SW1,
 + },
 + [TWL4030_MADC_SW2] = {
 + .sel= TWL4030_MADC_SW2SELECT_LSB,
 + .avg= TWL4030_MADC_SW2AVERAGE_LSB,
 + .rbase  = TWL4030_MADC_GPCH0_LSB,
 + .ctrl   = TWL4030_MADC_CTRL_SW2,
 + },
 +};
 +
 +static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
 +{
 + int ret;
 + u8 val;
 +
 + ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, val, reg);
 + if (ret) {
 + dev_dbg(madc-dev, unable to read register 0x%X\n, reg);
 + return ret;
 + }
 +
 + return val;
 +}
FWIW, you're not checking the return value on any of the madc_read calls
below.


 +static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 
 val)
 +{
 + int ret;
 +
 + ret = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
 + if (ret)
 + dev_err(madc-dev, unable to write register 0x%X\n, reg);
 +}
 +
 +static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 
 reg)
 +{
 + u8 msb, lsb;
 +
 + /* For each ADC channel, we have MSB and LSB register pair. MSB address
 +  * is always LSB address+1. reg parameter is the addr of LSB register */
 + msb = twl4030_madc_read(madc, reg + 1);
 + lsb = twl4030_madc_read(madc, reg);
 +
 + return (int)(((msb  8) | lsb)  6);
 +}
 +
 +static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
 + u8 reg_base, u16 channels, int *buf)
 +{
 + int count = 0;
 + u8 reg, i;
 +
 + if (unlikely(!buf))