All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ep93xx: update i2c support
@ 2009-09-18 19:18 H Hartley Sweeten
  2009-09-18 19:29 ` H Hartley Sweeten
  0 siblings, 1 reply; 10+ messages in thread
From: H Hartley Sweeten @ 2009-09-18 19:18 UTC (permalink / raw)
  To: linux-arm-kernel

Update the ep93xx i2c support to allow the platform init to configure
the sda and scl pins as open drain or normal cmos drivers.  Also allow
the platform to set the udelay and timeout for the i2c-gpio driver.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>

---

diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 16b92c3..d115000 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -549,12 +549,13 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
 static struct i2c_gpio_platform_data ep93xx_i2c_data = {
 	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
 	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
 };
 
 static struct platform_device ep93xx_i2c_device = {
@@ -563,8 +564,32 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num,
+				int sda_is_open_drain, int scl_is_open_drain,
+				int udelay, int timeout)
 {
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	ep93xx_i2c_data.sda_is_open_drain = sda_is_open_drain;
+	ep93xx_i2c_data.scl_is_open_drain = scl_is_open_drain;
+
+	__raw_write((sda_is_open_drain<<1) | (scl_is_open_drain<<0)),
+			EP93XX_GPIO_EEDRIVE);
+
+	/*
+	 * udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
+	 *         == 0 will default to 5 (100 khz)
+	 * timeout: clock stretching timeout in jiffies. If the slave keeps
+	 *          SCL low for longer than this, the transfer will time out.
+	 *          == 0 will default to HZ / 10 (100 ms)
+	 */
+	ep93xx_i2c_data.udelay = udelay;
+	ep93xx_i2c_data.timeout = timeout;
+
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae..39b8234 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -93,11 +93,13 @@ static void __init edb93xx_register_i2c(void)
 	if (machine_is_edb9302a() || machine_is_edb9307a() ||
 	    machine_is_edb9315a()) {
 		ep93xx_register_i2c(edb93xxa_i2c_data,
-				ARRAY_SIZE(edb93xxa_i2c_data));
+				ARRAY_SIZE(edb93xxa_i2c_data),
+				0, 0, 2, 0);
 	} else if (machine_is_edb9307() || machine_is_edb9312() ||
 		   machine_is_edb9315()) {
 		ep93xx_register_i2c(edb93xx_i2c_data,
-				ARRAY_SIZE(edb93xx_i2c_data));
+				ARRAY_SIZE(edb93xx_i2c_data),
+				0, 0, 2, 0);
 	}
 }
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index ea78e90..53f1277 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -126,6 +126,7 @@
 #define EP93XX_GPIO_B_INT_ACK		EP93XX_GPIO_REG(0xb4)
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 5f5fa65..25aa4a3 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -32,7 +32,9 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_board_info *devices, int num,
+			 int sda_is_open_drain, int scl_is_open_drain,
+			 int udelay, int timeout);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
 void ep93xx_pwm_release_gpio(struct platform_device *pdev); 

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

* [PATCH] ep93xx: update i2c support
  2009-09-18 19:18 [PATCH] ep93xx: update i2c support H Hartley Sweeten
@ 2009-09-18 19:29 ` H Hartley Sweeten
  2009-09-30 20:10   ` Ryan Mallon
  0 siblings, 1 reply; 10+ messages in thread
From: H Hartley Sweeten @ 2009-09-18 19:29 UTC (permalink / raw)
  To: linux-arm-kernel

Update the ep93xx i2c support to allow the platform init to configure
the sda and scl pins as open drain or normal cmos drivers.  Also allow
the platform to set the udelay and timeout for the i2c-gpio driver.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>

---

V2 - __raw_write should be __raw_writel


diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 16b92c3..49e74b6 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -549,12 +549,13 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
 static struct i2c_gpio_platform_data ep93xx_i2c_data = {
 	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
 	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
 };
 
 static struct platform_device ep93xx_i2c_device = {
@@ -563,8 +564,32 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num,
+				int sda_is_open_drain, int scl_is_open_drain,
+				int udelay, int timeout)
 {
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	ep93xx_i2c_data.sda_is_open_drain = sda_is_open_drain;
+	ep93xx_i2c_data.scl_is_open_drain = scl_is_open_drain;
+
+	__raw_writel((sda_is_open_drain<<1) | (scl_is_open_drain<<0)),
+			EP93XX_GPIO_EEDRIVE);
+
+	/*
+	 * udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
+	 *         == 0 will default to 5 (100 khz)
+	 * timeout: clock stretching timeout in jiffies. If the slave keeps
+	 *          SCL low for longer than this, the transfer will time out.
+	 *          == 0 will default to HZ / 10 (100 ms)
+	 */
+	ep93xx_i2c_data.udelay = udelay;
+	ep93xx_i2c_data.timeout = timeout;
+
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae..39b8234 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -93,11 +93,13 @@ static void __init edb93xx_register_i2c(void)
 	if (machine_is_edb9302a() || machine_is_edb9307a() ||
 	    machine_is_edb9315a()) {
 		ep93xx_register_i2c(edb93xxa_i2c_data,
-				ARRAY_SIZE(edb93xxa_i2c_data));
+				ARRAY_SIZE(edb93xxa_i2c_data),
+				0, 0, 2, 0);
 	} else if (machine_is_edb9307() || machine_is_edb9312() ||
 		   machine_is_edb9315()) {
 		ep93xx_register_i2c(edb93xx_i2c_data,
-				ARRAY_SIZE(edb93xx_i2c_data));
+				ARRAY_SIZE(edb93xx_i2c_data),
+				0, 0, 2, 0);
 	}
 }
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index ea78e90..53f1277 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -126,6 +126,7 @@
 #define EP93XX_GPIO_B_INT_ACK		EP93XX_GPIO_REG(0xb4)
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 5f5fa65..25aa4a3 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -32,7 +32,9 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_board_info *devices, int num,
+			 int sda_is_open_drain, int scl_is_open_drain,
+			 int udelay, int timeout);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
 void ep93xx_pwm_release_gpio(struct platform_device *pdev); 

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

* [PATCH] ep93xx: update i2c support
  2009-09-18 19:29 ` H Hartley Sweeten
@ 2009-09-30 20:10   ` Ryan Mallon
  2009-09-30 20:18     ` H Hartley Sweeten
  2009-09-30 21:01     ` H Hartley Sweeten
  0 siblings, 2 replies; 10+ messages in thread
From: Ryan Mallon @ 2009-09-30 20:10 UTC (permalink / raw)
  To: linux-arm-kernel

H Hartley Sweeten wrote:
> Update the ep93xx i2c support to allow the platform init to configure
> the sda and scl pins as open drain or normal cmos drivers.  Also allow
> the platform to set the udelay and timeout for the i2c-gpio driver.
>
> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
>
> ---
>
> V2 - __raw_write should be __raw_writel
>
>
> diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
> index 16b92c3..49e74b6 100644
> --- a/arch/arm/mach-ep93xx/core.c
> +++ b/arch/arm/mach-ep93xx/core.c
> @@ -549,12 +549,13 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
>  	platform_device_register(&ep93xx_eth_device);
>  }
>  
> +
> +/*************************************************************************
> + * EP93xx i2c peripheral handling
> + *************************************************************************/
>  static struct i2c_gpio_platform_data ep93xx_i2c_data = {
>  	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
> -	.sda_is_open_drain	= 0,
>  	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
> -	.scl_is_open_drain	= 0,
> -	.udelay			= 2,
>  };
>  
>  static struct platform_device ep93xx_i2c_device = {
> @@ -563,8 +564,32 @@ static struct platform_device ep93xx_i2c_device = {
>  	.dev.platform_data	= &ep93xx_i2c_data,
>  };
>  
> -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
> +void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num,
> +				int sda_is_open_drain, int scl_is_open_drain,
> +				int udelay, int timeout)
>  {
> +	/*
> +	 * Set the EEPROM interface pin drive type control.
> +	 * Defines the driver type for the EECLK and EEDAT pins as either
> +	 * open drain, which will require an external pull-up, or a normal
> +	 * CMOS driver.
> +	 */
> +	ep93xx_i2c_data.sda_is_open_drain = sda_is_open_drain;
> +	ep93xx_i2c_data.scl_is_open_drain = scl_is_open_drain;
> +
> +	__raw_writel((sda_is_open_drain<<1) | (scl_is_open_drain<<0)),
> +			EP93XX_GPIO_EEDRIVE);
> +
> +	/*
> +	 * udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
> +	 *         == 0 will default to 5 (100 khz)
> +	 * timeout: clock stretching timeout in jiffies. If the slave keeps
> +	 *          SCL low for longer than this, the transfer will time out.
> +	 *          == 0 will default to HZ / 10 (100 ms)
> +	 */
> +	ep93xx_i2c_data.udelay = udelay;
> +	ep93xx_i2c_data.timeout = timeout;
> +
>  	i2c_register_board_info(0, devices, num);
>  	platform_device_register(&ep93xx_i2c_device);
>  }
>
>   
I find this a bit ugly since you basically use the register_i2c function
to fill in the struct elements. Why not just let each board fill in the
i2c platform data itself. This is more consistent with the other device
registration functions and also allows boards to use other gpio pins for
i2c if they want, ie (untested):

diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 681bd68..a5bf12d 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -550,13 +550,7 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
-	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
-};
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
 	.name			= "i2c-gpio",
@@ -564,8 +558,13 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *pdata,
+				struct i2c_board_info *devices, int num)
 {
+	ep93xx_i2c_data = *pdata;
+	__raw_writel((ep9xx_i2c_data.sda_is_open_drain << 1) |
+		     (ep9xx_i2c_data.scl_is_open_drain << 0), 
+		     EP93XX_GPIO_EEDRIVE);
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }

Obviously the board files also need to be fixed up.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751 
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [PATCH] ep93xx: update i2c support
  2009-09-30 20:10   ` Ryan Mallon
@ 2009-09-30 20:18     ` H Hartley Sweeten
  2009-09-30 21:01     ` H Hartley Sweeten
  1 sibling, 0 replies; 10+ messages in thread
From: H Hartley Sweeten @ 2009-09-30 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, September 30, 2009 1:10 PM, Ryan Mallon wrote:
> H Hartley Sweeten wrote:
>> Update the ep93xx i2c support to allow the platform init to configure
>> the sda and scl pins as open drain or normal cmos drivers.  Also allow
>> the platform to set the udelay and timeout for the i2c-gpio driver.
>>
>> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
>>
>> ---
>>
>> V2 - __raw_write should be __raw_writel
>>
>>
>> diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
>> index 16b92c3..49e74b6 100644
>> --- a/arch/arm/mach-ep93xx/core.c
>> +++ b/arch/arm/mach-ep93xx/core.c
>> @@ -549,12 +549,13 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
>>  	platform_device_register(&ep93xx_eth_device);
>>  }
>>  
>> +
>> +/*************************************************************************
>> + * EP93xx i2c peripheral handling
>> + *************************************************************************/
>>  static struct i2c_gpio_platform_data ep93xx_i2c_data = {
>>  	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
>> -	.sda_is_open_drain	= 0,
>>  	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
>> -	.scl_is_open_drain	= 0,
>> -	.udelay			= 2,
>>  };
>>  
>>  static struct platform_device ep93xx_i2c_device = {
>> @@ -563,8 +564,32 @@ static struct platform_device ep93xx_i2c_device = {
>>  	.dev.platform_data	= &ep93xx_i2c_data,
>>  };
>>  
>> -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
>> +void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num,
>> +				int sda_is_open_drain, int scl_is_open_drain,
>> +				int udelay, int timeout)
>>  {
>> +	/*
>> +	 * Set the EEPROM interface pin drive type control.
>> +	 * Defines the driver type for the EECLK and EEDAT pins as either
>> +	 * open drain, which will require an external pull-up, or a normal
>> +	 * CMOS driver.
>> +	 */
>> +	ep93xx_i2c_data.sda_is_open_drain = sda_is_open_drain;
>> +	ep93xx_i2c_data.scl_is_open_drain = scl_is_open_drain;
>> +
>> +	__raw_writel((sda_is_open_drain<<1) | (scl_is_open_drain<<0)),
>> +			EP93XX_GPIO_EEDRIVE);
>> +
>> +	/*
>> +	 * udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
>> +	 *         == 0 will default to 5 (100 khz)
>> +	 * timeout: clock stretching timeout in jiffies. If the slave keeps
>> +	 *          SCL low for longer than this, the transfer will time out.
>> +	 *          == 0 will default to HZ / 10 (100 ms)
>> +	 */
>> +	ep93xx_i2c_data.udelay = udelay;
>> +	ep93xx_i2c_data.timeout = timeout;
>> +
>>  	i2c_register_board_info(0, devices, num);
>>  	platform_device_register(&ep93xx_i2c_device);
>>  }
>>
>>   
> I find this a bit ugly since you basically use the register_i2c function
> to fill in the struct elements. Why not just let each board fill in the
> i2c platform data itself. This is more consistent with the other device
> registration functions and also allows boards to use other gpio pins for
> i2c if they want, ie (untested):
> 
> diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
> index 681bd68..a5bf12d 100644
> --- a/arch/arm/mach-ep93xx/core.c
> +++ b/arch/arm/mach-ep93xx/core.c
> @@ -550,13 +550,7 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
>  	platform_device_register(&ep93xx_eth_device);
>  }
>  
> -static struct i2c_gpio_platform_data ep93xx_i2c_data = {
> -	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
> -	.sda_is_open_drain	= 0,
> -	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
> -	.scl_is_open_drain	= 0,
> -	.udelay			= 2,
> -};
> +static struct i2c_gpio_platform_data ep93xx_i2c_data;
>  
>  static struct platform_device ep93xx_i2c_device = {
>  	.name			= "i2c-gpio",
> @@ -564,8 +558,13 @@ static struct platform_device ep93xx_i2c_device = {
>  	.dev.platform_data	= &ep93xx_i2c_data,
>  };
>  
> -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
> +void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *pdata,
> +				struct i2c_board_info *devices, int num)
>  {
> +	ep93xx_i2c_data = *pdata;
> +	__raw_writel((ep9xx_i2c_data.sda_is_open_drain << 1) |
> +		     (ep9xx_i2c_data.scl_is_open_drain << 0), 
> +		     EP93XX_GPIO_EEDRIVE);
>  	i2c_register_board_info(0, devices, num);
>  	platform_device_register(&ep93xx_i2c_device);
>  }
> 
> Obviously the board files also need to be fixed up.
> 

Good point about using gpio pins other than EEDAT and EECLK.  For instance
the TS-7200 board doesn't have the pins accessible but there is a patch on
the yahoo site that uses two of the pins on their DIO port.

I will modify the patch and repost.

Thanks,
Hartley

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

* [PATCH] ep93xx: update i2c support
  2009-09-30 20:10   ` Ryan Mallon
  2009-09-30 20:18     ` H Hartley Sweeten
@ 2009-09-30 21:01     ` H Hartley Sweeten
  2009-09-30 21:08       ` Ryan Mallon
  1 sibling, 1 reply; 10+ messages in thread
From: H Hartley Sweeten @ 2009-09-30 21:01 UTC (permalink / raw)
  To: linux-arm-kernel

Update the ep93xx i2c support:

  1) The platform init code passes the configuration data for the
     i2c-gpio driver.  This allows any gpio pin do be used for the
     sda and scl pins.  It also allows the platform to specify the
     udelay and timeout.
  2) Program the gpio configuration register to enable/disable the
     open drain drivers.  Note that this really only works if the
     sda and scl pins are set to EP93XX_GPIO_LINE_EEDAT and
     EP93XX_GPIO_LINE_EECLK.
  3) Update the edb93xx.c platform init to use the new support.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>

---

V3 - rebased on comments from Ryan Mallon

diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index f7ebed9..dff9373 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -550,13 +550,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
-	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
 	.name			= "i2c-gpio",
@@ -564,8 +562,21 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+				struct i2c_board_info *devices, int num)
 {
+	ep93xx_i2c_data = *data;
+
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	__raw_writel((ep9xx_i2c_data.sda_is_open_drain << 1) |
+		     (ep9xx_i2c_data.scl_is_open_drain << 0),
+		     EP93XX_GPIO_EEDRIVE);
+
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae..5f22081 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
 #include <linux/mtd/physmap.h>
 
 #include <mach/hardware.h>
@@ -76,13 +77,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = {
 	.phy_id		= 1,
 };
 
-static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,	/* default to 100 kHz */
+	.timeout		= 0,	/* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("isl1208", 0x6f),
 	},
 };
 
-static struct i2c_board_info __initdata edb93xx_i2c_data[] = {
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("ds1337", 0x68),
 	},
@@ -92,12 +106,14 @@ static void __init edb93xx_register_i2c(void)
 {
 	if (machine_is_edb9302a() || machine_is_edb9307a() ||
 	    machine_is_edb9315a()) {
-		ep93xx_register_i2c(edb93xxa_i2c_data,
-				ARRAY_SIZE(edb93xxa_i2c_data));
+		ep93xx_register_i2c(edb93xx_i2c_gpio_data,
+				    edb93xxa_i2c_board_info,
+				    ARRAY_SIZE(edb93xxa_i2c_board_info));
 	} else if (machine_is_edb9307() || machine_is_edb9312() ||
 		   machine_is_edb9315()) {
-		ep93xx_register_i2c(edb93xx_i2c_data,
-				ARRAY_SIZE(edb93xx_i2c_data));
+		ep93xx_register_i2c(edb93xx_i2c_gpio_data
+				    edb93xx_i2c_board_info,
+				    ARRAY_SIZE(edb93xx_i2c_board_info));
 	}
 }
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 0fbf87b..2b3be3c 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -127,6 +127,7 @@
 #define EP93XX_GPIO_B_INT_ACK		EP93XX_GPIO_REG(0xb4)
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 01a0f08..a3ec33f 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -4,6 +4,7 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct platform_device;
 struct ep93xxfb_mach_info;
@@ -33,7 +34,8 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+			 struct i2c_board_info *devices, int num);
 void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); 

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

* [PATCH] ep93xx: update i2c support
  2009-09-30 21:01     ` H Hartley Sweeten
@ 2009-09-30 21:08       ` Ryan Mallon
  2009-09-30 21:24         ` H Hartley Sweeten
  0 siblings, 1 reply; 10+ messages in thread
From: Ryan Mallon @ 2009-09-30 21:08 UTC (permalink / raw)
  To: linux-arm-kernel

H Hartley Sweeten wrote:
> Update the ep93xx i2c support:
> 
>   1) The platform init code passes the configuration data for the
>      i2c-gpio driver.  This allows any gpio pin do be used for the
>      sda and scl pins.  It also allows the platform to specify the
>      udelay and timeout.
>   2) Program the gpio configuration register to enable/disable the
>      open drain drivers.  Note that this really only works if the
>      sda and scl pins are set to EP93XX_GPIO_LINE_EEDAT and
>      EP93XX_GPIO_LINE_EECLK.

Maybe print a warning then if sda/scl_is_open_drain is set and the pin
is not set to EEDAT/EECLK.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [PATCH] ep93xx: update i2c support
  2009-09-30 21:08       ` Ryan Mallon
@ 2009-09-30 21:24         ` H Hartley Sweeten
  2009-10-01  1:55           ` Ryan Mallon
  0 siblings, 1 reply; 10+ messages in thread
From: H Hartley Sweeten @ 2009-09-30 21:24 UTC (permalink / raw)
  To: linux-arm-kernel

Update the ep93xx i2c support:

  1) The platform init code passes the configuration data for the
     i2c-gpio driver.  This allows any gpio pin do be used for the
     sda and scl pins.  It also allows the platform to specify the
     udelay and timeout.
  2) Program the gpio configuration register to enable/disable the
     open drain drivers.  Note that this really only works if the
     sda and scl pins are set to EP93XX_GPIO_LINE_EEDAT and
     EP93XX_GPIO_LINE_EECLK.
  3) Update the edb93xx.c platform init to use the new support.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>

---

V4 - add warning message when sda/scl are not EEDAT/EECLK and
     configured as open drain
V3 - rebased on comments from Ryan Mallon

diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index f7ebed9..3803d4f 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -550,13 +550,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
-	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
 	.name			= "i2c-gpio",
@@ -564,8 +562,26 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+				struct i2c_board_info *devices, int num)
 {
+	ep93xx_i2c_data = *data;
+
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+		printk("ep93xx: sda != EEDAT, open drain has no effect\n");
+	if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+		printk("ep93xx: scl != EECLK, open drain has no effect\n");
+	
+	__raw_writel((ep9xx_i2c_data.sda_is_open_drain << 1) |
+		     (ep9xx_i2c_data.scl_is_open_drain << 0),
+		     EP93XX_GPIO_EEDRIVE);
+
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae..5f22081 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
 #include <linux/mtd/physmap.h>
 
 #include <mach/hardware.h>
@@ -76,13 +77,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = {
 	.phy_id		= 1,
 };
 
-static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,	/* default to 100 kHz */
+	.timeout		= 0,	/* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("isl1208", 0x6f),
 	},
 };
 
-static struct i2c_board_info __initdata edb93xx_i2c_data[] = {
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("ds1337", 0x68),
 	},
@@ -92,12 +106,14 @@ static void __init edb93xx_register_i2c(void)
 {
 	if (machine_is_edb9302a() || machine_is_edb9307a() ||
 	    machine_is_edb9315a()) {
-		ep93xx_register_i2c(edb93xxa_i2c_data,
-				ARRAY_SIZE(edb93xxa_i2c_data));
+		ep93xx_register_i2c(edb93xx_i2c_gpio_data,
+				    edb93xxa_i2c_board_info,
+				    ARRAY_SIZE(edb93xxa_i2c_board_info));
 	} else if (machine_is_edb9307() || machine_is_edb9312() ||
 		   machine_is_edb9315()) {
-		ep93xx_register_i2c(edb93xx_i2c_data,
-				ARRAY_SIZE(edb93xx_i2c_data));
+		ep93xx_register_i2c(edb93xx_i2c_gpio_data
+				    edb93xx_i2c_board_info,
+				    ARRAY_SIZE(edb93xx_i2c_board_info));
 	}
 }
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 0fbf87b..2b3be3c 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -127,6 +127,7 @@
 #define EP93XX_GPIO_B_INT_ACK		EP93XX_GPIO_REG(0xb4)
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 01a0f08..a3ec33f 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -4,6 +4,7 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct platform_device;
 struct ep93xxfb_mach_info;
@@ -33,7 +34,8 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+			 struct i2c_board_info *devices, int num);
 void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); 

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

* [PATCH] ep93xx: update i2c support
  2009-09-30 21:24         ` H Hartley Sweeten
@ 2009-10-01  1:55           ` Ryan Mallon
  2009-10-01 21:41             ` H Hartley Sweeten
  0 siblings, 1 reply; 10+ messages in thread
From: Ryan Mallon @ 2009-10-01  1:55 UTC (permalink / raw)
  To: linux-arm-kernel

H Hartley Sweeten wrote:
> Update the ep93xx i2c support:
> 
>   1) The platform init code passes the configuration data for the
>      i2c-gpio driver.  This allows any gpio pin do be used for the
>      sda and scl pins.  It also allows the platform to specify the
>      udelay and timeout.
>   2) Program the gpio configuration register to enable/disable the
>      open drain drivers.  Note that this really only works if the
>      sda and scl pins are set to EP93XX_GPIO_LINE_EEDAT and
>      EP93XX_GPIO_LINE_EECLK.
>   3) Update the edb93xx.c platform init to use the new support.
> 
> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
> 
> ---
> 
> -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
> +void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
> +				struct i2c_board_info *devices, int num)
>  {
> +	ep93xx_i2c_data = *data;
> +
> +	/*
> +	 * Set the EEPROM interface pin drive type control.
> +	 * Defines the driver type for the EECLK and EEDAT pins as either
> +	 * open drain, which will require an external pull-up, or a normal
> +	 * CMOS driver.
> +	 */
> +	if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
> +		printk("ep93xx: sda != EEDAT, open drain has no effect\n");
> +	if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
> +		printk("ep93xx: scl != EECLK, open drain has no effect\n");

pr_warning on these. Otherwise:

Acked-by: Ryan Mallon <ryan@bluewatersys.com>

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [PATCH] ep93xx: update i2c support
  2009-10-01  1:55           ` Ryan Mallon
@ 2009-10-01 21:41             ` H Hartley Sweeten
  2009-10-01 22:18               ` H Hartley Sweeten
  0 siblings, 1 reply; 10+ messages in thread
From: H Hartley Sweeten @ 2009-10-01 21:41 UTC (permalink / raw)
  To: linux-arm-kernel

Update the ep93xx i2c support:

  1) The platform init code passes the configuration data for the
     i2c-gpio driver.  This allows any gpio pin do be used for the
     sda and scl pins.  It also allows the platform to specify the
     udelay and timeout.
  2) Program the gpio configuration register to enable/disable the
     open drain drivers.  Note that this really only works if the
     sda and scl pins are set to EP93XX_GPIO_LINE_EEDAT and
     EP93XX_GPIO_LINE_EECLK.
  3) Update the edb93xx.c platform init to use the new support.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Ryan Mallon <ryan@bluewatersys.com>

--- 

V5 - use pr_warning for sda/scl messages
V4 - add warning message when sda/scl are not EEDAT/EECLK and
     configured as open drain
V3 - rebased on comments from Ryan Mallon


diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index f7ebed9..e8bae09 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -550,13 +550,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
-	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
 	.name			= "i2c-gpio",
@@ -564,8 +562,25 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+				struct i2c_board_info *devices, int num)
 {
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+		pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n");
+	if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+		pr_warning("ep93xx: scl != EECLK, open drain has no effect\n");
+	
+	__raw_writel((data->sda_is_open_drain << 1) |
+		     (data->scl_is_open_drain << 0),
+		     EP93XX_GPIO_EEDRIVE);
+
+	ep93xx_i2c_data = *data;
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae..307f435 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
 #include <linux/mtd/physmap.h>
 
 #include <mach/hardware.h>
@@ -76,13 +77,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = {
 	.phy_id		= 1,
 };
 
-static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,	/* default to 100 kHz */
+	.timeout		= 0,	/* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("isl1208", 0x6f),
 	},
 };
 
-static struct i2c_board_info __initdata edb93xx_i2c_data[] = {
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("ds1337", 0x68),
 	},
@@ -92,12 +106,14 @@ static void __init edb93xx_register_i2c(void)
 {
 	if (machine_is_edb9302a() || machine_is_edb9307a() ||
 	    machine_is_edb9315a()) {
-		ep93xx_register_i2c(edb93xxa_i2c_data,
-				ARRAY_SIZE(edb93xxa_i2c_data));
+		ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+				    edb93xxa_i2c_board_info,
+				    ARRAY_SIZE(edb93xxa_i2c_board_info));
 	} else if (machine_is_edb9307() || machine_is_edb9312() ||
 		   machine_is_edb9315()) {
-		ep93xx_register_i2c(edb93xx_i2c_data,
-				ARRAY_SIZE(edb93xx_i2c_data));
+		ep93xx_register_i2c(&edb93xx_i2c_gpio_data
+				    edb93xx_i2c_board_info,
+				    ARRAY_SIZE(edb93xx_i2c_board_info));
 	}
 }
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 0fbf87b..2b3be3c 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -127,6 +127,7 @@
 #define EP93XX_GPIO_B_INT_ACK		EP93XX_GPIO_REG(0xb4)
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 01a0f08..a3ec33f 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -4,6 +4,7 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct platform_device;
 struct ep93xxfb_mach_info;
@@ -33,7 +34,8 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+			 struct i2c_board_info *devices, int num);
 void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); 

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

* [PATCH] ep93xx: update i2c support
  2009-10-01 21:41             ` H Hartley Sweeten
@ 2009-10-01 22:18               ` H Hartley Sweeten
  0 siblings, 0 replies; 10+ messages in thread
From: H Hartley Sweeten @ 2009-10-01 22:18 UTC (permalink / raw)
  To: linux-arm-kernel

Update the ep93xx i2c support:

  1) The platform init code passes the configuration data for the
     i2c-gpio driver.  This allows any gpio pin do be used for the
     sda and scl pins.  It also allows the platform to specify the
     udelay and timeout.
  2) Program the gpio configuration register to enable/disable the
     open drain drivers.  Note that this really only works if the
     sda and scl pins are set to EP93XX_GPIO_LINE_EEDAT and
     EP93XX_GPIO_LINE_EECLK.
  3) Update the edb93xx.c platform init to use the new support.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Ryan Mallon <ryan@bluewatersys.com>

--- 

V6 - add missing #include <linux/gpio.h> to edb93xx.c
V5 - use pr_warning for sda/scl messages
V4 - add warning message when sda/scl are not EEDAT/EECLK and
     configured as open drain
V3 - rebased on comments from Ryan Mallon


diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index f7ebed9..e8bae09 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -550,13 +550,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 	platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
-	.sda_is_open_drain	= 0,
-	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
 	.name			= "i2c-gpio",
@@ -564,8 +562,25 @@ static struct platform_device ep93xx_i2c_device = {
 	.dev.platform_data	= &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+				struct i2c_board_info *devices, int num)
 {
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+		pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n");
+	if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+		pr_warning("ep93xx: scl != EECLK, open drain has no effect\n");
+	
+	__raw_writel((data->sda_is_open_drain << 1) |
+		     (data->scl_is_open_drain << 0),
+		     EP93XX_GPIO_EEDRIVE);
+
+	ep93xx_i2c_data = *data;
 	i2c_register_board_info(0, devices, num);
 	platform_device_register(&ep93xx_i2c_device);
 }
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae..ca71cf1 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -27,8 +27,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/i2c.h>
 #include <linux/mtd/physmap.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
 
 #include <mach/hardware.h>
 
@@ -76,13 +78,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = {
 	.phy_id		= 1,
 };
 
-static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,	/* default to 100 kHz */
+	.timeout		= 0,	/* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("isl1208", 0x6f),
 	},
 };
 
-static struct i2c_board_info __initdata edb93xx_i2c_data[] = {
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("ds1337", 0x68),
 	},
@@ -92,12 +107,14 @@ static void __init edb93xx_register_i2c(void)
 {
 	if (machine_is_edb9302a() || machine_is_edb9307a() ||
 	    machine_is_edb9315a()) {
-		ep93xx_register_i2c(edb93xxa_i2c_data,
-				ARRAY_SIZE(edb93xxa_i2c_data));
+		ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+				    edb93xxa_i2c_board_info,
+				    ARRAY_SIZE(edb93xxa_i2c_board_info));
 	} else if (machine_is_edb9307() || machine_is_edb9312() ||
 		   machine_is_edb9315()) {
-		ep93xx_register_i2c(edb93xx_i2c_data,
-				ARRAY_SIZE(edb93xx_i2c_data));
+		ep93xx_register_i2c(&edb93xx_i2c_gpio_data
+				    edb93xx_i2c_board_info,
+				    ARRAY_SIZE(edb93xx_i2c_board_info));
 	}
 }
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 0fbf87b..2b3be3c 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -127,6 +127,7 @@
 #define EP93XX_GPIO_B_INT_ACK		EP93XX_GPIO_REG(0xb4)
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
 
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 01a0f08..a3ec33f 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -4,6 +4,7 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct platform_device;
 struct ep93xxfb_mach_info;
@@ -33,7 +34,8 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+			 struct i2c_board_info *devices, int num);
 void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); 

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

end of thread, other threads:[~2009-10-01 22:18 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-18 19:18 [PATCH] ep93xx: update i2c support H Hartley Sweeten
2009-09-18 19:29 ` H Hartley Sweeten
2009-09-30 20:10   ` Ryan Mallon
2009-09-30 20:18     ` H Hartley Sweeten
2009-09-30 21:01     ` H Hartley Sweeten
2009-09-30 21:08       ` Ryan Mallon
2009-09-30 21:24         ` H Hartley Sweeten
2009-10-01  1:55           ` Ryan Mallon
2009-10-01 21:41             ` H Hartley Sweeten
2009-10-01 22:18               ` H Hartley Sweeten

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.