[U-Boot-Users] [Patch 3/9]U-boot-V2:I2C: Introduce core

Menon, Nishanth x0nishan at ti.com
Thu Jun 19 17:11:47 CEST 2008


First part of this patch introduces i2c-core.
The codebase is sourced from 2.6.25 rc5 kernel
contains ONLY i2c support. SMBUS is to be added
on a need basis

Signed-off-by: Nishanth Menon <x0nishan at ti.com>

---
 drivers/Kconfig             |    1
 drivers/Makefile            |    1
 drivers/i2c/Kconfig         |   39 ++++
 drivers/i2c/Makefile        |   10 +
 drivers/i2c/busses/Kconfig  |    7
 drivers/i2c/busses/Makefile |    9 +
 drivers/i2c/i2c-core.c      |  387 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/i2c-core.h      |   37 ++++
 include/driver.h            |    4
 include/linux/i2c.h         |  299 +++++++++++++++++++++++++++++++++
 10 files changed, 793 insertions(+), 1 deletion(-)

Index: u-boot-v2.git/drivers/i2c/i2c-core.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/drivers/i2c/i2c-core.c        2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,387 @@
+/**
+ * @file
+ * @brief a device driver for the iic-bus interface
+ *
+ * FileName: drivers/i2c/i2c-core.c
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <x0nishan at ti.com>
+ */
+/* ------------------------------------------------------------------------- */
+/*   Copyright (C) 1995-99 Simon G. Vogl
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+/* ------------------------------------------------------------------------- */
+
+/* With some changes from Kyösti MÃ$lkki <kmalkki at cc.hut.fi>.
+   All SMBus-related things are written by Frodo Looijaard <frodol at dds.nl>
+   SMBus 2.0 support by Mark Studebaker <mdsxyz123 at yahoo.com> and
+   Jean Delvare <khali at linux-fr.org> */
+
+#include <common.h>
+#include <errno.h>
+#include <list.h>
+#include <init.h>
+#include <driver.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/i2c.h>
+#include <linux/idr.h>
+
+#include "i2c-core.h"
+
+#ifdef CONFIG_I2C_DEBUG_CORE
+#define DBG_MODULE_NAME "i2c-core"
+#define dev_dbg(ARGS...) fprintf(stdout, ARGS);
+#define dev_warn(ARGS...) fprintf(stderr, ARGS);
+#define dbg_entry(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Entry:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#define dbg_exit(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Exit:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#else
+#define dev_dbg(ARGS...)
+#define dev_warn(ARGS...)
+#define dbg_entry(FORMAT, ARGS...)
+#define dbg_exit(FORMAT, ARGS...)
+#endif
+#define dev_err(ARGS...) fprintf(stderr, ARGS);
+
+static DEFINE_IDR(i2c_adapter_idr);
+
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * @brief When traversing the driver model tree, perhaps using driver model
+ * iterators like @device_for_each_child(), you can't assume very much
+ * about the nodes you find.  Use this function to avoid oopses caused
+ * by wrongly treating some non-I2C device as an i2c_client.
+ *
+ * @param dev device, probably from some driver model iterator
+ *
+ * @return return parameter as i2c_client, or NULL
+ */
+struct i2c_client *i2c_verify_client(struct device_d *dev)
+{
+       dbg_entry("dev=%x", (u32) dev);
+       return (dev->type == DEVICE_TYPE_I2C) ? to_i2c_client(dev) : NULL;
+}
+EXPORT_SYMBOL(i2c_verify_client);
+
+static int i2c_register_adapter(struct i2c_adapter *adap)
+{
+       int res = 0;
+       dbg_entry("adap=%x", (u32) adap);
+
+       INIT_LIST_HEAD(&adap->clients);
+
+       /* Add the adapter to the driver core.
+        * If the parent pointer is not set up,
+        * we add this adapter to the host bus.
+        */
+       res = register_device(&adap->dev);
+       if (res)
+               goto out_list;
+
+       dev_dbg("adapter [%s] registered\n", adap->name);
+
+out_unlock:
+       return res;
+
+out_list:
+       idr_remove(&i2c_adapter_idr, adap->nr);
+       goto out_unlock;
+}
+
+/**
+ * @brief declare i2c adapter, use dynamic bus number
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * doesn't matter.  Examples: for I2C adapters dynamically added by
+ * USB links or PCI plugin cards.
+ *
+ * @param adapter  the adapter to add
+ *
+ * @return When this returns zero, a new bus number was allocated and stored
+ * in adap->nr, and the specified adapter became available for clients.
+ * Otherwise, a negative errno value is returned.
+ */
+int i2c_add_adapter(struct i2c_adapter *adapter)
+{
+       int id, res = 0;
+       dbg_entry("adapter=%x", (u32) adapter);
+
+retry:
+       if (idr_pre_get(&i2c_adapter_idr) == 0)
+               return -ENOMEM;
+
+       /* "above" here means "above or equal to", sigh */
+       res = idr_get_new_above(&i2c_adapter_idr, adapter,
+                               __i2c_first_dynamic_bus_num, &id);
+
+       if (res < 0) {
+               if (res == -EAGAIN)
+                       goto retry;
+               return res;
+       }
+
+       adapter->nr = id;
+       return i2c_register_adapter(adapter);
+}
+EXPORT_SYMBOL(i2c_add_adapter);
+
+/**
+ * @brief declare i2c adapter, use static bus number
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * matters.  For example, use it for I2C adapters from system-on-chip CPUs,
+ * or otherwise built in to the system's mainboard, and where i2c_board_info
+ * is used to properly configure I2C devices.
+ *
+ * If no devices have pre-been declared for this bus, then be sure to
+ * register the adapter before any dynamically allocated ones.  Otherwise
+ * the required bus ID may not be available.
+ *
+ * @param adap adapter to register (with adap->nr initialized)
+ *
+ * @return When this returns zero, the specified adapter became available for
+ * clients using the bus number provided in adap->nr.  Also, the table
+ * of I2C devices pre-declared using i2c_register_board_info() is scanned,
+ * and the appropriate driver model device nodes are created.  Otherwise, a
+ * negative errno value is returned.
+ */
+int i2c_add_numbered_adapter(struct i2c_adapter *adap)
+{
+       int id;
+       int status;
+
+       dbg_entry("adap=%x", (u32) adap);
+       if (adap->nr & ~MAX_ID_MASK)
+               return -EINVAL;
+
+retry:
+       if (idr_pre_get(&i2c_adapter_idr) == 0)
+               return -ENOMEM;
+
+       /* "above" here means "above or equal to", sigh;
+        * we need the "equal to" result to force the result
+        */
+       status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
+       if (status == 0 && id != adap->nr) {
+               status = -EBUSY;
+               idr_remove(&i2c_adapter_idr, id);
+       }
+       if (status == -EAGAIN)
+               goto retry;
+
+       if (status == 0)
+               status = i2c_register_adapter(adap);
+       return status;
+}
+EXPORT_SYMBOL(i2c_add_numbered_adapter);
+
+/**
+ * @brief unregister I2C adapter
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ *
+ * @param adap  the adapter being unregistered
+ *
+ * @return success or failure in removal
+ */
+int i2c_del_adapter(struct i2c_adapter *adap)
+{
+       struct list_head *item, *_n;
+       struct i2c_client *client;
+       int res = 0;
+
+       dbg_entry("adap=%x", (u32) adap);
+       /* First make sure that this adapter was ever added */
+       if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
+               dev_err("i2c-core: attempting to delete unregistered "
+                       "adapter [%s]\n", adap->name);
+               res = -EINVAL;
+               goto out_unlock;
+       }
+
+       /* detach any active clients. This must be done first, because
+        * it can fail; in which case we give up. */
+       list_for_each_safe(item, _n, &adap->clients) {
+               struct i2c_driver *driver;
+
+               client = list_entry(item, struct i2c_client, list);
+               driver = client->driver;
+
+               /* new style, follow standard driver model
+                * Place holder
+               if (!driver) {
+                       i2c_unregister_device(client);
+                       continue;
+               }
+               */
+
+       }
+
+       /* clean up the sysfs representation */
+       unregister_device(&adap->dev);
+
+       /* free bus id */
+       idr_remove(&i2c_adapter_idr, adap->nr);
+
+       dev_dbg("adapter [%s] unregistered\n", adap->name);
+
+out_unlock:
+       return res;
+}
+EXPORT_SYMBOL(i2c_del_adapter);
+/**
+ * @brief find the adapter for an id
+ *  Also increase the adapter refcount
+ *
+ * @param id id to search
+ *
+ * @return adapter else NULL
+ */
+struct i2c_adapter *i2c_get_adapter(int id)
+{
+       struct i2c_adapter *adapter;
+       dbg_entry("id=%x", id);
+
+       adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+
+       return adapter;
+}
+EXPORT_SYMBOL(i2c_get_adapter);
+
+/**
+ * @brief  return the usage of get_adapter -> reduce refcount
+ *
+ * @param adap adapter to return
+ *
+ * @return none
+ */
+void i2c_put_adapter(struct i2c_adapter *adap)
+{
+       dbg_entry("adap=%x", (u32) adap);
+       /* Empty function for the timebeing.. */
+}
+EXPORT_SYMBOL(i2c_put_adapter);
+
+/* ------------------------------------------------------------------------- */
+
+/* ----------------------------------------------------
+ * the functional interface to the i2c busses.
+ * ----------------------------------------------------
+ */
+
+/**
+ * @brief do i2c_transfer to an adapter
+ *
+ * @param adap adapter
+ * @param msgs the messages
+ * @param num number of messages
+ *
+ * @return result of transfer
+ */
+int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       int ret;
+
+       dbg_entry("adap=%x msg=%x num=%x", (u32) adap, (u32) msgs, num);
+       if (adap->algo->master_xfer) {
+#ifdef DEBUG
+               for (ret = 0; ret < num; ret++) {
+                       dev_dbg("master_xfer[%d] %c, addr=0x%02x, "
+                               "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
+                               ? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
+                               (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
+               }
+#endif
+
+               ret = adap->algo->master_xfer(adap, msgs, num);
+               return ret;
+       } else {
+               dev_dbg("I2C level transfers not supported\n");
+               return -ENOSYS;
+       }
+}
+EXPORT_SYMBOL(i2c_transfer);
+
+/**
+ * @brief send few bytes to a client
+ *
+ * @param client client to send data to
+ * @param buf buffer data
+ * @param count num bytes
+ *
+ * @return result of operation
+ */
+int i2c_master_send(struct i2c_client *client, const char *buf, int count)
+{
+       int ret;
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+
+       dbg_entry("client=%x buf=%x count=%x", (u32) client, (u32) buf,
+                 (u32) count);
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.len = count;
+       msg.buf = (char *)buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
+}
+EXPORT_SYMBOL(i2c_master_send);
+
+/**
+ * @brief read a few bytes from client
+ *
+ * @param client client
+ * @param buf buffer
+ * @param count num bytes to read
+ *
+ * @return result of operation
+ */
+int i2c_master_recv(struct i2c_client *client, char *buf, int count)
+{
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+       int ret;
+
+       dbg_entry("client=%x buf=%x count=%x", (u32) client, (u32) buf,
+                 (u32) count);
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.flags |= I2C_M_RD;
+       msg.len = count;
+       msg.buf = buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
+}
+EXPORT_SYMBOL(i2c_master_recv);
Index: u-boot-v2.git/drivers/i2c/Kconfig
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/drivers/i2c/Kconfig   2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,39 @@
+#
+# I2C subsystem configuration
+#
+
+menuconfig I2C
+       tristate "I2C support"
+       ---help---
+         I2C (pronounce: I-square-C) is a slow serial bus protocol used in
+         many micro controller applications and developed by Philips.  SMBus,
+         or System Management Bus is a subset of the I2C protocol.  More
+         information is contained in the directory <file:Documentation/i2c/>,
+         especially in the file called "summary" there.
+
+         If you want I2C support, you should say Y here and also to the
+         specific driver for your bus adapter(s) below.
+
+         This I2C support can also be built as a module.  If so, the module
+         will be called i2c-core.
+
+if I2C
+
+source drivers/i2c/busses/Kconfig
+
+config I2C_DEBUG_CORE
+       bool "I2C Core debugging messages"
+       help
+         Say Y here if you want the I2C core to produce a bunch of debug
+         messages to the system log.  Select this if you are having a
+         problem with I2C support and want to see more of what is going on.
+
+config I2C_DEBUG_BUS
+       bool "I2C Bus debugging messages"
+       help
+         Say Y here if you want the I2C bus drivers to produce a bunch of
+         debug messages to the system log.  Select this if you are having
+         a problem with I2C support and want to see more of what is going
+         on.
+
+endif # I2C
Index: u-boot-v2.git/drivers/i2c/Makefile
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/drivers/i2c/Makefile  2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,10 @@
+#
+# Makefile for the i2c core.
+#
+
+obj-$(CONFIG_I2C)              += i2c-core.o
+obj-y                          += busses/
+
+ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
Index: u-boot-v2.git/drivers/i2c/busses/Kconfig
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/drivers/i2c/busses/Kconfig    2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,7 @@
+#
+# Sensor device configuration
+#
+
+menu "I2C Hardware Bus support"
+
+endmenu
Index: u-boot-v2.git/drivers/i2c/busses/Makefile
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/drivers/i2c/busses/Makefile   2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,9 @@
+#
+# Makefile for the i2c bus drivers.
+#
+
+obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
+
+ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
Index: u-boot-v2.git/drivers/i2c/i2c-core.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/drivers/i2c/i2c-core.h        2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,37 @@
+/**
+ * @file
+ * @brief - interfaces internal to the I2C framework
+ *
+ * FileName: drivers/i2c/i2c-core.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <x0nishan at ti.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __i2C_CORE_H
+#define  __i2C_CORE_H
+
+/* board_lock protects board_list and first_dynamic_bus_num.
+ * only i2c core components are allowed to use these symbols.
+ */
+extern struct list_head        __i2c_board_list;
+extern int             __i2c_first_dynamic_bus_num;
+
+#endif         /*  __i2C_CORE_H */
Index: u-boot-v2.git/include/linux/i2c.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ u-boot-v2.git/include/linux/i2c.h   2008-06-19 08:42:46.000000000 -0500
@@ -0,0 +1,299 @@
+/**
+ * @file
+ * @brief definitions for the i2c-bus interface
+ *
+ * FileName: include/linux/i2c.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <x0nishan at ti.com>
+ */
+/*   Copyright (C) 1995-2000 Simon G. Vogl
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+/* ------------------------------------------------------------------------- */
+
+/* With some changes from Kyösti MÃ$lkki <kmalkki at cc.hut.fi> and
+   Frodo Looijaard <frodol at dds.nl> */
+
+#ifndef _LINUX_I2C_H
+#define _LINUX_I2C_H
+
+#include <linux/types.h>
+#ifdef __U_BOOT__
+#include <module.h>
+#include <linux/mod_devicetable.h>
+#include <driver.h>
+
+/* --- General options ------------------------------------------------        */
+
+struct i2c_msg;
+struct i2c_algorithm;
+struct i2c_adapter;
+struct i2c_client;
+struct i2c_driver;
+
+/**
+ * The master routines are the ones normally used to transmit data to devices
+ * on a bus (or read from them). Apart from two basic transfer functions to
+ * transmit one message at a time, a more complex version can be used to
+ * transmit an arbitrary number of messages without interruption.
+ */
+extern int i2c_master_send(struct i2c_client *, const char *, int);
+extern int i2c_master_recv(struct i2c_client *, char *, int);
+
+/** Transfer num messages.
+ */
+extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,\
+                       int num);
+
+/**
+ * A driver is capable of handling one or more physical devices present on
+ * I2C adapters. This information is used to inform the driver of adapter
+ * events.
+ *
+ * The driver.owner field should be set to the module owner of this driver.
+ * The driver.name field should be set to the name of this driver.
+ *
+ * @warning: U-Boot V2 does not support legacy drivers as defined in Linux
+ * kernel
+ */
+struct i2c_driver {
+       int id;
+
+       /** Standard driver model interfaces, for "new style" i2c drivers.
+        * With the driver model, device enumeration is NEVER done by drivers;
+        * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
+        */
+       int (*probe)(struct i2c_client *, const struct i2c_device_id *);
+       int (*remove)(struct i2c_client *);
+
+       /** a ioctl like command that can be used to perform specific functions
+        * with the device.
+        */
+       int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
+
+       struct driver_d driver;
+       const struct i2c_device_id *id_table;
+};
+#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
+
+/**
+ * struct i2c_client - represent an I2C slave device
+ * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
+ *     I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
+ * @addr: Address used on the I2C bus connected to the parent adapter.
+ * @name: Indicates the type of the device, usually a chip name that's
+ *     generic enough to hide second-sourcing and compatible revisions.
+ * @adapter: manages the bus segment hosting this I2C device
+ * @driver: device's driver, hence pointer to access routines
+ * @dev: Driver model device node for the slave.
+ * @irq: indicates the IRQ generated by this device (if any)
+ * @list: list of active/busy clients (DEPRECATED)
+ * @released: used to synchronize client releases & detaches and references
+ *
+ * An i2c_client identifies a single device (i.e. chip) connected to an
+ * i2c bus. The behaviour exposed to Linux is defined by the driver
+ * managing the device.
+ */
+struct i2c_client {
+       unsigned short flags;           /* div., see below              */
+       unsigned short addr;            /* chip address - NOTE: 7bit    */
+                                       /* addresses are stored in the  */
+                                       /* _LOWER_ 7 bits               */
+       char name[I2C_NAME_SIZE];
+       struct i2c_adapter *adapter;    /* the adapter we sit on        */
+       struct i2c_driver *driver;      /* and our access routines      */
+       struct device_d dev;            /* the device structure         */
+       int irq;                        /* irq issued by device (or -1) */
+       struct list_head list;          /* DEPRECATED */
+};
+#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
+
+extern struct i2c_client *i2c_verify_client(struct device_d *dev);
+
+static inline void *i2c_get_clientdata(struct i2c_client *dev)
+{
+       return (&dev->dev)->platform_data;
+}
+
+static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
+{
+       (&dev->dev)->platform_data = data;
+}
+
+
+/**
+ * The following structs are for those who like to implement new bus drivers:
+ * i2c_algorithm is the interface to a class of hardware solutions which can
+ * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
+ * to name two of the most common.
+ */
+struct i2c_algorithm {
+       /** If an adapter algorithm can't do I2C-level access, set master_xfer
+          to NULL. If an adapter algorithm can do SMBus access, set
+          smbus_xfer. If set to NULL, the SMBus protocol is simulated
+          using common I2C messages */
+       /** master_xfer should return the number of messages successfully
+          processed, or a negative value on error */
+       int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
+                          int num);
+       /* To determine what the adapter supports */
+       u32 (*functionality) (struct i2c_adapter *);
+};
+
+/**
+ * i2c_adapter is the structure used to identify a physical i2c bus along
+ * with the access algorithms necessary to access it.
+ */
+struct i2c_adapter {
+       struct module *owner;
+       unsigned int id;
+       const struct i2c_algorithm *algo; /* the algorithm to access the bus */
+       void *algo_data;
+
+       /* --- administration stuff. */
+       int (*client_register)(struct i2c_client *);
+       int (*client_unregister)(struct i2c_client *);
+
+       int timeout;
+       int retries;
+       struct device_d dev;            /* the adapter device */
+
+       int nr;
+       struct list_head clients;       /* DEPRECATED */
+       char name[48];
+};
+#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
+
+static inline void *i2c_get_adapdata(struct i2c_adapter *dev)
+{
+       return (&dev->dev)->platform_data;
+}
+
+static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
+{
+       (&dev->dev)->platform_data = data;
+}
+
+/*flags for the client struct: */
+#define I2C_CLIENT_PEC 0x04            /* Use Packet Error Checking */
+#define I2C_CLIENT_TEN 0x10            /* we have a ten bit chip address */
+                                       /* Must equal I2C_M_TEN below */
+
+/* ----- functions exported by i2c.o */
+
+/* administration...
+ */
+extern int i2c_add_adapter(struct i2c_adapter *);
+extern int i2c_del_adapter(struct i2c_adapter *);
+extern int i2c_add_numbered_adapter(struct i2c_adapter *);
+
+extern struct i2c_adapter *i2c_get_adapter(int id);
+extern void i2c_put_adapter(struct i2c_adapter *adap);
+
+
+/** Return the functionality mask */
+static inline u32 i2c_get_functionality(struct i2c_adapter *adap)
+{
+       return adap->algo->functionality(adap);
+}
+
+/** Return 1 if adapter supports everything we need, 0 if not. */
+static inline int i2c_check_functionality(struct i2c_adapter *adap, u32 func)
+{
+       return (func & i2c_get_functionality(adap)) == func;
+}
+
+/** Return id number for a specific adapter */
+static inline int i2c_adapter_id(struct i2c_adapter *adap)
+{
+       return adap->nr;
+}
+#endif /* __U_BOOT__ */
+
+/**
+ * struct i2c_msg - an I2C transaction segment beginning with START
+ * @addr: Slave address, either seven or ten bits.  When this is a ten
+ *     bit address, I2C_M_TEN must be set in @flags and the adapter
+ *     must support I2C_FUNC_10BIT_ADDR.
+ * @flags: I2C_M_RD is handled by all adapters.  No other flags may be
+ *     provided unless the adapter exported the relevant I2C_FUNC_*
+ *     flags through i2c_check_functionality().
+ * @len: Number of data bytes in @buf being read from or written to the
+ *     I2C slave address.  For read transactions where I2C_M_RECV_LEN
+ *     is set, the caller guarantees that this buffer can hold up to
+ *     32 bytes in addition to the initial length byte sent by the
+ *     slave (plus, if used, the SMBus PEC); and this value will be
+ *     incremented by the number of block data bytes received.
+ * @buf: The buffer into which data is read, or from which it's written.
+ *
+ * An i2c_msg is the low level representation of one segment of an I2C
+ * transaction.  It is visible to drivers in the @i2c_transfer() procedure,
+ * to userspace from i2c-dev, and to I2C adapter drivers through the
+ * @i2c_adapter. at master_xfer() method.
+ *
+ * Except when I2C "protocol mangling" is used, all I2C adapters implement
+ * the standard rules for I2C transactions.  Each transaction begins with a
+ * START.  That is followed by the slave address, and a bit encoding read
+ * versus write.  Then follow all the data bytes, possibly including a byte
+ * with SMBus PEC.  The transfer terminates with a NAK, or when all those
+ * bytes have been transferred and ACKed.  If this is the last message in a
+ * group, it is followed by a STOP.  Otherwise it is followed by the next
+ * @i2c_msg transaction segment, beginning with a (repeated) START.
+ *
+ * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then
+ * passing certain @flags may have changed those standard protocol behaviors.
+ * Those flags are only for use with broken/nonconforming slaves, and with
+ * adapters which are known to support the specific mangling options they
+ * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR).
+ */
+struct i2c_msg {
+       __u16 addr;     /* slave address                        */
+       __u16 flags;
+#define I2C_M_TEN              0x0010  /* this is a ten bit chip address */
+#define I2C_M_RD               0x0001  /* read data, from slave to master */
+#define I2C_M_NOSTART          0x4000  /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR     0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK       0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NO_RD_ACK                0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_RECV_LEN         0x0400  /* length will be first received byte */
+       __u16 len;              /* msg length                           */
+       __u8 *buf;              /* pointer to msg data                  */
+};
+
+/** To determine what functionality is present */
+
+#define I2C_FUNC_I2C                   0x00000001
+#define I2C_FUNC_10BIT_ADDR            0x00000002
+/** I2C_M_{REV_DIR_ADDR,NOSTART,..} */
+#define I2C_FUNC_PROTOCOL_MANGLING     0x00000004
+
+
+/** SMBus transaction types (size parameter in the above functions)
+   Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK                    0
+#define I2C_SMBUS_BYTE             1
+#define I2C_SMBUS_BYTE_DATA        2
+#define I2C_SMBUS_WORD_DATA        3
+#define I2C_SMBUS_PROC_CALL        4
+#define I2C_SMBUS_BLOCK_DATA       5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN  6
+#define I2C_SMBUS_BLOCK_PROC_CALL   7          /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA    8
+
+#endif /* _LINUX_I2C_H */
Index: u-boot-v2.git/drivers/Kconfig
===================================================================
--- u-boot-v2.git.orig/drivers/Kconfig  2008-06-19 08:40:01.000000000 -0500
+++ u-boot-v2.git/drivers/Kconfig       2008-06-19 08:42:46.000000000 -0500
@@ -3,6 +3,7 @@
 source "drivers/serial/Kconfig"
 source "drivers/net/Kconfig"
 source "drivers/spi/Kconfig"
+source "drivers/i2c/Kconfig"

 menu "flash drivers                 "

Index: u-boot-v2.git/drivers/Makefile
===================================================================
--- u-boot-v2.git.orig/drivers/Makefile 2008-06-19 08:40:01.000000000 -0500
+++ u-boot-v2.git/drivers/Makefile      2008-06-19 08:42:46.000000000 -0500
@@ -2,6 +2,7 @@
 obj-y  += serial/
 obj-y  += nand/
 obj-$(CONFIG_SPI) += spi/
+obj-$(CONFIG_I2C) += i2c/
 obj-$(CONFIG_DRIVER_CFI_OLD) += cfi_flash.o
 obj-$(CONFIG_DRIVER_CFI_NEW) += cfi_flash_new.o
 obj-$(CONFIG_DRIVER_CFI_INTEL) += cfi_flash_intel.o
Index: u-boot-v2.git/include/driver.h
===================================================================
--- u-boot-v2.git.orig/include/driver.h 2008-06-19 08:40:00.000000000 -0500
+++ u-boot-v2.git/include/driver.h      2008-06-19 08:42:46.000000000 -0500
@@ -34,7 +34,9 @@
 #define DEVICE_TYPE_BLOCK      4
 #define DEVICE_TYPE_FS         5
 #define DEVICE_TYPE_MIIPHY     6
-#define MAX_DEVICE_TYPE         6
+#define DEVICE_TYPE_I2C                7
+#define DEVICE_TYPE_I2CDEV     8
+#define MAX_DEVICE_TYPE         8

 #include <param.h>





More information about the U-Boot mailing list