summaryrefslogtreecommitdiff
path: root/board/ti/logic/logic-at24.c
diff options
context:
space:
mode:
authorJustin Waters <justin.waters@timesys.com>2012-04-17 13:43:17 -0400
committerJustin Waters <justin.waters@timesys.com>2012-04-17 13:43:17 -0400
commit4f60d7e7027af17ceffc1a38e6dbe4e3e95c71ec (patch)
treedd33f3760e08226d5c05036d664d2d68fb3765dc /board/ti/logic/logic-at24.c
parentb1af6f532e0d348b153d5c148369229d24af361a (diff)
LogicPD Support for OMAP3/DM3/AM3 boards
From Logic BSP-2.0-5-01
Diffstat (limited to 'board/ti/logic/logic-at24.c')
-rw-r--r--board/ti/logic/logic-at24.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/board/ti/logic/logic-at24.c b/board/ti/logic/logic-at24.c
new file mode 100644
index 0000000000..e1f03db2ce
--- /dev/null
+++ b/board/ti/logic/logic-at24.c
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright 2008-2011
+ * Logic Product Development, <www.logicpd.com>
+ * Peter Barada <peter.barada@logicpd.com>
+ *
+ * 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 <common.h>
+#include <command.h>
+#include <asm/arch/cpu.h>
+#include <asm/io.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/clocks.h>
+#include <asm/arch/mem.h>
+#include <i2c.h>
+#include <asm/mach-types.h>
+#include "logic-i2c.h"
+
+#define AT24_CHIP_ID 0xA0
+#define AT24_ACCESS_WRITE 0
+#define AT24_ACCESS_READ 1
+
+#define AT24_DEVICE_ADDRESS(rw) (AT24_CHIP_ID | (rw & 1))
+#define AT24_SIZE_MASK 0x7FF /* 2048 byte AT24C16 */
+int at24_wakeup(void)
+{
+ int i;
+ gpio_i2c_init(100000);
+
+ /* Need 9 clocks to wake up AT24 chips */
+ gpio_i2c_config_pin(GPIO_I2C_SCLK, GPIO_I2C_OUTPUT);
+ gpio_i2c_set_pin_level(GPIO_I2C_SCLK, 1);
+ for (i=0; i<10; ++i) {
+ udelay(100);
+ gpio_i2c_set_pin_level(GPIO_I2C_SCLK, 0);
+ udelay(100);
+ gpio_i2c_set_pin_level(GPIO_I2C_SCLK, 1);
+ }
+
+ /* We can't identify AT24 chips... */
+
+ return 0;
+
+}
+
+int at24_shutdown(void)
+{
+ /* Restore GPIO_OE registers back to reset state (All input) */
+ gpio_i2c_config_pin(GPIO_I2C_SDATA, GPIO_I2C_INPUT);
+ gpio_i2c_config_pin(GPIO_I2C_SCLK, GPIO_I2C_INPUT);
+ /* Restore pins back to their intended use */
+ gpio_i2c_restore_pins();
+}
+
+/* Send the offset to the AT24 chip */
+static int at24_send_offset(u32 offset)
+{
+ int sleeps = 100;
+ int timeout = 1000;
+ int err, i;
+ u32 byteoffset, sizemask, sentoffset;
+
+ do {
+ while (gpio_i2c_busy() && timeout--)
+ udelay(100);
+ sleeps--;
+
+ gpio_i2c_tx_start();
+
+ err = gpio_i2c_tx_byte(AT24_DEVICE_ADDRESS(AT24_ACCESS_WRITE));
+
+ /* If the eeprom is busy, reset the bus an start over */
+ if (err)
+ gpio_i2c_tx_stop();
+
+ if (err && !sleeps) {
+ /* NACK, return error */
+ return err;
+ }
+ } while (err);
+
+ /* Write the destination offset to the AT24 */
+ sizemask = AT24_SIZE_MASK;
+ sentoffset = offset & sizemask;
+
+ for (i=0; i<4; ++i) {
+ byteoffset = (sentoffset & 0xFF000000) >> 24;
+ if (sizemask & 0xFF000000) {
+ err = gpio_i2c_tx_byte(byteoffset);
+ if (err)
+ return err;
+ }
+ sentoffset <<= 8;
+ sizemask <<= 8;
+ }
+ return 0;
+}
+
+/* Read 'size' bytes from the AT88 at offset 'offset'; return 0 if good */
+int at24_read(u32 offset, u8 *buf, u32 size)
+{
+ int rx_mode;
+ int err, idx;
+
+ err = at24_send_offset(offset);
+ if (err)
+ return err;
+ gpio_i2c_tx_stop();
+
+ gpio_i2c_tx_start();
+ err = gpio_i2c_tx_byte(AT24_DEVICE_ADDRESS(AT24_ACCESS_READ));
+ if (err)
+ return err;
+
+ for (idx = 0; idx < size; ++idx) {
+ if (size == 1)
+ rx_mode = RX_MODE_ONE_BYTE;
+ else if (idx == (size - 1))
+ rx_mode = RX_MODE_LAST_BYTE;
+ else if (idx == (size - 2))
+ rx_mode = RX_MODE_NEXT_TO_LAST_BYTE;
+ else if (idx == 0)
+ rx_mode = RX_MODE_FIRST_BYTE;
+ else
+ rx_mode = RX_MODE_MIDDLE_BYTE;
+
+ err = gpio_i2c_rx_byte(&buf[idx], rx_mode);
+ if (err)
+ printf("%s:%d err idx %d\n", __FUNCTION__, __LINE__, idx);
+ }
+
+ gpio_i2c_tx_stop();
+ return err;
+}