diff options
Diffstat (limited to 'drivers/i2c/busses')
25 files changed, 943 insertions, 169 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 5f318ce29770..4cc3807bd31c 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -77,7 +77,7 @@ config I2C_AMD8111 will be called i2c-amd8111. config I2C_I801 - tristate "Intel 82801 (ICH)" + tristate "Intel 82801 (ICH/PCH)" depends on PCI help If you say yes to this option, support will be included for the Intel @@ -97,7 +97,8 @@ config I2C_I801 ICH9 Tolapai ICH10 - PCH + 3400/5 Series (PCH) + Cougar Point (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -564,12 +565,23 @@ config I2C_VERSATILE This driver can also be built as a module. If so, the module will be called i2c-versatile. +config I2C_OCTEON + tristate "Cavium OCTEON I2C bus support" + depends on CPU_CAVIUM_OCTEON + help + Say yes if you want to support the I2C serial bus on Cavium + OCTEON SOC. + + This driver can also be built as a module. If so, the module + will be called i2c-octeon. + comment "External I2C/SMBus adapter drivers" config I2C_PARPORT tristate "Parallel port adapter" depends on PARPORT select I2C_ALGOBIT + select I2C_SMBUS help This supports parallel port I2C adapters such as the ones made by Philips or Velleman, Analog Devices evaluation boards, and more. @@ -593,6 +605,7 @@ config I2C_PARPORT config I2C_PARPORT_LIGHT tristate "Parallel port adapter (light)" select I2C_ALGOBIT + select I2C_SMBUS help This supports parallel port I2C adapters such as the ones made by Philips or Velleman, Analog Devices evaluation boards, and more. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 302c551977bb..c2c4ea1908d8 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o +obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o # External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 8de7d7b87bb0..bd8f1e4d9e6c 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -480,7 +480,7 @@ static struct i2c_adapter ali1535_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id ali1535_ids[] = { +static const struct pci_device_id ali1535_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { }, }; diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 4687af40dd50..a409cfcf0629 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -417,7 +417,7 @@ static void __devexit ali1563_remove(struct pci_dev * dev) ali1563_shutdown(dev); } -static struct pci_device_id __devinitdata ali1563_id_table[] = { +static const struct pci_device_id ali1563_id_table[] __devinitconst = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) }, {}, }; diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index e7e3205f1286..659f63f5e4af 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -477,7 +477,7 @@ static struct i2c_adapter ali15x3_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id ali15x3_ids[] = { +static const struct pci_device_id ali15x3_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 8f0b90ef8c76..c5a9fa488e7f 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -308,7 +308,7 @@ static const char* chipname[] = { "nVidia nForce", "AMD8111", }; -static struct pci_device_id amd756_ids[] = { +static const struct pci_device_id amd756_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), .driver_data = AMD756 }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 5b4ad86ca166..d0dc970d7370 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -351,7 +351,7 @@ static const struct i2c_algorithm smbus_algorithm = { }; -static struct pci_device_id amd8111_ids[] = { +static const struct pci_device_id amd8111_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index 9e18ef97f156..3e72b69aa7f8 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c @@ -497,13 +497,13 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) int i; if (abort_source & DW_IC_TX_ABRT_NOACK) { - for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) + for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) dev_dbg(dev->dev, "%s: %s\n", __func__, abort_sources[i]); return -EREMOTEIO; } - for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) + for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); if (abort_source & DW_IC_TX_ARB_LOST) diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index bec9b845dd16..c767295ad1fb 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -105,7 +105,7 @@ static struct i2c_adapter hydra_adap = { .algo_data = &hydra_bit_data, }; -static struct pci_device_id hydra_ids[] = { +static const struct pci_device_id hydra_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index df6ab553f975..9da5b05cdb52 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -41,7 +41,8 @@ Tolapai 0x5032 32 hard yes yes yes ICH10 0x3a30 32 hard yes yes yes ICH10 0x3a60 32 hard yes yes yes - PCH 0x3b30 32 hard yes yes yes + 3400/5 Series (PCH) 0x3b30 32 hard yes yes yes + Cougar Point (PCH) 0x1c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -561,7 +562,7 @@ static struct i2c_adapter i801_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id i801_ids[] = { +static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, @@ -578,6 +579,7 @@ static struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) }, { 0, } }; @@ -707,6 +709,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id case PCI_DEVICE_ID_INTEL_ICH10_4: case PCI_DEVICE_ID_INTEL_ICH10_5: case PCI_DEVICE_ID_INTEL_PCH_SMBUS: + case PCI_DEVICE_ID_INTEL_CPT_SMBUS: i801_features |= FEATURE_I2C_BLOCK_READ; /* fall through */ case PCI_DEVICE_ID_INTEL_82801DB_3: diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index dba6eb053e2f..69c22f79f231 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -256,7 +256,7 @@ static struct i2c_adapter sch_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id sch_ids[] = { +static const struct pci_device_id sch_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index ec11d1c4e77b..4a700587ef18 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -308,7 +308,7 @@ static struct i2c_algorithm smbus_algorithm = { }; -static struct pci_device_id nforce2_ids[] = { +static const struct pci_device_id nforce2_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c new file mode 100644 index 000000000000..60375504fa49 --- /dev/null +++ b/drivers/i2c/busses/i2c-octeon.c @@ -0,0 +1,651 @@ +/* + * (C) Copyright 2009-2010 + * Nokia Siemens Networks, michael.lawnick.ext@nsn.com + * + * Portions Copyright (C) 2010 Cavium Networks, Inc. + * + * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/init.h> + +#include <linux/io.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/platform_device.h> + +#include <asm/octeon/octeon.h> + +#define DRV_NAME "i2c-octeon" + +/* The previous out-of-tree version was implicitly version 1.0. */ +#define DRV_VERSION "2.0" + +/* register offsets */ +#define SW_TWSI 0x00 +#define TWSI_INT 0x10 + +/* Controller command patterns */ +#define SW_TWSI_V 0x8000000000000000ull +#define SW_TWSI_EOP_TWSI_DATA 0x0C00000100000000ull +#define SW_TWSI_EOP_TWSI_CTL 0x0C00000200000000ull +#define SW_TWSI_EOP_TWSI_CLKCTL 0x0C00000300000000ull +#define SW_TWSI_EOP_TWSI_STAT 0x0C00000300000000ull +#define SW_TWSI_EOP_TWSI_RST 0x0C00000700000000ull +#define SW_TWSI_OP_TWSI_CLK 0x0800000000000000ull +#define SW_TWSI_R 0x0100000000000000ull + +/* Controller command and status bits */ +#define TWSI_CTL_CE 0x80 +#define TWSI_CTL_ENAB 0x40 +#define TWSI_CTL_STA 0x20 +#define TWSI_CTL_STP 0x10 +#define TWSI_CTL_IFLG 0x08 +#define TWSI_CTL_AAK 0x04 + +/* Some status values */ +#define STAT_START 0x08 +#define STAT_RSTART 0x10 +#define STAT_TXADDR_ACK 0x18 +#define STAT_TXDATA_ACK 0x28 +#define STAT_RXADDR_ACK 0x40 +#define STAT_RXDATA_ACK 0x50 +#define STAT_IDLE 0xF8 + +struct octeon_i2c { + wait_queue_head_t queue; + struct i2c_adapter adap; + int irq; + int twsi_freq; + int sys_freq; + resource_size_t twsi_phys; + void __iomem *twsi_base; + resource_size_t regsize; + struct device *dev; +}; + +/** + * octeon_i2c_write_sw - write an I2C core register. + * @i2c: The struct octeon_i2c. + * @eop_reg: Register selector. + * @data: Value to be written. + * + * The I2C core registers are accessed indirectly via the SW_TWSI CSR. + */ +static void octeon_i2c_write_sw(struct octeon_i2c *i2c, + u64 eop_reg, + u8 data) +{ + u64 tmp; + + __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI); + do { + tmp = __raw_readq(i2c->twsi_base + SW_TWSI); + } while ((tmp & SW_TWSI_V) != 0); +} + +/** + * octeon_i2c_read_sw - write an I2C core register. + * @i2c: The struct octeon_i2c. + * @eop_reg: Register selector. + * + * Returns the data. + * + * The I2C core registers are accessed indirectly via the SW_TWSI CSR. + */ +static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg) +{ + u64 tmp; + + __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI); + do { + tmp = __raw_readq(i2c->twsi_base + SW_TWSI); + } while ((tmp & SW_TWSI_V) != 0); + + return tmp & 0xFF; +} + +/** + * octeon_i2c_write_int - write the TWSI_INT register + * @i2c: The struct octeon_i2c. + * @data: Value to be written. + */ +static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) +{ + u64 tmp; + + __raw_writeq(data, i2c->twsi_base + TWSI_INT); + tmp = __raw_readq(i2c->twsi_base + TWSI_INT); +} + +/** + * octeon_i2c_int_enable - enable the TS interrupt. + * @i2c: The struct octeon_i2c. + * + * The interrupt will be asserted when there is non-STAT_IDLE state in + * the SW_TWSI_EOP_TWSI_STAT register. + */ +static void octeon_i2c_int_enable(struct octeon_i2c *i2c) +{ + octeon_i2c_write_int(i2c, 0x40); +} + +/** + * octeon_i2c_int_disable - disable the TS interrupt. + * @i2c: The struct octeon_i2c. + */ +static void octeon_i2c_int_disable(struct octeon_i2c *i2c) +{ + octeon_i2c_write_int(i2c, 0); +} + +/** + * octeon_i2c_unblock - unblock the bus. + * @i2c: The struct octeon_i2c. + * + * If there was a reset while a device was driving 0 to bus, + * bus is blocked. We toggle it free manually by some clock + * cycles and send a stop. + */ +static void octeon_i2c_unblock(struct octeon_i2c *i2c) +{ + int i; + + dev_dbg(i2c->dev, "%s\n", __func__); + for (i = 0; i < 9; i++) { + octeon_i2c_write_int(i2c, 0x0); + udelay(5); + octeon_i2c_write_int(i2c, 0x200); + udelay(5); + } + octeon_i2c_write_int(i2c, 0x300); + udelay(5); + octeon_i2c_write_int(i2c, 0x100); + udelay(5); + octeon_i2c_write_int(i2c, 0x0); +} + +/** + * octeon_i2c_isr - the interrupt service routine. + * @int: The irq, unused. + * @dev_id: Our struct octeon_i2c. + */ +static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) +{ + struct octeon_i2c *i2c = dev_id; + + octeon_i2c_int_disable(i2c); + wake_up_interruptible(&i2c->queue); + + return IRQ_HANDLED; +} + + +static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) +{ + return (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_CTL) & TWSI_CTL_IFLG) != 0; +} + +/** + * octeon_i2c_wait - wait for the IFLG to be set. + * @i2c: The struct octeon_i2c. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_wait(struct octeon_i2c *i2c) +{ + int result; + + octeon_i2c_int_enable(i2c); + + result = wait_event_interruptible_timeout(i2c->queue, + octeon_i2c_test_iflg(i2c), + i2c->adap.timeout); + + octeon_i2c_int_disable(i2c); + + if (result < 0) { + dev_dbg(i2c->dev, "%s: wait interrupted\n", __func__); + return result; + } else if (result == 0) { + dev_dbg(i2c->dev, "%s: timeout\n", __func__); + result = -ETIMEDOUT; + } + + return 0; +} + +/** + * octeon_i2c_start - send START to the bus. + * @i2c: The struct octeon_i2c. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_start(struct octeon_i2c *i2c) +{ + u8 data; + int result; + + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + TWSI_CTL_ENAB | TWSI_CTL_STA); + + result = octeon_i2c_wait(i2c); + if (result) { + if (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT) == STAT_IDLE) { + /* + * Controller refused to send start flag May + * be a client is holding SDA low - let's try + * to free it. + */ + octeon_i2c_unblock(i2c); + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + TWSI_CTL_ENAB | TWSI_CTL_STA); + + result = octeon_i2c_wait(i2c); + } + if (result) + return result; + } + + data = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + if ((data != STAT_START) && (data != STAT_RSTART)) { + dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); + return -EIO; + } + + return 0; +} + +/** + * octeon_i2c_stop - send STOP to the bus. + * @i2c: The struct octeon_i2c. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_stop(struct octeon_i2c *i2c) +{ + u8 data; + + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + TWSI_CTL_ENAB | TWSI_CTL_STP); + + data = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + + if (data != STAT_IDLE) { + dev_err(i2c->dev, "%s: bad status(0x%x)\n", __func__, data); + return -EIO; + } + return 0; +} + +/** + * octeon_i2c_write - send data to the bus. + * @i2c: The struct octeon_i2c. + * @target: Target address. + * @data: Pointer to the data to be sent. + * @length: Length of the data. + * + * The address is sent over the bus, then the data. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_write(struct octeon_i2c *i2c, int target, + const u8 *data, int length) +{ + int i, result; + u8 tmp; + + result = octeon_i2c_start(i2c); + if (result) + return result; + + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, target << 1); + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + + for (i = 0; i < length; i++) { + tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) { + dev_err(i2c->dev, + "%s: bad status before write (0x%x)\n", + __func__, tmp); + return -EIO; + } + + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, data[i]); + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + } + + return 0; +} + +/** + * octeon_i2c_read - receive data from the bus. + * @i2c: The struct octeon_i2c. + * @target: Target address. + * @data: Pointer to the location to store the datae . + * @length: Length of the data. + * + * The address is sent over the bus, then the data is read. + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_read(struct octeon_i2c *i2c, int target, + u8 *data, int length) +{ + int i, result; + u8 tmp; + + if (length < 1) + return -EINVAL; + + result = octeon_i2c_start(i2c); + if (result) + return result; + + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, (target<<1) | 1); + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + + for (i = 0; i < length; i++) { + tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) { + dev_err(i2c->dev, + "%s: bad status before read (0x%x)\n", + __func__, tmp); + return -EIO; + } + + if (i+1 < length) + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + TWSI_CTL_ENAB | TWSI_CTL_AAK); + else + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, + TWSI_CTL_ENAB); + + result = octeon_i2c_wait(i2c); + if (result) + return result; + + data[i] = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_DATA); + } + return 0; +} + +/** + * octeon_i2c_xfer - The driver's master_xfer function. + * @adap: Pointer to the i2c_adapter structure. + * @msgs: Pointer to the messages to be processed. + * @num: Length of the MSGS array. + * + * Returns the number of messages processed, or a negative errno on + * failure. + */ +static int octeon_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, + int num) +{ + struct i2c_msg *pmsg; + int i; + int ret = 0; + struct octeon_i2c *i2c = i2c_get_adapdata(adap); + + for (i = 0; ret == 0 && i < num; i++) { + pmsg = &msgs[i]; + dev_dbg(i2c->dev, + "Doing %s %d byte(s) to/from 0x%02x - %d of %d messages\n", + pmsg->flags & I2C_M_RD ? "read" : "write", + pmsg->len, pmsg->addr, i + 1, num); + if (pmsg->flags & I2C_M_RD) + ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf, + pmsg->len); + else + ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf, + pmsg->len); + } + octeon_i2c_stop(i2c); + + return (ret != 0) ? ret : num; +} + +static u32 octeon_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm octeon_i2c_algo = { + .master_xfer = octeon_i2c_xfer, + .functionality = octeon_i2c_functionality, +}; + +static struct i2c_adapter octeon_i2c_ops = { + .owner = THIS_MODULE, + .name = "OCTEON adapter", + .algo = &octeon_i2c_algo, + .timeout = 2, +}; + +/** + * octeon_i2c_setclock - Calculate and set clock divisors. + */ +static int __init octeon_i2c_setclock(struct octeon_i2c *i2c) +{ + int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; + int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; + + for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) { + /* + * An mdiv value of less than 2 seems to not work well + * with ds1337 RTCs, so we constrain it to larger + * values. + */ + for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) { + /* + * For given ndiv and mdiv values check the + * two closest thp values. + */ + tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10; + tclk *= (1 << ndiv_idx); + thp_base = (i2c->sys_freq / (tclk * 2)) - 1; + for (inc = 0; inc <= 1; inc++) { + thp_idx = thp_base + inc; + if (thp_idx < 5 || thp_idx > 0xff) + continue; + + foscl = i2c->sys_freq / (2 * (thp_idx + 1)); + foscl = foscl / (1 << ndiv_idx); + foscl = foscl / (mdiv_idx + 1) / 10; + diff = abs(foscl - i2c->twsi_freq); + if (diff < delta_hz) { + delta_hz = diff; + thp = thp_idx; + mdiv = mdiv_idx; + ndiv = ndiv_idx; + } + } + } + } + octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp); + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); + + return 0; +} + +static int __init octeon_i2c_initlowlevel(struct octeon_i2c *i2c) +{ + u8 status; + int tries; + + /* disable high level controller, enable bus access */ + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); + + /* reset controller */ + octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0); + + for (tries = 10; tries; tries--) { + udelay(1); + status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); + if (status == STAT_IDLE) + return 0; + } + dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status); + return -EIO; +} + +static int __devinit octeon_i2c_probe(struct platform_device *pdev) +{ + int irq, result = 0; + struct octeon_i2c *i2c; + struct octeon_i2c_data *i2c_data; + struct resource *res_mem; + + /* All adaptors have an irq. */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + if (!i2c) { + dev_err(&pdev->dev, "kzalloc failed\n"); + result = -ENOMEM; + goto out; + } + i2c->dev = &pdev->dev; + i2c_data = pdev->dev.platform_data; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (res_mem == NULL) { + dev_err(i2c->dev, "found no memory resource\n"); + result = -ENXIO; + goto fail_region; + } + + if (i2c_data == NULL) { + dev_err(i2c->dev, "no I2C frequency data\n"); + result = -ENXIO; + goto fail_region; + } + + i2c->twsi_phys = res_mem->start; + i2c->regsize = resource_size(res_mem); + i2c->twsi_freq = i2c_data->i2c_freq; + i2c->sys_freq = i2c_data->sys_freq; + + if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) { + dev_err(i2c->dev, "request_mem_region failed\n"); + goto fail_region; + } + i2c->twsi_base = ioremap(i2c->twsi_phys, i2c->regsize); + + init_waitqueue_head(&i2c->queue); + + i2c->irq = irq; + + result = request_irq(i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c); + if (result < 0) { + dev_err(i2c->dev, "failed to attach interrupt\n"); + goto fail_irq; + } + + result = octeon_i2c_initlowlevel(i2c); + if (result) { + dev_err(i2c->dev, "init low level failed\n"); + goto fail_add; + } + + result = octeon_i2c_setclock(i2c); + if (result) { + dev_err(i2c->dev, "clock init failed\n"); + goto fail_add; + } + + i2c->adap = octeon_i2c_ops; + i2c->adap.dev.parent = &pdev->dev; + i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; + i2c_set_adapdata(&i2c->adap, i2c); + platform_set_drvdata(pdev, i2c); + + result = i2c_add_numbered_adapter(&i2c->adap); + if (result < 0) { + dev_err(i2c->dev, "failed to add adapter\n"); + goto fail_add; + } + + dev_info(i2c->dev, "version %s\n", DRV_VERSION); + + return result; + +fail_add: + platform_set_drvdata(pdev, NULL); + free_irq(i2c->irq, i2c); +fail_irq: + iounmap(i2c->twsi_base); + release_mem_region(i2c->twsi_phys, i2c->regsize); +fail_region: + kfree(i2c); +out: + return result; +}; + +static int __devexit octeon_i2c_remove(struct platform_device *pdev) +{ + struct octeon_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adap); + platform_set_drvdata(pdev, NULL); + free_irq(i2c->irq, i2c); + iounmap(i2c->twsi_base); + release_mem_region(i2c->twsi_phys, i2c->regsize); + kfree(i2c); + return 0; +}; + +static struct platform_driver octeon_i2c_driver = { + .probe = octeon_i2c_probe, + .remove = __devexit_p(octeon_i2c_remove), + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, +}; + +static int __init octeon_i2c_init(void) +{ + int rv; + + rv = platform_driver_register(&octeon_i2c_driver); + return rv; +} + +static void __exit octeon_i2c_exit(void) +{ + platform_driver_unregister(&octeon_i2c_driver); +} + +MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>"); +MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("platform:" DRV_NAME); + +module_init(octeon_i2c_init); +module_exit(octeon_i2c_exit); diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 322c5691e38e..5f41ec0f72d2 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------ * * i2c-parport-light.c I2C bus over parallel port * * ------------------------------------------------------------------------ * - Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> Based on older i2c-velleman.c driver Copyright (C) 1995-2000 Simon G. Vogl @@ -27,10 +27,12 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/delay.h> #include <linux/platform_device.h> #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> +#include <linux/i2c-smbus.h> #include <asm/io.h> #include "i2c-parport.h" @@ -43,6 +45,10 @@ static u16 base; module_param(base, ushort, 0); MODULE_PARM_DESC(base, "Base I/O address"); +static int irq; +module_param(irq, int, 0); +MODULE_PARM_DESC(irq, "IRQ (optional)"); + /* ----- Low-level parallel port access ----------------------------------- */ static inline void port_write(unsigned char p, unsigned char d) @@ -119,6 +125,16 @@ static struct i2c_adapter parport_adapter = { .name = "Parallel port adapter (light)", }; +/* SMBus alert support */ +static struct i2c_smbus_alert_setup alert_data = { + .alert_edge_triggered = 1, +}; +static struct i2c_client *ara; +static struct lineop parport_ctrl_irq = { + .val = (1 << 4), + .port = CTRL, +}; + static int __devinit i2c_parport_probe(struct platform_device *pdev) { int err; @@ -127,18 +143,39 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev) parport_setsda(NULL, 1); parport_setscl(NULL, 1); /* Other init if needed (power on...) */ - if (adapter_parm[type].init.val) + if (adapter_parm[type].init.val) { line_set(1, &adapter_parm[type].init); + /* Give powered devices some time to settle */ + msleep(100); + } parport_adapter.dev.parent = &pdev->dev; err = i2c_bit_add_bus(&parport_adapter); - if (err) + if (err) { dev_err(&pdev->dev, "Unable to register with I2C\n"); - return err; + return err; + } + + /* Setup SMBus alert if supported */ + if (adapter_parm[type].smbus_alert && irq) { + alert_data.irq = irq; + ara = i2c_setup_smbus_alert(&parport_adapter, &alert_data); + if (ara) + line_set(1, &parport_ctrl_irq); + else + dev_warn(&pdev->dev, "Failed to register ARA client\n"); + } + + return 0; } static int __devexit i2c_parport_remove(struct platform_device *pdev) { + if (ara) { + line_set(0, &parport_ctrl_irq); + i2c_unregister_device(ara); + ara = NULL; + } i2c_del_adapter(&parport_adapter); /* Un-init if needed (power off...) */ @@ -205,6 +242,9 @@ static int __init i2c_parport_init(void) if (!request_region(base, 3, DRVNAME)) return -EBUSY; + if (irq != 0) + pr_info(DRVNAME ": using irq %d\n", irq); + if (!adapter_parm[type].getscl.val) parport_algo_data.getscl = NULL; diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 0d8998610c74..220fca7f23a6 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------ * * i2c-parport.c I2C bus over parallel port * * ------------------------------------------------------------------------ * - Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> Based on older i2c-philips-par.c driver Copyright (C) 1995-2000 Simon G. Vogl @@ -27,9 +27,11 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/delay.h> #include <linux/parport.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> +#include <linux/i2c-smbus.h> #include "i2c-parport.h" /* ----- Device list ------------------------------------------------------ */ @@ -38,6 +40,8 @@ struct i2c_par { struct pardevice *pdev; struct i2c_adapter adapter; struct i2c_algo_bit_data algo_data; + struct i2c_smbus_alert_setup alert_data; + struct i2c_client *ara; struct i2c_par *next; }; @@ -143,6 +147,19 @@ static struct i2c_algo_bit_data parport_algo_data = { /* ----- I2c and parallel port call-back functions and structures --------- */ +void i2c_parport_irq(void *data) +{ + struct i2c_par *adapter = data; + struct i2c_client *ara = adapter->ara; + + if (ara) { + dev_dbg(&ara->dev, "SMBus alert received\n"); + i2c_handle_smbus_alert(ara); + } else + dev_dbg(&adapter->adapter.dev, + "SMBus alert received but no ARA client!\n"); +} + static void i2c_parport_attach (struct parport *port) { struct i2c_par *adapter; @@ -154,8 +171,9 @@ static void i2c_parport_attach (struct parport *port) } pr_debug("i2c-parport: attaching to %s\n", port->name); + parport_disable_irq(port); adapter->pdev = parport_register_device(port, "i2c-parport", - NULL, NULL, NULL, PARPORT_FLAG_EXCL, NULL); + NULL, NULL, i2c_parport_irq, PARPORT_FLAG_EXCL, adapter); if (!adapter->pdev) { printk(KERN_ERR "i2c-parport: Unable to register with parport\n"); goto ERROR0; @@ -185,14 +203,29 @@ static void i2c_parport_attach (struct parport *port) parport_setsda(port, 1); parport_setscl(port, 1); /* Other init if needed (power on...) */ - if (adapter_parm[type].init.val) + if (adapter_parm[type].init.val) { line_set(port, 1, &adapter_parm[type].init); + /* Give powered devices some time to settle */ + msleep(100); + } if (i2c_bit_add_bus(&adapter->adapter) < 0) { printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); goto ERROR1; } + /* Setup SMBus alert if supported */ + if (adapter_parm[type].smbus_alert) { + adapter->alert_data.alert_edge_triggered = 1; + adapter->ara = i2c_setup_smbus_alert(&adapter->adapter, + &adapter->alert_data); + if (adapter->ara) + parport_enable_irq(port); + else + printk(KERN_WARNING "i2c-parport: Failed to register " + "ARA client\n"); + } + /* Add the new adapter to the list */ adapter->next = adapter_list; adapter_list = adapter; @@ -213,6 +246,10 @@ static void i2c_parport_detach (struct parport *port) for (prev = NULL, adapter = adapter_list; adapter; prev = adapter, adapter = adapter->next) { if (adapter->pdev->port == port) { + if (adapter->ara) { + parport_disable_irq(port); + i2c_unregister_device(adapter->ara); + } i2c_del_adapter(&adapter->adapter); /* Un-init if needed (power off...) */ diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h index ed69d846cb95..a9f66816546c 100644 --- a/drivers/i2c/busses/i2c-parport.h +++ b/drivers/i2c/busses/i2c-parport.h @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------ * * i2c-parport.h I2C bus over parallel port * * ------------------------------------------------------------------------ * - Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> 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 @@ -38,6 +38,7 @@ struct adapter_parm { struct lineop getsda; struct lineop getscl; struct lineop init; + unsigned int smbus_alert:1; }; static struct adapter_parm adapter_parm[] = { @@ -73,6 +74,7 @@ static struct adapter_parm adapter_parm[] = { .setscl = { 0x01, DATA, 1 }, .getsda = { 0x10, STAT, 1 }, .init = { 0xf0, DATA, 0 }, + .smbus_alert = 1, }, /* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */ { diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index adf0fbb902f0..0d20ff46a518 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -400,7 +400,7 @@ static void __devexit pasemi_smb_remove(struct pci_dev *dev) kfree(smbus); } -static struct pci_device_id pasemi_smb_ids[] = { +static const struct pci_device_id pasemi_smb_ids[] = { { PCI_DEVICE(0x1959, 0xa003) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index e56e4b6823ca..ee9da6fcf69a 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -472,7 +472,7 @@ static struct i2c_adapter piix4_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id piix4_ids[] = { +static const struct pci_device_id piix4_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) }, diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d1c2603a130..2b0bd0b042d6 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -20,15 +20,15 @@ #include <linux/platform_device.h> #include <linux/i2c-pnx.h> #include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> + #include <mach/hardware.h> #include <mach/i2c.h> -#include <asm/irq.h> -#include <asm/uaccess.h> #define I2C_PNX_TIMEOUT 10 /* msec */ #define I2C_PNX_SPEED_KHZ 100 #define I2C_PNX_REGION_SIZE 0x100 -#define PNX_DEFAULT_FREQ 13 /* MHz */ static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) { @@ -50,22 +50,21 @@ static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) return (timeout <= 0); } -static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) +static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *data = adap->algo_data; - struct timer_list *timer = &data->mif.timer; - int expires = I2C_PNX_TIMEOUT / (1000 / HZ); + struct timer_list *timer = &alg_data->mif.timer; + unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT); if (expires <= 1) expires = 2; del_timer_sync(timer); - dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n", + dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n", jiffies, expires); timer->expires = jiffies + expires; - timer->data = (unsigned long)adap; + timer->data = (unsigned long)&alg_data; add_timer(timer); } @@ -77,34 +76,34 @@ static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) * * Generate a START signal in the desired mode. */ -static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) +static int i2c_pnx_start(unsigned char slave_addr, + struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__, + dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__, slave_addr, alg_data->mif.mode); /* Check for 7 bit slave addresses only */ if (slave_addr & ~0x7f) { - dev_err(&adap->dev, "%s: Invalid slave address %x. " - "Only 7-bit addresses are supported\n", - adap->name, slave_addr); + dev_err(&alg_data->adapter.dev, + "%s: Invalid slave address %x. Only 7-bit addresses are supported\n", + alg_data->adapter.name, slave_addr); return -EINVAL; } /* First, make sure bus is idle */ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) { /* Somebody else is monopolizing the bus */ - dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, " - "cntrl = %x, stat = %x\n", - adap->name, slave_addr, - ioread32(I2C_REG_CTL(alg_data)), - ioread32(I2C_REG_STS(alg_data))); + dev_err(&alg_data->adapter.dev, + "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n", + alg_data->adapter.name, slave_addr, + ioread32(I2C_REG_CTL(alg_data)), + ioread32(I2C_REG_STS(alg_data))); return -EBUSY; } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) { /* Sorry, we lost the bus */ - dev_err(&adap->dev, "%s: Arbitration failure. " - "Slave addr = %02x\n", adap->name, slave_addr); + dev_err(&alg_data->adapter.dev, + "%s: Arbitration failure. Slave addr = %02x\n", + alg_data->adapter.name, slave_addr); return -EIO; } @@ -115,14 +114,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); - dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__, + dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__, (slave_addr << 1) | start_bit | alg_data->mif.mode); /* Write the slave address, START bit and R/W bit */ iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode, I2C_REG_TX(alg_data)); - dev_dbg(&adap->dev, "%s(): exit\n", __func__); + dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__); return 0; } @@ -133,13 +132,12 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) * * Generate a STOP signal to terminate the master transaction. */ -static void i2c_pnx_stop(struct i2c_adapter *adap) +static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; /* Only 1 msec max timeout due to interrupt context */ long timeout = 1000; - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); /* Write a STOP bit to TX FIFO */ @@ -153,7 +151,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap) timeout--; } - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); } @@ -163,12 +161,11 @@ static void i2c_pnx_stop(struct i2c_adapter *adap) * * Sends one byte of data to the slave */ -static int i2c_pnx_master_xmit(struct i2c_adapter *adap) +static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; u32 val; - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); if (alg_data->mif.len > 0) { @@ -184,15 +181,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) alg_data->mif.len--; iowrite32(val, I2C_REG_TX(alg_data)); - dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__, - val, alg_data->mif.len + 1); + dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n", + __func__, val, alg_data->mif.len + 1); if (alg_data->mif.len == 0) { if (alg_data->last) { /* Wait until the STOP is seen. */ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&adap->dev, "The bus is still " - "active after timeout\n"); + dev_err(&alg_data->adapter.dev, + "The bus is still active after timeout\n"); } /* Disable master interrupts */ iowrite32(ioread32(I2C_REG_CTL(alg_data)) & @@ -201,14 +198,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) del_timer_sync(&alg_data->mif.timer); - dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): Waking up xfer routine.\n", __func__); complete(&alg_data->mif.complete); } } else if (alg_data->mif.len == 0) { /* zero-sized transfer */ - i2c_pnx_stop(adap); + i2c_pnx_stop(alg_data); /* Disable master interrupts. */ iowrite32(ioread32(I2C_REG_CTL(alg_data)) & @@ -217,13 +215,14 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) /* Stop timer. */ del_timer_sync(&alg_data->mif.timer); - dev_dbg(&adap->dev, "%s(): Waking up xfer routine after " - "zero-xfer.\n", __func__); + dev_dbg(&alg_data->adapter.dev, + "%s(): Waking up xfer routine after zero-xfer.\n", + __func__); complete(&alg_data->mif.complete); } - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); return 0; @@ -235,21 +234,21 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) * * Reads one byte data from the slave */ -static int i2c_pnx_master_rcv(struct i2c_adapter *adap) +static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; unsigned int val = 0; u32 ctl = 0; - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); /* Check, whether there is already data, * or we didn't 'ask' for it yet. */ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - dev_dbg(&adap->dev, "%s(): Write dummy data to fill " - "Rx-fifo...\n", __func__); + dev_dbg(&alg_data->adapter.dev, + "%s(): Write dummy data to fill Rx-fifo...\n", + __func__); if (alg_data->mif.len == 1) { /* Last byte, do not acknowledge next rcv. */ @@ -281,16 +280,16 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap) if (alg_data->mif.len > 0) { val = ioread32(I2C_REG_RX(alg_data)); *alg_data->mif.buf++ = (u8) (val & 0xff); - dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val, - alg_data->mif.len); + dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n", + __func__, val, alg_data->mif.len); alg_data->mif.len--; if (alg_data->mif.len == 0) { if (alg_data->last) /* Wait until the STOP is seen. */ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&adap->dev, "The bus is still " - "active after timeout\n"); + dev_err(&alg_data->adapter.dev, + "The bus is still active after timeout\n"); /* Disable master interrupts */ ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -304,7 +303,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap) } } - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); return 0; @@ -312,11 +311,11 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap) static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) { + struct i2c_pnx_algo_data *alg_data = dev_id; u32 stat, ctl; - struct i2c_adapter *adap = dev_id; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): mstat = %x mctrl = %x, mode = %d\n", __func__, ioread32(I2C_REG_STS(alg_data)), ioread32(I2C_REG_CTL(alg_data)), @@ -339,10 +338,10 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) complete(&alg_data->mif.complete); } else if (stat & mstatus_nai) { /* Slave did not acknowledge, generate a STOP */ - dev_dbg(&adap->dev, "%s(): " - "Slave did not acknowledge, generating a STOP.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): Slave did not acknowledge, generating a STOP.\n", __func__); - i2c_pnx_stop(adap); + i2c_pnx_stop(alg_data); /* Disable master interrupts. */ ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -368,9 +367,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) */ if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) { if (alg_data->mif.mode == I2C_SMBUS_WRITE) { - i2c_pnx_master_xmit(adap); + i2c_pnx_master_xmit(alg_data); } else if (alg_data->mif.mode == I2C_SMBUS_READ) { - i2c_pnx_master_rcv(adap); + i2c_pnx_master_rcv(alg_data); } } } @@ -379,7 +378,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) stat = ioread32(I2C_REG_STS(alg_data)); iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); - dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): exiting, stat = %x ctrl = %x.\n", __func__, ioread32(I2C_REG_STS(alg_data)), ioread32(I2C_REG_CTL(alg_data))); @@ -388,14 +388,13 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) static void i2c_pnx_timeout(unsigned long data) { - struct i2c_adapter *adap = (struct i2c_adapter *)data; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; + struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data; u32 ctl; - dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. " - "Resetting master...\n", - ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data))); + dev_err(&alg_data->adapter.dev, + "Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n", + ioread32(I2C_REG_STS(alg_data)), + ioread32(I2C_REG_CTL(alg_data))); /* Reset master and disable interrupts */ ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -409,15 +408,14 @@ static void i2c_pnx_timeout(unsigned long data) complete(&alg_data->mif.complete); } -static inline void bus_reset_if_active(struct i2c_adapter *adap) +static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; u32 stat; if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) { - dev_err(&adap->dev, + dev_err(&alg_data->adapter.dev, "%s: Bus is still active after xfer. Reset it...\n", - adap->name); + alg_data->adapter.name); iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, I2C_REG_CTL(alg_data)); wait_reset(I2C_PNX_TIMEOUT, alg_data); @@ -451,10 +449,11 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) struct i2c_pnx_algo_data *alg_data = adap->algo_data; u32 stat = ioread32(I2C_REG_STS(alg_data)); - dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): entering: %d messages, stat = %04x.\n", __func__, num, ioread32(I2C_REG_STS(alg_data))); - bus_reset_if_active(adap); + bus_reset_if_active(alg_data); /* Process transactions in a loop. */ for (i = 0; rc >= 0 && i < num; i++) { @@ -464,9 +463,9 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) addr = pmsg->addr; if (pmsg->flags & I2C_M_TEN) { - dev_err(&adap->dev, + dev_err(&alg_data->adapter.dev, "%s: 10 bits addr not supported!\n", - adap->name); + alg_data->adapter.name); rc = -EINVAL; break; } @@ -478,11 +477,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) alg_data->mif.ret = 0; alg_data->last = (i == num - 1); - dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__, - alg_data->mif.mode, - alg_data->mif.len); + dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n", + __func__, alg_data->mif.mode, alg_data->mif.len); - i2c_pnx_arm_timer(adap); + i2c_pnx_arm_timer(alg_data); /* initialize the completion var */ init_completion(&alg_data->mif.complete); @@ -493,7 +491,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) I2C_REG_CTL(alg_data)); /* Put start-code and slave-address on the bus. */ - rc = i2c_pnx_start(addr, adap); + rc = i2c_pnx_start(addr, alg_data); if (rc < 0) break; @@ -502,31 +500,32 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (!(rc = alg_data->mif.ret)) completed++; - dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): Complete, return code = %d.\n", __func__, rc); /* Clear TDI and AFI bits in case they are set. */ if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) { - dev_dbg(&adap->dev, + dev_dbg(&alg_data->adapter.dev, "%s: TDI still set... clearing now.\n", - adap->name); + alg_data->adapter.name); iowrite32(stat, I2C_REG_STS(alg_data)); } if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) { - dev_dbg(&adap->dev, + dev_dbg(&alg_data->adapter.dev, "%s: AFI still set... clearing now.\n", - adap->name); + alg_data->adapter.name); iowrite32(stat, I2C_REG_STS(alg_data)); } } - bus_reset_if_active(adap); + bus_reset_if_active(alg_data); /* Cleanup to be sure... */ alg_data->mif.buf = NULL; alg_data->mif.len = 0; - dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n", __func__, ioread32(I2C_REG_STS(alg_data))); if (completed != num) @@ -545,69 +544,92 @@ static struct i2c_algorithm pnx_algorithm = { .functionality = i2c_pnx_func, }; +#ifdef CONFIG_PM static int i2c_pnx_controller_suspend(struct platform_device *pdev, pm_message_t state) { - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - return i2c_pnx->suspend(pdev, state); + struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + + /* FIXME: shouldn't this be clk_disable? */ + clk_enable(alg_data->clk); + + return 0; } static int i2c_pnx_controller_resume(struct platform_device *pdev) { - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - return i2c_pnx->resume(pdev); + struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + + return clk_enable(alg_data->clk); } +#else +#define i2c_pnx_controller_suspend NULL +#define i2c_pnx_controller_resume NULL +#endif static int __devinit i2c_pnx_probe(struct platform_device *pdev) { unsigned long tmp; int ret = 0; struct i2c_pnx_algo_data *alg_data; - int freq_mhz; + unsigned long freq; struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; - if (!i2c_pnx || !i2c_pnx->adapter) { + if (!i2c_pnx || !i2c_pnx->name) { dev_err(&pdev->dev, "%s: no platform data supplied\n", __func__); ret = -EINVAL; goto out; } - platform_set_drvdata(pdev, i2c_pnx); - - if (i2c_pnx->calculate_input_freq) - freq_mhz = i2c_pnx->calculate_input_freq(pdev); - else { - freq_mhz = PNX_DEFAULT_FREQ; - dev_info(&pdev->dev, "Setting bus frequency to default value: " - "%d MHz\n", freq_mhz); + alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); + if (!alg_data) { + ret = -ENOMEM; + goto err_kzalloc; } - i2c_pnx->adapter->algo = &pnx_algorithm; + platform_set_drvdata(pdev, alg_data); + + strlcpy(alg_data->adapter.name, i2c_pnx->name, + sizeof(alg_data->adapter.name)); + alg_data->adapter.dev.parent = &pdev->dev; + alg_data->adapter.algo = &pnx_algorithm; + alg_data->adapter.algo_data = alg_data; + alg_data->adapter.nr = pdev->id; + alg_data->i2c_pnx = i2c_pnx; + + alg_data->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(alg_data->clk)) { + ret = PTR_ERR(alg_data->clk); + goto out_drvdata; + } - alg_data = i2c_pnx->adapter->algo_data; init_timer(&alg_data->mif.timer); alg_data->mif.timer.function = i2c_pnx_timeout; - alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter; + alg_data->mif.timer.data = (unsigned long)alg_data; /* Register I/O resource */ - if (!request_mem_region(alg_data->base, I2C_PNX_REGION_SIZE, + if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE, pdev->name)) { dev_err(&pdev->dev, "I/O region 0x%08x for I2C already in use.\n", - alg_data->base); + i2c_pnx->base); ret = -ENODEV; - goto out_drvdata; + goto out_clkget; } - if (!(alg_data->ioaddr = - (u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) { + alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE); + if (!alg_data->ioaddr) { dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); ret = -ENOMEM; goto out_release; } - i2c_pnx->set_clock_run(pdev); + ret = clk_enable(alg_data->clk); + if (ret) + goto out_unmap; + + freq = clk_get_rate(alg_data->clk); /* * Clock Divisor High This value is the number of system clocks @@ -620,45 +642,47 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) * the deglitching filter length. */ - tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; + tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; iowrite32(tmp, I2C_REG_CKH(alg_data)); iowrite32(tmp, I2C_REG_CKL(alg_data)); iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data)); if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) { ret = -ENODEV; - goto out_unmap; + goto out_clock; } init_completion(&alg_data->mif.complete); - ret = request_irq(alg_data->irq, i2c_pnx_interrupt, - 0, pdev->name, i2c_pnx->adapter); + ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt, + 0, pdev->name, alg_data); if (ret) goto out_clock; /* Register this adapter with the I2C subsystem */ - i2c_pnx->adapter->dev.parent = &pdev->dev; - i2c_pnx->adapter->nr = pdev->id; - ret = i2c_add_numbered_adapter(i2c_pnx->adapter); + ret = i2c_add_numbered_adapter(&alg_data->adapter); if (ret < 0) { dev_err(&pdev->dev, "I2C: Failed to add bus\n"); goto out_irq; } dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", - i2c_pnx->adapter->name, alg_data->base, alg_data->irq); + alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq); return 0; out_irq: - free_irq(alg_data->irq, i2c_pnx->adapter); + free_irq(i2c_pnx->irq, alg_data); out_clock: - i2c_pnx->set_clock_stop(pdev); + clk_disable(alg_data->clk); out_unmap: - iounmap((void *)alg_data->ioaddr); + iounmap(alg_data->ioaddr); out_release: - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); + release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); +out_clkget: + clk_put(alg_data->clk); out_drvdata: + kfree(alg_data); +err_kzalloc: platform_set_drvdata(pdev, NULL); out: return ret; @@ -666,15 +690,16 @@ out: static int __devexit i2c_pnx_remove(struct platform_device *pdev) { - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - struct i2c_adapter *adap = i2c_pnx->adapter; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - free_irq(alg_data->irq, i2c_pnx->adapter); - i2c_del_adapter(adap); - i2c_pnx->set_clock_stop(pdev); - iounmap((void *)alg_data->ioaddr); - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); + struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx; + + free_irq(i2c_pnx->irq, alg_data); + i2c_del_adapter(&alg_data->adapter); + clk_disable(alg_data->clk); + iounmap(alg_data->ioaddr); + release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); + clk_put(alg_data->clk); + kfree(alg_data); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 844569f7d8b7..55a71370c79b 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -369,7 +369,7 @@ static struct i2c_adapter sis5595_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id sis5595_ids[] __devinitdata = { +static const struct pci_device_id sis5595_ids[] __devinitconst = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 68cff7af7013..2309c7f1bde2 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -468,7 +468,7 @@ static struct i2c_adapter sis630_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id sis630_ids[] __devinitdata = { +static const struct pci_device_id sis630_ids[] __devinitconst = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, { 0, } diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 1649963b00dc..d43d8f8943dd 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -245,7 +245,7 @@ static struct i2c_adapter sis96x_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id sis96x_ids[] = { +static const struct pci_device_id sis96x_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index b1c050ff311d..b5b1bbf37d3c 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/module.h> +#include <linux/types.h> /* include interfaces to usb layer */ #include <linux/usb.h> @@ -30,11 +31,13 @@ #define CMD_I2C_IO_BEGIN (1<<0) #define CMD_I2C_IO_END (1<<1) -/* i2c bit delay, default is 10us -> 100kHz */ -static int delay = 10; -module_param(delay, int, 0); -MODULE_PARM_DESC(delay, "bit delay in microseconds, " - "e.g. 10 for 100kHz (default is 100kHz)"); +/* i2c bit delay, default is 10us -> 100kHz max + (in practice, due to additional delays in the i2c bitbanging + code this results in a i2c clock of about 50kHz) */ +static unsigned short delay = 10; +module_param(delay, ushort, 0); +MODULE_PARM_DESC(delay, "bit delay in microseconds " + "(default is 10us for 100kHz max)"); static int usb_read(struct i2c_adapter *adapter, int cmd, int value, int index, void *data, int len); @@ -109,7 +112,7 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) static u32 usb_func(struct i2c_adapter *adapter) { - u32 func; + __le32 func; /* get functionality from adapter */ if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != @@ -118,7 +121,7 @@ static u32 usb_func(struct i2c_adapter *adapter) return 0; } - return func; + return le32_to_cpu(func); } /* This is the actual algorithm we define */ @@ -136,7 +139,7 @@ static const struct i2c_algorithm usb_algorithm = { * Future Technology Devices International Ltd., later a pair was * bought from EZPrototypes */ -static struct usb_device_id i2c_tiny_usb_table [] = { +static const struct usb_device_id i2c_tiny_usb_table[] = { { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ { } /* Terminating entry */ @@ -216,8 +219,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, "i2c-tiny-usb at bus %03d device %03d", dev->usb_dev->bus->busnum, dev->usb_dev->devnum); - if (usb_write(&dev->adapter, CMD_SET_DELAY, - cpu_to_le16(delay), 0, NULL, 0) != 0) { + if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) { dev_err(&dev->adapter.dev, "failure setting delay to %dus\n", delay); retval = -EIO; diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index 8b24f192103a..de78283bddbe 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c @@ -89,7 +89,7 @@ static struct i2c_adapter vt586b_adapter = { }; -static struct pci_device_id vt586b_ids[] __devinitdata = { +static const struct pci_device_id vt586b_ids[] __devinitconst = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index a84a909e1234..d57292e5dae0 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -444,7 +444,7 @@ release_region: return error; } -static struct pci_device_id vt596_ids[] = { +static const struct pci_device_id vt596_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3), .driver_data = SMBBA1 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3), |