From e1bbb64ec2ca8ddf1dec91ae1e08ef96ee53639a Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Tue, 11 Jan 2011 17:31:17 +0100 Subject: fixed issue with submodules --- x-loader | 1 - x-loader/drivers/omap24xx_i2c.c | 354 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+), 1 deletion(-) delete mode 160000 x-loader create mode 100644 x-loader/drivers/omap24xx_i2c.c (limited to 'x-loader/drivers/omap24xx_i2c.c') diff --git a/x-loader b/x-loader deleted file mode 160000 index 1c9276a..0000000 --- a/x-loader +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1c9276af4d6a5b7014a7630a1abeddf3b3177563 diff --git a/x-loader/drivers/omap24xx_i2c.c b/x-loader/drivers/omap24xx_i2c.c new file mode 100644 index 0000000..7782e9d --- /dev/null +++ b/x-loader/drivers/omap24xx_i2c.c @@ -0,0 +1,354 @@ +/* + * Basic I2C functions + * + * Copyright (c) 2004 Texas Instruments + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the license found in the file + * named COPYING that should have accompanied this file. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Jian Zhang jzhang@ti.com, Texas Instruments + * + * Copyright (c) 2003 Wolfgang Denk, wd@denx.de + * Rewritten to fit into the current U-Boot framework + * + * Adapted for OMAP2420 I2C, r-woodruff2@ti.com + * + */ + +#include + +#if defined(CONFIG_DRIVER_OMAP24XX_I2C) || defined(CONFIG_DRIVER_OMAP34XX_I2C) + +#include +#include + +#define inb(a) __raw_readb(a) +#define outb(a,v) __raw_writeb(a,v) +#define inw(a) __raw_readw(a) +#define outw(a,v) __raw_writew(a,v) + +static void wait_for_bb (void); +static u16 wait_for_pin (void); +static void flush_fifo(void); + +void i2c_init (int speed, int slaveadd) +{ + u16 scl; + + outw(0x2, I2C_SYSC); /* for ES2 after soft reset */ + udelay(1000); + outw(0x0, I2C_SYSC); /* will probably self clear but */ + + if (inw (I2C_CON) & I2C_CON_EN) { + outw (0, I2C_CON); + udelay (50000); + } + + /* 12Mhz I2C module clock */ + outw (0, I2C_PSC); + speed = speed/1000; /* 100 or 400 */ + scl = ((12000/(speed*2)) - 7); /* use 7 when PSC = 0 */ + outw (scl, I2C_SCLL); + outw (scl, I2C_SCLH); + /* own address */ + outw (slaveadd, I2C_OA); + outw (I2C_CON_EN, I2C_CON); + + /* have to enable intrrupts or OMAP i2c module doesn't work */ + outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | + I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE); + udelay (1000); + flush_fifo(); + outw (0xFFFF, I2C_STAT); + outw (0, I2C_CNT); +} + +static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) +{ + int i2c_error = 0; + u16 status; + + /* wait until bus not busy */ + wait_for_bb (); + + /* one byte only */ + outw (1, I2C_CNT); + /* set slave address */ + outw (devaddr, I2C_SA); + /* no stop bit needed here */ + outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON); + + status = wait_for_pin (); + + if (status & I2C_STAT_XRDY) { + /* Important: have to use byte access */ + *(volatile u8 *) (I2C_DATA) = regoffset; + udelay (20000); + if (inw (I2C_STAT) & I2C_STAT_NACK) { + i2c_error = 1; + } + } else { + i2c_error = 1; + } + + if (!i2c_error) { + /* free bus, otherwise we can't use a combined transction */ + outw (0, I2C_CON); + while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) { + udelay (10000); + /* Have to clear pending interrupt to clear I2C_STAT */ + outw (0xFFFF, I2C_STAT); + } + + wait_for_bb (); + /* set slave address */ + outw (devaddr, I2C_SA); + /* read one byte from slave */ + outw (1, I2C_CNT); + /* need stop bit here */ + outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, + I2C_CON); + + status = wait_for_pin (); + if (status & I2C_STAT_RRDY) { +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + *value = inb(I2C_DATA); +#else + *value = inw(I2C_DATA); +#endif + udelay (20000); + } else { + i2c_error = 1; + } + + if (!i2c_error) { + outw (I2C_CON_EN, I2C_CON); + while (inw (I2C_STAT) + || (inw (I2C_CON) & I2C_CON_MST)) { + udelay (10000); + outw (0xFFFF, I2C_STAT); + } + } + } + flush_fifo(); + outw (0xFFFF, I2C_STAT); + outw (0, I2C_CNT); + return i2c_error; +} + +static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) +{ + int i2c_error = 0; + u16 status, stat; + + /* wait until bus not busy */ + wait_for_bb (); + + /* two bytes */ + outw (2, I2C_CNT); + /* set slave address */ + outw (devaddr, I2C_SA); + /* stop bit needed here */ + outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | + I2C_CON_STP, I2C_CON); + + /* wait until state change */ + status = wait_for_pin (); + + if (status & I2C_STAT_XRDY) { +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + /* send out 1 byte */ + outb(regoffset, I2C_DATA); + outw(I2C_STAT_XRDY, I2C_STAT); + status = wait_for_pin(); + if ((status & I2C_STAT_XRDY)) { + /* send out next 1 byte */ + outb(value, I2C_DATA); + outw(I2C_STAT_XRDY, I2C_STAT); + } else { + i2c_error = 1; + } +#else + /* send out two bytes */ + outw ((value << 8) + regoffset, I2C_DATA); +#endif + + /* must have enough delay to allow BB bit to go low */ + udelay (50000); + if (inw (I2C_STAT) & I2C_STAT_NACK) { + i2c_error = 1; + } + } else { + i2c_error = 1; + } + + if (!i2c_error) { + int eout = 200; + + outw (I2C_CON_EN, I2C_CON); + while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) { + udelay (1000); + /* have to read to clear intrrupt */ + outw (0xFFFF, I2C_STAT); + if(--eout == 0) /* better leave with error than hang */ + break; + } + } + flush_fifo(); + outw (0xFFFF, I2C_STAT); + outw (0, I2C_CNT); + return i2c_error; +} + +static void flush_fifo(void) +{ u16 stat; + + /* note: if you try and read data when its not there or ready + * you get a bus error + */ + while(1){ + stat = inw(I2C_STAT); + if(stat == I2C_STAT_RRDY){ +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + inb(I2C_DATA); +#else + inw(I2C_DATA); +#endif + outw(I2C_STAT_RRDY,I2C_STAT); + udelay(1000); + }else + break; + } +} + +int i2c_probe (uchar chip) +{ + int res = 1; /* default = fail */ + + if (chip == inw (I2C_OA)) { + return res; + } + + /* wait until bus not busy */ + wait_for_bb (); + + /* try to read one byte */ + outw (1, I2C_CNT); + /* set slave address */ + outw (chip, I2C_SA); + /* stop bit needed here */ + outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON); + /* enough delay for the NACK bit set */ + udelay (50000); + + if (!(inw (I2C_STAT) & I2C_STAT_NACK)) { + res = 0; /* success case */ + flush_fifo(); + outw(0xFFFF, I2C_STAT); + } else { + outw(0xFFFF, I2C_STAT); /* failue, clear sources*/ + outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */ + udelay(20000); + wait_for_bb (); + } + flush_fifo(); + outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/ + outw(0xFFFF, I2C_STAT); + return res; +} + +int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + int i; + + if (alen > 1) { + printf ("I2C read: addr len %d not supported\n", alen); + return 1; + } + + if (addr + len > 256) { + printf ("I2C read: address out of range\n"); + return 1; + } + + for (i = 0; i < len; i++) { + if (i2c_read_byte (chip, addr + i, &buffer[i])) { + printf ("I2C read: I/O error\n"); + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + return 1; + } + } + + return 0; +} + +int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + int i; + + if (alen > 1) { + printf ("I2C read: addr len %d not supported\n", alen); + return 1; + } + + if (addr + len > 256) { + printf ("I2C read: address out of range\n"); + return 1; + } + + for (i = 0; i < len; i++) { + if (i2c_write_byte (chip, addr + i, buffer[i])) { + printf ("I2C read: I/O error\n"); + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + return 1; + } + } + + return 0; +} + +static void wait_for_bb (void) +{ + int timeout = 10; + u16 stat; + + outw(0xFFFF, I2C_STAT); /* clear current interruts...*/ + while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) { + outw (stat, I2C_STAT); + udelay (50000); + } + + if (timeout <= 0) { + printf ("timed out in wait_for_bb: I2C_STAT=%x\n", + inw (I2C_STAT)); + } + outw(0xFFFF, I2C_STAT); /* clear delayed stuff*/ +} + +static u16 wait_for_pin (void) +{ + u16 status; + int timeout = 10; + + do { + udelay (1000); + status = inw (I2C_STAT); + } while ( !(status & + (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | + I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | + I2C_STAT_AL)) && timeout--); + + if (timeout <= 0) { + printf ("timed out in wait_for_pin: I2C_STAT=%x\n", + inw (I2C_STAT)); + outw(0xFFFF, I2C_STAT); +} + return status; +} + +#endif /* CONFIG_DRIVER_OMAP24XX_I2C */ -- cgit v1.1