From: =?UTF-8?B?SsO8cmdlbiBTY2jDtnc=?= Date: Sun, 4 Jan 2009 22:54:29 +0100 Subject: [U-Boot] [patch V3] [1/3] PNX8181 SOC support In-Reply-To: <20090104225017.50e928f0@schleppi.schoew.net> References: <20090104225017.50e928f0@schleppi.schoew.net> Message-ID: <20090104225429.0bdbdf66@schleppi.schoew.net> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de cpu/arm926ejs/pnx8181/Makefile | 45 +++ cpu/arm926ejs/pnx8181/timer.c | 141 ++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/pnx8181_i2c.c | 304 +++++++++++++++++ diff --git a/cpu/arm926ejs/pnx8181/Makefile b/cpu/arm926ejs/pnx8181/Makefile new file mode 100644 index 0000000..b34d9e8 --- /dev/null +++ b/cpu/arm926ejs/pnx8181/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd at denx.de. +# +# 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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = timer.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/pnx8181/timer.c b/cpu/arm926ejs/pnx8181/timer.c new file mode 100644 index 0000000..585aede --- /dev/null +++ b/cpu/arm926ejs/pnx8181/timer.c @@ -0,0 +1,141 @@ +/* + * pnx8181 SOC timer routines + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, + * + * 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 + */ + +#include +#include + +/* + * timer without interrupts + */ +/* timer */ +#define PNX8181_SCTU1_BASE 0xC2102000 +#define PNX8181_SCTU2_BASE 0xC2103000 + +#define PNX8181_SCTU_TIMxCR 0x00 +#define PNX8181_SCTU_TIMxRR 0x04 +#define PNX8181_SCTU_TIMxWR 0x08 +#define PNX8181_SCTU_TIMxC0 0x0c +#define PNX8181_SCTU_TIMxC1 0x10 +#define PNX8181_SCTU_TIMxC2 0x14 +#define PNX8181_SCTU_TIMxC3 0x18 +#define PNX8181_SCTU_TIMxSR 0x1c +#define PNX8181_SCTU_TIMxPR 0x20 + +/* + * U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ + * Keep total timer count to avoid losing decrements < div_timer + */ + +/* U-Boot ticks since startup */ +static ulong timestamp; +static ulong last_timer_read; + +/* + * starts up a counter + */ +void timer_init(void) +{ + /* set prescaler to have timer run at 64 kHz */ + writeb(0x00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxPR)); + + /* timer reload value = 0xffff - 13824, overflow @ 1kHz */ + writew(0xca00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxRR)); + + /* timer has no interrupt, run */ + writew(0x0001, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxCR)); + + /* init the timestamp */ + reset_timer_masked(); +} + +ulong get_timer(ulong base_ticks) +{ + return get_timer_masked() - base_ticks; +} + +/* + * converts the timer reading to U-Boot ticks + * the timestamp is the number of ticks since reset + */ +ulong get_timer_masked(void) +{ + /* get current count */ + ulong now = readw((void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxWR)); + + if (now < last_timer_read) + timestamp += 13824; + last_timer_read = now; + + /* + * FIXME this value is empirical! + * for some reason the calculated values are way to fast + */ + return (timestamp + now) / 64; +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + + +/* busy-loop spin-delay */ +void sdelay(unsigned long usec) +{ + ulong i, tmp; + tmp = 42; + for (i = 0 ; i < usec*3 ; i++) + /* avoid compiler optimisation */ + tmp = -tmp; +} + +/* delay usec useconds */ +void udelay(unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec / 1500; + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* form target timestamp */ + + /* loop till event */ + while (get_timer_masked() < tmo) + ; +} + +void reset_timer_masked(void) +{ + /* start "advancing" time stamp from 0 */ + timestamp = 0L; +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 6079c05..ef457a5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o +COBJS-$(CONFIG_PNX8181_I2C) += pnx8181_i2c.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/i2c/pnx8181_i2c.c b/drivers/i2c/pnx8181_i2c.c new file mode 100644 index 0000000..75a76a4 --- /dev/null +++ b/drivers/i2c/pnx8181_i2c.c @@ -0,0 +1,304 @@ +/* + * (C) Copyright 2008-2009, emlix GmbH, Germany + * Juergen Schoew + * + * 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 + * + */ + +#include +#include +#include + +#define I2C_TIMEOUT 10000 +#define I2C_DELAY 10 + +#define ARM_VPB1_BASE_ADDR 0xC2000000 +#define ARM_VPB3_BASE_ADDR 0xC2200000 +#define ARM_VPB_SIZE_SHIFT 12 + +#define SCON_BASE_ADDR (ARM_VPB3_BASE_ADDR + (4< I2C_TIMEOUT) + break; + timeout++; + udelay(I2C_DELAY); + } + debug("%s: speed: %d\n", __func__, speed); +} + + +int i2c_probe(uchar chip) +{ + unsigned long timeout; + + SEND_I2C_DEVICE_ADDRESS_START_STOP(chip); + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG); + if ((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) + return -1; + return 0; +} + +static int i2c_read_byte(u8 chip, u16 addr, u8 *byte) +{ + unsigned long timeout; + + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + SEND_I2C_START_ADDRESS(chip); + /* loop if scl=1, active=0 or drmi=0 */ + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_SCL) == I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) != I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) != I2C_DRMI)) + if (timeout > I2C_TIMEOUT) { + return -1; + timeout++; + udelay(I2C_DELAY); + } + writel((addr & 0xFF00) >> 8, I2C_TX_REG); /* ADDRESS_MODE16 */ + writel((addr & 0x00FF) >> 0, I2C_TX_REG); + SEND_I2C_READ_ADDRESS(chip); /* Dev Sel to Read */ + SEND_I2C_STOP_DATA(0x00); /* dummy write */ + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) || + ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) || + ((readl(I2C_STS_REG) & I2C_SCL) != I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) == I2C_DRMI)) + if (timeout > I2C_TIMEOUT) { + return -1; + timeout++; + udelay(I2C_DELAY); + } + writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG); + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_TDI) == I2C_TDI) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + *byte = readl(I2C_RX_REG) & 0xff; + return 0; +} + +static int i2c_write_byte(u8 chip, u16 addr, u8 *byte) +{ + u8 dummy; + unsigned long timeout; + + /* wait until data is written and eeprom back again */ + timeout = 0; + dummy = 1; + while ((timeout < I2C_TIMEOUT) && (dummy != 0)) { + dummy = -i2c_probe(chip); + timeout++; + udelay(I2C_DELAY); + } + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + SEND_I2C_START_ADDRESS(chip); + /* loop if scl=1, active=0 or drmi=0 */ + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_SCL) == I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) != I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) != I2C_DRMI)) { + if (timeout > I2C_TIMEOUT) + return -2; + timeout++; + udelay(I2C_DELAY); + } + writel((addr & 0xFF00) >> 8, I2C_TX_REG); /* ADDRESS_MODE16 */ + writel((addr & 0x00FF) >> 0, I2C_TX_REG); + SEND_I2C_STOP_DATA(*byte); + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) || + ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) || + ((readl(I2C_STS_REG) & I2C_SCL) != I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) == I2C_DRMI)) { + if (timeout > I2C_TIMEOUT) + return -3; + timeout++; + udelay(I2C_DELAY); + } + writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG); + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_TDI) == I2C_TDI) { + if (timeout > I2C_TIMEOUT) + return -4; + timeout++; + udelay(I2C_DELAY); + } + dummy = readl(I2C_RX_REG) & 0xff; + return 0; +} + +int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret; + u8 byte; + + debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", + __func__, chip, addr, alen, len); + while (len--) { + ret = i2c_read_byte(chip, addr, &byte); + if (ret < 0) + return -1; + *buf++ = byte; + addr++; + } + return 0; +} + +int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret; + + debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", + __func__, chip, addr, alen, len); + while (len--) { + ret = i2c_write_byte(chip, addr++, buf++); + if (ret) { + printf("i2c_write failed chip: 0x%x addr: " + "0x%04x error %d\n", chip, addr, ret); + return -1; + } + } + return 0; +} -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: not available Url : http://lists.denx.de/pipermail/u-boot/attachments/20090104/4453c58e/attachment.pgp