From 0db2bbdc04c7ba41861e686acb815fce5a227a01 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 13 Jun 2014 22:55:48 +0200 Subject: mvtwsi: convert to CONFIG_SYS_I2C framework Note this has only been tested on Allwinner sunxi devices (support for which gets introduced by a later patch). The kirkwood changes have been compile tested using the wireless_space board config, the orion5x changes have been compile tested using the edminiv2 board config. Signed-off-by: Hans de Goede Acked-by: Heiko Schocher --- drivers/i2c/mvtwsi.c | 70 ++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 38 deletions(-) (limited to 'drivers/i2c/mvtwsi.c') diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 5ba0e03862..c8b5425a01 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -220,11 +220,10 @@ static int twsi_stop(int status) /* * Reset controller. - * Called at end of i2c_init unsuccessful i2c transactions. * Controller reset also resets the baud rate and slave address, so - * re-establish them. + * they must be re-established afterwards. */ -static void twsi_reset(u8 baud_rate, u8 slave_address) +static void twsi_reset(struct i2c_adapter *adap) { /* ensure controller will be enabled by any twsi*() function */ twsi_control_flags = MVTWSI_CONTROL_TWSIEN; @@ -232,23 +231,17 @@ static void twsi_reset(u8 baud_rate, u8 slave_address) writel(0, &twsi->soft_reset); /* wait 2 ms -- this is what the Marvell LSP does */ udelay(20000); - /* set baud rate */ - writel(baud_rate, &twsi->baudrate); - /* set slave address even though we don't use it */ - writel(slave_address, &twsi->slave_address); - writel(0, &twsi->xtnd_slave_addr); - /* assert STOP but don't care for the result */ - (void) twsi_stop(0); } /* * I2C init called by cmd_i2c when doing 'i2c reset'. * Sets baud to the highest possible value not exceeding requested one. */ -void i2c_init(int requested_speed, int slaveadd) +static unsigned int twsi_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int requested_speed) { - int tmp_speed, highest_speed, n, m; - int baud = 0x44; /* baudrate at controller reset */ + unsigned int tmp_speed, highest_speed, n, m; + unsigned int baud = 0x44; /* baudrate at controller reset */ /* use actual speed to collect progressively higher values */ highest_speed = 0; @@ -263,8 +256,21 @@ void i2c_init(int requested_speed, int slaveadd) } } } + writel(baud, &twsi->baudrate); + return 0; +} + +static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +{ /* reset controller */ - twsi_reset(baud, slaveadd); + twsi_reset(adap); + /* set speed */ + twsi_i2c_set_bus_speed(adap, speed); + /* set slave address even though we don't use it */ + writel(slaveadd, &twsi->slave_address); + writel(0, &twsi->xtnd_slave_addr); + /* assert STOP but don't care for the result */ + (void) twsi_stop(0); } /* @@ -294,7 +300,7 @@ static int i2c_begin(int expected_start_status, u8 addr) * I2C probe called by cmd_i2c when doing 'i2c probe'. * Begin read, nak data byte, end. */ -int i2c_probe(uchar chip) +static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip) { u8 dummy_byte; int status; @@ -320,12 +326,13 @@ int i2c_probe(uchar chip) * cmd_eeprom, so we have to choose here, and for the moment that'll be * a repeated start without a preceding stop. */ -int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) +static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *data, int length) { int status; /* begin i2c write to send the address bytes */ - status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); + status = i2c_begin(MVTWSI_STATUS_START, (chip << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), @@ -333,7 +340,7 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) /* begin i2c read to receive eeprom data bytes */ if (status == 0) status = i2c_begin( - MVTWSI_STATUS_REPEATED_START, (dev << 1) | 1); + MVTWSI_STATUS_REPEATED_START, (chip << 1) | 1); /* prepare ACK if at least one byte must be received */ if (length > 0) twsi_control_flags |= MVTWSI_CONTROL_ACK; @@ -355,12 +362,13 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c * Begin write, send address byte(s), send data bytes, end. */ -int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) +static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *data, int length) { int status; /* begin i2c write to send the eeprom adress bytes then data bytes */ - status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); + status = i2c_begin(MVTWSI_STATUS_START, (chip << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), @@ -374,21 +382,7 @@ int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) return status; } -/* - * Bus set routine: we only support bus 0. - */ -int i2c_set_bus_num(unsigned int bus) -{ - if (bus > 0) { - return -1; - } - return 0; -} - -/* - * Bus get routine: hard-return bus 0. - */ -unsigned int i2c_get_bus_num(void) -{ - return 0; -} +U_BOOT_I2C_ADAP_COMPLETE(twsi0, twsi_i2c_init, twsi_i2c_probe, + twsi_i2c_read, twsi_i2c_write, + twsi_i2c_set_bus_speed, + CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0) -- cgit v1.2.3 From 6620377e4b8be3c232c59d673efcd673c30bc69f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 13 Jun 2014 22:55:49 +0200 Subject: sunxi: Add i2c support Add support for the i2c controller found on all Allwinner sunxi SoCs, this is the same controller as found on the Marvell orion5x and kirkwood SoC families, with a slightly different register layout, so this patch uses the existing mvtwsi code. Signed-off-by: Hans de Goede Acked-by: Ian Campbell Acked-By: Prafulla Wadaskar Acked-by: Heiko Schocher [ ijc -- updated u-boot-spl-fel.lds ] --- arch/arm/cpu/armv7/sunxi/board.c | 6 ++++++ arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds | 5 +++++ arch/arm/cpu/armv7/sunxi/u-boot-spl.lds | 5 +++++ arch/arm/include/asm/arch-sunxi/i2c.h | 15 +++++++++++++++ board/sunxi/board.c | 7 +++++++ drivers/i2c/mvtwsi.c | 18 ++++++++++++++++++ include/configs/sunxi-common.h | 8 ++++++++ 7 files changed, 64 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/i2c.h (limited to 'drivers/i2c/mvtwsi.c') diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 538ffa70a3..701f9195e2 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -93,11 +94,16 @@ void s_init(void) clock_init(); timer_init(); gpio_init(); + i2c_init_board(); #ifdef CONFIG_SPL_BUILD gd = &gdata; preloader_console_init(); +#ifdef CONFIG_SPL_I2C_SUPPORT + /* Needed early by sunxi_board_init if PMU is enabled */ + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif sunxi_board_init(); #endif } diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds index 364e35c32f..928b7c19e0 100644 --- a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds +++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds @@ -26,6 +26,11 @@ SECTIONS *(.data*) } + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + . = ALIGN(4); . = .; diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds index c1ae227f06..53f0cbd2b7 100644 --- a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds +++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds @@ -38,6 +38,11 @@ SECTIONS . = ALIGN(4); .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .sram + . = ALIGN(4); __image_copy_end = .; _end = .; diff --git a/arch/arm/include/asm/arch-sunxi/i2c.h b/arch/arm/include/asm/arch-sunxi/i2c.h new file mode 100644 index 0000000000..dc5406b213 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/i2c.h @@ -0,0 +1,15 @@ +/* + * Copyright 2014 - Hans de Goede + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _SUNXI_I2C_H_ +#define _SUNXI_I2C_H_ + +#include + +#define CONFIG_I2C_MVTWSI_BASE SUNXI_TWI0_BASE +/* This is abp0-clk on sun4i/5i/7i / abp1-clk on sun6i/sun8i which is 24MHz */ +#define CONFIG_SYS_TCLK 24000000 + +#endif diff --git a/board/sunxi/board.c b/board/sunxi/board.c index b05d0b9b18..543b8098e9 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -106,6 +106,13 @@ int board_mmc_init(bd_t *bis) } #endif +void i2c_init_board(void) +{ + sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUNXI_GPB0_TWI0); + sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUNXI_GPB0_TWI0); + clock_twi_onoff(0, 1); +} + #ifdef CONFIG_SPL_BUILD void sunxi_board_init(void) { diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index c8b5425a01..ab3ffa0fc1 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -22,6 +22,8 @@ #include #elif defined(CONFIG_KIRKWOOD) #include +#elif defined(CONFIG_SUNXI) +#include #else #error Driver mvtwsi not supported by SoC or board #endif @@ -30,6 +32,20 @@ * TWSI register structure */ +#ifdef CONFIG_SUNXI + +struct mvtwsi_registers { + u32 slave_address; + u32 xtnd_slave_addr; + u32 data; + u32 control; + u32 status; + u32 baudrate; + u32 soft_reset; +}; + +#else + struct mvtwsi_registers { u32 slave_address; u32 data; @@ -43,6 +59,8 @@ struct mvtwsi_registers { u32 soft_reset; }; +#endif + /* * Control register fields */ diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 3f04890526..42b0d2e51b 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -161,6 +161,14 @@ #undef CONFIG_CMD_NET #undef CONFIG_CMD_NFS +/* I2C */ +#define CONFIG_SPL_I2C_SUPPORT +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MVTWSI +#define CONFIG_SYS_I2C_SPEED 400000 +#define CONFIG_SYS_I2C_SLAVE 0x7f +#define CONFIG_CMD_I2C + #ifndef CONFIG_CONS_INDEX #define CONFIG_CONS_INDEX 1 /* UART0 */ #endif -- cgit v1.2.3