From patchwork Tue Jan 28 05:53:36 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sonic Zhang X-Patchwork-Id: 314587 X-Patchwork-Delegate: hs@denx.de 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 7E5CF2C00A2 for ; Tue, 28 Jan 2014 17:05:40 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 744814B174; Tue, 28 Jan 2014 07:05:38 +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 a82OPVNajnC3; Tue, 28 Jan 2014 07:05:38 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id AE3B64B17B; Tue, 28 Jan 2014 07:05:32 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 332634B0ED for ; Tue, 28 Jan 2014 07:05:22 +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 2KcKKrahEZnS for ; Tue, 28 Jan 2014 07:05:16 +0100 (CET) X-Greylist: delayed 907 seconds by postgrey-1.27 at theia; Tue, 28 Jan 2014 07:05:10 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 va3outboundpool.messaging.microsoft.com (va3ehsobe006.messaging.microsoft.com [216.32.180.16]) by theia.denx.de (Postfix) with ESMTPS id 1AB724B143 for ; Tue, 28 Jan 2014 07:05:10 +0100 (CET) Received: from mail26-va3-R.bigfish.com (10.7.14.245) by VA3EHSOBE009.bigfish.com (10.7.40.29) with Microsoft SMTP Server id 14.1.225.22; Tue, 28 Jan 2014 05:50:00 +0000 Received: from mail26-va3 (localhost [127.0.0.1]) by mail26-va3-R.bigfish.com (Postfix) with ESMTP id A683A30011E; Tue, 28 Jan 2014 05:50:00 +0000 (UTC) X-Forefront-Antispam-Report: CIP:137.71.25.57; KIP:(null); UIP:(null); IPV:NLI; H:nwd2mta2.analog.com; RD:nwd2mail11.analog.com; EFVD:NLI X-SpamScore: 1 X-BigFish: VS1(zzzz1f42h2148h1ee6h1ce5h1fdah201ch2073h2146h1202h1fd0h1e76h2189h1d1ah1cabh1d2ah21bch1fc6hzz1de098h8275bh1de097hz31h87h2a8h839hd24he5bh1288h12a5h12a9h12bdh12e5h137ah139eh13b6h13eah1441h14ddh1504h1537h15a8h162dh1631h1758h17eeh1898h18e1h1946h19b5h1b0ah224fh1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h2218h2216h226dh22d0h24afh2327h2336h2438h2461h2487h24d7h129fi1155h) Received-SPF: softfail (mail26-va3: transitioning domain of gmail.com does not designate 137.71.25.57 as permitted sender) client-ip=137.71.25.57; envelope-from=sonic.adi@gmail.com; helo=nwd2mta2.analog.com ; 2.analog.com ; X-FB-DOMAIN-IP-MATCH: fail Received: from mail26-va3 (localhost.localdomain [127.0.0.1]) by mail26-va3 (MessageSwitch) id 1390888198544964_16464; Tue, 28 Jan 2014 05:49:58 +0000 (UTC) Received: from VA3EHSMHS021.bigfish.com (unknown [10.7.14.233]) by mail26-va3.bigfish.com (Postfix) with ESMTP id 7EB952C0047; Tue, 28 Jan 2014 05:49:58 +0000 (UTC) Received: from nwd2mta2.analog.com (137.71.25.57) by VA3EHSMHS021.bigfish.com (10.7.99.31) with Microsoft SMTP Server (TLS) id 14.16.227.3; Tue, 28 Jan 2014 05:49:58 +0000 Received: from NWD2HUBCAS5.ad.analog.com (nwd2hubcas5.ad.analog.com [10.64.72.161]) by nwd2mta2.analog.com (8.13.8/8.13.8) with ESMTP id s0S80UJ0022653 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Tue, 28 Jan 2014 03:00:30 -0500 Received: from zeus.spd.analog.com (10.64.82.11) by NWD2HUBCAS5.ad.analog.com (10.64.72.161) with Microsoft SMTP Server id 14.3.158.1; Tue, 28 Jan 2014 00:49:19 -0500 Received: from linux.site ([10.99.22.20]) by zeus.spd.analog.com (8.14.6/8.14.6) with ESMTP id s0S5nHmH005780; Tue, 28 Jan 2014 00:49:18 -0500 Received: from nine.analog.com (unknown [10.99.24.98]) by linux.site (Postfix) with ESMTP id CFD753AB7DB4; Mon, 27 Jan 2014 14:42:32 -0700 (MST) From: Sonic Zhang To: Sonic Zhang , Date: Tue, 28 Jan 2014 13:53:36 +0800 Message-ID: <1390888416-23534-4-git-send-email-sonic.adi@gmail.com> X-Mailer: git-send-email 1.8.2.3 In-Reply-To: <1390888416-23534-1-git-send-email-sonic.adi@gmail.com> References: <1390888416-23534-1-git-send-email-sonic.adi@gmail.com> MIME-Version: 1.0 X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% Cc: Scott Jiang , Sonic Zhang , adi-u-boot-devel@lists.sourceforge.net Subject: [U-Boot] [PATCH 4/4] blackfin: make i2c driver blackfin independant X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Scott Jiang The ADI twi peripheral is not binding to Blackfin processor only. Access i2c registers by standard io functions. Fix coding style. Signed-off-by: Scott Jiang Signed-off-by: Sonic Zhang --- drivers/i2c/adi_i2c.c | 151 ++++++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 71 deletions(-) diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c index 743aa25..675f417 100644 --- a/drivers/i2c/adi_i2c.c +++ b/drivers/i2c/adi_i2c.c @@ -1,7 +1,7 @@ /* - * i2c.c - driver for Blackfin on-chip TWI/I2C + * i2c.c - driver for ADI TWI/I2C * - * Copyright (c) 2006-2010 Analog Devices Inc. + * Copyright (c) 2006-2013 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -11,6 +11,7 @@ #include #include +#include /* Every register is 32bit aligned, but only 16bits in size */ #define ureg(name) u16 name; u16 __pad_##name; @@ -39,7 +40,7 @@ struct twi_regs { #ifdef TWI_CLKDIV #define TWI0_CLKDIV TWI_CLKDIV #endif -static volatile struct twi_regs *twi = (void *)TWI0_CLKDIV; +static struct twi_regs *twi = (void *)TWI0_CLKDIV; #ifdef DEBUG # define dmemset(s, c, n) memset(s, c, n) @@ -93,53 +94,54 @@ struct i2c_msg { */ static int wait_for_completion(struct i2c_msg *msg) { - uint16_t int_stat; + u16 int_stat, ctl; ulong timebase = get_timer(0); do { - int_stat = twi->int_stat; + int_stat = readw(&twi->int_stat); if (int_stat & XMTSERV) { debugi("processing XMTSERV"); - twi->int_stat = XMTSERV; - SSYNC(); + writew(XMTSERV, &twi->int_stat); if (msg->alen) { - twi->xmt_data8 = *(msg->abuf++); + writew(*(msg->abuf++), &twi->xmt_data8); --msg->alen; } else if (!(msg->flags & I2C_M_COMBO) && msg->len) { - twi->xmt_data8 = *(msg->buf++); + writew(*(msg->buf++), &twi->xmt_data8); --msg->len; } else { - twi->master_ctl |= (msg->flags & I2C_M_COMBO) ? RSTART | MDIR : STOP; - SSYNC(); + ctl = readw(&twi->master_ctl); + if (msg->flags & I2C_M_COMBO) + writew(ctl | RSTART | MDIR, + &twi->master_ctl); + else + writew(ctl | STOP, &twi->master_ctl); } } if (int_stat & RCVSERV) { debugi("processing RCVSERV"); - twi->int_stat = RCVSERV; - SSYNC(); + writew(RCVSERV, &twi->int_stat); if (msg->len) { - *(msg->buf++) = twi->rcv_data8; + *(msg->buf++) = readw(&twi->rcv_data8); --msg->len; } else if (msg->flags & I2C_M_STOP) { - twi->master_ctl |= STOP; - SSYNC(); + ctl = readw(&twi->master_ctl); + writew(ctl | STOP, &twi->master_ctl); } } if (int_stat & MERR) { debugi("processing MERR"); - twi->int_stat = MERR; - SSYNC(); + writew(MERR, &twi->int_stat); return msg->len; } if (int_stat & MCOMP) { debugi("processing MCOMP"); - twi->int_stat = MCOMP; - SSYNC(); + writew(MCOMP, &twi->int_stat); if (msg->flags & I2C_M_COMBO && msg->len) { - twi->master_ctl = (twi->master_ctl & ~RSTART) | + ctl = readw(&twi->master_ctl); + ctl = (ctl & ~RSTART) | (min(msg->len, 0xff) << 6) | MEN | MDIR; - SSYNC(); + writew(ctl, &twi->master_ctl); } else break; } @@ -160,8 +162,11 @@ static int wait_for_completion(struct i2c_msg *msg) * Here we just get the i2c stuff all prepped and ready, and then tail off * into wait_for_completion() for all the bits to go. */ -static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, int len, u8 flags) +static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, + int len, u8 flags) { + int ret; + u16 ctl; uchar addr_buffer[] = { (addr >> 0), (addr >> 8), @@ -174,62 +179,59 @@ static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, int len, .abuf = addr_buffer, .alen = alen, }; - int ret; dmemset(buffer, 0xff, len); - debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i flags=0x%02x[%s] ", - chip, addr, alen, buffer[0], len, flags, (flags & I2C_M_READ ? "rd" : "wr")); + debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i ", + chip, addr, alen, buffer[0], len); + debugi("flags=0x%02x[%s] ", flags, + (flags & I2C_M_READ ? "rd" : "wr")); /* wait for things to settle */ - while (twi->master_stat & BUSBUSY) + while (readw(&twi->master_stat) & BUSBUSY) if (ctrlc()) return 1; /* Set Transmit device address */ - twi->master_addr = chip; + writew(chip, &twi->master_addr); /* Clear the FIFO before starting things */ - twi->fifo_ctl = XMTFLUSH | RCVFLUSH; - SSYNC(); - twi->fifo_ctl = 0; - SSYNC(); + writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl); + writew(0, &twi->fifo_ctl); /* prime the pump */ if (msg.alen) { len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len; debugi("first byte=0x%02x", *msg.abuf); - twi->xmt_data8 = *(msg.abuf++); + writew(*(msg.abuf++), &twi->xmt_data8); --msg.alen; } else if (!(msg.flags & I2C_M_READ) && msg.len) { debugi("first byte=0x%02x", *msg.buf); - twi->xmt_data8 = *(msg.buf++); + writew(*(msg.buf++), &twi->xmt_data8); --msg.len; } /* clear int stat */ - twi->master_stat = -1; - twi->int_stat = -1; - twi->int_mask = 0; - SSYNC(); + writew(-1, &twi->master_stat); + writew(-1, &twi->int_stat); + writew(0, &twi->int_mask); /* Master enable */ - twi->master_ctl = - (twi->master_ctl & FAST) | - (min(len, 0xff) << 6) | MEN | - ((msg.flags & I2C_M_READ) ? MDIR : 0); - SSYNC(); - debugi("CTL=0x%04x", twi->master_ctl); + ctl = readw(&twi->master_ctl); + ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN | + ((msg.flags & I2C_M_READ) ? MDIR : 0); + writew(ctl, &twi->master_ctl); /* process the rest */ ret = wait_for_completion(&msg); debugi("ret=%d", ret); if (ret) { - twi->master_ctl &= ~MEN; - twi->control &= ~TWI_ENA; - SSYNC(); - twi->control |= TWI_ENA; - SSYNC(); + ctl = readw(&twi->master_ctl) & ~MEN; + writew(ctl, &twi->master_ctl); + ctl = readw(&twi->control) & ~TWI_ENA; + writew(ctl, &twi->control); + ctl = readw(&twi->control) | TWI_ENA; + writew(ctl, &twi->control); } return ret; @@ -246,10 +248,11 @@ int i2c_set_bus_speed(unsigned int speed) /* Set TWI interface clock */ if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN) return -1; - twi->clkdiv = (clkdiv << 8) | (clkdiv & 0xff); + clkdiv = (clkdiv << 8) | (clkdiv & 0xff); + writew(clkdiv, &twi->clkdiv); /* Don't turn it on */ - twi->master_ctl = (speed > 100000 ? FAST : 0); + writew(speed > 100000 ? FAST : 0, &twi->master_ctl); return 0; } @@ -260,8 +263,9 @@ int i2c_set_bus_speed(unsigned int speed) */ unsigned int i2c_get_bus_speed(void) { + u16 clkdiv = readw(&twi->clkdiv) & 0xff; /* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */ - return 5000000 / (twi->clkdiv & 0xff); + return 5000000 / clkdiv; } /** @@ -274,27 +278,22 @@ unsigned int i2c_get_bus_speed(void) */ void i2c_init(int speed, int slaveaddr) { - uint8_t prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F; + u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F; /* Set TWI internal clock as 10MHz */ - twi->control = prescale; + writew(prescale, &twi->control); /* Set TWI interface clock as specified */ i2c_set_bus_speed(speed); /* Enable it */ - twi->control = TWI_ENA | prescale; - SSYNC(); + writew(TWI_ENA | prescale, &twi->control); - debugi("CONTROL:0x%04x CLKDIV:0x%04x", twi->control, twi->clkdiv); + debugi("CONTROL:0x%04x CLKDIV:0x%04x", readw(&twi->control), + readw(&twi->clkdiv)); #if CONFIG_SYS_I2C_SLAVE # error I2C slave support not tested/supported - /* If they want us as a slave, do it */ - if (slaveaddr) { - twi->slave_addr = slaveaddr; - twi->slave_ctl = SEN; - } #endif } @@ -320,7 +319,8 @@ int i2c_probe(uchar chip) */ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) { - return i2c_transfer(chip, addr, alen, buffer, len, (alen ? I2C_M_COMBO : I2C_M_READ)); + return i2c_transfer(chip, addr, alen, buffer, + len, (alen ? I2C_M_COMBO : I2C_M_READ)); } /** @@ -346,15 +346,21 @@ int i2c_set_bus_num(unsigned int bus) { switch (bus) { #if CONFIG_SYS_MAX_I2C_BUS > 0 - case 0: twi = (void *)TWI0_CLKDIV; return 0; + case 0: + twi = (void *)TWI0_CLKDIV; + return 0; #endif #if CONFIG_SYS_MAX_I2C_BUS > 1 - case 1: twi = (void *)TWI1_CLKDIV; return 0; + case 1: + twi = (void *)TWI1_CLKDIV; + return 0; #endif #if CONFIG_SYS_MAX_I2C_BUS > 2 - case 2: twi = (void *)TWI2_CLKDIV; return 0; + case 2: + twi = (void *)TWI2_CLKDIV; + return 0; #endif - default: return -1; + default: return -1; } } @@ -365,14 +371,17 @@ unsigned int i2c_get_bus_num(void) { switch ((unsigned long)twi) { #if CONFIG_SYS_MAX_I2C_BUS > 0 - case TWI0_CLKDIV: return 0; + case TWI0_CLKDIV: + return 0; #endif #if CONFIG_SYS_MAX_I2C_BUS > 1 - case TWI1_CLKDIV: return 1; + case TWI1_CLKDIV: + return 1; #endif #if CONFIG_SYS_MAX_I2C_BUS > 2 - case TWI2_CLKDIV: return 2; + case TWI2_CLKDIV: + return 2; #endif - default: return -1; + default: return -1; } }