#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/idr.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
static LIST_HEAD(adapters);
static LIST_HEAD(drivers);
static DECLARE_MUTEX(core_lists);
+static DEFINE_IDR(i2c_adapter_idr);
-int i2c_device_probe(struct device *dev)
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int i2c_bus_suspend(struct device * dev, pm_message_t state)
+{
+ int rc = 0;
+
+ if (dev->driver && dev->driver->suspend)
+ rc = dev->driver->suspend(dev,state,0);
+ return rc;
+}
+
+static int i2c_bus_resume(struct device * dev)
+{
+ int rc = 0;
+
+ if (dev->driver && dev->driver->resume)
+ rc = dev->driver->resume(dev,0);
+ return rc;
+}
+
+static struct bus_type i2c_bus_type = {
+ .name = "i2c",
+ .match = i2c_device_match,
+ .suspend = i2c_bus_suspend,
+ .resume = i2c_bus_resume,
+};
+
+static int i2c_device_probe(struct device *dev)
{
return -ENODEV;
}
-int i2c_device_remove(struct device *dev)
+static int i2c_device_remove(struct device *dev)
{
return 0;
}
*/
int i2c_add_adapter(struct i2c_adapter *adap)
{
- static int nr = 0;
+ int id, res = 0;
struct list_head *item;
struct i2c_driver *driver;
down(&core_lists);
- adap->nr = nr++;
+ if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
+ res = -ENOMEM;
+ goto out_unlock;
+ }
+
+ res = idr_get_new(&i2c_adapter_idr, NULL, &id);
+ if (res < 0) {
+ if (res == -EAGAIN)
+ res = -ENOMEM;
+ goto out_unlock;
+ }
+
+ adap->nr = id & MAX_ID_MASK;
init_MUTEX(&adap->bus_lock);
init_MUTEX(&adap->clist_lock);
list_add_tail(&adap->list,&adapters);
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
}
- up(&core_lists);
dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
- return 0;
+
+out_unlock:
+ up(&core_lists);
+ return res;
}
int i2c_del_adapter(struct i2c_adapter *adap)
{
struct list_head *item, *_n;
+ struct i2c_adapter *adap_from_list;
struct i2c_driver *driver;
struct i2c_client *client;
int res = 0;
down(&core_lists);
+ /* First make sure that this adapter was ever added */
+ list_for_each_entry(adap_from_list, &adapters, list) {
+ if (adap_from_list == adap)
+ break;
+ }
+ if (adap_from_list != adap) {
+ pr_debug("I2C: Attempting to delete an unregistered "
+ "adapter\n");
+ res = -EINVAL;
+ goto out_unlock;
+ }
+
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
if (driver->detach_adapter)
wait_for_completion(&adap->dev_released);
wait_for_completion(&adap->class_dev_released);
+ /* free dynamically allocated bus id */
+ idr_remove(&i2c_adapter_idr, adap->nr);
+
dev_dbg(&adap->dev, "adapter unregistered\n");
out_unlock:
up(&adap->clist_lock);
}
-
-/* match always succeeds, as we want the probe() to tell if we really accept this match */
-static int i2c_device_match(struct device *dev, struct device_driver *drv)
-{
- return 1;
-}
-
-struct bus_type i2c_bus_type = {
- .name = "i2c",
- .match = i2c_device_match,
-};
-
static int __init i2c_init(void)
{
int retval;
* ----------------------------------------------------
*/
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
+int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
{
int ret;
if (adap->algo->master_xfer) {
- dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num);
+#ifdef DEBUG
+ for (ret = 0; ret < num; ret++) {
+ dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
+ "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
+ 'R' : 'W', msgs[ret].addr, msgs[ret].len);
+ }
+#endif
down(&adap->bus_lock);
ret = adap->algo->master_xfer(adap,msgs,num);
at all */
found = 0;
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
+ for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
if (((adap_id == address_data->force[i]) ||
(address_data->force[i] == ANY_I2C_BUS)) &&
(addr == address_data->force[i+1])) {
if (addr == address_data->normal_i2c[i]) {
found = 1;
dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
- "addr %02x", adap_id,addr);
+ "addr %02x\n", adap_id, addr);
}
}
/* CRC over count bytes in the first array plus the bytes in the rest
array if it is non-null. rest[0] is the (length of rest) - 1
and is included. */
-u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
{
int i;
return crc;
}
-u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
{
return i2c_smbus_partial_pec(0, count, first, rest);
}
/* Returns new "size" (transaction type)
Note that we convert byte to byte_data and byte_data to word_data
rather than invent new xxx_PEC transactions. */
-int i2c_smbus_add_pec(u16 addr, u8 command, int size,
- union i2c_smbus_data *data)
+static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
+ union i2c_smbus_data *data)
{
u8 buf[3];
return size;
}
-int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
- union i2c_smbus_data *data)
+static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
+ union i2c_smbus_data *data)
{
u8 buf[3], rpec, cpec;
I2C_SMBUS_WORD_DATA,&data);
}
-s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
-{
- union i2c_smbus_data data;
- data.word = value;
- if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
- I2C_SMBUS_PROC_CALL, &data))
- return -1;
- else
- return 0x0FFFF & data.word;
-}
-
-/* Returns the number of read bytes */
-s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values)
-{
- union i2c_smbus_data data;
- int i;
- if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command,
- I2C_SMBUS_BLOCK_DATA,&data))
- return -1;
- else {
- for (i = 1; i <= data.block[0]; i++)
- values[i-1] = data.block[i];
- return data.block[0];
- }
-}
-
-s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
+ u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
data.block[i] = values[i-1];
data.block[0] = length;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
- I2C_SMBUS_BLOCK_DATA,&data);
-}
-
-/* Returns the number of read bytes */
-s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values)
-{
- union i2c_smbus_data data;
- int i;
- if (length > I2C_SMBUS_BLOCK_MAX - 1)
- return -1;
- data.block[0] = length;
- for (i = 1; i <= length; i++)
- data.block[i] = values[i-1];
- if(i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE, command,
- I2C_SMBUS_BLOCK_PROC_CALL, &data))
- return -1;
- for (i = 1; i <= data.block[0]; i++)
- values[i-1] = data.block[i];
- return data.block[0];
+ I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_DATA,&data);
}
/* Returns the number of read bytes */
}
}
-s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
-{
- union i2c_smbus_data data;
- int i;
- if (length > I2C_SMBUS_I2C_BLOCK_MAX)
- length = I2C_SMBUS_I2C_BLOCK_MAX;
- for (i = 1; i <= length; i++)
- data.block[i] = values[i-1];
- data.block[0] = length;
- return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
- I2C_SMBUS_I2C_BLOCK_DATA,&data);
-}
-
/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
}
-/* You should always define `functionality'; the 'else' is just for
- backward compatibility. */
-u32 i2c_get_functionality (struct i2c_adapter *adap)
-{
- if (adap->algo->functionality)
- return adap->algo->functionality(adap);
- else
- return 0xffffffff;
-}
-
-int i2c_check_functionality (struct i2c_adapter *adap, u32 func)
-{
- u32 adap_func = i2c_get_functionality (adap);
- return (func & adap_func) == func;
-}
-
EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
EXPORT_SYMBOL(i2c_add_driver);
EXPORT_SYMBOL(i2c_smbus_write_byte_data);
EXPORT_SYMBOL(i2c_smbus_read_word_data);
EXPORT_SYMBOL(i2c_smbus_write_word_data);
-EXPORT_SYMBOL(i2c_smbus_process_call);
-EXPORT_SYMBOL(i2c_smbus_read_block_data);
EXPORT_SYMBOL(i2c_smbus_write_block_data);
EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
-EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
-
-EXPORT_SYMBOL(i2c_get_functionality);
-EXPORT_SYMBOL(i2c_check_functionality);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");