From patchwork Mon Mar 14 10:16:12 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lei Wen X-Patchwork-Id: 86713 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 88361B6F06 for ; Mon, 14 Mar 2011 21:16:51 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 046862814E; Mon, 14 Mar 2011 11:16:40 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5lzSpYLJpjXT; Mon, 14 Mar 2011 11:16:39 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A200128134; Mon, 14 Mar 2011 11:16:26 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 99A062812C for ; Mon, 14 Mar 2011 11:16:24 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1dRcxbuHSapw for ; Mon, 14 Mar 2011 11:16:23 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from dakia2.marvell.com (dakia2.marvell.com [65.219.4.35]) by theia.denx.de (Postfix) with ESMTPS id 0EE552812A for ; Mon, 14 Mar 2011 11:16:20 +0100 (CET) X-ASG-Debug-ID: 1300097778-082b97b70001-4l7tJC Received: from maili.marvell.com (maili.marvell.com [10.68.76.51]) by dakia2.marvell.com with ESMTP id WhP7UNVZWlEtBvQU; Mon, 14 Mar 2011 03:16:18 -0700 (PDT) X-Barracuda-Envelope-From: leiwen@marvell.com Received: from localhost (unknown [10.38.164.123]) by maili.marvell.com (Postfix) with ESMTP id EA0348A07B; Mon, 14 Mar 2011 03:16:17 -0700 (PDT) From: Lei Wen To: "u-boot@lists.denx.de" , Marek Vasut , Prafulla Wadaskar , Lei Wen X-ASG-Orig-Subj: [PATCH 2/8] pxa_i2c: use structure to replace the direclty define Date: Mon, 14 Mar 2011 03:16:12 -0700 X-ASG-Orig-Subj: [PATCH 2/8] pxa_i2c: use structure to replace the direclty define Message-Id: <1300097775-15602-2-git-send-email-leiwen@marvell.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1300097775-15602-1-git-send-email-leiwen@marvell.com> References: <1300097775-15602-1-git-send-email-leiwen@marvell.com> X-Barracuda-Connect: maili.marvell.com[10.68.76.51] X-Barracuda-Start-Time: 1300097778 X-Barracuda-URL: http://10.68.76.222:80/cgi-mod/mark.cgi X-Barracuda-Spam-Score: -1002.00 X-Barracuda-Spam-Status: No, SCORE=-1002.00 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=1000.0 Subject: [U-Boot] [PATCH 2/8] pxa_i2c: use structure to replace the direclty define X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Signed-off-by: Lei Wen --- arch/arm/cpu/pxa/cpu.c | 11 +++ arch/arm/include/asm/arch-pxa/pxa-regs.h | 56 ------------ board/innokom/innokom.c | 9 +-- drivers/i2c/pxa_i2c.c | 139 +++++++++++++++++++++--------- include/configs/innokom.h | 1 + include/configs/xm250.h | 1 + 6 files changed, 111 insertions(+), 106 deletions(-) diff --git a/arch/arm/cpu/pxa/cpu.c b/arch/arm/cpu/pxa/cpu.c index 7d49cbb..24b59e7 100644 --- a/arch/arm/cpu/pxa/cpu.c +++ b/arch/arm/cpu/pxa/cpu.c @@ -318,3 +318,14 @@ int arch_cpu_init(void) pxa_clock_setup(); return 0; } + +void i2c_clk_enable(void) +{ +#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 +} diff --git a/arch/arm/include/asm/arch-pxa/pxa-regs.h b/arch/arm/include/asm/arch-pxa/pxa-regs.h index 65a387f..109fdc0 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 e658c35..22de7e3 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/pxa_i2c.c b/drivers/i2c/pxa_i2c.c index 7aa49ae..0e37417 100644 --- a/drivers/i2c/pxa_i2c.c +++ b/drivers/i2c/pxa_i2c.c @@ -8,6 +8,9 @@ * (C) Copyright 2003 Pengutronix e.K. * Robert Schwebel * + * (C) Copyright 2011 Marvell Inc. + * Lei Wen + * * See file CREDITS for list of people who contributed to this * project. * @@ -30,8 +33,6 @@ * Murray.Jensen@cmst.csiro.au, 27-Jan-01. */ -/* FIXME: this file is PXA255 specific! What about other XScales? */ - #include #include @@ -42,9 +43,41 @@ * - I2C_PXA_SLAVE_ADDR */ -#include -#include #include +extern void i2c_clk_enable(void); + +/* ----- 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 */ /*#define DEBUG_I2C 1 /###* activate local debugging output */ #define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */ @@ -86,6 +119,21 @@ struct i2c_msg { u8 data; }; +struct pxa_i2c { + u32 ibmr; + u32 pad0; + u32 idbr; + u32 pad1; + u32 icr; + u32 pad2; + u32 isr; + u32 pad3; + u32 isar; +}; + +static struct pxa_i2c *base = (struct pxa_i2c *)CONFIG_PXA_I2C_REG; +#define PXAI2C_AND(reg, val) writel(readl(reg) & val, reg) +#define PXAI2C_OR(reg, val) writel(readl(reg) | val, reg) /** * i2c_pxa_reset: - reset the host controller @@ -94,21 +142,17 @@ struct i2c_msg { static void i2c_reset( void ) { - writel(readl(ICR) & ~ICR_IUE, ICR); /* disable unit */ - writel(readl(ICR) | ICR_UR, ICR); /* reset the unit */ + PXAI2C_AND(&base->icr, ~ICR_IUE); /* disable unit */ + PXAI2C_OR(&base->icr, ICR_UR); /* 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 */ + PXAI2C_AND(&base->icr, ~ICR_IUE); /* disable unit */ + + i2c_clk_enable(); + + writel(I2C_PXA_SLAVE_ADDR, &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 */ + PXAI2C_OR(&base->icr, ICR_IUE); /* enable unit */ udelay(100); } @@ -121,12 +165,14 @@ static void i2c_reset( void ) */ static int i2c_isr_set_cleared( unsigned long set_mask, unsigned long cleared_mask ) { - int timeout = 10000; + int timeout = 10000, isr; - while( ((ISR & set_mask)!=set_mask) || ((ISR & cleared_mask)!=0) ){ - udelay( 10 ); + do { + isr = readl(&base->isr); + udelay(10); if( timeout-- < 0 ) return 0; - } + } while (((isr & set_mask)!=set_mask) + || ((isr & cleared_mask)!=0)); return 1; } @@ -162,26 +208,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); + PXAI2C_AND(&base->icr, ~ICR_START); + PXAI2C_AND(&base->icr, ~ICR_STOP); + writel(msg->data, &base->idbr); if (msg->condition == I2C_COND_START) - writel(readl(ICR) | ICR_START, ICR); + PXAI2C_OR(&base->icr, ICR_START); if (msg->condition == I2C_COND_STOP) - writel(readl(ICR) | ICR_STOP, ICR); + PXAI2C_OR(&base->icr, ICR_STOP); if (msg->acknack == I2C_ACKNAK_SENDNAK) - writel(readl(ICR) | ICR_ACKNAK, ICR); + PXAI2C_OR(&base->icr, ICR_ACKNAK); if (msg->acknack == I2C_ACKNAK_SENDACK) - writel(readl(ICR) & ~ICR_ACKNAK, ICR); - writel(readl(ICR) & ~ICR_ALDIE, ICR); - writel(readl(ICR) | ICR_TB, ICR); + PXAI2C_AND(&base->icr, ~ICR_ACKNAK); + PXAI2C_AND(&base->icr, ~ICR_ALDIE); + PXAI2C_OR(&base->icr, ICR_TB); /* 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); + PXAI2C_OR(&base->isr, ISR_ITE); /* wait for ACK from slave */ if (msg->acknack == I2C_ACKNAK_WAITACK) @@ -196,27 +242,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); + PXAI2C_AND(&base->icr, ~ICR_START); + PXAI2C_AND(&base->icr, ~ICR_STOP); if (msg->condition == I2C_COND_START) - writel(readl(ICR) | ICR_START, ICR); + PXAI2C_OR(&base->icr, ICR_START); if (msg->condition == I2C_COND_STOP) - writel(readl(ICR) | ICR_STOP, ICR); + PXAI2C_OR(&base->icr, ICR_STOP); if (msg->acknack == I2C_ACKNAK_SENDNAK) - writel(readl(ICR) | ICR_ACKNAK, ICR); + PXAI2C_OR(&base->icr, ICR_ACKNAK); if (msg->acknack == I2C_ACKNAK_SENDACK) - writel(readl(ICR) & ~ICR_ACKNAK, ICR); - writel(readl(ICR) & ~ICR_ALDIE, ICR); - writel(readl(ICR) | ICR_TB, ICR); + PXAI2C_AND(&base->icr, ~ICR_ACKNAK); + PXAI2C_AND(&base->icr, ~ICR_ALDIE); + PXAI2C_OR(&base->icr, ICR_TB); /* 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); + PXAI2C_OR(&base->isr, ISR_IRF); break; @@ -266,10 +312,19 @@ i2c_transfer_finish: void i2c_init(int speed, int slaveaddr) { #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); + PXAI2C_AND(&base->icr, ~(ICR_SCLE | ICR_IUE)); + i2c_init_board(); + + writel(icr, &base->icr); #endif } diff --git a/include/configs/innokom.h b/include/configs/innokom.h index 57d633c..b459668 100644 --- a/include/configs/innokom.h +++ b/include/configs/innokom.h @@ -141,6 +141,7 @@ * I2C bus */ #define CONFIG_PXA_I2C 1 +#define CONFIG_PXA_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 7a7c539..8cdad23 100644 --- a/include/configs/xm250.h +++ b/include/configs/xm250.h @@ -62,6 +62,7 @@ * I2C bus */ #define CONFIG_PXA_I2C 1 +#define CONFIG_PXA_I2C_REG 0x40301680 #define CONFIG_HARD_I2C 1 #define CONFIG_SYS_I2C_SPEED 50000 #define CONFIG_SYS_I2C_SLAVE 0xfe