* [PATCH 0/4] twl4030 driver changes
@ 2008-09-25 14:48 Felipe Balbi
2008-09-25 14:48 ` [PATCH 1/4] i2c: clean add_children a bit Felipe Balbi
2008-09-25 16:26 ` [PATCH 0/4] twl4030 driver changes David Brownell
0 siblings, 2 replies; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 14:48 UTC (permalink / raw)
To: linux-omap; +Cc: David Brownell, Tony Lindgren, Felipe Balbi
Move twl4030 keypad and usb to new style of
registration for twl4030 driver introduced
by David Brownell.
This is how the device tree looks now:
$ find /sys | grep twl4030
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/uevent
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/modalias
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/subsystem
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/bus
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/power
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/power/wakeup
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/driver
/sys/class/i2c-adapter/i2c-1/1-0048/twl4030_usb/vbus
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/uevent
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/modalias
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/subsystem
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/bus
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/power
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/power/wakeup
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/driver
/sys/class/i2c-adapter/i2c-1/1-004a/twl4030_keypad/input:input1
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/uevent
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/modalias
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/subsystem
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/bus
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/power
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/power/wakeup
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/driver
/sys/class/i2c-adapter/i2c-1/1-004b/twl4030_rtc/rtc:rtc0
Felipe Balbi (4):
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
arch/arm/mach-omap2/board-2430sdp.c | 20 +-
arch/arm/mach-omap2/board-3430sdp.c | 19 +-
arch/arm/mach-omap2/board-omap2evm.c | 21 +-
arch/arm/mach-omap2/board-omap3evm.c | 20 +-
drivers/i2c/chips/Kconfig | 16 --
drivers/i2c/chips/twl4030-core.c | 100 ++++++--
drivers/i2c/chips/twl4030-usb.c | 373 ++++++++++++++-------------
drivers/input/keyboard/omap-twl4030keypad.c | 6 +-
include/linux/i2c/twl4030.h | 38 +++
9 files changed, 344 insertions(+), 269 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] i2c: clean add_children a bit
2008-09-25 14:48 [PATCH 0/4] twl4030 driver changes Felipe Balbi
@ 2008-09-25 14:48 ` Felipe Balbi
2008-09-25 14:48 ` [PATCH 2/4] i2c: move twl4030_keypad to new style registration Felipe Balbi
2008-09-25 17:28 ` [PATCH 1/4] i2c: clean add_children a bit David Brownell
2008-09-25 16:26 ` [PATCH 0/4] twl4030 driver changes David Brownell
1 sibling, 2 replies; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 14:48 UTC (permalink / raw)
To: linux-omap; +Cc: David Brownell, Tony Lindgren, 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 | 58 ++++++++++++++++++++-----------------
include/linux/i2c/twl4030.h | 6 ++++
2 files changed, 37 insertions(+), 27 deletions(-)
diff --git a/drivers/i2c/chips/twl4030-core.c b/drivers/i2c/chips/twl4030-core.c
index 47f65f8..bbffc40 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -639,34 +639,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;
}
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index 2434ad0..ff1dff4 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -145,4 +145,10 @@ int twl4030_free_gpio(int gpio);
static inline int twl4030charger_usb_en(int enable) { return 0; }
#endif
+#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
+#define twl_has_rtc() (1)
+#else
+#define twl_has_rtc() (0)
+#endif
+
#endif /* End of __TWL4030_H */
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] i2c: move twl4030_keypad to new style registration
2008-09-25 14:48 ` [PATCH 1/4] i2c: clean add_children a bit Felipe Balbi
@ 2008-09-25 14:48 ` Felipe Balbi
2008-09-25 14:48 ` [PATCH 3/4] i2c: move twl4030-usb to platform_device Felipe Balbi
2008-09-25 17:28 ` [PATCH 1/4] i2c: clean add_children a bit David Brownell
1 sibling, 1 reply; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 14:48 UTC (permalink / raw)
To: linux-omap; +Cc: David Brownell, Tony Lindgren, 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 | 16 +++++-----------
drivers/i2c/chips/twl4030-core.c | 21 +++++++++++++++++++++
drivers/input/keyboard/omap-twl4030keypad.c | 6 +++---
include/linux/i2c/twl4030.h | 16 ++++++++++++++++
7 files changed, 58 insertions(+), 45 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..350f147 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..a9346b1 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -93,6 +93,9 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
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[] = {
@@ -187,23 +190,15 @@ static int omap3evm_keymap[] = {
KEY(3, 3, KEY_P)
};
-static struct omap_kp_platform_data omap3evm_kp_data = {
+static struct twl4030_keypad_data omap3evm_kp_data = {
.rows = 4,
.cols = 4,
- .keymap = omap3evm_keymap,
+ .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 +214,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 bbffc40..241752f 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -669,6 +669,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..eefdb78 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,
},
};
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index ff1dff4..246eef3 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 */
};
@@ -151,4 +161,10 @@ int twl4030_free_gpio(int gpio);
#define twl_has_rtc() (0)
#endif
+#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
+#define twl_has_keypad() (1)
+#else
+#define twl_has_keypad() (0)
+#endif
+
#endif /* End of __TWL4030_H */
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] i2c: move twl4030-usb to platform_device
2008-09-25 14:48 ` [PATCH 2/4] i2c: move twl4030_keypad to new style registration Felipe Balbi
@ 2008-09-25 14:48 ` Felipe Balbi
2008-09-25 14:48 ` [PATCH 4/4] i2c: twl4030-usb: add 'vbus' sysfs file Felipe Balbi
0 siblings, 1 reply; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 14:48 UTC (permalink / raw)
To: linux-omap; +Cc: David Brownell, Tony Lindgren, 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-omap2evm.c | 5 +
arch/arm/mach-omap2/board-omap3evm.c | 4 +
drivers/i2c/chips/Kconfig | 16 --
drivers/i2c/chips/twl4030-core.c | 21 +++
drivers/i2c/chips/twl4030-usb.c | 328 +++++++++++++++-------------------
include/linux/i2c/twl4030.h | 16 ++
8 files changed, 202 insertions(+), 199 deletions(-)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 8c4c9dd..f35c252 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_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-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c
index 350f147..0f9ad3f 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-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index a9346b1..94e5744 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 struct twl4030_platform_data omap3evm_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
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 241752f..afc566a 100644
--- a/drivers/i2c/chips/twl4030-core.c
+++ b/drivers/i2c/chips/twl4030-core.c
@@ -690,6 +690,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..e790c34 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,65 @@ 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;
-
- the_transceiver = twl;
+ return -ENOMEM;
+ 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;
- usb_irq_disable();
+ if (!pdata) {
+ dev_info(&pdev->dev, "platform_data not available, defaulting"
+ " to ULPI mode\n");
+ twl->usb_mode = T2_USB_MODE_ULPI;
+ } else {
+ twl->usb_mode = pdata->usb_mode;
+ }
+
+ 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");
+ dev_set_drvdata(&pdev->dev, 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 = dev_get_drvdata(&pdev->dev);
int val;
- usb_irq_disable();
+ usb_irq_disable(twl);
free_irq(twl->irq, twl);
/* set transceiver mode to power on defaults */
@@ -755,11 +697,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 +710,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 246eef3..950bf0f 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 */
};
@@ -167,4 +177,10 @@ int twl4030_free_gpio(int gpio);
#define twl_has_keypad() (0)
#endif
+#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
+#define twl_has_usb() (1)
+#else
+#define twl_has_usb() (0)
+#endif
+
#endif /* End of __TWL4030_H */
--
1.6.0.2.307.gc427
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] i2c: twl4030-usb: add 'vbus' sysfs file
2008-09-25 14:48 ` [PATCH 3/4] i2c: move twl4030-usb to platform_device Felipe Balbi
@ 2008-09-25 14:48 ` Felipe Balbi
0 siblings, 0 replies; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 14:48 UTC (permalink / raw)
To: linux-omap; +Cc: David Brownell, Tony Lindgren, 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 e790c34..dbd2e43 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,16 +668,22 @@ 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)
return -ENOMEM;
+ 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->vbus = vbus ? 1 : 0;
if (!pdata) {
dev_info(&pdev->dev, "platform_data not available, defaulting"
@@ -653,6 +693,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
twl->usb_mode = pdata->usb_mode;
}
+ /* 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);
if (status < 0) {
@@ -662,7 +708,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);
@@ -679,6 +724,9 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, 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;
}
@@ -689,6 +737,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] 9+ messages in thread
* Re: [PATCH 0/4] twl4030 driver changes
2008-09-25 14:48 [PATCH 0/4] twl4030 driver changes Felipe Balbi
2008-09-25 14:48 ` [PATCH 1/4] i2c: clean add_children a bit Felipe Balbi
@ 2008-09-25 16:26 ` David Brownell
2008-09-25 16:38 ` Felipe Balbi
1 sibling, 1 reply; 9+ messages in thread
From: David Brownell @ 2008-09-25 16:26 UTC (permalink / raw)
To: Felipe Balbi; +Cc: linux-omap, Tony Lindgren
On Thursday 25 September 2008, Felipe Balbi wrote:
> Move twl4030 keypad and usb to new style of
> registration for twl4030 driver
I can tell I'm going to need to accelerate my
GPIO updates! :)
Cool. I'll look at this after breakfast...
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/4] twl4030 driver changes
2008-09-25 16:26 ` [PATCH 0/4] twl4030 driver changes David Brownell
@ 2008-09-25 16:38 ` Felipe Balbi
0 siblings, 0 replies; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 16:38 UTC (permalink / raw)
To: David Brownell; +Cc: Felipe Balbi, linux-omap, Tony Lindgren
On Thu, 25 Sep 2008 09:26:12 -0700, David Brownell <david-b@pacbell.net>
wrote:
> On Thursday 25 September 2008, Felipe Balbi wrote:
>> Move twl4030 keypad and usb to new style of
>> registration for twl4030 driver
>
> I can tell I'm going to need to accelerate my
> GPIO updates! :)
>
> Cool. I'll look at this after breakfast...
ehehe, I'm planning on playing with madc tomorrow, so
maybe yeah, we're gonna need your gpio changes soonish :-)
on the other hand, remember I already had a patch converting
twl4030-usb to platform_device, I just had to update a few
stuff and that was it :-p
--
Best Regards,
Felipe Balbi
http://blog.felipebalbi.com
me@felipebalbi.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] i2c: clean add_children a bit
2008-09-25 14:48 ` [PATCH 1/4] i2c: clean add_children a bit Felipe Balbi
2008-09-25 14:48 ` [PATCH 2/4] i2c: move twl4030_keypad to new style registration Felipe Balbi
@ 2008-09-25 17:28 ` David Brownell
2008-09-25 22:08 ` Felipe Balbi
1 sibling, 1 reply; 9+ messages in thread
From: David Brownell @ 2008-09-25 17:28 UTC (permalink / raw)
To: Felipe Balbi; +Cc: linux-omap, Tony Lindgren
On Thursday 25 September 2008, Felipe Balbi wrote:
> Clean up add_children a bit before adding more children
> to twl4030-core.c
>
> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
ACK, except for:
> --- a/include/linux/i2c/twl4030.h
> +++ b/include/linux/i2c/twl4030.h
> @@ -145,4 +145,10 @@ int twl4030_free_gpio(int gpio);
> static inline int twl4030charger_usb_en(int enable) { return 0; }
> #endif
>
> +#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
> +#define twl_has_rtc() (1)
> +#else
> +#define twl_has_rtc() (0)
> +#endif
Who else would need this, other than the core?
I think the answer is "nobody" ... so these macros
belong in the core itself, not a public header.
Also: parens not appropriate around those values; and
"true" and "false" values would be a bit more clear...
> +
> #endif /* End of __TWL4030_H */
> --
> 1.6.0.2.307.gc427
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] i2c: clean add_children a bit
2008-09-25 17:28 ` [PATCH 1/4] i2c: clean add_children a bit David Brownell
@ 2008-09-25 22:08 ` Felipe Balbi
0 siblings, 0 replies; 9+ messages in thread
From: Felipe Balbi @ 2008-09-25 22:08 UTC (permalink / raw)
To: David Brownell; +Cc: Felipe Balbi, linux-omap, Tony Lindgren
Hi Dave,
On Thu, 25 Sep 2008 10:28:00 -0700, David Brownell <david-b@pacbell.net>
wrote:
> On Thursday 25 September 2008, Felipe Balbi wrote:
>> Clean up add_children a bit before adding more children
>> to twl4030-core.c
>>
>> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
>
> ACK, except for:
>
>> --- a/include/linux/i2c/twl4030.h
>> +++ b/include/linux/i2c/twl4030.h
>> @@ -145,4 +145,10 @@ int twl4030_free_gpio(int gpio);
>> static inline int twl4030charger_usb_en(int enable) { return 0; }
>> #endif
>>
>> +#if defined(CONFIG_RTC_DRV_TWL4030) ||
> defined(CONFIG_RTC_DRV_TWL4030_MODULE)
>> +#define twl_has_rtc() (1)
>> +#else
>> +#define twl_has_rtc() (0)
>> +#endif
>
> Who else would need this, other than the core?
> I think the answer is "nobody" ... so these macros
> belong in the core itself, not a public header.
>
> Also: parens not appropriate around those values; and
> "true" and "false" values would be a bit more clear...
you sure got a point here, I'll update the series when
I get to work tomorrow (actualy today, already 1am).
Anyways, I'll update and resend the series.
--
Best Regards,
Felipe Balbi
http://blog.felipebalbi.com
me@felipebalbi.com
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-09-25 22:08 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-25 14:48 [PATCH 0/4] twl4030 driver changes Felipe Balbi
2008-09-25 14:48 ` [PATCH 1/4] i2c: clean add_children a bit Felipe Balbi
2008-09-25 14:48 ` [PATCH 2/4] i2c: move twl4030_keypad to new style registration Felipe Balbi
2008-09-25 14:48 ` [PATCH 3/4] i2c: move twl4030-usb to platform_device Felipe Balbi
2008-09-25 14:48 ` [PATCH 4/4] i2c: twl4030-usb: add 'vbus' sysfs file Felipe Balbi
2008-09-25 17:28 ` [PATCH 1/4] i2c: clean add_children a bit David Brownell
2008-09-25 22:08 ` Felipe Balbi
2008-09-25 16:26 ` [PATCH 0/4] twl4030 driver changes David Brownell
2008-09-25 16:38 ` Felipe Balbi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox