public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Changes for adding and building TPS6235x based PR785 board support
@ 2009-01-13  7:41 Manikandan Pillai
  2009-01-13 14:59 ` Tony Lindgren
  0 siblings, 1 reply; 4+ messages in thread
From: Manikandan Pillai @ 2009-01-13  7:41 UTC (permalink / raw)
  To: linux-omap, broonie; +Cc: Manikandan Pillai

TPS6235x chip based PR785 power modules are from Texas Instruments
for OMAP3 EVM boards. This patch supports the PR785 card
and provides the driver support for the TPS devices.

For compilation, the LCD and MMC drivers are modified and will not
work. Further patches will be provided for support of LCD and MMC
with PR785 boards.

Signed-off-by: Manikandan Pillai <mani.pillai@ti.com>
---
 arch/arm/mach-omap2/Kconfig          |   11 +++
 arch/arm/mach-omap2/board-omap3evm.c |  137 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/mmc-twl4030.c    |    4 +-
 arch/arm/plat-omap/i2c.c             |   69 +++++++++++++++++-
 drivers/video/omap/lcd_omap3evm.c    |    6 ++
 5 files changed, 225 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 0a86a88..91890be 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -121,6 +121,17 @@ config MACH_OMAP3EVM
 	bool "OMAP 3530 EVM board"
 	depends on ARCH_OMAP3 && ARCH_OMAP34XX
 
+menu 	"PR785 Power board selection for OMAP3 EVM"
+config OMAP3EVM_PR785
+	bool "Power board for OMAP3 EVM"
+	depends on I2C=y && ARCH_OMAP34XX
+	help
+	Say yes here if you are using the TPS6235x based PR785 Power Module
+	for the EVM boards. This core driver provides register access and IRQ
+	handling facilities, and registers devices for the various functions
+	so that function-specific drivers can bind to them.
+endmenu
+
 config MACH_OMAP3_BEAGLE
 	bool "OMAP3 BEAGLE board"
 	depends on ARCH_OMAP3 && ARCH_OMAP34XX
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index e4e60e2..60d2d22 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -36,12 +36,19 @@
 #include <mach/usb-ehci.h>
 #include <mach/common.h>
 #include <mach/mcspi.h>
+#include <mach/mux.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "twl4030-generic-scripts.h"
 #include "mmc-twl4030.h"
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
 
+#define TPS6235X_REG_MAX	3
 
+#if defined(CONFIG_OMAP3EVM_PR785) && defined(CONFIG_TWL4030_CORE)
+#error config err : only one of OMAP3EVM_PR785 or TWL4030_CORE can be defined
+#endif
 static struct resource omap3evm_smc911x_resources[] = {
 	[0] =	{
 		.start  = OMAP3EVM_ETHR_START,
@@ -89,6 +96,7 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
+#if defined(CONFIG_TWL4030_CORE)
 static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -150,16 +158,125 @@ static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
 		.platform_data = &omap3evm_twldata,
 	},
 };
+#endif
+
+#if defined(CONFIG_OMAP3EVM_PR785)
+/* CORE voltage regulator */
+struct regulator_consumer_supply tps62352_core_consumers = {
+	.supply = "vdd2",
+};
+
+/* MPU voltage regulator */
+struct regulator_consumer_supply tps62352_mpu_consumers = {
+	.supply = "vdd1",
+};
+
+struct regulator_init_data vdd2_tps_regulator_data = {
+		.constraints = {
+			.min_uV = 750000,
+			.max_uV = 1537000,
+			.valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
+				REGULATOR_CHANGE_STATUS),
+		},
+		.num_consumer_supplies  = 1,
+		.consumer_supplies      = &tps62352_core_consumers,
+};
+
+struct regulator_init_data vdd1_tps_regulator_data = {
+		.constraints = {
+			.min_uV = 750000,
+			.max_uV = 1537000,
+			.valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
+				REGULATOR_CHANGE_STATUS),
+		},
+		.num_consumer_supplies  = 1,
+		.consumer_supplies      = &tps62352_mpu_consumers,
+};
+
+static struct i2c_board_info __initdata tps_6235x_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("tps62352", 0x4A),
+		.flags = I2C_CLIENT_WAKE,
+		.platform_data = &vdd2_tps_regulator_data,
+	},
+	{
+		I2C_BOARD_INFO("tps62353", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.platform_data = &vdd1_tps_regulator_data,
+	},
+};
+#endif
 
 static int __init omap3_evm_i2c_init(void)
 {
+#if defined(CONFIG_OMAP3EVM_PR785)
+	omap_register_i2c_bus(1, 2600, tps_6235x_i2c_board_info,
+		ARRAY_SIZE(tps_6235x_i2c_board_info));
+#endif
+#if defined(CONFIG_TWL4030_CORE)
 	omap_register_i2c_bus(1, 2600, omap3evm_i2c_boardinfo,
 			ARRAY_SIZE(omap3evm_i2c_boardinfo));
+#endif
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
 	return 0;
 }
 
+/*
+ * Read a value from a register in an tps_6235x device.
+ * The value is returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+int tps_6235x_read_reg(struct i2c_client *client, u8 reg, u8 *val)
+{
+	u8 data;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	if (reg > TPS6235X_REG_MAX)
+		return -1;
+
+	data = i2c_smbus_read_byte_data(client, reg);
+	*val = data;
+	return 0;
+}
+
+/*
+ * Write a value to a register in an tps_6235x device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+int tps_6235x_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+	int err;
+	int retry = 0;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	if (reg > TPS6235X_REG_MAX)
+		return -1;
+
+again:
+	err = i2c_smbus_write_byte_data(client, reg, val);
+	if (err >= 0)
+		return 0;
+
+	dev_err(&client->dev,
+		"wrote 0x%.2x to offset 0x%.2x error %d\n", val, reg, err);
+
+	/* Try 3 times */
+	if (retry <= 3) {
+		dev_info(&client->dev, "retry ... %d\n", retry);
+		retry++;
+		schedule_timeout(msecs_to_jiffies(20));
+		goto again;
+	}
+	return err;
+}
+
+/*-------------------------------------------------------------------*/
+
 static struct platform_device omap3_evm_lcd_device = {
 	.name		= "omap3evm_lcd",
 	.id		= -1,
@@ -233,6 +350,7 @@ static struct platform_device *omap3_evm_devices[] __initdata = {
 	&omap3evm_smc911x_device,
 };
 
+#if defined(CONFIG_TWL4030_CORE)
 static struct twl4030_hsmmc_info mmc[] __initdata = {
 	{
 		.mmc		= 1,
@@ -242,6 +360,20 @@ static struct twl4030_hsmmc_info mmc[] __initdata = {
 	},
 	{}	/* Terminator */
 };
+#endif
+
+static void omap_init_pr785(void)
+{
+	/* Initialize the mux settings for PR785 power module board */
+	if (cpu_is_omap343x()) {
+		omap_cfg_reg(AF26_34XX_GPIO0);
+		omap_cfg_reg(AF22_34XX_GPIO9);
+		omap_cfg_reg(AF6_34XX_GPIO140_UP);
+		omap_cfg_reg(AE6_34XX_GPIO141);
+		omap_cfg_reg(AF5_34XX_GPIO142);
+		omap_cfg_reg(AE5_34XX_GPIO143);
+	}
+}
 
 static void __init omap3_evm_init(void)
 {
@@ -255,7 +387,12 @@ static void __init omap3_evm_init(void)
 				ARRAY_SIZE(omap3evm_spi_board_info));
 
 	omap_serial_init();
+#if defined(CONFIG_TWL4030_CORE)
 	twl4030_mmc_init(mmc);
+#endif
+#if defined(CONFIG_OMAP3EVM_PR785)
+	omap_init_pr785();
+#endif
 	usb_musb_init();
 	usb_ehci_init();
 	omap3evm_flash_init();
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c
index 437f520..d907889 100644
--- a/arch/arm/mach-omap2/mmc-twl4030.c
+++ b/arch/arm/mach-omap2/mmc-twl4030.c
@@ -168,7 +168,7 @@ static int twl_mmc_resume(struct device *dev, int slot)
  */
 static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
 {
-	int ret;
+	int ret = 0;
 	u8 vmmc, dev_grp_val;
 
 	switch (1 << vdd) {
@@ -223,6 +223,7 @@ static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
 	else
 		dev_grp_val = LDO_CLR;		/* Power down */
 
+#if defined(CONFIG_TWL4030_CORE)
 	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 					dev_grp_val, c->twl_vmmc_dev_grp);
 	if (ret)
@@ -231,6 +232,7 @@ static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
 	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 					vmmc, c->twl_mmc_dedicated);
 
+#endif
 	return ret;
 }
 
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 89a6ab0..3bc21bb 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -27,6 +27,8 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <mach/mux.h>
+#include <linux/string.h>
+#include <linux/regulator/machine.h>
 
 #define OMAP_I2C_SIZE		0x3f
 #define OMAP1_I2C_BASE		0xfffb3800
@@ -97,6 +99,15 @@ static const int omap34xx_pins[][2] = {
 static const int omap34xx_pins[][2] = {};
 #endif
 
+#if defined(CONFIG_OMAP3EVM_PR785)
+struct platform_device *vdd2_platform_device;
+struct platform_device *vdd1_platform_device;
+extern struct regulator_init_data vdd2_tps_regulator_data;
+extern struct regulator_init_data vdd1_tps_regulator_data;
+extern struct regulator_consumer_supply tps62352_core_consumers;
+extern struct regulator_consumer_supply tps62352_mpu_consumers;
+#endif
+
 static void __init omap_i2c_mux_pins(int bus)
 {
 	int scl, sda;
@@ -118,6 +129,53 @@ static void __init omap_i2c_mux_pins(int bus)
 	omap_cfg_reg(scl);
 }
 
+#if defined(CONFIG_OMAP3EVM_PR785)
+/* This is the callback function used to find the correct
+ * i2c platform child for the regulator consumer
+*/
+int omap_i2c_match_child(struct device *dev, void *data)
+{
+	struct regulator_init_data *reg_init_data = dev->platform_data;
+	char *name = data;
+
+	/* Child does not match */
+	if (strcmp(name, reg_init_data->consumer_supplies->supply))
+		return 0;
+	else
+		return 1;
+}
+
+int omap_i2c_register_child(struct platform_device *pdev_parent,
+			const char *name, struct platform_device **pdev)
+{
+	int ret = 0;
+
+	*pdev = platform_device_alloc(name, -1);
+	if (pdev == NULL) {
+		dev_err(&(*pdev)->dev, "Failed to alloc i2c-child %s\n", name);
+		return -1;
+	}
+
+	(*pdev)->dev.parent = &pdev_parent->dev;
+	if (strcmp(name, "vdd2_consumer") == 0) {
+		tps62352_core_consumers.dev = &(*pdev)->dev;
+		(*pdev)->dev.platform_data = &vdd2_tps_regulator_data;
+	} else if (strcmp(name, "vdd1_consumer") == 0) {
+		tps62352_mpu_consumers.dev = &(*pdev)->dev;
+		(*pdev)->dev.platform_data = &vdd1_tps_regulator_data;
+	}
+
+	ret = platform_device_add(*pdev);
+	if (ret != 0) {
+		dev_err(&(*pdev)->dev, "Failed to register %s: %d\n",
+			name, ret);
+		platform_device_put(*pdev);
+		*pdev = NULL;
+	}
+	return ret;
+}
+#endif
+
 int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 			  struct i2c_board_info const *info,
 			  unsigned len)
@@ -160,5 +218,14 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 	}
 
 	omap_i2c_mux_pins(bus_id - 1);
-	return platform_device_register(pdev);
+	platform_device_register(pdev);
+#if defined(CONFIG_OMAP3EVM_PR785)
+	if (bus_id == 1) {
+		omap_i2c_register_child(pdev, "vdd2_consumer", \
+				&vdd2_platform_device);
+		omap_i2c_register_child(pdev, "vdd1_consumer", \
+				&vdd1_platform_device);
+	}
+#endif
+	return 0;
 }
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
index 1c3d814..4f373b2 100644
--- a/drivers/video/omap/lcd_omap3evm.c
+++ b/drivers/video/omap/lcd_omap3evm.c
@@ -66,9 +66,11 @@ static int omap3evm_panel_init(struct lcd_panel *panel,
 	gpio_direction_output(LCD_PANEL_LR, 1);
 	gpio_direction_output(LCD_PANEL_UD, 1);
 
+#if defined(CONFIG_TWL4030_CORE)
 	twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
 	twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
 	twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
+#endif
 	bklight_level = 100;
 
 	return 0;
@@ -97,6 +99,7 @@ static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
 static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
 						unsigned int level)
 {
+#if defined(CONFIG_TWL4030_CORE)
 	u8 c;
 	if ((level >= 0) && (level <= 100)) {
 		c = (125 * (100 - level)) / 100 + 2;
@@ -104,6 +107,9 @@ static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
 		bklight_level = level;
 	}
 	return 0;
+#endif
+	/* Fix this once patch fix is sent out for TPS-boards */
+	return -1;
 }
 
 static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)
-- 
1.5.6


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] Changes for adding and building TPS6235x based PR785 board support
  2009-01-13  7:41 [PATCH 2/2] Changes for adding and building TPS6235x based PR785 board support Manikandan Pillai
@ 2009-01-13 14:59 ` Tony Lindgren
  2009-01-13 21:49   ` David Brownell
  2009-01-13 21:51   ` Mark Brown
  0 siblings, 2 replies; 4+ messages in thread
From: Tony Lindgren @ 2009-01-13 14:59 UTC (permalink / raw)
  To: Manikandan Pillai; +Cc: linux-omap, broonie

Hi,

Few comments below.

* Manikandan Pillai <mani.pillai@ti.com> [090113 09:42]:
> TPS6235x chip based PR785 power modules are from Texas Instruments
> for OMAP3 EVM boards. This patch supports the PR785 card
> and provides the driver support for the TPS devices.
> 
> For compilation, the LCD and MMC drivers are modified and will not
> work. Further patches will be provided for support of LCD and MMC
> with PR785 boards.
> 
> Signed-off-by: Manikandan Pillai <mani.pillai@ti.com>
> ---
>  arch/arm/mach-omap2/Kconfig          |   11 +++
>  arch/arm/mach-omap2/board-omap3evm.c |  137 ++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/mmc-twl4030.c    |    4 +-
>  arch/arm/plat-omap/i2c.c             |   69 +++++++++++++++++-
>  drivers/video/omap/lcd_omap3evm.c    |    6 ++
>  5 files changed, 225 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index 0a86a88..91890be 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -121,6 +121,17 @@ config MACH_OMAP3EVM
>  	bool "OMAP 3530 EVM board"
>  	depends on ARCH_OMAP3 && ARCH_OMAP34XX
>  
> +menu 	"PR785 Power board selection for OMAP3 EVM"
> +config OMAP3EVM_PR785
> +	bool "Power board for OMAP3 EVM"
> +	depends on I2C=y && ARCH_OMAP34XX
> +	help
> +	Say yes here if you are using the TPS6235x based PR785 Power Module
> +	for the EVM boards. This core driver provides register access and IRQ
> +	handling facilities, and registers devices for the various functions
> +	so that function-specific drivers can bind to them.
> +endmenu
> +
>  config MACH_OMAP3_BEAGLE
>  	bool "OMAP3 BEAGLE board"
>  	depends on ARCH_OMAP3 && ARCH_OMAP34XX
> diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
> index e4e60e2..60d2d22 100644
> --- a/arch/arm/mach-omap2/board-omap3evm.c
> +++ b/arch/arm/mach-omap2/board-omap3evm.c
> @@ -36,12 +36,19 @@
>  #include <mach/usb-ehci.h>
>  #include <mach/common.h>
>  #include <mach/mcspi.h>
> +#include <mach/mux.h>
>  
>  #include "sdram-micron-mt46h32m32lf-6.h"
>  #include "twl4030-generic-scripts.h"
>  #include "mmc-twl4030.h"
> +#include <linux/regulator/machine.h>
> +#include <linux/regulator/driver.h>
>  
> +#define TPS6235X_REG_MAX	3
>  
> +#if defined(CONFIG_OMAP3EVM_PR785) && defined(CONFIG_TWL4030_CORE)
> +#error config err : only one of OMAP3EVM_PR785 or TWL4030_CORE can be defined
> +#endif
>  static struct resource omap3evm_smc911x_resources[] = {
>  	[0] =	{
>  		.start  = OMAP3EVM_ETHR_START,
> @@ -89,6 +96,7 @@ static struct omap_uart_config omap3_evm_uart_config __initdata = {
>  	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
>  };
>  
> +#if defined(CONFIG_TWL4030_CORE)
>  static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
>  	.gpio_base	= OMAP_MAX_GPIO_LINES,
>  	.irq_base	= TWL4030_GPIO_IRQ_BASE,
> @@ -150,16 +158,125 @@ static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
>  		.platform_data = &omap3evm_twldata,
>  	},
>  };
> +#endif
> +
> +#if defined(CONFIG_OMAP3EVM_PR785)
> +/* CORE voltage regulator */
> +struct regulator_consumer_supply tps62352_core_consumers = {
> +	.supply = "vdd2",
> +};
> +
> +/* MPU voltage regulator */
> +struct regulator_consumer_supply tps62352_mpu_consumers = {
> +	.supply = "vdd1",
> +};
> +
> +struct regulator_init_data vdd2_tps_regulator_data = {
> +		.constraints = {
> +			.min_uV = 750000,
> +			.max_uV = 1537000,
> +			.valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
> +				REGULATOR_CHANGE_STATUS),
> +		},
> +		.num_consumer_supplies  = 1,
> +		.consumer_supplies      = &tps62352_core_consumers,
> +};
> +
> +struct regulator_init_data vdd1_tps_regulator_data = {
> +		.constraints = {
> +			.min_uV = 750000,
> +			.max_uV = 1537000,
> +			.valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
> +				REGULATOR_CHANGE_STATUS),
> +		},
> +		.num_consumer_supplies  = 1,
> +		.consumer_supplies      = &tps62352_mpu_consumers,
> +};
> +
> +static struct i2c_board_info __initdata tps_6235x_i2c_board_info[] = {
> +	{
> +		I2C_BOARD_INFO("tps62352", 0x4A),
> +		.flags = I2C_CLIENT_WAKE,
> +		.platform_data = &vdd2_tps_regulator_data,
> +	},
> +	{
> +		I2C_BOARD_INFO("tps62353", 0x48),
> +		.flags = I2C_CLIENT_WAKE,
> +		.platform_data = &vdd1_tps_regulator_data,
> +	},
> +};
> +#endif
>
>  static int __init omap3_evm_i2c_init(void)
>  {
> +#if defined(CONFIG_OMAP3EVM_PR785)
> +	omap_register_i2c_bus(1, 2600, tps_6235x_i2c_board_info,
> +		ARRAY_SIZE(tps_6235x_i2c_board_info));
> +#endif
> +#if defined(CONFIG_TWL4030_CORE)
>  	omap_register_i2c_bus(1, 2600, omap3evm_i2c_boardinfo,
>  			ARRAY_SIZE(omap3evm_i2c_boardinfo));
> +#endif
>  	omap_register_i2c_bus(2, 400, NULL, 0);
>  	omap_register_i2c_bus(3, 400, NULL, 0);
>  	return 0;
>  }
>  
> +/*
> + * Read a value from a register in an tps_6235x device.
> + * The value is returned in 'val'.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +int tps_6235x_read_reg(struct i2c_client *client, u8 reg, u8 *val)
> +{
> +	u8 data;
> +
> +	if (!client->adapter)
> +		return -ENODEV;
> +
> +	if (reg > TPS6235X_REG_MAX)
> +		return -1;
> +
> +	data = i2c_smbus_read_byte_data(client, reg);
> +	*val = data;
> +	return 0;
> +}
> +
> +/*
> + * Write a value to a register in an tps_6235x device.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +int tps_6235x_write_reg(struct i2c_client *client, u8 reg, u8 val)
> +{
> +	int err;
> +	int retry = 0;
> +
> +	if (!client->adapter)
> +		return -ENODEV;
> +
> +	if (reg > TPS6235X_REG_MAX)
> +		return -1;
> +
> +again:
> +	err = i2c_smbus_write_byte_data(client, reg, val);
> +	if (err >= 0)
> +		return 0;
> +
> +	dev_err(&client->dev,
> +		"wrote 0x%.2x to offset 0x%.2x error %d\n", val, reg, err);
> +
> +	/* Try 3 times */
> +	if (retry <= 3) {
> +		dev_info(&client->dev, "retry ... %d\n", retry);
> +		retry++;
> +		schedule_timeout(msecs_to_jiffies(20));
> +		goto again;
> +	}
> +	return err;
> +}
> +
> +/*-------------------------------------------------------------------*/
> +

The the read/write_reg should be in drivers/mfd somewhere.


>  static struct platform_device omap3_evm_lcd_device = {
>  	.name		= "omap3evm_lcd",
>  	.id		= -1,
> @@ -233,6 +350,7 @@ static struct platform_device *omap3_evm_devices[] __initdata = {
>  	&omap3evm_smc911x_device,
>  };
>  
> +#if defined(CONFIG_TWL4030_CORE)
>  static struct twl4030_hsmmc_info mmc[] __initdata = {
>  	{
>  		.mmc		= 1,
> @@ -242,6 +360,20 @@ static struct twl4030_hsmmc_info mmc[] __initdata = {
>  	},
>  	{}	/* Terminator */
>  };
> +#endif
> +
> +static void omap_init_pr785(void)
> +{
> +	/* Initialize the mux settings for PR785 power module board */
> +	if (cpu_is_omap343x()) {
> +		omap_cfg_reg(AF26_34XX_GPIO0);
> +		omap_cfg_reg(AF22_34XX_GPIO9);
> +		omap_cfg_reg(AF6_34XX_GPIO140_UP);
> +		omap_cfg_reg(AE6_34XX_GPIO141);
> +		omap_cfg_reg(AF5_34XX_GPIO142);
> +		omap_cfg_reg(AE5_34XX_GPIO143);
> +	}
> +}
>  
>  static void __init omap3_evm_init(void)
>  {
> @@ -255,7 +387,12 @@ static void __init omap3_evm_init(void)
>  				ARRAY_SIZE(omap3evm_spi_board_info));
>  
>  	omap_serial_init();
> +#if defined(CONFIG_TWL4030_CORE)
>  	twl4030_mmc_init(mmc);
> +#endif
> +#if defined(CONFIG_OMAP3EVM_PR785)
> +	omap_init_pr785();
> +#endif
>  	usb_musb_init();
>  	usb_ehci_init();
>  	omap3evm_flash_init();
> diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c
> index 437f520..d907889 100644
> --- a/arch/arm/mach-omap2/mmc-twl4030.c
> +++ b/arch/arm/mach-omap2/mmc-twl4030.c
> @@ -168,7 +168,7 @@ static int twl_mmc_resume(struct device *dev, int slot)
>   */
>  static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
>  {
> -	int ret;
> +	int ret = 0;
>  	u8 vmmc, dev_grp_val;
>  
>  	switch (1 << vdd) {
> @@ -223,6 +223,7 @@ static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
>  	else
>  		dev_grp_val = LDO_CLR;		/* Power down */
>  
> +#if defined(CONFIG_TWL4030_CORE)
>  	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
>  					dev_grp_val, c->twl_vmmc_dev_grp);
>  	if (ret)
> @@ -231,6 +232,7 @@ static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
>  	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
>  					vmmc, c->twl_mmc_dedicated);
>  
> +#endif
>  	return ret;
>  }
>  
> diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
> index 89a6ab0..3bc21bb 100644
> --- a/arch/arm/plat-omap/i2c.c
> +++ b/arch/arm/plat-omap/i2c.c
> @@ -27,6 +27,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/i2c.h>
>  #include <mach/mux.h>
> +#include <linux/string.h>
> +#include <linux/regulator/machine.h>
>  
>  #define OMAP_I2C_SIZE		0x3f
>  #define OMAP1_I2C_BASE		0xfffb3800
> @@ -97,6 +99,15 @@ static const int omap34xx_pins[][2] = {
>  static const int omap34xx_pins[][2] = {};
>  #endif
>  
> +#if defined(CONFIG_OMAP3EVM_PR785)
> +struct platform_device *vdd2_platform_device;
> +struct platform_device *vdd1_platform_device;
> +extern struct regulator_init_data vdd2_tps_regulator_data;
> +extern struct regulator_init_data vdd1_tps_regulator_data;
> +extern struct regulator_consumer_supply tps62352_core_consumers;
> +extern struct regulator_consumer_supply tps62352_mpu_consumers;
> +#endif
> +
>  static void __init omap_i2c_mux_pins(int bus)
>  {
>  	int scl, sda;
> @@ -118,6 +129,53 @@ static void __init omap_i2c_mux_pins(int bus)
>  	omap_cfg_reg(scl);
>  }
>  
> +#if defined(CONFIG_OMAP3EVM_PR785)
> +/* This is the callback function used to find the correct
> + * i2c platform child for the regulator consumer
> +*/
> +int omap_i2c_match_child(struct device *dev, void *data)
> +{
> +	struct regulator_init_data *reg_init_data = dev->platform_data;
> +	char *name = data;
> +
> +	/* Child does not match */
> +	if (strcmp(name, reg_init_data->consumer_supplies->supply))
> +		return 0;
> +	else
> +		return 1;
> +}
> +
> +int omap_i2c_register_child(struct platform_device *pdev_parent,
> +			const char *name, struct platform_device **pdev)
> +{
> +	int ret = 0;
> +
> +	*pdev = platform_device_alloc(name, -1);
> +	if (pdev == NULL) {
> +		dev_err(&(*pdev)->dev, "Failed to alloc i2c-child %s\n", name);
> +		return -1;
> +	}
> +
> +	(*pdev)->dev.parent = &pdev_parent->dev;
> +	if (strcmp(name, "vdd2_consumer") == 0) {
> +		tps62352_core_consumers.dev = &(*pdev)->dev;
> +		(*pdev)->dev.platform_data = &vdd2_tps_regulator_data;
> +	} else if (strcmp(name, "vdd1_consumer") == 0) {
> +		tps62352_mpu_consumers.dev = &(*pdev)->dev;
> +		(*pdev)->dev.platform_data = &vdd1_tps_regulator_data;
> +	}
> +
> +	ret = platform_device_add(*pdev);
> +	if (ret != 0) {
> +		dev_err(&(*pdev)->dev, "Failed to register %s: %d\n",
> +			name, ret);
> +		platform_device_put(*pdev);
> +		*pdev = NULL;
> +	}
> +	return ret;
> +}
> +#endif
> +
>  int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
>  			  struct i2c_board_info const *info,
>  			  unsigned len)
> @@ -160,5 +218,14 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
>  	}
>  
>  	omap_i2c_mux_pins(bus_id - 1);
> -	return platform_device_register(pdev);
> +	platform_device_register(pdev);
> +#if defined(CONFIG_OMAP3EVM_PR785)
> +	if (bus_id == 1) {
> +		omap_i2c_register_child(pdev, "vdd2_consumer", \
> +				&vdd2_platform_device);
> +		omap_i2c_register_child(pdev, "vdd1_consumer", \
> +				&vdd1_platform_device);
> +	}
> +#endif
> +	return 0;
>  }

Argh, i2c-omap.c is the _bus_ driver, not i2c device! Please move
the above code to drivers/mfd somewhere.

How different tps6235 is from the twl4030? Maybe you can just add
functionality to the existing drivers/mfd/twl4030-core.c.


> diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
> index 1c3d814..4f373b2 100644
> --- a/drivers/video/omap/lcd_omap3evm.c
> +++ b/drivers/video/omap/lcd_omap3evm.c
> @@ -66,9 +66,11 @@ static int omap3evm_panel_init(struct lcd_panel *panel,
>  	gpio_direction_output(LCD_PANEL_LR, 1);
>  	gpio_direction_output(LCD_PANEL_UD, 1);
>  
> +#if defined(CONFIG_TWL4030_CORE)
>  	twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
>  	twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
>  	twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
> +#endif
>  	bklight_level = 100;
>  
>  	return 0;
> @@ -97,6 +99,7 @@ static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
>  static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
>  						unsigned int level)
>  {
> +#if defined(CONFIG_TWL4030_CORE)
>  	u8 c;
>  	if ((level >= 0) && (level <= 100)) {
>  		c = (125 * (100 - level)) / 100 + 2;
> @@ -104,6 +107,9 @@ static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
>  		bklight_level = level;
>  	}
>  	return 0;
> +#endif
> +	/* Fix this once patch fix is sent out for TPS-boards */
> +	return -1;
>  }
>  
>  static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)

Looks like the above needs some more work too.

Tony

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] Changes for adding and building TPS6235x based PR785 board support
  2009-01-13 14:59 ` Tony Lindgren
@ 2009-01-13 21:49   ` David Brownell
  2009-01-13 21:51   ` Mark Brown
  1 sibling, 0 replies; 4+ messages in thread
From: David Brownell @ 2009-01-13 21:49 UTC (permalink / raw)
  To: Tony Lindgren, Manikandan Pillai; +Cc: linux-omap, broonie

On Tuesday 13 January 2009, Tony Lindgren wrote:
> The the read/write_reg should be in drivers/mfd somewhere.

I wouldn't think so ... it's not an MFD, it's just a
regulator that has a feature that's not yet envisioned
by the current regulator framework.  (Floor/Ceiling
controls, basically.)


> > @@ -160,5 +218,14 @@ int __init omap_register_i2c_bus(int bus_id, u32
> > clkrate, }
> >  
> >       omap_i2c_mux_pins(bus_id - 1);
> > -     return platform_device_register(pdev);
> > +     platform_device_register(pdev);
> > +#if defined(CONFIG_OMAP3EVM_PR785)
> > +     if (bus_id == 1) {
> > +             omap_i2c_register_child(pdev, "vdd2_consumer", \
> > +                             &vdd2_platform_device);
> > +             omap_i2c_register_child(pdev, "vdd1_consumer", \
> > +                             &vdd1_platform_device);
> > +     }
> > +#endif
> > +     return 0;
> >  }
>
> Argh, i2c-omap.c is the _bus_ driver, not i2c device!

Right.  I don't understand why there's this urge to
scatter board-specific code throughout the driver
tree, instead of leaving it all in mach-omap2/pr785.c
and having the tps6235x.c driver be a pure regulator
driver...


> How different tps6235 is from the twl4030? Maybe you can just add
> functionality to the existing drivers/mfd/twl4030-core.c.

It's very different ... the tps623x chips are trivial,
with about four registers each.  No capability OTHER
than being a voltage regulator.

Which is why it's puzzling to see it take so long to
just get a simple voltage regulator driver patch...


Admittedly, the regulator framework is new, and parts
of it still seem to me like they have design problems.
But even so, it's not so hard to figure out how to pass
board-specific regulator configuration data down to the
regulator drivers from a pr785.c board driver.

Now, there *can* be a bit of chicken/egg going on in
some of that initialization.  But I don't think that
applies to all of the PR785 support.

- Dave
--
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] 4+ messages in thread

* Re: [PATCH 2/2] Changes for adding and building TPS6235x based PR785 board support
  2009-01-13 14:59 ` Tony Lindgren
  2009-01-13 21:49   ` David Brownell
@ 2009-01-13 21:51   ` Mark Brown
  1 sibling, 0 replies; 4+ messages in thread
From: Mark Brown @ 2009-01-13 21:51 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Manikandan Pillai, linux-omap

On Tue, Jan 13, 2009 at 04:59:10PM +0200, Tony Lindgren wrote:

> > +int tps_6235x_read_reg(struct i2c_client *client, u8 reg, u8 *val)

> The the read/write_reg should be in drivers/mfd somewhere.

Is this a multi-function device?  If so then there should be a similar
structure to the TWL4030 drivers should be used with the function
drivers all being platform drivers instantiated by the core (either
manually or via the MFD helpers).  The regulator driver was a regular
I2C device, suggesting that all the device does is regulation, in which
case the register I/O functions should be in there.

> > +	platform_device_register(pdev);
> > +#if defined(CONFIG_OMAP3EVM_PR785)
> > +	if (bus_id == 1) {
> > +		omap_i2c_register_child(pdev, "vdd2_consumer", \
> > +				&vdd2_platform_device);
> > +		omap_i2c_register_child(pdev, "vdd1_consumer", \
> > +				&vdd1_platform_device);
> > +	}
> > +#endif
> > +	return 0;
> >  }

> Argh, i2c-omap.c is the _bus_ driver, not i2c device! Please move
> the above code to drivers/mfd somewhere.

There should be no need to do this at all.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-01-13 21:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-13  7:41 [PATCH 2/2] Changes for adding and building TPS6235x based PR785 board support Manikandan Pillai
2009-01-13 14:59 ` Tony Lindgren
2009-01-13 21:49   ` David Brownell
2009-01-13 21:51   ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox