| /* |
| * Copyright (C) 2009 Marc Kleine-Budde <mkl@pengutronix.de> |
| * |
| * This file is released under the GPLv2 |
| * |
| * Derived from: |
| * - i2c-core.c - a device driver for the iic-bus interface |
| * Copyright (C) 1995-99 Simon G. Vogl |
| * - at24.c - handle most I2C EEPROMs |
| * Copyright (C) 2005-2007 David Brownell |
| * Copyright (C) 2008 Wolfram Sang, Pengutronix |
| * - spi.c - barebox SPI Framework |
| * Copyright (C) 2008 Sascha Hauer, Pengutronix |
| * - Linux SPI Framework |
| * Copyright (C) 2005 David Brownell |
| * |
| */ |
| |
| #include <clock.h> |
| #include <common.h> |
| #include <errno.h> |
| #include <malloc.h> |
| #include <xfuncs.h> |
| |
| #include <i2c/i2c.h> |
| |
| /** |
| * I2C devices should normally not be created by I2C device drivers; |
| * that would make them board-specific. Similarly with I2C master |
| * drivers. Device registration normally goes into like |
| * arch/.../mach.../board-YYY.c with other readonly (flashable) |
| * information about mainboard devices. |
| */ |
| struct boardinfo { |
| struct list_head list; |
| unsigned int bus_num; |
| unsigned int n_board_info; |
| struct i2c_board_info board_info[0]; |
| }; |
| |
| static LIST_HEAD(board_list); |
| static LIST_HEAD(adapter_list); |
| |
| /** |
| * i2c_transfer - execute a single or combined I2C message |
| * @param adap Handle to I2C bus |
| * @param msgs One or more messages to execute before STOP is |
| * issued to terminate the operation; each |
| * message begins with a START. |
| * |
| * @param num Number of messages to be executed. |
| * |
| * Returns negative errno, else the number of messages executed. |
| * |
| * Note that there is no requirement that each message be sent to the |
| * same slave address, although that is the most common model. |
| */ |
| int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
| { |
| uint64_t start; |
| int ret, try; |
| |
| /* |
| * REVISIT the fault reporting model here is weak: |
| * |
| * - When we get an error after receiving N bytes from a slave, |
| * there is no way to report "N". |
| * |
| * - When we get a NAK after transmitting N bytes to a slave, |
| * there is no way to report "N" ... or to let the master |
| * continue executing the rest of this combined message, if |
| * that's the appropriate response. |
| * |
| * - When for example "num" is two and we successfully complete |
| * the first message but get an error part way through the |
| * second, it's unclear whether that should be reported as |
| * one (discarding status on the second message) or errno |
| * (discarding status on the first one). |
| */ |
| |
| 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); |
| } |
| |
| /* Retry automatically on arbitration loss */ |
| start = get_time_ns(); |
| for (ret = 0, try = 0; try <= 2; try++) { |
| ret = adap->master_xfer(adap, msgs, num); |
| if (ret != -EAGAIN) |
| break; |
| if (is_timeout(start, SECOND >> 1)) |
| break; |
| } |
| |
| return ret; |
| } |
| EXPORT_SYMBOL(i2c_transfer); |
| |
| /** |
| * i2c_master_send - issue a single I2C message in master transmit mode |
| * |
| * @param client Handle to slave device |
| * @param buf Data that will be written to the slave |
| * @param count How many bytes to write |
| * |
| * Returns negative errno, or else the number of bytes written. |
| */ |
| int i2c_master_send(struct i2c_client *client, const char *buf, int count) |
| { |
| struct i2c_adapter *adap = client->adapter; |
| struct i2c_msg msg; |
| int ret; |
| |
| msg.addr = client->addr; |
| 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); |
| |
| /** |
| * i2c_master_recv - issue a single I2C message in master receive mode |
| * |
| * @param client Handle to slave device |
| * @param buf Where to store data read from slave |
| * @param count How many bytes to read |
| * |
| * Returns negative errno, or else the number of bytes read. |
| */ |
| int i2c_master_recv(struct i2c_client *client, char *buf, int count) |
| { |
| struct i2c_adapter *adap = client->adapter; |
| struct i2c_msg msg; |
| int ret; |
| |
| msg.addr = client->addr; |
| 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); |
| |
| int i2c_read_reg(struct i2c_client *client, u32 addr, u8 *buf, u16 count) |
| { |
| u8 msgbuf[2]; |
| struct i2c_msg msg[] = { |
| { |
| .addr = client->addr, |
| .buf = msgbuf, |
| }, |
| { |
| .addr = client->addr, |
| .flags = I2C_M_RD, |
| .buf = buf, |
| .len = count, |
| }, |
| }; |
| int status, i; |
| |
| i = 0; |
| if (addr & I2C_ADDR_16_BIT) |
| msgbuf[i++] = addr >> 8; |
| msgbuf[i++] = addr; |
| msg->len = i; |
| |
| status = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); |
| dev_dbg(&client->dev, "%s: %zu@%d --> %d\n", __func__, |
| count, addr, status); |
| |
| if (status == ARRAY_SIZE(msg)) |
| return count; |
| else if (status >= 0) |
| return -EIO; |
| else |
| return status; |
| } |
| EXPORT_SYMBOL(i2c_read_reg); |
| |
| int i2c_write_reg(struct i2c_client *client, u32 addr, const u8 *buf, u16 count) |
| { |
| u8 msgbuf[256]; /* FIXME */ |
| struct i2c_msg msg[] = { |
| { |
| .addr = client->addr, |
| .buf = msgbuf, |
| .len = count, |
| } |
| }; |
| int status, i; |
| |
| i = 0; |
| if (addr & I2C_ADDR_16_BIT) |
| msgbuf[i++] = addr >> 8; |
| msgbuf[i++] = addr; |
| msg->len += i; |
| |
| memcpy(msg->buf + i, buf, count); |
| |
| status = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); |
| dev_dbg(&client->dev, "%s: %u@%d --> %d\n", __func__, |
| count, addr, status); |
| |
| if (status == ARRAY_SIZE(msg)) |
| return count; |
| else if (status >= 0) |
| return -EIO; |
| else |
| return status; |
| } |
| EXPORT_SYMBOL(i2c_write_reg); |
| |
| /** |
| * i2c_new_device - instantiate one new I2C device |
| * |
| * @param adapter Controller to which device is connected |
| * @param chip Describes the I2C device |
| * |
| * On typical mainboards, this is purely internal; and it's not needed |
| * after board init creates the hard-wired devices. Some development |
| * platforms may not be able to use i2c_register_board_info though, |
| * and this is exported so that for example a USB or parport based |
| * adapter driver could add devices (which it would learn about |
| * out-of-band). |
| * |
| * Returns the new device, or NULL. |
| */ |
| struct i2c_client *i2c_new_device(struct i2c_adapter *adapter, |
| struct i2c_board_info *chip) |
| { |
| struct i2c_client *client; |
| int status; |
| |
| client = xzalloc(sizeof *client); |
| strcpy(client->dev.name, chip->type); |
| client->dev.type_data = client; |
| client->adapter = adapter; |
| client->addr = chip->addr; |
| |
| status = register_device(&client->dev); |
| |
| #if 0 |
| /* drivers may modify this initial i/o setup */ |
| status = master->setup(client); |
| if (status < 0) { |
| printf("can't setup %s, status %d\n", |
| client->dev.name, status); |
| goto fail; |
| } |
| #endif |
| |
| return client; |
| |
| #if 0 |
| fail: |
| free(proxy); |
| return NULL; |
| #endif |
| } |
| EXPORT_SYMBOL(i2c_new_device); |
| |
| /** |
| * i2c_register_board_info - register I2C devices for a given board |
| * |
| * @param info array of chip descriptors |
| * @param n how many descriptors are provided |
| * |
| * Board-specific early init code calls this (probably during |
| * arch_initcall) with segments of the I2C device table. |
| * |
| * Other code can also call this, e.g. a particular add-on board might |
| * provide I2C devices through its expansion connector, so code |
| * initializing that board would naturally declare its I2C devices. |
| * |
| */ |
| int i2c_register_board_info(int bus_num, struct i2c_board_info const *info, unsigned n) |
| { |
| struct boardinfo *bi; |
| |
| bi = xmalloc(sizeof(*bi) + n * sizeof(*info)); |
| |
| bi->n_board_info = n; |
| bi->bus_num = bus_num; |
| memcpy(bi->board_info, info, n * sizeof(*info)); |
| |
| list_add_tail(&bi->list, &board_list); |
| |
| return 0; |
| } |
| |
| static void scan_boardinfo(struct i2c_adapter *adapter) |
| { |
| struct boardinfo *bi; |
| |
| list_for_each_entry(bi, &board_list, list) { |
| struct i2c_board_info *chip = bi->board_info; |
| unsigned n; |
| |
| if (bi->bus_num != adapter->nr) |
| continue; |
| |
| for (n = bi->n_board_info; n > 0; n--, chip++) { |
| debug("%s: bus_num: %d, chip->addr 0x%02x\n", __func__, bi->bus_num, chip->addr); |
| /* |
| * NOTE: this relies on i2c_new_device to |
| * issue diagnostics when given bogus inputs |
| */ |
| (void) i2c_new_device(adapter, chip); |
| } |
| } |
| } |
| |
| /** |
| * |
| * i2c_get_adapter - get an i2c adapter from its busnum |
| * |
| * @param busnum the desired bus number |
| * |
| */ |
| struct i2c_adapter *i2c_get_adapter(int busnum) |
| { |
| struct i2c_adapter *adap; |
| |
| list_for_each_entry(adap, &adapter_list, list) |
| if (adap->nr == busnum) |
| return adap; |
| return NULL; |
| } |
| |
| /** |
| * i2c_add_numbered_adapter - declare i2c adapter, use static bus number |
| * @adapter: the adapter to register (with adap->nr initialized) |
| * |
| * 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. |
| * |
| * 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 *adapter) |
| { |
| if (i2c_get_adapter(adapter->nr)) |
| return -EBUSY; |
| |
| list_add_tail(&adapter->list, &adapter_list); |
| |
| /* populate children from any i2c device tables */ |
| scan_boardinfo(adapter); |
| |
| return 0; |
| } |
| EXPORT_SYMBOL(i2c_add_numbered_adapter); |