PATCH - s3c2410 clock control patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ben,

> This patch makes it possible for the I2C unit
> to disable the clock fed into it whilst it is
> not being used. This should reduce the power
> consumption, with only minimal extra time during
> the start and end of a transfer.
> 
> This patch also ensures that the clock is in
> the right state when going in and out of
> suspend.
> 
> Also included is a minor bugfix to place a minor
> delay if going to next part of a write, the
> controller can generate incorrect bus data if
> a small number of register reads inserted
> before returning from the IRQ handler

This probably should be a separate patch.

> diff -urpN -X ../dontdiff linux-2.6.16-rmk/drivers/i2c/busses/Kconfig linux-2.6.16-rmk-bjd1/drivers/i2c/busses/Kconfig
> --- linux-2.6.16-rmk/drivers/i2c/busses/Kconfig	2006-03-20 05:53:29.000000000 +0000
> +++ linux-2.6.16-rmk-bjd1/drivers/i2c/busses/Kconfig	2006-03-21 22:44:26.000000000 +0000
> @@ -343,6 +343,14 @@ config I2C_S3C2410
>  	  Say Y here to include support for I2C controller in the
>  	  Samsung S3C2410 based System-on-Chip devices.
>  
> +config I2C_S3C2410_CLKIDLE
> +	bool "Stop I2C clock during IDLE"
> +	depends on I2C_S3C2410
> +	help
> +	  Say Y here to enable support for disabling the I2C unit
> +	  clock when the bus is idle. This is useful to save power
> +	  if not using the unit as a bus slave.
> +
>  config I2C_SAVAGE4
>  	tristate "S3 Savage 4"
>  	depends on I2C && PCI && EXPERIMENTAL
> diff -urpN -X ../dontdiff linux-2.6.16-rmk/drivers/i2c/busses/i2c-s3c2410.c linux-2.6.16-rmk-bjd1/drivers/i2c/busses/i2c-s3c2410.c
> --- linux-2.6.16-rmk/drivers/i2c/busses/i2c-s3c2410.c	2006-03-20 05:53:29.000000000 +0000
> +++ linux-2.6.16-rmk-bjd1/drivers/i2c/busses/i2c-s3c2410.c	2006-03-21 22:44:26.000000000 +0000
> @@ -44,6 +44,14 @@
>  #include <asm/arch/regs-iic.h>
>  #include <asm/arch/iic.h>
>  
> +/* configuration */
> +
> +#ifdef CONFIG_I2C_S3C2410_CLKIDLE
> +static int clock_idle = 1;
> +#else
> +static const int clock_idle = 0;
> +#endif
> +

Why did you make it a compilation-time choice, rather than a run-time
one? It would be easy to define a sysfs attribute for the driver, so
that the user can change his/her mind anytime.

>  /* i2c controller state */
>  
>  enum s3c24xx_i2c_state {
> @@ -96,6 +104,11 @@ static inline int s3c24xx_i2c_is2440(str
>  	return !strcmp(pdev->name, "s3c2440-i2c");
>  }
>  
> +static inline int s3c24xx_i2c_clkidle(struct s3c24xx_i2c *i2c)
> +{
> +	return clock_idle;
> +}
> +

This function doesn't make much sense, why don't you test clock_idle
directly?

>  
>  /* s3c24xx_i2c_get_platformdata
>   *
> @@ -214,7 +227,7 @@ static inline void s3c24xx_i2c_stop(stru
>  {
>  	unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT);
>  
> -	dev_dbg(i2c->dev, "STOP\n");
> +	dev_dbg(i2c->dev, "STOP (ret=%d)\n", ret);
>  
>  	/* stop the transfer */
>  	iicstat &= ~ S3C2410_IICSTAT_START;
> @@ -269,6 +282,7 @@ static int i2s_s3c_irq_nextbyte(struct s
>  	unsigned long tmp;
>  	unsigned char byte;
>  	int ret = 0;
> +	int i;
>  
>  	switch (i2c->state) {
>  
> @@ -324,7 +338,15 @@ static int i2s_s3c_irq_nextbyte(struct s
>  		if (!is_msgend(i2c)) {
>  			byte = i2c->msg->buf[i2c->msg_ptr++];
>  			writeb(byte, i2c->regs + S3C2410_IICDS);
> -			
> +
> +			/* sometimes write operations fail if the write is
> +			 * let go too quickly, slow down the proceedings
> +			 * slightly.
> +			 */
> +
> +			for (i = 0; i < 6; i++) 
> +				tmp += readl(i2c->regs + S3C2410_IICSTAT);
> +

Ugly hack, is there no cleaner way? :(

BTW I'd expect a warning from the compiler, as tmp is uninitialized at
this point. Why do you need tmp at all?

> @@ -870,6 +903,9 @@ static int s3c24xx_i2c_remove(struct pla
>  	if (i2c != NULL) {
>  		s3c24xx_i2c_free(i2c);
>  		platform_set_drvdata(pdev, NULL);
> +
> +		if (!s3c24xx_i2c_clkidle(i2c))
> +			clk_disable(i2c->clk);
>  	}

You already disable the clock in s3c24xx_i2c_free, so why do it again?

-- 
Jean Delvare




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux