S3C24XX Updates for post 2.6.26
Subsystems (2)
cover S3C24XX Updates for post 2.6.26
I2C updates for merging once 2.6.26 is out.
Signature · 6 lines
Ben _______________________________________________ i2c mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/i2c
PATCH 1/2 I2C: S3C2410: Pass the I2C bus number via drivers platform data
Allow the platform data to specify the bus bumber that the new I2C bus will be given. This is to allow the use of the board registration mechanism to specify the new style of I2C device registration which allows boards to provide a list of attached devices.
Note, as discussed on the mailing list, we have dropped backwards compatibility of adding an dynamic bus number as it should not affect most boards to have the bus pinned to 0 if they have either not specified platform data for driver. Any board supplying platform data will automatically have the bus_num field set to 0, and anyone who needs the driver on a different bus number can supply platform data to set bus_num.
drivers/i2c/busses/i2c-s3c2410.c +12 -1
@@ -752,9 +752,12 @@ static int s3c24xx_i2c_init(struct s3c24static int s3c24xx_i2c_probe (struct platform_device *pdev) {struct s3c24xx_i2c *i2c = &s3c24xx_i2c; +struct s3c2410_platform_i2c *pdata;struct resource *res;int ret; + pdata =s3c24xx_i2c_get_platformdata (&pdev->dev); +/* find the clock and enable it */ i2c->dev = &pdev->dev;
@@ -832,7 +835,15 @@ static int s3c24xx_i2c_probe(struct platdev_dbg (&pdev->dev,"irq resource %p (%lu)\n" , res, (unsigned long )res->start); - ret =i2c_add_adapter (&i2c->adap); +/* Note, previous versions of the driver used i2c_add_adapter() +* to add an bus at any number. We now pass the bus number via +* the platform data, so if unset it will now default to always +* being bus 0. +*/ + + i2c->adap.nr = pdata->bus_num; + ret =i2c_add_numbered_adapter (&i2c->adap); +if (ret <0 ) {dev_err (&pdev->dev,"failed to add bus to i2c core\n" ); goto err_irq;
include/asm-arm/plat-s3c/iic.h +1 -0
@@ -21,6 +21,7 @@*/ struct s3c2410_platform_i2c { +int bus_num;/* bus number to use */ unsigned int flags;unsigned int slave_addr;/* slave address for controller */ unsigned long bus_freq;/* standard bus frequency */
Signature · 4 lines
_______________________________________________ i2c mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/i2c
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch 1/2] I2C: S3C2410: Pass the I2C bus number via drivers platform data
Hi Ben,
Quoted 10 lines · Ben Dooks
Allow the platform data to specify the bus bumber that the new I2C bus will be given. This is to allow the use of the board registration mechanism to specify the new style of I2C device registration which allows boards to provide a list of attached devices.
Note, as discussed on the mailing list, we have dropped backwards compatibility of adding an dynamic bus number as it should not affect most boards to have the bus pinned to 0 if they have either not specified platform data for
either?
Quoted 4 lines
driver. Any board supplying platform data will automatically have the
bus_numfield set to 0, and anyone who needs the driver on a different bus number can supply platform data to setbus_num.
Sounds OK to me.
Quoted 21 lines
Signed-off-by Ben Dooks <[email protected]>Index:
linux-2.6.26-rc4-quilt3/drivers/i2c/busses/i2c-s3c2410.c
===================================================================drivers/i2c/busses/i2c-s3c2410.c +3
-0@@ -752,9 +752,12 @@ static int s3c24xx_i2c_init(struct s3c24static int s3c24xx_i2c_probe (struct platform_device *pdev) {struct s3c24xx_i2c *i2c = &s3c24xx_i2c; +struct s3c2410_platform_i2c *pdata;struct resource *res;int ret; + pdata =s3c24xx_i2c_get_platformdata (&pdev->dev); +/* find the clock and enable it */ i2c->dev = &pdev->dev;
drivers/i2c/busses/i2c-s3c2410.c static int s3c24xx_i2c_probe(struct plat · line 839
Quoted 6 lines
drivers/i2c/busses/i2c-s3c2410.c +2
-1@@ -832,7 +835,15 @@ static int s3c24xx_i2c_probe(struct platdev_dbg (&pdev->dev,"irq resource %p (%lu)\n" , res, (unsigned long )res->start); - ret =i2c_add_adapter (&i2c->adap); +/* Note, previous versions of the driver used i2c_add_adapter() +* to add an bus at any number. We now pass the bus number via
"an bus" doesn't look correct.
drivers/i2c/busses/i2c-s3c2410.c static int s3c24xx_i2c_probe(struct plat · line 847
Quoted 8 lines
drivers/i2c/busses/i2c-s3c2410.c +7
-0+* the platform data, so if unset it will now default to always +* being bus 0. +*/ + + i2c->adap.nr = pdata->bus_num; + ret =i2c_add_numbered_adapter (&i2c->adap); +if (ret <0 ) {
Best practice is to not have a blank line between a function call and the test of its return value.
Quoted 8 lines
drivers/i2c/busses/i2c-s3c2410.c +0
-0dev_err (&pdev->dev,"failed to add bus to i2c core\n" ); goto err_irq;Index:
linux-2.6.26-rc4-quilt3/include/asm-arm/plat-s3c/iic.h
===================================================================
include/asm-arm/plat-s3c/iic.h line 27
Quoted 7 lines
include/asm-arm/plat-s3c/iic.h +1
-0@@ -21,6 +21,7 @@*/ struct s3c2410_platform_i2c { +int bus_num;/* bus number to use */ unsigned int flags;unsigned int slave_addr;/* slave address for controller */ unsigned long bus_freq;/* standard bus frequency */
Other than these details, the patch looks OK to me.
Signature · 6 lines
Jean Delvare _______________________________________________ i2c mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/i2c
PATCH 2/2 I2C: S3C24XX I2C frequency scaling support.
In reply to Ben DooksAdd support for CPU frequency scaling to the S3C24XX I2C driver.
drivers/i2c/busses/i2c-s3c2410.c +103 -13
@@ -33,6 +33,7 @@#include <linux/err.h> #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/cpufreq.h> #include <asm/hardware.h> #include <asm/irq.h>
@@ -64,6 +65,7 @@ struct s3c24xx_i2c {unsigned int tx_setup;enum s3c24xx_i2c_state state; +unsigned long clkrate;void __iomem *regs;struct clk *clk;
@@ -71,6 +73,10 @@ struct s3c24xx_i2c {struct resource *irq;struct resource *ioarea;struct i2c_adapter adap; + +#ifdef CONFIG_CPU_FREQ +struct notifier_block freq_transition; +#endif };/* default platform data to use if not supplied in the platform_device
@@ -501,6 +507,9 @@ static int s3c24xx_i2c_doxfer(struct s3cunsigned long timeout;int ret; +if (!readl (i2c->regs +S3C2410_IICCON ) &S3C2410_IICCON_IRQEN ) +return -EIO ; + ret =s3c24xx_i2c_set_master (i2c);if (ret !=0 ) {dev_err (i2c->dev,"cannot get bus (error %d)\n" , ret);
@@ -636,27 +645,28 @@ static inline int freq_acceptable(unsignreturn (diff >=-2 && diff <=2 ); } -/* s3c24xx_i2c_getdivisor +/* s3c24xx_i2c_clockrate * * work out a divisor for the user requested frequency setting, * either by the requested frequency, or scanning the acceptable * range of frequencies until something is found */ -static int s3c24xx_i2c_getdivisor (struct s3c24xx_i2c *i2c, -struct s3c2410_platform_i2c *pdata, -unsigned long *iicon, -unsigned int *got) +static int s3c24xx_i2c_clockrate (struct s3c24xx_i2c *i2c,unsigned int *got) { +struct s3c2410_platform_i2c *pdata;unsigned long clkin =clk_get_rate (i2c->clk); -unsigned int divs, div1; +u32 iiccon;int freq;int start, end; + i2c->clkrate = clkin; + + pdata =s3c24xx_i2c_get_platformdata (i2c->adap.dev.parent); clkin /=1000 ;/* clkin now in KHz */ -dev_dbg (i2c->dev,"pdata %p, freq %lu %lu..%lu\n" , +dev_dbg (i2c->dev,"pdata %p, freq %lu %lu..%lu\n" , pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);if (pdata->bus_freq !=0 ) {
@@ -688,11 +698,79 @@ static int s3c24xx_i2c_getdivisor(struct found: *got = freq; - *iicon |= (divs-1 ); - *iicon |= (div1 ==512 ) ?S3C2410_IICCON_TXDIV_512 :0 ; + + iiccon =readl (i2c->regs +S3C2410_IICCON ); + iiccon &= ~(S3C2410_IICCON_SCALEMASK |S3C2410_IICCON_TXDIV_512 ); + iiccon |= (divs-1 ); + +if (div1 ==512 ) + iiccon |=S3C2410_IICCON_TXDIV_512 ; + +writel (iiccon, i2c->regs +S3C2410_IICCON ); + +return 0 ; +} + +#ifdef CONFIG_CPU_FREQ + +#define freq_to_i2c (_n) container_of(_n, struct s3c24xx_i2c, freq_transition) + +static int s3c24xx_i2c_cpufreq_transition (struct notifier_block *nb, +unsigned long val,void *data) +{ +struct s3c24xx_i2c *i2c =freq_to_i2c (nb); +unsigned long clkrate; +unsigned long flags; +unsigned int got; +int ret; + + clkrate =clk_get_rate (i2c->clk); + +/* if we're post-change and the input clock has slowed down +* or at pre-change and the clock is about to speed up, then +* adjust our clock rate. +*/ + +if ((val ==CPUFREQ_POSTCHANGE && clkrate < i2c->clkrate) || + (val ==CPUFREQ_PRECHANGE && clkrate > i2c->clkrate)) { +spin_lock_irqsave (&i2c->lock, flags); + ret =s3c24xx_i2c_clockrate (i2c, &got); +spin_unlock_irqrestore (&i2c->lock, flags); + +if (ret <0 ) +dev_err (i2c->dev,"cannot find frequency\n" ); +else +dev_info (i2c->dev,"setting freq %d\n" , got); + } +return 0 ; } +static inline int s3c24xx_i2c_register_cpufreq (struct s3c24xx_i2c *i2c) +{ + i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition; + +return cpufreq_register_notifier (&i2c->freq_transition, +CPUFREQ_TRANSITION_NOTIFIER ); +} + +static inline void s3c24xx_i2c_deregister_cpufreq (struct s3c24xx_i2c *i2c) +{ +cpufreq_unregister_notifier (&i2c->freq_transition, +CPUFREQ_TRANSITION_NOTIFIER ); +} + +#else +static inline int s3c24xx_i2c_register_cpufreq (struct s3c24xx_i2c *i2c) +{ +return 0 ; +} + +static inline void s3c24xx_i2c_deregister_cpufreq (struct s3c24xx_i2c *i2c) +{ +} +#endif +/* s3c24xx_i2c_init * * initialise the controller, set the IO lines and frequency
@@ -719,9 +797,12 @@ static int s3c24xx_i2c_init(struct s3c24dev_info (i2c->dev,"slave address 0x%02x\n" , pdata->slave_addr); +writel (iicon, i2c->regs +S3C2410_IICCON ); +/* we need to work out the divisors for the clock... */ -if (s3c24xx_i2c_getdivisor (i2c, pdata, &iicon, &freq) !=0 ) { +if (s3c24xx_i2c_clockrate (i2c, &freq) !=0 ) { +writel (0 , i2c->regs +S3C2410_IICCON );dev_err (i2c->dev,"cannot meet bus frequency required\n" );return -EINVAL ; }
@@ -730,8 +811,6 @@ static int s3c24xx_i2c_init(struct s3c24dev_info (i2c->dev,"bus frequency set to %d KHz\n" , freq);dev_dbg (i2c->dev,"S3C2410_IICCON=0x%02lx\n" , iicon); - -writel (iicon, i2c->regs +S3C2410_IICCON );/* check for s3c2440 i2c controller */
@@ -835,6 +914,12 @@ static int s3c24xx_i2c_probe(struct platdev_dbg (&pdev->dev,"irq resource %p (%lu)\n" , res, (unsigned long )res->start); + ret =s3c24xx_i2c_register_cpufreq (i2c); +if (ret <0 ) { +dev_err (&pdev->dev,"failed to register cpufreq notifier\n" ); + goto err_irq; + } +/* Note, previous versions of the driver used i2c_add_adapter() * to add an bus at any number. We now pass the bus number via * the platform data, so if unset it will now default to always
@@ -846,7 +931,7 @@ static int s3c24xx_i2c_probe(struct platif (ret <0 ) {dev_err (&pdev->dev,"failed to add bus to i2c core\n" ); - goto err_irq; + goto err_cpufreq; }platform_set_drvdata (pdev, i2c);
@@ -854,6 +939,9 @@ static int s3c24xx_i2c_probe(struct platdev_info (&pdev->dev,"%s: S3C I2C adapter\n" , i2c->adap.dev.bus_id);return 0 ; + err_cpufreq: +s3c24xx_i2c_deregister_cpufreq (i2c); + err_irq:free_irq (i2c->irq->start, i2c);
@@ -881,6 +969,8 @@ static int s3c24xx_i2c_remove(struct pla {struct s3c24xx_i2c *i2c =platform_get_drvdata (pdev); +s3c24xx_i2c_deregister_cpufreq (i2c); +i2c_del_adapter (&i2c->adap);free_irq (i2c->irq->start, i2c);
Signature · 4 lines
_______________________________________________ i2c mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/i2c