diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 13:28:19 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 13:28:19 -0200 |
commit | 734d1ece37fbf3d2ddfc71bc6c69e0fe35f02542 (patch) | |
tree | c4805dd7e746b1feb9e09e9849f3245d0b2c0c6b /drivers/i2c/busses | |
parent | 216c82c6aba63eeb49d7654b448e0d47bea255bb (diff) | |
parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) |
Merge tag 'v3.8-rc3' into v4l_for_linus
Linux 3.8-rc3
* tag 'v3.8-rc3': (11110 commits)
Linux 3.8-rc3
mm: reinstante dropped pmd_trans_splitting() check
cred: Remove tgcred pointer from struct cred
drm/ttm: fix fence locking in ttm_buffer_object_transfer
ARM: clps711x: Fix bad merge of clockevents setup
ARM: highbank: save and restore L2 cache and GIC on suspend
ARM: highbank: add a power request clear
ARM: highbank: fix secondary boot and hotplug
ARM: highbank: fix typos with hignbank in power request functions
ARM: dts: fix highbank cpu mpidr values
ARM: dts: add device_type prop to cpu nodes on Calxeda platforms
drm/prime: drop reference on imported dma-buf come from gem
xen/netfront: improve truesize tracking
ARM: mx5: Fix MX53 flexcan2 clock
ARM: OMAP2+: am33xx-hwmod: Fix wrongly terminated am33xx_usbss_mpu_irqs array
sctp: fix Kconfig bug in default cookie hmac selection
EDAC: Cleanup device deregistering path
EDAC: Fix EDAC Kconfig menu
EDAC: Fix kernel panic on module unloading
ALSA: hda - add mute LED for HP Pavilion 17 (Realtek codec)
...
Diffstat (limited to 'drivers/i2c/busses')
58 files changed, 1881 insertions, 562 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e9df4612b7e..bdca5111eb9 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -337,6 +337,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ help The unit of the TWI clock is kHz. +config I2C_CBUS_GPIO + tristate "CBUS I2C driver" + depends on GENERIC_GPIO + help + Support for CBUS access using I2C API. Mostly relevant for Nokia + Internet Tablets (770, N800 and N810). + + This driver can also be built as a module. If so, the module + will be called i2c-cbus-gpio. + config I2C_CPM tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" depends on (CPM1 || CPM2) && OF_I2C @@ -818,6 +828,16 @@ config I2C_TINY_USB This driver can also be built as a module. If so, the module will be called i2c-tiny-usb. +config I2C_VIPERBOARD + tristate "Viperboard I2C master support" + depends on MFD_VIPERBOARD && USB + help + Say yes here to access the I2C part of the Nano River + Technologies Viperboard as I2C master. + See viperboard API specification and Nano + River Tech's viperboard.h for detailed meaning + of the module parameters. + comment "Other I2C/SMBus bus drivers" config I2C_ACORN diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 395b516ffa0..6181f3ff263 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o +obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o @@ -79,6 +80,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o +obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o # Other I2C/SMBus bus drivers obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 125cd8e0ad2..3f491815e2c 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -139,7 +139,7 @@ static unsigned short ali1535_offset; Note the differences between kernels with the old PCI BIOS interface and newer kernels with the real PCI interface. In compat.h some things are defined to make the transition easier. */ -static int __devinit ali1535_setup(struct pci_dev *dev) +static int ali1535_setup(struct pci_dev *dev) { int retval; unsigned char temp; @@ -502,7 +502,7 @@ static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = { MODULE_DEVICE_TABLE(pci, ali1535_ids); -static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (ali1535_setup(dev)) { dev_warn(&dev->dev, @@ -518,7 +518,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_ return i2c_add_adapter(&ali1535_adapter); } -static void __devexit ali1535_remove(struct pci_dev *dev) +static void ali1535_remove(struct pci_dev *dev) { i2c_del_adapter(&ali1535_adapter); release_region(ali1535_smba, ALI1535_SMB_IOSIZE); @@ -528,7 +528,7 @@ static struct pci_driver ali1535_driver = { .name = "ali1535_smbus", .id_table = ali1535_ids, .probe = ali1535_probe, - .remove = __devexit_p(ali1535_remove), + .remove = ali1535_remove, }; module_pci_driver(ali1535_driver); diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index e02d9f86c6a..84ccd9496a5 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -326,7 +326,7 @@ static u32 ali1563_func(struct i2c_adapter * a) } -static int __devinit ali1563_setup(struct pci_dev * dev) +static int ali1563_setup(struct pci_dev *dev) { u16 ctrl; @@ -390,8 +390,8 @@ static struct i2c_adapter ali1563_adapter = { .algo = &ali1563_algorithm, }; -static int __devinit ali1563_probe(struct pci_dev * dev, - const struct pci_device_id * id_table) +static int ali1563_probe(struct pci_dev *dev, + const struct pci_device_id *id_table) { int error; @@ -411,7 +411,7 @@ exit: return error; } -static void __devexit ali1563_remove(struct pci_dev * dev) +static void ali1563_remove(struct pci_dev *dev) { i2c_del_adapter(&ali1563_adapter); ali1563_shutdown(dev); @@ -428,7 +428,7 @@ static struct pci_driver ali1563_pci_driver = { .name = "ali1563_smbus", .id_table = ali1563_id_table, .probe = ali1563_probe, - .remove = __devexit_p(ali1563_remove), + .remove = ali1563_remove, }; module_pci_driver(ali1563_pci_driver); diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index ce8d26d053a..26bcc6127ce 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -131,7 +131,7 @@ MODULE_PARM_DESC(force_addr, static struct pci_driver ali15x3_driver; static unsigned short ali15x3_smba; -static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev) +static int ali15x3_setup(struct pci_dev *ALI15X3_dev) { u16 a; unsigned char temp; @@ -484,7 +484,7 @@ static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = { MODULE_DEVICE_TABLE (pci, ali15x3_ids); -static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (ali15x3_setup(dev)) { dev_err(&dev->dev, @@ -500,7 +500,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_ return i2c_add_adapter(&ali15x3_adapter); } -static void __devexit ali15x3_remove(struct pci_dev *dev) +static void ali15x3_remove(struct pci_dev *dev) { i2c_del_adapter(&ali15x3_adapter); release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); @@ -510,7 +510,7 @@ static struct pci_driver ali15x3_driver = { .name = "ali15x3_smbus", .id_table = ali15x3_ids, .probe = ali15x3_probe, - .remove = __devexit_p(ali15x3_remove), + .remove = ali15x3_remove, }; module_pci_driver(ali15x3_driver); diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 304aa03b57b..e13e2aa2d05 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -324,8 +324,7 @@ static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = { MODULE_DEVICE_TABLE (pci, amd756_ids); -static int __devinit amd756_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int nforce = (id->driver_data == NFORCE); int error; @@ -397,7 +396,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev, return error; } -static void __devexit amd756_remove(struct pci_dev *dev) +static void amd756_remove(struct pci_dev *dev) { i2c_del_adapter(&amd756_smbus); release_region(amd756_ioport, SMB_IOSIZE); @@ -407,7 +406,7 @@ static struct pci_driver amd756_driver = { .name = "amd756_smbus", .id_table = amd756_ids, .probe = amd756_probe, - .remove = __devexit_p(amd756_remove), + .remove = amd756_remove, }; module_pci_driver(amd756_driver); diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 0919ac1d99a..a44e6e77c5a 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -422,8 +422,7 @@ static DEFINE_PCI_DEVICE_TABLE(amd8111_ids) = { MODULE_DEVICE_TABLE (pci, amd8111_ids); -static int __devinit amd8111_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct amd_smbus *smbus; int error; @@ -475,7 +474,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev, return error; } -static void __devexit amd8111_remove(struct pci_dev *dev) +static void amd8111_remove(struct pci_dev *dev) { struct amd_smbus *smbus = pci_get_drvdata(dev); @@ -488,7 +487,7 @@ static struct pci_driver amd8111_driver = { .name = "amd8111_smbus2", .id_table = amd8111_ids, .probe = amd8111_probe, - .remove = __devexit_p(amd8111_remove), + .remove = amd8111_remove, }; module_pci_driver(amd8111_driver); diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index c02bf208084..2bfc04d0a1b 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -19,6 +19,8 @@ #include <linux/clk.h> #include <linux/completion.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> #include <linux/err.h> #include <linux/i2c.h> #include <linux/interrupt.h> @@ -29,9 +31,11 @@ #include <linux/of_i2c.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/platform_data/dma-atmel.h> #define TWI_CLK_HZ 100000 /* max 400 Kbits/s */ #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ +#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */ /* AT91 TWI register definitions */ #define AT91_TWI_CR 0x0000 /* Control Register */ @@ -66,24 +70,39 @@ #define AT91_TWI_THR 0x0034 /* Transmit Holding Register */ struct at91_twi_pdata { - unsigned clk_max_div; - unsigned clk_offset; - bool has_unre_flag; + unsigned clk_max_div; + unsigned clk_offset; + bool has_unre_flag; + bool has_dma_support; + struct at_dma_slave dma_slave; +}; + +struct at91_twi_dma { + struct dma_chan *chan_rx; + struct dma_chan *chan_tx; + struct scatterlist sg; + struct dma_async_tx_descriptor *data_desc; + enum dma_data_direction direction; + bool buf_mapped; + bool xfer_in_progress; }; struct at91_twi_dev { - struct device *dev; - void __iomem *base; - struct completion cmd_complete; - struct clk *clk; - u8 *buf; - size_t buf_len; - struct i2c_msg *msg; - int irq; - unsigned transfer_status; - struct i2c_adapter adapter; - unsigned twi_cwgr_reg; - struct at91_twi_pdata *pdata; + struct device *dev; + void __iomem *base; + struct completion cmd_complete; + struct clk *clk; + u8 *buf; + size_t buf_len; + struct i2c_msg *msg; + int irq; + unsigned imr; + unsigned transfer_status; + struct i2c_adapter adapter; + unsigned twi_cwgr_reg; + struct at91_twi_pdata *pdata; + bool use_dma; + struct at91_twi_dma dma; }; static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) @@ -102,6 +121,17 @@ static void at91_disable_twi_interrupts(struct at91_twi_dev *dev) AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); } +static void at91_twi_irq_save(struct at91_twi_dev *dev) +{ + dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7; + at91_disable_twi_interrupts(dev); +} + +static void at91_twi_irq_restore(struct at91_twi_dev *dev) +{ + at91_twi_write(dev, AT91_TWI_IER, dev->imr); +} + static void at91_init_twi_bus(struct at91_twi_dev *dev) { at91_disable_twi_interrupts(dev); @@ -115,7 +145,7 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev) * Calculate symmetric clock as stated in datasheet: * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset)) */ -static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk) +static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk) { int ckdiv, cdiv, div; struct at91_twi_pdata *pdata = dev->pdata; @@ -138,6 +168,28 @@ static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk) dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv); } +static void at91_twi_dma_cleanup(struct at91_twi_dev *dev) +{ + struct at91_twi_dma *dma = &dev->dma; + + at91_twi_irq_save(dev); + + if (dma->xfer_in_progress) { + if (dma->direction == DMA_FROM_DEVICE) + dmaengine_terminate_all(dma->chan_rx); + else + dmaengine_terminate_all(dma->chan_tx); + dma->xfer_in_progress = false; + } + if (dma->buf_mapped) { + dma_unmap_single(dev->dev, sg_dma_address(&dma->sg), + dev->buf_len, dma->direction); + dma->buf_mapped = false; + } + + at91_twi_irq_restore(dev); +} + static void at91_twi_write_next_byte(struct at91_twi_dev *dev) { if (dev->buf_len <= 0) @@ -154,6 +206,60 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev) ++dev->buf; } +static void at91_twi_write_data_dma_callback(void *data) +{ + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; + + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), + dev->buf_len, DMA_MEM_TO_DEV); + + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); +} + +static void at91_twi_write_data_dma(struct at91_twi_dev *dev) +{ + dma_addr_t dma_addr; + struct dma_async_tx_descriptor *txdesc; + struct at91_twi_dma *dma = &dev->dma; + struct dma_chan *chan_tx = dma->chan_tx; + + if (dev->buf_len <= 0) + return; + + dma->direction = DMA_TO_DEVICE; + + at91_twi_irq_save(dev); + dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len, + DMA_TO_DEVICE); + if (dma_mapping_error(dev->dev, dma_addr)) { + dev_err(dev->dev, "dma map failed\n"); + return; + } + dma->buf_mapped = true; + at91_twi_irq_restore(dev); + sg_dma_len(&dma->sg) = dev->buf_len; + sg_dma_address(&dma->sg) = dma_addr; + + txdesc = dmaengine_prep_slave_sg(chan_tx, &dma->sg, 1, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!txdesc) { + dev_err(dev->dev, "dma prep slave sg failed\n"); + goto error; + } + + txdesc->callback = at91_twi_write_data_dma_callback; + txdesc->callback_param = dev; + + dma->xfer_in_progress = true; + dmaengine_submit(txdesc); + dma_async_issue_pending(chan_tx); + + return; + +error: + at91_twi_dma_cleanup(dev); +} + static void at91_twi_read_next_byte(struct at91_twi_dev *dev) { if (dev->buf_len <= 0) @@ -179,6 +285,61 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev) ++dev->buf; } +static void at91_twi_read_data_dma_callback(void *data) +{ + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; + + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), + dev->buf_len, DMA_DEV_TO_MEM); + + /* The last two bytes have to be read without using dma */ + dev->buf += dev->buf_len - 2; + dev->buf_len = 2; + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY); +} + +static void at91_twi_read_data_dma(struct at91_twi_dev *dev) +{ + dma_addr_t dma_addr; + struct dma_async_tx_descriptor *rxdesc; + struct at91_twi_dma *dma = &dev->dma; + struct dma_chan *chan_rx = dma->chan_rx; + + dma->direction = DMA_FROM_DEVICE; + + /* Keep in mind that we won't use dma to read the last two bytes */ + at91_twi_irq_save(dev); + dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len - 2, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev->dev, dma_addr)) { + dev_err(dev->dev, "dma map failed\n"); + return; + } + dma->buf_mapped = true; + at91_twi_irq_restore(dev); + dma->sg.dma_address = dma_addr; + sg_dma_len(&dma->sg) = dev->buf_len - 2; + + rxdesc = dmaengine_prep_slave_sg(chan_rx, &dma->sg, 1, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!rxdesc) { + dev_err(dev->dev, "dma prep slave sg failed\n"); + goto error; + } + + rxdesc->callback = at91_twi_read_data_dma_callback; + rxdesc->callback_param = dev; + + dma->xfer_in_progress = true; + dmaengine_submit(rxdesc); + dma_async_issue_pending(dma->chan_rx); + + return; + +error: + at91_twi_dma_cleanup(dev); +} + static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) { struct at91_twi_dev *dev = dev_id; @@ -229,12 +390,36 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN)) start_flags |= AT91_TWI_STOP; at91_twi_write(dev, AT91_TWI_CR, start_flags); - at91_twi_write(dev, AT91_TWI_IER, + /* + * When using dma, the last byte has to be read manually in + * order to not send the stop command too late and then + * to receive extra data. In practice, there are some issues + * if you use the dma to read n-1 bytes because of latency. + * Reading n-2 bytes with dma and the two last ones manually + * seems to be the best solution. + */ + if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { + at91_twi_read_data_dma(dev); + /* + * It is important to enable TXCOMP irq here because + * doing it only when transferring the last two bytes + * will mask NACK errors since TXCOMP is set when a + * NACK occurs. + */ + at91_twi_write(dev, AT91_TWI_IER, + AT91_TWI_TXCOMP); + } else + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP | AT91_TWI_RXRDY); } else { - at91_twi_write_next_byte(dev); - at91_twi_write(dev, AT91_TWI_IER, - AT91_TWI_TXCOMP | AT91_TWI_TXRDY); + if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { + at91_twi_write_data_dma(dev); + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else { + at91_twi_write_next_byte(dev); + at91_twi_write(dev, AT91_TWI_IER, + AT91_TWI_TXCOMP | AT91_TWI_TXRDY); + } } ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, @@ -242,23 +427,31 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) if (ret == 0) { dev_err(dev->dev, "controller timed out\n"); at91_init_twi_bus(dev); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto error; } if (dev->transfer_status & AT91_TWI_NACK) { dev_dbg(dev->dev, "received nack\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto error; } if (dev->transfer_status & AT91_TWI_OVRE) { dev_err(dev->dev, "overrun while reading\n"); - return -EIO; + ret = -EIO; + goto error; } if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) { dev_err(dev->dev, "underrun while writing\n"); - return -EIO; + ret = -EIO; + goto error; } dev_dbg(dev->dev, "transfer complete\n"); return 0; + +error: + at91_twi_dma_cleanup(dev); + return ret; } static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) @@ -329,36 +522,42 @@ static struct at91_twi_pdata at91rm9200_config = { .clk_max_div = 5, .clk_offset = 3, .has_unre_flag = true, + .has_dma_support = false, }; static struct at91_twi_pdata at91sam9261_config = { .clk_max_div = 5, .clk_offset = 4, .has_unre_flag = false, + .has_dma_support = false, }; static struct at91_twi_pdata at91sam9260_config = { .clk_max_div = 7, .clk_offset = 4, .has_unre_flag = false, + .has_dma_support = false, }; static struct at91_twi_pdata at91sam9g20_config = { .clk_max_div = 7, .clk_offset = 4, .has_unre_flag = false, + .has_dma_support = false, }; static struct at91_twi_pdata at91sam9g10_config = { .clk_max_div = 7, .clk_offset = 4, .has_unre_flag = false, + .has_dma_support = false, }; static struct at91_twi_pdata at91sam9x5_config = { .clk_max_div = 7, .clk_offset = 4, .has_unre_flag = false, + .has_dma_support = true, }; static const struct platform_device_id at91_twi_devtypes[] = { @@ -405,7 +604,91 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids); #define atmel_twi_dt_ids NULL #endif -static struct at91_twi_pdata * __devinit at91_twi_get_driver_data( +static bool filter(struct dma_chan *chan, void *slave) +{ + struct at_dma_slave *sl = slave; + + if (sl->dma_dev == chan->device->dev) { + chan->private = sl; + return true; + } else { + return false; + } +} + +static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr) +{ + int ret = 0; + struct at_dma_slave *sdata; + struct dma_slave_config slave_config; + struct at91_twi_dma *dma = &dev->dma; + + sdata = &dev->pdata->dma_slave; + + memset(&slave_config, 0, sizeof(slave_config)); + slave_config.src_addr = (dma_addr_t)phy_addr + AT91_TWI_RHR; + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.src_maxburst = 1; + slave_config.dst_addr = (dma_addr_t)phy_addr + AT91_TWI_THR; + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.dst_maxburst = 1; + slave_config.device_fc = false; + + if (sdata && sdata->dma_dev) { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma->chan_tx = dma_request_channel(mask, filter, sdata); + if (!dma->chan_tx) { + dev_err(dev->dev, "no DMA channel available for tx\n"); + ret = -EBUSY; + goto error; + } + dma->chan_rx = dma_request_channel(mask, filter, sdata); + if (!dma->chan_rx) { + dev_err(dev->dev, "no DMA channel available for rx\n"); + ret = -EBUSY; + goto error; + } + } else { + ret = -EINVAL; + goto error; + } + + slave_config.direction = DMA_MEM_TO_DEV; + if (dmaengine_slave_config(dma->chan_tx, &slave_config)) { + dev_err(dev->dev, "failed to configure tx channel\n"); + ret = -EINVAL; + goto error; + } + + slave_config.direction = DMA_DEV_TO_MEM; + if (dmaengine_slave_config(dma->chan_rx, &slave_config)) { + dev_err(dev->dev, "failed to configure rx channel\n"); + ret = -EINVAL; + goto error; + } + + sg_init_table(&dma->sg, 1); + dma->buf_mapped = false; + dma->xfer_in_progress = false; + + dev_info(dev->dev, "using %s (tx) and %s (rx) for DMA transfers\n", + dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx)); + + return ret; + +error: + dev_info(dev->dev, "can't use DMA\n"); + if (dma->chan_rx) + dma_release_channel(dma->chan_rx); + if (dma->chan_tx) + dma_release_channel(dma->chan_tx); + return ret; +} + +static struct at91_twi_pdata *at91_twi_get_driver_data( struct platform_device *pdev) { if (pdev->dev.of_node) { @@ -413,16 +696,17 @@ static struct at91_twi_pdata * __devinit at91_twi_get_driver_data( match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node); if (!match) return NULL; - return match->data; + return (struct at91_twi_pdata *)match->data; } return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data; } -static int __devinit at91_twi_probe(struct platform_device *pdev) +static int at91_twi_probe(struct platform_device *pdev) { struct at91_twi_dev *dev; struct resource *mem; int rc; + u32 phy_addr; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) @@ -433,6 +717,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) return -ENODEV; + phy_addr = mem->start; dev->pdata = at91_twi_get_driver_data(pdev); if (!dev->pdata) @@ -462,6 +747,11 @@ static int __devinit at91_twi_probe(struct platform_device *pdev) } clk_prepare_enable(dev->clk); + if (dev->pdata->has_dma_support) { + if (at91_twi_configure_dma(dev, phy_addr) == 0) + dev->use_dma = true; + } + at91_calc_twi_clock(dev, TWI_CLK_HZ); at91_init_twi_bus(dev); @@ -489,7 +779,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev) return 0; } -static int __devexit at91_twi_remove(struct platform_device *pdev) +static int at91_twi_remove(struct platform_device *pdev) { struct at91_twi_dev *dev = platform_get_drvdata(pdev); int rc; @@ -530,7 +820,7 @@ static const struct dev_pm_ops at91_twi_pm = { static struct platform_driver at91_twi_driver = { .probe = at91_twi_probe, - .remove = __devexit_p(at91_twi_remove), + .remove = at91_twi_remove, .id_table = at91_twi_devtypes, .driver = { .name = "at91_i2c", diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index 582d616db34..b278298787d 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -313,7 +313,7 @@ static void i2c_au1550_disable(struct i2c_au1550_data *priv) * Prior to calling us, the 50MHz clock frequency and routing * must have been set up for the PSC indicated by the adapter. */ -static int __devinit +static int i2c_au1550_probe(struct platform_device *pdev) { struct i2c_au1550_data *priv; @@ -372,7 +372,7 @@ out: return ret; } -static int __devexit i2c_au1550_remove(struct platform_device *pdev) +static int i2c_au1550_remove(struct platform_device *pdev) { struct i2c_au1550_data *priv = platform_get_drvdata(pdev); @@ -423,7 +423,7 @@ static struct platform_driver au1xpsc_smbus_driver = { .pm = AU1XPSC_SMBUS_PMOPS, }, .probe = i2c_au1550_probe, - .remove = __devexit_p(i2c_au1550_remove), + .remove = i2c_au1550_remove, }; module_platform_driver(au1xpsc_smbus_driver); diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c new file mode 100644 index 00000000000..98386d65931 --- /dev/null +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -0,0 +1,300 @@ +/* + * CBUS I2C driver for Nokia Internet Tablets. + * + * Copyright (C) 2004-2010 Nokia Corporation + * + * Based on code written by Juha Yrjölä, David Weinehall, Mikko Ylinen and + * Felipe Balbi. Converted to I2C driver by Aaro Koskinen. + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * 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. + */ + +#include <linux/io.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/platform_data/i2c-cbus-gpio.h> + +/* + * Bit counts are derived from Nokia implementation. These should be checked + * if other CBUS implementations appear. + */ +#define CBUS_ADDR_BITS 3 +#define CBUS_REG_BITS 5 + +struct cbus_host { + spinlock_t lock; /* host lock */ + struct device *dev; + int clk_gpio; + int dat_gpio; + int sel_gpio; +}; + +/** + * cbus_send_bit - sends one bit over the bus + * @host: the host we're using + * @bit: one bit of information to send + */ +static void cbus_send_bit(struct cbus_host *host, unsigned bit) +{ + gpio_set_value(host->dat_gpio, bit ? 1 : 0); + gpio_set_value(host->clk_gpio, 1); + gpio_set_value(host->clk_gpio, 0); +} + +/** + * cbus_send_data - sends @len amount of data over the bus + * @host: the host we're using + * @data: the data to send + * @len: size of the transfer + */ +static void cbus_send_data(struct cbus_host *host, unsigned data, unsigned len) +{ + int i; + + for (i = len; i > 0; i--) + cbus_send_bit(host, data & (1 << (i - 1))); +} + +/** + * cbus_receive_bit - receives one bit from the bus + * @host: the host we're using + */ +static int cbus_receive_bit(struct cbus_host *host) +{ + int ret; + + gpio_set_value(host->clk_gpio, 1); + ret = gpio_get_value(host->dat_gpio); + gpio_set_value(host->clk_gpio, 0); + return ret; +} + +/** + * cbus_receive_word - receives 16-bit word from the bus + * @host: the host we're using + */ +static int cbus_receive_word(struct cbus_host *host) +{ + int ret = 0; + int i; + + for (i = 16; i > 0; i--) { + int bit = cbus_receive_bit(host); + + if (bit < 0) + return bit; + + if (bit) + ret |= 1 << (i - 1); + } + return ret; +} + +/** + * cbus_transfer - transfers data over the bus + * @host: the host we're using + * @rw: read/write flag + * @dev: device address + * @reg: register address + * @data: if @rw == I2C_SBUS_WRITE data to send otherwise 0 + */ +static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev, + unsigned reg, unsigned data) +{ + unsigned long flags; + int ret; + + /* We don't want interrupts disturbing our transfer */ + spin_lock_irqsave(&host->lock, flags); + + /* Reset state and start of transfer, SEL stays down during transfer */ + gpio_set_value(host->sel_gpio, 0); + + /* Set the DAT pin to output */ + gpio_direction_output(host->dat_gpio, 1); + + /* Send the device address */ + cbus_send_data(host, dev, CBUS_ADDR_BITS); + + /* Send the rw flag */ + cbus_send_bit(host, rw == I2C_SMBUS_READ); + + /* Send the register address */ + cbus_send_data(host, reg, CBUS_REG_BITS); + + if (rw == I2C_SMBUS_WRITE) { + cbus_send_data(host, data, 16); + ret = 0; + } else { + ret = gpio_direction_input(host->dat_gpio); + if (ret) { + dev_dbg(host->dev, "failed setting direction\n"); + goto out; + } + gpio_set_value(host->clk_gpio, 1); + + ret = cbus_receive_word(host); + if (ret < 0) { + dev_dbg(host->dev, "failed receiving data\n"); + goto out; + } + } + + /* Indicate end of transfer, SEL goes up until next transfer */ + gpio_set_value(host->sel_gpio, 1); + gpio_set_value(host->clk_gpio, 1); + gpio_set_value(host->clk_gpio, 0); + +out: + spin_unlock_irqrestore(&host->lock, flags); + + return ret; +} + +static int cbus_i2c_smbus_xfer(struct i2c_adapter *adapter, + u16 addr, + unsigned short flags, + char read_write, + u8 command, + int size, + union i2c_smbus_data *data) +{ + struct cbus_host *chost = i2c_get_adapdata(adapter); + int ret; + + if (size != I2C_SMBUS_WORD_DATA) + return -EINVAL; + + ret = cbus_transfer(chost, read_write == I2C_SMBUS_READ, addr, + command, data->word); + if (ret < 0) + return ret; + + if (read_write == I2C_SMBUS_READ) + data->word = ret; + + return 0; +} + +static u32 cbus_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; +} + +static const struct i2c_algorithm cbus_i2c_algo = { + .smbus_xfer = cbus_i2c_smbus_xfer, + .functionality = cbus_i2c_func, +}; + +static int cbus_i2c_remove(struct platform_device *pdev) +{ + struct i2c_adapter *adapter = platform_get_drvdata(pdev); + + return i2c_del_adapter(adapter); +} + +static int cbus_i2c_probe(struct platform_device *pdev) +{ + struct i2c_adapter *adapter; + struct cbus_host *chost; + int ret; + + adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter), + GFP_KERNEL); + if (!adapter) + return -ENOMEM; + + chost = devm_kzalloc(&pdev->dev, sizeof(*chost), GFP_KERNEL); + if (!chost) + return -ENOMEM; + + if (pdev->dev.of_node) { + struct device_node *dnode = pdev->dev.of_node; + if (of_gpio_count(dnode) != 3) + return -ENODEV; + chost->clk_gpio = of_get_gpio(dnode, 0); + chost->dat_gpio = of_get_gpio(dnode, 1); + chost->sel_gpio = of_get_gpio(dnode, 2); + } else if (pdev->dev.platform_data) { + struct i2c_cbus_platform_data *pdata = pdev->dev.platform_data; + chost->clk_gpio = pdata->clk_gpio; + chost->dat_gpio = pdata->dat_gpio; + chost->sel_gpio = pdata->sel_gpio; + } else { + return -ENODEV; + } + + adapter->owner = THIS_MODULE; + adapter->class = I2C_CLASS_HWMON; + adapter->dev.parent = &pdev->dev; + adapter->nr = pdev->id; + adapter->timeout = HZ; + adapter->algo = &cbus_i2c_algo; + strlcpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name)); + + spin_lock_init(&chost->lock); + chost->dev = &pdev->dev; + + ret = devm_gpio_request_one(&pdev->dev, chost->clk_gpio, + GPIOF_OUT_INIT_LOW, "CBUS clk"); + if (ret) + return ret; + + ret = devm_gpio_request_one(&pdev->dev, chost->dat_gpio, GPIOF_IN, + "CBUS data"); + if (ret) + return ret; + + ret = devm_gpio_request_one(&pdev->dev, chost->sel_gpio, + GPIOF_OUT_INIT_HIGH, "CBUS sel"); + if (ret) + return ret; + + i2c_set_adapdata(adapter, chost); + platform_set_drvdata(pdev, adapter); + + return i2c_add_numbered_adapter(adapter); +} + +#if defined(CONFIG_OF) +static const struct of_device_id i2c_cbus_dt_ids[] = { + { .compatible = "i2c-cbus-gpio", }, + { } +}; +MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids); +#endif + +static struct platform_driver cbus_i2c_driver = { + .probe = cbus_i2c_probe, + .remove = cbus_i2c_remove, + .driver = { + .owner = THIS_MODULE, + .name = "i2c-cbus-gpio", + }, +}; +module_platform_driver(cbus_i2c_driver); + +MODULE_ALIAS("platform:i2c-cbus-gpio"); +MODULE_DESCRIPTION("CBUS I2C driver"); +MODULE_AUTHOR("Juha Yrjölä"); +MODULE_AUTHOR("David Weinehall"); +MODULE_AUTHOR("Mikko Ylinen"); +MODULE_AUTHOR("Felipe Balbi"); +MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index c1e1096ba06..2e79c102419 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -426,7 +426,7 @@ static const struct i2c_adapter cpm_ops = { .algo = &cpm_i2c_algo, }; -static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) +static int cpm_i2c_setup(struct cpm_i2c *cpm) { struct platform_device *ofdev = cpm->ofdev; const u32 *data; @@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) cpm_muram_free(cpm->i2c_addr); } -static int __devinit cpm_i2c_probe(struct platform_device *ofdev) +static int cpm_i2c_probe(struct platform_device *ofdev) { int result, len; struct cpm_i2c *cpm; @@ -688,7 +688,7 @@ out_free: return result; } -static int __devexit cpm_i2c_remove(struct platform_device *ofdev) +static int cpm_i2c_remove(struct platform_device *ofdev) { struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); @@ -716,7 +716,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match); static struct platform_driver cpm_i2c_driver = { .probe = cpm_i2c_probe, - .remove = __devexit_p(cpm_i2c_remove), + .remove = cpm_i2c_remove, .driver = { .name = "fsl-i2c-cpm", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 92a1e2c15ba..6add851e9de 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -207,7 +207,7 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) return dev->controller->clk_khz; } -static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev, +static int i2c_dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct dw_i2c_dev *dev; @@ -328,7 +328,7 @@ exit: return r; } -static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev) +static void i2c_dw_pci_remove(struct pci_dev *pdev) { struct dw_i2c_dev *dev = pci_get_drvdata(pdev); @@ -368,7 +368,7 @@ static struct pci_driver dw_i2c_driver = { .name = DRIVER_NAME, .id_table = i2_designware_pci_ids, .probe = i2c_dw_pci_probe, - .remove = __devexit_p(i2c_dw_pci_remove), + .remove = i2c_dw_pci_remove, .driver = { .pm = &i2c_dw_pm_ops, }, diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 0506fef8dc0..343357a2b5b 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -50,7 +50,7 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) return clk_get_rate(dev->clk)/1000; } -static int __devinit dw_i2c_probe(struct platform_device *pdev) +static int dw_i2c_probe(struct platform_device *pdev) { struct dw_i2c_dev *dev; struct i2c_adapter *adap; @@ -169,7 +169,7 @@ err_release_region: return r; } -static int __devexit dw_i2c_remove(struct platform_device *pdev) +static int dw_i2c_remove(struct platform_device *pdev) { struct dw_i2c_dev *dev = platform_get_drvdata(pdev); struct resource *mem; @@ -228,7 +228,7 @@ static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume); MODULE_ALIAS("platform:i2c_designware"); static struct platform_driver dw_i2c_driver = { - .remove = __devexit_p(dw_i2c_remove), + .remove = dw_i2c_remove, .driver = { .name = "i2c_designware", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 259f7697bf2..5e7886e7136 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -758,7 +758,7 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap) iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK); } -static int __devinit pch_i2c_probe(struct pci_dev *pdev, +static int pch_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *base_addr; @@ -851,7 +851,7 @@ err_pci_enable: return ret; } -static void __devexit pch_i2c_remove(struct pci_dev *pdev) +static void pch_i2c_remove(struct pci_dev *pdev) { int i; struct adapter_info *adap_info = pci_get_drvdata(pdev); @@ -948,7 +948,7 @@ static struct pci_driver pch_pcidriver = { .name = KBUILD_MODNAME, .id_table = pch_pcidev_id, .probe = pch_i2c_probe, - .remove = __devexit_p(pch_i2c_remove), + .remove = pch_i2c_remove, .suspend = pch_i2c_suspend, .resume = pch_i2c_resume }; diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 37e2e82a9c8..485497066ed 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -205,7 +205,7 @@ static struct i2c_adapter pcf_isa_ops = { .name = "i2c-elektor", }; -static int __devinit elektor_match(struct device *dev, unsigned int id) +static int elektor_match(struct device *dev, unsigned int id) { #ifdef __alpha__ /* check to see we have memory mapped PCF8584 connected to the @@ -264,7 +264,7 @@ static int __devinit elektor_match(struct device *dev, unsigned int id) return 1; } -static int __devinit elektor_probe(struct device *dev, unsigned int id) +static int elektor_probe(struct device *dev, unsigned int id) { init_waitqueue_head(&pcf_wait); if (pcf_isa_init()) @@ -293,7 +293,7 @@ static int __devinit elektor_probe(struct device *dev, unsigned int id) return -ENODEV; } -static int __devexit elektor_remove(struct device *dev, unsigned int id) +static int elektor_remove(struct device *dev, unsigned int id) { i2c_del_adapter(&pcf_isa_ops); @@ -316,7 +316,7 @@ static int __devexit elektor_remove(struct device *dev, unsigned int id) static struct isa_driver i2c_elektor_driver = { .match = elektor_match, .probe = elektor_probe, - .remove = __devexit_p(elektor_remove), + .remove = elektor_remove, .driver = { .owner = THIS_MODULE, .name = "i2c-elektor", diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index e62d2d93862..f3fa4332bbd 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -85,7 +85,7 @@ static int i2c_gpio_getscl(void *data) return gpio_get_value(pdata->scl_pin); } -static int __devinit of_i2c_gpio_probe(struct device_node *np, +static int of_i2c_gpio_probe(struct device_node *np, struct i2c_gpio_platform_data *pdata) { u32 reg; @@ -117,7 +117,7 @@ static int __devinit of_i2c_gpio_probe(struct device_node *np, return 0; } -static int __devinit i2c_gpio_probe(struct platform_device *pdev) +static int i2c_gpio_probe(struct platform_device *pdev) { struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; @@ -184,7 +184,11 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) bit_data->data = pdata; adap->owner = THIS_MODULE; - snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); + if (pdev->dev.of_node) + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); + else + snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); + adap->algo_data = bit_data; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->dev.parent = &pdev->dev; @@ -214,7 +218,7 @@ err_request_sda: return ret; } -static int __devexit i2c_gpio_remove(struct platform_device *pdev) +static int i2c_gpio_remove(struct platform_device *pdev) { struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; @@ -247,7 +251,7 @@ static struct platform_driver i2c_gpio_driver = { .of_match_table = of_match_ptr(i2c_gpio_dt_ids), }, .probe = i2c_gpio_probe, - .remove = __devexit_p(i2c_gpio_remove), + .remove = i2c_gpio_remove, }; static int __init i2c_gpio_init(void) diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index 19515df6102..3351cc7ed11 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -356,7 +356,7 @@ static const struct i2c_algorithm highlander_i2c_algo = { .functionality = highlander_i2c_func, }; -static int __devinit highlander_i2c_probe(struct platform_device *pdev) +static int highlander_i2c_probe(struct platform_device *pdev) { struct highlander_i2c_dev *dev; struct i2c_adapter *adap; @@ -441,7 +441,7 @@ err: return ret; } -static int __devexit highlander_i2c_remove(struct platform_device *pdev) +static int highlander_i2c_remove(struct platform_device *pdev) { struct highlander_i2c_dev *dev = platform_get_drvdata(pdev); @@ -465,7 +465,7 @@ static struct platform_driver highlander_i2c_driver = { }, .probe = highlander_i2c_probe, - .remove = __devexit_p(highlander_i2c_remove), + .remove = highlander_i2c_remove, }; module_platform_driver(highlander_i2c_driver); diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index c9f95e1666a..79c3d9069a4 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -112,7 +112,7 @@ static DEFINE_PCI_DEVICE_TABLE(hydra_ids) = { MODULE_DEVICE_TABLE (pci, hydra_ids); -static int __devinit hydra_probe(struct pci_dev *dev, +static int hydra_probe(struct pci_dev *dev, const struct pci_device_id *id) { unsigned long base = pci_resource_start(dev, 0); @@ -139,7 +139,7 @@ static int __devinit hydra_probe(struct pci_dev *dev, return 0; } -static void __devexit hydra_remove(struct pci_dev *dev) +static void hydra_remove(struct pci_dev *dev) { pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ i2c_del_adapter(&hydra_adap); @@ -153,7 +153,7 @@ static struct pci_driver hydra_driver = { .name = "hydra_smbus", .id_table = hydra_ids, .probe = hydra_probe, - .remove = __devexit_p(hydra_remove), + .remove = hydra_remove, }; module_pci_driver(hydra_driver); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 6abc00d5988..3092387f6ef 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -81,6 +81,7 @@ #include <linux/slab.h> #include <linux/wait.h> #include <linux/err.h> +#include <linux/of_i2c.h> #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ defined CONFIG_DMI @@ -840,14 +841,14 @@ struct dmi_onboard_device_info { const char *i2c_type; }; -static struct dmi_onboard_device_info __devinitdata dmi_devices[] = { +static const struct dmi_onboard_device_info dmi_devices[] = { { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" }, { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" }, { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" }, }; -static void __devinit dmi_check_onboard_device(u8 type, const char *name, - struct i2c_adapter *adap) +static void dmi_check_onboard_device(u8 type, const char *name, + struct i2c_adapter *adap) { int i; struct i2c_board_info info; @@ -870,8 +871,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name, /* We use our own function to check for onboard devices instead of dmi_find_device() as some buggy BIOS's have the devices we are interested in marked as disabled */ -static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, - void *adap) +static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) { int i, count; @@ -900,7 +900,7 @@ static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, } /* Register optional slaves */ -static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) +static void i801_probe_optional_slaves(struct i801_priv *priv) { /* Only register slaves on main SMBus channel */ if (priv->features & FEATURE_IDF) @@ -920,7 +920,7 @@ static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) } #else static void __init input_apanel_init(void) {} -static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} +static void i801_probe_optional_slaves(struct i801_priv *priv) {} #endif /* CONFIG_X86 && CONFIG_DMI */ #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ @@ -943,7 +943,7 @@ static struct i801_mux_config i801_mux_config_asus_z8_d18 = { .n_gpios = 2, }; -static struct dmi_system_id __devinitdata mux_dmi_table[] = { +static const struct dmi_system_id mux_dmi_table[] = { { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), @@ -1011,7 +1011,7 @@ static struct dmi_system_id __devinitdata mux_dmi_table[] = { }; /* Setup multiplexing if needed */ -static int __devinit i801_add_mux(struct i801_priv *priv) +static int i801_add_mux(struct i801_priv *priv) { struct device *dev = &priv->adapter.dev; const struct i801_mux_config *mux_config; @@ -1047,13 +1047,13 @@ static int __devinit i801_add_mux(struct i801_priv *priv) return 0; } -static void __devexit i801_del_mux(struct i801_priv *priv) +static void i801_del_mux(struct i801_priv *priv) { if (priv->mux_pdev) platform_device_unregister(priv->mux_pdev); } -static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv) +static unsigned int i801_get_adapter_class(struct i801_priv *priv) { const struct dmi_system_id *id; const struct i801_mux_config *mux_config; @@ -1083,8 +1083,7 @@ static inline unsigned int i801_get_adapter_class(struct i801_priv *priv) } #endif -static int __devinit i801_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { unsigned char temp; int err, i; @@ -1108,6 +1107,7 @@ static int __devinit i801_probe(struct pci_dev *dev, /* fall through */ default: priv->features |= FEATURE_I2C_BLOCK_READ; + priv->features |= FEATURE_IRQ; /* fall through */ case PCI_DEVICE_ID_INTEL_82801DB_3: priv->features |= FEATURE_SMBUS_PEC; @@ -1120,16 +1120,6 @@ static int __devinit i801_probe(struct pci_dev *dev, break; } - /* IRQ processing tested on CougarPoint PCH, ICH5, ICH7-M and ICH10 */ - if (dev->device == PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS || - dev->device == PCI_DEVICE_ID_INTEL_82801EB_3 || - dev->device == PCI_DEVICE_ID_INTEL_ICH7_17 || - dev->device == PCI_DEVICE_ID_INTEL_ICH8_5 || - dev->device == PCI_DEVICE_ID_INTEL_ICH9_6 || - dev->device == PCI_DEVICE_ID_INTEL_ICH10_4 || - dev->device == PCI_DEVICE_ID_INTEL_ICH10_5) - priv->features |= FEATURE_IRQ; - /* Disable features on user request */ for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { if (priv->features & disable_features & (1 << i)) @@ -1215,6 +1205,7 @@ static int __devinit i801_probe(struct pci_dev *dev, goto exit_free_irq; } + of_i2c_register_devices(&priv->adapter); i801_probe_optional_slaves(priv); /* We ignore errors - multiplexing is optional */ i801_add_mux(priv); @@ -1233,7 +1224,7 @@ exit: return err; } -static void __devexit i801_remove(struct pci_dev *dev) +static void i801_remove(struct pci_dev *dev) { struct i801_priv *priv = pci_get_drvdata(dev); @@ -1279,7 +1270,7 @@ static struct pci_driver i801_driver = { .name = "i801_smbus", .id_table = i801_ids, .probe = i801_probe, - .remove = __devexit_p(i801_remove), + .remove = i801_remove, .suspend = i801_suspend, .resume = i801_resume, }; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 806e225f3de..33a2abb6c06 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -660,7 +660,7 @@ static inline u8 iic_clckdiv(unsigned int opb) return (u8)((opb + 9) / 10 - 1); } -static int __devinit iic_request_irq(struct platform_device *ofdev, +static int iic_request_irq(struct platform_device *ofdev, struct ibm_iic_private *dev) { struct device_node *np = ofdev->dev.of_node; @@ -691,7 +691,7 @@ static int __devinit iic_request_irq(struct platform_device *ofdev, /* * Register single IIC interface */ -static int __devinit iic_probe(struct platform_device *ofdev) +static int iic_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct ibm_iic_private *dev; @@ -781,7 +781,7 @@ error_cleanup: /* * Cleanup initialized IIC interface */ -static int __devexit iic_remove(struct platform_device *ofdev) +static int iic_remove(struct platform_device *ofdev) { struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); @@ -812,7 +812,7 @@ static struct platform_driver ibm_iic_driver = { .of_match_table = ibm_iic_match, }, .probe = iic_probe, - .remove = __devexit_p(iic_remove), + .remove = iic_remove, }; module_platform_driver(ibm_iic_driver); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 2ef162d148c..b9734747d61 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -52,8 +52,6 @@ #include <linux/of_device.h> #include <linux/of_i2c.h> #include <linux/pinctrl/consumer.h> - -#include <mach/hardware.h> #include <linux/platform_data/i2c-imx.h> /** Defines ******************************************************************** @@ -115,6 +113,11 @@ static u16 __initdata i2c_clk_div[50][2] = { { 3072, 0x1E }, { 3840, 0x1F } }; +enum imx_i2c_type { + IMX1_I2C, + IMX21_I2C, +}; + struct imx_i2c_struct { struct i2c_adapter adapter; struct clk *clk; @@ -124,13 +127,33 @@ struct imx_i2c_struct { unsigned int disable_delay; int stopped; unsigned int ifdr; /* IMX_I2C_IFDR */ + enum imx_i2c_type devtype; +}; + +static struct platform_device_id imx_i2c_devtype[] = { + { + .name = "imx1-i2c", + .driver_data = IMX1_I2C, + }, { + .name = "imx21-i2c", + .driver_data = IMX21_I2C, + }, { + /* sentinel */ + } }; +MODULE_DEVICE_TABLE(platform, imx_i2c_devtype); static const struct of_device_id i2c_imx_dt_ids[] = { - { .compatible = "fsl,imx1-i2c", }, + { .compatible = "fsl,imx1-i2c", .data = &imx_i2c_devtype[IMX1_I2C], }, + { .compatible = "fsl,imx21-i2c", .data = &imx_i2c_devtype[IMX21_I2C], }, { /* sentinel */ } }; +static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) +{ + return i2c_imx->devtype == IMX1_I2C; +} + /** Functions for IMX I2C adapter driver *************************************** *******************************************************************************/ @@ -223,7 +246,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, i2c_imx->base + IMX_I2C_I2CR); } - if (cpu_is_mx1()) { + if (is_imx1_i2c(i2c_imx)) { /* * This delay caused by an i.MXL hardware bug. * If no (or too short) delay, no "STOP" bit will be generated. @@ -465,6 +488,8 @@ static struct i2c_algorithm i2c_imx_algo = { static int __init i2c_imx_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids, + &pdev->dev); struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = pdev->dev.platform_data; @@ -497,6 +522,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev) return -ENOMEM; } + if (of_id) + pdev->id_entry = of_id->data; + i2c_imx->devtype = pdev->id_entry->driver_data; + /* Setup i2c_imx driver structure */ strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); i2c_imx->adapter.owner = THIS_MODULE; @@ -593,7 +622,8 @@ static struct platform_driver i2c_imx_driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = i2c_imx_dt_ids, - } + }, + .id_table = imx_i2c_devtype, }; static int __init i2c_adap_imx_init(void) diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c index 7c28f10f95c..de3736bf646 100644 --- a/drivers/i2c/busses/i2c-intel-mid.c +++ b/drivers/i2c/busses/i2c-intel-mid.c @@ -947,7 +947,7 @@ static const struct dev_pm_ops intel_mid_i2c_pm_ops = { * 5. Call intel_mid_i2c_hwinit() for hardware initialization * 6. Register I2C adapter in i2c-core */ -static int __devinit intel_mid_i2c_probe(struct pci_dev *dev, +static int intel_mid_i2c_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct intel_mid_i2c_private *mrst; @@ -1079,7 +1079,7 @@ exit: return err; } -static void __devexit intel_mid_i2c_remove(struct pci_dev *dev) +static void intel_mid_i2c_remove(struct pci_dev *dev) { struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev); intel_mid_i2c_disable(&mrst->adap); @@ -1113,7 +1113,7 @@ static struct pci_driver intel_mid_i2c_driver = { .name = DRIVER_NAME, .id_table = intel_mid_i2c_ids, .probe = intel_mid_i2c_probe, - .remove = __devexit_p(intel_mid_i2c_remove), + .remove = intel_mid_i2c_remove, }; module_pci_driver(intel_mid_i2c_driver); diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index f90a6057508..4099f79c228 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -249,7 +249,7 @@ static struct i2c_adapter sch_adapter = { .algo = &smbus_algorithm, }; -static int __devinit smbus_sch_probe(struct platform_device *dev) +static int smbus_sch_probe(struct platform_device *dev) { struct resource *res; int retval; @@ -284,7 +284,7 @@ static int __devinit smbus_sch_probe(struct platform_device *dev) return retval; } -static int __devexit smbus_sch_remove(struct platform_device *pdev) +static int smbus_sch_remove(struct platform_device *pdev) { struct resource *res; if (sch_smba) { @@ -303,7 +303,7 @@ static struct platform_driver smbus_sch_driver = { .owner = THIS_MODULE, }, .probe = smbus_sch_probe, - .remove = __devexit_p(smbus_sch_remove), + .remove = smbus_sch_remove, }; module_platform_driver(smbus_sch_driver); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index ca86430cb4a..a69459e5c3f 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -175,7 +175,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) } #if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x) -static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = { +static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = { {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23}, {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02}, {36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28}, @@ -196,7 +196,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = { {10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f} }; -static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, +static int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler, u32 *real_clk) { const struct mpc_i2c_divider *div = NULL; @@ -230,7 +230,7 @@ static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, return (int)div->fdr; } -static void __devinit mpc_i2c_setup_52xx(struct device_node *node, +static void mpc_i2c_setup_52xx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { @@ -252,7 +252,7 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node, fdr); } #else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */ -static void __devinit mpc_i2c_setup_52xx(struct device_node *node, +static void mpc_i2c_setup_52xx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { @@ -260,7 +260,7 @@ static void __devinit mpc_i2c_setup_52xx(struct device_node *node, #endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */ #ifdef CONFIG_PPC_MPC512x -static void __devinit mpc_i2c_setup_512x(struct device_node *node, +static void mpc_i2c_setup_512x(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { @@ -288,7 +288,7 @@ static void __devinit mpc_i2c_setup_512x(struct device_node *node, mpc_i2c_setup_52xx(node, i2c, clock, prescaler); } #else /* CONFIG_PPC_MPC512x */ -static void __devinit mpc_i2c_setup_512x(struct device_node *node, +static void mpc_i2c_setup_512x(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { @@ -296,7 +296,7 @@ static void __devinit mpc_i2c_setup_512x(struct device_node *node, #endif /* CONFIG_PPC_MPC512x */ #ifdef CONFIG_FSL_SOC -static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = { +static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = { {160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123}, {288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102}, {416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127}, @@ -316,7 +316,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = { {49152, 0x011e}, {61440, 0x011f} }; -static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void) +static u32 mpc_i2c_get_sec_cfg_8xxx(void) { struct device_node *node = NULL; u32 __iomem *reg; @@ -345,7 +345,7 @@ static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void) return val; } -static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, +static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler, u32 *real_clk) { const struct mpc_i2c_divider *div = NULL; @@ -383,7 +383,7 @@ static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, return div ? (int)div->fdr : -EINVAL; } -static void __devinit mpc_i2c_setup_8xxx(struct device_node *node, +static void mpc_i2c_setup_8xxx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { @@ -408,7 +408,7 @@ static void __devinit mpc_i2c_setup_8xxx(struct device_node *node, } #else /* !CONFIG_FSL_SOC */ -static void __devinit mpc_i2c_setup_8xxx(struct device_node *node, +static void mpc_i2c_setup_8xxx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { @@ -615,7 +615,7 @@ static struct i2c_adapter mpc_ops = { }; static const struct of_device_id mpc_i2c_of_match[]; -static int __devinit fsl_i2c_probe(struct platform_device *op) +static int fsl_i2c_probe(struct platform_device *op) { const struct of_device_id *match; struct mpc_i2c *i2c; @@ -706,7 +706,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op) return result; }; -static int __devexit fsl_i2c_remove(struct platform_device *op) +static int fsl_i2c_remove(struct platform_device *op) { struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); @@ -746,24 +746,24 @@ static int mpc_i2c_resume(struct device *dev) SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume); #endif -static const struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_512x = { .setup = mpc_i2c_setup_512x, }; -static const struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_52xx = { .setup = mpc_i2c_setup_52xx, }; -static const struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_8313 = { .setup = mpc_i2c_setup_8xxx, }; -static const struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_8543 = { .setup = mpc_i2c_setup_8xxx, .prescaler = 2, }; -static const struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = { +static const struct mpc_i2c_data mpc_i2c_data_8544 = { .setup = mpc_i2c_setup_8xxx, .prescaler = 3, }; @@ -785,7 +785,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); /* Structure for a device driver */ static struct platform_driver mpc_i2c_driver = { .probe = fsl_i2c_probe, - .remove = __devexit_p(fsl_i2c_remove), + .remove = fsl_i2c_remove, .driver = { .owner = THIS_MODULE, .name = DRV_NAME, diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 2e9d56719e9..8b20ef8524a 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -495,7 +495,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = { * ***************************************************************************** */ -static int __devinit +static int mv64xxx_i2c_map_regs(struct platform_device *pd, struct mv64xxx_i2c_data *drv_data) { @@ -530,13 +530,13 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) } #ifdef CONFIG_OF -static int __devinit +static int mv64xxx_calc_freq(const int tclk, const int n, const int m) { return tclk / (10 * (m + 1) * (2 << n)); } -static bool __devinit +static bool mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, u32 *best_m) { @@ -560,7 +560,7 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, return true; } -static int __devinit +static int mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, struct device_node *np) { @@ -597,7 +597,7 @@ out: #endif } #else /* CONFIG_OF */ -static int __devinit +static int mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, struct device_node *np) { @@ -605,7 +605,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, } #endif /* CONFIG_OF */ -static int __devinit +static int mv64xxx_i2c_probe(struct platform_device *pd) { struct mv64xxx_i2c_data *drv_data; @@ -697,7 +697,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) return rc; } -static int __devexit +static int mv64xxx_i2c_remove(struct platform_device *dev) { struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev); @@ -718,7 +718,7 @@ mv64xxx_i2c_remove(struct platform_device *dev) return rc; } -static const struct of_device_id mv64xxx_i2c_of_match_table[] __devinitdata = { +static const struct of_device_id mv64xxx_i2c_of_match_table[] = { { .compatible = "marvell,mv64xxx-i2c", }, {} }; @@ -726,7 +726,7 @@ MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); static struct platform_driver mv64xxx_i2c_driver = { .probe = mv64xxx_i2c_probe, - .remove = __devexit_p(mv64xxx_i2c_remove), + .remove = mv64xxx_i2c_remove, .driver = { .owner = THIS_MODULE, .name = MV64XXX_I2C_CTLR_NAME, diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 0670da79ee5..1b1a936eccc 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -359,7 +359,7 @@ static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 mxs_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) @@ -432,7 +432,7 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) return 0; } -static int __devinit mxs_i2c_probe(struct platform_device *pdev) +static int mxs_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mxs_i2c_dev *i2c; @@ -515,7 +515,7 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) return 0; } -static int __devexit mxs_i2c_remove(struct platform_device *pdev) +static int mxs_i2c_remove(struct platform_device *pdev) { struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev); int ret; @@ -546,7 +546,7 @@ static struct platform_driver mxs_i2c_driver = { .owner = THIS_MODULE, .of_match_table = mxs_i2c_dt_ids, }, - .remove = __devexit_p(mxs_i2c_remove), + .remove = mxs_i2c_remove, }; static int __init mxs_i2c_init(void) diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 392303b4be0..adac8542771 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -117,7 +117,7 @@ struct nforce2_smbus { #define MAX_TIMEOUT 100 /* We disable the second SMBus channel on these boards */ -static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = { +static const struct dmi_system_id nforce2_dmi_blacklist2[] = { { .ident = "DFI Lanparty NF4 Expert", .matches = { @@ -330,8 +330,8 @@ static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { MODULE_DEVICE_TABLE (pci, nforce2_ids); -static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, - int alt_reg, struct nforce2_smbus *smbus, const char *name) +static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg, + struct nforce2_smbus *smbus, const char *name) { int error; @@ -382,7 +382,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, } -static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct nforce2_smbus *smbuses; int res1, res2; @@ -430,7 +430,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ } -static void __devexit nforce2_remove(struct pci_dev *dev) +static void nforce2_remove(struct pci_dev *dev) { struct nforce2_smbus *smbuses = pci_get_drvdata(dev); @@ -450,7 +450,7 @@ static struct pci_driver nforce2_driver = { .name = "nForce2_smbus", .id_table = nforce2_ids, .probe = nforce2_probe, - .remove = __devexit_p(nforce2_remove), + .remove = nforce2_remove, }; module_pci_driver(nforce2_driver); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 02c3115a2df..8b2ffcf4532 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -435,13 +435,6 @@ static int read_i2c(struct nmk_i2c_dev *dev, u16 flags) timeout = wait_for_completion_timeout( &dev->xfer_complete, dev->adap.timeout); - if (timeout < 0) { - dev_err(&dev->adev->dev, - "wait_for_completion_timeout " - "returned %d waiting for event\n", timeout); - status = timeout; - } - if (timeout == 0) { /* Controller timed out */ dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n", @@ -523,13 +516,6 @@ static int write_i2c(struct nmk_i2c_dev *dev, u16 flags) timeout = wait_for_completion_timeout( &dev->xfer_complete, dev->adap.timeout); - if (timeout < 0) { - dev_err(&dev->adev->dev, - "wait_for_completion_timeout " - "returned %d waiting for event\n", timeout); - status = timeout; - } - if (timeout == 0) { /* Controller timed out */ dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n", diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c index f41502ef3f5..865ee350adb 100644 --- a/drivers/i2c/busses/i2c-nuc900.c +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -304,7 +304,7 @@ retry_write: case STATE_READ: /* we have a byte of data in the data register, do - * something with it, and then work out wether we are + * something with it, and then work out whether we are * going to do any more read/write */ @@ -518,7 +518,7 @@ static const struct i2c_algorithm nuc900_i2c_algorithm = { * called by the bus driver when a suitable device is found */ -static int __devinit nuc900_i2c_probe(struct platform_device *pdev) +static int nuc900_i2c_probe(struct platform_device *pdev) { struct nuc900_i2c *i2c; struct nuc900_platform_i2c *pdata; @@ -663,7 +663,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev) * called when device is removed from the bus */ -static int __devexit nuc900_i2c_remove(struct platform_device *pdev) +static int nuc900_i2c_remove(struct platform_device *pdev) { struct nuc900_i2c *i2c = platform_get_drvdata(pdev); @@ -684,7 +684,7 @@ static int __devexit nuc900_i2c_remove(struct platform_device *pdev) static struct platform_driver nuc900_i2c_driver = { .probe = nuc900_i2c_probe, - .remove = __devexit_p(nuc900_i2c_remove), + .remove = nuc900_i2c_remove, .driver = { .owner = THIS_MODULE, .name = "nuc900-i2c0", diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index bffd5501ac2..a873d0ad1ac 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -4,15 +4,14 @@ * * Peter Korsgaard <jacmet@sunsite.dk> * + * Support for the GRLIB port of the controller by + * Andreas Larsson <andreas@gaisler.com> + * * 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. */ -/* - * This driver can be used from the device tree, see - * Documentation/devicetree/bindings/i2c/ocore-i2c.txt - */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -38,6 +37,8 @@ struct ocores_i2c { int nmsgs; int state; /* see STATE_ */ int clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); }; /* registers */ @@ -71,24 +72,47 @@ struct ocores_i2c { #define STATE_READ 3 #define STATE_ERROR 4 +#define TYPE_OCORES 0 +#define TYPE_GRLIB 1 + +static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) { - if (i2c->reg_io_width == 4) - iowrite32(value, i2c->base + (reg << i2c->reg_shift)); - else if (i2c->reg_io_width == 2) - iowrite16(value, i2c->base + (reg << i2c->reg_shift)); - else - iowrite8(value, i2c->base + (reg << i2c->reg_shift)); + i2c->setreg(i2c, reg, value); } static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) { - if (i2c->reg_io_width == 4) - return ioread32(i2c->base + (reg << i2c->reg_shift)); - else if (i2c->reg_io_width == 2) - return ioread16(i2c->base + (reg << i2c->reg_shift)); - else - return ioread8(i2c->base + (reg << i2c->reg_shift)); + return i2c->getreg(i2c, reg); } static void ocores_process(struct ocores_i2c *i2c) @@ -227,11 +251,59 @@ static struct i2c_adapter ocores_adapter = { .algo = &ocores_algorithm, }; +static struct of_device_id ocores_i2c_match[] = { + { + .compatible = "opencores,i2c-ocores", + .data = (void *)TYPE_OCORES, + }, + { + .compatible = "aeroflexgaisler,i2cmst", + .data = (void *)TYPE_GRLIB, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ocores_i2c_match); + #ifdef CONFIG_OF +/* Read and write functions for the GRLIB port of the controller. Registers are + * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one + * register. The subsequent registers has their offset decreased accordingly. */ +static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) +{ + u32 rd; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PREHIGH) + return (u8)(rd >> 8); + else + return (u8)rd; +} + +static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value) +{ + u32 curr, wr; + int rreg = reg; + if (reg != OCI2C_PRELOW) + rreg--; + if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { + curr = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PRELOW) + wr = (curr & 0xff00) | value; + else + wr = (((u32)value) << 8) | (curr & 0xff); + } else { + wr = value; + } + iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift)); +} + static int ocores_i2c_of_probe(struct platform_device *pdev, struct ocores_i2c *i2c) { struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; u32 val; if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { @@ -257,17 +329,26 @@ static int ocores_i2c_of_probe(struct platform_device *pdev, of_property_read_u32(pdev->dev.of_node, "reg-io-width", &i2c->reg_io_width); + + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); + if (match && (int)match->data == TYPE_GRLIB) { + dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n"); + i2c->setreg = oc_setreg_grlib; + i2c->getreg = oc_getreg_grlib; + } + return 0; } #else #define ocores_i2c_of_probe(pdev,i2c) -ENODEV #endif -static int __devinit ocores_i2c_probe(struct platform_device *pdev) +static int ocores_i2c_probe(struct platform_device *pdev) { struct ocores_i2c *i2c; struct ocores_i2c_platform_data *pdata; - struct resource *res, *res2; + struct resource *res; + int irq; int ret; int i; @@ -275,26 +356,17 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) if (!res) return -ENODEV; - res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res2) - return -ENODEV; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Memory region busy\n"); - return -EBUSY; - } - - i2c->base = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); - if (!i2c->base) { - dev_err(&pdev->dev, "Unable to map registers\n"); - return -EIO; - } + i2c->base = devm_request_and_ioremap(&pdev->dev, res); + if (!i2c->base) + return -EADDRNOTAVAIL; pdata = pdev->dev.platform_data; if (pdata) { @@ -310,10 +382,34 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) if (i2c->reg_io_width == 0) i2c->reg_io_width = 1; /* Set to default value */ + if (!i2c->setreg || !i2c->getreg) { + switch (i2c->reg_io_width) { + case 1: + i2c->setreg = oc_setreg_8; + i2c->getreg = oc_getreg_8; + break; + + case 2: + i2c->setreg = oc_setreg_16; + i2c->getreg = oc_getreg_16; + break; + + case 4: + i2c->setreg = oc_setreg_32; + i2c->getreg = oc_getreg_32; + break; + + default: + dev_err(&pdev->dev, "Unsupported I/O width (%d)\n", + i2c->reg_io_width); + return -EINVAL; + } + } + ocores_init(i2c); init_waitqueue_head(&i2c->wait); - ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); @@ -345,7 +441,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) return 0; } -static int __devexit ocores_i2c_remove(struct platform_device *pdev) +static int ocores_i2c_remove(struct platform_device *pdev) { struct ocores_i2c *i2c = platform_get_drvdata(pdev); @@ -387,15 +483,9 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); #define OCORES_I2C_PM NULL #endif -static struct of_device_id ocores_i2c_match[] = { - { .compatible = "opencores,i2c-ocores", }, - {}, -}; -MODULE_DEVICE_TABLE(of, ocores_i2c_match); - static struct platform_driver ocores_i2c_driver = { .probe = ocores_i2c_probe, - .remove = __devexit_p(ocores_i2c_remove), + .remove = ocores_i2c_remove, .driver = { .owner = THIS_MODULE, .name = "ocores-i2c", diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index f44c83549fe..484ca771fdf 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -446,7 +446,7 @@ static struct i2c_adapter octeon_i2c_ops = { /** * octeon_i2c_setclock - Calculate and set clock divisors. */ -static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c) +static int 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; @@ -489,7 +489,7 @@ static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c) return 0; } -static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c) +static int octeon_i2c_initlowlevel(struct octeon_i2c *i2c) { u8 status; int tries; @@ -510,7 +510,7 @@ static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c) return -EIO; } -static int __devinit octeon_i2c_probe(struct platform_device *pdev) +static int octeon_i2c_probe(struct platform_device *pdev) { int irq, result = 0; struct octeon_i2c *i2c; @@ -609,7 +609,7 @@ out: return result; }; -static int __devexit octeon_i2c_remove(struct platform_device *pdev) +static int octeon_i2c_remove(struct platform_device *pdev) { struct octeon_i2c *i2c = platform_get_drvdata(pdev); @@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match); static struct platform_driver octeon_i2c_driver = { .probe = octeon_i2c_probe, - .remove = __devexit_p(octeon_i2c_remove), + .remove = octeon_i2c_remove, .driver = { .owner = THIS_MODULE, .name = DRV_NAME, diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 3525c9e62cb..20d41bfa7c1 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,14 +43,16 @@ #include <linux/slab.h> #include <linux/i2c-omap.h> #include <linux/pm_runtime.h> +#include <linux/pinctrl/consumer.h> /* I2C controller revisions */ #define OMAP_I2C_OMAP1_REV_2 0x20 /* I2C controller revisions present on specific hardware */ -#define OMAP_I2C_REV_ON_2430 0x36 -#define OMAP_I2C_REV_ON_3430_3530 0x3C -#define OMAP_I2C_REV_ON_3630_4430 0x40 +#define OMAP_I2C_REV_ON_2430 0x00000036 +#define OMAP_I2C_REV_ON_3430_3530 0x0000003C +#define OMAP_I2C_REV_ON_3630 0x00000040 +#define OMAP_I2C_REV_ON_4430_PLUS 0x50400002 /* timeout waiting for the controller to respond */ #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) @@ -190,7 +192,6 @@ struct omap_i2c_dev { void (*set_mpu_wkup_lat)(struct device *dev, long latency); u32 speed; /* Speed of bus in kHz */ - u32 dtrev; /* extra revision from DT */ u32 flags; u16 cmd_err; u8 *buf; @@ -202,17 +203,18 @@ struct omap_i2c_dev { * fifo_size==0 implies no fifo * if set, should be trsh+1 */ - u8 rev; + u32 rev; unsigned b_hw:1; /* bad h/w fixes */ unsigned receiver:1; /* true when we're in receiver mode */ u16 iestate; /* Saved interrupt register */ u16 pscstate; u16 scllstate; u16 sclhstate; - u16 bufstate; u16 syscstate; u16 westate; u16 errata; + + struct pinctrl *pins; }; static const u8 reg_map_ip_v1[] = { @@ -275,16 +277,39 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } -static int omap_i2c_init(struct omap_i2c_dev *dev) +static void __omap_i2c_init(struct omap_i2c_dev *dev) +{ + + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); + + /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ + omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); + + /* SCL low and high time values */ + omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate); + omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate); + if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) + omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); + + /* Take the I2C module out of reset: */ + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); + + /* + * Don't write to this register if the IE state is 0 as it can + * cause deadlock. + */ + if (dev->iestate) + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); +} + +static int omap_i2c_reset(struct omap_i2c_dev *dev) { - u16 psc = 0, scll = 0, sclh = 0, buf = 0; - u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; - unsigned long fclk_rate = 12000000; unsigned long timeout; - unsigned long internal_clk = 0; - struct clk *fclk; + u16 sysc; if (dev->rev >= OMAP_I2C_OMAP1_REV_2) { + sysc = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG); + /* Disable I2C controller before soft reset */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & @@ -306,32 +331,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) } /* SYSC register is cleared by the reset; rewrite it */ - if (dev->rev == OMAP_I2C_REV_ON_2430) { - - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, - SYSC_AUTOIDLE_MASK); - - } else if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) { - dev->syscstate = SYSC_AUTOIDLE_MASK; - dev->syscstate |= SYSC_ENAWAKEUP_MASK; - dev->syscstate |= (SYSC_IDLEMODE_SMART << - __ffs(SYSC_SIDLEMODE_MASK)); - dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK << - __ffs(SYSC_CLOCKACTIVITY_MASK)); - - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, - dev->syscstate); - /* - * Enabling all wakup sources to stop I2C freezing on - * WFI instruction. - * REVISIT: Some wkup sources might not be needed. - */ - dev->westate = OMAP_I2C_WE_ALL; - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, - dev->westate); - } + omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, sysc); + + } + return 0; +} + +static int omap_i2c_init(struct omap_i2c_dev *dev) +{ + u16 psc = 0, scll = 0, sclh = 0; + u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; + unsigned long fclk_rate = 12000000; + unsigned long internal_clk = 0; + struct clk *fclk; + + if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) { + /* + * Enabling all wakup sources to stop I2C freezing on + * WFI instruction. + * REVISIT: Some wkup sources might not be needed. + */ + dev->westate = OMAP_I2C_WE_ALL; } - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) { /* @@ -416,28 +437,17 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) sclh = fclk_rate / (dev->speed * 2) - 7 + psc; } - /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ - omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); - - /* SCL low and high time values */ - omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); - omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); - - /* Take the I2C module out of reset: */ - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - - /* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | OMAP_I2C_IE_AL) | ((dev->fifo_size) ? (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0); - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); - if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { - dev->pscstate = psc; - dev->scllstate = scll; - dev->sclhstate = sclh; - dev->bufstate = buf; - } + + dev->pscstate = psc; + dev->scllstate = scll; + dev->sclhstate = sclh; + + __omap_i2c_init(dev); + return 0; } @@ -490,7 +500,7 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); - if (dev->rev < OMAP_I2C_REV_ON_3630_4430) + if (dev->rev < OMAP_I2C_REV_ON_3630) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ @@ -586,7 +596,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, OMAP_I2C_TIMEOUT); if (timeout == 0) { dev_err(dev->dev, "controller timed out\n"); - omap_i2c_init(dev); + omap_i2c_reset(dev); + __omap_i2c_init(dev); return -ETIMEDOUT; } @@ -596,7 +607,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, /* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR | OMAP_I2C_STAT_XUDF)) { - omap_i2c_init(dev); + omap_i2c_reset(dev); + __omap_i2c_init(dev); return -EIO; } @@ -642,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) break; } - if (dev->set_mpu_wkup_lat != NULL) - dev->set_mpu_wkup_lat(dev->dev, -1); - if (r == 0) r = num; omap_i2c_wait_for_bb(dev); + + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); + out: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1025,9 +1038,7 @@ static const struct i2c_algorithm omap_i2c_algo = { #ifdef CONFIG_OF static struct omap_i2c_bus_platform_data omap3_pdata = { .rev = OMAP_I2C_IP_VERSION_1, - .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | - OMAP_I2C_FLAG_RESET_REGS_POSTIDLE | - OMAP_I2C_FLAG_BUS_SHIFT_2, + .flags = OMAP_I2C_FLAG_BUS_SHIFT_2, }; static struct omap_i2c_bus_platform_data omap4_pdata = { @@ -1048,7 +1059,17 @@ static const struct of_device_id omap_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, omap_i2c_of_match); #endif -static int __devinit +#define OMAP_I2C_SCHEME(rev) ((rev & 0xc000) >> 14) + +#define OMAP_I2C_REV_SCHEME_0_MAJOR(rev) (rev >> 4) +#define OMAP_I2C_REV_SCHEME_0_MINOR(rev) (rev & 0xf) + +#define OMAP_I2C_REV_SCHEME_1_MAJOR(rev) ((rev & 0x0700) >> 7) +#define OMAP_I2C_REV_SCHEME_1_MINOR(rev) (rev & 0x1f) +#define OMAP_I2C_SCHEME_0 0 +#define OMAP_I2C_SCHEME_1 1 + +static int omap_i2c_probe(struct platform_device *pdev) { struct omap_i2c_dev *dev; @@ -1060,6 +1081,8 @@ omap_i2c_probe(struct platform_device *pdev) const struct of_device_id *match; int irq; int r; + u32 rev; + u16 minor, major, scheme; /* NOTE: driver uses the static register mapping */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1091,7 +1114,6 @@ omap_i2c_probe(struct platform_device *pdev) u32 freq = 100000; /* default to 100000 Hz */ pdata = match->data; - dev->dtrev = pdata->rev; dev->flags = pdata->flags; of_property_read_u32(node, "clock-frequency", &freq); @@ -1101,7 +1123,16 @@ omap_i2c_probe(struct platform_device *pdev) dev->speed = pdata->clkrate; dev->flags = pdata->flags; dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; - dev->dtrev = pdata->rev; + } + + dev->pins = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(dev->pins)) { + if (PTR_ERR(dev->pins) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n", + PTR_ERR(dev->pins)); + dev->pins = NULL; } dev->dev = &pdev->dev; @@ -1114,11 +1145,6 @@ omap_i2c_probe(struct platform_device *pdev) dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; - if (dev->dtrev == OMAP_I2C_IP_VERSION_2) - dev->regs = (u8 *)reg_map_ip_v2; - else - dev->regs = (u8 *)reg_map_ip_v1; - pm_runtime_enable(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT); pm_runtime_use_autosuspend(dev->dev); @@ -1127,11 +1153,37 @@ omap_i2c_probe(struct platform_device *pdev) if (IS_ERR_VALUE(r)) goto err_free_mem; - dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; + /* + * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2. + * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset. + * Also since the omap_i2c_read_reg uses reg_map_ip_* a + * raw_readw is done. + */ + rev = __raw_readw(dev->base + 0x04); + + scheme = OMAP_I2C_SCHEME(rev); + switch (scheme) { + case OMAP_I2C_SCHEME_0: + dev->regs = (u8 *)reg_map_ip_v1; + dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG); + minor = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); + major = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); + break; + case OMAP_I2C_SCHEME_1: + /* FALLTHROUGH */ + default: + dev->regs = (u8 *)reg_map_ip_v2; + rev = (rev << 16) | + omap_i2c_read_reg(dev, OMAP_I2C_IP_V2_REVNB_LO); + minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev); + major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev); + dev->rev = rev; + } dev->errata = 0; - if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207) + if (dev->rev >= OMAP_I2C_REV_ON_2430 && + dev->rev < OMAP_I2C_REV_ON_4430_PLUS) dev->errata |= I2C_OMAP_ERRATA_I207; if (dev->rev <= OMAP_I2C_REV_ON_3430_3530) @@ -1152,7 +1204,7 @@ omap_i2c_probe(struct platform_device *pdev) dev->fifo_size = (dev->fifo_size / 2); - if (dev->rev < OMAP_I2C_REV_ON_3630_4430) + if (dev->rev < OMAP_I2C_REV_ON_3630) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ @@ -1195,8 +1247,8 @@ omap_i2c_probe(struct platform_device *pdev) goto err_unuse_clocks; } - dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr, - dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); + dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr, + major, minor, dev->speed); of_i2c_register_devices(adap); @@ -1215,7 +1267,7 @@ err_free_mem: return r; } -static int __devexit omap_i2c_remove(struct platform_device *pdev) +static int omap_i2c_remove(struct platform_device *pdev) { struct omap_i2c_dev *dev = platform_get_drvdata(pdev); int ret; @@ -1239,14 +1291,13 @@ static int omap_i2c_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); - u16 iv; _dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG); omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0); if (_dev->rev < OMAP_I2C_OMAP1_REV_2) { - iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */ + omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */ } else { omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate); @@ -1262,23 +1313,10 @@ static int omap_i2c_runtime_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); - if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { - omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0); - omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate); - omap_i2c_write_reg(_dev, OMAP_I2C_SCLL_REG, _dev->scllstate); - omap_i2c_write_reg(_dev, OMAP_I2C_SCLH_REG, _dev->sclhstate); - omap_i2c_write_reg(_dev, OMAP_I2C_BUF_REG, _dev->bufstate); - omap_i2c_write_reg(_dev, OMAP_I2C_SYSC_REG, _dev->syscstate); - omap_i2c_write_reg(_dev, OMAP_I2C_WE_REG, _dev->westate); - omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - } + if (!_dev->regs) + return 0; - /* - * Don't write to this register if the IE state is 0 as it can - * cause deadlock. - */ - if (_dev->iestate) - omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, _dev->iestate); + __omap_i2c_init(_dev); return 0; } @@ -1295,7 +1333,7 @@ static struct dev_pm_ops omap_i2c_pm_ops = { static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, - .remove = __devexit_p(omap_i2c_remove), + .remove = omap_i2c_remove, .driver = { .name = "omap_i2c", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 4b95f7a63a3..aa957788192 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -135,7 +135,7 @@ static struct lineop parport_ctrl_irq = { .port = PORT_CTRL, }; -static int __devinit i2c_parport_probe(struct platform_device *pdev) +static int i2c_parport_probe(struct platform_device *pdev) { int err; @@ -169,7 +169,7 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev) return 0; } -static int __devexit i2c_parport_remove(struct platform_device *pdev) +static int i2c_parport_remove(struct platform_device *pdev) { if (ara) { line_set(0, &parport_ctrl_irq); @@ -191,7 +191,7 @@ static struct platform_driver i2c_parport_driver = { .name = DRVNAME, }, .probe = i2c_parport_probe, - .remove = __devexit_p(i2c_parport_remove), + .remove = i2c_parport_remove, }; static int __init i2c_parport_device_add(u16 address) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 12edefd4183..615f632c846 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -340,7 +340,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = pasemi_smb_func, }; -static int __devinit pasemi_smb_probe(struct pci_dev *dev, +static int pasemi_smb_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct pasemi_smbus *smbus; @@ -392,7 +392,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, return error; } -static void __devexit pasemi_smb_remove(struct pci_dev *dev) +static void pasemi_smb_remove(struct pci_dev *dev) { struct pasemi_smbus *smbus = pci_get_drvdata(dev); @@ -412,7 +412,7 @@ static struct pci_driver pasemi_smb_driver = { .name = "i2c-pasemi", .id_table = pasemi_smb_ids, .probe = pasemi_smb_probe, - .remove = __devexit_p(pasemi_smb_remove), + .remove = pasemi_smb_remove, }; module_pci_driver(pasemi_smb_driver); diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index 29933f87d8f..323f061a316 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -119,7 +119,7 @@ static struct i2c_adapter pca_isa_ops = { .timeout = HZ, }; -static int __devinit pca_isa_match(struct device *dev, unsigned int id) +static int pca_isa_match(struct device *dev, unsigned int id) { int match = base != 0; @@ -132,7 +132,7 @@ static int __devinit pca_isa_match(struct device *dev, unsigned int id) return match; } -static int __devinit pca_isa_probe(struct device *dev, unsigned int id) +static int pca_isa_probe(struct device *dev, unsigned int id) { init_waitqueue_head(&pca_wait); @@ -174,7 +174,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id) return -ENODEV; } -static int __devexit pca_isa_remove(struct device *dev, unsigned int id) +static int pca_isa_remove(struct device *dev, unsigned int id) { i2c_del_adapter(&pca_isa_ops); @@ -190,7 +190,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id) static struct isa_driver pca_isa_driver = { .match = pca_isa_match, .probe = pca_isa_probe, - .remove = __devexit_p(pca_isa_remove), + .remove = pca_isa_remove, .driver = { .owner = THIS_MODULE, .name = DRIVER, diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 675878f49f7..a30d2f613c0 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -131,7 +131,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id) } -static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) +static int i2c_pca_pf_probe(struct platform_device *pdev) { struct i2c_pca_pf_data *i2c; struct resource *res; @@ -257,7 +257,7 @@ e_print: return ret; } -static int __devexit i2c_pca_pf_remove(struct platform_device *pdev) +static int i2c_pca_pf_remove(struct platform_device *pdev) { struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); @@ -279,7 +279,7 @@ static int __devexit i2c_pca_pf_remove(struct platform_device *pdev) static struct platform_driver i2c_pca_pf_driver = { .probe = i2c_pca_pf_probe, - .remove = __devexit_p(i2c_pca_pf_remove), + .remove = i2c_pca_pf_remove, .driver = { .name = "i2c-pca-platform", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 8bbd6ece7c4..39ab78c1a02 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -99,7 +99,7 @@ MODULE_PARM_DESC(force_addr, static int srvrworks_csb5_delay; static struct pci_driver piix4_driver; -static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = { +static const struct dmi_system_id piix4_dmi_blacklist[] = { { .ident = "Sapphire AM2RD790", .matches = { @@ -119,7 +119,7 @@ static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = { /* The IBM entry is in a separate table because we only check it on Intel-based systems */ -static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = { +static const struct dmi_system_id piix4_dmi_ibm[] = { { .ident = "IBM", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, @@ -131,8 +131,8 @@ struct i2c_piix4_adapdata { unsigned short smba; }; -static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) +static int piix4_setup(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id) { unsigned char temp; unsigned short piix4_smba; @@ -204,9 +204,8 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, */ pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 1); - dev_printk(KERN_NOTICE, &PIIX4_dev->dev, - "WARNING: SMBus interface has been " - "FORCEFULLY ENABLED!\n"); + dev_notice(&PIIX4_dev->dev, + "WARNING: SMBus interface has been FORCEFULLY ENABLED!\n"); } else { dev_err(&PIIX4_dev->dev, "Host SMBus controller not enabled!\n"); @@ -231,8 +230,8 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, return piix4_smba; } -static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) +static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id) { unsigned short piix4_smba; unsigned short smba_idx = 0xcd6; @@ -295,9 +294,9 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, return piix4_smba; } -static int __devinit piix4_setup_aux(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id, - unsigned short base_reg_addr) +static int piix4_setup_aux(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id, + unsigned short base_reg_addr) { /* Set up auxiliary SMBus controllers found on some * AMD chipsets e.g. SP5100 (SB700 derivative) */ @@ -541,9 +540,8 @@ MODULE_DEVICE_TABLE (pci, piix4_ids); static struct i2c_adapter *piix4_main_adapter; static struct i2c_adapter *piix4_aux_adapter; -static int __devinit piix4_add_adapter(struct pci_dev *dev, - unsigned short smba, - struct i2c_adapter **padap) +static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, + struct i2c_adapter **padap) { struct i2c_adapter *adap; struct i2c_piix4_adapdata *adapdata; @@ -589,8 +587,7 @@ static int __devinit piix4_add_adapter(struct pci_dev *dev, return 0; } -static int __devinit piix4_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; @@ -627,7 +624,7 @@ static int __devinit piix4_probe(struct pci_dev *dev, return 0; } -static void __devexit piix4_adap_remove(struct i2c_adapter *adap) +static void piix4_adap_remove(struct i2c_adapter *adap) { struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap); @@ -639,7 +636,7 @@ static void __devexit piix4_adap_remove(struct i2c_adapter *adap) } } -static void __devexit piix4_remove(struct pci_dev *dev) +static void piix4_remove(struct pci_dev *dev) { if (piix4_main_adapter) { piix4_adap_remove(piix4_main_adapter); @@ -656,7 +653,7 @@ static struct pci_driver piix4_driver = { .name = "piix4_smbus", .id_table = piix4_ids, .probe = piix4_probe, - .remove = __devexit_p(piix4_remove), + .remove = piix4_remove, }; module_pci_driver(piix4_driver); diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 3d71395ae1f..083d68cfaf0 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -270,7 +270,7 @@ static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr) /* * Probe for and register the device and return 0 if there is one. */ -static int __devinit pmcmsptwi_probe(struct platform_device *pldev) +static int pmcmsptwi_probe(struct platform_device *pldev) { struct resource *res; int rc = -ENODEV; @@ -368,7 +368,7 @@ ret_err: /* * Release the device and return 0 if there is one. */ -static int __devexit pmcmsptwi_remove(struct platform_device *pldev) +static int pmcmsptwi_remove(struct platform_device *pldev) { struct resource *res; @@ -628,7 +628,7 @@ static struct i2c_adapter pmcmsptwi_adapter = { static struct platform_driver pmcmsptwi_driver = { .probe = pmcmsptwi_probe, - .remove = __devexit_p(pmcmsptwi_remove), + .remove = pmcmsptwi_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 8488bddfe46..ce4097012e9 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -619,7 +619,7 @@ static SIMPLE_DEV_PM_OPS(i2c_pnx_pm, #define PNX_I2C_PM NULL #endif -static int __devinit i2c_pnx_probe(struct platform_device *pdev) +static int i2c_pnx_probe(struct platform_device *pdev) { unsigned long tmp; int ret = 0; @@ -765,7 +765,7 @@ err_kzalloc: return ret; } -static int __devexit i2c_pnx_remove(struct platform_device *pdev) +static int i2c_pnx_remove(struct platform_device *pdev) { struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); @@ -797,7 +797,7 @@ static struct platform_driver i2c_pnx_driver = { .pm = PNX_I2C_PM, }, .probe = i2c_pnx_probe, - .remove = __devexit_p(i2c_pnx_remove), + .remove = i2c_pnx_remove, }; static int __init i2c_adap_pnx_init(void) diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 5285f8565de..0dd5b334d09 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -210,7 +210,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = { }; -static int __devexit i2c_powermac_remove(struct platform_device *dev) +static int i2c_powermac_remove(struct platform_device *dev) { struct i2c_adapter *adapter = platform_get_drvdata(dev); int rc; @@ -227,7 +227,7 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev) return 0; } -static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap, +static u32 i2c_powermac_get_addr(struct i2c_adapter *adap, struct pmac_i2c_bus *bus, struct device_node *node) { @@ -255,7 +255,7 @@ static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap, return 0xffffffff; } -static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap, +static void i2c_powermac_create_one(struct i2c_adapter *adap, const char *type, u32 addr) { @@ -271,7 +271,7 @@ static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap, type); } -static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap, +static void i2c_powermac_add_missing(struct i2c_adapter *adap, struct pmac_i2c_bus *bus, bool found_onyx) { @@ -297,7 +297,7 @@ static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap, } } -static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap, +static bool i2c_powermac_get_type(struct i2c_adapter *adap, struct device_node *node, u32 addr, char *type, int type_size) { @@ -336,7 +336,7 @@ static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap, return false; } -static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap, +static void i2c_powermac_register_devices(struct i2c_adapter *adap, struct pmac_i2c_bus *bus) { struct i2c_client *newdev; @@ -403,7 +403,7 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap, i2c_powermac_add_missing(adap, bus, found_onyx); } -static int __devinit i2c_powermac_probe(struct platform_device *dev) +static int i2c_powermac_probe(struct platform_device *dev) { struct pmac_i2c_bus *bus = dev->dev.platform_data; struct device_node *parent = NULL; @@ -467,7 +467,7 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev) static struct platform_driver i2c_powermac_driver = { .probe = i2c_powermac_probe, - .remove = __devexit_p(i2c_powermac_remove), + .remove = i2c_powermac_remove, .driver = { .name = "i2c-powermac", .bus = &platform_bus_type, diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c index d8515be00b9..d7c512d717a 100644 --- a/drivers/i2c/busses/i2c-puv3.c +++ b/drivers/i2c/busses/i2c-puv3.c @@ -184,7 +184,7 @@ static struct i2c_algorithm puv3_i2c_algorithm = { /* * Main initialization routine. */ -static int __devinit puv3_i2c_probe(struct platform_device *pdev) +static int puv3_i2c_probe(struct platform_device *pdev) { struct i2c_adapter *adapter; struct resource *mem; @@ -231,7 +231,7 @@ fail_nomem: return rc; } -static int __devexit puv3_i2c_remove(struct platform_device *pdev) +static int puv3_i2c_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); struct resource *mem; @@ -276,7 +276,7 @@ static SIMPLE_DEV_PM_OPS(puv3_i2c_pm, puv3_i2c_suspend, NULL); static struct platform_driver puv3_i2c_driver = { .probe = puv3_i2c_probe, - .remove = __devexit_p(puv3_i2c_remove), + .remove = puv3_i2c_remove, .driver = { .name = "PKUnity-v3-I2C", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c index 4dc9bef17d7..3d4985695ae 100644 --- a/drivers/i2c/busses/i2c-pxa-pci.c +++ b/drivers/i2c/busses/i2c-pxa-pci.c @@ -94,7 +94,7 @@ out: return ERR_PTR(ret); } -static int __devinit ce4100_i2c_probe(struct pci_dev *dev, +static int ce4100_i2c_probe(struct pci_dev *dev, const struct pci_device_id *ent) { int ret; @@ -135,7 +135,7 @@ err_mem: return ret; } -static void __devexit ce4100_i2c_remove(struct pci_dev *dev) +static void ce4100_i2c_remove(struct pci_dev *dev) { struct ce4100_devices *sds; unsigned int i; @@ -160,7 +160,7 @@ static struct pci_driver ce4100_i2c_driver = { .name = "ce4100_i2c", .id_table = ce4100_i2c_devices, .probe = ce4100_i2c_probe, - .remove = __devexit_p(ce4100_i2c_remove), + .remove = ce4100_i2c_remove, }; module_pci_driver(ce4100_i2c_driver); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index f9399d163af..9bd4d73d29e 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -613,7 +613,7 @@ static const struct i2c_algorithm rcar_i2c_algo = { .functionality = rcar_i2c_func, }; -static int __devinit rcar_i2c_probe(struct platform_device *pdev) +static int rcar_i2c_probe(struct platform_device *pdev) { struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data; struct rcar_i2c_priv *priv; @@ -642,7 +642,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev) if (ret < 0) return ret; - priv->io = devm_ioremap(dev, res->start, resource_size(res)); + priv->io = devm_request_and_ioremap(dev, res); if (!priv->io) { dev_err(dev, "cannot ioremap\n"); return -ENODEV; @@ -682,7 +682,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev) return 0; } -static int __devexit rcar_i2c_remove(struct platform_device *pdev) +static int rcar_i2c_remove(struct platform_device *pdev) { struct rcar_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -693,16 +693,16 @@ static int __devexit rcar_i2c_remove(struct platform_device *pdev) return 0; } -static struct platform_driver rcar_i2c_drv = { +static struct platform_driver rcar_i2c_driver = { .driver = { .name = "i2c-rcar", .owner = THIS_MODULE, }, .probe = rcar_i2c_probe, - .remove = __devexit_p(rcar_i2c_remove), + .remove = rcar_i2c_remove, }; -module_platform_driver(rcar_i2c_drv); +module_platform_driver(rcar_i2c_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Renesas R-Car I2C bus driver"); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 9d902725bac..a290d089cea 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -38,6 +38,7 @@ #include <linux/io.h> #include <linux/of_i2c.h> #include <linux/of_gpio.h> +#include <linux/pinctrl/consumer.h> #include <asm/irq.h> @@ -49,6 +50,9 @@ #define QUIRK_HDMIPHY (1 << 1) #define QUIRK_NO_GPIO (1 << 2) +/* Max time to wait for bus to become idle after a xfer (in us) */ +#define S3C2410_IDLE_TIMEOUT 5000 + /* i2c controller state */ enum s3c24xx_i2c_state { STATE_IDLE, @@ -59,7 +63,6 @@ enum s3c24xx_i2c_state { }; struct s3c24xx_i2c { - spinlock_t lock; wait_queue_head_t wait; unsigned int quirks; unsigned int suspended:1; @@ -78,11 +81,11 @@ struct s3c24xx_i2c { void __iomem *regs; struct clk *clk; struct device *dev; - struct resource *ioarea; struct i2c_adapter adap; struct s3c2410_platform_i2c *pdata; int gpios[2]; + struct pinctrl *pctrl; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif @@ -208,7 +211,7 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, if (msg->flags & I2C_M_REV_DIR_ADDR) addr ^= 1; - /* todo - check for wether ack wanted or not */ + /* todo - check for whether ack wanted or not */ s3c24xx_i2c_enable_ack(i2c); iiccon = readl(i2c->regs + S3C2410_IICCON); @@ -235,8 +238,47 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) dev_dbg(i2c->dev, "STOP\n"); - /* stop the transfer */ - iicstat &= ~S3C2410_IICSTAT_START; + /* + * The datasheet says that the STOP sequence should be: + * 1) I2CSTAT.5 = 0 - Clear BUSY (or 'generate STOP') + * 2) I2CCON.4 = 0 - Clear IRQPEND + * 3) Wait until the stop condition takes effect. + * 4*) I2CSTAT.4 = 0 - Clear TXRXEN + * + * Where, step "4*" is only for buses with the "HDMIPHY" quirk. + * + * However, after much experimentation, it appears that: + * a) normal buses automatically clear BUSY and transition from + * Master->Slave when they complete generating a STOP condition. + * Therefore, step (3) can be done in doxfer() by polling I2CCON.4 + * after starting the STOP generation here. + * b) HDMIPHY bus does neither, so there is no way to do step 3. + * There is no indication when this bus has finished generating + * STOP. + * + * In fact, we have found that as soon as the IRQPEND bit is cleared in + * step 2, the HDMIPHY bus generates the STOP condition, and then + * immediately starts transferring another data byte, even though the + * bus is supposedly stopped. This is presumably because the bus is + * still in "Master" mode, and its BUSY bit is still set. + * + * To avoid these extra post-STOP transactions on HDMI phy devices, we + * just disable Serial Output on the bus (I2CSTAT.4 = 0) directly, + * instead of first generating a proper STOP condition. This should + * float SDA & SCK terminating the transfer. Subsequent transfers + * start with a proper START condition, and proceed normally. + * + * The HDMIPHY bus is an internal bus that always has exactly two + * devices, the host as Master and the HDMIPHY device as the slave. + * Skipping the STOP condition has been tested on this bus and works. + */ + if (i2c->quirks & QUIRK_HDMIPHY) { + /* Stop driving the I2C pins */ + iicstat &= ~S3C2410_IICSTAT_TXRXEN; + } else { + /* stop the transfer */ + iicstat &= ~S3C2410_IICSTAT_START; + } writel(iicstat, i2c->regs + S3C2410_IICSTAT); i2c->state = STATE_STOP; @@ -397,7 +439,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) case STATE_READ: /* we have a byte of data in the data register, do - * something with it, and then work out wether we are + * something with it, and then work out whether we are * going to do any more read/write */ @@ -490,13 +532,6 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) unsigned long iicstat; int timeout = 400; - /* the timeout for HDMIPHY is reduced to 10 ms because - * the hangup is expected to happen, so waiting 400 ms - * causes only unnecessary system hangup - */ - if (i2c->quirks & QUIRK_HDMIPHY) - timeout = 10; - while (timeout-- > 0) { iicstat = readl(i2c->regs + S3C2410_IICSTAT); @@ -506,16 +541,61 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) msleep(1); } - /* hang-up of bus dedicated for HDMIPHY occurred, resetting */ - if (i2c->quirks & QUIRK_HDMIPHY) { - writel(0, i2c->regs + S3C2410_IICCON); - writel(0, i2c->regs + S3C2410_IICSTAT); - writel(0, i2c->regs + S3C2410_IICDS); + return -ETIMEDOUT; +} - return 0; +/* s3c24xx_i2c_wait_idle + * + * wait for the i2c bus to become idle. +*/ + +static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c) +{ + unsigned long iicstat; + ktime_t start, now; + unsigned long delay; + int spins; + + /* ensure the stop has been through the bus */ + + dev_dbg(i2c->dev, "waiting for bus idle\n"); + + start = now = ktime_get(); + + /* + * Most of the time, the bus is already idle within a few usec of the + * end of a transaction. However, really slow i2c devices can stretch + * the clock, delaying STOP generation. + * + * On slower SoCs this typically happens within a very small number of + * instructions so busy wait briefly to avoid scheduling overhead. + */ + spins = 3; + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + while ((iicstat & S3C2410_IICSTAT_START) && --spins) { + cpu_relax(); + iicstat = readl(i2c->regs + S3C2410_IICSTAT); } - return -ETIMEDOUT; + /* + * If we do get an appreciable delay as a compromise between idle + * detection latency for the normal, fast case, and system load in the + * slow device case, use an exponential back off in the polling loop, + * up to 1/10th of the total timeout, then continue to poll at a + * constant rate up to the timeout. + */ + delay = 1; + while ((iicstat & S3C2410_IICSTAT_START) && + ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) { + usleep_range(delay, 2 * delay); + if (delay < S3C2410_IDLE_TIMEOUT / 10) + delay <<= 1; + now = ktime_get(); + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + } + + if (iicstat & S3C2410_IICSTAT_START) + dev_warn(i2c->dev, "timeout waiting for bus idle\n"); } /* s3c24xx_i2c_doxfer @@ -526,8 +606,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { - unsigned long iicstat, timeout; - int spins = 20; + unsigned long timeout; int ret; if (i2c->suspended) @@ -540,8 +619,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, goto out; } - spin_lock_irq(&i2c->lock); - i2c->msg = msgs; i2c->msg_num = num; i2c->msg_ptr = 0; @@ -550,7 +627,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs); - spin_unlock_irq(&i2c->lock); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); @@ -564,24 +640,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, else if (ret != num) dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); - /* ensure the stop has been through the bus */ - - dev_dbg(i2c->dev, "waiting for bus idle\n"); - - /* first, try busy waiting briefly */ - do { - cpu_relax(); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } while ((iicstat & S3C2410_IICSTAT_START) && --spins); - - /* if that timed out sleep */ - if (!spins) { - msleep(1); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } + /* For QUIRK_HDMIPHY, bus is already disabled */ + if (i2c->quirks & QUIRK_HDMIPHY) + goto out; - if (iicstat & S3C2410_IICSTAT_START) - dev_warn(i2c->dev, "timeout waiting for bus idle\n"); + s3c24xx_i2c_wait_idle(i2c); out: return ret; @@ -740,7 +803,6 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data) { struct s3c24xx_i2c *i2c = freq_to_i2c(nb); - unsigned long flags; unsigned int got; int delta_f; int ret; @@ -754,9 +816,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || (val == CPUFREQ_PRECHANGE && delta_f > 0)) { - spin_lock_irqsave(&i2c->lock, flags); + i2c_lock_adapter(&i2c->adap); ret = s3c24xx_i2c_clockrate(i2c, &got); - spin_unlock_irqrestore(&i2c->lock, flags); + i2c_unlock_adapter(&i2c->adap); if (ret < 0) dev_err(i2c->dev, "cannot find frequency\n"); @@ -858,14 +920,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) pdata = i2c->pdata; - /* inititalise the gpio */ - - if (pdata->cfg_gpio) - pdata->cfg_gpio(to_platform_device(i2c->dev)); - else - if (s3c24xx_i2c_parse_dt_gpio(i2c)) - return -EINVAL; - /* write slave address */ writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); @@ -963,7 +1017,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; i2c->tx_setup = 50; - spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wait); /* find the clock and enable it */ @@ -989,36 +1042,38 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) goto err_clk; } - i2c->ioarea = request_mem_region(res->start, resource_size(res), - pdev->name); - - if (i2c->ioarea == NULL) { - dev_err(&pdev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err_clk; - } - - i2c->regs = ioremap(res->start, resource_size(res)); + i2c->regs = devm_request_and_ioremap(&pdev->dev, res); if (i2c->regs == NULL) { dev_err(&pdev->dev, "cannot map IO\n"); ret = -ENXIO; - goto err_ioarea; + goto err_clk; } - dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", - i2c->regs, i2c->ioarea, res); + dev_dbg(&pdev->dev, "registers %p (%p)\n", + i2c->regs, res); /* setup info block for the i2c core */ i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &pdev->dev; + i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev); + + /* inititalise the i2c gpio lines */ + + if (i2c->pdata->cfg_gpio) { + i2c->pdata->cfg_gpio(to_platform_device(i2c->dev)); + } else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) { + ret = -EINVAL; + goto err_clk; + } + /* initialise the i2c controller */ ret = s3c24xx_i2c_init(i2c); if (ret != 0) - goto err_iomap; + goto err_clk; /* find the IRQ for this unit (note, this relies on the init call to * ensure no current IRQs pending @@ -1027,7 +1082,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) i2c->irq = ret = platform_get_irq(pdev, 0); if (ret <= 0) { dev_err(&pdev->dev, "cannot find IRQ\n"); - goto err_iomap; + goto err_clk; } ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0, @@ -1035,7 +1090,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) if (ret != 0) { dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - goto err_iomap; + goto err_clk; } ret = s3c24xx_i2c_register_cpufreq(i2c); @@ -1075,13 +1130,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) err_irq: free_irq(i2c->irq, i2c); - err_iomap: - iounmap(i2c->regs); - - err_ioarea: - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - err_clk: clk_disable_unprepare(i2c->clk); clk_put(i2c->clk); @@ -1110,16 +1158,13 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) clk_disable_unprepare(i2c->clk); clk_put(i2c->clk); - iounmap(i2c->regs); - - release_resource(i2c->ioarea); - s3c24xx_i2c_dt_gpio_free(i2c); - kfree(i2c->ioarea); + if (pdev->dev.of_node && IS_ERR(i2c->pctrl)) + s3c24xx_i2c_dt_gpio_free(i2c); return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int s3c24xx_i2c_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -1142,10 +1187,14 @@ static int s3c24xx_i2c_resume(struct device *dev) return 0; } +#endif +#ifdef CONFIG_PM static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { +#ifdef CONFIG_PM_SLEEP .suspend_noirq = s3c24xx_i2c_suspend_noirq, .resume = s3c24xx_i2c_resume, +#endif }; #define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops) diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c index b76a29d1f8e..008836409ef 100644 --- a/drivers/i2c/busses/i2c-s6000.c +++ b/drivers/i2c/busses/i2c-s6000.c @@ -248,7 +248,7 @@ static struct i2c_algorithm s6i2c_algorithm = { .functionality = s6i2c_functionality, }; -static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns) +static u16 nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns) { u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000; if (dividend > 0xffff) @@ -256,7 +256,7 @@ static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns) return dividend; } -static int __devinit s6i2c_probe(struct platform_device *dev) +static int s6i2c_probe(struct platform_device *dev) { struct s6i2c_if *iface = &s6i2c_if; struct i2c_adapter *p_adap; @@ -361,7 +361,7 @@ err_out: return rc; } -static int __devexit s6i2c_remove(struct platform_device *pdev) +static int s6i2c_remove(struct platform_device *pdev) { struct s6i2c_if *iface = platform_get_drvdata(pdev); i2c_wr16(iface, S6_I2C_ENABLE, 0); @@ -378,7 +378,7 @@ static int __devexit s6i2c_remove(struct platform_device *pdev) static struct platform_driver s6i2c_driver = { .probe = s6i2c_probe, - .remove = __devexit_p(s6i2c_remove), + .remove = s6i2c_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index c0c9dffbdb1..3a2253e1bf5 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -390,7 +390,7 @@ static const struct i2c_algorithm sh7760_i2c_algo = { * iclk = mclk/(CDF + 1). iclk must be < 20MHz. * scl = iclk/(SCGD*8 + 20). */ -static int __devinit calc_CCR(unsigned long scl_hz) +static int calc_CCR(unsigned long scl_hz) { struct clk *mclk; unsigned long mck, m1, dff, odff, iclk; @@ -430,7 +430,7 @@ static int __devinit calc_CCR(unsigned long scl_hz) return ((scgdm << 2) | cdfm); } -static int __devinit sh7760_i2c_probe(struct platform_device *pdev) +static int sh7760_i2c_probe(struct platform_device *pdev) { struct sh7760_i2c_platdata *pd; struct resource *res; @@ -536,7 +536,7 @@ out0: return ret; } -static int __devexit sh7760_i2c_remove(struct platform_device *pdev) +static int sh7760_i2c_remove(struct platform_device *pdev) { struct cami2c *id = platform_get_drvdata(pdev); @@ -557,7 +557,7 @@ static struct platform_driver sh7760_i2c_drv = { .owner = THIS_MODULE, }, .probe = sh7760_i2c_probe, - .remove = __devexit_p(sh7760_i2c_remove), + .remove = sh7760_i2c_remove, }; module_platform_driver(sh7760_i2c_drv); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 8110ca45f34..b6e7a83a829 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -120,11 +120,12 @@ struct sh_mobile_i2c_data { void __iomem *reg; struct i2c_adapter adap; unsigned long bus_speed; + unsigned int clks_per_count; struct clk *clk; u_int8_t icic; - u_int8_t iccl; - u_int8_t icch; u_int8_t flags; + u_int16_t iccl; + u_int16_t icch; spinlock_t lock; wait_queue_head_t wait; @@ -135,7 +136,8 @@ struct sh_mobile_i2c_data { #define IIC_FLAG_HAS_ICIC67 (1 << 0) -#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ +#define STANDARD_MODE 100000 +#define FAST_MODE 400000 /* Register offsets */ #define ICDR 0x00 @@ -187,57 +189,90 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); } -static void activate_ch(struct sh_mobile_i2c_data *pd) +static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset) { - unsigned long i2c_clk; - u_int32_t num; - u_int32_t denom; - u_int32_t tmp; - - /* Wake up device and enable clock */ - pm_runtime_get_sync(pd->dev); - clk_enable(pd->clk); - - /* Get clock rate after clock is enabled */ - i2c_clk = clk_get_rate(pd->clk); + /* + * Conditional expression: + * ICCL >= COUNT_CLK * (tLOW + tf) + * + * SH-Mobile IIC hardware starts counting the LOW period of + * the SCL signal (tLOW) as soon as it pulls the SCL line. + * In order to meet the tLOW timing spec, we need to take into + * account the fall time of SCL signal (tf). Default tf value + * should be 0.3 us, for safety. + */ + return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset; +} - /* Calculate the value for iccl. From the data sheet: - * iccl = (p clock / transfer rate) * (L / (L + H)) - * where L and H are the SCL low/high ratio (5/4 in this case). - * We also round off the result. +static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset) +{ + /* + * Conditional expression: + * ICCH >= COUNT_CLK * (tHIGH + tf) + * + * SH-Mobile IIC hardware is aware of SCL transition period 'tr', + * and can ignore it. SH-Mobile IIC controller starts counting + * the HIGH period of the SCL signal (tHIGH) after the SCL input + * voltage increases at VIH. + * + * Afterward it turned out calculating ICCH using only tHIGH spec + * will result in violation of the tHD;STA timing spec. We need + * to take into account the fall time of SDA signal (tf) at START + * condition, in order to meet both tHIGH and tHD;STA specs. */ - num = i2c_clk * 5; - denom = pd->bus_speed * 9; - tmp = num * 10 / denom; - if (tmp % 10 >= 5) - pd->iccl = (u_int8_t)((num/denom) + 1); - else - pd->iccl = (u_int8_t)(num/denom); + return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset; +} - /* one more bit of ICCL in ICIC */ - if (pd->flags & IIC_FLAG_HAS_ICIC67) { - if ((num/denom) > 0xff) - pd->icic |= ICIC_ICCLB8; - else - pd->icic &= ~ICIC_ICCLB8; +static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd) +{ + unsigned long i2c_clk_khz; + u32 tHIGH, tLOW, tf; + int offset; + + /* Get clock rate after clock is enabled */ + clk_enable(pd->clk); + i2c_clk_khz = clk_get_rate(pd->clk) / 1000; + i2c_clk_khz /= pd->clks_per_count; + + if (pd->bus_speed == STANDARD_MODE) { + tLOW = 47; /* tLOW = 4.7 us */ + tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */ + tf = 3; /* tf = 0.3 us */ + offset = 0; /* No offset */ + } else if (pd->bus_speed == FAST_MODE) { + tLOW = 13; /* tLOW = 1.3 us */ + tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */ + tf = 3; /* tf = 0.3 us */ + offset = 0; /* No offset */ + } else { + dev_err(pd->dev, "unrecognized bus speed %lu Hz\n", + pd->bus_speed); + goto out; } - /* Calculate the value for icch. From the data sheet: - icch = (p clock / transfer rate) * (H / (L + H)) */ - num = i2c_clk * 4; - tmp = num * 10 / denom; - if (tmp % 10 >= 5) - pd->icch = (u_int8_t)((num/denom) + 1); + pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset); + /* one more bit of ICCL in ICIC */ + if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67)) + pd->icic |= ICIC_ICCLB8; else - pd->icch = (u_int8_t)(num/denom); + pd->icic &= ~ICIC_ICCLB8; + pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset); /* one more bit of ICCH in ICIC */ - if (pd->flags & IIC_FLAG_HAS_ICIC67) { - if ((num/denom) > 0xff) - pd->icic |= ICIC_ICCHB8; - else - pd->icic &= ~ICIC_ICCHB8; - } + if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67)) + pd->icic |= ICIC_ICCHB8; + else + pd->icic &= ~ICIC_ICCHB8; + +out: + clk_disable(pd->clk); +} + +static void activate_ch(struct sh_mobile_i2c_data *pd) +{ + /* Wake up device and enable clock */ + pm_runtime_get_sync(pd->dev); + clk_enable(pd->clk); /* Enable channel and configure rx ack */ iic_set_clr(pd, ICCR, ICCR_ICE, 0); @@ -246,8 +281,8 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) iic_wr(pd, ICIC, 0); /* Set the clock */ - iic_wr(pd, ICCL, pd->iccl); - iic_wr(pd, ICCH, pd->icch); + iic_wr(pd, ICCL, pd->iccl & 0xff); + iic_wr(pd, ICCH, pd->icch & 0xff); } static void deactivate_ch(struct sh_mobile_i2c_data *pd) @@ -434,6 +469,9 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) wake_up(&pd->wait); } + /* defeat write posting to avoid spurious WAIT interrupts */ + iic_rd(pd, ICSR); + return IRQ_HANDLED; } @@ -451,8 +489,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) iic_set_clr(pd, ICCR, ICCR_ICE, 0); /* Set the clock */ - iic_wr(pd, ICCL, pd->iccl); - iic_wr(pd, ICCH, pd->icch); + iic_wr(pd, ICCL, pd->iccl & 0xff); + iic_wr(pd, ICCH, pd->icch & 0xff); pd->msg = usr_msg; pd->pos = -1; @@ -621,10 +659,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) goto err_irq; } - /* Use platformd data bus speed or NORMAL_SPEED */ - pd->bus_speed = NORMAL_SPEED; + /* Use platform data bus speed or STANDARD_MODE */ + pd->bus_speed = STANDARD_MODE; if (pdata && pdata->bus_speed) pd->bus_speed = pdata->bus_speed; + pd->clks_per_count = 1; + if (pdata && pdata->clks_per_count) + pd->clks_per_count = pdata->clks_per_count; /* The IIC blocks on SH-Mobile ARM processors * come with two new bits in ICIC. @@ -632,6 +673,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) if (size > 0x17) pd->flags |= IIC_FLAG_HAS_ICIC67; + sh_mobile_i2c_init(pd); + /* Enable Runtime PM for this device. * * Also tell the Runtime PM core to ignore children @@ -667,8 +710,9 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) goto err_all; } - dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n", - adap->nr, pd->bus_speed); + dev_info(&dev->dev, + "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n", + adap->nr, pd->bus_speed, pd->iccl, pd->icch); of_i2c_register_devices(adap); return 0; @@ -714,7 +758,7 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { .runtime_resume = sh_mobile_i2c_runtime_nop, }; -static const struct of_device_id sh_mobile_i2c_dt_ids[] __devinitconst = { +static const struct of_device_id sh_mobile_i2c_dt_ids[] = { { .compatible = "renesas,rmobile-iic", }, {}, }; diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 5574a47792f..3f1818b8797 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -258,7 +258,7 @@ static const struct i2c_algorithm i2c_sirfsoc_algo = { .functionality = i2c_sirfsoc_func, }; -static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev) +static int i2c_sirfsoc_probe(struct platform_device *pdev) { struct sirfsoc_i2c *siic; struct i2c_adapter *adap; @@ -385,7 +385,7 @@ err_get_clk: return err; } -static int __devexit i2c_sirfsoc_remove(struct platform_device *pdev) +static int i2c_sirfsoc_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); struct sirfsoc_i2c *siic = adapter->algo_data; @@ -433,7 +433,7 @@ static const struct dev_pm_ops i2c_sirfsoc_pm_ops = { }; #endif -static const struct of_device_id sirfsoc_i2c_of_match[] __devinitconst = { +static const struct of_device_id sirfsoc_i2c_of_match[] = { { .compatible = "sirf,prima2-i2c", }, {}, }; @@ -449,7 +449,7 @@ static struct platform_driver i2c_sirfsoc_driver = { .of_match_table = sirfsoc_i2c_of_match, }, .probe = i2c_sirfsoc_probe, - .remove = __devexit_p(i2c_sirfsoc_remove), + .remove = i2c_sirfsoc_remove, }; module_platform_driver(i2c_sirfsoc_driver); diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 87e5126d449..79fd96a0438 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -142,7 +142,7 @@ static void sis5595_write(u8 reg, u8 data) outb(data, sis5595_base + SMB_DAT); } -static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev) +static int sis5595_setup(struct pci_dev *SIS5595_dev) { u16 a; u8 val; @@ -376,7 +376,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis5595_ids) = { MODULE_DEVICE_TABLE (pci, sis5595_ids); -static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) { int err; diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 5d6723b7525..de6dddb9f86 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -389,7 +389,7 @@ static u32 sis630_func(struct i2c_adapter *adapter) I2C_FUNC_SMBUS_BLOCK_DATA; } -static int __devinit sis630_setup(struct pci_dev *sis630_dev) +static int sis630_setup(struct pci_dev *sis630_dev) { unsigned char b; struct pci_dev *dummy = NULL; @@ -480,7 +480,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = { MODULE_DEVICE_TABLE (pci, sis630_ids); -static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (sis630_setup(dev)) { dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n"); @@ -496,7 +496,7 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i return i2c_add_adapter(&sis630_adapter); } -static void __devexit sis630_remove(struct pci_dev *dev) +static void sis630_remove(struct pci_dev *dev) { if (acpi_base) { i2c_del_adapter(&sis630_adapter); @@ -510,7 +510,7 @@ static struct pci_driver sis630_driver = { .name = "sis630_smbus", .id_table = sis630_ids, .probe = sis630_probe, - .remove = __devexit_p(sis630_remove), + .remove = sis630_remove, }; module_pci_driver(sis630_driver); diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 7b72614a9bc..b9faf9b6002 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -252,7 +252,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis96x_ids) = { MODULE_DEVICE_TABLE (pci, sis96x_ids); -static int __devinit sis96x_probe(struct pci_dev *dev, +static int sis96x_probe(struct pci_dev *dev, const struct pci_device_id *id) { u16 ww = 0; @@ -308,7 +308,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev, return retval; } -static void __devexit sis96x_remove(struct pci_dev *dev) +static void sis96x_remove(struct pci_dev *dev) { if (sis96x_smbus_base) { i2c_del_adapter(&sis96x_adapter); @@ -321,7 +321,7 @@ static struct pci_driver sis96x_driver = { .name = "sis96x_smbus", .id_table = sis96x_ids, .probe = sis96x_probe, - .remove = __devexit_p(sis96x_remove), + .remove = sis96x_remove, }; module_pci_driver(sis96x_driver); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index dcea77bf6f5..7b38877ffec 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -642,7 +642,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { #if defined(CONFIG_OF) /* Match table for of_platform binding */ -static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { +static const struct of_device_id tegra_i2c_of_match[] = { { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, @@ -651,7 +651,7 @@ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); #endif -static int __devinit tegra_i2c_probe(struct platform_device *pdev) +static int tegra_i2c_probe(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; @@ -769,7 +769,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) return 0; } -static int __devexit tegra_i2c_remove(struct platform_device *pdev) +static int tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adapter); @@ -817,7 +817,7 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume); static struct platform_driver tegra_i2c_driver = { .probe = tegra_i2c_probe, - .remove = __devexit_p(tegra_i2c_remove), + .remove = tegra_i2c_remove, .driver = { .name = "tegra-i2c", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index 7ffee71ca19..be662511c58 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c @@ -96,7 +96,7 @@ static DEFINE_PCI_DEVICE_TABLE(vt586b_ids) = { MODULE_DEVICE_TABLE (pci, vt586b_ids); -static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) { u16 base; u8 rev; @@ -146,7 +146,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i return 0; } -static void __devexit vt586b_remove(struct pci_dev *dev) +static void vt586b_remove(struct pci_dev *dev) { i2c_del_adapter(&vt586b_adapter); release_region(I2C_DIR, IOSPACE); @@ -158,7 +158,7 @@ static struct pci_driver vt586b_driver = { .name = "vt586b_smbus", .id_table = vt586b_ids, .probe = vt586b_probe, - .remove = __devexit_p(vt586b_remove), + .remove = vt586b_remove, }; module_pci_driver(vt586b_driver); diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 271c9a2b0fd..b2d90e105f4 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -320,8 +320,8 @@ static struct i2c_adapter vt596_adapter = { .algo = &smbus_algorithm, }; -static int __devinit vt596_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int vt596_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { unsigned char temp; int error; diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c new file mode 100644 index 00000000000..f45c32c1ace --- /dev/null +++ b/drivers/i2c/busses/i2c-viperboard.c @@ -0,0 +1,480 @@ +/* + * Nano River Technologies viperboard i2c master driver + * + * (C) 2012 by Lemonage GmbH + * Author: Lars Poeschel <poeschel@lemonage.de> + * All rights reserved. + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> + +#include <linux/usb.h> +#include <linux/i2c.h> + +#include <linux/mfd/viperboard.h> + +struct vprbrd_i2c { + struct i2c_adapter i2c; + u8 bus_freq_param; +}; + +/* i2c bus frequency module parameter */ +static u8 i2c_bus_param; +static unsigned int i2c_bus_freq = 100; +module_param(i2c_bus_freq, int, 0); +MODULE_PARM_DESC(i2c_bus_freq, + "i2c bus frequency in khz (default is 100) valid values: 10, 100, 200, 400, 1000, 3000, 6000"); + +static int vprbrd_i2c_status(struct i2c_adapter *i2c, + struct vprbrd_i2c_status *status, bool prev_error) +{ + u16 bytes_xfer; + int ret; + struct vprbrd *vb = (struct vprbrd *)i2c->algo_data; + + /* check for protocol error */ + bytes_xfer = sizeof(struct vprbrd_i2c_status); + + ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0), + VPRBRD_USB_REQUEST_I2C, VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, + status, bytes_xfer, VPRBRD_USB_TIMEOUT_MS); + + if (ret != bytes_xfer) + prev_error = true; + + if (prev_error) { + dev_err(&i2c->dev, "failure in usb communication\n"); + return -EREMOTEIO; + } + + dev_dbg(&i2c->dev, " status = %d\n", status->status); + if (status->status != 0x00) { + dev_err(&i2c->dev, "failure: i2c protocol error\n"); + return -EPROTO; + } + return 0; +} + +static int vprbrd_i2c_receive(struct usb_device *usb_dev, + struct vprbrd_i2c_read_msg *rmsg, int bytes_xfer) +{ + int ret, bytes_actual; + int error = 0; + + /* send the read request */ + ret = usb_bulk_msg(usb_dev, + usb_sndbulkpipe(usb_dev, VPRBRD_EP_OUT), rmsg, + sizeof(struct vprbrd_i2c_read_hdr), &bytes_actual, + VPRBRD_USB_TIMEOUT_MS); + + if ((ret < 0) + || (bytes_actual != sizeof(struct vprbrd_i2c_read_hdr))) { + dev_err(&usb_dev->dev, "failure transmitting usb\n"); + error = -EREMOTEIO; + } + + /* read the actual data */ + ret = usb_bulk_msg(usb_dev, + usb_rcvbulkpipe(usb_dev, VPRBRD_EP_IN), rmsg, + bytes_xfer, &bytes_actual, VPRBRD_USB_TIMEOUT_MS); + + if ((ret < 0) || (bytes_xfer != bytes_actual)) { + dev_err(&usb_dev->dev, "failure receiving usb\n"); + error = -EREMOTEIO; + } + return error; +} + +static int vprbrd_i2c_addr(struct usb_device *usb_dev, + struct vprbrd_i2c_addr_msg *amsg) +{ + int ret, bytes_actual; + + ret = usb_bulk_msg(usb_dev, + usb_sndbulkpipe(usb_dev, VPRBRD_EP_OUT), amsg, + sizeof(struct vprbrd_i2c_addr_msg), &bytes_actual, + VPRBRD_USB_TIMEOUT_MS); + + if ((ret < 0) || + (sizeof(struct vprbrd_i2c_addr_msg) != bytes_actual)) { + dev_err(&usb_dev->dev, "failure transmitting usb\n"); + return -EREMOTEIO; + } + return 0; +} + +static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg) +{ + int ret; + u16 remain_len, bytes_xfer, len1, len2, + start = 0x0000; + struct vprbrd_i2c_read_msg *rmsg = + (struct vprbrd_i2c_read_msg *)vb->buf; + + remain_len = msg->len; + rmsg->header.cmd = VPRBRD_I2C_CMD_READ; + while (remain_len > 0) { + rmsg->header.addr = cpu_to_le16(start + 0x4000); + if (remain_len <= 255) { + len1 = remain_len; + len2 = 0x00; + rmsg->header.len0 = remain_len; + rmsg->header.len1 = 0x00; + rmsg->header.len2 = 0x00; + rmsg->header.len3 = 0x00; + rmsg->header.len4 = 0x00; + rmsg->header.len5 = 0x00; + remain_len = 0; + } else if (remain_len <= 510) { + len1 = remain_len; + len2 = 0x00; + rmsg->header.len0 = remain_len - 255; + rmsg->header.len1 = 0xff; + rmsg->header.len2 = 0x00; + rmsg->header.len3 = 0x00; + rmsg->header.len4 = 0x00; + rmsg->header.len5 = 0x00; + remain_len = 0; + } else if (remain_len <= 512) { + len1 = remain_len; + len2 = 0x00; + rmsg->header.len0 = remain_len - 510; + rmsg->header.len1 = 0xff; + rmsg->header.len2 = 0xff; + rmsg->header.len3 = 0x00; + rmsg->header.len4 = 0x00; + rmsg->header.len5 = 0x00; + remain_len = 0; + } else if (remain_len <= 767) { + len1 = 512; + len2 = remain_len - 512; + rmsg->header.len0 = 0x02; + rmsg->header.len1 = 0xff; + rmsg->header.len2 = 0xff; + rmsg->header.len3 = remain_len - 512; + rmsg->header.len4 = 0x00; + rmsg->header.len5 = 0x00; + bytes_xfer = remain_len; + remain_len = 0; + } else if (remain_len <= 1022) { + len1 = 512; + len2 = remain_len - 512; + rmsg->header.len0 = 0x02; + rmsg->header.len1 = 0xff; + rmsg->header.len2 = 0xff; + rmsg->header.len3 = remain_len - 767; + rmsg->header.len4 = 0xff; + rmsg->header.len5 = 0x00; + remain_len = 0; + } else if (remain_len <= 1024) { + len1 = 512; + len2 = remain_len - 512; + rmsg->header.len0 = 0x02; + rmsg->header.len1 = 0xff; + rmsg->header.len2 = 0xff; + rmsg->header.len3 = remain_len - 1022; + rmsg->header.len4 = 0xff; + rmsg->header.len5 = 0xff; + remain_len = 0; + } else { + len1 = 512; + len2 = 512; + rmsg->header.len0 = 0x02; + rmsg->header.len1 = 0xff; + rmsg->header.len2 = 0xff; + rmsg->header.len3 = 0x02; + rmsg->header.len4 = 0xff; + rmsg->header.len5 = 0xff; + remain_len -= 1024; + start += 1024; + } + rmsg->header.tf1 = cpu_to_le16(len1); + rmsg->header.tf2 = cpu_to_le16(len2); + + /* first read transfer */ + ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len1); + if (ret < 0) + return ret; + /* copy the received data */ + memcpy(msg->buf + start, rmsg, len1); + + /* second read transfer if neccessary */ + if (len2 > 0) { + ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len2); + if (ret < 0) + return ret; + /* copy the received data */ + memcpy(msg->buf + start + 512, rmsg, len2); + } + } + return 0; +} + +static int vprbrd_i2c_write(struct vprbrd *vb, struct i2c_msg *msg) +{ + int ret, bytes_actual; + u16 remain_len, bytes_xfer, + start = 0x0000; + struct vprbrd_i2c_write_msg *wmsg = + (struct vprbrd_i2c_write_msg *)vb->buf; + + remain_len = msg->len; + wmsg->header.cmd = VPRBRD_I2C_CMD_WRITE; + wmsg->header.last = 0x00; + wmsg->header.chan = 0x00; + wmsg->header.spi = 0x0000; + while (remain_len > 0) { + wmsg->header.addr = cpu_to_le16(start + 0x4000); + if (remain_len > 503) { + wmsg->header.len1 = 0xff; + wmsg->header.len2 = 0xf8; + remain_len -= 503; + bytes_xfer = 503 + sizeof(struct vprbrd_i2c_write_hdr); + start += 503; + } else if (remain_len > 255) { + wmsg->header.len1 = 0xff; + wmsg->header.len2 = (remain_len - 255); + bytes_xfer = remain_len + + sizeof(struct vprbrd_i2c_write_hdr); + remain_len = 0; + } else { + wmsg->header.len1 = remain_len; + wmsg->header.len2 = 0x00; + bytes_xfer = remain_len + + sizeof(struct vprbrd_i2c_write_hdr); + remain_len = 0; + } + memcpy(wmsg->data, msg->buf + start, + bytes_xfer - sizeof(struct vprbrd_i2c_write_hdr)); + + ret = usb_bulk_msg(vb->usb_dev, + usb_sndbulkpipe(vb->usb_dev, + VPRBRD_EP_OUT), wmsg, + bytes_xfer, &bytes_actual, VPRBRD_USB_TIMEOUT_MS); + if ((ret < 0) || (bytes_xfer != bytes_actual)) + return -EREMOTEIO; + } + return 0; +} + +static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs, + int num) +{ + struct i2c_msg *pmsg; + int i, ret, + error = 0; + struct vprbrd *vb = (struct vprbrd *)i2c->algo_data; + struct vprbrd_i2c_addr_msg *amsg = + (struct vprbrd_i2c_addr_msg *)vb->buf; + struct vprbrd_i2c_status *smsg = (struct vprbrd_i2c_status *)vb->buf; + + dev_dbg(&i2c->dev, "master xfer %d messages:\n", num); + + for (i = 0 ; i < num ; i++) { + pmsg = &msgs[i]; + + dev_dbg(&i2c->dev, + " %d: %s (flags %d) %d bytes to 0x%02x\n", + i, pmsg->flags & I2C_M_RD ? "read" : "write", + pmsg->flags, pmsg->len, pmsg->addr); + + /* msgs longer than 2048 bytes are not supported by adapter */ + if (pmsg->len > 2048) + return -EINVAL; + + mutex_lock(&vb->lock); + /* directly send the message */ + if (pmsg->flags & I2C_M_RD) { + /* read data */ + amsg->cmd = VPRBRD_I2C_CMD_ADDR; + amsg->unknown2 = 0x00; + amsg->unknown3 = 0x00; + amsg->addr = pmsg->addr; + amsg->unknown1 = 0x01; + amsg->len = cpu_to_le16(pmsg->len); + /* send the addr and len, we're interested to board */ + ret = vprbrd_i2c_addr(vb->usb_dev, amsg); + if (ret < 0) + error = ret; + + ret = vprbrd_i2c_read(vb, pmsg); + if (ret < 0) + error = ret; + + ret = vprbrd_i2c_status(i2c, smsg, error); + if (ret < 0) + error = ret; + /* in case of protocol error, return the error */ + if (error < 0) + goto error; + } else { + /* write data */ + ret = vprbrd_i2c_write(vb, pmsg); + + amsg->cmd = VPRBRD_I2C_CMD_ADDR; + amsg->unknown2 = 0x00; + amsg->unknown3 = 0x00; + amsg->addr = pmsg->addr; + amsg->unknown1 = 0x00; + amsg->len = cpu_to_le16(pmsg->len); + /* send the addr, the data goes to to board */ + ret = vprbrd_i2c_addr(vb->usb_dev, amsg); + if (ret < 0) + error = ret; + + ret = vprbrd_i2c_status(i2c, smsg, error); + if (ret < 0) + error = ret; + + if (error < 0) + goto error; + } + mutex_unlock(&vb->lock); + } + return 0; +error: + mutex_unlock(&vb->lock); + return error; +} + +static u32 vprbrd_i2c_func(struct i2c_adapter *i2c) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +/* This is the actual algorithm we define */ +static const struct i2c_algorithm vprbrd_algorithm = { + .master_xfer = vprbrd_i2c_xfer, + .functionality = vprbrd_i2c_func, +}; + +static int vprbrd_i2c_probe(struct platform_device *pdev) +{ + struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent); + struct vprbrd_i2c *vb_i2c; + int ret; + int pipe; + + vb_i2c = kzalloc(sizeof(*vb_i2c), GFP_KERNEL); + if (vb_i2c == NULL) + return -ENOMEM; + + /* setup i2c adapter description */ + vb_i2c->i2c.owner = THIS_MODULE; + vb_i2c->i2c.class = I2C_CLASS_HWMON; + vb_i2c->i2c.algo = &vprbrd_algorithm; + vb_i2c->i2c.algo_data = vb; + /* save the param in usb capabable memory */ + vb_i2c->bus_freq_param = i2c_bus_param; + + snprintf(vb_i2c->i2c.name, sizeof(vb_i2c->i2c.name), + "viperboard at bus %03d device %03d", + vb->usb_dev->bus->busnum, vb->usb_dev->devnum); + + /* setting the bus frequency */ + if ((i2c_bus_param <= VPRBRD_I2C_FREQ_10KHZ) + && (i2c_bus_param >= VPRBRD_I2C_FREQ_6MHZ)) { + pipe = usb_sndctrlpipe(vb->usb_dev, 0); + ret = usb_control_msg(vb->usb_dev, pipe, + VPRBRD_USB_REQUEST_I2C_FREQ, VPRBRD_USB_TYPE_OUT, + 0x0000, 0x0000, &vb_i2c->bus_freq_param, 1, + VPRBRD_USB_TIMEOUT_MS); + if (ret != 1) { + dev_err(&pdev->dev, + "failure setting i2c_bus_freq to %d\n", i2c_bus_freq); + ret = -EIO; + goto error; + } + } else { + dev_err(&pdev->dev, + "invalid i2c_bus_freq setting:%d\n", i2c_bus_freq); + ret = -EIO; + goto error; + } + + vb_i2c->i2c.dev.parent = &pdev->dev; + + /* attach to i2c layer */ + i2c_add_adapter(&vb_i2c->i2c); + + platform_set_drvdata(pdev, vb_i2c); + + return 0; + +error: + kfree(vb_i2c); + return ret; +} + +static int vprbrd_i2c_remove(struct platform_device *pdev) +{ + struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev); + int ret; + + ret = i2c_del_adapter(&vb_i2c->i2c); + + return ret; +} + +static struct platform_driver vprbrd_i2c_driver = { + .driver.name = "viperboard-i2c", + .driver.owner = THIS_MODULE, + .probe = vprbrd_i2c_probe, + .remove = vprbrd_i2c_remove, +}; + +static int __init vprbrd_i2c_init(void) +{ + switch (i2c_bus_freq) { + case 6000: + i2c_bus_param = VPRBRD_I2C_FREQ_6MHZ; + break; + case 3000: + i2c_bus_param = VPRBRD_I2C_FREQ_3MHZ; + break; + case 1000: + i2c_bus_param = VPRBRD_I2C_FREQ_1MHZ; + break; + case 400: + i2c_bus_param = VPRBRD_I2C_FREQ_400KHZ; + break; + case 200: + i2c_bus_param = VPRBRD_I2C_FREQ_200KHZ; + break; + case 100: + i2c_bus_param = VPRBRD_I2C_FREQ_100KHZ; + break; + case 10: + i2c_bus_param = VPRBRD_I2C_FREQ_10KHZ; + break; + default: + pr_warn("invalid i2c_bus_freq (%d)\n", i2c_bus_freq); + i2c_bus_param = VPRBRD_I2C_FREQ_100KHZ; + } + + return platform_driver_register(&vprbrd_i2c_driver); +} +subsys_initcall(vprbrd_i2c_init); + +static void __exit vprbrd_i2c_exit(void) +{ + platform_driver_unregister(&vprbrd_i2c_driver); +} +module_exit(vprbrd_i2c_exit); + +MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>"); +MODULE_DESCRIPTION("I2C master driver for Nano River Techs Viperboard"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:viperboard-i2c"); diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 641d0e5e330..f042f6da0ac 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -689,7 +689,7 @@ static struct i2c_adapter xiic_adapter = { }; -static int __devinit xiic_i2c_probe(struct platform_device *pdev) +static int xiic_i2c_probe(struct platform_device *pdev) { struct xiic_i2c *i2c; struct xiic_i2c_platform_data *pdata; @@ -774,7 +774,7 @@ resource_missing: return -ENOENT; } -static int __devexit xiic_i2c_remove(struct platform_device* pdev) +static int xiic_i2c_remove(struct platform_device *pdev) { struct xiic_i2c *i2c = platform_get_drvdata(pdev); struct resource *res; @@ -800,7 +800,7 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev) } #if defined(CONFIG_OF) -static const struct of_device_id xiic_of_match[] __devinitconst = { +static const struct of_device_id xiic_of_match[] = { { .compatible = "xlnx,xps-iic-2.00.a", }, {}, }; @@ -809,7 +809,7 @@ MODULE_DEVICE_TABLE(of, xiic_of_match); static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, - .remove = __devexit_p(xiic_i2c_remove), + .remove = xiic_i2c_remove, .driver = { .owner = THIS_MODULE, .name = DRIVER_NAME, diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c index 96d3fabd888..a005265461d 100644 --- a/drivers/i2c/busses/i2c-xlr.c +++ b/drivers/i2c/busses/i2c-xlr.c @@ -214,7 +214,7 @@ static struct i2c_algorithm xlr_i2c_algo = { .functionality = xlr_func, }; -static int __devinit xlr_i2c_probe(struct platform_device *pdev) +static int xlr_i2c_probe(struct platform_device *pdev) { struct xlr_i2c_private *priv; struct resource *res; @@ -251,7 +251,7 @@ static int __devinit xlr_i2c_probe(struct platform_device *pdev) return 0; } -static int __devexit xlr_i2c_remove(struct platform_device *pdev) +static int xlr_i2c_remove(struct platform_device *pdev) { struct xlr_i2c_private *priv; @@ -263,7 +263,7 @@ static int __devexit xlr_i2c_remove(struct platform_device *pdev) static struct platform_driver xlr_i2c_driver = { .probe = xlr_i2c_probe, - .remove = __devexit_p(xlr_i2c_remove), + .remove = xlr_i2c_remove, .driver = { .name = "xlr-i2cbus", .owner = THIS_MODULE, diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 08aab57337d..3862a953239 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -389,7 +389,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = { static struct scx200_acb_iface *scx200_acb_list; static DEFINE_MUTEX(scx200_acb_list_mutex); -static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface) +static int scx200_acb_probe(struct scx200_acb_iface *iface) { u8 val; @@ -424,7 +424,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface) return 0; } -static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text, +static struct scx200_acb_iface *scx200_create_iface(const char *text, struct device *dev, int index) { struct scx200_acb_iface *iface; @@ -449,7 +449,7 @@ static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text, return iface; } -static int __devinit scx200_acb_create(struct scx200_acb_iface *iface) +static int scx200_acb_create(struct scx200_acb_iface *iface) { struct i2c_adapter *adapter; int rc; @@ -480,7 +480,7 @@ static int __devinit scx200_acb_create(struct scx200_acb_iface *iface) return 0; } -static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text, +static struct scx200_acb_iface *scx200_create_dev(const char *text, unsigned long base, int index, struct device *dev) { struct scx200_acb_iface *iface; @@ -508,7 +508,7 @@ static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text, return NULL; } -static int __devinit scx200_probe(struct platform_device *pdev) +static int scx200_probe(struct platform_device *pdev) { struct scx200_acb_iface *iface; struct resource *res; @@ -530,14 +530,14 @@ static int __devinit scx200_probe(struct platform_device *pdev) return 0; } -static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface) +static void scx200_cleanup_iface(struct scx200_acb_iface *iface) { i2c_del_adapter(&iface->adapter); release_region(iface->base, 8); kfree(iface); } -static int __devexit scx200_remove(struct platform_device *pdev) +static int scx200_remove(struct platform_device *pdev) { struct scx200_acb_iface *iface; @@ -554,7 +554,7 @@ static struct platform_driver scx200_pci_driver = { .owner = THIS_MODULE, }, .probe = scx200_probe, - .remove = __devexit_p(scx200_remove), + .remove = scx200_remove, }; static DEFINE_PCI_DEVICE_TABLE(scx200_isa) = { |