Merge branch 'for-linus/2639/i2c-2' of git://git.fluff.org/bjdooks/linux

* 'for-linus/2639/i2c-2' of git://git.fluff.org/bjdooks/linux:
  i2c-pxa2xx: Don't clear isr bits too early
  i2c-pxa2xx: Fix register offsets
  i2c-pxa2xx: pass of_node from platform driver to adapter and publish
  i2c-pxa2xx: check timeout correctly
  i2c-pxa2xx: add support for shared IRQ handler
  i2c-pxa2xx: Add PCI support for PXA I2C controller
  ARM: pxa2xx: reorganize I2C files
  i2c-pxa2xx: use dynamic register layout
  i2c-mxs: set controller to pio queue mode after reset
  i2c-eg20t: support new device OKI SEMICONDUCTOR ML7213 IOH
  i2c/busses: Add support for Diolan U2C-12 USB-I2C adapter
This commit is contained in:
Linus Torvalds 2011-03-22 10:05:27 -07:00
commit 75ea6358bc
48 changed files with 996 additions and 147 deletions

View file

@ -0,0 +1,26 @@
Kernel driver i2c-diolan-u2c
Supported adapters:
* Diolan U2C-12 I2C-USB adapter
Documentation:
http://www.diolan.com/i2c/u2c12.html
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
This is the driver for the Diolan U2C-12 USB-I2C adapter.
The Diolan U2C-12 I2C-USB Adapter provides a low cost solution to connect
a computer to I2C slave devices using a USB interface. It also supports
connectivity to SPI devices.
This driver only supports the I2C interface of U2C-12. The driver does not use
interrupts.
Module parameters
-----------------
* frequency: I2C bus frequency

View file

@ -2138,6 +2138,12 @@ F: Documentation/serial/digiepca.txt
F: drivers/char/epca* F: drivers/char/epca*
F: drivers/char/digi* F: drivers/char/digi*
DIOLAN U2C-12 I2C DRIVER
M: Guenter Roeck <guenter.roeck@ericsson.com>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-diolan-u2c.c
DIRECTORY NOTIFICATION (DNOTIFY) DIRECTORY NOTIFICATION (DNOTIFY)
M: Eric Paris <eparis@parisplace.org> M: Eric Paris <eparis@parisplace.org>
S: Maintained S: Maintained

View file

@ -11,8 +11,8 @@ extern void __init mmp2_init_irq(void);
extern void mmp2_clear_pmic_int(void); extern void mmp2_clear_pmic_int(void);
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <mach/devices.h> #include <mach/devices.h>
#include <plat/i2c.h>
extern struct pxa_device_desc mmp2_device_uart1; extern struct pxa_device_desc mmp2_device_uart1;
extern struct pxa_device_desc mmp2_device_uart2; extern struct pxa_device_desc mmp2_device_uart2;

View file

@ -8,8 +8,8 @@ extern void __init pxa168_init_irq(void);
extern void pxa168_clear_keypad_wakeup(void); extern void pxa168_clear_keypad_wakeup(void);
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <mach/devices.h> #include <mach/devices.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
#include <video/pxa168fb.h> #include <video/pxa168fb.h>
#include <plat/pxa27x_keypad.h> #include <plat/pxa27x_keypad.h>

View file

@ -7,8 +7,8 @@ extern struct sys_timer pxa910_timer;
extern void __init pxa910_init_irq(void); extern void __init pxa910_init_irq(void);
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <mach/devices.h> #include <mach/devices.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
extern struct pxa_device_desc pxa910_device_uart1; extern struct pxa_device_desc pxa910_device_uart1;

View file

@ -27,6 +27,7 @@
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/i2c/pcf857x.h> #include <linux/i2c/pcf857x.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/regulator/max1586.h> #include <linux/regulator/max1586.h>
@ -51,8 +52,6 @@
#include <mach/irda.h> #include <mach/irda.h>
#include <mach/ohci.h> #include <mach/ohci.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -29,6 +29,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pca953x.h> #include <linux/i2c/pca953x.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/mfd/da903x.h> #include <linux/mfd/da903x.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
@ -48,7 +49,6 @@
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/ohci.h> #include <mach/ohci.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
#include <mach/audio.h> #include <mach/audio.h>
#include <mach/pxa3xx-u2d.h> #include <mach/pxa3xx-u2d.h>

View file

@ -20,6 +20,7 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <mach/pxa27x.h> #include <mach/pxa27x.h>
#include <mach/colibri.h> #include <mach/colibri.h>
@ -27,8 +28,6 @@
#include <mach/ohci.h> #include <mach/ohci.h>
#include <mach/pxa27x-udc.h> #include <mach/pxa27x-udc.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -21,6 +21,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <asm/irq.h> #include <asm/irq.h>
@ -33,8 +34,6 @@
#include <mach/pxa27x-udc.h> #include <mach/pxa27x-udc.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <plat/i2c.h>
#include "devices.h" #include "devices.h"
#include "generic.h" #include "generic.h"

View file

@ -24,6 +24,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/backlight.h> #include <linux/backlight.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/ads7846.h> #include <linux/spi/ads7846.h>
@ -45,7 +46,6 @@
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <mach/pxa25x.h> #include <mach/pxa25x.h>
#include <plat/i2c.h>
#include <mach/irda.h> #include <mach/irda.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/udc.h> #include <mach/udc.h>

View file

@ -17,12 +17,12 @@
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/sm501.h> #include <linux/sm501.h>
#include <linux/smsc911x.h> #include <linux/smsc911x.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <mach/csb726.h> #include <mach/csb726.h>
#include <mach/mfp-pxa27x.h> #include <mach/mfp-pxa27x.h>
#include <plat/i2c.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/ohci.h> #include <mach/ohci.h>
#include <mach/pxa2xx-regs.h> #include <mach/pxa2xx-regs.h>

View file

@ -4,6 +4,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/pmu.h> #include <asm/pmu.h>
#include <mach/udc.h> #include <mach/udc.h>
@ -16,7 +17,6 @@
#include <mach/camera.h> #include <mach/camera.h>
#include <mach/audio.h> #include <mach/audio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
#include "devices.h" #include "devices.h"

View file

@ -31,6 +31,7 @@
#include <linux/apm-emulation.h> #include <linux/apm-emulation.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pca953x.h> #include <linux/i2c/pca953x.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/regulator/userspace-consumer.h> #include <linux/regulator/userspace-consumer.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
@ -45,7 +46,6 @@
#include <mach/ohci.h> #include <mach/ohci.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <plat/pxa27x_keypad.h> #include <plat/pxa27x_keypad.h>
#include <plat/i2c.h>
#include <mach/camera.h> #include <mach/camera.h>
#include "generic.h" #include "generic.h"

View file

@ -20,6 +20,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/leds-lp3944.h> #include <linux/leds-lp3944.h>
#include <linux/i2c/pxa-i2c.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
@ -30,7 +31,6 @@
#include <mach/pxa27x.h> #include <mach/pxa27x.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <mach/ohci.h> #include <mach/ohci.h>
#include <plat/i2c.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <plat/pxa27x_keypad.h> #include <plat/pxa27x_keypad.h>
#include <mach/camera.h> #include <mach/camera.h>

View file

@ -35,6 +35,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/usb/gpio_vbus.h> #include <linux/usb/gpio_vbus.h>
#include <linux/i2c/pxa-i2c.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -42,7 +43,6 @@
#include <mach/pxa27x.h> #include <mach/pxa27x.h>
#include <mach/hx4700.h> #include <mach/hx4700.h>
#include <plat/i2c.h>
#include <mach/irda.h> #include <mach/irda.h>
#include <video/platform_lcd.h> #include <video/platform_lcd.h>

View file

@ -28,6 +28,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/mfd/da903x.h> #include <linux/mfd/da903x.h>
#include <linux/i2c/max732x.h> #include <linux/i2c/max732x.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/setup.h> #include <asm/setup.h>
@ -45,7 +46,6 @@
#include <mach/mmc.h> #include <mach/mmc.h>
#include <plat/pxa27x_keypad.h> #include <plat/pxa27x_keypad.h>
#include <mach/littleton.h> #include <mach/littleton.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
#include "generic.h" #include "generic.h"

View file

@ -28,6 +28,7 @@
#include <linux/regulator/bq24022.h> #include <linux/regulator/bq24022.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/usb/gpio_vbus.h> #include <linux/usb/gpio_vbus.h>
#include <linux/i2c/pxa-i2c.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -36,7 +37,6 @@
#include <mach/pxa27x.h> #include <mach/pxa27x.h>
#include <mach/magician.h> #include <mach/magician.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <plat/i2c.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/irda.h> #include <mach/irda.h>
#include <mach/ohci.h> #include <mach/ohci.h>

View file

@ -27,6 +27,7 @@
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/setup.h> #include <asm/setup.h>
@ -46,7 +47,6 @@
#include <mach/mainstone.h> #include <mach/mainstone.h>
#include <mach/audio.h> #include <mach/audio.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <plat/i2c.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/irda.h> #include <mach/irda.h>
#include <mach/ohci.h> #include <mach/ohci.h>

View file

@ -39,6 +39,7 @@
#include <linux/usb/gpio_vbus.h> #include <linux/usb/gpio_vbus.h>
#include <linux/regulator/max1586.h> #include <linux/regulator/max1586.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -50,7 +51,6 @@
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/udc.h> #include <mach/udc.h>
#include <mach/pxa27x-udc.h> #include <mach/pxa27x-udc.h>
#include <plat/i2c.h>
#include <mach/camera.h> #include <mach/camera.h>
#include <mach/audio.h> #include <mach/audio.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>

View file

@ -22,8 +22,8 @@
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/dm9000.h> #include <linux/dm9000.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c/pxa-i2c.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>

View file

@ -22,6 +22,7 @@
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/usb/gpio_vbus.h> #include <linux/usb/gpio_vbus.h>
#include <linux/regulator/max1586.h> #include <linux/regulator/max1586.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -36,8 +37,6 @@
#include <mach/palmasoc.h> #include <mach/palmasoc.h>
#include <mach/palm27x.h> #include <mach/palm27x.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -23,12 +23,12 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <plat/i2c.h>
#include <mach/camera.h> #include <mach/camera.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <mach/pxa27x.h> #include <mach/pxa27x.h>

View file

@ -23,6 +23,7 @@
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/ads7846.h> #include <linux/spi/ads7846.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
@ -44,7 +45,6 @@
#include <mach/irda.h> #include <mach/irda.h>
#include <mach/poodle.h> #include <mach/poodle.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <plat/i2c.h>
#include <asm/hardware/scoop.h> #include <asm/hardware/scoop.h>
#include <asm/hardware/locomo.h> #include <asm/hardware/locomo.h>

View file

@ -19,6 +19,7 @@
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <mach/hardware.h> #include <mach/hardware.h>
@ -32,8 +33,6 @@
#include <mach/dma.h> #include <mach/dma.h>
#include <mach/smemc.h> #include <mach/smemc.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"
#include "clock.h" #include "clock.h"

View file

@ -21,6 +21,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <mach/hardware.h> #include <mach/hardware.h>
@ -32,7 +33,6 @@
#include <mach/dma.h> #include <mach/dma.h>
#include <mach/regs-intc.h> #include <mach/regs-intc.h>
#include <mach/smemc.h> #include <mach/smemc.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -15,6 +15,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
@ -27,7 +28,6 @@
#include <mach/pm.h> #include <mach/pm.h>
#include <mach/dma.h> #include <mach/dma.h>
#include <mach/regs-intc.h> #include <mach/regs-intc.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -32,6 +32,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h> #include <linux/spi/spi_gpio.h>
#include <linux/lis3lv02d.h> #include <linux/lis3lv02d.h>
@ -53,7 +54,6 @@
#include <mach/ohci.h> #include <mach/ohci.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h> #include <plat/pxa3xx_nand.h>
#include "generic.h" #include "generic.h"

View file

@ -20,6 +20,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
#include <linux/mfd/da903x.h> #include <linux/mfd/da903x.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
@ -31,7 +32,6 @@
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <mach/pxa930.h> #include <mach/pxa930.h>
#include <plat/i2c.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include "devices.h" #include "devices.h"

View file

@ -13,6 +13,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/mfd/88pm860x.h> #include <linux/mfd/88pm860x.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -24,8 +25,6 @@
#include <mach/mfp-pxa930.h> #include <mach/mfp-pxa930.h>
#include <mach/gpio.h> #include <mach/gpio.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#define SAARB_NR_IRQS (IRQ_BOARD_START + 40) #define SAARB_NR_IRQS (IRQ_BOARD_START + 40)

View file

@ -19,6 +19,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/i2c/pca953x.h> #include <linux/i2c/pca953x.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/ads7846.h> #include <linux/spi/ads7846.h>
@ -47,8 +48,6 @@
#include <mach/sharpsl_pm.h> #include <mach/sharpsl_pm.h>
#include <mach/smemc.h> #include <mach/smemc.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -25,6 +25,7 @@
#include <linux/mtd/plat-ram.h> #include <linux/mtd/plat-ram.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/i2c/pcf857x.h> #include <linux/i2c/pcf857x.h>
#include <linux/i2c/at24.h> #include <linux/i2c/at24.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
@ -43,7 +44,6 @@
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <mach/pxa27x.h> #include <mach/pxa27x.h>
#include <plat/i2c.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/udc.h> #include <mach/udc.h>
#include <mach/pxa27x-udc.h> #include <mach/pxa27x-udc.h>

View file

@ -15,6 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/mfd/88pm860x.h> #include <linux/mfd/88pm860x.h>
@ -23,8 +24,6 @@
#include <mach/pxa930.h> #include <mach/pxa930.h>
#include <plat/i2c.h>
#include "devices.h" #include "devices.h"
#include "generic.h" #include "generic.h"

View file

@ -34,6 +34,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/input/matrix_keypad.h> #include <linux/input/matrix_keypad.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -41,7 +42,6 @@
#include <mach/pxa25x.h> #include <mach/pxa25x.h>
#include <mach/reset.h> #include <mach/reset.h>
#include <mach/irda.h> #include <mach/irda.h>
#include <plat/i2c.h>
#include <mach/mmc.h> #include <mach/mmc.h>
#include <mach/udc.h> #include <mach/udc.h>
#include <mach/tosa_bt.h> #include <mach/tosa_bt.h>

View file

@ -26,6 +26,7 @@
#include <linux/dm9000.h> #include <linux/dm9000.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/setup.h> #include <asm/setup.h>
@ -47,7 +48,6 @@
#include <mach/irda.h> #include <mach/irda.h>
#include <mach/ohci.h> #include <mach/ohci.h>
#include <mach/smemc.h> #include <mach/smemc.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -36,6 +36,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
@ -47,7 +48,6 @@
#include <mach/pxa25x.h> #include <mach/pxa25x.h>
#include <mach/audio.h> #include <mach/audio.h>
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <plat/i2c.h>
#include <mach/regs-uart.h> #include <mach/regs-uart.h>
#include <mach/arcom-pcmcia.h> #include <mach/arcom-pcmcia.h>
#include <mach/viper.h> #include <mach/viper.h>

View file

@ -26,6 +26,7 @@
#include <linux/ucb1400.h> #include <linux/ucb1400.h>
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
#include <linux/regulator/max1586.h> #include <linux/regulator/max1586.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -40,8 +41,6 @@
#include <mach/udc.h> #include <mach/udc.h>
#include <mach/pata_pxa.h> #include <mach/pata_pxa.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -16,6 +16,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
@ -26,8 +27,6 @@
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <plat/i2c.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/pxa2xx-regs.h> #include <mach/pxa2xx-regs.h>
#include <mach/mfp-pxa25x.h> #include <mach/mfp-pxa25x.h>

View file

@ -29,6 +29,7 @@
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -40,8 +41,6 @@
#include <mach/mmc.h> #include <mach/mmc.h>
#include <plat/pxa27x_keypad.h> #include <plat/pxa27x_keypad.h>
#include <plat/i2c.h>
#include "generic.h" #include "generic.h"
#include "devices.h" #include "devices.h"

View file

@ -25,6 +25,7 @@
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/i2c/pca953x.h> #include <linux/i2c/pca953x.h>
#include <linux/apm-emulation.h> #include <linux/apm-emulation.h>
#include <linux/can/platform/mcp251x.h> #include <linux/can/platform/mcp251x.h>
@ -33,8 +34,6 @@
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <plat/i2c.h>
#include <mach/pxa2xx-regs.h> #include <mach/pxa2xx-regs.h>
#include <mach/regs-uart.h> #include <mach/regs-uart.h>
#include <mach/ohci.h> #include <mach/ohci.h>

View file

@ -17,11 +17,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/i2c/pca953x.h> #include <linux/i2c/pca953x.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <mach/pxa300.h> #include <mach/pxa300.h>
#include <plat/i2c.h>
#include <mach/zylonite.h> #include <mach/zylonite.h>
#include "generic.h" #include "generic.h"

View file

@ -547,15 +547,18 @@ config I2C_PUV3
config I2C_PXA config I2C_PXA
tristate "Intel PXA2XX I2C adapter" tristate "Intel PXA2XX I2C adapter"
depends on ARCH_PXA || ARCH_MMP depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
help help
If you have devices in the PXA I2C bus, say yes to this option. If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-pxa. will be called i2c-pxa.
config I2C_PXA_PCI
def_bool I2C_PXA && X86_32 && PCI && OF
config I2C_PXA_SLAVE config I2C_PXA_SLAVE
bool "Intel PXA2XX I2C Slave comms support" bool "Intel PXA2XX I2C Slave comms support"
depends on I2C_PXA depends on I2C_PXA && !X86_32
help help
Support I2C slave mode communications on the PXA I2C bus. This Support I2C slave mode communications on the PXA I2C bus. This
is necessary for systems where the PXA may be a target on the is necessary for systems where the PXA may be a target on the
@ -668,15 +671,28 @@ config I2C_XILINX
will be called xilinx_i2c. will be called xilinx_i2c.
config I2C_EG20T config I2C_EG20T
tristate "PCH I2C of Intel EG20T" tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH"
depends on PCI depends on PCI
help help
This driver is for PCH(Platform controller Hub) I2C of EG20T which This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor. is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH I2C bus device. This driver can access PCH I2C bus device.
This driver also supports the ML7213, a companion chip for the
Atom E6xx series and compatible with the Intel EG20T PCH.
comment "External I2C/SMBus adapter drivers" comment "External I2C/SMBus adapter drivers"
config I2C_DIOLAN_U2C
tristate "Diolan U2C-12 USB adapter"
depends on USB
help
If you say yes to this option, support will be included for Diolan
U2C-12, a USB to I2C interface.
This driver can also be built as a module. If so, the module
will be called i2c-diolan-u2c.
config I2C_PARPORT config I2C_PARPORT
tristate "Parallel port adapter" tristate "Parallel port adapter"
depends on PARPORT depends on PARPORT

View file

@ -54,6 +54,7 @@ obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_S6000) += i2c-s6000.o obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
@ -67,6 +68,7 @@ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
# External I2C/SMBus adapter drivers # External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o

View file

@ -0,0 +1,535 @@
/*
* Driver for the Diolan u2c-12 USB-I2C adapter
*
* Copyright (c) 2010-2011 Ericsson AB
*
* Derived from:
* i2c-tiny-usb.c
* Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/i2c.h>
#define DRIVER_NAME "i2c-diolan-u2c"
#define USB_VENDOR_ID_DIOLAN 0x0abf
#define USB_DEVICE_ID_DIOLAN_U2C 0x3370
#define DIOLAN_OUT_EP 0x02
#define DIOLAN_IN_EP 0x84
/* commands via USB, must match command ids in the firmware */
#define CMD_I2C_READ 0x01
#define CMD_I2C_WRITE 0x02
#define CMD_I2C_SCAN 0x03 /* Returns list of detected devices */
#define CMD_I2C_RELEASE_SDA 0x04
#define CMD_I2C_RELEASE_SCL 0x05
#define CMD_I2C_DROP_SDA 0x06
#define CMD_I2C_DROP_SCL 0x07
#define CMD_I2C_READ_SDA 0x08
#define CMD_I2C_READ_SCL 0x09
#define CMD_GET_FW_VERSION 0x0a
#define CMD_GET_SERIAL 0x0b
#define CMD_I2C_START 0x0c
#define CMD_I2C_STOP 0x0d
#define CMD_I2C_REPEATED_START 0x0e
#define CMD_I2C_PUT_BYTE 0x0f
#define CMD_I2C_GET_BYTE 0x10
#define CMD_I2C_PUT_ACK 0x11
#define CMD_I2C_GET_ACK 0x12
#define CMD_I2C_PUT_BYTE_ACK 0x13
#define CMD_I2C_GET_BYTE_ACK 0x14
#define CMD_I2C_SET_SPEED 0x1b
#define CMD_I2C_GET_SPEED 0x1c
#define CMD_I2C_SET_CLK_SYNC 0x24
#define CMD_I2C_GET_CLK_SYNC 0x25
#define CMD_I2C_SET_CLK_SYNC_TO 0x26
#define CMD_I2C_GET_CLK_SYNC_TO 0x27
#define RESP_OK 0x00
#define RESP_FAILED 0x01
#define RESP_BAD_MEMADDR 0x04
#define RESP_DATA_ERR 0x05
#define RESP_NOT_IMPLEMENTED 0x06
#define RESP_NACK 0x07
#define RESP_TIMEOUT 0x09
#define U2C_I2C_SPEED_FAST 0 /* 400 kHz */
#define U2C_I2C_SPEED_STD 1 /* 100 kHz */
#define U2C_I2C_SPEED_2KHZ 242 /* 2 kHz, minimum speed */
#define U2C_I2C_SPEED(f) ((DIV_ROUND_UP(1000000, (f)) - 10) / 2 + 1)
#define U2C_I2C_FREQ_FAST 400000
#define U2C_I2C_FREQ_STD 100000
#define U2C_I2C_FREQ(s) (1000000 / (2 * (s - 1) + 10))
#define DIOLAN_USB_TIMEOUT 100 /* in ms */
#define DIOLAN_SYNC_TIMEOUT 20 /* in ms */
#define DIOLAN_OUTBUF_LEN 128
#define DIOLAN_FLUSH_LEN (DIOLAN_OUTBUF_LEN - 4)
#define DIOLAN_INBUF_LEN 256 /* Maximum supported receive length */
/* Structure to hold all of our device specific stuff */
struct i2c_diolan_u2c {
u8 obuffer[DIOLAN_OUTBUF_LEN]; /* output buffer */
u8 ibuffer[DIOLAN_INBUF_LEN]; /* input buffer */
struct usb_device *usb_dev; /* the usb device for this device */
struct usb_interface *interface;/* the interface for this device */
struct i2c_adapter adapter; /* i2c related things */
int olen; /* Output buffer length */
int ocount; /* Number of enqueued messages */
};
static uint frequency = U2C_I2C_FREQ_STD; /* I2C clock frequency in Hz */
module_param(frequency, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz");
/* usb layer */
/* Send command to device, and get response. */
static int diolan_usb_transfer(struct i2c_diolan_u2c *dev)
{
int ret = 0;
int actual;
int i;
if (!dev->olen || !dev->ocount)
return -EINVAL;
ret = usb_bulk_msg(dev->usb_dev,
usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP),
dev->obuffer, dev->olen, &actual,
DIOLAN_USB_TIMEOUT);
if (!ret) {
for (i = 0; i < dev->ocount; i++) {
int tmpret;
tmpret = usb_bulk_msg(dev->usb_dev,
usb_rcvbulkpipe(dev->usb_dev,
DIOLAN_IN_EP),
dev->ibuffer,
sizeof(dev->ibuffer), &actual,
DIOLAN_USB_TIMEOUT);
/*
* Stop command processing if a previous command
* returned an error.
* Note that we still need to retrieve all messages.
*/
if (ret < 0)
continue;
ret = tmpret;
if (ret == 0 && actual > 0) {
switch (dev->ibuffer[actual - 1]) {
case RESP_NACK:
/*
* Return ENXIO if NACK was received as
* response to the address phase,
* EIO otherwise
*/
ret = i == 1 ? -ENXIO : -EIO;
break;
case RESP_TIMEOUT:
ret = -ETIMEDOUT;
break;
case RESP_OK:
/* strip off return code */
ret = actual - 1;
break;
default:
ret = -EIO;
break;
}
}
}
}
dev->olen = 0;
dev->ocount = 0;
return ret;
}
static int diolan_write_cmd(struct i2c_diolan_u2c *dev, bool flush)
{
if (flush || dev->olen >= DIOLAN_FLUSH_LEN)
return diolan_usb_transfer(dev);
return 0;
}
/* Send command (no data) */
static int diolan_usb_cmd(struct i2c_diolan_u2c *dev, u8 command, bool flush)
{
dev->obuffer[dev->olen++] = command;
dev->ocount++;
return diolan_write_cmd(dev, flush);
}
/* Send command with one byte of data */
static int diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data,
bool flush)
{
dev->obuffer[dev->olen++] = command;
dev->obuffer[dev->olen++] = data;
dev->ocount++;
return diolan_write_cmd(dev, flush);
}
/* Send command with two bytes of data */
static int diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1,
u8 d2, bool flush)
{
dev->obuffer[dev->olen++] = command;
dev->obuffer[dev->olen++] = d1;
dev->obuffer[dev->olen++] = d2;
dev->ocount++;
return diolan_write_cmd(dev, flush);
}
/*
* Flush input queue.
* If we don't do this at startup and the controller has queued up
* messages which were not retrieved, it will stop responding
* at some point.
*/
static void diolan_flush_input(struct i2c_diolan_u2c *dev)
{
int i;
for (i = 0; i < 10; i++) {
int actual = 0;
int ret;
ret = usb_bulk_msg(dev->usb_dev,
usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP),
dev->ibuffer, sizeof(dev->ibuffer), &actual,
DIOLAN_USB_TIMEOUT);
if (ret < 0 || actual == 0)
break;
}
if (i == 10)
dev_err(&dev->interface->dev, "Failed to flush input buffer\n");
}
static int diolan_i2c_start(struct i2c_diolan_u2c *dev)
{
return diolan_usb_cmd(dev, CMD_I2C_START, false);
}
static int diolan_i2c_repeated_start(struct i2c_diolan_u2c *dev)
{
return diolan_usb_cmd(dev, CMD_I2C_REPEATED_START, false);
}
static int diolan_i2c_stop(struct i2c_diolan_u2c *dev)
{
return diolan_usb_cmd(dev, CMD_I2C_STOP, true);
}
static int diolan_i2c_get_byte_ack(struct i2c_diolan_u2c *dev, bool ack,
u8 *byte)
{
int ret;
ret = diolan_usb_cmd_data(dev, CMD_I2C_GET_BYTE_ACK, ack, true);
if (ret > 0)
*byte = dev->ibuffer[0];
else if (ret == 0)
ret = -EIO;
return ret;
}
static int diolan_i2c_put_byte_ack(struct i2c_diolan_u2c *dev, u8 byte)
{
return diolan_usb_cmd_data(dev, CMD_I2C_PUT_BYTE_ACK, byte, false);
}
static int diolan_set_speed(struct i2c_diolan_u2c *dev, u8 speed)
{
return diolan_usb_cmd_data(dev, CMD_I2C_SET_SPEED, speed, true);
}
/* Enable or disable clock synchronization (stretching) */
static int diolan_set_clock_synch(struct i2c_diolan_u2c *dev, bool enable)
{
return diolan_usb_cmd_data(dev, CMD_I2C_SET_CLK_SYNC, enable, true);
}
/* Set clock synchronization timeout in ms */
static int diolan_set_clock_synch_timeout(struct i2c_diolan_u2c *dev, int ms)
{
int to_val = ms * 10;
return diolan_usb_cmd_data2(dev, CMD_I2C_SET_CLK_SYNC_TO,
to_val & 0xff, (to_val >> 8) & 0xff, true);
}
static void diolan_fw_version(struct i2c_diolan_u2c *dev)
{
int ret;
ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true);
if (ret >= 2)
dev_info(&dev->interface->dev,
"Diolan U2C firmware version %u.%u\n",
(unsigned int)dev->ibuffer[0],
(unsigned int)dev->ibuffer[1]);
}
static void diolan_get_serial(struct i2c_diolan_u2c *dev)
{
int ret;
u32 serial;
ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true);
if (ret >= 4) {
serial = le32_to_cpu(*(u32 *)dev->ibuffer);
dev_info(&dev->interface->dev,
"Diolan U2C serial number %u\n", serial);
}
}
static int diolan_init(struct i2c_diolan_u2c *dev)
{
int speed, ret;
if (frequency >= 200000) {
speed = U2C_I2C_SPEED_FAST;
frequency = U2C_I2C_FREQ_FAST;
} else if (frequency >= 100000 || frequency == 0) {
speed = U2C_I2C_SPEED_STD;
frequency = U2C_I2C_FREQ_STD;
} else {
speed = U2C_I2C_SPEED(frequency);
if (speed > U2C_I2C_SPEED_2KHZ)
speed = U2C_I2C_SPEED_2KHZ;
frequency = U2C_I2C_FREQ(speed);
}
dev_info(&dev->interface->dev,
"Diolan U2C at USB bus %03d address %03d speed %d Hz\n",
dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency);
diolan_flush_input(dev);
diolan_fw_version(dev);
diolan_get_serial(dev);
/* Set I2C speed */
ret = diolan_set_speed(dev, speed);
if (ret < 0)
return ret;
/* Configure I2C clock synchronization */
ret = diolan_set_clock_synch(dev, speed != U2C_I2C_SPEED_FAST);
if (ret < 0)
return ret;
if (speed != U2C_I2C_SPEED_FAST)
ret = diolan_set_clock_synch_timeout(dev, DIOLAN_SYNC_TIMEOUT);
return ret;
}
/* i2c layer */
static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
int num)
{
struct i2c_diolan_u2c *dev = i2c_get_adapdata(adapter);
struct i2c_msg *pmsg;
int i, j;
int ret, sret;
ret = diolan_i2c_start(dev);
if (ret < 0)
return ret;
for (i = 0; i < num; i++) {
pmsg = &msgs[i];
if (i) {
ret = diolan_i2c_repeated_start(dev);
if (ret < 0)
goto abort;
}
if (pmsg->flags & I2C_M_RD) {
ret =
diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1);
if (ret < 0)
goto abort;
for (j = 0; j < pmsg->len; j++) {
u8 byte;
bool ack = j < pmsg->len - 1;
/*
* Don't send NACK if this is the first byte
* of a SMBUS_BLOCK message.
*/
if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN))
ack = true;
ret = diolan_i2c_get_byte_ack(dev, ack, &byte);
if (ret < 0)
goto abort;
/*
* Adjust count if first received byte is length
*/
if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) {
if (byte == 0
|| byte > I2C_SMBUS_BLOCK_MAX) {
ret = -EPROTO;
goto abort;
}
pmsg->len += byte;
}
pmsg->buf[j] = byte;
}
} else {
ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1);
if (ret < 0)
goto abort;
for (j = 0; j < pmsg->len; j++) {
ret = diolan_i2c_put_byte_ack(dev,
pmsg->buf[j]);
if (ret < 0)
goto abort;
}
}
}
abort:
sret = diolan_i2c_stop(dev);
if (sret < 0 && ret >= 0)
ret = sret;
return ret;
}
/*
* Return list of supported functionality.
*/
static u32 diolan_usb_func(struct i2c_adapter *a)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
}
static const struct i2c_algorithm diolan_usb_algorithm = {
.master_xfer = diolan_usb_xfer,
.functionality = diolan_usb_func,
};
/* device layer */
static const struct usb_device_id diolan_u2c_table[] = {
{ USB_DEVICE(USB_VENDOR_ID_DIOLAN, USB_DEVICE_ID_DIOLAN_U2C) },
{ }
};
MODULE_DEVICE_TABLE(usb, diolan_u2c_table);
static void diolan_u2c_free(struct i2c_diolan_u2c *dev)
{
usb_put_dev(dev->usb_dev);
kfree(dev);
}
static int diolan_u2c_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct i2c_diolan_u2c *dev;
int ret;
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
dev_err(&interface->dev, "no memory for device state\n");
ret = -ENOMEM;
goto error;
}
dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
/* setup i2c adapter description */
dev->adapter.owner = THIS_MODULE;
dev->adapter.class = I2C_CLASS_HWMON;
dev->adapter.algo = &diolan_usb_algorithm;
i2c_set_adapdata(&dev->adapter, dev);
snprintf(dev->adapter.name, sizeof(dev->adapter.name),
DRIVER_NAME " at bus %03d device %03d",
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
dev->adapter.dev.parent = &dev->interface->dev;
/* initialize diolan i2c interface */
ret = diolan_init(dev);
if (ret < 0) {
dev_err(&interface->dev, "failed to initialize adapter\n");
goto error_free;
}
/* and finally attach to i2c layer */
ret = i2c_add_adapter(&dev->adapter);
if (ret < 0) {
dev_err(&interface->dev, "failed to add I2C adapter\n");
goto error_free;
}
dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
return 0;
error_free:
usb_set_intfdata(interface, NULL);
diolan_u2c_free(dev);
error:
return ret;
}
static void diolan_u2c_disconnect(struct usb_interface *interface)
{
struct i2c_diolan_u2c *dev = usb_get_intfdata(interface);
i2c_del_adapter(&dev->adapter);
usb_set_intfdata(interface, NULL);
diolan_u2c_free(dev);
dev_dbg(&interface->dev, "disconnected\n");
}
static struct usb_driver diolan_u2c_driver = {
.name = DRIVER_NAME,
.probe = diolan_u2c_probe,
.disconnect = diolan_u2c_disconnect,
.id_table = diolan_u2c_table,
};
static int __init diolan_u2c_init(void)
{
/* register this driver with the USB subsystem */
return usb_register(&diolan_u2c_driver);
}
static void __exit diolan_u2c_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&diolan_u2c_driver);
}
module_init(diolan_u2c_init);
module_exit(diolan_u2c_exit);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_DESCRIPTION(DRIVER_NAME " driver");
MODULE_LICENSE("GPL");

View file

@ -132,6 +132,13 @@
#define pch_pci_dbg(pdev, fmt, arg...) \ #define pch_pci_dbg(pdev, fmt, arg...) \
dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg) dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg)
/*
Set the number of I2C instance max
Intel EG20T PCH : 1ch
OKI SEMICONDUCTOR ML7213 IOH : 2ch
*/
#define PCH_I2C_MAX_DEV 2
/** /**
* struct i2c_algo_pch_data - for I2C driver functionalities * struct i2c_algo_pch_data - for I2C driver functionalities
* @pch_adapter: stores the reference to i2c_adapter structure * @pch_adapter: stores the reference to i2c_adapter structure
@ -156,12 +163,14 @@ struct i2c_algo_pch_data {
* @pch_data: stores a list of i2c_algo_pch_data * @pch_data: stores a list of i2c_algo_pch_data
* @pch_i2c_suspended: specifies whether the system is suspended or not * @pch_i2c_suspended: specifies whether the system is suspended or not
* perhaps with more lines and words. * perhaps with more lines and words.
* @ch_num: specifies the number of i2c instance
* *
* pch_data has as many elements as maximum I2C channels * pch_data has as many elements as maximum I2C channels
*/ */
struct adapter_info { struct adapter_info {
struct i2c_algo_pch_data pch_data; struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV];
bool pch_i2c_suspended; bool pch_i2c_suspended;
int ch_num;
}; };
@ -170,8 +179,13 @@ static int pch_clk = 50000; /* specifies I2C clock speed in KHz */
static wait_queue_head_t pch_event; static wait_queue_head_t pch_event;
static DEFINE_MUTEX(pch_mutex); static DEFINE_MUTEX(pch_mutex);
/* Definition for ML7213 by OKI SEMICONDUCTOR */
#define PCI_VENDOR_ID_ROHM 0x10DB
#define PCI_DEVICE_ID_ML7213_I2C 0x802D
static struct pci_device_id __devinitdata pch_pcidev_id[] = { static struct pci_device_id __devinitdata pch_pcidev_id[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_I2C)}, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C), 1, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
{0,} {0,}
}; };
@ -212,8 +226,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
/* Initialize I2C registers */ /* Initialize I2C registers */
iowrite32(0x21, p + PCH_I2CNF); iowrite32(0x21, p + PCH_I2CNF);
pch_setbit(adap->pch_base_address, PCH_I2CCTL, pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN);
PCH_I2CCTL_I2CMEN);
if (pch_i2c_speed != 400) if (pch_i2c_speed != 400)
pch_i2c_speed = 100; pch_i2c_speed = 100;
@ -255,7 +268,7 @@ static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
* @timeout: waiting time counter (us). * @timeout: waiting time counter (us).
*/ */
static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
s32 timeout) s32 timeout)
{ {
void __iomem *p = adap->pch_base_address; void __iomem *p = adap->pch_base_address;
@ -475,8 +488,8 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
* @last: specifies whether last message or not. * @last: specifies whether last message or not.
* @first: specifies whether first message or not. * @first: specifies whether first message or not.
*/ */
s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
u32 last, u32 first) u32 last, u32 first)
{ {
struct i2c_algo_pch_data *adap = i2c_adap->algo_data; struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
@ -569,10 +582,10 @@ s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
} }
/** /**
* pch_i2c_cb_ch0() - Interrupt handler Call back function * pch_i2c_cb() - Interrupt handler Call back function
* @adap: Pointer to struct i2c_algo_pch_data. * @adap: Pointer to struct i2c_algo_pch_data.
*/ */
static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap) static void pch_i2c_cb(struct i2c_algo_pch_data *adap)
{ {
u32 sts; u32 sts;
void __iomem *p = adap->pch_base_address; void __iomem *p = adap->pch_base_address;
@ -600,24 +613,30 @@ static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap)
*/ */
static irqreturn_t pch_i2c_handler(int irq, void *pData) static irqreturn_t pch_i2c_handler(int irq, void *pData)
{ {
s32 reg_val; u32 reg_val;
int flag;
int i;
struct adapter_info *adap_info = pData;
void __iomem *p;
u32 mode;
struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData; for (i = 0, flag = 0; i < adap_info->ch_num; i++) {
void __iomem *p = adap_data->pch_base_address; p = adap_info->pch_data[i].pch_base_address;
u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE); mode = ioread32(p + PCH_I2CMOD);
mode &= BUFFER_MODE | EEPROM_SR_MODE;
if (mode != NORMAL_MODE) { if (mode != NORMAL_MODE) {
pch_err(adap_data, "I2C mode is not supported\n"); pch_err(adap_info->pch_data,
return IRQ_NONE; "I2C-%d mode(%d) is not supported\n", mode, i);
continue;
}
reg_val = ioread32(p + PCH_I2CSR);
if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) {
pch_i2c_cb(&adap_info->pch_data[i]);
flag = 1;
}
} }
reg_val = ioread32(p + PCH_I2CSR); return flag ? IRQ_HANDLED : IRQ_NONE;
if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT))
pch_i2c_cb_ch0(adap_data);
else
return IRQ_NONE;
return IRQ_HANDLED;
} }
/** /**
@ -627,7 +646,7 @@ static irqreturn_t pch_i2c_handler(int irq, void *pData)
* @num: number of messages. * @num: number of messages.
*/ */
static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, s32 num) struct i2c_msg *msgs, s32 num)
{ {
struct i2c_msg *pmsg; struct i2c_msg *pmsg;
u32 i = 0; u32 i = 0;
@ -710,11 +729,13 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
} }
static int __devinit pch_i2c_probe(struct pci_dev *pdev, static int __devinit pch_i2c_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
void __iomem *base_addr; void __iomem *base_addr;
s32 ret; int ret;
int i, j;
struct adapter_info *adap_info; struct adapter_info *adap_info;
struct i2c_adapter *pch_adap;
pch_pci_dbg(pdev, "Entered.\n"); pch_pci_dbg(pdev, "Entered.\n");
@ -744,44 +765,48 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
goto err_pci_iomap; goto err_pci_iomap;
} }
adap_info->pch_i2c_suspended = false; /* Set the number of I2C channel instance */
adap_info->ch_num = id->driver_data;
adap_info->pch_data.p_adapter_info = adap_info; for (i = 0; i < adap_info->ch_num; i++) {
pch_adap = &adap_info->pch_data[i].pch_adapter;
adap_info->pch_i2c_suspended = false;
adap_info->pch_data.pch_adapter.owner = THIS_MODULE; adap_info->pch_data[i].p_adapter_info = adap_info;
adap_info->pch_data.pch_adapter.class = I2C_CLASS_HWMON;
strcpy(adap_info->pch_data.pch_adapter.name, KBUILD_MODNAME);
adap_info->pch_data.pch_adapter.algo = &pch_algorithm;
adap_info->pch_data.pch_adapter.algo_data =
&adap_info->pch_data;
/* (i * 0x80) + base_addr; */ pch_adap->owner = THIS_MODULE;
adap_info->pch_data.pch_base_address = base_addr; pch_adap->class = I2C_CLASS_HWMON;
strcpy(pch_adap->name, KBUILD_MODNAME);
pch_adap->algo = &pch_algorithm;
pch_adap->algo_data = &adap_info->pch_data[i];
adap_info->pch_data.pch_adapter.dev.parent = &pdev->dev; /* base_addr + offset; */
adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
ret = i2c_add_adapter(&(adap_info->pch_data.pch_adapter)); pch_adap->dev.parent = &pdev->dev;
if (ret) { ret = i2c_add_adapter(pch_adap);
pch_pci_err(pdev, "i2c_add_adapter FAILED\n"); if (ret) {
goto err_i2c_add_adapter; pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
goto err_i2c_add_adapter;
}
pch_i2c_init(&adap_info->pch_data[i]);
} }
pch_i2c_init(&adap_info->pch_data);
ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
KBUILD_MODNAME, &adap_info->pch_data); KBUILD_MODNAME, adap_info);
if (ret) { if (ret) {
pch_pci_err(pdev, "request_irq FAILED\n"); pch_pci_err(pdev, "request_irq FAILED\n");
goto err_request_irq; goto err_i2c_add_adapter;
} }
pci_set_drvdata(pdev, adap_info); pci_set_drvdata(pdev, adap_info);
pch_pci_dbg(pdev, "returns %d.\n", ret); pch_pci_dbg(pdev, "returns %d.\n", ret);
return 0; return 0;
err_request_irq:
i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
err_i2c_add_adapter: err_i2c_add_adapter:
for (j = 0; j < i; j++)
i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
pci_iounmap(pdev, base_addr); pci_iounmap(pdev, base_addr);
err_pci_iomap: err_pci_iomap:
pci_release_regions(pdev); pci_release_regions(pdev);
@ -794,17 +819,22 @@ err_pci_enable:
static void __devexit pch_i2c_remove(struct pci_dev *pdev) static void __devexit pch_i2c_remove(struct pci_dev *pdev)
{ {
int i;
struct adapter_info *adap_info = pci_get_drvdata(pdev); struct adapter_info *adap_info = pci_get_drvdata(pdev);
pch_i2c_disbl_int(&adap_info->pch_data); free_irq(pdev->irq, adap_info);
free_irq(pdev->irq, &adap_info->pch_data);
i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
if (adap_info->pch_data.pch_base_address) { for (i = 0; i < adap_info->ch_num; i++) {
pci_iounmap(pdev, adap_info->pch_data.pch_base_address); pch_i2c_disbl_int(&adap_info->pch_data[i]);
adap_info->pch_data.pch_base_address = 0; i2c_del_adapter(&adap_info->pch_data[i].pch_adapter);
} }
if (adap_info->pch_data[0].pch_base_address)
pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
for (i = 0; i < adap_info->ch_num; i++)
adap_info->pch_data[i].pch_base_address = 0;
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
pci_release_regions(pdev); pci_release_regions(pdev);
@ -817,17 +847,22 @@ static void __devexit pch_i2c_remove(struct pci_dev *pdev)
static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
int ret; int ret;
int i;
struct adapter_info *adap_info = pci_get_drvdata(pdev); struct adapter_info *adap_info = pci_get_drvdata(pdev);
void __iomem *p = adap_info->pch_data.pch_base_address; void __iomem *p = adap_info->pch_data[0].pch_base_address;
adap_info->pch_i2c_suspended = true; adap_info->pch_i2c_suspended = true;
while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) { for (i = 0; i < adap_info->ch_num; i++) {
/* Wait until all channel transfers are completed */ while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) {
msleep(20); /* Wait until all channel transfers are completed */
msleep(20);
}
} }
/* Disable the i2c interrupts */ /* Disable the i2c interrupts */
pch_i2c_disbl_int(&adap_info->pch_data); for (i = 0; i < adap_info->ch_num; i++)
pch_i2c_disbl_int(&adap_info->pch_data[i]);
pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x " pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x "
"invoked function pch_i2c_disbl_int successfully\n", "invoked function pch_i2c_disbl_int successfully\n",
@ -850,6 +885,7 @@ static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
static int pch_i2c_resume(struct pci_dev *pdev) static int pch_i2c_resume(struct pci_dev *pdev)
{ {
int i;
struct adapter_info *adap_info = pci_get_drvdata(pdev); struct adapter_info *adap_info = pci_get_drvdata(pdev);
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);
@ -862,7 +898,8 @@ static int pch_i2c_resume(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3hot, 0);
pch_i2c_init(&adap_info->pch_data); for (i = 0; i < adap_info->ch_num; i++)
pch_i2c_init(&adap_info->pch_data[i]);
adap_info->pch_i2c_suspended = false; adap_info->pch_i2c_suspended = false;
@ -894,7 +931,7 @@ static void __exit pch_pci_exit(void)
} }
module_exit(pch_pci_exit); module_exit(pch_pci_exit);
MODULE_DESCRIPTION("PCH I2C PCI Driver"); MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>"); MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR)); module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));

View file

@ -118,6 +118,8 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
{ {
mxs_reset_block(i2c->regs); mxs_reset_block(i2c->regs);
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
i2c->regs + MXS_I2C_QUEUECTRL_SET);
} }
static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
@ -347,8 +349,6 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
/* Do reset to enforce correct startup after pinmuxing */ /* Do reset to enforce correct startup after pinmuxing */
mxs_i2c_reset(i2c); mxs_i2c_reset(i2c);
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
i2c->regs + MXS_I2C_QUEUECTRL_SET);
adap = &i2c->adapter; adap = &i2c->adapter;
strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name)); strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));

View file

@ -0,0 +1,176 @@
/*
* The CE4100's I2C device is more or less the same one as found on PXA.
* It does not support slave mode, the register slightly moved. This PCI
* device provides three bars, every contains a single I2C controller.
*/
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#define CE4100_PCI_I2C_DEVS 3
struct ce4100_devices {
struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
};
static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
{
struct platform_device *pdev;
struct i2c_pxa_platform_data pdata;
struct resource res[2];
struct device_node *child;
static int devnum;
int ret;
memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
memset(&res, 0, sizeof(res));
res[0].flags = IORESOURCE_MEM;
res[0].start = pci_resource_start(dev, bar);
res[0].end = pci_resource_end(dev, bar);
res[1].flags = IORESOURCE_IRQ;
res[1].start = dev->irq;
res[1].end = dev->irq;
for_each_child_of_node(dev->dev.of_node, child) {
const void *prop;
struct resource r;
int ret;
ret = of_address_to_resource(child, 0, &r);
if (ret < 0)
continue;
if (r.start != res[0].start)
continue;
if (r.end != res[0].end)
continue;
if (r.flags != res[0].flags)
continue;
prop = of_get_property(child, "fast-mode", NULL);
if (prop)
pdata.fast_mode = 1;
break;
}
if (!child) {
dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
bar);
ret = -EINVAL;
goto out;
}
pdev = platform_device_alloc("ce4100-i2c", devnum);
if (!pdev) {
of_node_put(child);
ret = -ENOMEM;
goto out;
}
pdev->dev.parent = &dev->dev;
pdev->dev.of_node = child;
ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
if (ret)
goto err;
ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
if (ret)
goto err;
ret = platform_device_add(pdev);
if (ret)
goto err;
devnum++;
return pdev;
err:
platform_device_put(pdev);
out:
return ERR_PTR(ret);
}
static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
int ret;
int i;
struct ce4100_devices *sds;
ret = pci_enable_device_mem(dev);
if (ret)
return ret;
if (!dev->dev.of_node) {
dev_err(&dev->dev, "Missing device tree node.\n");
return -EINVAL;
}
sds = kzalloc(sizeof(*sds), GFP_KERNEL);
if (!sds)
goto err_mem;
for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
sds->pdev[i] = add_i2c_device(dev, i);
if (IS_ERR(sds->pdev[i])) {
while (--i >= 0)
platform_device_unregister(sds->pdev[i]);
goto err_dev_add;
}
}
pci_set_drvdata(dev, sds);
return 0;
err_dev_add:
pci_set_drvdata(dev, NULL);
kfree(sds);
err_mem:
pci_disable_device(dev);
return ret;
}
static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
{
struct ce4100_devices *sds;
unsigned int i;
sds = pci_get_drvdata(dev);
pci_set_drvdata(dev, NULL);
for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
platform_device_unregister(sds->pdev[i]);
pci_disable_device(dev);
kfree(sds);
}
static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
{ },
};
MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
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),
};
static int __init ce4100_i2c_init(void)
{
return pci_register_driver(&ce4100_i2c_driver);
}
module_init(ce4100_i2c_init);
static void __exit ce4100_i2c_exit(void)
{
pci_unregister_driver(&ce4100_i2c_driver);
}
module_exit(ce4100_i2c_exit);
MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");

View file

@ -29,38 +29,75 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2c-pxa.h> #include <linux/i2c-pxa.h>
#include <linux/of_i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <plat/i2c.h>
#ifndef CONFIG_HAVE_CLK
#define clk_get(dev, id) NULL
#define clk_put(clk) do { } while (0)
#define clk_disable(clk) do { } while (0)
#define clk_enable(clk) do { } while (0)
#endif
struct pxa_reg_layout {
u32 ibmr;
u32 idbr;
u32 icr;
u32 isr;
u32 isar;
};
enum pxa_i2c_types {
REGS_PXA2XX,
REGS_PXA3XX,
REGS_CE4100,
};
/* /*
* I2C register offsets will be shifted 0 or 1 bit left, depending on * I2C registers definitions
* different SoCs
*/ */
#define REG_SHIFT_0 (0 << 0) static struct pxa_reg_layout pxa_reg_layout[] = {
#define REG_SHIFT_1 (1 << 0) [REGS_PXA2XX] = {
#define REG_SHIFT(d) ((d) & 0x1) .ibmr = 0x00,
.idbr = 0x08,
.icr = 0x10,
.isr = 0x18,
.isar = 0x20,
},
[REGS_PXA3XX] = {
.ibmr = 0x00,
.idbr = 0x04,
.icr = 0x08,
.isr = 0x0c,
.isar = 0x10,
},
[REGS_CE4100] = {
.ibmr = 0x14,
.idbr = 0x0c,
.icr = 0x00,
.isr = 0x04,
/* no isar register */
},
};
static const struct platform_device_id i2c_pxa_id_table[] = { static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REG_SHIFT_1 }, { "pxa2xx-i2c", REGS_PXA2XX },
{ "pxa3xx-pwri2c", REG_SHIFT_0 }, { "pxa3xx-pwri2c", REGS_PXA3XX },
{ "ce4100-i2c", REGS_CE4100 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
/* /*
* I2C registers and bit definitions * I2C bit definitions
*/ */
#define IBMR (0x00)
#define IDBR (0x08)
#define ICR (0x10)
#define ISR (0x18)
#define ISAR (0x20)
#define ICR_START (1 << 0) /* start bit */ #define ICR_START (1 << 0) /* start bit */
#define ICR_STOP (1 << 1) /* stop bit */ #define ICR_STOP (1 << 1) /* stop bit */
@ -111,7 +148,11 @@ struct pxa_i2c {
u32 icrlog[32]; u32 icrlog[32];
void __iomem *reg_base; void __iomem *reg_base;
unsigned int reg_shift; void __iomem *reg_ibmr;
void __iomem *reg_idbr;
void __iomem *reg_icr;
void __iomem *reg_isr;
void __iomem *reg_isar;
unsigned long iobase; unsigned long iobase;
unsigned long iosize; unsigned long iosize;
@ -121,11 +162,11 @@ struct pxa_i2c {
unsigned int fast_mode :1; unsigned int fast_mode :1;
}; };
#define _IBMR(i2c) ((i2c)->reg_base + (0x0 << (i2c)->reg_shift)) #define _IBMR(i2c) ((i2c)->reg_ibmr)
#define _IDBR(i2c) ((i2c)->reg_base + (0x4 << (i2c)->reg_shift)) #define _IDBR(i2c) ((i2c)->reg_idbr)
#define _ICR(i2c) ((i2c)->reg_base + (0x8 << (i2c)->reg_shift)) #define _ICR(i2c) ((i2c)->reg_icr)
#define _ISR(i2c) ((i2c)->reg_base + (0xc << (i2c)->reg_shift)) #define _ISR(i2c) ((i2c)->reg_isr)
#define _ISAR(i2c) ((i2c)->reg_base + (0x10 << (i2c)->reg_shift)) #define _ISAR(i2c) ((i2c)->reg_isar)
/* /*
* I2C Slave mode address * I2C Slave mode address
@ -418,7 +459,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(I2C_ISR_INIT, _ISR(i2c)); writel(I2C_ISR_INIT, _ISR(i2c));
writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c)); writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
writel(i2c->slave_addr, _ISAR(i2c)); if (i2c->reg_isar)
writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */ /* set control register values */
writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
@ -729,8 +771,10 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
*/ */
ret = i2c->msg_idx; ret = i2c->msg_idx;
if (timeout == 0) if (!timeout && i2c->msg_num) {
i2c_pxa_scream_blue_murder(i2c, "timeout"); i2c_pxa_scream_blue_murder(i2c, "timeout");
ret = I2C_RETRY;
}
out: out:
return ret; return ret;
@ -915,11 +959,16 @@ static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
writel(icr, _ICR(i2c)); writel(icr, _ICR(i2c));
} }
#define VALID_INT_SOURCE (ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \
ISR_SAD | ISR_BED)
static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
{ {
struct pxa_i2c *i2c = dev_id; struct pxa_i2c *i2c = dev_id;
u32 isr = readl(_ISR(i2c)); u32 isr = readl(_ISR(i2c));
if (!(isr & VALID_INT_SOURCE))
return IRQ_NONE;
if (i2c_debug > 2 && 0) { if (i2c_debug > 2 && 0) {
dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n", dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
__func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c))); __func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
@ -934,7 +983,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
/* /*
* Always clear all pending IRQs. * Always clear all pending IRQs.
*/ */
writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c)); writel(isr & VALID_INT_SOURCE, _ISR(i2c));
if (isr & ISR_SAD) if (isr & ISR_SAD)
i2c_pxa_slave_start(i2c, isr); i2c_pxa_slave_start(i2c, isr);
@ -1001,6 +1050,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
struct resource *res; struct resource *res;
struct i2c_pxa_platform_data *plat = dev->dev.platform_data; struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
const struct platform_device_id *id = platform_get_device_id(dev); const struct platform_device_id *id = platform_get_device_id(dev);
enum pxa_i2c_types i2c_type = id->driver_data;
int ret; int ret;
int irq; int irq;
@ -1044,7 +1094,13 @@ static int i2c_pxa_probe(struct platform_device *dev)
ret = -EIO; ret = -EIO;
goto eremap; goto eremap;
} }
i2c->reg_shift = REG_SHIFT(id->driver_data);
i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
if (i2c_type != REGS_CE4100)
i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
i2c->iobase = res->start; i2c->iobase = res->start;
i2c->iosize = resource_size(res); i2c->iosize = resource_size(res);
@ -1072,7 +1128,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->adap.algo = &i2c_pxa_pio_algorithm; i2c->adap.algo = &i2c_pxa_pio_algorithm;
} else { } else {
i2c->adap.algo = &i2c_pxa_algorithm; i2c->adap.algo = &i2c_pxa_algorithm;
ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED, ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED,
i2c->adap.name, i2c); i2c->adap.name, i2c);
if (ret) if (ret)
goto ereqirq; goto ereqirq;
@ -1082,12 +1138,19 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->adap.algo_data = i2c; i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &dev->dev; i2c->adap.dev.parent = &dev->dev;
#ifdef CONFIG_OF
i2c->adap.dev.of_node = dev->dev.of_node;
#endif
ret = i2c_add_numbered_adapter(&i2c->adap); if (i2c_type == REGS_CE4100)
ret = i2c_add_adapter(&i2c->adap);
else
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) { if (ret < 0) {
printk(KERN_INFO "I2C: Failed to add bus\n"); printk(KERN_INFO "I2C: Failed to add bus\n");
goto eadapt; goto eadapt;
} }
of_i2c_register_devices(&i2c->adap);
platform_set_drvdata(dev, i2c); platform_set_drvdata(dev, i2c);