[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