--- a/arch/arm/mach-at91/Kconfig 2011-10-24 18:07:29.000000000 -0400 +++ b/arch/arm/mach-at91/Kconfig 2011-11-09 21:44:03.923156549 -0500 @@ -497,6 +497,16 @@ config SAM9G20_SPI1 Select this to have silicon based SPI master on PB0, PB1, PB2 and chip select on PB3 or PC5. +if I2C_AT91 + +config SAM9G20_EXTRA_I2C + bool "extra I2C master on PA25,PA26" + help + Configures a gpio based I2C master on PA25(SDA) and PA26. + Assumes there is a silicon based I2C master on PA23,PA24. + +endif + endif choice --- a/arch/arm/mach-at91/board-foxg20.c 2011-10-25 00:07:29.000000000 +0200 +++ b/arch/arm/mach-at91/board-foxg20.c 2011-11-28 17:13:41.004946297 +0100 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -242,6 +243,81 @@ #endif +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_TWI, + .end = AT91SAM9260_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_TWI, + .end = AT91SAM9260_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +static void __init g20_add_device_i2c(struct i2c_board_info *devices, + int nr_devices) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91sam9260_twi_device); +} + +#elif defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PA23, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA24, + .scl_is_open_drain = 1, + /* Some I2C devices are limited to 100 kHz and i2c-gpio.h + * says "frequency is (500 / udelay) kHz" so 5 is best (and is + * used in i2c-gpio.c) + */ + .udelay = 5, /* ~100 kHz */ +}; + +static struct platform_device at91sam9260_twi_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +static void __init g20_add_device_i2c(struct i2c_board_info *devices, + int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PA23, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_GPIO_periph(AT91_PIN_PA24, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91sam9260_twi_device); +} + +#else +static void __init g20_add_device_i2c(struct i2c_board_info *devices, + int nr_devices) +{} +#endif + static struct i2c_board_info __initdata foxg20_i2c_devices[] = { { @@ -249,6 +325,47 @@ }, }; +#if defined(CONFIG_SAM9G20_EXTRA_I2C) || defined(CONFIG_SAM9G20_EXTRA_I2C_MODULE) + + +static struct i2c_gpio_platform_data i2c_pdata = { + .sda_pin = AT91_PIN_PA25, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA26, + .scl_is_open_drain = 1, + /* Some I2C devices are limited to 100 kHz and i2c-gpio.h + * says "frequency is (500 / udelay) kHz" so 5 is best (and is + * used in i2c-gpio.c) + */ + .udelay = 5, /* ~100 kHz */ +}; + +static struct platform_device sam9g20_extra_twi_device = { + .name = "i2c-gpio", + .id = 1, /* hooks to /dev/i2c-1 */ + .dev.platform_data = &i2c_pdata, +}; + +static void __init add_device_i2c_extra(struct i2c_board_info *devices, + int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PA25, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA25, 1); + + at91_set_GPIO_periph(AT91_PIN_PA26, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA26, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&sam9g20_extra_twi_device); +} + +static struct i2c_board_info __initdata foxg20_i2c_extra_devices[] = { + { + I2C_BOARD_INFO("xyzxyz", 0x1), + }, +}; +#endif + static void __init foxg20_board_init(void) { @@ -265,7 +382,11 @@ static void __init foxg20_board_init(voi /* MMC */ at91_add_device_mmc(0, &foxg20_mmc_data); /* I2C */ - at91_add_device_i2c(foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices)); + g20_add_device_i2c(foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices)); +#if defined(CONFIG_SAM9G20_EXTRA_I2C) || defined(CONFIG_SAM9G20_EXTRA_I2C_MODULE) + add_device_i2c_extra(foxg20_i2c_extra_devices, + ARRAY_SIZE(foxg20_i2c_extra_devices)); +#endif /* LEDs */ at91_gpio_leds(foxg20_leds, ARRAY_SIZE(foxg20_leds)); /* Push Buttons */