diff mbox

[3/8] i2c: at91: use an id table for SoC dependent parameters

Message ID 1346404884-18451-4-git-send-email-ludovic.desroches@atmel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ludovic Desroches Aug. 31, 2012, 9:21 a.m. UTC
From: Ludovic Desroches <ludovic.desroches@atmel.com>

Use the id_table to store configuration structures which are depending on
SoC.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
---
 arch/arm/mach-at91/at91rm9200.c          |  2 +-
 arch/arm/mach-at91/at91rm9200_devices.c  | 11 +----
 arch/arm/mach-at91/at91sam9260.c         |  3 +-
 arch/arm/mach-at91/at91sam9260_devices.c |  8 ++-
 arch/arm/mach-at91/at91sam9261.c         |  3 +-
 arch/arm/mach-at91/at91sam9261_devices.c | 17 +++----
 arch/arm/mach-at91/at91sam9263.c         |  2 +-
 arch/arm/mach-at91/at91sam9263_devices.c |  2 +-
 arch/arm/mach-at91/at91sam9g45.c         |  4 +-
 arch/arm/mach-at91/at91sam9g45_devices.c |  4 +-
 arch/arm/mach-at91/at91sam9rl.c          |  4 +-
 arch/arm/mach-at91/at91sam9rl_devices.c  |  2 +-
 drivers/i2c/busses/i2c-at91.c            | 85 +++++++++++++++++++++++++-------
 13 files changed, 95 insertions(+), 52 deletions(-)

Comments

Jean-Christophe PLAGNIOL-VILLARD Aug. 31, 2012, 2:29 p.m. UTC | #1
On 11:21 Fri 31 Aug     , ludovic.desroches@atmel.com wrote:
> From: Ludovic Desroches <ludovic.desroches@atmel.com>
> 
> Use the id_table to store configuration structures which are depending on
> SoC.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
> ---
>  arch/arm/mach-at91/at91rm9200.c          |  2 +-
>  arch/arm/mach-at91/at91rm9200_devices.c  | 11 +----
>  arch/arm/mach-at91/at91sam9260.c         |  3 +-
>  arch/arm/mach-at91/at91sam9260_devices.c |  8 ++-
>  arch/arm/mach-at91/at91sam9261.c         |  3 +-
>  arch/arm/mach-at91/at91sam9261_devices.c | 17 +++----
>  arch/arm/mach-at91/at91sam9263.c         |  2 +-
>  arch/arm/mach-at91/at91sam9263_devices.c |  2 +-
>  arch/arm/mach-at91/at91sam9g45.c         |  4 +-
>  arch/arm/mach-at91/at91sam9g45_devices.c |  4 +-
>  arch/arm/mach-at91/at91sam9rl.c          |  4 +-
>  arch/arm/mach-at91/at91sam9rl_devices.c  |  2 +-
>  drivers/i2c/busses/i2c-at91.c            | 85 +++++++++++++++++++++++++-------
>  13 files changed, 95 insertions(+), 52 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
> index f2112f9..0bc91e5 100644
> --- a/arch/arm/mach-at91/at91rm9200.c
> +++ b/arch/arm/mach-at91/at91rm9200.c
> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>  	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
>  	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
>  	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c", &twi_clk),
use i2c-xxx as on other drivers

and I do not like to have platform_device_id

as we need to touch the driver to add a new soc

please use platform data

Best Regards,
J.
Nicolas Ferre Aug. 31, 2012, 2:51 p.m. UTC | #2
On 08/31/2012 04:29 PM, Jean-Christophe PLAGNIOL-VILLARD :
> On 11:21 Fri 31 Aug     , ludovic.desroches@atmel.com wrote:
>> From: Ludovic Desroches <ludovic.desroches@atmel.com>
>>
>> Use the id_table to store configuration structures which are depending on
>> SoC.
>>
>> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
>> ---
>>  arch/arm/mach-at91/at91rm9200.c          |  2 +-
>>  arch/arm/mach-at91/at91rm9200_devices.c  | 11 +----
>>  arch/arm/mach-at91/at91sam9260.c         |  3 +-
>>  arch/arm/mach-at91/at91sam9260_devices.c |  8 ++-
>>  arch/arm/mach-at91/at91sam9261.c         |  3 +-
>>  arch/arm/mach-at91/at91sam9261_devices.c | 17 +++----
>>  arch/arm/mach-at91/at91sam9263.c         |  2 +-
>>  arch/arm/mach-at91/at91sam9263_devices.c |  2 +-
>>  arch/arm/mach-at91/at91sam9g45.c         |  4 +-
>>  arch/arm/mach-at91/at91sam9g45_devices.c |  4 +-
>>  arch/arm/mach-at91/at91sam9rl.c          |  4 +-
>>  arch/arm/mach-at91/at91sam9rl_devices.c  |  2 +-
>>  drivers/i2c/busses/i2c-at91.c            | 85 +++++++++++++++++++++++++-------
>>  13 files changed, 95 insertions(+), 52 deletions(-)
>>
>> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
>> index f2112f9..0bc91e5 100644
>> --- a/arch/arm/mach-at91/at91rm9200.c
>> +++ b/arch/arm/mach-at91/at91rm9200.c
>> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>>  	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
>>  	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
>>  	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
>> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
>> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c", &twi_clk),
> use i2c-xxx as on other drivers
> 
> and I do not like to have platform_device_id

Me, I like it and find this implementation very elegant.

> as we need to touch the driver to add a new soc

So what? We still keep the compatibility if the new SoC has it
compatibility assured with previous revision: there is nothing to modify.

> please use platform data

No, it does not have to be exposed to the user: these data are highly
dependent on the actual hardware (IP revision in fact). So, no need to
mess with platform data.

So I will acknowledge Ludo's patches.

Bye,
Sylwester Nawrocki Aug. 31, 2012, 8:47 p.m. UTC | #3
On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
>>> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
>>> index f2112f9..0bc91e5 100644
>>> --- a/arch/arm/mach-at91/at91rm9200.c
>>> +++ b/arch/arm/mach-at91/at91rm9200.c
>>> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.0",&ssc0_clk),
>>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.1",&ssc1_clk),
>>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.2",&ssc2_clk),
>>> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c",&twi_clk),
>>> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c",&twi_clk),
>> use i2c-xxx as on other drivers
>>
>> and I do not like to have platform_device_id
> 
> Me, I like it and find this implementation very elegant.
> 
>> as we need to touch the driver to add a new soc
> 
> So what? We still keep the compatibility if the new SoC has it
> compatibility assured with previous revision: there is nothing to modify.

I agree. The driver would need to be touched to support new SoC only if
the IP there have had some differences, which would have needed to be 
resolved anyway.

>> please use platform data

Using platform data for the dt platforms would have been more troublesome,
wouldn't it ? I like Ludovic's approach which handles both: dt and non-dt 
cases in uniform way from the driver's POV.

> No, it does not have to be exposed to the user: these data are highly
> dependent on the actual hardware (IP revision in fact). So, no need to
> mess with platform data.

Agreed.
 
> So I will acknowledge Ludo's patches.
> 
> Bye,

--

Regards,
Sylwester
Jean-Christophe PLAGNIOL-VILLARD Sept. 1, 2012, 9:10 a.m. UTC | #4
On 22:47 Fri 31 Aug     , Sylwester Nawrocki wrote:
> On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
> >>> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
> >>> index f2112f9..0bc91e5 100644
> >>> --- a/arch/arm/mach-at91/at91rm9200.c
> >>> +++ b/arch/arm/mach-at91/at91rm9200.c
> >>> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
> >>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.0",&ssc0_clk),
> >>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.1",&ssc1_clk),
> >>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.2",&ssc2_clk),
> >>> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c",&twi_clk),
> >>> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c",&twi_clk),
> >> use i2c-xxx as on other drivers
> >>
> >> and I do not like to have platform_device_id
> > 
> > Me, I like it and find this implementation very elegant.
> > 
> >> as we need to touch the driver to add a new soc
> > 
> > So what? We still keep the compatibility if the new SoC has it
> > compatibility assured with previous revision: there is nothing to modify.
> 
> I agree. The driver would need to be touched to support new SoC only if
> the IP there have had some differences, which would have needed to be 
> resolved anyway.
> 
> >> please use platform data
> 
> Using platform data for the dt platforms would have been more troublesome,
> wouldn't it ? I like Ludovic's approach which handles both: dt and non-dt 
> cases in uniform way from the driver's POV.
no you will describe it via DT as done on all the other drivers
> 
> > No, it does not have to be exposed to the user: these data are highly
> > dependent on the actual hardware (IP revision in fact). So, no need to
> > mess with platform data.
no I really see no point on these list of platform_id it's does not look more
nice just more huggly to have x names. This is at the end the same as passing
platform data via soc info (add_xx or dtsi)

And here you just do the same as cpu_is via names.

The driver need to read IP revision instead

Best Regards,
J.
Sylwester Nawrocki Sept. 2, 2012, 5:21 p.m. UTC | #5
On 09/01/2012 11:10 AM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 22:47 Fri 31 Aug     , Sylwester Nawrocki wrote:
>> On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
>>>>> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
>>>>> index f2112f9..0bc91e5 100644
>>>>> --- a/arch/arm/mach-at91/at91rm9200.c
>>>>> +++ b/arch/arm/mach-at91/at91rm9200.c
>>>>> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>>>>>    	CLKDEV_CON_DEV_ID("pclk", "ssc.0",&ssc0_clk),
>>>>>    	CLKDEV_CON_DEV_ID("pclk", "ssc.1",&ssc1_clk),
>>>>>    	CLKDEV_CON_DEV_ID("pclk", "ssc.2",&ssc2_clk),
>>>>> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c",&twi_clk),
>>>>> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c",&twi_clk),
>>>> use i2c-xxx as on other drivers
>>>>
>>>> and I do not like to have platform_device_id
>>>
>>> Me, I like it and find this implementation very elegant.
>>>
>>>> as we need to touch the driver to add a new soc
>>>
>>> So what? We still keep the compatibility if the new SoC has it
>>> compatibility assured with previous revision: there is nothing to modify.
>>
>> I agree. The driver would need to be touched to support new SoC only if
>> the IP there have had some differences, which would have needed to be
>> resolved anyway.
>>
>>>> please use platform data
>>
>> Using platform data for the dt platforms would have been more troublesome,
>> wouldn't it ? I like Ludovic's approach which handles both: dt and non-dt
>> cases in uniform way from the driver's POV.
> no you will describe it via DT as done on all the other drivers

Yeah, makes sense. However there are drivers that deduce some parameters
only from the 'compatible' property, let's take drivers/dma/mxs-dma.c as an
example. I'm just trying to understand if there is a general preference on
how to handle those things. Of course we could have all detail properties
listed in a .dtsi file. But since we can derive these from a single property,
it might be more sensible to avoid parsing ?

>>> No, it does not have to be exposed to the user: these data are highly
>>> dependent on the actual hardware (IP revision in fact). So, no need to
>>> mess with platform data.
> no I really see no point on these list of platform_id it's does not look more
> nice just more huggly to have x names. This is at the end the same as passing
> platform data via soc info (add_xx or dtsi)
> 
> And here you just do the same as cpu_is via names.
> 
> The driver need to read IP revision instead

OK, but wouldn't it be needed to resolve an IP revision at run time, e.g.
with soc_is_*() anyway ? Having it set at each board doesn't look like an 
optimal method either.

--

Regards,
Sylwester
Voss, Nikolaus Sept. 3, 2012, 5:55 a.m. UTC | #6
ludovic.desroches@atmel.com wrote on Friday, August 31, 2012 11:21 AM
> From: Ludovic Desroches <ludovic.desroches@atmel.com>
>
> Use the id_table to store configuration structures which are depending on
> SoC.
>
> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Nice solution!
Acked-by: Nikolaus Voss <n.voss@weinmann.de>

> ---
>  arch/arm/mach-at91/at91rm9200.c          |  2 +-
>  arch/arm/mach-at91/at91rm9200_devices.c  | 11 +----
>  arch/arm/mach-at91/at91sam9260.c         |  3 +-
>  arch/arm/mach-at91/at91sam9260_devices.c |  8 ++-
>  arch/arm/mach-at91/at91sam9261.c         |  3 +-
>  arch/arm/mach-at91/at91sam9261_devices.c | 17 +++----
>  arch/arm/mach-at91/at91sam9263.c         |  2 +-
>  arch/arm/mach-at91/at91sam9263_devices.c |  2 +-
>  arch/arm/mach-at91/at91sam9g45.c         |  4 +-
>  arch/arm/mach-at91/at91sam9g45_devices.c |  4 +-
>  arch/arm/mach-at91/at91sam9rl.c          |  4 +-
>  arch/arm/mach-at91/at91sam9rl_devices.c  |  2 +-
>  drivers/i2c/busses/i2c-at91.c            | 85 +++++++++++++++++++++++++-------
>  13 files changed, 95 insertions(+), 52 deletions(-)
>
> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-
> at91/at91rm9200.c
> index f2112f9..0bc91e5 100644
> --- a/arch/arm/mach-at91/at91rm9200.c
> +++ b/arch/arm/mach-at91/at91rm9200.c
> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c", &twi_clk),
>       /* fake hclk clock */
>       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
>       CLKDEV_CON_ID("pioA", &pioA_clk),
> diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-
> at91/at91rm9200_devices.c
> index 71e7387..cddfe02 100644
> --- a/arch/arm/mach-at91/at91rm9200_devices.c
> +++ b/arch/arm/mach-at91/at91rm9200_devices.c
> @@ -494,18 +494,9 @@ static struct resource twi_resources[] = {
>       },
>  };
>
> -static const struct platform_device_id twi_ip_type = {
> -     /*
> -      * driver_data is 1 for RM9200 compatible ip, see enum twi_ip_id in
> -      * drivers/i2c/busses/i2c-at91.c
> -      */
> -     .driver_data    = 1,
> -};
> -
>  static struct platform_device at91rm9200_twi_device = {
> -     .name           = "at91_i2c",
> +     .name           = "at91rm9200_i2c",
>       .id             = -1,
> -     .id_entry       = &twi_ip_type,
>       .resource       = twi_resources,
>       .num_resources  = ARRAY_SIZE(twi_resources),
>  };
> diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-
> at91/at91sam9260.c
> index 57c79ee..5f86e71 100644
> --- a/arch/arm/mach-at91/at91sam9260.c
> +++ b/arch/arm/mach-at91/at91sam9260.c
> @@ -211,7 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
>       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
>       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9260_i2c", &twi_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9g20_i2c", &twi_clk),
>       /* more usart lookup table for DT entries */
>       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
>       CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
> diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-
> at91/at91sam9260_devices.c
> index 7b9c2ba..ed02171 100644
> --- a/arch/arm/mach-at91/at91sam9260_devices.c
> +++ b/arch/arm/mach-at91/at91sam9260_devices.c
> @@ -503,7 +503,6 @@ static struct resource twi_resources[] = {
>  };
>
>  static struct platform_device at91sam9260_twi_device = {
> -     .name           = "at91_i2c",
>       .id             = -1,
>       .resource       = twi_resources,
>       .num_resources  = ARRAY_SIZE(twi_resources),
> @@ -511,6 +510,13 @@ static struct platform_device
> at91sam9260_twi_device = {
>
>  void __init at91_add_device_i2c(struct i2c_board_info *devices, int
> nr_devices)
>  {
> +     /* IP version is not the same on 9260 and g20 */
> +     if (cpu_is_at91sam9g20()) {
> +             at91sam9260_twi_device.name = "at91sam9g20_i2c";
> +     } else {
> +             at91sam9260_twi_device.name = "at91sam9260_i2c";
> +     }
> +
>       /* pins used for TWI interface */
>       at91_set_A_periph(AT91_PIN_PA23, 0);            /* TWD */
>       at91_set_multi_drive(AT91_PIN_PA23, 1);
> diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-
> at91/at91sam9261.c
> index 71ca1e0..0ccf63c 100644
> --- a/arch/arm/mach-at91/at91sam9261.c
> +++ b/arch/arm/mach-at91/at91sam9261.c
> @@ -178,7 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
>       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
>       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9261_i2c", &twi_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9g10_i2c", &twi_clk),
>       CLKDEV_CON_ID("pioA", &pioA_clk),
>       CLKDEV_CON_ID("pioB", &pioB_clk),
>       CLKDEV_CON_ID("pioC", &pioC_clk),
> diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-
> at91/at91sam9261_devices.c
> index d830724..c94495d 100644
> --- a/arch/arm/mach-at91/at91sam9261_devices.c
> +++ b/arch/arm/mach-at91/at91sam9261_devices.c
> @@ -316,24 +316,21 @@ static struct resource twi_resources[] = {
>       },
>  };
>
> -static const struct platform_device_id twi_ip_type = {
> -     /*
> -      * driver_data is 2 for SAM9261 compatible ip, see enum twi_ip_id in
> -      * drivers/i2c/busses/i2c-at91.c
> -      */
> -     .driver_data    = 2,
> -};
> -
>  static struct platform_device at91sam9261_twi_device = {
> -     .name           = "at91_i2c",
>       .id             = -1,
> -     .id_entry       = &twi_ip_type,
>       .resource       = twi_resources,
>       .num_resources  = ARRAY_SIZE(twi_resources),
>  };
>
>  void __init at91_add_device_i2c(struct i2c_board_info *devices, int
> nr_devices)
>  {
> +     /* IP version is not the same on 9261 and g10 */
> +     if (cpu_is_at91sam9g10()) {
> +             at91sam9261_twi_device.name = "at91sam9g10_i2c";
> +     } else {
> +             at91sam9261_twi_device.name = "at91sam9261_i2c";
> +     }
> +
>       /* pins used for TWI interface */
>       at91_set_A_periph(AT91_PIN_PA7, 0);             /* TWD */
>       at91_set_multi_drive(AT91_PIN_PA7, 1);
> diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-
> at91/at91sam9263.c
> index 2a08305..a4d760c 100644
> --- a/arch/arm/mach-at91/at91sam9263.c
> +++ b/arch/arm/mach-at91/at91sam9263.c
> @@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
>       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
>       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9260_i2c", &twi_clk),
>       /* fake hclk clock */
>       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
>       CLKDEV_CON_ID("pioA", &pioA_clk),
> diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-
> at91/at91sam9263_devices.c
> index eb6bbf8..7cff86c 100644
> --- a/arch/arm/mach-at91/at91sam9263_devices.c
> +++ b/arch/arm/mach-at91/at91sam9263_devices.c
> @@ -574,7 +574,7 @@ static struct resource twi_resources[] = {
>  };
>
>  static struct platform_device at91sam9263_twi_device = {
> -     .name           = "at91_i2c",
> +     .name           = "at91sam9260_i2c",
>       .id             = -1,
>       .resource       = twi_resources,
>       .num_resources  = ARRAY_SIZE(twi_resources),
> diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-
> at91/at91sam9g45.c
> index ddf3d37..15e62b9 100644
> --- a/arch/arm/mach-at91/at91sam9g45.c
> +++ b/arch/arm/mach-at91/at91sam9g45.c
> @@ -237,8 +237,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
>       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
>       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
>       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9g10_i2c.0", &twi0_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9g10_i2c.1", &twi1_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
>       CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
> diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-
> at91/at91sam9g45_devices.c
> index f001305..a61c7ec 100644
> --- a/arch/arm/mach-at91/at91sam9g45_devices.c
> +++ b/arch/arm/mach-at91/at91sam9g45_devices.c
> @@ -653,7 +653,7 @@ static struct resource twi0_resources[] = {
>  };
>
>  static struct platform_device at91sam9g45_twi0_device = {
> -     .name           = "at91_i2c",
> +     .name           = "at91sam9g10_i2c",
>       .id             = 0,
>       .resource       = twi0_resources,
>       .num_resources  = ARRAY_SIZE(twi0_resources),
> @@ -673,7 +673,7 @@ static struct resource twi1_resources[] = {
>  };
>
>  static struct platform_device at91sam9g45_twi1_device = {
> -     .name           = "at91_i2c",
> +     .name           = "at91sam9g10_i2c",
>       .id             = 1,
>       .resource       = twi1_resources,
>       .num_resources  = ARRAY_SIZE(twi1_resources),
> diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-
> at91/at91sam9rl.c
> index bf79c1f..d708dfa 100644
> --- a/arch/arm/mach-at91/at91sam9rl.c
> +++ b/arch/arm/mach-at91/at91sam9rl.c
> @@ -186,8 +186,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
>       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
>       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
> -     CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9g20_i2c.0", &twi0_clk),
> +     CLKDEV_CON_DEV_ID(NULL, "at91sam9g20_i2c.1", &twi1_clk),
>       CLKDEV_CON_ID("pioA", &pioA_clk),
>       CLKDEV_CON_ID("pioB", &pioB_clk),
>       CLKDEV_CON_ID("pioC", &pioC_clk),
> diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-
> at91/at91sam9rl_devices.c
> index f09fff9..2df7411 100644
> --- a/arch/arm/mach-at91/at91sam9rl_devices.c
> +++ b/arch/arm/mach-at91/at91sam9rl_devices.c
> @@ -346,7 +346,7 @@ static struct resource twi_resources[] = {
>  };
>
>  static struct platform_device at91sam9rl_twi_device = {
> -     .name           = "at91_i2c",
> +     .name           = "at91sam9g20_i2c",
>       .id             = -1,
>       .resource       = twi_resources,
>       .num_resources  = ARRAY_SIZE(twi_resources),
> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
> index 08aaee7..bcf9a5c 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -61,10 +61,10 @@
>  #define      AT91_TWI_RHR            0x0030  /* Receive Holding
> Register */
>  #define      AT91_TWI_THR            0x0034  /* Transmit Holding Register
> */
>
> -enum twi_ip_id {
> -     DEFAULT         = 0, /* default ip, no known limitations */
> -     RM9200          = 1,
> -     SAM9261         = 2,
> +struct at91_twi_pdata {
> +     unsigned        clk_max_div;
> +     unsigned        clk_offset;
> +     bool            has_unre_flag;
>  };
>
>  struct at91_twi_dev {
> @@ -78,8 +78,8 @@ struct at91_twi_dev {
>       int                     irq;
>       unsigned                transfer_status;
>       struct i2c_adapter      adapter;
> -     enum twi_ip_id          ip_id;
>       unsigned                twi_cwgr_reg;
> +     struct at91_twi_pdata   *pdata;
>  };
>
>  static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
> @@ -114,16 +114,9 @@ static void at91_init_twi_bus(struct at91_twi_dev
> *dev)
>  static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int
> twi_clk)
>  {
>       int ckdiv, cdiv, div;
> -     int offset = 4;
> -     int max_ckdiv = 7;
> -
> -     if (dev->ip_id == RM9200) {
> -             offset = 3;
> -             max_ckdiv = 5;
> -     } else if (dev->ip_id == SAM9261) {
> -             offset = 4;
> -             max_ckdiv = 5;
> -     }
> +     struct at91_twi_pdata *pdata = dev->pdata;
> +     int offset = pdata->clk_offset;
> +     int max_ckdiv = pdata->clk_max_div;
>
>       div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
>                                      2 * twi_clk) - offset);
> @@ -209,6 +202,7 @@ static irqreturn_t atmel_twi_interrupt(int irq, void
> *dev_id)
>  static int at91_do_twi_transfer(struct at91_twi_dev *dev)
>  {
>       int ret;
> +     bool has_unre_flag = dev->pdata->has_unre_flag;
>
>       dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
>               (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev-
> >buf_len);
> @@ -250,7 +244,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev
> *dev)
>               dev_err(dev->dev, "overrun while reading\n");
>               return -EIO;
>       }
> -     if (dev->transfer_status & AT91_TWI_UNRE && dev->ip_id ==
> RM9200) {
> +     if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
>               dev_err(dev->dev, "underrun while writing\n");
>               return -EIO;
>       }
> @@ -323,6 +317,57 @@ static struct i2c_algorithm at91_twi_algorithm = {
>       .functionality  = at91_twi_func,
>  };
>
> +static struct at91_twi_pdata at91rm9200_config = {
> +     .clk_max_div = 5,
> +     .clk_offset = 3,
> +     .has_unre_flag = true,
> +};
> +
> +static struct at91_twi_pdata at91sam9261_config = {
> +     .clk_max_div = 5,
> +     .clk_offset = 4,
> +     .has_unre_flag = false,
> +};
> +
> +static struct at91_twi_pdata at91sam9260_config = {
> +     .clk_max_div = 7,
> +     .clk_offset = 4,
> +     .has_unre_flag = false,
> +};
> +
> +static struct at91_twi_pdata at91sam9g20_config = {
> +     .clk_max_div = 7,
> +     .clk_offset = 4,
> +     .has_unre_flag = false,
> +};
> +
> +static struct at91_twi_pdata at91sam9g10_config = {
> +     .clk_max_div = 7,
> +     .clk_offset = 4,
> +     .has_unre_flag = false,
> +};
> +
> +static const struct platform_device_id at91_twi_devtypes[] = {
> +     {
> +             .name = "at91rm9200_i2c",
> +             .driver_data = (unsigned long) &at91rm9200_config,
> +     }, {
> +             .name = "at91sam9261_i2c",
> +             .driver_data = (unsigned long) &at91sam9261_config,
> +     }, {
> +             .name = "at91sam9260_i2c",
> +             .driver_data = (unsigned long) &at91sam9260_config,
> +     }, {
> +             .name = "at91sam9g20_i2c",
> +             .driver_data = (unsigned long) &at91sam9g20_config,
> +     }, {
> +             .name = "at91sam9g10_i2c",
> +             .driver_data = (unsigned long) &at91sam9g10_config,
> +     }, {
> +             /* sentinel */
> +     }
> +};
> +
>  static int __devinit at91_twi_probe(struct platform_device *pdev)
>  {
>       struct at91_twi_dev *dev;
> @@ -339,6 +384,10 @@ static int __devinit at91_twi_probe(struct
> platform_device *pdev)
>       if (!mem)
>               return -ENODEV;
>
> +     dev->pdata = at91_twi_get_driver_data(pdev);
> +     if (!dev->pdata)
> +             return -ENODEV;
> +
>       dev->base = devm_request_and_ioremap(&pdev->dev, mem);
>       if (!dev->base)
>               return -EBUSY;
> @@ -354,9 +403,6 @@ static int __devinit at91_twi_probe(struct
> platform_device *pdev)
>               return rc;
>       }
>
> -     if (pdev->id_entry)
> -             dev->ip_id = pdev->id_entry->driver_data;
> -
>       platform_set_drvdata(pdev, dev);
>
>       dev->clk = devm_clk_get(dev->dev, NULL);
> @@ -432,6 +478,7 @@ static const struct dev_pm_ops at91_twi_pm = {
>  static struct platform_driver at91_twi_driver = {
>       .probe          = at91_twi_probe,
>       .remove         = __devexit_p(at91_twi_remove),
> +     .id_table       = at91_twi_devtypes,
>       .driver         = {
>               .name   = "at91_i2c",
>               .owner  = THIS_MODULE,
> --
> 1.7.11.3
Voss, Nikolaus Sept. 3, 2012, 6:16 a.m. UTC | #7
Jean-Christophe PLAGNIOL-VILLARD wrote on Saturday, September 01, 2012 11:11 AM:
> On 22:47 Fri 31 Aug     , Sylwester Nawrocki wrote:
> > On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
> > >>> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-
> at91/at91rm9200.c
> > >>> index f2112f9..0bc91e5 100644
> > >>> --- a/arch/arm/mach-at91/at91rm9200.c
> > >>> +++ b/arch/arm/mach-at91/at91rm9200.c
> > >>> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[]
> = {
> > >>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.0",&ssc0_clk),
> > >>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.1",&ssc1_clk),
> > >>>   	CLKDEV_CON_DEV_ID("pclk", "ssc.2",&ssc2_clk),
> > >>> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c",&twi_clk),
> > >>> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c",&twi_clk),
> > >> use i2c-xxx as on other drivers
> > >>
> > >> and I do not like to have platform_device_id
> > >
> > > Me, I like it and find this implementation very elegant.
> > >
> > >> as we need to touch the driver to add a new soc
> > >
> > > So what? We still keep the compatibility if the new SoC has it
> > > compatibility assured with previous revision: there is nothing to modify.
> >
> > I agree. The driver would need to be touched to support new SoC only if
> > the IP there have had some differences, which would have needed to be
> > resolved anyway.
> >
> > >> please use platform data
> >
> > Using platform data for the dt platforms would have been more
> troublesome,
> > wouldn't it ? I like Ludovic's approach which handles both: dt and non-dt
> > cases in uniform way from the driver's POV.
> no you will describe it via DT as done on all the other drivers
> >
> > > No, it does not have to be exposed to the user: these data are highly
> > > dependent on the actual hardware (IP revision in fact). So, no need to
> > > mess with platform data.
> no I really see no point on these list of platform_id it's does not look more
> nice just more huggly to have x names. This is at the end the same as
> passing
> platform data via soc info (add_xx or dtsi)
> 
> And here you just do the same as cpu_is via names.

That's what the names suggest, but it's not the case. What the DEV_IDs
stand for is actually an IP version which cannot be read out from the IP
directly. So the version information is coded at a place where it should
be available: in the SoC setup code (not in the driver code, as with the
cpu_is() variant). Example: the name at91sam9g10 does not stand for
the cpu type but for the IP class which is also used on g45 SoC. 

> 
> The driver need to read IP revision instead

That would be the easiest solution, but the IP does not know it's
version. The DEV_ID approach is a workaround for this limitation.

Regards,
Niko
Ludovic Desroches Sept. 3, 2012, 7:24 a.m. UTC | #8
Le 09/01/2012 11:10 AM, Jean-Christophe PLAGNIOL-VILLARD a écrit :
> On 22:47 Fri 31 Aug     , Sylwester Nawrocki wrote:
>> On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
>>>>> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
>>>>> index f2112f9..0bc91e5 100644
>>>>> --- a/arch/arm/mach-at91/at91rm9200.c
>>>>> +++ b/arch/arm/mach-at91/at91rm9200.c
>>>>> @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
>>>>>    	CLKDEV_CON_DEV_ID("pclk", "ssc.0",&ssc0_clk),
>>>>>    	CLKDEV_CON_DEV_ID("pclk", "ssc.1",&ssc1_clk),
>>>>>    	CLKDEV_CON_DEV_ID("pclk", "ssc.2",&ssc2_clk),
>>>>> -	CLKDEV_CON_DEV_ID(NULL, "at91_i2c",&twi_clk),
>>>>> +	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c",&twi_clk),
>>>> use i2c-xxx as on other drivers
>>>>
>>>> and I do not like to have platform_device_id
>>>
>>> Me, I like it and find this implementation very elegant.
>>>
>>>> as we need to touch the driver to add a new soc
>>>
>>> So what? We still keep the compatibility if the new SoC has it
>>> compatibility assured with previous revision: there is nothing to modify.
>>
>> I agree. The driver would need to be touched to support new SoC only if
>> the IP there have had some differences, which would have needed to be
>> resolved anyway.
>>
>>>> please use platform data
>>
>> Using platform data for the dt platforms would have been more troublesome,
>> wouldn't it ? I like Ludovic's approach which handles both: dt and non-dt
>> cases in uniform way from the driver's POV.
> no you will describe it via DT as done on all the other drivers
>>
>>> No, it does not have to be exposed to the user: these data are highly
>>> dependent on the actual hardware (IP revision in fact). So, no need to
>>> mess with platform data.
> no I really see no point on these list of platform_id it's does not look more
> nice just more huggly to have x names. This is at the end the same as passing
> platform data via soc info (add_xx or dtsi)
>
> And here you just do the same as cpu_is via names.
>
> The driver need to read IP revision instead
>

At the beginning it was planned to do this but:
- a new SoC, with a new IP version lead to update the driver also
- with the MCI driver which uses IP version, I have some cases where 
using the version was not enough, a SoC approach would be better. For 
instance, the IP version tells that we can use PDC feature but PDC is 
not connected.

> Best Regards,
> J.
>
>

Regards

Ludovic
Nicolas Ferre Sept. 3, 2012, 7:51 a.m. UTC | #9
On 09/03/2012 09:24 AM, ludovic.desroches :
> Le 09/01/2012 11:10 AM, Jean-Christophe PLAGNIOL-VILLARD a écrit :
>> On 22:47 Fri 31 Aug     , Sylwester Nawrocki wrote:
>>> On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
>>>>>> diff --git a/arch/arm/mach-at91/at91rm9200.c
>>>>>> b/arch/arm/mach-at91/at91rm9200.c
>>>>>> index f2112f9..0bc91e5 100644
>>>>>> --- a/arch/arm/mach-at91/at91rm9200.c
>>>>>> +++ b/arch/arm/mach-at91/at91rm9200.c
>>>>>> @@ -187,7 +187,7 @@ static struct clk_lookup
>>>>>> periph_clocks_lookups[] = {
>>>>>>        CLKDEV_CON_DEV_ID("pclk", "ssc.0",&ssc0_clk),
>>>>>>        CLKDEV_CON_DEV_ID("pclk", "ssc.1",&ssc1_clk),
>>>>>>        CLKDEV_CON_DEV_ID("pclk", "ssc.2",&ssc2_clk),
>>>>>> -    CLKDEV_CON_DEV_ID(NULL, "at91_i2c",&twi_clk),
>>>>>> +    CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c",&twi_clk),
>>>>> use i2c-xxx as on other drivers
>>>>>
>>>>> and I do not like to have platform_device_id
>>>>
>>>> Me, I like it and find this implementation very elegant.
>>>>
>>>>> as we need to touch the driver to add a new soc
>>>>
>>>> So what? We still keep the compatibility if the new SoC has it
>>>> compatibility assured with previous revision: there is nothing to
>>>> modify.
>>>
>>> I agree. The driver would need to be touched to support new SoC only if
>>> the IP there have had some differences, which would have needed to be
>>> resolved anyway.
>>>
>>>>> please use platform data
>>>
>>> Using platform data for the dt platforms would have been more
>>> troublesome,
>>> wouldn't it ? I like Ludovic's approach which handles both: dt and
>>> non-dt
>>> cases in uniform way from the driver's POV.
>> no you will describe it via DT as done on all the other drivers
>>>
>>>> No, it does not have to be exposed to the user: these data are highly
>>>> dependent on the actual hardware (IP revision in fact). So, no need to
>>>> mess with platform data.
>> no I really see no point on these list of platform_id it's does not
>> look more
>> nice just more huggly to have x names. This is at the end the same as
>> passing
>> platform data via soc info (add_xx or dtsi)
>>
>> And here you just do the same as cpu_is via names.
>>
>> The driver need to read IP revision instead
>>
> 
> At the beginning it was planned to do this but:
> - a new SoC, with a new IP version lead to update the driver also
> - with the MCI driver which uses IP version, I have some cases where
> using the version was not enough, a SoC approach would be better. For
> instance, the IP version tells that we can use PDC feature but PDC is
> not connected.

Absolutely. Nikolaus and you have summarized clearly the situation.

I think there is a consensus here.

So, we can move to a v2 patch series...

Bye,
Warner Losh Sept. 6, 2012, 4:54 a.m. UTC | #10
On Sep 2, 2012, at 11:21 AM, Sylwester Nawrocki wrote:

> On 09/01/2012 11:10 AM, Jean-Christophe PLAGNIOL-VILLARD wrote:
>> On 22:47 Fri 31 Aug     , Sylwester Nawrocki wrote:
>>> On 08/31/2012 04:51 PM, Nicolas Ferre wrote:
>>>> No, it does not have to be exposed to the user: these data are highly
>>>> dependent on the actual hardware (IP revision in fact). So, no need to
>>>> mess with platform data.
>> no I really see no point on these list of platform_id it's does not look more
>> nice just more huggly to have x names. This is at the end the same as passing
>> platform data via soc info (add_xx or dtsi)
>> 
>> And here you just do the same as cpu_is via names.
>> 
>> The driver need to read IP revision instead
> 
> OK, but wouldn't it be needed to resolve an IP revision at run time, e.g.
> with soc_is_*() anyway ? Having it set at each board doesn't look like an 
> optimal method either.

I'd much rather have a DT setting that gives the IP version in some manner, so I can key work arounds off of that.  Not so important for legacy devices where the Errata are well known (since you could do the same thing with some kind of property that's a boolean like for the AT91RM9200's mci controller that needs to swap bytes).  However, given my experience of bringing the FreeBSD at91rm9200 port to life and taking a product to market with it, I'd anticipate that the Errata will evolve over time, as will the need for workarounds.  Having an IP version helps deploy new drivers to the field without needing new DT files.

As you can tell, I'm not a big soc_is_* fan...

Warner
diff mbox

Patch

diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index f2112f9..0bc91e5 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -187,7 +187,7 @@  static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91rm9200_i2c", &twi_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 71e7387..cddfe02 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -494,18 +494,9 @@  static struct resource twi_resources[] = {
 	},
 };
 
-static const struct platform_device_id twi_ip_type = {
-	/*
-	 * driver_data is 1 for RM9200 compatible ip, see enum twi_ip_id in
-	 * drivers/i2c/busses/i2c-at91.c
-	 */
-	.driver_data	= 1,
-};
-
 static struct platform_device at91rm9200_twi_device = {
-	.name		= "at91_i2c",
+	.name		= "at91rm9200_i2c",
 	.id		= -1,
-	.id_entry	= &twi_ip_type,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
 };
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 57c79ee..5f86e71 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -211,7 +211,8 @@  static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9260_i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9g20_i2c", &twi_clk),
 	/* more usart lookup table for DT entries */
 	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
 	CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 7b9c2ba..ed02171 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -503,7 +503,6 @@  static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-	.name		= "at91_i2c",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
@@ -511,6 +510,13 @@  static struct platform_device at91sam9260_twi_device = {
 
 void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
 {
+	/* IP version is not the same on 9260 and g20 */
+	if (cpu_is_at91sam9g20()) {
+		at91sam9260_twi_device.name = "at91sam9g20_i2c";
+	} else {
+		at91sam9260_twi_device.name = "at91sam9260_i2c";
+	}
+
 	/* pins used for TWI interface */
 	at91_set_A_periph(AT91_PIN_PA23, 0);		/* TWD */
 	at91_set_multi_drive(AT91_PIN_PA23, 1);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 71ca1e0..0ccf63c 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -178,7 +178,8 @@  static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9261_i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9g10_i2c", &twi_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index d830724..c94495d 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -316,24 +316,21 @@  static struct resource twi_resources[] = {
 	},
 };
 
-static const struct platform_device_id twi_ip_type = {
-	/*
-	 * driver_data is 2 for SAM9261 compatible ip, see enum twi_ip_id in
-	 * drivers/i2c/busses/i2c-at91.c
-	 */
-	.driver_data	= 2,
-};
-
 static struct platform_device at91sam9261_twi_device = {
-	.name		= "at91_i2c",
 	.id		= -1,
-	.id_entry	= &twi_ip_type,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
 };
 
 void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
 {
+	/* IP version is not the same on 9261 and g10 */
+	if (cpu_is_at91sam9g10()) {
+		at91sam9261_twi_device.name = "at91sam9g10_i2c";
+	} else {
+		at91sam9261_twi_device.name = "at91sam9261_i2c";
+	}
+
 	/* pins used for TWI interface */
 	at91_set_A_periph(AT91_PIN_PA7, 0);		/* TWD */
 	at91_set_multi_drive(AT91_PIN_PA7, 1);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 2a08305..a4d760c 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -193,7 +193,7 @@  static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9260_i2c", &twi_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index eb6bbf8..7cff86c 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -574,7 +574,7 @@  static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9263_twi_device = {
-	.name		= "at91_i2c",
+	.name		= "at91sam9260_i2c",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index ddf3d37..15e62b9 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -237,8 +237,8 @@  static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9g10_i2c.0", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9g10_i2c.1", &twi1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index f001305..a61c7ec 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -653,7 +653,7 @@  static struct resource twi0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_twi0_device = {
-	.name		= "at91_i2c",
+	.name		= "at91sam9g10_i2c",
 	.id		= 0,
 	.resource	= twi0_resources,
 	.num_resources	= ARRAY_SIZE(twi0_resources),
@@ -673,7 +673,7 @@  static struct resource twi1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_twi1_device = {
-	.name		= "at91_i2c",
+	.name		= "at91sam9g10_i2c",
 	.id		= 1,
 	.resource	= twi1_resources,
 	.num_resources	= ARRAY_SIZE(twi1_resources),
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index bf79c1f..d708dfa 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -186,8 +186,8 @@  static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c.0", &twi0_clk),
-	CLKDEV_CON_DEV_ID(NULL, "at91_i2c.1", &twi1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9g20_i2c.0", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "at91sam9g20_i2c.1", &twi1_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index f09fff9..2df7411 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -346,7 +346,7 @@  static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9rl_twi_device = {
-	.name		= "at91_i2c",
+	.name		= "at91sam9g20_i2c",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 08aaee7..bcf9a5c 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -61,10 +61,10 @@ 
 #define	AT91_TWI_RHR		0x0030	/* Receive Holding Register */
 #define	AT91_TWI_THR		0x0034	/* Transmit Holding Register */
 
-enum twi_ip_id {
-	DEFAULT		= 0, /* default ip, no known limitations */
-	RM9200		= 1,
-	SAM9261		= 2,
+struct at91_twi_pdata {
+	unsigned	clk_max_div;
+	unsigned	clk_offset;
+	bool		has_unre_flag;
 };
 
 struct at91_twi_dev {
@@ -78,8 +78,8 @@  struct at91_twi_dev {
 	int			irq;
 	unsigned		transfer_status;
 	struct i2c_adapter	adapter;
-	enum twi_ip_id		ip_id;
 	unsigned		twi_cwgr_reg;
+	struct at91_twi_pdata	*pdata;
 };
 
 static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
@@ -114,16 +114,9 @@  static void at91_init_twi_bus(struct at91_twi_dev *dev)
 static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
 {
 	int ckdiv, cdiv, div;
-	int offset = 4;
-	int max_ckdiv = 7;
-
-	if (dev->ip_id == RM9200) {
-		offset = 3;
-		max_ckdiv = 5;
-	} else if (dev->ip_id == SAM9261) {
-		offset = 4;
-		max_ckdiv = 5;
-	}
+	struct at91_twi_pdata *pdata = dev->pdata;
+	int offset = pdata->clk_offset;
+	int max_ckdiv = pdata->clk_max_div;
 
 	div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
 				       2 * twi_clk) - offset);
@@ -209,6 +202,7 @@  static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 {
 	int ret;
+	bool has_unre_flag = dev->pdata->has_unre_flag;
 
 	dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
 		(dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len);
@@ -250,7 +244,7 @@  static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 		dev_err(dev->dev, "overrun while reading\n");
 		return -EIO;
 	}
-	if (dev->transfer_status & AT91_TWI_UNRE && dev->ip_id == RM9200) {
+	if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
 		dev_err(dev->dev, "underrun while writing\n");
 		return -EIO;
 	}
@@ -323,6 +317,57 @@  static struct i2c_algorithm at91_twi_algorithm = {
 	.functionality	= at91_twi_func,
 };
 
+static struct at91_twi_pdata at91rm9200_config = {
+	.clk_max_div = 5,
+	.clk_offset = 3,
+	.has_unre_flag = true,
+};
+
+static struct at91_twi_pdata at91sam9261_config = {
+	.clk_max_div = 5,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9260_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g20_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g10_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static const struct platform_device_id at91_twi_devtypes[] = {
+	{
+		.name = "at91rm9200_i2c",
+		.driver_data = (unsigned long) &at91rm9200_config,
+	}, {
+		.name = "at91sam9261_i2c",
+		.driver_data = (unsigned long) &at91sam9261_config,
+	}, {
+		.name = "at91sam9260_i2c",
+		.driver_data = (unsigned long) &at91sam9260_config,
+	}, {
+		.name = "at91sam9g20_i2c",
+		.driver_data = (unsigned long) &at91sam9g20_config,
+	}, {
+		.name = "at91sam9g10_i2c",
+		.driver_data = (unsigned long) &at91sam9g10_config,
+	}, {
+		/* sentinel */
+	}
+};
+
 static int __devinit at91_twi_probe(struct platform_device *pdev)
 {
 	struct at91_twi_dev *dev;
@@ -339,6 +384,10 @@  static int __devinit at91_twi_probe(struct platform_device *pdev)
 	if (!mem)
 		return -ENODEV;
 
+	dev->pdata = at91_twi_get_driver_data(pdev);
+	if (!dev->pdata)
+		return -ENODEV;
+
 	dev->base = devm_request_and_ioremap(&pdev->dev, mem);
 	if (!dev->base)
 		return -EBUSY;
@@ -354,9 +403,6 @@  static int __devinit at91_twi_probe(struct platform_device *pdev)
 		return rc;
 	}
 
-	if (pdev->id_entry)
-		dev->ip_id = pdev->id_entry->driver_data;
-
 	platform_set_drvdata(pdev, dev);
 
 	dev->clk = devm_clk_get(dev->dev, NULL);
@@ -432,6 +478,7 @@  static const struct dev_pm_ops at91_twi_pm = {
 static struct platform_driver at91_twi_driver = {
 	.probe		= at91_twi_probe,
 	.remove		= __devexit_p(at91_twi_remove),
+	.id_table	= at91_twi_devtypes,
 	.driver		= {
 		.name	= "at91_i2c",
 		.owner	= THIS_MODULE,