i2c: mv_i2c.c: cosmetic: Coding style cleanups
PATCH 1/7 i2c: mv_i2c.c: cosmetic: Coding style cleanups
Some mostly indentation coding style cleanups. Also, move this driver to use debug() for debug output.
--- drivers/i2c/mv_i2c.c | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-)
drivers/i2c/mv_i2c.c +34 -34
@@ -24,12 +24,6 @@#include <i2c.h> #include "mv_i2c.h" -#ifdef DEBUG_I2C -#define PRINTD (x) printf x -#else -#define PRINTD (x) -#endif -/* All transfers are described by this data structure */ struct mv_i2c_msg {u8 condition;
@@ -234,33 +228,39 @@ int i2c_transfer(struct mv_i2c_msg *msg)return 0 ; transfer_error_msg_empty: -PRINTD (("i2c_transfer: error: 'msg' is empty\n" )); - ret =-1 ; goto i2c_transfer_finish; +debug ("i2c_transfer: error: 'msg' is empty\n" ); + ret =-1 ; + goto i2c_transfer_finish; transfer_error_transmit_timeout: -PRINTD (("i2c_transfer: error: transmit timeout\n" )); - ret =-2 ; goto i2c_transfer_finish; +debug ("i2c_transfer: error: transmit timeout\n" ); + ret =-2 ; + goto i2c_transfer_finish; transfer_error_ack_missing: -PRINTD (("i2c_transfer: error: ACK missing\n" )); - ret =-3 ; goto i2c_transfer_finish; +debug ("i2c_transfer: error: ACK missing\n" ); + ret =-3 ; + goto i2c_transfer_finish; transfer_error_receive_timeout: -PRINTD (("i2c_transfer: error: receive timeout\n" )); - ret =-4 ; goto i2c_transfer_finish; +debug ("i2c_transfer: error: receive timeout\n" ); + ret =-4 ; + goto i2c_transfer_finish; transfer_error_illegal_param: -PRINTD (("i2c_transfer: error: illegal parameters\n" )); - ret =-5 ; goto i2c_transfer_finish; +debug ("i2c_transfer: error: illegal parameters\n" ); + ret =-5 ; + goto i2c_transfer_finish; transfer_error_bus_busy: -PRINTD (("i2c_transfer: error: bus is busy\n" )); - ret =-6 ; goto i2c_transfer_finish; +debug ("i2c_transfer: error: bus is busy\n" ); + ret =-6 ; + goto i2c_transfer_finish; i2c_transfer_finish: -PRINTD (("i2c_transfer: ISR: 0x%04x\n" ,readl (&base->isr))); -i2c_reset (); -return ret; +debug ("i2c_transfer: ISR: 0x%04x\n" ,readl (&base->isr)); +i2c_reset (); +return ret; }/* ------------------------------------------------------------------------ */
@@ -325,13 +325,13 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)struct mv_i2c_msg msg;u8 addr_bytes[3 ];/* lowest...highest byte of data address */ -PRINTD (("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " -"len=0x%02x)\n" , chip, addr, alen, len)); +debug ("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " +"len=0x%02x)\n" , chip, addr, alen, len);i2c_reset ();/* dummy chip address write */ -PRINTD (("i2c_read: dummy chip address write\n" )); +debug ("i2c_read: dummy chip address write\n" ); msg.condition =I2C_COND_START ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ;
@@ -350,7 +350,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) addr_bytes[2 ] = (u8)((addr >>16 ) &0x000000FF );while (--alen >=0 ) { -PRINTD (("i2c_read: send memory word address byte %1d\n" , alen)); +debug ("i2c_read: send memory word address byte %1d\n" , alen); msg.condition =I2C_COND_NORMAL ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ;
@@ -360,7 +360,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) }/* start read sequence */ -PRINTD (("i2c_read: start read sequence\n" )); +debug ("i2c_read: start read sequence\n" ); msg.condition =I2C_COND_START ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ;
@@ -385,8 +385,8 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)return -1 ; *buffer = msg.data; -PRINTD (("i2c_read: reading byte (0x%08x)=0x%02x\n" , - (unsigned int )buffer, *buffer)); +debug ("i2c_read: reading byte (0x%08x)=0x%02x\n" , + (unsigned int )buffer, *buffer); buffer++; }
@@ -413,13 +413,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)struct mv_i2c_msg msg;u8 addr_bytes[3 ];/* lowest...highest byte of data address */ -PRINTD (("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, " -"len=0x%02x)\n" , chip, addr, alen, len)); +debug ("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, " +"len=0x%02x)\n" , chip, addr, alen, len);i2c_reset ();/* chip address write */ -PRINTD (("i2c_write: chip address write\n" )); +debug ("i2c_write: chip address write\n" ); msg.condition =I2C_COND_START ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ;
@@ -437,7 +437,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) addr_bytes[2 ] = (u8)((addr >>16 ) &0x000000FF );while (--alen >=0 ) { -PRINTD (("i2c_write: send memory word address\n" )); +debug ("i2c_write: send memory word address\n" ); msg.condition =I2C_COND_NORMAL ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ;
@@ -448,8 +448,8 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)/* write bytes; send NACK at last byte */ while (len--) { -PRINTD (("i2c_write: writing byte (0x%08x)=0x%02x\n" , - (unsigned int )buffer, *buffer)); +debug ("i2c_write: writing byte (0x%08x)=0x%02x\n" , + (unsigned int )buffer, *buffer);if (len ==0 ) msg.condition =I2C_COND_STOP ;
Signature · 1 line
2.9.3
PATCH 2/7 i2c: mv_i2c.c: Remove CONFIG_HARD_I2C
CONFIG_HARD_I2C is not needed, lets remove it.
--- drivers/i2c/mv_i2c.c | 2 -- 1 file changed, 2 deletions(-)
drivers/i2c/mv_i2c.c +0 -2
@@ -20,7 +20,6 @@#include <common.h> #include <asm/io.h> -#ifdef CONFIG_HARD_I2C #include <i2c.h> #include "mv_i2c.h"
@@ -468,4 +467,3 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)return 0 ; } -#endif /* CONFIG_HARD_I2C */
Signature · 1 line
2.9.3
PATCH 3/7 i2c: mv_i2c.c: Prepare driver for DM conversion
In reply to Stefan RoeseTo prepare for the DM conversion, we add a layer of compatibility functions to be used by both the legacy and the DM functions.
--- drivers/i2c/mv_i2c.c | 267 +++++++++++++++++++++++++++------------------------ 1 file changed, 141 insertions(+), 126 deletions(-)
drivers/i2c/mv_i2c.c +141 -126
@@ -18,9 +18,8 @@*/ #include <common.h> -#include <asm/io.h> -#include <i2c.h> +#include <asm/io.h> #include "mv_i2c.h" /* All transfers are described by this data structure */
@@ -43,62 +42,11 @@ struct mv_i2c {u32 isar; }; -static struct mv_i2c *base; -static void i2c_board_init (struct mv_i2c *base) -{ -#ifdef CONFIG_SYS_I2C_INIT_BOARD -u32 icr; -/* -* call board specific i2c bus reset routine before accessing the -* environment, which might be in a chip on that bus. For details -* about this problem see doc/I2C_Edge_Conditions. -* -* disable I2C controller first, otherwhise it thinks we want to -* talk to the slave port... -*/ - icr =readl (&base->icr); -writel (readl (&base->icr) & ~(ICR_SCLE |ICR_IUE ), &base->icr); - -i2c_init_board (); - -writel (icr, &base->icr); -#endif -} - -#ifdef CONFIG_I2C_MULTI_BUS -static unsigned long i2c_regs[CONFIG_MV_I2C_NUM ] =CONFIG_MV_I2C_REG ; -static unsigned int bus_initialized[CONFIG_MV_I2C_NUM ]; -static unsigned int current_bus; - -int i2c_set_bus_num (unsigned int bus) -{ -if ((bus <0 ) || (bus >=CONFIG_MV_I2C_NUM )) { -printf ("Bad bus: %d\n" , bus); -return -1 ; - } - - base = (struct mv_i2c *)i2c_regs[bus]; - current_bus = bus; - -if (!bus_initialized[current_bus]) { -i2c_board_init (base); - bus_initialized[current_bus] =1 ; - } - -return 0 ; -} - -unsigned int i2c_get_bus_num (void ) -{ -return current_bus; -} -#endif -/* * i2c_reset: - reset the host controller * */ -static void i2c_reset (void ) +static void i2c_reset (struct mv_i2c *base) {writel (readl (&base->icr) & ~ICR_IUE , &base->icr);/* disable unit */ writel (readl (&base->icr) |ICR_UR , &base->icr);/* reset the unit */
@@ -120,7 +68,7 @@ static void i2c_reset(void)* * @return: 1 in case of success, 0 means timeout (no match within 10 ms). */ -static int i2c_isr_set_cleared (unsigned long set_mask, +static int i2c_isr_set_cleared (struct mv_i2c *base,unsigned long set_mask,unsigned long cleared_mask) {int timeout =1000 , isr;
@@ -150,7 +98,7 @@ static int i2c_isr_set_cleared(unsigned long set_mask,* -5: illegal parameters * -6: bus is busy and couldn't be aquired */ -int i2c_transfer (struct mv_i2c_msg *msg) +static int i2c_transfer (struct mv_i2c *base,struct mv_i2c_msg *msg) {int ret;
@@ -160,7 +108,7 @@ int i2c_transfer(struct mv_i2c_msg *msg)switch (msg->direction) {case I2C_WRITE :/* check if bus is not busy */ -if (!i2c_isr_set_cleared (0 ,ISR_IBB )) +if (!i2c_isr_set_cleared (base,0 ,ISR_IBB )) goto transfer_error_bus_busy;/* start transmission */
@@ -179,7 +127,7 @@ int i2c_transfer(struct mv_i2c_msg *msg)writel (readl (&base->icr) |ICR_TB , &base->icr);/* transmit register empty? */ -if (!i2c_isr_set_cleared (ISR_ITE ,0 )) +if (!i2c_isr_set_cleared (base,ISR_ITE ,0 )) goto transfer_error_transmit_timeout;/* clear 'transmit empty' state */
@@ -187,14 +135,14 @@ int i2c_transfer(struct mv_i2c_msg *msg)/* wait for ACK from slave */ if (msg->acknack ==I2C_ACKNAK_WAITACK ) -if (!i2c_isr_set_cleared (0 ,ISR_ACKNAK )) +if (!i2c_isr_set_cleared (base,0 ,ISR_ACKNAK )) goto transfer_error_ack_missing;break ;case I2C_READ :/* check if bus is not busy */ -if (!i2c_isr_set_cleared (0 ,ISR_IBB )) +if (!i2c_isr_set_cleared (base,0 ,ISR_IBB )) goto transfer_error_bus_busy;/* start receive */
@@ -212,7 +160,7 @@ int i2c_transfer(struct mv_i2c_msg *msg)writel (readl (&base->icr) |ICR_TB , &base->icr);/* receive register full? */ -if (!i2c_isr_set_cleared (ISR_IRF ,0 )) +if (!i2c_isr_set_cleared (base,ISR_IRF ,0 )) goto transfer_error_receive_timeout; msg->data =readl (&base->idbr);
@@ -258,68 +206,35 @@ transfer_error_bus_busy: i2c_transfer_finish:debug ("i2c_transfer: ISR: 0x%04x\n" ,readl (&base->isr)); -i2c_reset (); +i2c_reset (base);return ret; } -/* ------------------------------------------------------------------------ */ -/* API Functions */ -/* ------------------------------------------------------------------------ */ -void i2c_init (int speed,int slaveaddr) -{ -#ifdef CONFIG_I2C_MULTI_BUS - current_bus =0 ; - base = (struct mv_i2c *)i2c_regs[current_bus]; -#else - base = (struct mv_i2c *)CONFIG_MV_I2C_REG ; -#endif - -i2c_board_init (base); -} - -/* -* i2c_probe: - Test if a chip answers for a given i2c address -* -* @chip: address of the chip which is searched for -* @return: 0 if a chip was found, -1 otherwhise -*/ -int i2c_probe (uchar chip) +static int __i2c_probe_chip (struct mv_i2c *base,uchar chip) {struct mv_i2c_msg msg; -i2c_reset (); +i2c_reset (base); msg.condition =I2C_COND_START ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ; msg.data = (chip <<1 ) +1 ; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ; msg.condition =I2C_COND_STOP ; msg.acknack =I2C_ACKNAK_SENDNAK ; msg.direction =I2C_READ ; msg.data =0x00 ; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ;return 0 ; } -/* -* i2c_read: - Read multiple bytes from an i2c device -* -* The higher level routines take into account that this function is only -* called with len < page length of the device (see configuration file) -* -* @chip: address of the chip which is to be read -* @addr: i2c data address within the chip -* @alen: length of the i2c data address (1..2 bytes) -* @buffer: where to write the data -* @len: how much byte do we want to read -* @return: 0 in case of success -*/ -int i2c_read (uchar chip,uint addr,int alen,uchar *buffer,int len) +static int __i2c_read (struct mv_i2c *base,uchar chip,uint addr,int alen, +uchar *buffer,int len) {struct mv_i2c_msg msg;u8 addr_bytes[3 ];/* lowest...highest byte of data address */
@@ -327,7 +242,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)debug ("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " "len=0x%02x)\n" , chip, addr, alen, len); -i2c_reset (); +i2c_reset (base);/* dummy chip address write */ debug ("i2c_read: dummy chip address write\n" );
@@ -336,7 +251,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.direction =I2C_WRITE ; msg.data = (chip <<1 ); msg.data &=0xFE ; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ;/*
@@ -354,7 +269,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ; msg.data = addr_bytes[alen]; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ; }
@@ -365,7 +280,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.direction =I2C_WRITE ; msg.data = (chip <<1 ); msg.data |=0x01 ; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ;/* read bytes; send NACK@last byte */
@@ -380,7 +295,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.direction =I2C_READ ; msg.data =0x00 ; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ; *buffer = msg.data;
@@ -389,25 +304,13 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) buffer++; } -i2c_reset (); +i2c_reset (base);return 0 ; } -/* -* i2c_write: - Write multiple bytes to an i2c device -* -* The higher level routines take into account that this function is only -* called with len < page length of the device (see configuration file) -* -* @chip: address of the chip which is to be written -* @addr: i2c data address within the chip -* @alen: length of the i2c data address (1..2 bytes) -* @buffer: where to find the data to be written -* @len: how much byte do we want to read -* @return: 0 in case of success -*/ -int i2c_write (uchar chip,uint addr,int alen,uchar *buffer,int len) +static int __i2c_write (struct mv_i2c *base,uchar chip,uint addr,int alen, +uchar *buffer,int len) {struct mv_i2c_msg msg;u8 addr_bytes[3 ];/* lowest...highest byte of data address */
@@ -415,7 +318,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)debug ("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, " "len=0x%02x)\n" , chip, addr, alen, len); -i2c_reset (); +i2c_reset (base);/* chip address write */ debug ("i2c_write: chip address write\n" );
@@ -424,7 +327,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.direction =I2C_WRITE ; msg.data = (chip <<1 ); msg.data &=0xFE ; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ;/*
@@ -441,7 +344,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ; msg.data = addr_bytes[alen]; -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ; }
@@ -459,11 +362,123 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) msg.direction =I2C_WRITE ; msg.data = *(buffer++); -if (i2c_transfer (&msg)) +if (i2c_transfer (base, &msg))return -1 ; } -i2c_reset (); +i2c_reset (base);return 0 ; } + +static struct mv_i2c *base_glob; + +static void i2c_board_init (struct mv_i2c *base) +{ +#ifdef CONFIG_SYS_I2C_INIT_BOARD +u32 icr; +/* +* call board specific i2c bus reset routine before accessing the +* environment, which might be in a chip on that bus. For details +* about this problem see doc/I2C_Edge_Conditions. +* +* disable I2C controller first, otherwhise it thinks we want to +* talk to the slave port... +*/ + icr =readl (&base->icr); +writel (readl (&base->icr) & ~(ICR_SCLE |ICR_IUE ), &base->icr); + +i2c_init_board (); + +writel (icr, &base->icr); +#endif +} + +#ifdef CONFIG_I2C_MULTI_BUS +static unsigned long i2c_regs[CONFIG_MV_I2C_NUM ] =CONFIG_MV_I2C_REG ; +static unsigned int bus_initialized[CONFIG_MV_I2C_NUM ]; +static unsigned int current_bus; + +int i2c_set_bus_num (unsigned int bus) +{ +if ((bus <0 ) || (bus >=CONFIG_MV_I2C_NUM )) { +printf ("Bad bus: %d\n" , bus); +return -1 ; + } + + base_glob = (struct mv_i2c *)i2c_regs[bus]; + current_bus = bus; + +if (!bus_initialized[current_bus]) { +i2c_board_init (base_glob); + bus_initialized[current_bus] =1 ; + } + +return 0 ; +} + +unsigned int i2c_get_bus_num (void ) +{ +return current_bus; +} +#endif + +/* API Functions */ +void i2c_init (int speed,int slaveaddr) +{ +#ifdef CONFIG_I2C_MULTI_BUS + current_bus =0 ; + base_glob = (struct mv_i2c *)i2c_regs[current_bus]; +#else + base_glob = (struct mv_i2c *)CONFIG_MV_I2C_REG ; +#endif + +i2c_board_init (base_glob); +} + +/* +* i2c_probe: - Test if a chip answers for a given i2c address +* +* @chip: address of the chip which is searched for +* @return: 0 if a chip was found, -1 otherwhise +*/ +int i2c_probe (uchar chip) +{ +return __i2c_probe_chip (base_glob, chip); +} + +/* +* i2c_read: - Read multiple bytes from an i2c device +* +* The higher level routines take into account that this function is only +* called with len < page length of the device (see configuration file) +* +* @chip: address of the chip which is to be read +* @addr: i2c data address within the chip +* @alen: length of the i2c data address (1..2 bytes) +* @buffer: where to write the data +* @len: how much byte do we want to read +* @return: 0 in case of success +*/ +int i2c_read (uchar chip,uint addr,int alen,uchar *buffer,int len) +{ +return __i2c_read (base_glob, chip, addr, alen, buffer, len); +} + +/* +* i2c_write: - Write multiple bytes to an i2c device +* +* The higher level routines take into account that this function is only +* called with len < page length of the device (see configuration file) +* +* @chip: address of the chip which is to be written +* @addr: i2c data address within the chip +* @alen: length of the i2c data address (1..2 bytes) +* @buffer: where to find the data to be written +* @len: how much byte do we want to read +* @return: 0 in case of success +*/ +int i2c_write (uchar chip,uint addr,int alen,uchar *buffer,int len) +{ +return __i2c_write (base_glob, chip, addr, alen, buffer, len); +}
Signature · 1 line
2.9.3
PATCH 4/7 i2c: mv_i2c.c: Add DM support
In reply to Stefan Roese--- drivers/i2c/mv_i2c.c | 184 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 136 insertions(+), 48 deletions(-)
drivers/i2c/mv_i2c.c +136 -48
@@ -18,6 +18,7 @@*/ #include <common.h> +#include <dm.h> #include <i2c.h> #include <asm/io.h> #include "mv_i2c.h"
@@ -30,6 +31,16 @@ struct mv_i2c_msg {u8 data; }; +#ifdef CONFIG_ARMADA_3700 +/* Armada 3700 has no padding between the registers */ +struct mv_i2c { + u32 ibmr; + u32 idbr; + u32 icr; + u32 isr; + u32 isar; +}; +#else struct mv_i2c { u32 ibmr; u32 pad0;
@@ -41,6 +52,15 @@ struct mv_i2c {u32 pad3; u32 isar; }; +#endif + +/* +* Dummy implementation that can be overwritten by a board +* specific function +*/ +__weak void i2c_clk_enable (void ) +{ +}/* * i2c_reset: - reset the host controller
@@ -210,37 +230,13 @@ i2c_transfer_finish:return ret; } -static int __i2c_probe_chip (struct mv_i2c *base,uchar chip) -{ -struct mv_i2c_msg msg; - -i2c_reset (base); - - msg.condition =I2C_COND_START ; - msg.acknack =I2C_ACKNAK_WAITACK ; - msg.direction =I2C_WRITE ; - msg.data = (chip <<1 ) +1 ; -if (i2c_transfer (base, &msg)) -return -1 ; - - msg.condition =I2C_COND_STOP ; - msg.acknack =I2C_ACKNAK_SENDNAK ; - msg.direction =I2C_READ ; - msg.data =0x00 ; -if (i2c_transfer (base, &msg)) -return -1 ; - -return 0 ; -} - -static int __i2c_read (struct mv_i2c *base,uchar chip,uint addr,int alen, +static int __i2c_read (struct mv_i2c *base,uchar chip,u8 *addr,int alen,uchar *buffer,int len) {struct mv_i2c_msg msg; -u8 addr_bytes[3 ];/* lowest...highest byte of data address */ debug ("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " -"len=0x%02x)\n" , chip, addr, alen, len); +"len=0x%02x)\n" , chip, *addr, alen, len);i2c_reset (base);
@@ -258,17 +254,13 @@ static int __i2c_read(struct mv_i2c *base, uchar chip, uint addr, int alen,* send memory address bytes; * alen defines how much bytes we have to send. */ -/*addr &= ((1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)-1); */ - addr_bytes[0 ] = (u8)((addr >>0 ) &0x000000FF ); - addr_bytes[1 ] = (u8)((addr >>8 ) &0x000000FF ); - addr_bytes[2 ] = (u8)((addr >>16 ) &0x000000FF ); -while (--alen >=0 ) { -debug ("i2c_read: send memory word address byte %1d\n" , alen); +debug ("i2c_read: send address byte %02x (alen=%d)\n" , + *addr, alen); msg.condition =I2C_COND_NORMAL ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ; - msg.data = addr_bytes[alen]; + msg.data = *(addr++);if (i2c_transfer (base, &msg))return -1 ; }
@@ -299,8 +291,8 @@ static int __i2c_read(struct mv_i2c *base, uchar chip, uint addr, int alen,return -1 ; *buffer = msg.data; -debug ("i2c_read: reading byte (0x%08x)=0x%02x\n" , - (unsigned int )buffer, *buffer); +debug ("i2c_read: reading byte (%p)=0x%02x\n" , + buffer, *buffer); buffer++; }
@@ -309,14 +301,13 @@ static int __i2c_read(struct mv_i2c *base, uchar chip, uint addr, int alen,return 0 ; } -static int __i2c_write (struct mv_i2c *base,uchar chip,uint addr,int alen, +static int __i2c_write (struct mv_i2c *base,uchar chip,u8 *addr,int alen,uchar *buffer,int len) {struct mv_i2c_msg msg; -u8 addr_bytes[3 ];/* lowest...highest byte of data address */ debug ("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, " -"len=0x%02x)\n" , chip, addr, alen, len); +"len=0x%02x)\n" , chip, *addr, alen, len);i2c_reset (base);
@@ -334,24 +325,21 @@ static int __i2c_write(struct mv_i2c *base, uchar chip, uint addr, int alen,* send memory address bytes; * alen defines how much bytes we have to send. */ - addr_bytes[0 ] = (u8)((addr >>0 ) &0x000000FF ); - addr_bytes[1 ] = (u8)((addr >>8 ) &0x000000FF ); - addr_bytes[2 ] = (u8)((addr >>16 ) &0x000000FF ); -while (--alen >=0 ) { -debug ("i2c_write: send memory word address\n" ); +debug ("i2c_read: send address byte %02x (alen=%d)\n" , + *addr, alen); msg.condition =I2C_COND_NORMAL ; msg.acknack =I2C_ACKNAK_WAITACK ; msg.direction =I2C_WRITE ; - msg.data = addr_bytes[alen]; + msg.data = *(addr++);if (i2c_transfer (base, &msg))return -1 ; }/* write bytes; send NACK at last byte */ while (len--) { -debug ("i2c_write: writing byte (0x%08x)=0x%02x\n" , - (unsigned int )buffer, *buffer); +debug ("i2c_write: writing byte (%p)=0x%02x\n" , + buffer, *buffer);if (len ==0 ) msg.condition =I2C_COND_STOP ;
@@ -371,6 +359,8 @@ static int __i2c_write(struct mv_i2c *base, uchar chip, uint addr, int alen,return 0 ; } +#ifndef CONFIG_DM_I2C +static struct mv_i2c *base_glob;static void i2c_board_init (struct mv_i2c *base)
@@ -436,6 +426,29 @@ void i2c_init(int speed, int slaveaddr)i2c_board_init (base_glob); } +static int __i2c_probe_chip (struct mv_i2c *base,uchar chip) +{ +struct mv_i2c_msg msg; + +i2c_reset (base); + + msg.condition =I2C_COND_START ; + msg.acknack =I2C_ACKNAK_WAITACK ; + msg.direction =I2C_WRITE ; + msg.data = (chip <<1 ) +1 ; +if (i2c_transfer (base, &msg)) +return -1 ; + + msg.condition =I2C_COND_STOP ; + msg.acknack =I2C_ACKNAK_SENDNAK ; + msg.direction =I2C_READ ; + msg.data =0x00 ; +if (i2c_transfer (base, &msg)) +return -1 ; + +return 0 ; +} +/* * i2c_probe: - Test if a chip answers for a given i2c address *
@@ -462,7 +475,14 @@ int i2c_probe(uchar chip)*/ int i2c_read (uchar chip,uint addr,int alen,uchar *buffer,int len) { -return __i2c_read (base_glob, chip, addr, alen, buffer, len); +u8 addr_bytes[4 ]; + + addr_bytes[0 ] = (addr >>0 ) &0xFF ; + addr_bytes[1 ] = (addr >>8 ) &0xFF ; + addr_bytes[2 ] = (addr >>16 ) &0xFF ; + addr_bytes[3 ] = (addr >>24 ) &0xFF ; + +return __i2c_read (base_glob, chip, addr_bytes, alen, buffer, len); }/*
@@ -480,5 +500,73 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)*/ int i2c_write (uchar chip,uint addr,int alen,uchar *buffer,int len) { -return __i2c_write (base_glob, chip, addr, alen, buffer, len); +u8 addr_bytes[4 ]; + + addr_bytes[0 ] = (addr >>0 ) &0xFF ; + addr_bytes[1 ] = (addr >>8 ) &0xFF ; + addr_bytes[2 ] = (addr >>16 ) &0xFF ; + addr_bytes[3 ] = (addr >>24 ) &0xFF ; + +return __i2c_write (base_glob, chip, addr_bytes, alen, buffer, len); +} + +#else /* CONFIG_DM_I2C */ + +struct mv_i2c_priv { +struct mv_i2c *base; +}; + +static int mv_i2c_xfer (struct udevice *bus,struct i2c_msg *msg,int nmsgs) +{ +struct mv_i2c_priv *i2c =dev_get_priv (bus); +struct i2c_msg *dmsg, *omsg, dummy; + +memset (&dummy,0 ,sizeof (struct i2c_msg )); + +/* +* We expect either two messages (one with an offset and one with the +* actual data) or one message (just data or offset/data combined) +*/ +if (nmsgs >2 || nmsgs ==0 ) { +debug ("%s: Only one or two messages are supported." , __func__); +return -1 ; + } + + omsg = nmsgs ==1 ? &dummy : msg; + dmsg = nmsgs ==1 ? msg : msg +1 ; + +if (dmsg->flags &I2C_M_RD ) +return __i2c_read (i2c->base, dmsg->addr, omsg->buf, + omsg->len, dmsg->buf, dmsg->len); +else +return __i2c_write (i2c->base, dmsg->addr, omsg->buf, + omsg->len, dmsg->buf, dmsg->len); } + +static int mv_i2c_probe (struct udevice *bus) +{ +struct mv_i2c_priv *priv =dev_get_priv (bus); + + priv->base = (void *)dev_get_addr_ptr (bus); + +return 0 ; +} + +static const struct dm_i2c_ops mv_i2c_ops = { + .xfer = mv_i2c_xfer, +}; + +static const struct udevice_id mv_i2c_ids[] = { + { .compatible ="marvell,armada-3700-i2c" }, + { } +}; + +U_BOOT_DRIVER (i2c_mv) = { + .name ="i2c_mv" , + .id =UCLASS_I2C , + .of_match = mv_i2c_ids, + .probe = mv_i2c_probe, + .priv_auto_alloc_size =sizeof (struct mv_i2c_priv ), + .ops = &mv_i2c_ops, +}; +#endif /* CONFIG_DM_I2C */
Signature · 1 line
2.9.3
PATCH 5/7 i2c: mv_i2c.c: Enable runtime speed selection (standard vs fast mode)
In reply to Stefan RoeseThis patch adds runtime speed configuration to the mv_i2c driver. Currently standard (max 100kHz) and fast mode (max 400kHz) are supported.
--- drivers/i2c/mv_i2c.c | 30 +++++++++++++++++++++++++++++- drivers/i2c/mv_i2c.h | 15 +++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-)
drivers/i2c/mv_i2c.c +29 -1
@@ -68,6 +68,10 @@ __weak void i2c_clk_enable(void)*/ static void i2c_reset (struct mv_i2c *base) { +u32 icr_mode; + +/* Save bus mode (standard or fast speed) for later use */ + icr_mode =readl (&base->icr) &ICR_MODE_MASK ;writel (readl (&base->icr) & ~ICR_IUE , &base->icr);/* disable unit */ writel (readl (&base->icr) |ICR_UR , &base->icr);/* reset the unit */ udelay (100 );
@@ -76,7 +80,8 @@ static void i2c_reset(struct mv_i2c *base)i2c_clk_enable ();writel (CONFIG_SYS_I2C_SLAVE , &base->isar);/* set our slave address */ -writel (I2C_ICR_INIT , &base->icr);/* set control reg values */ +/* set control reg values */ +writel (I2C_ICR_INIT | icr_mode, &base->icr);writel (I2C_ISR_INIT , &base->isr);/* set clear interrupt bits */ writel (readl (&base->icr) |ICR_IUE , &base->icr);/* enable unit */ udelay (100 );
@@ -416,6 +421,8 @@ unsigned int i2c_get_bus_num(void)/* API Functions */ void i2c_init (int speed,int slaveaddr) { +u32 val; +#ifdef CONFIG_I2C_MULTI_BUS current_bus =0 ; base_glob = (struct mv_i2c *)i2c_regs[current_bus];
@@ -423,6 +430,12 @@ void i2c_init(int speed, int slaveaddr) base_glob = (struct mv_i2c *)CONFIG_MV_I2C_REG ;#endif +if (speed >100000 ) + val =ICR_FM ; +else + val =ICR_SM ; +clrsetbits_le32 (&base_glob->icr,ICR_MODE_MASK , val); +i2c_board_init (base_glob); }
@@ -543,6 +556,20 @@ static int mv_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) omsg->len, dmsg->buf, dmsg->len); } +static int mv_i2c_set_bus_speed (struct udevice *bus,unsigned int speed) +{ +struct mv_i2c_priv *priv =dev_get_priv (bus); +u32 val; + +if (speed >100000 ) + val =ICR_FM ; +else + val =ICR_SM ; +clrsetbits_le32 (&priv->base->icr,ICR_MODE_MASK , val); + +return 0 ; +} +static int mv_i2c_probe (struct udevice *bus) {struct mv_i2c_priv *priv =dev_get_priv (bus);
@@ -554,6 +581,7 @@ static int mv_i2c_probe(struct udevice *bus)static const struct dm_i2c_ops mv_i2c_ops = { .xfer = mv_i2c_xfer, + .set_bus_speed = mv_i2c_set_bus_speed, };static const struct udevice_id mv_i2c_ids[] = {
drivers/i2c/mv_i2c.h +9 -6
@@ -23,12 +23,7 @@ extern void i2c_clk_enable(void);#define I2C_READ 0#define I2C_WRITE 1 -#if (CONFIG_SYS_I2C_SPEED ==400000 ) -#define I2C_ICR_INIT (ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD \ - | ICR_SCLE) -#else #define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) -#endif #define I2C_ISR_INIT 0x7FF/* ----- Control register bits ---------------------------------------- */
@@ -48,7 +43,15 @@ extern void i2c_clk_enable(void);#define ICR_ALDIE 0x1000/* enable arbitration interrupt */ #define ICR_SADIE 0x2000/* slave address detected int enable */ #define ICR_UR 0x4000/* unit reset */ -#define ICR_FM 0x8000/* Fast Mode */ +#ifdef CONFIG_ARMADA_3700 +#define ICR_SM 0x00000/* Standard Mode */ +#define ICR_FM 0x10000/* Fast Mode */ +#define ICR_MODE_MASK 0x30000/* Mode mask */ +#else +#define ICR_SM 0x00000/* Standard Mode */ +#define ICR_FM 0x08000/* Fast Mode */ +#define ICR_MODE_MASK 0x18000/* Mode mask */ +#endif /* ----- Status register bits ----------------------------------------- */
Signature · 1 line
2.9.3
PATCH 6/7 i2c: mv_i2c.c: Validate read length in I2C command
In reply to Stefan RoeseFrom: jinghua <[email protected]>
The I2C bus will get stuck when reading 0 byte. So we add validation of the read length in i2c_read(). This issue only occurs on read operation.
--- drivers/i2c/mv_i2c.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/i2c/mv_i2c.c +5 -0
@@ -243,6 +243,11 @@ static int __i2c_read(struct mv_i2c *base, uchar chip, u8 *addr, int alen,debug ("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " "len=0x%02x)\n" , chip, *addr, alen, len); +if (len ==0 ) { +printf ("reading zero byte is invalid\n" ); +return -EINVAL ; + } +i2c_reset (base);/* dummy chip address write */
Signature · 1 line
2.9.3
PATCH 7/7 i2c: mvtwsi.c: Add support for Marvell Armada 7K/8K
In reply to Stefan RoeseBy adding the "marvell,mv78230-i2c" compatible property, we can enable this I2C driver to support these new ARM64 chips as well.
--- drivers/i2c/mvtwsi.c | 1 + 1 file changed, 1 insertion(+)
drivers/i2c/mvtwsi.c +1 -0
@@ -830,6 +830,7 @@ static const struct dm_i2c_ops mvtwsi_i2c_ops = {static const struct udevice_id mvtwsi_i2c_ids[] = { { .compatible ="marvell,mv64xxx-i2c" , }, + { .compatible ="marvell,mv78230-i2c" , }, {/* sentinel */ } };
Signature · 1 line
2.9.3