add drivers/mfd/twl4030-core.c
Subsystems (2)
PATCH 1/1 add drivers/mfd/twl4030-core.c
From: David Brownell <[email protected]>
This patch adds the core of the TWL4030 driver, which supports chips including the TPS65950. These chips are multi-function; see
http://focus.ti.com/docs/prod/folders/print/tps65950.html
Public specs are in the works. For now, the block diagram on the second page of the datasheet is fairly informative.
There are some known issues with this core code. Most notably, the IRQ dispatching needs simplification (to use more of genirq), generalization (integrating support for secondary IRQ dispatch as well as primary, and removing the build dependency on OMAP), and then probably updating to leverage threaded IRQ support (expected to arrive in mainline "soon").
Once the core is in mainline, drivers for other parts of this chip can follow its lead and start swimming upstream too.
--- drivers/mfd/Kconfig | 14 drivers/mfd/Makefile | 2 drivers/mfd/twl4030-core.c | 1257 ++++++++++++++++++++++++++++++++++++++++++ include/linux/i2c/twl4030.h | 339 +++++++++++ 4 files changed, 1612 insertions(+)
drivers/mfd/Kconfig +14 -0
@@ -50,6 +50,20 @@ config HTC_PASIC3 HTC Magician devices, respectively. Actual functionality is handled by the leds-pasic3 and ds1wm drivers. +config TWL4030_CORE + bool "Texas Instruments TWL4030/TPS659x0 Support" + depends on I2C=y && GENERIC_HARDIRQS && (ARCH_OMAP2 || ARCH_OMAP3) + help + Say yes here if you have TWL4030 family chip on your board. + This core driver provides register access and IRQ handling + facilities, and registers devices for the various functions + so that function-specific drivers can bind to them. + + These multi-function chips are found on many OMAP2 and OMAP3 + boards, providing power management, RTC, GPIO, keypad, a + high speed USB OTG transceiver, an audio codec (on most + versions) and many other features. + config MFD_TMIO bool default n
drivers/mfd/Makefile +2 -0
@@ -12,6 +12,8 @@ obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o +obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o + obj-$(CONFIG_MFD_CORE) += mfd-core.o obj-$(CONFIG_MCP) += mcp-core.o
drivers/mfd/twl4030-core.c new file +1257 -0
1,257 lines not on this page · raw message
include/linux/i2c/twl4030.h new file +339 -0
339 lines not on this page · raw message
Samuel Ortiz
AppliedHi Dave,
Quoted 17 lines · David Brownell
From: David Brownell <[email protected]>
This patch adds the core of the TWL4030 driver, which supports chips including the TPS65950. These chips are multi-function; see
http://focus.ti.com/docs/prod/folders/print/tps65950.html
Public specs are in the works. For now, the block diagram on the second page of the datasheet is fairly informative.
There are some known issues with this core code. Most notably, the IRQ dispatching needs simplification (to use more of genirq), generalization (integrating support for secondary IRQ dispatch as well as primary, and removing the build dependency on OMAP), and then probably updating to leverage threaded IRQ support (expected to arrive in mainline "soon").
Quoted 4 lines
Once the core is in mainline, drivers for other parts of this chip can follow its lead and start swimming upstream too.
Signed-off-by David Brownell <[email protected]>
Thanks, applied to my mfd tree.
drivers/mfd/twl4030-core.c line 60
Quoted 2 lines
drivers/mfd/twl4030-core.c new file +2
-0+#if defined(CONFIG_TWL4030_BCI_BATTERY ) || \ + defined(CONFIG_TWL4030_BCI_BATTERY_MODUEL )
minor typo, you probably meant: CONFIG_TWL4030_BCI_BATTERY_MODULE
Cheers,
Samuel.
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/
Quoted 1 line · Samuel Ortiz
Thanks, applied to my mfd tree.
Great!
Quoted 4 lines
Quoted 2 lines
+#if
defined(CONFIG_TWL4030_BCI_BATTERY)|| \
+ defined(CONFIG_TWL4030_BCI_BATTERY_MODUEL)minor typo, you probably meant:
CONFIG_TWL4030_BCI_BATTERY_MODULE
Yes, good catch. You'll tweak?
Appended is that simple IRQ cleanup I mentioned.
(Get a load of the diffstat!)
There's more substantial IRQ stuff on the way, but it won't be ready before the 2.6.28 merges start.
- Dave
================== CUT HERE
From: David Brownell <[email protected]>
twl4030-core irq simplification
Simplify twl4030 IRQ handling by removing a needless custom flow handler. The top level IRQs, from the PIH, are well suited for handle_simple_irq() ... they can't be acked or masked.
Switching resolves some issues with how IRQs were dispatched. Notably, abuse of desc->status, IRQ accounting, and handling of various faults.
In short, use standard genirq code.
Drivers that request_irq() to the PIH will need to pay more attention to things like setting IRQF_DISABLED (since it's no longer ignored), and making I2C calls from handlers (you'll need a lockdep workaround).
--- drivers/mfd/twl4030-core.c | 68 +-------------------------------------------- 1 file changed, 2 insertions(+), 66 deletions(-)
drivers/mfd/twl4030-core.c +2 -66
@@ -535,68 +535,6 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8);/*----------------------------------------------------------------------*/ -/* -* do_twl4030_module_irq() is the desc->handle method for each of the twl4030 -* module interrupts that doesn't chain to another irq_chip (GPIO, power, etc). -* It executes in kernel thread context. On entry, cpu interrupts are disabled. -*/ -static void do_twl4030_module_irq (unsigned int irq,irq_desc_t *desc) -{ -struct irqaction *action; -const unsigned int cpu =smp_processor_id (); - -/* -* Earlier this was desc->triggered = 1; -*/ - desc->status |=IRQ_LEVEL ; - -/* -* The desc->handle method would normally call the desc->chip->ack -* method here, but we won't bother since our ack method is NULL. -*/ - -if (!desc->depth) { -kstat_cpu (cpu).irqs[irq]++; - - action = desc->action; -if (action) { -int ret; -int status =0 ; -int retval =0 ; - -local_irq_enable (); - -do { -/* Call the ISR with cpu interrupts enabled */ - ret = action->handler (irq, action->dev_id); -if (ret ==IRQ_HANDLED ) - status |= action->flags; - retval |= ret; - action = action->next; - }while (action); - -if (status &IRQF_SAMPLE_RANDOM ) -add_interrupt_randomness (irq); - -local_irq_disable (); - -if (retval !=IRQ_HANDLED ) -printk (KERN_ERR "ISR for TWL4030 module" -" irq %d can't handle interrupt\n" , - irq); - -/* -* Here is where we should call the unmask method, but -* again we won't bother since it is NULL. -*/ - }else -printk (KERN_CRIT "TWL4030 module irq %d has no ISR" -" but can't be masked!\n" , irq); - }else -printk (KERN_CRIT "TWL4030 module irq %d is disabled but can't" -" be masked!\n" , irq); -} -static unsigned twl4030_irq_base;static struct completion irq_event;
@@ -611,7 +549,6 @@ static int twl4030_irq_thread(void *data)static unsigned i2c_errors;const static unsigned max_i2c_errors =100 ; -daemonize ("twl4030-irq" ); current->flags |=PF_NOFREEZE ;while (!kthread_should_stop ()) {
@@ -691,8 +628,7 @@ static struct task_struct * __init start_twl4030_irq_thread(long irq)struct task_struct *thread;init_completion (&irq_event); - thread =kthread_run (twl4030_irq_thread, (void *)irq, -"twl4030 irq %ld" , irq); + thread =kthread_run (twl4030_irq_thread, (void *)irq,"twl4030-irq" );if (!thread)pr_err ("%s: could not create twl4030 irq %ld thread!\n" ,DRIVER_NAME , irq);
@@ -1126,7 +1062,7 @@ static void twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)/* install an irq handler for each of the PIH modules */ for (i = irq_base; i < irq_end; i++) {set_irq_chip_and_handler (i, &twl4030_irq_chip, - do_twl4030_module_irq); + handle_simple_irq);activate_irq (i); }
Quoted 11 lines · David Brownell
Quoted 1 line · Samuel Ortiz
Thanks, applied to my mfd tree.
Great!
Quoted 4 lines
Quoted 2 lines
+#if
defined(CONFIG_TWL4030_BCI_BATTERY)|| \
+ defined(CONFIG_TWL4030_BCI_BATTERY_MODUEL)minor typo, you probably meant:
CONFIG_TWL4030_BCI_BATTERY_MODULEYes, good catch. You'll tweak?
Sure.
Quoted 2 lines
Appended is that simple IRQ cleanup I mentioned.
(Get a load of the diffstat!)
Sweet. I should look at it for the asic3 driver.
Applied to the mfd tree, thanks.
Quoted 2 lines
There's more substantial IRQ stuff on the way, but it won't be ready before the 2.6.28 merges start.
I can still take patches during the merge window, if you think they're really ready and necessary.
Cheers,
Samuel.
Quoted 127 lines
- Dave
================== CUT HERE
From: David Brownell <[email protected]>twl4030-core irq simplification
Simplify twl4030 IRQ handling by removing a needless custom flow handler. The top level IRQs, from the PIH, are well suited for
handle_simple_irq()... they can't be acked or masked.Switching resolves some issues with how IRQs were dispatched. Notably, abuse of
desc->status, IRQ accounting, and handling of various faults.In short, use standard genirq code.
Drivers that
request_irq()to the PIH will need to pay more attention to things like settingIRQF_DISABLED(since it's no longer ignored), and making I2C calls from handlers (you'll need a lockdep workaround).Signed-off-by David Brownell <[email protected]>Signed-off-by Tony Lindgren <[email protected]>--- drivers/mfd/twl4030-core.c | 68 +-------------------------------------------- 1 file changed, 2 insertions(+), 66 deletions(-)drivers/mfd/twl4030-core.c +2
-66@@ -535,68 +535,6 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8);/*----------------------------------------------------------------------*/ -/* -* do_twl4030_module_irq() is the desc->handle method for each of the twl4030 -* module interrupts that doesn't chain to another irq_chip (GPIO, power, etc). -* It executes in kernel thread context. On entry, cpu interrupts are disabled. -*/ -static void do_twl4030_module_irq (unsigned int irq,irq_desc_t *desc) -{ -struct irqaction *action; -const unsigned int cpu =smp_processor_id (); - -/* -* Earlier this was desc->triggered = 1; -*/ - desc->status |=IRQ_LEVEL ; - -/* -* The desc->handle method would normally call the desc->chip->ack -* method here, but we won't bother since our ack method is NULL. -*/ - -if (!desc->depth) { -kstat_cpu (cpu).irqs[irq]++; - - action = desc->action; -if (action) { -int ret; -int status =0 ; -int retval =0 ; - -local_irq_enable (); - -do { -/* Call the ISR with cpu interrupts enabled */ - ret = action->handler (irq, action->dev_id); -if (ret ==IRQ_HANDLED ) - status |= action->flags; - retval |= ret; - action = action->next; - }while (action); - -if (status &IRQF_SAMPLE_RANDOM ) -add_interrupt_randomness (irq); - -local_irq_disable (); - -if (retval !=IRQ_HANDLED ) -printk (KERN_ERR "ISR for TWL4030 module" -" irq %d can't handle interrupt\n" , - irq); - -/* -* Here is where we should call the unmask method, but -* again we won't bother since it is NULL. -*/ - }else -printk (KERN_CRIT "TWL4030 module irq %d has no ISR" -" but can't be masked!\n" , irq); - }else -printk (KERN_CRIT "TWL4030 module irq %d is disabled but can't" -" be masked!\n" , irq); -} -static unsigned twl4030_irq_base;static struct completion irq_event;@@ -611,7 +549,6 @@ static int twl4030_irq_thread(void *data)static unsigned i2c_errors;const static unsigned max_i2c_errors =100 ; -daemonize ("twl4030-irq" ); current->flags |=PF_NOFREEZE ;while (!kthread_should_stop ()) {@@ -691,8 +628,7 @@ static struct task_struct * __init start_twl4030_irq_thread(long irq)struct task_struct *thread;init_completion (&irq_event); - thread =kthread_run (twl4030_irq_thread, (void *)irq, -"twl4030 irq %ld" , irq); + thread =kthread_run (twl4030_irq_thread, (void *)irq,"twl4030-irq" );if (!thread)pr_err ("%s: could not create twl4030 irq %ld thread!\n" ,DRIVER_NAME , irq);@@ -1126,7 +1062,7 @@ static void twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)/* install an irq handler for each of the PIH modules */ for (i = irq_base; i < irq_end; i++) {set_irq_chip_and_handler (i, &twl4030_irq_chip, - do_twl4030_module_irq); + handle_simple_irq);activate_irq (i); }
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/
Quoted 5 lines · Samuel Ortiz
Quoted 2 lines
There's more substantial IRQ stuff on the way, but it won't be ready before the 2.6.28 merges start.
I can still take patches during the merge window, if you think they're really ready and necessary.
I think they're necessary, but they'll be more ready a bit later in the merge window.
Other issues are still stabilizing; right now we're chasing down some unrelated issues.
Like ... it turns out some power management support in the I2C driver is causing trouble with this driver (intermittent failures). Workaround is to turn off I2C power management; the real fix seems to involve recognizing that OMAP2 != OMAP3.
The problem first surfaced when the $SUBJECT core moved from drivers/i2c/chips to drivers/mfd, and some timings changed. Intermittent failure then morphed intoGood fun! ;)
- Dave
Quoted 6 lines · David Brownell
This patch adds the core of the TWL4030 driver, which supports chips including the TPS65950. These chips are multi-function; see
http://focus.ti.com/docs/prod/folders/print/tps65950.html
Public specs are in the works.
... and are now available at that URL: all 925 pages (!!) of technical reference manual, for your reading pleasure.
I understand that the tps65950 is more or less equivalent to the twl5030, which is the latest incarnation of the twl4030.
- Dave