* [PATCH 00/23] twl4030 patches (v4)
@ 2008-09-30 10:05 Felipe Balbi
2008-09-30 10:05 ` [PATCH 01/23] twl4030: fix potential null pointer dereference Felipe Balbi
2008-09-30 13:05 ` [PATCH 00/23] twl4030 patches (v4) Tony Lindgren
0 siblings, 2 replies; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
In this version there are irq fixes from David Brownell.
David Brownell (11):
twl4030 gpio platform data
twl4030 uses gpiolib
minor twl4030-core cleanups
provide detailed diagnostics in add_children()
move twl4030-gpio to drivers/gpio
minor irq-related cleanups
Move I2C driver model init earlier in the boot sequence
twl4030-gpio irq_chip.set_type
twl4030-gpio: remove legacy irq triggering calls and user
twl4030-gpio: irq and other cleanup
twl4030-core: portability updates
Felipe Balbi (11):
twl4030: fix potential null pointer dereference
i2c: clean add_children a bit
i2c: move twl4030_keypad to new style registration
i2c: move twl4030-usb to platform_device
i2c: twl4030-usb: add 'vbus' sysfs file
i2c: move twl4030-madc to new registration style
i2c: added a few missing gotos to add_children()
i2c: switch twl4030-usb to use a resource for irq
i2c: minor cleanups to twl4030-pwrbutton.c
twl4030: minor cleanups to twl4030_bci_battery.c
twl4030-bci: move to new style registration method
Jagadeesh Bhaskar Pakaravoor (1):
twl4030-gpio: Remove default pullup enable/disable of GPIO
arch/arm/mach-omap2/Makefile | 4 +-
arch/arm/mach-omap2/bci.c | 57 ----
arch/arm/mach-omap2/board-2430sdp.c | 32 ++-
arch/arm/mach-omap2/board-3430sdp.c | 49 +++-
arch/arm/mach-omap2/board-ldp.c | 37 +++-
arch/arm/mach-omap2/board-omap2evm.c | 33 ++-
arch/arm/mach-omap2/board-omap3beagle.c | 19 ++
arch/arm/mach-omap2/board-omap3evm.c | 85 +++---
arch/arm/mach-omap2/board-overo.c | 11 +
arch/arm/mach-omap2/hsmmc.c | 5 -
arch/arm/plat-omap/include/mach/bci.h | 17 -
arch/arm/plat-omap/include/mach/irqs.h | 2 +-
drivers/gpio/Kconfig | 7 +
drivers/gpio/Makefile | 1 +
drivers/{i2c/chips => gpio}/twl4030-gpio.c | 418 +++++++++++++++++++--------
drivers/i2c/chips/Kconfig | 20 --
drivers/i2c/chips/Makefile | 1 -
drivers/i2c/chips/twl4030-core.c | 344 +++++++++++++++++++---
drivers/i2c/chips/twl4030-madc.c | 243 ++++++++++------
drivers/i2c/chips/twl4030-pwrbutton.c | 10 +-
drivers/i2c/chips/twl4030-usb.c | 373 ++++++++++++------------
drivers/i2c/i2c-core.c | 2 +-
drivers/input/keyboard/omap-twl4030keypad.c | 10 +-
drivers/mmc/host/omap_hsmmc.c | 4 +-
drivers/power/twl4030_bci_battery.c | 184 ++++++------
drivers/rtc/rtc-twl4030.c | 11 +-
include/linux/i2c/twl4030.h | 64 ++++-
27 files changed, 1306 insertions(+), 737 deletions(-)
delete mode 100644 arch/arm/mach-omap2/bci.c
delete mode 100644 arch/arm/plat-omap/include/mach/bci.h
rename drivers/{i2c/chips => gpio}/twl4030-gpio.c (67%)
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 01/23] twl4030: fix potential null pointer dereference
2008-09-30 10:05 [PATCH 00/23] twl4030 patches (v4) Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 02/23] twl4030-gpio: Remove default pullup enable/disable of GPIO Felipe Balbi
2008-09-30 13:05 ` [PATCH 00/23] twl4030 patches (v4) Tony Lindgren
1 sibling, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
The following patch fix a potential null pointer
dereference in twl4030 keypad driver when parts
of keypad platform_data aren't passed down to the
driver. At that point kp->dbg_dev is not set yet.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/input/keyboard/omap-twl4030keypad.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/input/keyboard/omap-twl4030keypad.c b/drivers/input/keyboard/omap-twl4030keypad.c
index 3893d63..48f29d3 100644
--- a/drivers/input/keyboard/omap-twl4030keypad.c
+++ b/drivers/input/keyboard/omap-twl4030keypad.c
@@ -238,7 +238,7 @@ static int __init omap_kp_probe(struct platform_device *pdev)
return -ENOMEM;
if (!pdata->rows || !pdata->cols || !pdata->keymap) {
- dev_err(kp->dbg_dev, "No rows, cols or keymap from pdata\n");
+ dev_err(&pdev->dev, "No rows, cols or keymap from pdata\n");
kfree(kp);
return -EINVAL;
}
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 02/23] twl4030-gpio: Remove default pullup enable/disable of GPIO
2008-09-30 10:05 ` [PATCH 01/23] twl4030: fix potential null pointer dereference Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 03/23] i2c: clean add_children a bit Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap
Cc: Tony Lindgren, David Brownell, Jagadeesh Bhaskar Pakaravoor,
Girish S G, Felipe Balbi
From: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
One twl4030_request_gpio() should not tamper with the pullup
enabling/disabling of the rest of the GPIOs. So removing the default
pullup values written to REG_GPIOPUPDCTR1.
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Girish S G <girishsg@ti.com>
Signed-off-by: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-gpio.c | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-gpio.c b/drivers/i2c/chips/twl4030-gpio.c
index 4d89abc..b51bed0 100644
--- a/drivers/i2c/chips/twl4030-gpio.c
+++ b/drivers/i2c/chips/twl4030-gpio.c
@@ -301,7 +301,6 @@ int twl4030_request_gpio(int gpio)
if (gpio_usage_count & (0x1 << gpio))
ret = -EBUSY;
else {
- u8 clear_pull[6] = { 0, 0, 0, 0, 0, 0 };
/* First time usage? - switch on GPIO module */
if (!gpio_usage_count) {
ret =
@@ -311,10 +310,6 @@ int twl4030_request_gpio(int gpio)
}
if (!ret)
gpio_usage_count |= (0x1 << gpio);
-
- ret =
- twl4030_i2c_write(TWL4030_MODULE_GPIO, clear_pull,
- REG_GPIOPUPDCTR1, 5);
}
up(&gpio_sem);
return ret;
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 03/23] i2c: clean add_children a bit
2008-09-30 10:05 ` [PATCH 02/23] twl4030-gpio: Remove default pullup enable/disable of GPIO Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 04/23] i2c: move twl4030_keypad to new style registration Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
Clean up add_children a bit before adding more children
to twl4030-core.c
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-core.c | 63 +++++++++++++++++++++----------------
1 files changed, 36 insertions(+), 27 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 47f65f8..e55f49e 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -45,6 +45,11 @@
#define DRIVER_NAME "twl4030"
+#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
+#define twl_has_rtc() true
+#else
+#define twl_has_rtc() false
+#endif
/* Primary Interrupt Handler on TWL4030 Registers */
@@ -639,34 +644,38 @@ static int add_children(struct twl4030_platform_data *pdata)
struct twl4030_client *twl = NULL;
int status = 0;
-#ifdef CONFIG_RTC_DRV_TWL4030
- pdev = platform_device_alloc("twl4030_rtc", -1);
- if (pdev) {
- twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
-
- /*
- * FIXME add the relevant IRQ resource, and make the
- * rtc driver use it instead of hard-wiring ...
- *
- * REVISIT platform_data here currently only supports
- * setting up the "msecure" line ... which actually
- * violates the "princple of least privilege", since
- * it's effectively always in "high trust" mode.
- *
- * For now, expect equivalent treatment at board init:
- * setting msecure high. Eventually, Linux might
- * become more aware of those HW security concerns.
- */
-
- status = platform_device_add(pdev);
- if (status < 0)
- platform_device_put(pdev);
- } else
- status = -ENOMEM;
-#endif
+ if (twl_has_rtc()) {
+ pdev = platform_device_alloc("twl4030_rtc", -1);
+ if (pdev) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+
+ /*
+ * FIXME add the relevant IRQ resource, and make the
+ * rtc driver use it instead of hard-wiring ...
+ *
+ * REVISIT platform_data here currently only supports
+ * setting up the "msecure" line ... which actually
+ * violates the "princple of least privilege", since
+ * it's effectively always in "high trust" mode.
+ *
+ * For now, expect equivalent treatment at board init:
+ * setting msecure high. Eventually, Linux might
+ * become more aware of those HW security concerns.
+ */
+
+ status = platform_device_add(pdev);
+ if (status < 0)
+ platform_device_put(pdev);
+ } else {
+ status = -ENOMEM;
+ goto err;
+ }
+ }
+err:
+ pr_err("failed to add twl4030's children\n");
return status;
}
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 04/23] i2c: move twl4030_keypad to new style registration
2008-09-30 10:05 ` [PATCH 03/23] i2c: clean add_children a bit Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 05/23] i2c: move twl4030-usb to platform_device Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
let twl4030-core.c take care of twl4030_keypad registration.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/mach-omap2/board-2430sdp.c | 14 ++----
arch/arm/mach-omap2/board-3430sdp.c | 14 ++----
arch/arm/mach-omap2/board-omap2evm.c | 16 ++----
arch/arm/mach-omap2/board-omap3evm.c | 69 ++++++++++++--------------
drivers/i2c/chips/twl4030-core.c | 27 ++++++++++
drivers/input/keyboard/omap-twl4030keypad.c | 8 ++--
include/linux/i2c/twl4030.h | 10 ++++
7 files changed, 86 insertions(+), 72 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 3649a94..8c4c9dd 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -173,7 +173,7 @@ static int sdp2430_keymap[] = {
0
};
-static struct omap_kp_platform_data sdp2430_kp_data = {
+static struct twl4030_keypad_data sdp2430_kp_data = {
.rows = 5,
.cols = 6,
.keymap = sdp2430_keymap,
@@ -182,14 +182,6 @@ static struct omap_kp_platform_data sdp2430_kp_data = {
.irq = TWL4030_MODIRQ_KEYPAD,
};
-static struct platform_device sdp2430_kp_device = {
- .name = "omap_twl4030keypad",
- .id = -1,
- .dev = {
- .platform_data = &sdp2430_kp_data,
- },
-};
-
static int __init msecure_init(void)
{
int ret = 0;
@@ -216,7 +208,6 @@ out:
static struct platform_device *sdp2430_devices[] __initdata = {
&sdp2430_smc91x_device,
&sdp2430_flash_device,
- &sdp2430_kp_device,
&sdp2430_lcd_device,
};
@@ -356,6 +347,9 @@ static struct omap_board_config_kernel sdp2430_config[] __initdata = {
static struct twl4030_platform_data sdp2430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .keypad = &sdp2430_kp_data,
};
static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 4c60d7b..fe1ba4e 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -110,7 +110,7 @@ static int sdp3430_keymap[] = {
0
};
-static struct omap_kp_platform_data sdp3430_kp_data = {
+static struct twl4030_keypad_data sdp3430_kp_data = {
.rows = 5,
.cols = 6,
.keymap = sdp3430_keymap,
@@ -119,14 +119,6 @@ static struct omap_kp_platform_data sdp3430_kp_data = {
.irq = TWL4030_MODIRQ_KEYPAD,
};
-static struct platform_device sdp3430_kp_device = {
- .name = "omap_twl4030keypad",
- .id = -1,
- .dev = {
- .platform_data = &sdp3430_kp_data,
- },
-};
-
static int ts_gpio;
static int __init msecure_init(void)
@@ -252,7 +244,6 @@ static struct platform_device sdp3430_lcd_device = {
static struct platform_device *sdp3430_devices[] __initdata = {
&sdp3430_smc91x_device,
- &sdp3430_kp_device,
&sdp3430_lcd_device,
};
@@ -312,6 +303,9 @@ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
static struct twl4030_platform_data sdp3430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .keypad = &sdp3430_kp_data,
};
static struct i2c_board_info __initdata sdp3430_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c
index 6ce7740..d2a3743 100644
--- a/arch/arm/mach-omap2/board-omap2evm.c
+++ b/arch/arm/mach-omap2/board-omap2evm.c
@@ -200,23 +200,15 @@ static int omap2evm_keymap[] = {
KEY(3, 3, KEY_P)
};
-static struct omap_kp_platform_data omap2evm_kp_data = {
+static struct twl4030_keypad_data omap2evm_kp_data = {
.rows = 4,
.cols = 4,
- .keymap = omap2evm_keymap,
+ .keymap = omap2evm_keymap,
.keymapsize = ARRAY_SIZE(omap2evm_keymap),
.rep = 1,
.irq = TWL4030_MODIRQ_KEYPAD,
};
-static struct platform_device omap2evm_kp_device = {
- .name = "omap_twl4030keypad",
- .id = -1,
- .dev = {
- .platform_data = &omap2evm_kp_data,
- },
-};
-
static void __init omap2_evm_init_irq(void)
{
omap2_init_common_hw(NULL);
@@ -237,6 +229,9 @@ static struct omap_board_config_kernel omap2_evm_config[] __initdata = {
static struct twl4030_platform_data omap2evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .keypad = &omap2evm_kp_data,
};
static struct i2c_board_info __initdata omap2evm_i2c_boardinfo[] = {
@@ -259,7 +254,6 @@ static int __init omap2_evm_i2c_init(void)
static struct platform_device *omap2_evm_devices[] __initdata = {
&omap2_evm_lcd_device,
&omap2evm_smc911x_device,
- &omap2evm_kp_device,
};
static void __init omap2_evm_init(void)
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 6aa7e28..c4a969d 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -90,9 +90,41 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
+static int omap3evm_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_A),
+ KEY(0, 3, KEY_B),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_E),
+ KEY(1, 3, KEY_F),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_I),
+ KEY(2, 2, KEY_J),
+ KEY(2, 3, KEY_K),
+ KEY(3, 0, KEY_M),
+ KEY(3, 1, KEY_N),
+ KEY(3, 2, KEY_O),
+ KEY(3, 3, KEY_P)
+};
+
+static struct twl4030_keypad_data omap3evm_kp_data = {
+ .rows = 4,
+ .cols = 4,
+ .keymap = omap3evm_keymap,
+ .keymapsize = ARRAY_SIZE(omap3evm_keymap),
+ .rep = 1,
+ .irq = TWL4030_MODIRQ_KEYPAD,
+};
+
+
static struct twl4030_platform_data omap3evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .keypad = &omap3evm_kp_data,
};
static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
@@ -168,42 +200,6 @@ struct spi_board_info omap3evm_spi_board_info[] = {
},
};
-static int omap3evm_keymap[] = {
- KEY(0, 0, KEY_LEFT),
- KEY(0, 1, KEY_RIGHT),
- KEY(0, 2, KEY_A),
- KEY(0, 3, KEY_B),
- KEY(1, 0, KEY_DOWN),
- KEY(1, 1, KEY_UP),
- KEY(1, 2, KEY_E),
- KEY(1, 3, KEY_F),
- KEY(2, 0, KEY_ENTER),
- KEY(2, 1, KEY_I),
- KEY(2, 2, KEY_J),
- KEY(2, 3, KEY_K),
- KEY(3, 0, KEY_M),
- KEY(3, 1, KEY_N),
- KEY(3, 2, KEY_O),
- KEY(3, 3, KEY_P)
-};
-
-static struct omap_kp_platform_data omap3evm_kp_data = {
- .rows = 4,
- .cols = 4,
- .keymap = omap3evm_keymap,
- .keymapsize = ARRAY_SIZE(omap3evm_keymap),
- .rep = 1,
- .irq = TWL4030_MODIRQ_KEYPAD,
-};
-
-static struct platform_device omap3evm_kp_device = {
- .name = "omap_twl4030keypad",
- .id = -1,
- .dev = {
- .platform_data = &omap3evm_kp_data,
- },
-};
-
static void __init omap3_evm_init_irq(void)
{
omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
@@ -219,7 +215,6 @@ static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
static struct platform_device *omap3_evm_devices[] __initdata = {
&omap3_evm_lcd_device,
- &omap3evm_kp_device,
&omap3evm_smc911x_device,
};
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index e55f49e..0a2d8fe 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -51,6 +51,12 @@
#define twl_has_rtc() false
#endif
+#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
+#define twl_has_keypad() true
+#else
+#define twl_has_keypad() false
+#endif
+
/* Primary Interrupt Handler on TWL4030 Registers */
/* Register Definitions */
@@ -674,6 +680,27 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
+ if (twl_has_keypad() && pdata->keypad) {
+ pdev = platform_device_alloc("twl4030_keypad", -1);
+ if (pdev) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM2];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->keypad,
+ sizeof(*pdata->keypad));
+ if (status < 0) {
+ platform_device_put(pdev);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0)
+ platform_device_put(pdev);
+ } else {
+ status = -ENOMEM;
+ goto err;
+ }
+ }
+
err:
pr_err("failed to add twl4030's children\n");
return status;
diff --git a/drivers/input/keyboard/omap-twl4030keypad.c b/drivers/input/keyboard/omap-twl4030keypad.c
index 48f29d3..e6b34be 100644
--- a/drivers/input/keyboard/omap-twl4030keypad.c
+++ b/drivers/input/keyboard/omap-twl4030keypad.c
@@ -38,7 +38,6 @@
#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
#include <linux/irq.h>
-#include <mach/keypad.h>
#include "twl4030-keypad.h"
#define PTV_PRESCALER 4
@@ -46,6 +45,7 @@
#define MAX_ROWS 8 /* TWL4030 hardlimit */
#define ROWCOL_MASK 0xFF000000
#define KEYNUM_MASK 0x00FFFFFF
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
/* Global variables */
@@ -231,7 +231,7 @@ static int __init omap_kp_probe(struct platform_device *pdev)
int i;
int ret = 0;
struct omap_keypad *kp;
- struct omap_kp_platform_data *pdata = pdev->dev.platform_data;
+ struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
kp = kzalloc(sizeof(*kp), GFP_KERNEL);
if (!kp)
@@ -389,7 +389,7 @@ static struct platform_driver omap_kp_driver = {
.probe = omap_kp_probe,
.remove = __devexit_p(omap_kp_remove),
.driver = {
- .name = "omap_twl4030keypad",
+ .name = "twl4030_keypad",
.owner = THIS_MODULE,
},
};
@@ -409,7 +409,7 @@ static void __exit omap_kp_exit(void)
module_init(omap_kp_init);
module_exit(omap_kp_exit);
-MODULE_ALIAS("platform:omap_twl4030keypad");
+MODULE_ALIAS("platform:twl4030_keypad");
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("OMAP TWL4030 Keypad Driver");
MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 2434ad0..0ac417c 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -52,8 +52,18 @@
#define TWL4030_MODULE_RTC 0x14
#define TWL4030_MODULE_SECURED_REG 0x15
+struct twl4030_keypad_data {
+ int rows;
+ int cols;
+ int *keymap;
+ int irq;
+ unsigned int keymapsize;
+ unsigned int rep:1;
+};
+
struct twl4030_platform_data {
unsigned irq_base, irq_end;
+ struct twl4030_keypad_data *keypad;
/* REVISIT more to come ... _nothing_ should be hard-wired */
};
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 05/23] i2c: move twl4030-usb to platform_device
2008-09-30 10:05 ` [PATCH 04/23] i2c: move twl4030_keypad to new style registration Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 06/23] i2c: twl4030-usb: add 'vbus' sysfs file Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
use new style twl4030-core to register a platform_device
for twl4030-usb.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/mach-omap2/board-2430sdp.c | 6 +
arch/arm/mach-omap2/board-3430sdp.c | 5 +
arch/arm/mach-omap2/board-ldp.c | 7 +
arch/arm/mach-omap2/board-omap2evm.c | 5 +
arch/arm/mach-omap2/board-omap3beagle.c | 7 +
arch/arm/mach-omap2/board-omap3evm.c | 6 +-
arch/arm/mach-omap2/board-overo.c | 5 +
drivers/i2c/chips/Kconfig | 16 --
drivers/i2c/chips/twl4030-core.c | 27 +++
drivers/i2c/chips/twl4030-usb.c | 324 ++++++++++++++-----------------
include/linux/i2c/twl4030.h | 10 +
11 files changed, 219 insertions(+), 199 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 8c4c9dd..3073528 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -344,12 +344,18 @@ static struct omap_board_config_kernel sdp2430_config[] __initdata = {
{OMAP_TAG_SERIAL_CONSOLE, &sdp2430_serial_console_config},
};
+
+static struct twl4030_usb_data sdp2430_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static struct twl4030_platform_data sdp2430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.keypad = &sdp2430_kp_data,
+ .usb = &sdp2430_usb_data,
};
static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index fe1ba4e..e0c39c2 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -300,12 +300,17 @@ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
{ OMAP_TAG_LCD, &sdp3430_lcd_config },
};
+static struct twl4030_usb_data sdp3430_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static struct twl4030_platform_data sdp3430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.keypad = &sdp3430_kp_data,
+ .usb = &sdp3430_usb_data,
};
static struct i2c_board_info __initdata sdp3430_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index c07c712..219579b 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -183,9 +183,16 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
{ OMAP_TAG_UART, &ldp_uart_config },
};
+static struct twl4030_usb_data ldp_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static struct twl4030_platform_data ldp_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .usb = &ldp_usb_data,
};
static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c
index d2a3743..be8348d 100644
--- a/arch/arm/mach-omap2/board-omap2evm.c
+++ b/arch/arm/mach-omap2/board-omap2evm.c
@@ -226,12 +226,17 @@ static struct omap_board_config_kernel omap2_evm_config[] __initdata = {
{ OMAP_TAG_LCD, &omap2_evm_lcd_config },
};
+static struct twl4030_usb_data omap2evm_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static struct twl4030_platform_data omap2evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.keypad = &omap2evm_kp_data,
+ .usb = &omap2evm_usb_data,
};
static struct i2c_board_info __initdata omap2evm_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index fa8f5f6..ae677b9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -110,9 +110,16 @@ static struct omap_uart_config omap3_beagle_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
+static struct twl4030_usb_data beagle_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static struct twl4030_platform_data beagle_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .usb = &beagle_usb_data,
};
static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index c4a969d..158138c 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -90,6 +90,10 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
+static struct twl4030_usb_data omap3evm_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static int omap3evm_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
@@ -118,13 +122,13 @@ static struct twl4030_keypad_data omap3evm_kp_data = {
.irq = TWL4030_MODIRQ_KEYPAD,
};
-
static struct twl4030_platform_data omap3evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.keypad = &omap3evm_kp_data,
+ .usb = &omap3evm_usb_data,
};
static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index a41e6fa..2e6d2c7 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -146,9 +146,14 @@ static struct omap_uart_config overo_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
+static struct twl4030_usb_data overo_usb_data = {
+ .usb_mode = T2_USB_MODE_ULPI,
+};
+
static struct twl4030_platform_data overo_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+ .usb = &overo_usb_data,
};
static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index e91be60..121aec9 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -186,22 +186,6 @@ config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE
-choice
- prompt "Transceiver mode"
- depends on TWL4030_USB
- help
- TWL4030 USB transceiver can operate in various
- mutually-exclusive modes. Select one of them.
-
-config TWL4030_USB_HS_ULPI
- depends on TWL4030_USB
- bool "High-speed ULPI"
- help
- Say Y here if the TWL4030 is connected to high-speed USB
- controller through a ULPI interface.
-
-endchoice
-
config TWL4030_PWRBUTTON
tristate "TWL4030 Power button Driver"
depends on TWL4030_CORE
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 0a2d8fe..02be771 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -57,6 +57,12 @@
#define twl_has_keypad() false
#endif
+#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
+#define twl_has_usb() true
+#else
+#define twl_has_usb() false
+#endif
+
/* Primary Interrupt Handler on TWL4030 Registers */
/* Register Definitions */
@@ -701,6 +707,27 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
+ if (twl_has_usb() && pdata->usb) {
+ pdev = platform_device_alloc("twl4030_usb", -1);
+ if (pdev) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM0];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->usb,
+ sizeof(*pdata->usb));
+ if (status < 0) {
+ platform_device_put(pdev);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0)
+ platform_device_put(pdev);
+ } else {
+ status = -ENOMEM;
+ goto err;
+ }
+ }
+
err:
pr_err("failed to add twl4030's children\n");
return status;
diff --git a/drivers/i2c/chips/twl4030-usb.c b/drivers/i2c/chips/twl4030-usb.c
index 2906b82..246aa9d 100644
--- a/drivers/i2c/chips/twl4030-usb.c
+++ b/drivers/i2c/chips/twl4030-usb.c
@@ -2,6 +2,8 @@
* twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
*
* Copyright (C) 2004-2007 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.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
@@ -22,11 +24,11 @@
* - 3-pin mode support may be added in future.
*/
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
@@ -228,14 +230,6 @@
#define VUSB3V1_TYPE 0x78
#define VUSB3V1_REMAP 0x79
-#define ID_STATUS 0x96
-#define ID_RES_FLOAT (1 << 4) /* mini-B */
-#define ID_RES_440K (1 << 3) /* type 2 charger */
-#define ID_RES_200K (1 << 2) /* 5-wire carkit or
- type 1 charger */
-#define ID_RES_102K (1 << 1) /* phone */
-#define ID_RES_GND (1 << 0) /* mini-A */
-
/* In module TWL4030_MODULE_INTBR */
#define PMBR1 0x0D
#define GPIO_USB_4PIN_ULPI_2430C (3 << 0)
@@ -250,11 +244,7 @@
#define REG_PWR_SIH_CTRL 0x07
#define COR (1 << 2)
-/* internal define on top of container_of */
-#define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg);
-
/* bits in OTG_CTRL */
-
#define OTG_XCEIV_OUTPUTS \
(OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
#define OTG_XCEIV_INPUTS \
@@ -268,22 +258,23 @@
OTG_CTRL_BITS)
-/*-------------------------------------------------------------------------*/
-
struct twl4030_usb {
struct otg_transceiver otg;
+ struct device *dev;
+
+ /* pin configuration */
+ enum twl4030_usb_mode usb_mode;
int irq;
- u8 usb_mode; /* pin configuration */
-#define T2_USB_MODE_ULPI 1
-/* #define T2_USB_MODE_CEA2011_3PIN 2 */
u8 asleep;
};
-static struct twl4030_usb *the_transceiver;
+/* internal define on top of container_of */
+#define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg);
/*-------------------------------------------------------------------------*/
-static int twl4030_i2c_write_u8_verify(u8 module, u8 data, u8 address)
+static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
+ u8 module, u8 data, u8 address)
{
u8 check;
@@ -297,46 +288,51 @@ static int twl4030_i2c_write_u8_verify(u8 module, u8 data, u8 address)
(check == data))
return 0;
/* Failed again: Return error */
+
return -EBUSY;
}
-#define twl4030_usb_write_verify(address, data) \
- twl4030_i2c_write_u8_verify(TWL4030_MODULE_USB, (data), (address))
+#define twl4030_usb_write_verify(twl, address, data) \
+ twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address))
-static inline int twl4030_usb_write(u8 address, u8 data)
+static inline int twl4030_usb_write(struct twl4030_usb *twl,
+ u8 address, u8 data)
{
int ret = 0;
+
ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address);
if (ret >= 0) {
#if 0 /* debug */
u8 data1;
if (twl4030_i2c_read_u8(TWL4030_MODULE_USB, &data1,
address) < 0)
- printk(KERN_ERR "re-read failed\n");
+ dev_err(twl->dev, "re-read failed\n");
else
- printk(KERN_INFO
+ dev_dbg(twl->dev,
"Write %s wrote %x read %x from reg %x\n",
(data1 == data) ? "succeed" : "mismatch",
data, data1, address);
#endif
} else {
- printk(KERN_WARNING
+ dev_warn(twl->dev,
"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
}
+
return ret;
}
-static inline int twl4030_usb_read(u8 address)
+static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
{
u8 data;
int ret = 0;
+
ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &data, address);
- if (ret >= 0) {
+ if (ret >= 0)
ret = data;
- } else {
- printk(KERN_WARNING
+ else
+ dev_warn(twl->dev,
"TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
- }
+
return ret;
}
@@ -345,14 +341,13 @@ static inline int twl4030_usb_read(u8 address)
static inline int
twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
{
- return twl4030_usb_write(reg + 1, bits);
+ return twl4030_usb_write(twl, reg + 1, bits);
}
static inline int
twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
{
- return twl4030_usb_write(reg + 2, bits);
-
+ return twl4030_usb_write(twl, reg + 2, bits);
}
/*-------------------------------------------------------------------------*/
@@ -380,185 +375,130 @@ static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
};
}
-#ifdef CONFIG_TWL4030_USB_HS_ULPI
-static void hs_usb_init(struct twl4030_usb *twl)
-{
- twl->usb_mode = T2_USB_MODE_ULPI;
- return;
-}
-
-#endif
-
-static void twl4030_i2c_access(int on)
+static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
{
unsigned long timeout;
- int val = twl4030_usb_read(PHY_CLK_CTRL);
+ int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
if (val >= 0) {
if (on) {
/* enable DPLL to access PHY registers over I2C */
val |= REQ_PHY_DPLL_CLK;
- if (twl4030_usb_write_verify(PHY_CLK_CTRL,
- (u8)val) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
+ (u8)val) < 0);
timeout = jiffies + HZ;
- while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &
+ while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
PHY_DPLL_CLK)
&& time_before(jiffies, timeout))
udelay(10);
- if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) &
+ if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
PHY_DPLL_CLK))
- printk(KERN_ERR "Timeout setting T2 HSUSB "
+ dev_err(twl->dev, "Timeout setting T2 HSUSB "
"PHY DPLL clock\n");
} else {
/* let ULPI control the DPLL clock */
val &= ~REQ_PHY_DPLL_CLK;
- if (twl4030_usb_write_verify(PHY_CLK_CTRL,
- (u8)val) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- }
+ WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
+ (u8)val) < 0);
}
}
- return;
}
-static void usb_irq_enable(int rising, int falling)
+static void usb_irq_enable(struct twl4030_usb *twl, int rising, int falling)
{
u8 val;
/* edge setup */
- if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c read failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &val, REG_PWR_EDR1) < 0);
+
val &= ~(USB_PRES_RISING | USB_PRES_FALLING);
if (rising)
val = val | USB_PRES_RISING;
if (falling)
val = val | USB_PRES_FALLING;
- if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
- REG_PWR_EDR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
+ val, REG_PWR_EDR1) < 0);
/* un-mask interrupt */
- if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_IMR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c read failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &val, REG_PWR_IMR1) < 0);
+
val &= ~USB_PRES;
- if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
- REG_PWR_IMR1) < 0)
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- return;
+ WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
+ val, REG_PWR_IMR1) < 0);
}
-static void usb_irq_disable(void)
+static void usb_irq_disable(struct twl4030_usb *twl)
{
u8 val;
/* undo edge setup */
- if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c read failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &val, REG_PWR_EDR1) < 0);
val &= ~(USB_PRES_RISING | USB_PRES_FALLING);
- if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
- REG_PWR_EDR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
+ val, REG_PWR_EDR1) < 0);
/* mask interrupt */
- if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_IMR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c read failed,"
- " line %d\n", __LINE__);
- return;
- }
+ WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &val, REG_PWR_IMR1) < 0);
val |= USB_PRES;
- if (twl4030_i2c_write_u8_verify(TWL4030_MODULE_INT, val,
- REG_PWR_IMR1) < 0)
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- return;
+ WARN_ON(twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_INT,
+ val, REG_PWR_IMR1) < 0);
}
static void twl4030_phy_power(struct twl4030_usb *twl, int on)
{
u8 pwr;
- pwr = twl4030_usb_read(PHY_PWR_CTRL);
+ pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
if (on) {
pwr &= ~PHY_PWR_PHYPWD;
- if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- return;
- }
- twl4030_usb_write(PHY_CLK_CTRL,
- twl4030_usb_read(PHY_CLK_CTRL) |
+ WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+ twl4030_usb_write(twl, PHY_CLK_CTRL,
+ twl4030_usb_read(twl, PHY_CLK_CTRL) |
(PHY_CLK_CTRL_CLOCKGATING_EN |
PHY_CLK_CTRL_CLK32K_EN));
} else {
pwr |= PHY_PWR_PHYPWD;
- if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c write failed,"
- " line %d\n", __LINE__);
- }
+ WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
}
- return;
}
-static void twl4030_phy_suspend(int controller_off)
+static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
{
- struct twl4030_usb *twl = the_transceiver;
-
if (controller_off)
- usb_irq_disable();
+ usb_irq_disable(twl);
if (twl->asleep)
return;
if (!controller_off)
/* enable rising edge interrupt to detect cable attach */
- usb_irq_enable(1, 0);
+ usb_irq_enable(twl, 1, 0);
twl4030_phy_power(twl, 0);
twl->asleep = 1;
- return;
}
-static void twl4030_phy_resume(void)
+static void twl4030_phy_resume(struct twl4030_usb *twl)
{
- struct twl4030_usb *twl = the_transceiver;
-
if (!twl->asleep)
return;
/* enable falling edge interrupt to detect cable detach */
- usb_irq_enable(0, 1);
+ usb_irq_enable(twl, 0, 1);
twl4030_phy_power(twl, 1);
- twl4030_i2c_access(1);
+ twl4030_i2c_access(twl, 1);
twl4030_usb_set_mode(twl, twl->usb_mode);
if (twl->usb_mode == T2_USB_MODE_ULPI)
- twl4030_i2c_access(0);
+ twl4030_i2c_access(twl, 0);
twl->asleep = 0;
- return;
}
static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
@@ -591,59 +531,57 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{
- int ret = IRQ_NONE;
+ struct twl4030_usb *twl = _twl;
u8 val;
/* action based on cable attach or detach */
- if (twl4030_i2c_read_u8(TWL4030_MODULE_INT, &val, REG_PWR_EDR1) < 0) {
- printk(KERN_ERR "twl4030_usb: i2c read failed,"
- " line %d\n", __LINE__);
- goto done;
- }
+ WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &val, REG_PWR_EDR1) < 0);
if (val & USB_PRES_RISING) {
- twl4030_phy_resume();
+ twl4030_phy_resume(twl);
twl4030charger_usb_en(1);
} else {
twl4030charger_usb_en(0);
- twl4030_phy_suspend(0);
+ twl4030_phy_suspend(twl, 0);
}
- ret = IRQ_HANDLED;
-
-done:
- return ret;
+ return IRQ_HANDLED;
}
static int twl4030_set_suspend(struct otg_transceiver *x, int suspend)
{
+ struct twl4030_usb *twl = xceiv_to_twl(x);
+
if (suspend)
- twl4030_phy_suspend(1);
+ twl4030_phy_suspend(twl, 1);
else
- twl4030_phy_resume();
+ twl4030_phy_resume(twl);
return 0;
}
-static int twl4030_set_peripheral(struct otg_transceiver *xceiv,
+static int twl4030_set_peripheral(struct otg_transceiver *x,
struct usb_gadget *gadget)
{
+ struct twl4030_usb *twl;
u32 l;
- struct twl4030_usb *twl = xceiv_to_twl(xceiv);
- if (!xceiv)
+ if (!x)
return -ENODEV;
+ twl = xceiv_to_twl(x);
+
if (!gadget) {
omap_writew(0, OTG_IRQ_EN);
- twl4030_phy_suspend(1);
+ twl4030_phy_suspend(twl, 1);
twl->otg.gadget = NULL;
return -ENODEV;
}
twl->otg.gadget = gadget;
- twl4030_phy_resume();
+ twl4030_phy_resume(twl);
l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
@@ -660,23 +598,25 @@ static int twl4030_set_peripheral(struct otg_transceiver *xceiv,
return 0;
}
-static int twl4030_set_host(struct otg_transceiver *xceiv, struct usb_bus *host)
+static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host)
{
- struct twl4030_usb *twl = xceiv_to_twl(xceiv);
+ struct twl4030_usb *twl;
- if (!xceiv)
+ if (!x)
return -ENODEV;
+ twl = xceiv_to_twl(x);
+
if (!host) {
omap_writew(0, OTG_IRQ_EN);
- twl4030_phy_suspend(1);
+ twl4030_phy_suspend(twl, 1);
twl->otg.host = NULL;
return -ENODEV;
}
twl->otg.host = host;
- twl4030_phy_resume();
+ twl4030_phy_resume(twl);
twl4030_usb_set_bits(twl, TWL4030_OTG_CTRL,
TWL4030_OTG_CTRL_DMPULLDOWN
@@ -689,63 +629,63 @@ static int twl4030_set_host(struct otg_transceiver *xceiv, struct usb_bus *host)
return 0;
}
-static int __init twl4030_usb_init(void)
+static int __init twl4030_usb_probe(struct platform_device *pdev)
{
+ struct twl4030_usb_data *pdata = pdev->dev.platform_data;
struct twl4030_usb *twl;
int status;
- if (the_transceiver)
- return 0;
-
twl = kzalloc(sizeof *twl, GFP_KERNEL);
if (!twl)
- return 0;
+ return -ENOMEM;
- the_transceiver = twl;
+ if (!pdata) {
+ dev_info(&pdev->dev, "platform_data not available\n");
+ return -EINVAL;
+ }
+ twl->dev = &pdev->dev;
twl->irq = TWL4030_PWRIRQ_USB_PRES;
twl->otg.set_host = twl4030_set_host;
twl->otg.set_peripheral = twl4030_set_peripheral;
twl->otg.set_suspend = twl4030_set_suspend;
+ twl->usb_mode = pdata->usb_mode;
- usb_irq_disable();
+ usb_irq_disable(twl);
status = request_irq(twl->irq, twl4030_usb_irq, 0, "twl4030_usb", twl);
if (status < 0) {
- printk(KERN_DEBUG "can't get IRQ %d, err %d\n",
+ dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq, status);
kfree(twl);
- return -ENODEV;
+ return status;
}
-#if defined(CONFIG_TWL4030_USB_HS_ULPI)
- hs_usb_init(twl);
-#endif
+
twl4030_usb_ldo_init(twl);
twl4030_phy_power(twl, 1);
- twl4030_i2c_access(1);
+ twl4030_i2c_access(twl, 1);
twl4030_usb_set_mode(twl, twl->usb_mode);
- if (twl->usb_mode == T2_USB_MODE_ULPI)
- twl4030_i2c_access(0);
twl->asleep = 0;
- if (twl->usb_mode == T2_USB_MODE_ULPI)
- twl4030_phy_suspend(1);
+ if (twl->usb_mode == T2_USB_MODE_ULPI) {
+ twl4030_i2c_access(twl, 0);
+ twl4030_phy_suspend(twl, 0);
+ }
otg_set_transceiver(&twl->otg);
-
- printk(KERN_INFO "Initialized TWL4030 USB module\n");
+ platform_set_drvdata(pdev, twl);
+ dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
return 0;
}
-
-static void __exit twl4030_usb_exit(void)
+static int __exit twl4030_usb_remove(struct platform_device *pdev)
{
- struct twl4030_usb *twl = the_transceiver;
+ struct twl4030_usb *twl = platform_get_drvdata(pdev);
int val;
- usb_irq_disable();
+ usb_irq_disable(twl);
free_irq(twl->irq, twl);
/* set transceiver mode to power on defaults */
@@ -755,11 +695,11 @@ static void __exit twl4030_usb_exit(void)
* clear dpll clock request for i2c access,
* disable 32KHz
*/
- val = twl4030_usb_read(PHY_CLK_CTRL);
+ val = twl4030_usb_read(twl, PHY_CLK_CTRL);
if (val >= 0) {
val |= PHY_CLK_CTRL_CLOCKGATING_EN;
val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
- twl4030_usb_write(PHY_CLK_CTRL, (u8)val);
+ twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
}
/* disable complete OTG block */
@@ -768,12 +708,32 @@ static void __exit twl4030_usb_exit(void)
twl4030_phy_power(twl, 0);
kfree(twl);
+
+ return 0;
}
-subsys_initcall(twl4030_usb_init);
+static struct platform_driver twl4030_driver = {
+ .probe = twl4030_usb_probe,
+ .remove = __exit_p(twl4030_remove),
+ .driver = {
+ .name = "twl4030_usb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init twl4030_usb_init(void)
+{
+ return platform_driver_register(&twl4030_driver);
+}
+module_init(twl4030_usb_init);
+
+static void __exit twl4030_usb_exit(void)
+{
+ platform_driver_unregister(&twl4030_driver);
+}
module_exit(twl4030_usb_exit);
-MODULE_ALIAS("i2c:twl4030-usb");
-MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_ALIAS("platform:twl4030_usb");
+MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 0ac417c..8a12ff0 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -61,9 +61,19 @@ struct twl4030_keypad_data {
unsigned int rep:1;
};
+enum twl4030_usb_mode {
+ T2_USB_MODE_ULPI = 1,
+ T2_USB_MODE_CEA2011_3PIN = 2,
+};
+
+struct twl4030_usb_data {
+ enum twl4030_usb_mode usb_mode;
+};
+
struct twl4030_platform_data {
unsigned irq_base, irq_end;
struct twl4030_keypad_data *keypad;
+ struct twl4030_usb_data *usb;
/* REVISIT more to come ... _nothing_ should be hard-wired */
};
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 06/23] i2c: twl4030-usb: add 'vbus' sysfs file
2008-09-30 10:05 ` [PATCH 05/23] i2c: move twl4030-usb to platform_device Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 07/23] twl4030 gpio platform data Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
vbus sysfs file will report the state of vbus irq coming from
twl4030-usb.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-usb.c | 51 ++++++++++++++++++++++++++++++++++++++-
1 files changed, 50 insertions(+), 1 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-usb.c b/drivers/i2c/chips/twl4030-usb.c
index 246aa9d..f530e71 100644
--- a/drivers/i2c/chips/twl4030-usb.c
+++ b/drivers/i2c/chips/twl4030-usb.c
@@ -29,6 +29,8 @@
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
#include <linux/io.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
@@ -259,11 +261,17 @@
struct twl4030_usb {
+ struct work_struct irq_work;
struct otg_transceiver otg;
struct device *dev;
+ /* for vbus reporting with irqs disabled */
+ spinlock_t lock;
+
/* pin configuration */
enum twl4030_usb_mode usb_mode;
+
+ unsigned vbus:1;
int irq;
u8 asleep;
};
@@ -529,6 +537,29 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
}
+static ssize_t twl4030_usb_vbus_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct twl4030_usb *twl = dev_get_drvdata(dev);
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ spin_lock_irqsave(&twl->lock, flags);
+ ret = sprintf(buf, "%s\n", twl->vbus ? "on" : "off");
+ spin_unlock_irqrestore(&twl->lock, flags);
+
+ return ret;
+}
+static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
+
+static void twl4030_usb_irq_work(struct work_struct *work)
+{
+ struct twl4030_usb *twl = container_of(work,
+ struct twl4030_usb, irq_work);
+
+ sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+}
+
static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{
struct twl4030_usb *twl = _twl;
@@ -541,10 +572,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
if (val & USB_PRES_RISING) {
twl4030_phy_resume(twl);
twl4030charger_usb_en(1);
+ twl->vbus = 1;
} else {
twl4030charger_usb_en(0);
+ twl->vbus = 0;
twl4030_phy_suspend(twl, 0);
}
+ schedule_work(&twl->irq_work);
return IRQ_HANDLED;
}
@@ -634,6 +668,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
struct twl4030_usb_data *pdata = pdev->dev.platform_data;
struct twl4030_usb *twl;
int status;
+ u8 vbus;
twl = kzalloc(sizeof *twl, GFP_KERNEL);
if (!twl)
@@ -644,12 +679,23 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
return -EINVAL;
}
+ WARN_ON(twl4030_i2c_read_u8(TWL4030_MODULE_INT,
+ &vbus, REG_PWR_EDR1) < 0);
+ vbus &= USB_PRES_RISING;
+
twl->dev = &pdev->dev;
twl->irq = TWL4030_PWRIRQ_USB_PRES;
twl->otg.set_host = twl4030_set_host;
twl->otg.set_peripheral = twl4030_set_peripheral;
twl->otg.set_suspend = twl4030_set_suspend;
twl->usb_mode = pdata->usb_mode;
+ twl->vbus = vbus ? 1 : 0;
+
+ /* init spinlock for workqueue */
+ spin_lock_init(&twl->lock);
+
+ /* init irq workqueue before request_irq */
+ INIT_WORK(&twl->irq_work, twl4030_usb_irq_work);
usb_irq_disable(twl);
status = request_irq(twl->irq, twl4030_usb_irq, 0, "twl4030_usb", twl);
@@ -660,7 +706,6 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
return status;
}
-
twl4030_usb_ldo_init(twl);
twl4030_phy_power(twl, 1);
twl4030_i2c_access(twl, 1);
@@ -677,6 +722,9 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, twl);
dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
+ if (device_create_file(&pdev->dev, &dev_attr_vbus))
+ dev_warn(&pdev->dev, "could not create sysfs file\n");
+
return 0;
}
@@ -687,6 +735,7 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
usb_irq_disable(twl);
free_irq(twl->irq, twl);
+ device_remove_file(twl->dev, &dev_attr_vbus);
/* set transceiver mode to power on defaults */
twl4030_usb_set_mode(twl, -1);
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 07/23] twl4030 gpio platform data
2008-09-30 10:05 ` [PATCH 06/23] i2c: twl4030-usb: add 'vbus' sysfs file Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 08/23] twl4030 uses gpiolib Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Define platform data for configuring TWL4030 GPIOs,
and provide it for all boards using these chips.
For now all boards use the same fixed assignments for
GPIO and IRQ numbers. Eventually we should be able
to shuffle them without changing platform headers.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/mach-omap2/board-2430sdp.c | 7 +++++++
arch/arm/mach-omap2/board-3430sdp.c | 7 +++++++
arch/arm/mach-omap2/board-ldp.c | 7 +++++++
arch/arm/mach-omap2/board-omap2evm.c | 7 +++++++
arch/arm/mach-omap2/board-omap3beagle.c | 12 ++++++++++++
arch/arm/mach-omap2/board-omap3evm.c | 7 +++++++
arch/arm/mach-omap2/board-overo.c | 6 ++++++
include/linux/i2c/twl4030.h | 24 +++++++++++++++++++++---
8 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 3073528..7842110 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -345,6 +345,12 @@ static struct omap_board_config_kernel sdp2430_config[] __initdata = {
};
+static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
+
static struct twl4030_usb_data sdp2430_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -354,6 +360,7 @@ static struct twl4030_platform_data sdp2430_twldata = {
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
+ .gpio = &sdp2430_gpio_data,
.keypad = &sdp2430_kp_data,
.usb = &sdp2430_usb_data,
};
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index e0c39c2..66f0f98 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -300,6 +300,12 @@ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
{ OMAP_TAG_LCD, &sdp3430_lcd_config },
};
+static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
+
static struct twl4030_usb_data sdp3430_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -309,6 +315,7 @@ static struct twl4030_platform_data sdp3430_twldata = {
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
+ .gpio = &sdp3430_gpio_data,
.keypad = &sdp3430_kp_data,
.usb = &sdp3430_usb_data,
};
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 219579b..48342f4 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -187,12 +187,19 @@ static struct twl4030_usb_data ldp_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
+static struct twl4030_gpio_platform_data ldp_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
+
static struct twl4030_platform_data ldp_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.usb = &ldp_usb_data,
+ .gpio = &ldp_gpio_data,
};
static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c
index be8348d..a921cf1 100644
--- a/arch/arm/mach-omap2/board-omap2evm.c
+++ b/arch/arm/mach-omap2/board-omap2evm.c
@@ -226,6 +226,12 @@ static struct omap_board_config_kernel omap2_evm_config[] __initdata = {
{ OMAP_TAG_LCD, &omap2_evm_lcd_config },
};
+static struct twl4030_gpio_platform_data omap2evm_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
+
static struct twl4030_usb_data omap2evm_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -237,6 +243,7 @@ static struct twl4030_platform_data omap2evm_twldata = {
/* platform_data for children goes here */
.keypad = &omap2evm_kp_data,
.usb = &omap2evm_usb_data,
+ .gpio = &omap2evm_gpio_data,
};
static struct i2c_board_info __initdata omap2evm_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index ae677b9..aa5e9a6 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -114,12 +114,24 @@ static struct twl4030_usb_data beagle_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
+static struct twl4030_gpio_platform_data beagle_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+
+ /* REVISIT: setup() should use twl gpio index
+ * - 0 as MMC card detect,
+ * - 1 as EHCI port overcurrent (active low)
+ */
+};
+
static struct twl4030_platform_data beagle_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.usb = &beagle_usb_data,
+ .gpio = &beagle_gpio_data,
};
static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 158138c..2c1d76f 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -90,6 +90,12 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
+static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
+
static struct twl4030_usb_data omap3evm_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -129,6 +135,7 @@ static struct twl4030_platform_data omap3evm_twldata = {
/* platform_data for children goes here */
.keypad = &omap3evm_kp_data,
.usb = &omap3evm_usb_data,
+ .gpio = &omap3evm_gpio_data,
};
static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 2e6d2c7..a490f15 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -145,6 +145,11 @@ static void __init overo_flash_init(void)
static struct omap_uart_config overo_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
+static struct twl4030_gpio_platform_data overo_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
static struct twl4030_usb_data overo_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
@@ -153,6 +158,7 @@ static struct twl4030_usb_data overo_usb_data = {
static struct twl4030_platform_data overo_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
+ .gpio = &overo_gpio_data,
.usb = &overo_usb_data,
};
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 8a12ff0..b80e8b6 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -52,6 +52,21 @@
#define TWL4030_MODULE_RTC 0x14
#define TWL4030_MODULE_SECURED_REG 0x15
+
+/* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
+struct twl4030_gpio_platform_data {
+ int gpio_base;
+ unsigned irq_base, irq_end;
+
+ /* for gpio-N, bit (1 << N) is set if pullup should be used */
+ u32 pullups;
+
+ int (*setup)(struct device *dev,
+ unsigned gpio, unsigned ngpio);
+ int (*teardown)(struct device *dev,
+ unsigned gpio, unsigned ngpio);
+};
+
struct twl4030_keypad_data {
int rows;
int cols;
@@ -71,9 +86,10 @@ struct twl4030_usb_data {
};
struct twl4030_platform_data {
- unsigned irq_base, irq_end;
- struct twl4030_keypad_data *keypad;
- struct twl4030_usb_data *usb;
+ unsigned irq_base, irq_end;
+ struct twl4030_gpio_platform_data *gpio;
+ struct twl4030_keypad_data *keypad;
+ struct twl4030_usb_data *usb;
/* REVISIT more to come ... _nothing_ should be hard-wired */
};
@@ -151,6 +167,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
/*
* Exported TWL4030 GPIO APIs
+ *
+ * WARNING -- use standard GPIO and IRQ calls instead; these will vanish.
*/
int twl4030_get_gpio_datain(int gpio);
int twl4030_request_gpio(int gpio);
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 08/23] twl4030 uses gpiolib
2008-09-30 10:05 ` [PATCH 07/23] twl4030 gpio platform data Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 09/23] i2c: move twl4030-madc to new registration style Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Make the twl4030 core create a platform device to which its
GPIO code will bind, with platform_data used to configure
board-specific behaviors and configuration.
Update the twl4030 GPIO code:
- Morph its gpio function code into a platform driver.
- Move away from IRQ (and GPIO) numbers hard-wired in headers.
- Hook up the twl4030 GPIO code to gpiolib.
- Start phasing out the older TWL-specific calls ... currently
those are used only by arch/arm/mach-omap2/hsmmc.c setup code.
- Use a mutex for locking, not a binary semaphore.
NOTE: more patches pending: (a) this doesn't use pdata->pullups
to initialize (currently hsmmc code always sets GPIO-0 pullup even
if the board has an external pullup); (b) there's a new gpio
request/free hook forthcoming in 2.6.28, which this should use;
(c) likewise there's a new gpio_to_irq() hook; (d) the irq_chip
set_type() mechanism needs to be supported; (e) needs to move over
to drivers/gpio; (f) upcoming threaded IRQ infrastructure should
be used, when that merges.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/Kconfig | 2 +-
drivers/i2c/chips/twl4030-core.c | 44 ++++++
drivers/i2c/chips/twl4030-gpio.c | 273 +++++++++++++++++++++++++++-----------
3 files changed, 238 insertions(+), 81 deletions(-)
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 121aec9..1a21388 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -159,7 +159,7 @@ config TWL4030_CORE
config TWL4030_GPIO
bool "TWL4030 GPIO Driver"
- depends on TWL4030_CORE
+ depends on TWL4030_CORE && GPIOLIB
config TWL4030_MADC
tristate "TWL4030 MADC Driver"
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 02be771..c9460f7 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -63,6 +63,12 @@
#define twl_has_usb() false
#endif
+#ifdef CONFIG_TWL4030_GPIO
+#define twl_has_gpio() true
+#else
+#define twl_has_gpio() false
+#endif
+
/* Primary Interrupt Handler on TWL4030 Registers */
/* Register Definitions */
@@ -656,6 +662,44 @@ static int add_children(struct twl4030_platform_data *pdata)
struct twl4030_client *twl = NULL;
int status = 0;
+ if (twl_has_gpio() && pdata->gpio) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM1];
+
+ pdev = platform_device_alloc("twl4030_gpio", -1);
+ if (!pdev)
+ status = -ENOMEM;
+
+ /* more driver model init */
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ /* device_init_wakeup(&pdev->dev, 1); */
+
+ status = platform_device_add_data(pdev, pdata->gpio,
+ sizeof(*pdata->gpio));
+ }
+
+ /* GPIO module IRQ */
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 0,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create gpio dev, %d\n",
+ status);
+ goto err;
+ }
+ }
+
if (twl_has_rtc()) {
pdev = platform_device_alloc("twl4030_rtc", -1);
if (pdev) {
diff --git a/drivers/i2c/chips/twl4030-gpio.c b/drivers/i2c/chips/twl4030-gpio.c
index b51bed0..0d4dd28 100644
--- a/drivers/i2c/chips/twl4030-gpio.c
+++ b/drivers/i2c/chips/twl4030-gpio.c
@@ -31,22 +31,31 @@
#include <linux/init.h>
#include <linux/time.h>
#include <linux/interrupt.h>
-#include <linux/random.h>
-#include <linux/syscalls.h>
+#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
-#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
#include <linux/i2c/twl4030-gpio.h>
-#include <linux/slab.h>
#include <mach/irqs.h>
#include <asm/mach/irq.h>
#include <mach/gpio.h>
#include <mach/mux.h>
-#include <linux/device.h>
+
+/* REVISIT when these symbols vanish elsewhere, remove them here too */
+#undef TWL4030_GPIO_IRQ_BASE
+#undef TWL4030_GPIO_IRQ_END
+#undef TWL4030_MODIRQ_GPIO
+
+static struct gpio_chip twl_gpiochip;
+static int twl4030_gpio_irq_base;
+static int twl4030_gpio_irq_end;
+
/* BitField Definitions */
@@ -130,7 +139,7 @@
#define GPIO_32_MASK 0x0003ffff
/* Data structures */
-static struct semaphore gpio_sem;
+static DEFINE_MUTEX(gpio_lock);
/* store usage of each GPIO. - each bit represents one GPIO */
static unsigned int gpio_usage_count;
@@ -147,7 +156,7 @@ static struct task_struct *gpio_unmask_thread;
/*
* Helper functions to read and write the GPIO ISR and IMR registers as
* 32-bit integers. Functions return 0 on success, non-zero otherwise.
- * The caller must hold a lock on gpio_sem.
+ * The caller must hold gpio_lock.
*/
static int gpio_read_isr(unsigned int *isr)
@@ -197,25 +206,25 @@ static int gpio_write_imr(unsigned int imr)
*/
static void twl4030_gpio_mask_and_ack(unsigned int irq)
{
- int gpio = irq - TWL4030_GPIO_IRQ_BASE;
+ int gpio = irq - twl4030_gpio_irq_base;
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
/* mask */
gpio_imr_shadow |= (1 << gpio);
gpio_write_imr(gpio_imr_shadow);
/* ack */
gpio_write_isr(1 << gpio);
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
}
static void twl4030_gpio_unmask(unsigned int irq)
{
- int gpio = irq - TWL4030_GPIO_IRQ_BASE;
+ int gpio = irq - twl4030_gpio_irq_base;
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
gpio_imr_shadow &= ~(1 << gpio);
gpio_write_imr(gpio_imr_shadow);
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
}
/*
@@ -234,7 +243,7 @@ static void twl4030_gpio_mask_irqchip(unsigned int irq) {}
static void twl4030_gpio_unmask_irqchip(unsigned int irq)
{
- int gpio = irq - TWL4030_GPIO_IRQ_BASE;
+ int gpio = irq - twl4030_gpio_irq_base;
gpio_pending_unmask |= (1 << gpio);
if (gpio_unmask_thread && gpio_unmask_thread->state != TASK_RUNNING)
@@ -242,7 +251,7 @@ static void twl4030_gpio_unmask_irqchip(unsigned int irq)
}
static struct irq_chip twl4030_gpio_irq_chip = {
- .name = "twl4030-gpio",
+ .name = "twl4030",
.ack = twl4030_gpio_mask_and_ack_irqchip,
.mask = twl4030_gpio_mask_irqchip,
.unmask = twl4030_gpio_unmask_irqchip,
@@ -297,21 +306,26 @@ int twl4030_request_gpio(int gpio)
if (unlikely(gpio >= TWL4030_GPIO_MAX))
return -EPERM;
- down(&gpio_sem);
- if (gpio_usage_count & (0x1 << gpio))
+ ret = gpio_request(twl_gpiochip.base + gpio, NULL);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&gpio_lock);
+ if (gpio_usage_count & (0x1 << gpio)) {
ret = -EBUSY;
- else {
+ } else {
/* First time usage? - switch on GPIO module */
if (!gpio_usage_count) {
- ret =
- gpio_twl4030_write(REG_GPIO_CTRL,
+ ret = gpio_twl4030_write(REG_GPIO_CTRL,
MASK_GPIO_CTRL_GPIO_ON);
ret = gpio_twl4030_write(REG_GPIO_SIH_CTRL, 0x00);
}
if (!ret)
gpio_usage_count |= (0x1 << gpio);
+ else
+ gpio_free(twl_gpiochip.base + gpio);
}
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
EXPORT_SYMBOL(twl4030_request_gpio);
@@ -326,18 +340,20 @@ int twl4030_free_gpio(int gpio)
if (unlikely(gpio >= TWL4030_GPIO_MAX))
return -EPERM;
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
- if ((gpio_usage_count & (0x1 << gpio)) == 0)
+ if ((gpio_usage_count & (0x1 << gpio)) == 0) {
ret = -EPERM;
- else
+ } else {
gpio_usage_count &= ~(0x1 << gpio);
+ gpio_free(twl_gpiochip.base + gpio);
+ }
/* Last time usage? - switch off GPIO module */
- if (!gpio_usage_count)
+ if (ret == 0 && !gpio_usage_count)
ret = gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
EXPORT_SYMBOL(twl4030_free_gpio);
@@ -345,21 +361,18 @@ EXPORT_SYMBOL(twl4030_free_gpio);
/*
* Set direction for TWL4030 GPIO
*/
-int twl4030_set_gpio_direction(int gpio, int is_input)
+static int twl4030_set_gpio_direction(int gpio, int is_input)
{
u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
u8 d_msk = MASK_GPIODATADIR_GPIOxDIR(GET_GPIO_DATA_OFF(gpio));
u8 reg = 0;
- u8 base = 0;
+ u8 base = REG_GPIODATADIR1 + d_bnk;
int ret = 0;
- if (unlikely((gpio >= TWL4030_GPIO_MAX)
- || !(gpio_usage_count & (0x1 << gpio))))
+ if (unlikely(!(gpio_usage_count & (0x1 << gpio))))
return -EPERM;
- base = REG_GPIODATADIR1 + d_bnk;
-
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
if (ret >= 0) {
if (is_input)
@@ -369,23 +382,21 @@ int twl4030_set_gpio_direction(int gpio, int is_input)
ret = gpio_twl4030_write(base, reg);
}
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
-EXPORT_SYMBOL(twl4030_set_gpio_direction);
/*
* To enable/disable GPIO pin on TWL4030
*/
-int twl4030_set_gpio_dataout(int gpio, int enable)
+static int twl4030_set_gpio_dataout(int gpio, int enable)
{
u8 d_bnk = GET_GPIO_DATA_BANK(gpio);
u8 d_msk = MASK_GPIODATAOUT_GPIOxOUT(GET_GPIO_DATA_OFF(gpio));
u8 base = 0;
int ret = 0;
- if (unlikely((gpio >= TWL4030_GPIO_MAX)
- || !(gpio_usage_count & (0x1 << gpio))))
+ if (unlikely(!(gpio_usage_count & (0x1 << gpio))))
return -EPERM;
if (enable)
@@ -393,12 +404,11 @@ int twl4030_set_gpio_dataout(int gpio, int enable)
else
base = REG_CLEARGPIODATAOUT1 + d_bnk;
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_write(base, d_msk);
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
-EXPORT_SYMBOL(twl4030_set_gpio_dataout);
/*
* To get the status of a GPIO pin on TWL4030
@@ -415,9 +425,9 @@ int twl4030_get_gpio_datain(int gpio)
return -EPERM;
base = REG_GPIODATAIN1 + d_bnk;
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
if (ret > 0)
ret = (ret >> d_off) & 0x1;
@@ -425,6 +435,7 @@ int twl4030_get_gpio_datain(int gpio)
}
EXPORT_SYMBOL(twl4030_get_gpio_datain);
+#if 0
/*
* Configure PULL type for a GPIO pin on TWL4030
*/
@@ -447,7 +458,7 @@ int twl4030_set_gpio_pull(int gpio, int pull_dircn)
else if (pull_dircn == TWL4030_GPIO_PULL_UP)
c_msk = MASK_GPIOPUPDCTR1_GPIOxPU(c_off);
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
if (ret >= 0) {
/* clear the previous up/down values */
@@ -457,13 +468,15 @@ int twl4030_set_gpio_pull(int gpio, int pull_dircn)
reg |= c_msk;
ret = gpio_twl4030_write(base, reg);
}
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
-EXPORT_SYMBOL(twl4030_set_gpio_pull);
+#endif
/*
* Configure Edge control for a GPIO pin on TWL4030
+ *
+ * FIXME this should just be the irq_chip.set_type() method
*/
int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
{
@@ -486,7 +499,7 @@ int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
if (edge & TWL4030_GPIO_EDGE_FALLING)
c_msk |= MASK_GPIO_EDR1_GPIOxFALLING(c_off);
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
if (ret >= 0) {
/* clear the previous rising/falling values */
@@ -497,7 +510,7 @@ int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
reg |= c_msk;
ret = gpio_twl4030_write(base, reg);
}
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
EXPORT_SYMBOL(twl4030_set_gpio_edge_ctrl);
@@ -518,7 +531,7 @@ int twl4030_set_gpio_debounce(int gpio, int enable)
return -EPERM;
base = REG_GPIO_DEBEN1 + d_bnk;
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
if (ret >= 0) {
if (enable)
@@ -528,11 +541,12 @@ int twl4030_set_gpio_debounce(int gpio, int enable)
ret = gpio_twl4030_write(base, reg);
}
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return ret;
}
EXPORT_SYMBOL(twl4030_set_gpio_debounce);
+#if 0
/*
* Configure Card detect for GPIO pin on TWL4030
*/
@@ -549,7 +563,7 @@ int twl4030_set_gpio_card_detect(int gpio, int enable)
return -EPERM;
}
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(REG_GPIO_CTRL);
if (ret >= 0) {
if (enable)
@@ -559,10 +573,10 @@ int twl4030_set_gpio_card_detect(int gpio, int enable)
ret = gpio_twl4030_write(REG_GPIO_CTRL, reg);
}
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
return (ret);
}
-EXPORT_SYMBOL(twl4030_set_gpio_card_detect);
+#endif
/* MODULE FUNCTIONS */
@@ -590,7 +604,7 @@ static int twl4030_gpio_unmask_thread(void *data)
gpio_pending_unmask = 0;
local_irq_enable();
- for (irq = TWL4030_GPIO_IRQ_BASE; 0 != gpio_unmask;
+ for (irq = twl4030_gpio_irq_base; 0 != gpio_unmask;
gpio_unmask >>= 1, irq++) {
if (gpio_unmask & 0x1)
twl4030_gpio_unmask(irq);
@@ -677,12 +691,12 @@ static void do_twl4030_gpio_module_irq(unsigned int irq, irq_desc_t *desc)
kstat_cpu(cpu).irqs[irq]++;
local_irq_enable();
- down(&gpio_sem);
+ mutex_lock(&gpio_lock);
if (gpio_read_isr(&gpio_isr))
gpio_isr = 0;
- up(&gpio_sem);
+ mutex_unlock(&gpio_lock);
- for (gpio_irq = TWL4030_GPIO_IRQ_BASE; 0 != gpio_isr;
+ for (gpio_irq = twl4030_gpio_irq_base; 0 != gpio_isr;
gpio_isr >>= 1, gpio_irq++) {
if (gpio_isr & 0x1) {
irq_desc_t *d = irq_desc + gpio_irq;
@@ -698,19 +712,60 @@ static void do_twl4030_gpio_module_irq(unsigned int irq, irq_desc_t *desc)
}
}
-/* TWL4030 Initialization module */
-static int __init gpio_twl4030_init(void)
+/*----------------------------------------------------------------------*/
+
+static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ return twl4030_set_gpio_direction(offset, 1);
+}
+
+static int twl_get(struct gpio_chip *chip, unsigned offset)
+{
+ int status = twl4030_get_gpio_datain(offset);
+
+ return (status < 0) ? 0 : status;
+}
+
+static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+ twl4030_set_gpio_dataout(offset, value);
+ return twl4030_set_gpio_direction(offset, 0);
+}
+
+static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
{
+ twl4030_set_gpio_dataout(offset, value);
+}
+
+static struct gpio_chip twl_gpiochip = {
+ .label = "twl4030",
+ .owner = THIS_MODULE,
+ .direction_input = twl_direction_in,
+ .get = twl_get,
+ .direction_output = twl_direction_out,
+ .set = twl_set,
+ .can_sleep = 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int gpio_twl4030_remove(struct platform_device *pdev);
+
+static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+{
+ struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
int ret;
int irq = 0;
- /* init the global locking sem */
- sema_init(&gpio_sem, 1);
-
/* All GPIO interrupts are initially masked */
gpio_pending_unmask = 0;
gpio_imr_shadow = GPIO_32_MASK;
ret = gpio_write_imr(gpio_imr_shadow);
+
+ twl4030_gpio_irq_base = pdata->irq_base;
+ twl4030_gpio_irq_end = pdata->irq_end;
+
+ /* REVISIT skip most of this if the irq range is empty... */
if (!ret) {
/*
* Create a kernel thread to handle deferred unmasking of gpio
@@ -719,50 +774,88 @@ static int __init gpio_twl4030_init(void)
gpio_unmask_thread = kthread_create(twl4030_gpio_unmask_thread,
NULL, "twl4030 gpio");
if (!gpio_unmask_thread) {
- printk(KERN_ERR
- "%s: could not create twl4030 gpio unmask"
- " thread!\n", __func__);
+ dev_err(&pdev->dev,
+ "could not create twl4030 gpio unmask"
+ " thread!\n");
ret = -ENOMEM;
}
}
if (!ret) {
/* install an irq handler for each of the gpio interrupts */
- for (irq = TWL4030_GPIO_IRQ_BASE; irq < TWL4030_GPIO_IRQ_END;
- irq++) {
+ for (irq = twl4030_gpio_irq_base; irq < twl4030_gpio_irq_end;
+ irq++) {
set_irq_chip(irq, &twl4030_gpio_irq_chip);
set_irq_handler(irq, do_twl4030_gpio_irq);
set_irq_flags(irq, IRQF_VALID);
}
+ /* gpio module IRQ */
+ irq = platform_get_irq(pdev, 0);
+
/*
* Install an irq handler to demultiplex the gpio module
* interrupt.
*/
- set_irq_chip(TWL4030_MODIRQ_GPIO,
- &twl4030_gpio_module_irq_chip);
- set_irq_chained_handler(TWL4030_MODIRQ_GPIO,
- do_twl4030_gpio_module_irq);
+ set_irq_chip(irq, &twl4030_gpio_module_irq_chip);
+ set_irq_chained_handler(irq, do_twl4030_gpio_module_irq);
wake_up_process(gpio_unmask_thread);
+
+ dev_info(&pdev->dev, "IRQ %d chains IRQs %d..%d\n", irq,
+ twl4030_gpio_irq_base, twl4030_gpio_irq_end - 1);
+ }
+
+ if (!ret) {
+ twl_gpiochip.base = pdata->gpio_base;
+ twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
+ twl_gpiochip.dev = &pdev->dev;
+
+ ret = gpiochip_add(&twl_gpiochip);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "could not register gpiochip, %d\n",
+ ret);
+ twl_gpiochip.ngpio = 0;
+ gpio_twl4030_remove(pdev);
+ } else if (pdata->setup) {
+ int status;
+
+ status = pdata->setup(&pdev->dev,
+ pdata->gpio_base, TWL4030_GPIO_MAX);
+ if (status)
+ dev_dbg(&pdev->dev, "setup --> %d\n", status);
+ }
}
- printk(KERN_INFO "TWL4030 GPIO Demux: IRQ Range %d to %d,"
- " Initialization %s\n", TWL4030_GPIO_IRQ_BASE,
- TWL4030_GPIO_IRQ_END, (ret) ? "Failed" : "Success");
return ret;
}
-/* TWL GPIO exit module */
-static void __exit gpio_twl4030_exit(void)
+static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
{
+ struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+ int status;
int irq;
+ if (pdata->teardown) {
+ status = pdata->teardown(&pdev->dev,
+ pdata->gpio_base, TWL4030_GPIO_MAX);
+ if (status) {
+ dev_dbg(&pdev->dev, "teardown --> %d\n", status);
+ return status;
+ }
+ }
+
+ status = gpiochip_remove(&twl_gpiochip);
+ if (status < 0)
+ return status;
+
/* uninstall the gpio demultiplexing interrupt handler */
- set_irq_handler(TWL4030_MODIRQ_GPIO, NULL);
- set_irq_flags(TWL4030_MODIRQ_GPIO, 0);
+ irq = platform_get_irq(pdev, 0);
+ set_irq_handler(irq, NULL);
+ set_irq_flags(irq, 0);
/* uninstall the irq handler for each of the gpio interrupts */
- for (irq = TWL4030_GPIO_IRQ_BASE; irq < TWL4030_GPIO_IRQ_END; irq++) {
+ for (irq = twl4030_gpio_irq_base; irq < twl4030_gpio_irq_end; irq++) {
set_irq_handler(irq, NULL);
set_irq_flags(irq, 0);
}
@@ -772,12 +865,32 @@ static void __exit gpio_twl4030_exit(void)
kthread_stop(gpio_unmask_thread);
gpio_unmask_thread = NULL;
}
+
+ return 0;
}
+/* Note: this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl4030_gpio");
+
+static struct platform_driver gpio_twl4030_driver = {
+ .driver.name = "twl4030_gpio",
+ .driver.owner = THIS_MODULE,
+ .probe = gpio_twl4030_probe,
+ .remove = __devexit_p(gpio_twl4030_remove),
+};
+
+static int __init gpio_twl4030_init(void)
+{
+ return platform_driver_register(&gpio_twl4030_driver);
+}
module_init(gpio_twl4030_init);
+
+static void __exit gpio_twl4030_exit(void)
+{
+ platform_driver_unregister(&gpio_twl4030_driver);
+}
module_exit(gpio_twl4030_exit);
-MODULE_ALIAS("i2c:twl4030-gpio");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_DESCRIPTION("GPIO interface for TWL4030");
MODULE_LICENSE("GPL");
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 09/23] i2c: move twl4030-madc to new registration style
2008-09-30 10:05 ` [PATCH 08/23] twl4030 uses gpiolib Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 10/23] minor twl4030-core cleanups Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi, Mikko Ylinen
Moving twl4030-madc to new style registration just like
the other twl4030 children.
Cc: Mikko Ylinen <mikko.k.ylinen@nokia.com>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/mach-omap2/board-2430sdp.c | 5 +
arch/arm/mach-omap2/board-3430sdp.c | 5 +
arch/arm/mach-omap2/board-ldp.c | 5 +
arch/arm/mach-omap2/board-omap2evm.c | 5 +
arch/arm/mach-omap2/board-omap3evm.c | 5 +
drivers/i2c/chips/twl4030-core.c | 27 ++++
drivers/i2c/chips/twl4030-madc.c | 243 +++++++++++++++++++++-------------
include/linux/i2c/twl4030.h | 5 +
8 files changed, 209 insertions(+), 91 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 7842110..cea2540 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -355,12 +355,17 @@ static struct twl4030_usb_data sdp2430_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
+static struct twl4030_madc_platform_data sdp2430_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data sdp2430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.gpio = &sdp2430_gpio_data,
+ .madc = &sdp2430_madc_data,
.keypad = &sdp2430_kp_data,
.usb = &sdp2430_usb_data,
};
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 66f0f98..661d5d0 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -310,12 +310,17 @@ static struct twl4030_usb_data sdp3430_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
+static struct twl4030_madc_platform_data sdp3430_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data sdp3430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.gpio = &sdp3430_gpio_data,
+ .madc = &sdp3430_madc_data,
.keypad = &sdp3430_kp_data,
.usb = &sdp3430_usb_data,
};
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 48342f4..a0e2c7a 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -193,11 +193,16 @@ static struct twl4030_gpio_platform_data ldp_gpio_data = {
.irq_end = TWL4030_GPIO_IRQ_END,
};
+static struct twl4030_madc_platform_data ldp_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data ldp_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
+ .madc = &ldp_madc_data,
.usb = &ldp_usb_data,
.gpio = &ldp_gpio_data,
};
diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c
index a921cf1..9f19c34 100644
--- a/arch/arm/mach-omap2/board-omap2evm.c
+++ b/arch/arm/mach-omap2/board-omap2evm.c
@@ -236,12 +236,17 @@ static struct twl4030_usb_data omap2evm_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
+static struct twl4030_madc_platform_data omap2evm_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data omap2evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.keypad = &omap2evm_kp_data,
+ .madc = &omap2evm_madc_data,
.usb = &omap2evm_usb_data,
.gpio = &omap2evm_gpio_data,
};
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 2c1d76f..a9ff8d1 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -128,12 +128,17 @@ static struct twl4030_keypad_data omap3evm_kp_data = {
.irq = TWL4030_MODIRQ_KEYPAD,
};
+static struct twl4030_madc_platform_data omap3evm_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data omap3evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.keypad = &omap3evm_kp_data,
+ .madc = &omap3evm_madc_data,
.usb = &omap3evm_usb_data,
.gpio = &omap3evm_gpio_data,
};
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index c9460f7..79d4d82 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -69,6 +69,12 @@
#define twl_has_gpio() false
#endif
+#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
+#define twl_has_madc() true
+#else
+#define twl_has_madc() false
+#endif
+
/* Primary Interrupt Handler on TWL4030 Registers */
/* Register Definitions */
@@ -772,6 +778,27 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
+ if (twl_has_madc() && pdata->madc) {
+ pdev = platform_device_alloc("twl4030_madc", -1);
+ if (pdev) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM2];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->madc,
+ sizeof(*pdata->madc));
+ if (status < 0) {
+ platform_device_put(pdev);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0)
+ platform_device_put(pdev);
+ } else {
+ status = -ENOMEM;
+ goto err;
+ }
+ }
+
err:
pr_err("failed to add twl4030's children\n");
return status;
diff --git a/drivers/i2c/chips/twl4030-madc.c b/drivers/i2c/chips/twl4030-madc.c
index 743db74..bff2554 100644
--- a/drivers/i2c/chips/twl4030-madc.c
+++ b/drivers/i2c/chips/twl4030-madc.c
@@ -29,6 +29,7 @@
#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>
@@ -37,13 +38,16 @@
#define TWL4030_MADC_PFX "twl4030-madc: "
-static struct twl4030_madc_data {
+struct twl4030_madc_data {
+ struct device *dev;
struct mutex lock;
struct work_struct ws;
struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
-} twl4030_madc;
+ int imr;
+ int isr;
+};
-static const char irq_pin = 1; /* XXX Read from platfrom data */
+static struct twl4030_madc_data *the_madc;
static
const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
@@ -66,35 +70,43 @@ const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
},
};
-static void twl4030_madc_read(u8 reg, u8 *val)
+static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
{
- int ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, val, reg);
- if (ret)
- printk(KERN_ERR TWL4030_MADC_PFX
- "unable to read register 0x%X\n", 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;
}
-static void twl4030_madc_write(u8 reg, u8 val)
+static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 val)
{
- int ret = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
+ int ret;
+
+ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
if (ret)
- printk(KERN_ERR TWL4030_MADC_PFX
- "unable to write register 0x%X\n", reg);
+ dev_err(madc->dev, "unable to write register 0x%X\n", reg);
}
-static int twl4030_madc_channel_raw_read(u8 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 */
- twl4030_madc_read(reg+1, &msb);
- twl4030_madc_read(reg, &lsb);
+ 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(u8 reg_base, u16 channels, int *buf)
+static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
+ u8 reg_base, u16 channels, int *buf)
{
int count = 0;
u8 reg, i;
@@ -105,47 +117,40 @@ static int twl4030_madc_read_channels(u8 reg_base, u16 channels, int *buf)
for (i = 0; i < TWL4030_MADC_MAX_CHANNELS; i++) {
if (channels & (1<<i)) {
reg = reg_base + 2*i;
- buf[i] = twl4030_madc_channel_raw_read(reg);
+ buf[i] = twl4030_madc_channel_raw_read(madc, reg);
count++;
}
}
return count;
}
-static void twl4030_madc_enable_irq(int id)
+static void twl4030_madc_enable_irq(struct twl4030_madc_data *madc, int id)
{
u8 val;
- static u8 imr = (irq_pin == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
-
- twl4030_madc_read(imr, &val);
+ val = twl4030_madc_read(madc, madc->imr);
val &= ~(1 << id);
- twl4030_madc_write(imr, val);
+ twl4030_madc_write(madc, madc->imr, val);
}
-static void twl4030_madc_disable_irq(int id)
+static void twl4030_madc_disable_irq(struct twl4030_madc_data *madc, int id)
{
u8 val;
- static u8 imr = (irq_pin == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
-
- twl4030_madc_read(imr, &val);
+ val = twl4030_madc_read(madc, madc->imr);
val |= (1 << id);
- twl4030_madc_write(imr, val);
+ twl4030_madc_write(madc, madc->imr, val);
}
-static irqreturn_t twl4030_madc_irq_handler(int irq, void *madc_dev)
+static irqreturn_t twl4030_madc_irq_handler(int irq, void *_madc)
{
+ struct twl4030_madc_data *madc = _madc;
u8 isr_val, imr_val;
- static u8 isr, imr;
int i;
- imr = (irq_pin == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
- isr = (irq_pin == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
-
/* Use COR to ack interrupts since we have no shared IRQs in ISRx */
- twl4030_madc_read(isr, &isr_val);
- twl4030_madc_read(imr, &imr_val);
+ isr_val = twl4030_madc_read(madc, madc->isr);
+ imr_val = twl4030_madc_read(madc, madc->imr);
isr_val &= ~imr_val;
@@ -154,11 +159,11 @@ static irqreturn_t twl4030_madc_irq_handler(int irq, void *madc_dev)
if (!(isr_val & (1<<i)))
continue;
- twl4030_madc_disable_irq(i);
- twl4030_madc.requests[i].result_pending = 1;
+ twl4030_madc_disable_irq(madc, i);
+ madc->requests[i].result_pending = 1;
}
- schedule_work(&twl4030_madc.ws);
+ schedule_work(&madc->ws);
return IRQ_HANDLED;
}
@@ -166,14 +171,16 @@ static irqreturn_t twl4030_madc_irq_handler(int irq, void *madc_dev)
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;
- mutex_lock(&twl4030_madc.lock);
+ madc = container_of(ws, struct twl4030_madc_data, ws);
+ mutex_lock(&madc->lock);
for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
- r = &twl4030_madc.requests[i];
+ r = &madc->requests[i];
/* No pending results for this method, move to next one */
if (!r->result_pending)
@@ -182,7 +189,7 @@ static void twl4030_madc_work(struct work_struct *ws)
method = &twl4030_conversion_methods[r->method];
/* Read results */
- len = twl4030_madc_read_channels(method->rbase,
+ len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf);
/* Return results to caller */
@@ -196,23 +203,25 @@ static void twl4030_madc_work(struct work_struct *ws)
r->active = 0;
}
- mutex_unlock(&twl4030_madc.lock);
+ mutex_unlock(&madc->lock);
}
-static int twl4030_madc_set_irq(struct twl4030_madc_request *req)
+static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
+ struct twl4030_madc_request *req)
{
struct twl4030_madc_request *p;
- p = &twl4030_madc.requests[req->method];
+ p = &madc->requests[req->method];
memcpy(p, req, sizeof *req);
- twl4030_madc_enable_irq(req->method);
+ twl4030_madc_enable_irq(madc, req->method);
return 0;
}
-static inline void twl4030_madc_start_conversion(int conv_method)
+static inline void twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
+ int conv_method)
{
const struct twl4030_madc_conversion_method *method;
@@ -221,7 +230,7 @@ static inline void twl4030_madc_start_conversion(int conv_method)
switch (conv_method) {
case TWL4030_MADC_SW1:
case TWL4030_MADC_SW2:
- twl4030_madc_write(method->ctrl, TWL4030_MADC_SW_START);
+ twl4030_madc_write(madc, method->ctrl, TWL4030_MADC_SW_START);
break;
case TWL4030_MADC_RT:
default:
@@ -229,14 +238,16 @@ static inline void twl4030_madc_start_conversion(int conv_method)
}
}
-static void twl4030_madc_wait_conversion_ready_ms(u8 *time, u8 status_reg)
+static void twl4030_madc_wait_conversion_ready_ms(
+ struct twl4030_madc_data *madc,
+ u8 *time, u8 status_reg)
{
u8 reg = 0;
do {
msleep(1);
(*time)--;
- twl4030_madc_read(status_reg, ®);
+ reg = twl4030_madc_read(madc, status_reg);
} while (((reg & TWL4030_MADC_BUSY) && !(reg & TWL4030_MADC_EOC_SW)) &&
(*time != 0));
}
@@ -251,7 +262,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
return -EINVAL;
/* Do we have a conversion request ongoing */
- if (twl4030_madc.requests[req->method].active)
+ if (the_madc->requests[req->method].active)
return -EBUSY;
ch_msb = (req->channels >> 8) & 0xff;
@@ -259,22 +270,22 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
method = &twl4030_conversion_methods[req->method];
- mutex_lock(&twl4030_madc.lock);
+ mutex_lock(&the_madc->lock);
/* Select channels to be converted */
- twl4030_madc_write(method->sel + 1, ch_msb);
- twl4030_madc_write(method->sel, ch_lsb);
+ twl4030_madc_write(the_madc, method->sel + 1, ch_msb);
+ twl4030_madc_write(the_madc, method->sel, ch_lsb);
/* Select averaging for all channels if do_avg is set */
if (req->do_avg) {
- twl4030_madc_write(method->avg + 1, ch_msb);
- twl4030_madc_write(method->avg, ch_lsb);
+ twl4030_madc_write(the_madc, method->avg + 1, ch_msb);
+ twl4030_madc_write(the_madc, method->avg, ch_lsb);
}
if ((req->type == TWL4030_MADC_IRQ_ONESHOT) && (req->func_cb != NULL)) {
- twl4030_madc_set_irq(req);
- twl4030_madc_start_conversion(req->method);
- twl4030_madc.requests[req->method].active = 1;
+ twl4030_madc_set_irq(the_madc, req);
+ twl4030_madc_start_conversion(the_madc, req->method);
+ the_madc->requests[req->method].active = 1;
ret = 0;
goto out;
}
@@ -285,32 +296,33 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
goto out;
}
- twl4030_madc_start_conversion(req->method);
- twl4030_madc.requests[req->method].active = 1;
+ twl4030_madc_start_conversion(the_madc, req->method);
+ the_madc->requests[req->method].active = 1;
/* Wait until conversion is ready (ctrl register returns EOC) */
wait_time = 50;
- twl4030_madc_wait_conversion_ready_ms(&wait_time, method->ctrl);
+ twl4030_madc_wait_conversion_ready_ms(the_madc,
+ &wait_time, method->ctrl);
if (wait_time == 0) {
- printk(KERN_ERR TWL4030_MADC_PFX "conversion timeout!\n");
+ dev_dbg(the_madc->dev, "conversion timeout!\n");
ret = -EAGAIN;
goto out;
}
- ret = twl4030_madc_read_channels(method->rbase, req->channels,
+ ret = twl4030_madc_read_channels(the_madc, method->rbase, req->channels,
req->rbuf);
- twl4030_madc.requests[req->method].active = 0;
+ the_madc->requests[req->method].active = 0;
out:
- mutex_unlock(&twl4030_madc.lock);
+ mutex_unlock(&the_madc->lock);
return ret;
}
-
EXPORT_SYMBOL(twl4030_madc_conversion);
-static int twl4030_madc_set_current_generator(int chan, int on)
+static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
+ int chan, int on)
{
int ret;
u8 regval;
@@ -332,16 +344,16 @@ static int twl4030_madc_set_current_generator(int chan, int on)
return ret;
}
-static int twl4030_madc_set_power(int on)
+static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
{
u8 regval;
- twl4030_madc_read(TWL4030_MADC_CTRL1, ®val);
+ regval = twl4030_madc_read(madc, TWL4030_MADC_CTRL1);
if (on)
regval |= TWL4030_MADC_MADCON;
else
regval &= ~TWL4030_MADC_MADCON;
- twl4030_madc_write(TWL4030_MADC_CTRL1, regval);
+ twl4030_madc_write(madc, TWL4030_MADC_CTRL1, regval);
return 0;
}
@@ -354,7 +366,7 @@ static int twl4030_madc_ioctl(struct inode *inode, struct file *filp,
ret = copy_from_user(&par, (void __user *) arg, sizeof(par));
if (ret) {
- printk(KERN_ERR TWL4030_MADC_PFX "copy_from_user: %d\n", ret);
+ dev_dbg(the_madc->dev, "copy_from_user: %d\n", ret);
return -EACCES;
}
@@ -364,7 +376,7 @@ static int twl4030_madc_ioctl(struct inode *inode, struct file *filp,
if (par.channel >= TWL4030_MADC_MAX_CHANNELS)
return -EINVAL;
- req.channels = (1<<par.channel);
+ req.channels = (1 << par.channel);
req.do_avg = par.average;
req.method = TWL4030_MADC_SW1;
req.func_cb = NULL;
@@ -384,7 +396,7 @@ static int twl4030_madc_ioctl(struct inode *inode, struct file *filp,
ret = copy_to_user((void __user *) arg, &par, sizeof(par));
if (ret) {
- printk(KERN_ERR TWL4030_MADC_PFX "copy_to_user: %d\n", ret);
+ dev_dbg(the_madc->dev, "copy_to_user: %d\n", ret);
return -EACCES;
}
@@ -398,22 +410,37 @@ static struct file_operations twl4030_madc_fileops = {
static struct miscdevice twl4030_madc_device = {
.minor = MISC_DYNAMIC_MINOR,
- .name = "twl4030-adc",
+ .name = "twl4030-madc",
.fops = &twl4030_madc_fileops
};
-static int __init twl4030_madc_init(void)
+static int __init twl4030_madc_probe(struct platform_device *pdev)
{
+ struct twl4030_madc_data *madc;
+ struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
int ret;
u8 regval;
+ madc = kzalloc(sizeof *madc, GFP_KERNEL);
+ if (!madc)
+ return -ENOMEM;
+
+ if (!pdata) {
+ dev_dbg(&pdev->dev, "platform_data not available\n");
+ ret = -EINVAL;
+ goto err_pdata;
+ }
+
+ madc->imr = (pdata->irq_line == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
+ madc->isr = (pdata->irq_line == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
+
ret = misc_register(&twl4030_madc_device);
- if (ret == -1) {
- printk(KERN_ERR TWL4030_MADC_PFX "misc_register() failed!\n");
- return ret;
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not register misc_device\n");
+ goto err_misc;
}
- twl4030_madc_set_power(1);
- twl4030_madc_set_current_generator(0, 1);
+ twl4030_madc_set_power(madc, 1);
+ twl4030_madc_set_current_generator(madc, 0, 1);
ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
®val, TWL4030_BCI_BCICTL1);
@@ -424,32 +451,66 @@ static int __init twl4030_madc_init(void)
regval, TWL4030_BCI_BCICTL1);
ret = request_irq(TWL4030_MODIRQ_MADC, twl4030_madc_irq_handler,
- IRQF_DISABLED, "twl4030_madc", &twl4030_madc);
- if (ret)
- printk(KERN_ERR TWL4030_MADC_PFX "request_irq: %d\n", ret);
+ IRQF_DISABLED, "twl4030_madc", madc);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq\n");
+ goto err_irq;
+ }
- mutex_init(&twl4030_madc.lock);
+ platform_set_drvdata(pdev, madc);
+ mutex_init(&madc->lock);
+ INIT_WORK(&madc->ws, twl4030_madc_work);
- INIT_WORK(&twl4030_madc.ws, twl4030_madc_work);
+ the_madc = madc;
- printk(KERN_INFO TWL4030_MADC_PFX "initialised\n");
+ return 0;
+
+err_irq:
+ misc_deregister(&twl4030_madc_device);
+
+err_misc:
+err_pdata:
+ kfree(madc);
return ret;
}
-static void __exit twl4030_madc_exit(void)
+static int __exit twl4030_madc_remove(struct platform_device *pdev)
{
- twl4030_madc_set_power(0);
- twl4030_madc_set_current_generator(0, 0);
- free_irq(TWL4030_MODIRQ_MADC, &twl4030_madc);
- cancel_work_sync(&twl4030_madc.ws);
+ struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
+
+ twl4030_madc_set_power(madc, 0);
+ twl4030_madc_set_current_generator(madc, 0, 0);
+ free_irq(TWL4030_MODIRQ_MADC, madc);
+ cancel_work_sync(&madc->ws);
misc_deregister(&twl4030_madc_device);
+
+ return 0;
}
+static struct platform_driver twl4030_madc_driver = {
+ .probe = twl4030_madc_probe,
+ .remove = __exit_p(twl4030_madc_remove),
+ .driver = {
+ .name = "twl4030_madc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init twl4030_madc_init(void)
+{
+ return platform_driver_register(&twl4030_madc_driver);
+}
module_init(twl4030_madc_init);
+
+static void __exit twl4030_madc_exit(void)
+{
+ platform_driver_unregister(&twl4030_madc_driver);
+}
module_exit(twl4030_madc_exit);
-MODULE_ALIAS("i2c:twl4030-adc");
+MODULE_ALIAS("platform:twl4030-madc");
MODULE_AUTHOR("Nokia Corporation");
MODULE_DESCRIPTION("twl4030 ADC driver");
MODULE_LICENSE("GPL");
+
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index b80e8b6..404300c 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -67,6 +67,10 @@ struct twl4030_gpio_platform_data {
unsigned gpio, unsigned ngpio);
};
+struct twl4030_madc_platform_data {
+ int irq_line;
+};
+
struct twl4030_keypad_data {
int rows;
int cols;
@@ -88,6 +92,7 @@ struct twl4030_usb_data {
struct twl4030_platform_data {
unsigned irq_base, irq_end;
struct twl4030_gpio_platform_data *gpio;
+ struct twl4030_madc_platform_data *madc;
struct twl4030_keypad_data *keypad;
struct twl4030_usb_data *usb;
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 10/23] minor twl4030-core cleanups
2008-09-30 10:05 ` [PATCH 09/23] i2c: move twl4030-madc to new registration style Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 11/23] provide detailed diagnostics in add_children() Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Minor twl4030-core cleanups: alphabetize the creation of the
new sub-function nodes; wrap an #if around the OMAP-only part
(to get more general build testing when this goes upstream);
remove reference to undocumented "twl3040" variant.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Moved gpio before keypad driver due to alphabetic order.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-core.c | 103 +++++++++++++++++++------------------
1 files changed, 53 insertions(+), 50 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 79d4d82..22850a8 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -45,24 +45,12 @@
#define DRIVER_NAME "twl4030"
-#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
-#define twl_has_rtc() true
-#else
-#define twl_has_rtc() false
-#endif
-
#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
#define twl_has_keypad() true
#else
#define twl_has_keypad() false
#endif
-#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
-#define twl_has_usb() true
-#else
-#define twl_has_usb() false
-#endif
-
#ifdef CONFIG_TWL4030_GPIO
#define twl_has_gpio() true
#else
@@ -75,6 +63,18 @@
#define twl_has_madc() false
#endif
+#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
+#define twl_has_rtc() true
+#else
+#define twl_has_rtc() false
+#endif
+
+#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
+#define twl_has_usb() true
+#else
+#define twl_has_usb() false
+#endif
+
/* Primary Interrupt Handler on TWL4030 Registers */
/* Register Definitions */
@@ -706,27 +706,18 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
- if (twl_has_rtc()) {
- pdev = platform_device_alloc("twl4030_rtc", -1);
+ if (twl_has_keypad() && pdata->keypad) {
+ pdev = platform_device_alloc("twl4030_keypad", -1);
if (pdev) {
- twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM2];
pdev->dev.parent = &twl->client->dev;
device_init_wakeup(&pdev->dev, 1);
-
- /*
- * FIXME add the relevant IRQ resource, and make the
- * rtc driver use it instead of hard-wiring ...
- *
- * REVISIT platform_data here currently only supports
- * setting up the "msecure" line ... which actually
- * violates the "princple of least privilege", since
- * it's effectively always in "high trust" mode.
- *
- * For now, expect equivalent treatment at board init:
- * setting msecure high. Eventually, Linux might
- * become more aware of those HW security concerns.
- */
-
+ status = platform_device_add_data(pdev, pdata->keypad,
+ sizeof(*pdata->keypad));
+ if (status < 0) {
+ platform_device_put(pdev);
+ goto err;
+ }
status = platform_device_add(pdev);
if (status < 0)
platform_device_put(pdev);
@@ -736,14 +727,14 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
- if (twl_has_keypad() && pdata->keypad) {
- pdev = platform_device_alloc("twl4030_keypad", -1);
+ if (twl_has_madc() && pdata->madc) {
+ pdev = platform_device_alloc("twl4030_madc", -1);
if (pdev) {
twl = &twl4030_modules[TWL4030_SLAVENUM_NUM2];
pdev->dev.parent = &twl->client->dev;
device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->keypad,
- sizeof(*pdata->keypad));
+ status = platform_device_add_data(pdev, pdata->madc,
+ sizeof(*pdata->madc));
if (status < 0) {
platform_device_put(pdev);
goto err;
@@ -757,18 +748,27 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
- if (twl_has_usb() && pdata->usb) {
- pdev = platform_device_alloc("twl4030_usb", -1);
+ if (twl_has_rtc()) {
+ pdev = platform_device_alloc("twl4030_rtc", -1);
if (pdev) {
- twl = &twl4030_modules[TWL4030_SLAVENUM_NUM0];
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
pdev->dev.parent = &twl->client->dev;
device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->usb,
- sizeof(*pdata->usb));
- if (status < 0) {
- platform_device_put(pdev);
- goto err;
- }
+
+ /*
+ * FIXME add the relevant IRQ resource, and make the
+ * rtc driver use it instead of hard-wiring ...
+ *
+ * REVISIT platform_data here currently only supports
+ * setting up the "msecure" line ... which actually
+ * violates the "princple of least privilege", since
+ * it's effectively always in "high trust" mode.
+ *
+ * For now, expect equivalent treatment at board init:
+ * setting msecure high. Eventually, Linux might
+ * become more aware of those HW security concerns.
+ */
+
status = platform_device_add(pdev);
if (status < 0)
platform_device_put(pdev);
@@ -778,14 +778,14 @@ static int add_children(struct twl4030_platform_data *pdata)
}
}
- if (twl_has_madc() && pdata->madc) {
- pdev = platform_device_alloc("twl4030_madc", -1);
+ if (twl_has_usb() && pdata->usb) {
+ pdev = platform_device_alloc("twl4030_usb", -1);
if (pdev) {
- twl = &twl4030_modules[TWL4030_SLAVENUM_NUM2];
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM0];
pdev->dev.parent = &twl->client->dev;
device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->madc,
- sizeof(*pdata->madc));
+ status = platform_device_add_data(pdev, pdata->usb,
+ sizeof(*pdata->usb));
if (status < 0) {
platform_device_put(pdev);
goto err;
@@ -844,17 +844,19 @@ static int __init unprotect_pm_master(void)
static int __init power_companion_init(void)
{
+ int e = 0;
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
struct clk *osc;
u32 rate;
u8 ctrl = HFCLK_FREQ_26_MHZ;
- int e = 0;
if (cpu_is_omap2430())
osc = clk_get(NULL, "osc_ck");
else
osc = clk_get(NULL, "osc_sys_ck");
if (IS_ERR(osc)) {
- printk(KERN_WARNING "Skipping twl3040 internal clock init and "
+ printk(KERN_WARNING "Skipping twl4030 internal clock init and "
"using bootloader value (unknown osc rate)\n");
return 0;
}
@@ -879,6 +881,7 @@ static int __init power_companion_init(void)
/* effect->MADC+USB ck en */
e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
e |= protect_pm_master();
+#endif /* OMAP */
return e;
}
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 11/23] provide detailed diagnostics in add_children()
2008-09-30 10:05 ` [PATCH 10/23] minor twl4030-core cleanups Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 12/23] move twl4030-gpio to drivers/gpio Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Provide detailed diagnostics in add_children() when DEBUG is
defined ... and fix the non-DEBUG message to include minimal
status, and not appear unless there was actually an error.
Update the IRQ message; have it match what the GPIO subchip
says, and as a precaution, make it only appear if the IRQs
have been initialized.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Added a few more diagnostics when platform_device_add() fails.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-core.c | 59 ++++++++++++++++++++++++++++++-------
1 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 22850a8..5dcc3b1 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -672,8 +672,10 @@ static int add_children(struct twl4030_platform_data *pdata)
twl = &twl4030_modules[TWL4030_SLAVENUM_NUM1];
pdev = platform_device_alloc("twl4030_gpio", -1);
- if (!pdev)
+ if (!pdev) {
+ pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME);
status = -ENOMEM;
+ }
/* more driver model init */
if (status == 0) {
@@ -682,6 +684,12 @@ static int add_children(struct twl4030_platform_data *pdata)
status = platform_device_add_data(pdev, pdata->gpio,
sizeof(*pdata->gpio));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add gpio data, %d\n",
+ status);
+ goto err;
+ }
}
/* GPIO module IRQ */
@@ -715,13 +723,21 @@ static int add_children(struct twl4030_platform_data *pdata)
status = platform_device_add_data(pdev, pdata->keypad,
sizeof(*pdata->keypad));
if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add keypad data, %d\n",
+ status);
platform_device_put(pdev);
goto err;
}
status = platform_device_add(pdev);
- if (status < 0)
+ if (status < 0) {
platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create keypad dev, %d\n",
+ status);
+ }
} else {
+ pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME);
status = -ENOMEM;
goto err;
}
@@ -737,12 +753,20 @@ static int add_children(struct twl4030_platform_data *pdata)
sizeof(*pdata->madc));
if (status < 0) {
platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't add madc data, %d\n",
+ status);
goto err;
}
status = platform_device_add(pdev);
- if (status < 0)
+ if (status < 0) {
platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create madc dev, %d\n",
+ status);
+ }
} else {
+ pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME);
status = -ENOMEM;
goto err;
}
@@ -770,9 +794,14 @@ static int add_children(struct twl4030_platform_data *pdata)
*/
status = platform_device_add(pdev);
- if (status < 0)
+ if (status < 0) {
platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create rtc dev, %d\n",
+ status);
+ }
} else {
+ pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
status = -ENOMEM;
goto err;
}
@@ -788,19 +817,28 @@ static int add_children(struct twl4030_platform_data *pdata)
sizeof(*pdata->usb));
if (status < 0) {
platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't add usb data, %d\n",
+ status);
goto err;
}
status = platform_device_add(pdev);
- if (status < 0)
+ if (status < 0) {
platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create usb dev, %d\n",
+ status);
+ }
} else {
+ pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
status = -ENOMEM;
goto err;
}
}
err:
- pr_err("failed to add twl4030's children\n");
+ if (status)
+ pr_err("failed to add twl4030's children (status %d)\n", status);
return status;
}
@@ -1084,13 +1122,12 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
&& twl4030_irq_base == 0
&& client->irq
&& pdata->irq_base
- && pdata->irq_end > pdata->irq_base)
+ && pdata->irq_end > pdata->irq_base) {
twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end);
+ dev_info(&client->dev, "IRQ %d chains IRQs %d..%d\n",
+ client->irq, pdata->irq_base, pdata->irq_end - 1);
+ }
- dev_info(&client->dev, "chaining %d irqs\n",
- twl4030_irq_base
- ? (pdata->irq_end - pdata->irq_base)
- : 0);
return 0;
fail:
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 12/23] move twl4030-gpio to drivers/gpio
2008-09-30 10:05 ` [PATCH 11/23] provide detailed diagnostics in add_children() Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 13/23] i2c: added a few missing gotos to add_children() Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Move the twl4030 GPIO support from drivers/i2c/chips to drivers/gpio,
which is a more appropriate home for this code.
The Kconfig symbol name is changed to match the GPIO_* convention for
such symbols, so config files must change in the obvious ways (Kconfig
will prompt you). There's now some helptext.
It can now be compiled as a module, should anyone really want to
do that; that'll be mostly useful for test builds. Sanity check the
IRQ range we're given.
Initialization order needed a bit of work too: core add_children()
called only after IRQs get set up, gpio uses subsys_initcall. This
depends on a patch making i2c driver model init use postcore_initcall.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/plat-omap/include/mach/irqs.h | 2 +-
drivers/gpio/Kconfig | 7 +++++
drivers/gpio/Makefile | 1 +
drivers/{i2c/chips => gpio}/twl4030-gpio.c | 37 +++++++++++++++++++++++----
drivers/i2c/chips/Kconfig | 4 ---
drivers/i2c/chips/Makefile | 1 -
drivers/i2c/chips/twl4030-core.c | 12 +++------
7 files changed, 44 insertions(+), 20 deletions(-)
rename drivers/{i2c/chips => gpio}/twl4030-gpio.c (96%)
diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h
index 29c92c9..8a4473e 100644
--- a/arch/arm/plat-omap/include/mach/irqs.h
+++ b/arch/arm/plat-omap/include/mach/irqs.h
@@ -369,7 +369,7 @@
/* External TWL4030 gpio interrupts are optional */
#define TWL4030_GPIO_IRQ_BASE TWL4030_PWR_IRQ_END
-#ifdef CONFIG_TWL4030_GPIO
+#ifdef CONFIG_GPIO_TWL4030
#define TWL4030_GPIO_NR_IRQS 18
#else
#define TWL4030_GPIO_NR_IRQS 0
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index dbd42d6..293b4a7 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -127,6 +127,13 @@ config GPIO_PCF857X
This driver provides an in-kernel interface to those GPIOs using
platform-neutral GPIO calls.
+config GPIO_TWL4030
+ tristate "TWL4030/TPS659x0 GPIO Driver"
+ depends on TWL4030_CORE && GPIOLIB
+ help
+ Say yes here to access the GPIO signals of various multi-function
+ power management chips from Texas Instruments.
+
comment "PCI GPIO expanders:"
config GPIO_BT8XX
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 01b4bbd..6aafdeb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
+obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
diff --git a/drivers/i2c/chips/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
similarity index 96%
rename from drivers/i2c/chips/twl4030-gpio.c
rename to drivers/gpio/twl4030-gpio.c
index 0d4dd28..2949da1 100644
--- a/drivers/i2c/chips/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/i2c/chips/twl4030_gpio.c
+ * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
*
* Copyright (C) 2006-2007 Texas Instruments, Inc.
* Copyright (C) 2006 MontaVista Software, Inc.
@@ -23,7 +23,6 @@
* 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
- *
*/
#include <linux/module.h>
@@ -48,14 +47,19 @@
/* REVISIT when these symbols vanish elsewhere, remove them here too */
-#undef TWL4030_GPIO_IRQ_BASE
-#undef TWL4030_GPIO_IRQ_END
+/* #undef TWL4030_GPIO_IRQ_BASE */
+/* #undef TWL4030_GPIO_IRQ_END */
#undef TWL4030_MODIRQ_GPIO
static struct gpio_chip twl_gpiochip;
static int twl4030_gpio_irq_base;
static int twl4030_gpio_irq_end;
+#ifdef MODULE
+#define is_module() true
+#else
+#define is_module() false
+#endif
/* BitField Definitions */
@@ -765,7 +769,24 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
twl4030_gpio_irq_base = pdata->irq_base;
twl4030_gpio_irq_end = pdata->irq_end;
- /* REVISIT skip most of this if the irq range is empty... */
+ if ((twl4030_gpio_irq_end - twl4030_gpio_irq_base) > 0) {
+ if (is_module()) {
+ dev_err(&pdev->dev,
+ "can't dispatch IRQs from modules\n");
+ goto no_irqs;
+ }
+ if (twl4030_gpio_irq_end > NR_IRQS) {
+ dev_err(&pdev->dev,
+ "last IRQ is too large: %d\n",
+ twl4030_gpio_irq_end);
+ return -EINVAL;
+ }
+ } else {
+ dev_notice(&pdev->dev,
+ "no IRQs being dispatched\n");
+ goto no_irqs;
+ }
+
if (!ret) {
/*
* Create a kernel thread to handle deferred unmasking of gpio
@@ -805,6 +826,7 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
twl4030_gpio_irq_base, twl4030_gpio_irq_end - 1);
}
+no_irqs:
if (!ret) {
twl_gpiochip.base = pdata->gpio_base;
twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
@@ -849,6 +871,9 @@ static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
if (status < 0)
return status;
+ if (is_module() || (twl4030_gpio_irq_end - twl4030_gpio_irq_base) <= 0)
+ return 0;
+
/* uninstall the gpio demultiplexing interrupt handler */
irq = platform_get_irq(pdev, 0);
set_irq_handler(irq, NULL);
@@ -883,7 +908,7 @@ static int __init gpio_twl4030_init(void)
{
return platform_driver_register(&gpio_twl4030_driver);
}
-module_init(gpio_twl4030_init);
+subsys_initcall(gpio_twl4030_init);
static void __exit gpio_twl4030_exit(void)
{
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 1a21388..e6ac6a2 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -157,10 +157,6 @@ config TWL4030_CORE
help
Say yes here if you have TWL4030 chip on your board
-config TWL4030_GPIO
- bool "TWL4030 GPIO Driver"
- depends on TWL4030_CORE && GPIOLIB
-
config TWL4030_MADC
tristate "TWL4030 MADC Driver"
depends on TWL4030_CORE
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index ad5f5db..75c531a 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-pwrirq.o twl4030-power.o
-obj-$(CONFIG_TWL4030_GPIO) += twl4030-gpio.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
obj-$(CONFIG_TWL4030_POWEROFF) += twl4030-poweroff.o
obj-$(CONFIG_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 5dcc3b1..4ea6444 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -51,7 +51,7 @@
#define twl_has_keypad() false
#endif
-#ifdef CONFIG_TWL4030_GPIO
+#if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE)
#define twl_has_gpio() true
#else
#define twl_has_gpio() false
@@ -1110,10 +1110,6 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
mutex_init(&twl->xfer_lock);
}
- status = add_children(pdata);
- if (status < 0)
- goto fail;
-
/*
* Check if the PIH module is initialized, if yes, then init
* the T2 Interrupt subsystem
@@ -1128,10 +1124,10 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
client->irq, pdata->irq_base, pdata->irq_end - 1);
}
- return 0;
-
+ status = add_children(pdata);
fail:
- twl4030_remove(client);
+ if (status < 0)
+ twl4030_remove(client);
return status;
}
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 13/23] i2c: added a few missing gotos to add_children()
2008-09-30 10:05 ` [PATCH 12/23] move twl4030-gpio to drivers/gpio Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 14/23] minor irq-related cleanups Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
Previously we were failing platform_device_add_data()
and returning from add_children but trying to keep going
when platform_device_add() fails.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-core.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 4ea6444..80cf231 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -675,6 +675,7 @@ static int add_children(struct twl4030_platform_data *pdata)
if (!pdev) {
pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME);
status = -ENOMEM;
+ goto err;
}
/* more driver model init */
@@ -735,6 +736,7 @@ static int add_children(struct twl4030_platform_data *pdata)
dev_dbg(&twl->client->dev,
"can't create keypad dev, %d\n",
status);
+ goto err;
}
} else {
pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME);
@@ -764,6 +766,7 @@ static int add_children(struct twl4030_platform_data *pdata)
dev_dbg(&twl->client->dev,
"can't create madc dev, %d\n",
status);
+ goto err;
}
} else {
pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME);
@@ -799,6 +802,7 @@ static int add_children(struct twl4030_platform_data *pdata)
dev_dbg(&twl->client->dev,
"can't create rtc dev, %d\n",
status);
+ goto err;
}
} else {
pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
@@ -832,7 +836,6 @@ static int add_children(struct twl4030_platform_data *pdata)
} else {
pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
status = -ENOMEM;
- goto err;
}
}
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 14/23] minor irq-related cleanups
2008-09-30 10:05 ` [PATCH 13/23] i2c: added a few missing gotos to add_children() Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 15/23] i2c: switch twl4030-usb to use a resource for irq Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Minor IRQ-related cleanups: comment out the no-longer-used
GPIO irq symbol (more to come, eventually); create RTC IRQ
resource; and use that RTC IRQ resource.
And incidentally, make the RTC code free the correct IRQ;
it was pretty goofed up...
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/gpio/twl4030-gpio.c | 1 -
drivers/i2c/chips/twl4030-core.c | 57 +++++++++++++++++++++----------------
drivers/rtc/rtc-twl4030.c | 11 +++++--
include/linux/i2c/twl4030.h | 2 +-
4 files changed, 41 insertions(+), 30 deletions(-)
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index 2949da1..b65d476 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -49,7 +49,6 @@
/* REVISIT when these symbols vanish elsewhere, remove them here too */
/* #undef TWL4030_GPIO_IRQ_BASE */
/* #undef TWL4030_GPIO_IRQ_END */
-#undef TWL4030_MODIRQ_GPIO
static struct gpio_chip twl_gpiochip;
static int twl4030_gpio_irq_base;
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 80cf231..e0a6ef4 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -776,37 +776,44 @@ static int add_children(struct twl4030_platform_data *pdata)
}
if (twl_has_rtc()) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
+
pdev = platform_device_alloc("twl4030_rtc", -1);
- if (pdev) {
- twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
+ if (!pdev) {
+ pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ } else {
pdev->dev.parent = &twl->client->dev;
device_init_wakeup(&pdev->dev, 1);
+ }
- /*
- * FIXME add the relevant IRQ resource, and make the
- * rtc driver use it instead of hard-wiring ...
- *
- * REVISIT platform_data here currently only supports
- * setting up the "msecure" line ... which actually
- * violates the "princple of least privilege", since
- * it's effectively always in "high trust" mode.
- *
- * For now, expect equivalent treatment at board init:
- * setting msecure high. Eventually, Linux might
- * become more aware of those HW security concerns.
- */
+ /*
+ * REVISIT platform_data here currently might use of
+ * "msecure" line ... but for now we just expect board
+ * setup to tell the chip "we are secure" at all times.
+ * Eventually, Linux might become more aware of such
+ * HW security concerns, and "least privilege".
+ */
+
+ /* RTC module IRQ */
+ if (status == 0) {
+ struct resource r = {
+ /* REVISIT don't hard-wire this stuff */
+ .start = TWL4030_PWRIRQ_RTC,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+ if (status == 0)
status = platform_device_add(pdev);
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create rtc dev, %d\n",
- status);
- goto err;
- }
- } else {
- pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
- status = -ENOMEM;
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create rtc dev, %d\n",
+ status);
goto err;
}
}
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c
index 98aea07..b19151a 100644
--- a/drivers/rtc/rtc-twl4030.c
+++ b/drivers/rtc/rtc-twl4030.c
@@ -353,8 +353,12 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
struct twl4030rtc_platform_data *pdata = pdev->dev.platform_data;
struct rtc_device *rtc;
int ret = 0;
+ int irq = platform_get_irq(pdev, 0);
u8 rd_reg;
+ if (irq < 0)
+ return irq;
+
if (pdata != NULL && pdata->init != NULL) {
ret = pdata->init();
if (ret < 0)
@@ -389,7 +393,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
if (ret < 0)
goto out1;
- ret = request_irq(TWL4030_PWRIRQ_RTC, twl4030_rtc_interrupt,
+ ret = request_irq(irq, twl4030_rtc_interrupt,
0, rtc->dev.bus_id, rtc);
if (ret < 0) {
dev_err(&pdev->dev, "IRQ is not free.\n");
@@ -438,7 +442,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
out2:
- free_irq(TWL4030_MODIRQ_PWR, rtc);
+ free_irq(irq, rtc);
out1:
rtc_device_unregister(rtc);
out0:
@@ -457,11 +461,12 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
/* leave rtc running, but disable irqs */
struct twl4030rtc_platform_data *pdata = pdev->dev.platform_data;
struct rtc_device *rtc = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
- free_irq(TWL4030_MODIRQ_PWR, rtc);
+ free_irq(irq, rtc);
if (pdata != NULL && pdata->exit != NULL)
pdata->exit();
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 404300c..5828485 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -108,7 +108,7 @@ struct twl4030_platform_data {
#include <mach/irqs.h>
/* TWL4030 interrupts */
-#define TWL4030_MODIRQ_GPIO (TWL4030_IRQ_BASE + 0)
+/* #define TWL4030_MODIRQ_GPIO (TWL4030_IRQ_BASE + 0) */
#define TWL4030_MODIRQ_KEYPAD (TWL4030_IRQ_BASE + 1)
#define TWL4030_MODIRQ_BCI (TWL4030_IRQ_BASE + 2)
#define TWL4030_MODIRQ_MADC (TWL4030_IRQ_BASE + 3)
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 15/23] i2c: switch twl4030-usb to use a resource for irq
2008-09-30 10:05 ` [PATCH 14/23] minor irq-related cleanups Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
use platform_get_irq() for getting irq number passed
to twl4030-usb via twl4030-core.c:add_children()
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-core.c | 38 +++++++++++++++++++++++++++-----------
drivers/i2c/chips/twl4030-usb.c | 2 +-
include/linux/i2c/twl4030.h | 2 +-
3 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index e0a6ef4..43424a8 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -819,9 +819,16 @@ static int add_children(struct twl4030_platform_data *pdata)
}
if (twl_has_usb() && pdata->usb) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM0];
+
pdev = platform_device_alloc("twl4030_usb", -1);
- if (pdev) {
- twl = &twl4030_modules[TWL4030_SLAVENUM_NUM0];
+ if (!pdev) {
+ pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+
+ if (status == 0) {
pdev->dev.parent = &twl->client->dev;
device_init_wakeup(&pdev->dev, 1);
status = platform_device_add_data(pdev, pdata->usb,
@@ -833,16 +840,25 @@ static int add_children(struct twl4030_platform_data *pdata)
status);
goto err;
}
+ }
+
+ if (status == 0) {
+ struct resource r = {
+ .start = TWL4030_PWRIRQ_USB_PRES,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
status = platform_device_add(pdev);
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create usb dev, %d\n",
- status);
- }
- } else {
- pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
- status = -ENOMEM;
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create usb dev, %d\n",
+ status);
}
}
diff --git a/drivers/i2c/chips/twl4030-usb.c b/drivers/i2c/chips/twl4030-usb.c
index f530e71..133cc0f 100644
--- a/drivers/i2c/chips/twl4030-usb.c
+++ b/drivers/i2c/chips/twl4030-usb.c
@@ -684,7 +684,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
vbus &= USB_PRES_RISING;
twl->dev = &pdev->dev;
- twl->irq = TWL4030_PWRIRQ_USB_PRES;
+ twl->irq = platform_get_irq(pdev, 0);
twl->otg.set_host = twl4030_set_host;
twl->otg.set_peripheral = twl4030_set_peripheral;
twl->otg.set_suspend = twl4030_set_suspend;
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 5828485..1c79c89 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -112,7 +112,7 @@ struct twl4030_platform_data {
#define TWL4030_MODIRQ_KEYPAD (TWL4030_IRQ_BASE + 1)
#define TWL4030_MODIRQ_BCI (TWL4030_IRQ_BASE + 2)
#define TWL4030_MODIRQ_MADC (TWL4030_IRQ_BASE + 3)
-#define TWL4030_MODIRQ_USB (TWL4030_IRQ_BASE + 4)
+/* #define TWL4030_MODIRQ_USB (TWL4030_IRQ_BASE + 4) */
#define TWL4030_MODIRQ_PWR (TWL4030_IRQ_BASE + 5)
#define TWL4030_PWRIRQ_PWRBTN (TWL4030_PWR_IRQ_BASE + 0)
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 16/23] Move I2C driver model init earlier in the boot sequence
2008-09-30 10:05 ` [PATCH 15/23] i2c: switch twl4030-usb to use a resource for irq Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 17/23] i2c: minor cleanups to twl4030-pwrbutton.c Felipe Balbi
2008-09-30 15:52 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence David Brownell
0 siblings, 2 replies; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
This avoids oopsing in statically linked systems when some
subsystems register I2C drivers in subsys_initcall() code,
but those subsystems are linked (and initialized) before I2C.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/i2c-core.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index b346a68..f520108 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -978,7 +978,7 @@ static void __exit i2c_exit(void)
bus_unregister(&i2c_bus_type);
}
-subsys_initcall(i2c_init);
+postcore_initcall(i2c_init);
module_exit(i2c_exit);
/* ----------------------------------------------------
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 17/23] i2c: minor cleanups to twl4030-pwrbutton.c
2008-09-30 10:05 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 18/23] twl4030-gpio irq_chip.set_type Felipe Balbi
2008-09-30 15:52 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence David Brownell
1 sibling, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
Trivial brainless fixes, a few unused headers removed,
changed one printk to pr_err() and removed one comment.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-pwrbutton.c | 10 +---------
1 files changed, 1 insertions(+), 9 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-pwrbutton.c b/drivers/i2c/chips/twl4030-pwrbutton.c
index d86d489..9a361b3 100644
--- a/drivers/i2c/chips/twl4030-pwrbutton.c
+++ b/drivers/i2c/chips/twl4030-pwrbutton.c
@@ -26,9 +26,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/input.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/i2c/twl4030.h>
@@ -47,11 +44,6 @@
static struct input_dev *powerbutton_dev;
-/*
- * Note : the following function runs in kernel thread context
- * with IRQs enabled
- */
-
static irqreturn_t powerbutton_irq(int irq, void *dev_id)
{
int err;
@@ -63,7 +55,7 @@ static irqreturn_t powerbutton_irq(int irq, void *dev_id)
input_report_key(powerbutton_dev, KEY_POWER,
value & PWR_PWRON_IRQ);
} else {
- printk(KERN_WARNING "I2C error %d while reading TWL4030"
+ pr_err("twl4030: i2c error %d while reading TWL4030"
" PM_MASTER STS_HW_CONDITIONS register\n", err);
}
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 18/23] twl4030-gpio irq_chip.set_type
2008-09-30 10:05 ` [PATCH 17/23] i2c: minor cleanups to twl4030-pwrbutton.c Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Make twl4030 GPIO support set_type() request.
Plus a bit of cleanup for the simple functions.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/gpio/twl4030-gpio.c | 84 +++++++++++++++++++++++++++++++++++++-----
1 files changed, 74 insertions(+), 10 deletions(-)
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index b65d476..e709fbb 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -153,6 +153,9 @@ static unsigned int gpio_imr_shadow;
/* bitmask of pending requests to unmask gpio interrupts */
static unsigned int gpio_pending_unmask;
+/* bitmask of requests to set gpio irq trigger type */
+static unsigned int gpio_pending_trigger;
+
/* pointer to gpio unmask thread struct */
static struct task_struct *gpio_unmask_thread;
@@ -241,10 +244,15 @@ static void twl4030_gpio_unmask(unsigned int irq)
* controller to a kernel thread. We only need to support the unmask method.
*/
-static void twl4030_gpio_mask_and_ack_irqchip(unsigned int irq) {}
-static void twl4030_gpio_mask_irqchip(unsigned int irq) {}
+static void twl4030_gpio_irq_mask_and_ack(unsigned int irq)
+{
+}
+
+static void twl4030_gpio_irq_mask(unsigned int irq)
+{
+}
-static void twl4030_gpio_unmask_irqchip(unsigned int irq)
+static void twl4030_gpio_irq_unmask(unsigned int irq)
{
int gpio = irq - twl4030_gpio_irq_base;
@@ -253,11 +261,36 @@ static void twl4030_gpio_unmask_irqchip(unsigned int irq)
wake_up_process(gpio_unmask_thread);
}
+static int twl4030_gpio_irq_set_type(unsigned int irq, unsigned trigger)
+{
+ struct irq_desc *desc = irq_desc + irq;
+ int gpio = irq - twl4030_gpio_irq_base;
+
+ trigger &= IRQ_TYPE_SENSE_MASK;
+ if (trigger & ~IRQ_TYPE_EDGE_BOTH)
+ return -EINVAL;
+ if ((desc->status & IRQ_TYPE_SENSE_MASK) == trigger)
+ return 0;
+
+ desc->status &= ~IRQ_TYPE_SENSE_MASK;
+ desc->status |= trigger;
+
+ /* REVISIT This makes the "unmask" thread do double duty,
+ * updating IRQ trigger modes too. Rename appropriately...
+ */
+ gpio_pending_trigger |= (1 << gpio);
+ if (gpio_unmask_thread && gpio_unmask_thread->state != TASK_RUNNING)
+ wake_up_process(gpio_unmask_thread);
+
+ return 0;
+}
+
static struct irq_chip twl4030_gpio_irq_chip = {
- .name = "twl4030",
- .ack = twl4030_gpio_mask_and_ack_irqchip,
- .mask = twl4030_gpio_mask_irqchip,
- .unmask = twl4030_gpio_unmask_irqchip,
+ .name = "twl4030",
+ .ack = twl4030_gpio_irq_mask_and_ack,
+ .mask = twl4030_gpio_irq_mask,
+ .unmask = twl4030_gpio_irq_unmask,
+ .set_type = twl4030_gpio_irq_set_type,
};
/*
@@ -478,8 +511,6 @@ int twl4030_set_gpio_pull(int gpio, int pull_dircn)
/*
* Configure Edge control for a GPIO pin on TWL4030
- *
- * FIXME this should just be the irq_chip.set_type() method
*/
int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
{
@@ -601,10 +632,14 @@ static int twl4030_gpio_unmask_thread(void *data)
while (!kthread_should_stop()) {
int irq;
unsigned int gpio_unmask;
+ unsigned int gpio_trigger;
local_irq_disable();
gpio_unmask = gpio_pending_unmask;
gpio_pending_unmask = 0;
+
+ gpio_trigger = gpio_pending_trigger;
+ gpio_pending_trigger = 0;
local_irq_enable();
for (irq = twl4030_gpio_irq_base; 0 != gpio_unmask;
@@ -613,8 +648,37 @@ static int twl4030_gpio_unmask_thread(void *data)
twl4030_gpio_unmask(irq);
}
+ for (irq = twl4030_gpio_irq_base;
+ gpio_trigger;
+ gpio_trigger >>= 1, irq++) {
+ struct irq_desc *desc;
+ unsigned type, edge;
+
+ if (!(gpio_trigger & 0x1))
+ continue;
+
+ desc = irq_desc + irq;
+ spin_lock_irq(&desc->lock);
+ type = desc->status & IRQ_TYPE_SENSE_MASK;
+ spin_unlock_irq(&desc->lock);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ edge = TWL4030_GPIO_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ edge = TWL4030_GPIO_EDGE_FALLING;
+ break;
+ default:
+ edge = TWL4030_GPIO_EDGE_RISING
+ | TWL4030_GPIO_EDGE_FALLING;
+ break;
+ }
+ twl4030_set_gpio_edge_ctrl(irq, edge);
+ }
+
local_irq_disable();
- if (!gpio_pending_unmask)
+ if (!gpio_pending_unmask && !gpio_pending_trigger)
set_current_state(TASK_INTERRUPTIBLE);
local_irq_enable();
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user
2008-09-30 10:05 ` [PATCH 18/23] twl4030-gpio irq_chip.set_type Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 20/23] twl4030-gpio: irq and other cleanup Felipe Balbi
2008-09-30 17:37 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user David Brownell
0 siblings, 2 replies; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Make the hsmmc code use genirq interfaces to make sure the
card detect IRQ triggers on both edges. Remove the older
TWL-specific infrastructure for making that happen.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/mach-omap2/hsmmc.c | 5 -----
drivers/gpio/twl4030-gpio.c | 38 ++++++++------------------------------
drivers/mmc/host/omap_hsmmc.c | 4 +++-
include/linux/i2c/twl4030.h | 4 ----
4 files changed, 11 insertions(+), 40 deletions(-)
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 7334d86..2ba9986 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -65,11 +65,6 @@ static int hsmmc_late_init(struct device *dev)
if (ret)
goto err;
- ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ,
- TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING);
- if (ret)
- goto err;
-
ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02,
TWL_GPIO_PUPDCTR1);
if (ret)
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index e709fbb..404cb34 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -509,10 +509,7 @@ int twl4030_set_gpio_pull(int gpio, int pull_dircn)
}
#endif
-/*
- * Configure Edge control for a GPIO pin on TWL4030
- */
-int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
+static int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
{
u8 c_bnk = GET_GPIO_CTL_BANK(gpio);
u8 c_off = GET_GPIO_CTL_OFF(gpio);
@@ -521,33 +518,26 @@ int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
u8 base = 0;
int ret = 0;
- if (unlikely((gpio >= TWL4030_GPIO_MAX)
- || !(gpio_usage_count & (0x1 << gpio))))
- return -EPERM;
-
base = REG_GPIO_EDR1 + c_bnk;
- if (edge & TWL4030_GPIO_EDGE_RISING)
+ if (edge & IRQ_TYPE_EDGE_RISING)
c_msk |= MASK_GPIO_EDR1_GPIOxRISING(c_off);
-
- if (edge & TWL4030_GPIO_EDGE_FALLING)
+ if (edge & IRQ_TYPE_EDGE_FALLING)
c_msk |= MASK_GPIO_EDR1_GPIOxFALLING(c_off);
mutex_lock(&gpio_lock);
ret = gpio_twl4030_read(base);
if (ret >= 0) {
/* clear the previous rising/falling values */
- reg =
- (u8) (ret &
- ~(MASK_GPIO_EDR1_GPIOxFALLING(c_off) |
- MASK_GPIO_EDR1_GPIOxRISING(c_off)));
+ reg = (u8) ret;
+ reg &= ~( MASK_GPIO_EDR1_GPIOxFALLING(c_off)
+ | MASK_GPIO_EDR1_GPIOxRISING(c_off));
reg |= c_msk;
ret = gpio_twl4030_write(base, reg);
}
mutex_unlock(&gpio_lock);
return ret;
}
-EXPORT_SYMBOL(twl4030_set_gpio_edge_ctrl);
/*
* Configure debounce timing value for a GPIO pin on TWL4030
@@ -652,7 +642,7 @@ static int twl4030_gpio_unmask_thread(void *data)
gpio_trigger;
gpio_trigger >>= 1, irq++) {
struct irq_desc *desc;
- unsigned type, edge;
+ unsigned type;
if (!(gpio_trigger & 0x1))
continue;
@@ -662,19 +652,7 @@ static int twl4030_gpio_unmask_thread(void *data)
type = desc->status & IRQ_TYPE_SENSE_MASK;
spin_unlock_irq(&desc->lock);
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- edge = TWL4030_GPIO_EDGE_RISING;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- edge = TWL4030_GPIO_EDGE_FALLING;
- break;
- default:
- edge = TWL4030_GPIO_EDGE_RISING
- | TWL4030_GPIO_EDGE_FALLING;
- break;
- }
- twl4030_set_gpio_edge_ctrl(irq, edge);
+ twl4030_set_gpio_edge_ctrl(irq, type);
}
local_irq_disable();
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 7744669..4f5c0ab 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -918,7 +918,9 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
/* Request IRQ for card detect */
if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
ret = request_irq(mmc_slot(host).card_detect_irq,
- omap_mmc_cd_handler, IRQF_DISABLED,
+ omap_mmc_cd_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_DISABLED,
mmc_hostname(mmc), host);
if (ret) {
dev_dbg(mmc_dev(host->mmc),
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 1c79c89..f26fda1 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -149,9 +149,6 @@ struct twl4030_platform_data {
#define TWL4030_GPIO_PULL_UP 0
#define TWL4030_GPIO_PULL_DOWN 1
#define TWL4030_GPIO_PULL_NONE 2
-#define TWL4030_GPIO_EDGE_NONE 0
-#define TWL4030_GPIO_EDGE_RISING 1
-#define TWL4030_GPIO_EDGE_FALLING 2
/* Functions to read and write from TWL4030 */
@@ -177,7 +174,6 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
*/
int twl4030_get_gpio_datain(int gpio);
int twl4030_request_gpio(int gpio);
-int twl4030_set_gpio_edge_ctrl(int gpio, int edge);
int twl4030_set_gpio_debounce(int gpio, int enable);
int twl4030_free_gpio(int gpio);
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 20/23] twl4030-gpio: irq and other cleanup
2008-09-30 10:05 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 21/23] twl4030-core: portability updates Felipe Balbi
2008-09-30 17:37 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user David Brownell
1 sibling, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Remove some ARM and OMAP specific stuff from the twl4030 GPIO code,
and some unused/undesirable CPP symbols. Add minor checkpatch fixes.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/gpio/twl4030-gpio.c | 36 +++++++++++++++++++-----------------
include/linux/i2c/twl4030.h | 6 ------
2 files changed, 19 insertions(+), 23 deletions(-)
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index 404cb34..04a58cb 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -40,20 +40,25 @@
#include <linux/i2c/twl4030.h>
#include <linux/i2c/twl4030-gpio.h>
-#include <mach/irqs.h>
-#include <asm/mach/irq.h>
-#include <mach/gpio.h>
-#include <mach/mux.h>
-
-/* REVISIT when these symbols vanish elsewhere, remove them here too */
-/* #undef TWL4030_GPIO_IRQ_BASE */
-/* #undef TWL4030_GPIO_IRQ_END */
+static inline void activate_irq(int irq)
+{
+#ifdef CONFIG_ARM
+ /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+ * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
+ */
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ /* same effect on other architectures */
+ set_irq_noprobe(irq);
+#endif
+}
static struct gpio_chip twl_gpiochip;
static int twl4030_gpio_irq_base;
static int twl4030_gpio_irq_end;
+/* genirq interfaces are not available to modules */
#ifdef MODULE
#define is_module() true
#else
@@ -530,7 +535,7 @@ static int twl4030_set_gpio_edge_ctrl(int gpio, int edge)
if (ret >= 0) {
/* clear the previous rising/falling values */
reg = (u8) ret;
- reg &= ~( MASK_GPIO_EDR1_GPIOxFALLING(c_off)
+ reg &= ~(MASK_GPIO_EDR1_GPIOxFALLING(c_off)
| MASK_GPIO_EDR1_GPIOxRISING(c_off));
reg |= c_msk;
ret = gpio_twl4030_write(base, reg);
@@ -598,7 +603,7 @@ int twl4030_set_gpio_card_detect(int gpio, int enable)
ret = gpio_twl4030_write(REG_GPIO_CTRL, reg);
}
mutex_unlock(&gpio_lock);
- return (ret);
+ return ret;
}
#endif
@@ -847,9 +852,9 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
/* install an irq handler for each of the gpio interrupts */
for (irq = twl4030_gpio_irq_base; irq < twl4030_gpio_irq_end;
irq++) {
- set_irq_chip(irq, &twl4030_gpio_irq_chip);
- set_irq_handler(irq, do_twl4030_gpio_irq);
- set_irq_flags(irq, IRQF_VALID);
+ set_irq_chip_and_handler(irq, &twl4030_gpio_irq_chip,
+ do_twl4030_gpio_irq);
+ activate_irq(irq);
}
/* gpio module IRQ */
@@ -918,13 +923,10 @@ static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
/* uninstall the gpio demultiplexing interrupt handler */
irq = platform_get_irq(pdev, 0);
set_irq_handler(irq, NULL);
- set_irq_flags(irq, 0);
/* uninstall the irq handler for each of the gpio interrupts */
- for (irq = twl4030_gpio_irq_base; irq < twl4030_gpio_irq_end; irq++) {
+ for (irq = twl4030_gpio_irq_base; irq < twl4030_gpio_irq_end; irq++)
set_irq_handler(irq, NULL);
- set_irq_flags(irq, 0);
- }
/* stop the gpio unmask kernel thread */
if (gpio_unmask_thread) {
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index f26fda1..56a9415 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -138,17 +138,11 @@ struct twl4030_platform_data {
/* TWL4030 GPIO interrupt definitions */
-#define TWL4030_GPIO_MIN 0
#define TWL4030_GPIO_MAX 18
-#define TWL4030_GPIO_MAX_CD 2
#define TWL4030_GPIO_IRQ_NO(n) (TWL4030_GPIO_IRQ_BASE + (n))
-#define TWL4030_GPIO_IS_INPUT 1
-#define TWL4030_GPIO_IS_OUTPUT 0
#define TWL4030_GPIO_IS_ENABLE 1
-#define TWL4030_GPIO_IS_DISABLE 0
#define TWL4030_GPIO_PULL_UP 0
#define TWL4030_GPIO_PULL_DOWN 1
-#define TWL4030_GPIO_PULL_NONE 2
/* Functions to read and write from TWL4030 */
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 21/23] twl4030-core: portability updates
2008-09-30 10:05 ` [PATCH 20/23] twl4030-gpio: irq and other cleanup Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:05 ` [PATCH 22/23] twl4030: minor cleanups to twl4030_bci_battery.c Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
From: David Brownell <dbrownell@users.sourceforge.net>
Improve handling of the OMAP-specific setup in twl4030-core,
and remove various warnings on non-OMAP builds.
The main remaining portability problem for this core code (from
a build perspective) is needing symbols like TWL4030_PWR_IRQ_BASE
which are undesirable and platform-specific.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/twl4030-core.c | 34 ++++++++++++++++++++++++----------
1 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 43424a8..efba776 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -75,6 +75,19 @@
#define twl_has_usb() false
#endif
+static inline void activate_irq(int irq)
+{
+#ifdef CONFIG_ARM
+ /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+ * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
+ */
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ /* same effect on other architectures */
+ set_irq_noprobe(irq);
+#endif
+}
+
/* Primary Interrupt Handler on TWL4030 Registers */
/* Register Definitions */
@@ -584,7 +597,7 @@ static unsigned twl4030_irq_base;
*/
static int twl4030_irq_thread(void *data)
{
- int irq = (int)data;
+ long irq = (long)data;
irq_desc_t *desc = irq_desc + irq;
static unsigned i2c_errors;
const static unsigned max_i2c_errors = 100;
@@ -868,15 +881,15 @@ err:
return status;
}
-static struct task_struct * __init start_twl4030_irq_thread(int irq)
+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 %d", irq);
+ "twl4030 irq %ld", irq);
if (!thread)
- pr_err("%s: could not create twl4030 irq %d thread!\n",
+ pr_err("%s: could not create twl4030 irq %ld thread!\n",
DRIVER_NAME, irq);
return thread;
@@ -909,16 +922,18 @@ static int __init unprotect_pm_master(void)
static int __init power_companion_init(void)
{
int e = 0;
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
struct clk *osc;
u32 rate;
u8 ctrl = HFCLK_FREQ_26_MHZ;
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
if (cpu_is_omap2430())
osc = clk_get(NULL, "osc_ck");
else
osc = clk_get(NULL, "osc_sys_ck");
+#else
+ osc = ERR_PTR(-EIO);
+#endif
if (IS_ERR(osc)) {
printk(KERN_WARNING "Skipping twl4030 internal clock init and "
"using bootloader value (unknown osc rate)\n");
@@ -945,7 +960,6 @@ static int __init power_companion_init(void)
/* effect->MADC+USB ck en */
e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
e |= protect_pm_master();
-#endif /* OMAP */
return e;
}
@@ -1051,9 +1065,9 @@ 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(i, &twl4030_irq_chip);
- set_irq_handler(i, do_twl4030_module_irq);
- set_irq_flags(i, IRQF_VALID);
+ set_irq_chip_and_handler(i, &twl4030_irq_chip,
+ do_twl4030_module_irq);
+ activate_irq(i);
}
/* install an irq handler to demultiplex the TWL4030 interrupt */
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 22/23] twl4030: minor cleanups to twl4030_bci_battery.c
2008-09-30 10:05 ` [PATCH 21/23] twl4030-core: portability updates Felipe Balbi
@ 2008-09-30 10:05 ` Felipe Balbi
2008-09-30 10:06 ` [PATCH 23/23] twl4030-bci: move to new style registration method Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:05 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
Brainless fixes, checkpatch.pl fixes, variable naming,
etc.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/power/twl4030_bci_battery.c | 161 ++++++++++++++++-------------------
1 files changed, 75 insertions(+), 86 deletions(-)
diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
index 6a55838..9ab6127 100644
--- a/drivers/power/twl4030_bci_battery.c
+++ b/drivers/power/twl4030_bci_battery.c
@@ -42,8 +42,8 @@
#define REG_PHY_CLK_CTRL_STS 0x0FF
#define PHY_DPLL_CLK 0x01
-#define REG_BCICTL1 0x023
-#define REG_BCICTL2 0x024
+#define REG_BCICTL1 0x023
+#define REG_BCICTL2 0x024
#define CGAIN 0x020
#define ITHEN 0x010
#define ITHSENS 0x007
@@ -70,7 +70,7 @@
#define REG_BCIMSTATEC 0x02
#define REG_BCIMFSTS4 0x010
#define REG_BCIMFSTS2 0x00E
-#define REG_BCIMFSTS3 0x00F
+#define REG_BCIMFSTS3 0x00F
#define REG_BCIMFSTS1 0x001
#define USBFASTMCHG 0x004
#define BATSTSPCHG 0x004
@@ -99,8 +99,8 @@
#define COR 0x004
/* interrupt status registers */
-#define REG_BCIISR1A 0x0
-#define REG_BCIISR2A 0x01
+#define REG_BCIISR1A 0x0
+#define REG_BCIISR2A 0x01
/* Interrupt flags bits BCIISR1 */
#define BATSTS_ISR1 0x080
@@ -146,14 +146,6 @@
/* Ptr to thermistor table */
int *therm_tbl;
-static int twl4030_bci_battery_probe(struct platform_device *dev);
-static int twl4030_bci_battery_remove(struct platform_device *dev);
-#ifdef CONFIG_PM
-static int twl4030_bci_battery_suspend(struct platform_device *dev,
- pm_message_t state);
-static int twl4030_bci_battery_resume(struct platform_device *dev);
-#endif
-
struct twl4030_bci_device_info {
struct device *dev;
@@ -171,18 +163,6 @@ struct twl4030_bci_device_info {
struct delayed_work twl4030_bk_bci_monitor_work;
};
-static struct platform_driver twl4030_bci_battery_driver = {
- .probe = twl4030_bci_battery_probe,
- .remove = twl4030_bci_battery_remove,
-#ifdef CONFIG_PM
- .suspend = twl4030_bci_battery_suspend,
- .resume = twl4030_bci_battery_resume,
-#endif
- .driver = {
- .name = "twl4030-bci-battery",
- },
-};
-
static int usb_charger_flag;
static int LVL_1, LVL_2, LVL_3, LVL_4;
@@ -204,14 +184,11 @@ static inline int twl4030charger_presence_evt(void)
if (ret)
return IRQ_NONE;
- /* If the AC charger have been connected */
- if (chg_sts & STS_CHG) {
+ if (chg_sts & STS_CHG) { /* If the AC charger have been connected */
/* configuring falling edge detection for CHG_PRES */
set = CHG_PRES_FALLING;
clear = CHG_PRES_RISING;
- }
- /* If the AC charger have been disconnected */
- else {
+ } else { /* If the AC charger have been disconnected */
/* configuring rising edge detection for CHG_PRES */
set = CHG_PRES_RISING;
clear = CHG_PRES_FALLING;
@@ -230,9 +207,9 @@ static inline int twl4030charger_presence_evt(void)
* USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
*
*/
-static irqreturn_t twl4030charger_interrupt(int irq, void *dev_id)
+static irqreturn_t twl4030charger_interrupt(int irq, void *_di)
{
- struct twl4030_bci_device_info *di = dev_id;
+ struct twl4030_bci_device_info *di = _di;
twl4030charger_presence_evt();
power_supply_changed(&di->bat);
@@ -264,17 +241,14 @@ static int twl4030battery_presence_evt(void)
* REVISIT: Physically inserting/removing the batt
* does not seem to generate an int on 3430ES2 SDP.
*/
-
- /* In case of the battery insertion event */
if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
+ /* In case of the battery insertion event */
ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
BATSTS_EDRFALLING, REG_BCIEDR2);
if (ret)
return ret;
- }
-
- /* In case of the battery removal event */
- else {
+ } else {
+ /* In case of the battery removal event */
ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
BATSTS_EDRRISIN, REG_BCIEDR2);
if (ret)
@@ -298,18 +272,27 @@ static int twl4030battery_level_evt(void)
if (ret)
return ret;
+ /* REVISIT could use a bitmap */
if (mfst & VBATOV4) {
LVL_4 = 1;
- LVL_3 = LVL_2 = LVL_1 = 0;
+ LVL_3 = 0;
+ LVL_2 = 0;
+ LVL_1 = 0;
} else if (mfst & VBATOV3) {
+ LVL_4 = 0;
LVL_3 = 1;
- LVL_4 = LVL_2 = LVL_1 = 0;
+ LVL_2 = 0;
+ LVL_1 = 0;
} else if (mfst & VBATOV2) {
+ LVL_4 = 0;
+ LVL_3 = 0;
LVL_2 = 1;
- LVL_4 = LVL_3 = LVL_1 = 0;
+ LVL_1 = 0;
} else {
+ LVL_4 = 0;
+ LVL_3 = 0;
+ LVL_2 = 0;
LVL_1 = 1;
- LVL_4 = LVL_3 = LVL_2 = 0;
}
return 0;
@@ -323,10 +306,10 @@ static int twl4030battery_level_evt(void)
* VBATOV (main battery voltage threshold) events
*
*/
-static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
+static irqreturn_t twl4030battery_interrupt(int irq, void *_di)
{
- int ret;
u8 isr1a_val, isr2a_val, clear_2a, clear_1a;
+ int ret;
ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val,
REG_BCIISR1A);
@@ -338,8 +321,8 @@ static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
if (ret)
return IRQ_NONE;
- clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0;
- clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0;
+ clear_2a = (isr2a_val & VBATLVL_ISR1) ? (VBATLVL_ISR1) : 0;
+ clear_1a = (isr1a_val & BATSTS_ISR1) ? (BATSTS_ISR1) : 0;
/* cleaning BCI interrupt status flags */
ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS,
@@ -446,6 +429,7 @@ static int twl4030charger_ac_en(int enable)
if (ret)
return ret;
}
+
return 0;
}
@@ -544,7 +528,7 @@ static int twl4030battery_temperature(void)
/*calculating temperature*/
for (temp = 58; temp >= 0; temp--) {
- int actual = therm_tbl [temp];
+ int actual = therm_tbl[temp];
if ((actual - res) >= 0)
break;
}
@@ -631,12 +615,12 @@ static int twl4030charger_presence(void)
ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
REG_STS_HW_CONDITIONS);
if (ret) {
- pr_err("BATTERY DRIVER: error reading STS_HW_CONDITIONS \n");
+ pr_err("twl4030_bci: error reading STS_HW_CONDITIONS\n");
return ret;
}
- ret = (hwsts & STS_CHG)? AC_PW_CONN: NO_PW_CONN;
- ret += (hwsts & STS_VBUS)? USB_PW_CONN: NO_PW_CONN;
+ ret = (hwsts & STS_CHG) ? AC_PW_CONN : NO_PW_CONN;
+ ret += (hwsts & STS_VBUS) ? USB_PW_CONN : NO_PW_CONN;
if (ret & USB_PW_CONN)
usb_charger_flag = 1;
@@ -659,7 +643,7 @@ static int twl4030bci_status(void)
ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
&status, REG_BCIMSTATEC);
if (ret) {
- pr_err("BATTERY DRIVER: error reading BCIMSTATEC \n");
+ pr_err("twl4030_bci: error reading BCIMSTATEC\n");
return ret;
}
@@ -905,11 +889,11 @@ static char *twl4030_bci_supplied_to[] = {
"twl4030_bci_battery",
};
-static int twl4030_bci_battery_probe(struct platform_device *dev)
+static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
{
+ struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
struct twl4030_bci_device_info *di;
int ret;
- struct twl4030_bci_platform_data *pdata = dev->dev.platform_data;
therm_tbl = pdata->battery_tmp_tbl;
@@ -917,9 +901,7 @@ static int twl4030_bci_battery_probe(struct platform_device *dev)
if (!di)
return -ENOMEM;
- platform_set_drvdata(dev, di);
-
- di->dev = &dev->dev;
+ di->dev = &pdev->dev;
di->bat.name = "twl4030_bci_battery";
di->bat.supplied_to = twl4030_bci_supplied_to;
di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
@@ -944,6 +926,8 @@ static int twl4030_bci_battery_probe(struct platform_device *dev)
twl4030battery_hw_level_en(ENABLE);
twl4030battery_hw_presence_en(ENABLE);
+ platform_set_drvdata(pdev, di);
+
/* settings for temperature sensing */
ret = twl4030battery_temp_setup();
if (ret)
@@ -956,26 +940,26 @@ static int twl4030_bci_battery_probe(struct platform_device *dev)
/* request BCI interruption */
ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
- IRQF_DISABLED, dev->name, NULL);
+ IRQF_DISABLED, pdev->name, NULL);
if (ret) {
- pr_err("BATTERY DRIVER: (BCI) IRQ%d is not free.\n",
- TWL4030_MODIRQ_PWR);
+ dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+ TWL4030_MODIRQ_BCI, ret);
goto batt_irq_fail;
}
/* request Power interruption */
ret = request_irq(TWL4030_PWRIRQ_CHG_PRES, twl4030charger_interrupt,
- 0, dev->name, di);
+ 0, pdev->name, di);
if (ret) {
- pr_err("BATTERY DRIVER: (POWER) IRQ%d is not free.\n",
- TWL4030_MODIRQ_PWR);
+ dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+ TWL4030_PWRIRQ_CHG_PRES, ret);
goto chg_irq_fail;
}
ret = power_supply_register(&dev->dev, &di->bat);
if (ret) {
- pr_err("BATTERY DRIVER: failed to register main battery\n");
+ dev_dbg(&pdev->dev, "failed to register main battery\n");
goto batt_failed;
}
@@ -983,9 +967,9 @@ static int twl4030_bci_battery_probe(struct platform_device *dev)
twl4030_bci_battery_work);
schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
- ret = power_supply_register(&dev->dev, &di->bk_bat);
+ ret = power_supply_register(&pdev->dev, &di->bk_bat);
if (ret) {
- pr_err("BATTERY DRIVER: failed to register backup battery\n");
+ dev_dbg(&pdev->dev, "failed to register backup battery\n");
goto bk_batt_failed;
}
@@ -1014,9 +998,9 @@ temp_setup_fail:
return ret;
}
-static int twl4030_bci_battery_remove(struct platform_device *dev)
+static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
{
- struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
twl4030charger_ac_en(DISABLE);
twl4030charger_usb_en(DISABLE);
@@ -1029,17 +1013,17 @@ static int twl4030_bci_battery_remove(struct platform_device *dev)
flush_scheduled_work();
power_supply_unregister(&di->bat);
power_supply_unregister(&di->bk_bat);
- platform_set_drvdata(dev, NULL);
+ platform_set_drvdata(pdev, NULL);
kfree(di);
return 0;
}
#ifdef CONFIG_PM
-static int twl4030_bci_battery_suspend(struct platform_device *dev,
+static int twl4030_bci_battery_suspend(struct platform_device *pdev,
pm_message_t state)
{
- struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
cancel_delayed_work(&di->twl4030_bci_monitor_work);
@@ -1047,37 +1031,42 @@ static int twl4030_bci_battery_suspend(struct platform_device *dev,
return 0;
}
-static int twl4030_bci_battery_resume(struct platform_device *dev)
+static int twl4030_bci_battery_resume(struct platform_device *pdev)
{
- struct twl4030_bci_device_info *di = platform_get_drvdata(dev);
+ struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 50);
return 0;
}
+#else
+#define twl4030_bci_battery_suspend NULL
+#define twl4030_bci_battery_resume NULL
#endif /* CONFIG_PM */
-/*
- * Battery driver module initializer function
- * registers battery driver structure
- */
+static struct platform_driver twl4030_bci_battery_driver = {
+ .probe = twl4030_bci_battery_probe,
+ .remove = __exit_p(twl4030_bci_battery_remove),
+ .suspend = twl4030_bci_battery_suspend,
+ .resume = twl4030_bci_battery_resume,
+ .driver = {
+ .name = "twl4030_bci",
+ },
+};
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030_bci");
+MODULE_AUTHOR("Texas Instruments Inc");
+
static int __init twl4030_battery_init(void)
{
return platform_driver_register(&twl4030_bci_battery_driver);
-
}
+module_init(twl4030_battery_init);
-/*
- * Battery driver module exit function
- * unregister battery driver structure
- */
static void __exit twl4030_battery_exit(void)
{
platform_driver_unregister(&twl4030_bci_battery_driver);
}
-
-module_init(twl4030_battery_init);
module_exit(twl4030_battery_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("twl4030_bci_battery");
-MODULE_AUTHOR("Texas Instruments Inc");
+
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 23/23] twl4030-bci: move to new style registration method
2008-09-30 10:05 ` [PATCH 22/23] twl4030: minor cleanups to twl4030_bci_battery.c Felipe Balbi
@ 2008-09-30 10:06 ` Felipe Balbi
0 siblings, 0 replies; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 10:06 UTC (permalink / raw)
To: linux-omap; +Cc: Tony Lindgren, David Brownell, Felipe Balbi
twl4030_bci_battery.c is now moved to new style
registration of twl4030 children.
During the process a few bugfixes came but the main one
is that twl4030-bci was releasing the wrong irq if
battery registration had failed.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
arch/arm/mach-omap2/Makefile | 4 +--
arch/arm/mach-omap2/bci.c | 57 ---------------------------------
arch/arm/mach-omap2/board-3430sdp.c | 18 ++++++++++-
arch/arm/mach-omap2/board-ldp.c | 18 ++++++++++-
arch/arm/plat-omap/include/mach/bci.h | 17 ----------
drivers/i2c/chips/twl4030-core.c | 50 +++++++++++++++++++++++++++++
drivers/power/twl4030_bci_battery.c | 25 +++++++++------
include/linux/i2c/twl4030.h | 5 +++
8 files changed, 105 insertions(+), 89 deletions(-)
delete mode 100644 arch/arm/mach-omap2/bci.c
delete mode 100644 arch/arm/plat-omap/include/mach/bci.h
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index e18da0c..33de217 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -54,8 +54,7 @@ obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
hsmmc.o \
usb-musb.o \
usb-ehci.o \
- board-3430sdp-flash.o \
- bci.o
+ board-3430sdp-flash.o
obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o \
hsmmc.o \
usb-musb.o usb-ehci.o \
@@ -65,7 +64,6 @@ obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
hsmmc.o \
- bci.o \
usb-musb.o
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o \
board-apollon-mmc.o \
diff --git a/arch/arm/mach-omap2/bci.c b/arch/arm/mach-omap2/bci.c
deleted file mode 100644
index 9b9f9d2..0000000
--- a/arch/arm/mach-omap2/bci.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/bci.c
- *
- * TWL4030 BCI platform device setup/initialization
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <mach/bci.h>
-
-#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
- defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
-/*
- * Thermistor Calibration for Current Source and MADC
- * Tolerance (for THS05-3H103F)
- */
-static int sdp3430_batt_table[] = {
-/* 0 C*/
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
-8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
-5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
-4040, 3910, 3790, 3670, 3550
-};
-
-static struct twl4030_bci_platform_data sdp3430_bci_data = {
- .battery_tmp_tbl = sdp3430_batt_table,
- .tblsize = ARRAY_SIZE(sdp3430_batt_table),
-};
-
-static struct platform_device twl4030_bci_battery_device = {
- .name = "twl4030-bci-battery",
- .id = -1,
- .dev = {
- .platform_data = &sdp3430_bci_data,
- },
- .num_resources = 0,
-};
-
-void __init twl4030_bci_battery_init(void)
-{
- (void) platform_device_register(&twl4030_bci_battery_device);
-}
-#else
-void __init twl4030_bci_battery_init(void)
-{
-}
-#endif
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 661d5d0..4264b68 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -300,6 +300,22 @@ static struct omap_board_config_kernel sdp3430_config[] __initdata = {
{ OMAP_TAG_LCD, &sdp3430_lcd_config },
};
+static int sdp3430_batt_table[] = {
+/* 0 C*/
+30800, 29500, 28300, 27100,
+26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
+17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
+11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
+8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
+5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
+4040, 3910, 3790, 3670, 3550
+};
+
+static struct twl4030_bci_platform_data sdp3430_bci_data = {
+ .battery_tmp_tbl = sdp3430_batt_table,
+ .tblsize = ARRAY_SIZE(sdp3430_batt_table),
+};
+
static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
@@ -319,6 +335,7 @@ static struct twl4030_platform_data sdp3430_twldata = {
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
+ .bci = &sdp3430_bci_data,
.gpio = &sdp3430_gpio_data,
.madc = &sdp3430_madc_data,
.keypad = &sdp3430_kp_data,
@@ -361,7 +378,6 @@ static void __init omap_3430sdp_init(void)
ads7846_dev_init();
sdp3430_flash_init();
msecure_init();
- twl4030_bci_battery_init();
omap_serial_init();
usb_musb_init();
usb_ehci_init();
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index a0e2c7a..35c03b7 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -183,6 +183,22 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
{ OMAP_TAG_UART, &ldp_uart_config },
};
+static int ldp_batt_table[] = {
+/* 0 C*/
+30800, 29500, 28300, 27100,
+26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
+17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
+11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
+8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
+5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
+4040, 3910, 3790, 3670, 3550
+};
+
+static struct twl4030_bci_platform_data ldp_bci_data = {
+ .battery_tmp_tbl = ldp_batt_table,
+ .tblsize = ARRAY_SIZE(ldp_batt_table),
+};
+
static struct twl4030_usb_data ldp_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -202,6 +218,7 @@ static struct twl4030_platform_data ldp_twldata = {
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
+ .bci = &ldp_bci_data,
.madc = &ldp_madc_data,
.usb = &ldp_usb_data,
.gpio = &ldp_gpio_data,
@@ -237,7 +254,6 @@ static void __init omap_ldp_init(void)
ARRAY_SIZE(ldp_spi_board_info));
msecure_init();
ads7846_dev_init();
- twl4030_bci_battery_init();
omap_serial_init();
usb_musb_init();
hsmmc_init();
diff --git a/arch/arm/plat-omap/include/mach/bci.h b/arch/arm/plat-omap/include/mach/bci.h
deleted file mode 100644
index 9baf59e..0000000
--- a/arch/arm/plat-omap/include/mach/bci.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/bci.h
- *
- * Copyright (C) 2008 Texas Instruments, Inc.
- *
- * 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.
- */
-#ifndef ASMARM_ARCH_BCI_H
-#define ASMARM_ARCH_BCI_H
-struct twl4030_bci_platform_data {
- int *battery_tmp_tbl;
- unsigned int tblsize;
-};
-#endif
-
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index efba776..9debab4 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -45,6 +45,13 @@
#define DRIVER_NAME "twl4030"
+#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
+ defined(CONFIG_TWL4030_BCI_BATTERY_MODUEL)
+#define twl_has_bci() true
+#else
+#define twl_has_bci() false
+#endif
+
#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
#define twl_has_keypad() true
#else
@@ -681,6 +688,49 @@ static int add_children(struct twl4030_platform_data *pdata)
struct twl4030_client *twl = NULL;
int status = 0;
+ if (twl_has_bci() && pdata->bci) {
+ twl = &twl4030_modules[TWL4030_SLAVENUM_NUM3];
+
+ pdev = platform_device_alloc("twl4030_bci", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ status = platform_device_add_data(pdev, pdata->bci,
+ sizeof(*pdata->bci));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add bci data, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (status == 0) {
+ struct resource r = {
+ .start = TWL4030_PWRIRQ_CHG_PRES,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create bci dev, %d\n",
+ status);
+ goto err;
+ }
+ }
+
if (twl_has_gpio() && pdata->gpio) {
twl = &twl4030_modules[TWL4030_SLAVENUM_NUM1];
diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
index 9ab6127..72a018b 100644
--- a/drivers/power/twl4030_bci_battery.c
+++ b/drivers/power/twl4030_bci_battery.c
@@ -23,7 +23,6 @@
#include <linux/platform_device.h>
#include <linux/i2c/twl4030.h>
#include <linux/power_supply.h>
-#include <mach/bci.h>
#include <linux/i2c/twl4030-madc.h>
#define T2_BATTERY_VOLT 0x04
@@ -583,9 +582,8 @@ static int twl4030battery_current(void)
*/
static int twl4030backupbatt_voltage(void)
{
- int ret, temp;
- u8 volt;
struct twl4030_madc_request req;
+ int temp;
req.channels = (1 << 9);
req.do_avg = 0;
@@ -826,9 +824,11 @@ static int twl4030_bci_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct twl4030_bci_device_info *di = to_twl4030_bci_device_info(psy);
+ struct twl4030_bci_device_info *di;
int status = 0;
+ di = to_twl4030_bci_device_info(psy);
+
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
val->intval = di->charge_status;
@@ -893,6 +893,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
{
struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
struct twl4030_bci_device_info *di;
+ int irq;
int ret;
therm_tbl = pdata->battery_tmp_tbl;
@@ -938,6 +939,8 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
if (ret)
goto voltage_setup_fail;
+ /* REVISIT do we need to request both IRQs ?? */
+
/* request BCI interruption */
ret = request_irq(TWL4030_MODIRQ_BCI, twl4030battery_interrupt,
IRQF_DISABLED, pdev->name, NULL);
@@ -947,17 +950,19 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
goto batt_irq_fail;
}
+ irq = platform_get_irq(pdev, 0);
+
/* request Power interruption */
- ret = request_irq(TWL4030_PWRIRQ_CHG_PRES, twl4030charger_interrupt,
+ ret = request_irq(irq, twl4030charger_interrupt,
0, pdev->name, di);
if (ret) {
dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
- TWL4030_PWRIRQ_CHG_PRES, ret);
+ irq, ret);
goto chg_irq_fail;
}
- ret = power_supply_register(&dev->dev, &di->bat);
+ ret = power_supply_register(&pdev->dev, &di->bat);
if (ret) {
dev_dbg(&pdev->dev, "failed to register main battery\n");
goto batt_failed;
@@ -982,9 +987,8 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
bk_batt_failed:
power_supply_unregister(&di->bat);
batt_failed:
- free_irq(TWL4030_MODIRQ_PWR, di);
+ free_irq(irq, di);
chg_irq_fail:
-prev_setup_err:
free_irq(TWL4030_MODIRQ_BCI, NULL);
batt_irq_fail:
voltage_setup_fail:
@@ -1001,6 +1005,7 @@ temp_setup_fail:
static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
{
struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
twl4030charger_ac_en(DISABLE);
twl4030charger_usb_en(DISABLE);
@@ -1008,7 +1013,7 @@ static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
twl4030battery_hw_presence_en(DISABLE);
free_irq(TWL4030_MODIRQ_BCI, NULL);
- free_irq(TWL4030_MODIRQ_PWR, di);
+ free_irq(irq, di);
flush_scheduled_work();
power_supply_unregister(&di->bat);
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 56a9415..1746733 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -52,6 +52,10 @@
#define TWL4030_MODULE_RTC 0x14
#define TWL4030_MODULE_SECURED_REG 0x15
+struct twl4030_bci_platform_data {
+ int *battery_tmp_tbl;
+ unsigned int tblsize;
+};
/* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
struct twl4030_gpio_platform_data {
@@ -91,6 +95,7 @@ struct twl4030_usb_data {
struct twl4030_platform_data {
unsigned irq_base, irq_end;
+ struct twl4030_bci_platform_data *bci;
struct twl4030_gpio_platform_data *gpio;
struct twl4030_madc_platform_data *madc;
struct twl4030_keypad_data *keypad;
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 00/23] twl4030 patches (v4)
2008-09-30 10:05 [PATCH 00/23] twl4030 patches (v4) Felipe Balbi
2008-09-30 10:05 ` [PATCH 01/23] twl4030: fix potential null pointer dereference Felipe Balbi
@ 2008-09-30 13:05 ` Tony Lindgren
2008-09-30 16:26 ` Steve Sakoman
1 sibling, 1 reply; 30+ messages in thread
From: Tony Lindgren @ 2008-09-30 13:05 UTC (permalink / raw)
To: Felipe Balbi; +Cc: linux-omap, David Brownell
* Felipe Balbi <felipe.balbi@nokia.com> [080930 13:34]:
> In this version there are irq fixes from David Brownell.
>
> David Brownell (11):
> twl4030 gpio platform data
> twl4030 uses gpiolib
> minor twl4030-core cleanups
> provide detailed diagnostics in add_children()
> move twl4030-gpio to drivers/gpio
> minor irq-related cleanups
> Move I2C driver model init earlier in the boot sequence
> twl4030-gpio irq_chip.set_type
> twl4030-gpio: remove legacy irq triggering calls and user
> twl4030-gpio: irq and other cleanup
> twl4030-core: portability updates
>
> Felipe Balbi (11):
> twl4030: fix potential null pointer dereference
> i2c: clean add_children a bit
> i2c: move twl4030_keypad to new style registration
> i2c: move twl4030-usb to platform_device
> i2c: twl4030-usb: add 'vbus' sysfs file
> i2c: move twl4030-madc to new registration style
> i2c: added a few missing gotos to add_children()
> i2c: switch twl4030-usb to use a resource for irq
> i2c: minor cleanups to twl4030-pwrbutton.c
> twl4030: minor cleanups to twl4030_bci_battery.c
> twl4030-bci: move to new style registration method
>
> Jagadeesh Bhaskar Pakaravoor (1):
> twl4030-gpio: Remove default pullup enable/disable of GPIO
Let's plan on applying these tomorrow unless there are more comments.
Tony
>
> arch/arm/mach-omap2/Makefile | 4 +-
> arch/arm/mach-omap2/bci.c | 57 ----
> arch/arm/mach-omap2/board-2430sdp.c | 32 ++-
> arch/arm/mach-omap2/board-3430sdp.c | 49 +++-
> arch/arm/mach-omap2/board-ldp.c | 37 +++-
> arch/arm/mach-omap2/board-omap2evm.c | 33 ++-
> arch/arm/mach-omap2/board-omap3beagle.c | 19 ++
> arch/arm/mach-omap2/board-omap3evm.c | 85 +++---
> arch/arm/mach-omap2/board-overo.c | 11 +
> arch/arm/mach-omap2/hsmmc.c | 5 -
> arch/arm/plat-omap/include/mach/bci.h | 17 -
> arch/arm/plat-omap/include/mach/irqs.h | 2 +-
> drivers/gpio/Kconfig | 7 +
> drivers/gpio/Makefile | 1 +
> drivers/{i2c/chips => gpio}/twl4030-gpio.c | 418 +++++++++++++++++++--------
> drivers/i2c/chips/Kconfig | 20 --
> drivers/i2c/chips/Makefile | 1 -
> drivers/i2c/chips/twl4030-core.c | 344 +++++++++++++++++++---
> drivers/i2c/chips/twl4030-madc.c | 243 ++++++++++------
> drivers/i2c/chips/twl4030-pwrbutton.c | 10 +-
> drivers/i2c/chips/twl4030-usb.c | 373 ++++++++++++------------
> drivers/i2c/i2c-core.c | 2 +-
> drivers/input/keyboard/omap-twl4030keypad.c | 10 +-
> drivers/mmc/host/omap_hsmmc.c | 4 +-
> drivers/power/twl4030_bci_battery.c | 184 ++++++------
> drivers/rtc/rtc-twl4030.c | 11 +-
> include/linux/i2c/twl4030.h | 64 ++++-
> 27 files changed, 1306 insertions(+), 737 deletions(-)
> delete mode 100644 arch/arm/mach-omap2/bci.c
> delete mode 100644 arch/arm/plat-omap/include/mach/bci.h
> rename drivers/{i2c/chips => gpio}/twl4030-gpio.c (67%)
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 16/23] Move I2C driver model init earlier in the boot sequence
2008-09-30 10:05 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence Felipe Balbi
2008-09-30 10:05 ` [PATCH 17/23] i2c: minor cleanups to twl4030-pwrbutton.c Felipe Balbi
@ 2008-09-30 15:52 ` David Brownell
1 sibling, 0 replies; 30+ messages in thread
From: David Brownell @ 2008-09-30 15:52 UTC (permalink / raw)
To: Felipe Balbi; +Cc: linux-omap, Tony Lindgren
On Tuesday 30 September 2008, Felipe Balbi wrote:
> From: David Brownell <dbrownell@users.sourceforge.net>
>
> This avoids oopsing in statically linked systems when some
> subsystems register I2C drivers in subsys_initcall() code,
> but those subsystems are linked (and initialized) before I2C.
>
> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
And as of this morning:
Signed-off-by: Jean Delvare <khali@linux-fr.org>
> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
> ---
> drivers/i2c/i2c-core.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index b346a68..f520108 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -978,7 +978,7 @@ static void __exit i2c_exit(void)
> bus_unregister(&i2c_bus_type);
> }
>
> -subsys_initcall(i2c_init);
> +postcore_initcall(i2c_init);
> module_exit(i2c_exit);
>
> /* ----------------------------------------------------
> --
> 1.6.0.2.307.gc427
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 00/23] twl4030 patches (v4)
2008-09-30 13:05 ` [PATCH 00/23] twl4030 patches (v4) Tony Lindgren
@ 2008-09-30 16:26 ` Steve Sakoman
2008-09-30 17:37 ` Felipe Balbi
0 siblings, 1 reply; 30+ messages in thread
From: Steve Sakoman @ 2008-09-30 16:26 UTC (permalink / raw)
To: linux-omap; +Cc: Felipe Balbi, David Brownell, Tony Lindgren
On Tue, Sep 30, 2008 at 6:05 AM, Tony Lindgren <tony@atomide.com> wrote:
> Let's plan on applying these tomorrow unless there are more comments.
I'm seeing some issues on Overo when applying these patches.
On a cold boot everything proceeds normally (including devices being
enumerated on the musb channel) until the kernel attempts to mount the
rootfs from mmc. At that point boot messages stop:
mmc0: new high speed SD card at address 55ce
mmcblk0: mmc0:55ce SD02G 1921024KiB
mmcblk0:<7>mmc0: starting CMD18 arg 00000000 flags 000000b5
p1 p2
At first I thought mmc support was broken and the system was hung.
But after a 10 - 20 second delay I noticed that approximately every 10
seconds I get the following message:
musb_h_tx_flush_fifo 124: Could not flush host TX fifo: csr: 000a
After a few cycles of this the boot continues and completes normally,
but the musb port is now non-functional.
If I do a reboot command or press the reset button, the overo reboots
without the above delays or error messages, however the musb port is
non-functional.
It seems that something has gone awry in the twl4030 usb section,
since I get a functional system without these patches. Any
suggestions as to where I should begin looking to help debug this?
Steve
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 00/23] twl4030 patches (v4)
2008-09-30 16:26 ` Steve Sakoman
@ 2008-09-30 17:37 ` Felipe Balbi
2008-09-30 18:12 ` Steve Sakoman
0 siblings, 1 reply; 30+ messages in thread
From: Felipe Balbi @ 2008-09-30 17:37 UTC (permalink / raw)
To: Steve Sakoman; +Cc: linux-omap, Felipe Balbi, David Brownell, Tony Lindgren
On Tue, Sep 30, 2008 at 09:26:09AM -0700, Steve Sakoman wrote:
> On Tue, Sep 30, 2008 at 6:05 AM, Tony Lindgren <tony@atomide.com> wrote:
>
> > Let's plan on applying these tomorrow unless there are more comments.
>
> I'm seeing some issues on Overo when applying these patches.
>
> On a cold boot everything proceeds normally (including devices being
> enumerated on the musb channel) until the kernel attempts to mount the
> rootfs from mmc. At that point boot messages stop:
>
> mmc0: new high speed SD card at address 55ce
> mmcblk0: mmc0:55ce SD02G 1921024KiB
> mmcblk0:<7>mmc0: starting CMD18 arg 00000000 flags 000000b5
> p1 p2
>
> At first I thought mmc support was broken and the system was hung.
> But after a 10 - 20 second delay I noticed that approximately every 10
> seconds I get the following message:
>
> musb_h_tx_flush_fifo 124: Could not flush host TX fifo: csr: 000a
>
> After a few cycles of this the boot continues and completes normally,
> but the musb port is now non-functional.
>
> If I do a reboot command or press the reset button, the overo reboots
> without the above delays or error messages, however the musb port is
> non-functional.
>
> It seems that something has gone awry in the twl4030 usb section,
> since I get a functional system without these patches. Any
> suggestions as to where I should begin looking to help debug this?
remove the devices you have attached to musb port for now. musb
shouldn't prevent these patches from being applied. As I said before,
musb otg-host mode is not quite ok for omap3.
I'm pretty sure we're gonna have a lot to patch in order to get it in
good shape. A few patches are already coming from mainline btw.
--
balbi
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user
2008-09-30 10:05 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user Felipe Balbi
2008-09-30 10:05 ` [PATCH 20/23] twl4030-gpio: irq and other cleanup Felipe Balbi
@ 2008-09-30 17:37 ` David Brownell
1 sibling, 0 replies; 30+ messages in thread
From: David Brownell @ 2008-09-30 17:37 UTC (permalink / raw)
To: Felipe Balbi; +Cc: linux-omap, Tony Lindgren
Here's an important bugfix ... strictly speaking the bug was
introduced in patch #18, but rather than redo both patches
I think it's simpler to just merge this one-liner here where
it could first have been noticed.
With this, I can confirm I've actually seen TWL triggering
GPIO interrupts ... on the appropriate edge. At least,
when using GPIO-1, since I wasn't keen on trying to use
GPIO-0 to report removal of my SD-resident rootfs. ;)
--- beagle.orig/drivers/gpio/twl4030-gpio.c 2008-09-30 10:28:25.000000000 -0700
+++ beagle/drivers/gpio/twl4030-gpio.c 2008-09-30 10:28:18.000000000 -0700
@@ -652,7 +652,8 @@ static int twl4030_gpio_unmask_thread(vo
type = desc->status & IRQ_TYPE_SENSE_MASK;
spin_unlock_irq(&desc->lock);
- twl4030_set_gpio_edge_ctrl(irq, type);
+ twl4030_set_gpio_edge_ctrl(irq - twl4030_gpio_irq_base,
+ type);
}
local_irq_disable();
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 00/23] twl4030 patches (v4)
2008-09-30 17:37 ` Felipe Balbi
@ 2008-09-30 18:12 ` Steve Sakoman
0 siblings, 0 replies; 30+ messages in thread
From: Steve Sakoman @ 2008-09-30 18:12 UTC (permalink / raw)
To: me; +Cc: linux-omap, Felipe Balbi, David Brownell, Tony Lindgren
On Tue, Sep 30, 2008 at 10:37 AM, Felipe Balbi <me@felipebalbi.com> wrote:
> On Tue, Sep 30, 2008 at 09:26:09AM -0700, Steve Sakoman wrote:
>> On Tue, Sep 30, 2008 at 6:05 AM, Tony Lindgren <tony@atomide.com> wrote:
>>
>> > Let's plan on applying these tomorrow unless there are more comments.
>>
>> I'm seeing some issues on Overo when applying these patches.
>>
>> On a cold boot everything proceeds normally (including devices being
>> enumerated on the musb channel) until the kernel attempts to mount the
>> rootfs from mmc. At that point boot messages stop:
>>
>> mmc0: new high speed SD card at address 55ce
>> mmcblk0: mmc0:55ce SD02G 1921024KiB
>> mmcblk0:<7>mmc0: starting CMD18 arg 00000000 flags 000000b5
>> p1 p2
>>
>> At first I thought mmc support was broken and the system was hung.
>> But after a 10 - 20 second delay I noticed that approximately every 10
>> seconds I get the following message:
>>
>> musb_h_tx_flush_fifo 124: Could not flush host TX fifo: csr: 000a
>>
>> After a few cycles of this the boot continues and completes normally,
>> but the musb port is now non-functional.
>>
>> If I do a reboot command or press the reset button, the overo reboots
>> without the above delays or error messages, however the musb port is
>> non-functional.
>>
>> It seems that something has gone awry in the twl4030 usb section,
>> since I get a functional system without these patches. Any
>> suggestions as to where I should begin looking to help debug this?
>
> remove the devices you have attached to musb port for now. musb
> shouldn't prevent these patches from being applied. As I said before,
> musb otg-host mode is not quite ok for omap3.
>
> I'm pretty sure we're gonna have a lot to patch in order to get it in
> good shape. A few patches are already coming from mainline btw.
I should have mentioned that these patches were applied to current top
of tree *plus* the 7 musb patches you have queued up on linux-usb
list.
Steve
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2008-09-30 18:12 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-30 10:05 [PATCH 00/23] twl4030 patches (v4) Felipe Balbi
2008-09-30 10:05 ` [PATCH 01/23] twl4030: fix potential null pointer dereference Felipe Balbi
2008-09-30 10:05 ` [PATCH 02/23] twl4030-gpio: Remove default pullup enable/disable of GPIO Felipe Balbi
2008-09-30 10:05 ` [PATCH 03/23] i2c: clean add_children a bit Felipe Balbi
2008-09-30 10:05 ` [PATCH 04/23] i2c: move twl4030_keypad to new style registration Felipe Balbi
2008-09-30 10:05 ` [PATCH 05/23] i2c: move twl4030-usb to platform_device Felipe Balbi
2008-09-30 10:05 ` [PATCH 06/23] i2c: twl4030-usb: add 'vbus' sysfs file Felipe Balbi
2008-09-30 10:05 ` [PATCH 07/23] twl4030 gpio platform data Felipe Balbi
2008-09-30 10:05 ` [PATCH 08/23] twl4030 uses gpiolib Felipe Balbi
2008-09-30 10:05 ` [PATCH 09/23] i2c: move twl4030-madc to new registration style Felipe Balbi
2008-09-30 10:05 ` [PATCH 10/23] minor twl4030-core cleanups Felipe Balbi
2008-09-30 10:05 ` [PATCH 11/23] provide detailed diagnostics in add_children() Felipe Balbi
2008-09-30 10:05 ` [PATCH 12/23] move twl4030-gpio to drivers/gpio Felipe Balbi
2008-09-30 10:05 ` [PATCH 13/23] i2c: added a few missing gotos to add_children() Felipe Balbi
2008-09-30 10:05 ` [PATCH 14/23] minor irq-related cleanups Felipe Balbi
2008-09-30 10:05 ` [PATCH 15/23] i2c: switch twl4030-usb to use a resource for irq Felipe Balbi
2008-09-30 10:05 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence Felipe Balbi
2008-09-30 10:05 ` [PATCH 17/23] i2c: minor cleanups to twl4030-pwrbutton.c Felipe Balbi
2008-09-30 10:05 ` [PATCH 18/23] twl4030-gpio irq_chip.set_type Felipe Balbi
2008-09-30 10:05 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user Felipe Balbi
2008-09-30 10:05 ` [PATCH 20/23] twl4030-gpio: irq and other cleanup Felipe Balbi
2008-09-30 10:05 ` [PATCH 21/23] twl4030-core: portability updates Felipe Balbi
2008-09-30 10:05 ` [PATCH 22/23] twl4030: minor cleanups to twl4030_bci_battery.c Felipe Balbi
2008-09-30 10:06 ` [PATCH 23/23] twl4030-bci: move to new style registration method Felipe Balbi
2008-09-30 17:37 ` [PATCH 19/23] twl4030-gpio: remove legacy irq triggering calls and user David Brownell
2008-09-30 15:52 ` [PATCH 16/23] Move I2C driver model init earlier in the boot sequence David Brownell
2008-09-30 13:05 ` [PATCH 00/23] twl4030 patches (v4) Tony Lindgren
2008-09-30 16:26 ` Steve Sakoman
2008-09-30 17:37 ` Felipe Balbi
2008-09-30 18:12 ` Steve Sakoman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox