diff options
| author | Lei Wen <[leiwen@marvell.com]> | 2011-04-13 23:48:31 +0530 | 
|---|---|---|
| committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2011-04-27 19:38:08 +0200 | 
| commit | 3df619ec2cae3305c20b808c4d49cfed66c1cf9b (patch) | |
| tree | 28492296d69892e06b869f0bab4cafdfda38632a /drivers | |
| parent | 879de1275abf66fbb08e601f12d6ac5a888255e1 (diff) | |
| download | olio-uboot-2014.01-3df619ec2cae3305c20b808c4d49cfed66c1cf9b.tar.xz olio-uboot-2014.01-3df619ec2cae3305c20b808c4d49cfed66c1cf9b.zip | |
mv_i2c: use structure to replace the direclty define
Add i2c_clk_enable in the cpu specific code, since previous platform it,
while new platform don't need. In the pantheon and armada100 platform,
this function is defined as NULL one.
Acked-by: Heiko Schocher <hs@denx.de>
Acked-by: Prafulla Wadaskar <prafulla@marvell.com>
Signed-off-by: Lei Wen <leiwen@marvell.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/i2c/mv_i2c.c | 141 | ||||
| -rw-r--r-- | drivers/i2c/mv_i2c.h | 83 | 
2 files changed, 151 insertions, 73 deletions
| diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c index 562b95022..7ea66d481 100644 --- a/drivers/i2c/mv_i2c.c +++ b/drivers/i2c/mv_i2c.c @@ -8,6 +8,9 @@   * (C) Copyright 2003 Pengutronix e.K.   * Robert Schwebel <r.schwebel@pengutronix.de>   * + * (C) Copyright 2011 Marvell Inc. + * Lei Wen <leiwen@marvell.com> + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -34,24 +37,8 @@  #include <asm/io.h>  #ifdef CONFIG_HARD_I2C - -/* - *	- CONFIG_SYS_I2C_SPEED - *	- I2C_PXA_SLAVE_ADDR - */ - -#include <asm/arch/hardware.h> -#include <asm/arch/pxa-regs.h>  #include <i2c.h> - -#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 +#include "mv_i2c.h"  #ifdef DEBUG_I2C  #define PRINTD(x) printf x @@ -59,20 +46,6 @@  #define PRINTD(x)  #endif -/* Shall the current transfer have a start/stop condition? */ -#define I2C_COND_NORMAL		0 -#define I2C_COND_START		1 -#define I2C_COND_STOP		2 - -/* Shall the current transfer be ack/nacked or being waited for it? */ -#define I2C_ACKNAK_WAITACK	1 -#define I2C_ACKNAK_SENDACK	2 -#define I2C_ACKNAK_SENDNAK	4 - -/* Specify who shall transfer the data (master or slave) */ -#define I2C_READ		0 -#define I2C_WRITE		1 -  /* All transfers are described by this data structure */  struct i2c_msg {  	u8 condition; @@ -81,27 +54,37 @@ struct i2c_msg {  	u8 data;  }; +struct mv_i2c { +	u32 ibmr; +	u32 pad0; +	u32 idbr; +	u32 pad1; +	u32 icr; +	u32 pad2; +	u32 isr; +	u32 pad3; +	u32 isar; +}; + +static struct mv_i2c *base = (struct mv_i2c *)CONFIG_MV_I2C_REG; +  /* - * i2c_pxa_reset: - reset the host controller + * i2c_reset: - reset the host controller   *   */  static void i2c_reset(void)  { -	writel(readl(ICR) & ~ICR_IUE, ICR);	/* disable unit */ -	writel(readl(ICR) | ICR_UR, ICR);	/* reset the unit */ +	writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */ +	writel(readl(&base->icr) | ICR_UR, &base->icr);	  /* reset the unit */  	udelay(100); -	writel(readl(ICR) & ~ICR_IUE, ICR);	/* disable unit */ -#ifdef CONFIG_CPU_MONAHANS -	/* | CKENB_1_PWM1 | CKENB_0_PWM0); */ -	writel(readl(CKENB) | (CKENB_4_I2C), CKENB); -#else /* CONFIG_CPU_MONAHANS */ -	/* set the global I2C clock on */ -	writel(readl(CKEN) | CKEN14_I2C, CKEN); -#endif -	writel(I2C_PXA_SLAVE_ADDR, ISAR);	/* set our slave address */ -	writel(I2C_ICR_INIT, ICR);		/* set control reg values */ -	writel(I2C_ISR_INIT, ISR);		/* set clear interrupt bits */ -	writel(readl(ICR) | ICR_IUE, ICR);	/* enable unit */ +	writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */ + +	i2c_clk_enable(); + +	writel(CONFIG_SYS_I2C_SLAVE, &base->isar); /* set our slave address */ +	writel(I2C_ICR_INIT, &base->icr); /* set control reg values */ +	writel(I2C_ISR_INIT, &base->isr); /* set clear interrupt bits */ +	writel(readl(&base->icr) | ICR_IUE, &base->icr); /* enable unit */  	udelay(100);  } @@ -114,13 +97,15 @@ static void i2c_reset(void)  static int i2c_isr_set_cleared(unsigned long set_mask,  			       unsigned long cleared_mask)  { -	int timeout = 1000; +	int timeout = 1000, isr; -	while (((ISR & set_mask) != set_mask) || ((ISR & cleared_mask) != 0)) { +	do { +		isr = readl(&base->isr);  		udelay(10);  		if (timeout-- < 0)  			return 0; -	} +	} while (((isr & set_mask) != set_mask) +		|| ((isr & cleared_mask) != 0));  	return 1;  } @@ -153,26 +138,26 @@ int i2c_transfer(struct i2c_msg *msg)  			goto transfer_error_bus_busy;  		/* start transmission */ -		writel(readl(ICR) & ~ICR_START, ICR); -		writel(readl(ICR) & ~ICR_STOP, ICR); -		writel(msg->data, IDBR); +		writel(readl(&base->icr) & ~ICR_START, &base->icr); +		writel(readl(&base->icr) & ~ICR_STOP, &base->icr); +		writel(msg->data, &base->idbr);  		if (msg->condition == I2C_COND_START) -			writel(readl(ICR) | ICR_START, ICR); +			writel(readl(&base->icr) | ICR_START, &base->icr);  		if (msg->condition == I2C_COND_STOP) -			writel(readl(ICR) | ICR_STOP, ICR); +			writel(readl(&base->icr) | ICR_STOP, &base->icr);  		if (msg->acknack == I2C_ACKNAK_SENDNAK) -			writel(readl(ICR) | ICR_ACKNAK, ICR); +			writel(readl(&base->icr) | ICR_ACKNAK, &base->icr);  		if (msg->acknack == I2C_ACKNAK_SENDACK) -			writel(readl(ICR) & ~ICR_ACKNAK, ICR); -		writel(readl(ICR) & ~ICR_ALDIE, ICR); -		writel(readl(ICR) | ICR_TB, ICR); +			writel(readl(&base->icr) & ~ICR_ACKNAK, &base->icr); +		writel(readl(&base->icr) & ~ICR_ALDIE, &base->icr); +		writel(readl(&base->icr) | ICR_TB, &base->icr);  		/* transmit register empty? */  		if (!i2c_isr_set_cleared(ISR_ITE, 0))  			goto transfer_error_transmit_timeout;  		/* clear 'transmit empty' state */ -		writel(readl(ISR) | ISR_ITE, ISR); +		writel(readl(&base->isr) | ISR_ITE, &base->isr);  		/* wait for ACK from slave */  		if (msg->acknack == I2C_ACKNAK_WAITACK) @@ -187,28 +172,27 @@ int i2c_transfer(struct i2c_msg *msg)  			goto transfer_error_bus_busy;  		/* start receive */ -		writel(readl(ICR) & ~ICR_START, ICR); -		writel(readl(ICR) & ~ICR_STOP, ICR); +		writel(readl(&base->icr) & ~ICR_START, &base->icr); +		writel(readl(&base->icr) & ~ICR_STOP, &base->icr);  		if (msg->condition == I2C_COND_START) -			writel(readl(ICR) | ICR_START, ICR); +			writel(readl(&base->icr) | ICR_START, &base->icr);  		if (msg->condition == I2C_COND_STOP) -			writel(readl(ICR) | ICR_STOP, ICR); +			writel(readl(&base->icr) | ICR_STOP, &base->icr);  		if (msg->acknack == I2C_ACKNAK_SENDNAK) -			writel(readl(ICR) | ICR_ACKNAK, ICR); +			writel(readl(&base->icr) | ICR_ACKNAK, &base->icr);  		if (msg->acknack == I2C_ACKNAK_SENDACK) -			writel(readl(ICR) & ~ICR_ACKNAK, ICR); -		writel(readl(ICR) & ~ICR_ALDIE, ICR); -		writel(readl(ICR) | ICR_TB, ICR); +			writel(readl(&base->icr) & ~ICR_ACKNAK, &base->icr); +		writel(readl(&base->icr) & ~ICR_ALDIE, &base->icr); +		writel(readl(&base->icr) | ICR_TB, &base->icr);  		/* receive register full? */  		if (!i2c_isr_set_cleared(ISR_IRF, 0))  			goto transfer_error_receive_timeout; -		msg->data = readl(IDBR); +		msg->data = readl(&base->idbr);  		/* clear 'receive empty' state */ -		writel(readl(ISR) | ISR_IRF, ISR); - +		writel(readl(&base->isr) | ISR_IRF, &base->isr);  		break;  	default:  		goto transfer_error_illegal_param; @@ -252,10 +236,21 @@ i2c_transfer_finish:  void i2c_init(int speed, int slaveaddr)  {  #ifdef CONFIG_SYS_I2C_INIT_BOARD -	/* 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.                  */ +	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  } diff --git a/drivers/i2c/mv_i2c.h b/drivers/i2c/mv_i2c.h new file mode 100644 index 000000000..41af0d9bd --- /dev/null +++ b/drivers/i2c/mv_i2c.h @@ -0,0 +1,83 @@ +/* + * (C) Copyright 2011 + * Marvell Inc, <www.marvell.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _MV_I2C_H_ +#define _MV_I2C_H_ +extern void i2c_clk_enable(void); + +/* Shall the current transfer have a start/stop condition? */ +#define I2C_COND_NORMAL		0 +#define I2C_COND_START		1 +#define I2C_COND_STOP		2 + +/* Shall the current transfer be ack/nacked or being waited for it? */ +#define I2C_ACKNAK_WAITACK	1 +#define I2C_ACKNAK_SENDACK	2 +#define I2C_ACKNAK_SENDNAK	4 + +/* Specify who shall transfer the data (master or slave) */ +#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 ---------------------------------------- */ + +#define ICR_START	0x1		/* start bit */ +#define ICR_STOP	0x2		/* stop bit */ +#define ICR_ACKNAK	0x4		/* send ACK(0) or NAK(1) */ +#define ICR_TB		0x8		/* transfer byte bit */ +#define ICR_MA		0x10		/* master abort */ +#define ICR_SCLE	0x20		/* master clock enable, mona SCLEA */ +#define ICR_IUE		0x40		/* unit enable */ +#define ICR_GCD		0x80		/* general call disable */ +#define ICR_ITEIE	0x100		/* enable tx interrupts */ +#define ICR_IRFIE	0x200		/* enable rx interrupts, mona: DRFIE */ +#define ICR_BEIE	0x400		/* enable bus error ints */ +#define ICR_SSDIE	0x800		/* slave STOP detected int enable */ +#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 */ + +/* ----- Status register bits ----------------------------------------- */ + +#define ISR_RWM		0x1		/* read/write mode */ +#define ISR_ACKNAK	0x2		/* ack/nak status */ +#define ISR_UB		0x4		/* unit busy */ +#define ISR_IBB		0x8		/* bus busy */ +#define ISR_SSD		0x10		/* slave stop detected */ +#define ISR_ALD		0x20		/* arbitration loss detected */ +#define ISR_ITE		0x40		/* tx buffer empty */ +#define ISR_IRF		0x80		/* rx buffer full */ +#define ISR_GCAD	0x100		/* general call address detected */ +#define ISR_SAD		0x200		/* slave address detected */ +#define ISR_BED		0x400		/* bus error no ACK/NAK */ + +#endif |