diff options
| -rw-r--r-- | arch/arm/cpu/pxa/cpu.c | 10 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-pxa/pxa-regs.h | 56 | ||||
| -rw-r--r-- | board/innokom/innokom.c | 9 | ||||
| -rw-r--r-- | drivers/i2c/mv_i2c.c | 141 | ||||
| -rw-r--r-- | drivers/i2c/mv_i2c.h | 83 | ||||
| -rw-r--r-- | include/configs/innokom.h | 1 | ||||
| -rw-r--r-- | include/configs/xm250.h | 1 | 
7 files changed, 164 insertions, 137 deletions
| diff --git a/arch/arm/cpu/pxa/cpu.c b/arch/arm/cpu/pxa/cpu.c index 7d49cbb4f..9970a4b45 100644 --- a/arch/arm/cpu/pxa/cpu.c +++ b/arch/arm/cpu/pxa/cpu.c @@ -318,3 +318,13 @@ int arch_cpu_init(void)  	pxa_clock_setup();  	return 0;  } + +void i2c_clk_enable(void) +{ +	/* set the global I2C clock on */ +#ifdef CONFIG_CPU_MONAHANS +	writel(readl(CKENB) | (CKENB_4_I2C), CKENB); +#else +	writel(readl(CKEN) | CKEN14_I2C, CKEN); +#endif +} diff --git a/arch/arm/include/asm/arch-pxa/pxa-regs.h b/arch/arm/include/asm/arch-pxa/pxa-regs.h index 65a387f9f..109fdc06a 100644 --- a/arch/arm/include/asm/arch-pxa/pxa-regs.h +++ b/arch/arm/include/asm/arch-pxa/pxa-regs.h @@ -456,62 +456,6 @@ typedef void		(*ExcpHndlr) (void) ;  		IrSR_XMITIR_IR_MODE)  /* - * I2C registers - */ -#define IBMR		0x40301680  /* I2C Bus Monitor Register - IBMR */ -#define IDBR		0x40301688  /* I2C Data Buffer Register - IDBR */ -#define ICR		0x40301690  /* I2C Control Register - ICR */ -#define ISR		0x40301698  /* I2C Status Register - ISR */ -#define ISAR		0x403016A0  /* I2C Slave Address Register - ISAR */ - -#ifdef CONFIG_CPU_MONAHANS -#define PWRIBMR		0x40f500C0  /* Power I2C Bus Monitor Register-IBMR */ -#define PWRIDBR		0x40f500C4  /* Power I2C Data Buffer Register-IDBR */ -#define PWRICR		0x40f500C8  /* Power I2C Control Register - ICR */ -#define PWRISR		0x40f500CC  /* Power I2C Status Register - ISR */ -#define PWRISAR		0x40f500D0  /* Power I2C Slave Address Register-ISAR */ -#else -#define PWRIBMR		0x40f00180  /* Power I2C Bus Monitor Register-IBMR */ -#define PWRIDBR		0x40f00188  /* Power I2C Data Buffer Register-IDBR */ -#define PWRICR		0x40f00190  /* Power I2C Control Register - ICR */ -#define PWRISR		0x40f00198  /* Power I2C Status Register - ISR */ -#define PWRISAR		0x40f001A0  /* Power I2C Slave Address Register-ISAR */ -#endif - -/* ----- 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 */ - -/*   * Serial Audio Controller   */  /* FIXME the audio defines collide w/ the SA1111 defines.  I don't like these diff --git a/board/innokom/innokom.c b/board/innokom/innokom.c index e658c3529..22de7e340 100644 --- a/board/innokom/innokom.c +++ b/board/innokom/innokom.c @@ -45,12 +45,7 @@ DECLARE_GLOBAL_DATA_PTR;   */  int i2c_init_board(void)  { -	int i, icr; - -	/* disable I2C controller first, otherwhise it thinks we want to    */ -	/* talk to the slave port...                                        */ -	icr = readl(ICR); -	writel(readl(ICR) & ~(ICR_SCLE | ICR_IUE), ICR); +	int i;  	/* set gpio pin low _before_ we change direction to output          */  	writel(GPIO_bit(70), GPCR(70)); @@ -63,8 +58,6 @@ int i2c_init_board(void)  		udelay(10);  	} -	writel(icr, ICR); -  	return 0;  } 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 diff --git a/include/configs/innokom.h b/include/configs/innokom.h index 0ea73c919..744d65c6e 100644 --- a/include/configs/innokom.h +++ b/include/configs/innokom.h @@ -141,6 +141,7 @@   * I2C bus   */  #define CONFIG_I2C_MV			1 +#define CONFIG_MV_I2C_REG		0x40301680  #define CONFIG_HARD_I2C			1  #define CONFIG_SYS_I2C_SPEED			50000  #define CONFIG_SYS_I2C_SLAVE			0xfe diff --git a/include/configs/xm250.h b/include/configs/xm250.h index b4b940a06..232baf361 100644 --- a/include/configs/xm250.h +++ b/include/configs/xm250.h @@ -62,6 +62,7 @@   * I2C bus   */  #define CONFIG_I2C_MV			1 +#define CONFIG_MV_I2C_REG		0x40301680  #define CONFIG_HARD_I2C			1  #define CONFIG_SYS_I2C_SPEED			50000  #define CONFIG_SYS_I2C_SLAVE			0xfe |