add i2c
author柯飞雄 <kfx@rock-chips.com>
Tue, 11 May 2010 14:07:00 +0000 (14:07 +0000)
committer黄涛 <huangtao@rock-chips.com>
Mon, 21 Jun 2010 05:34:50 +0000 (13:34 +0800)
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-rk2818.c [new file with mode: 0755]

index e8fe7f169e25773612a37774218e3231d21ba964..b8a36ab4d3dcbcd5c7b2d29caa52e6739ac1a121 100644 (file)
 
 menu "I2C Hardware Bus support"
 
-comment "PC SMBus host controller drivers"
-       depends on PCI
-
-config I2C_ALI1535
-       tristate "ALI 1535"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the SMB
-         Host controller on Acer Labs Inc. (ALI) M1535 South Bridges.  The SMB
-         controller is part of the 7101 device, which is an ACPI-compliant
-         Power Management Unit (PMU).
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-ali1535.
-
-config I2C_ALI1563
-       tristate "ALI 1563"
-       depends on PCI && EXPERIMENTAL
-       help
-         If you say yes to this option, support will be included for the SMB
-         Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
-         controller is part of the 7101 device, which is an ACPI-compliant
-         Power Management Unit (PMU).
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-ali1563.
-
-config I2C_ALI15X3
-       tristate "ALI 15x3"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the
-         Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-ali15x3.
-
-config I2C_AMD756
-       tristate "AMD 756/766/768/8111 and nVidia nForce"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the AMD
-         756/766/768 mainboard I2C interfaces.  The driver also includes
-         support for the first (SMBus 1.0) I2C interface of the AMD 8111 and
-         the nVidia nForce I2C interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-amd756.
-
-config I2C_AMD756_S4882
-       tristate "SMBus multiplexing on the Tyan S4882"
-       depends on I2C_AMD756 && X86 && EXPERIMENTAL
-       help
-         Enabling this option will add specific SMBus support for the Tyan
-         S4882 motherboard.  On this 4-CPU board, the SMBus is multiplexed
-         over 8 different channels, where the various memory module EEPROMs
-         and temperature sensors live.  Saying yes here will give you access
-         to these in addition to the trunk.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-amd756-s4882.
-
-config I2C_AMD8111
-       tristate "AMD 8111"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the
-         second (SMBus 2.0) AMD 8111 mainboard I2C interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-amd8111.
-
-config I2C_I801
-       tristate "Intel 82801 (ICH)"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the Intel
-         801 family of mainboard I2C interfaces.  Specifically, the following
-         versions of the chipset are supported:
-           82801AA
-           82801AB
-           82801BA
-           82801CA/CAM
-           82801DB
-           82801EB/ER (ICH5/ICH5R)
-           6300ESB
-           ICH6
-           ICH7
-           ESB2
-           ICH8
-           ICH9
-           Tolapai
-           ICH10
-           PCH
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-i801.
-
-config I2C_ISCH
-       tristate "Intel SCH SMBus 1.0"
-       depends on PCI
-       help
-         Say Y here if you want to use SMBus controller on the Intel SCH
-         based systems.
-
-         This driver can also be built as a module. If so, the module
-         will be called i2c-isch.
-
-config I2C_PIIX4
-       tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the Intel
-         PIIX4 family of mainboard I2C interfaces.  Specifically, the following
-         versions of the chipset are supported (note that Serverworks is part
-         of Broadcom):
-           Intel PIIX4
-           Intel 440MX
-           ATI IXP200
-           ATI IXP300
-           ATI IXP400
-           ATI SB600
-           ATI SB700
-           ATI SB800
-           AMD Hudson-2
-           Serverworks OSB4
-           Serverworks CSB5
-           Serverworks CSB6
-           Serverworks HT-1000
-           Serverworks HT-1100
-           SMSC Victory66
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-piix4.
-
-config I2C_NFORCE2
-       tristate "Nvidia nForce2, nForce3 and nForce4"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the Nvidia
-         nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-nforce2.
-
-config I2C_NFORCE2_S4985
-       tristate "SMBus multiplexing on the Tyan S4985"
-       depends on I2C_NFORCE2 && X86 && EXPERIMENTAL
-       help
-         Enabling this option will add specific SMBus support for the Tyan
-         S4985 motherboard.  On this 4-CPU board, the SMBus is multiplexed
-         over 4 different channels, where the various memory module EEPROMs
-         live.  Saying yes here will give you access to these in addition
-         to the trunk.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-nforce2-s4985.
-
-config I2C_SIS5595
-       tristate "SiS 5595"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the
-         SiS5595 SMBus (a subset of I2C) interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis5595.
-
-config I2C_SIS630
-       tristate "SiS 630/730"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the
-         SiS630 and SiS730 SMBus (a subset of I2C) interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis630.
-
-config I2C_SIS96X
-       tristate "SiS 96x"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the SiS
-         96x SMBus (a subset of I2C) interfaces.  Specifically, the following
-         chipsets are supported:
-           645/961
-           645DX/961
-           645DX/962
-           648/961
-           650/961
-           735
-           745
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis96x.
-
-config I2C_VIA
-       tristate "VIA VT82C586B"
-       depends on PCI && EXPERIMENTAL
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for the VIA
-          82C586B I2C interface
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-via.
-
-config I2C_VIAPRO
-       tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the VIA
-         VT82C596 and later SMBus interface.  Specifically, the following
-         chipsets are supported:
-           VT82C596A/B
-           VT82C686A/B
-           VT8231
-           VT8233/A
-           VT8235
-           VT8237R/A/S
-           VT8251
-           CX700
-           VX800/VX820
-           VX855/VX875
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-viapro.
-
-if ACPI
-
-comment "ACPI drivers"
-
-config I2C_SCMI
-       tristate "SMBus Control Method Interface"
-       help
-         This driver supports the SMBus Control Method Interface. It needs the
-         BIOS to declare ACPI control methods as described in the SMBus Control
-         Method Interface specification.
-
-         To compile this driver as a module, choose M here:
-         the module will be called i2c-scmi.
-
-endif # ACPI
-
-comment "Mac SMBus host controller drivers"
-       depends on PPC_CHRP || PPC_PMAC
-
-config I2C_HYDRA
-       tristate "CHRP Apple Hydra Mac I/O I2C interface"
-       depends on PCI && PPC_CHRP && EXPERIMENTAL
-       select I2C_ALGOBIT
-       help
-         This supports the use of the I2C interface in the Apple Hydra Mac
-         I/O chip on some CHRP machines (e.g. the LongTrail).  Say Y if you
-         have such a machine.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-hydra.
-
-config I2C_POWERMAC
-       tristate "Powermac I2C interface"
-       depends on PPC_PMAC
-       default y
-       help
-         This exposes the various PowerMac i2c interfaces to the linux i2c
-         layer and to userland. It is used by various drivers on the PowerMac
-         platform, and should generally be enabled.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-powermac.
-
-comment "I2C system bus drivers (mostly embedded / system-on-chip)"
-
-config I2C_AT91
-       tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-       depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
-       help
-         This supports the use of the I2C interface on Atmel AT91
-         processors.
-
-         This driver is BROKEN because the controller which it uses
-         will easily trigger RX overrun and TX underrun errors.  Using
-         low I2C clock rates may partially work around those issues
-         on some systems.  Another serious problem is that there is no
-         documented way to issue repeated START conditions, as needed
-         to support combined I2C messages.  Use the i2c-gpio driver
-         unless your system can cope with those limitations.
-
-config I2C_AU1550
-       tristate "Au1550/Au1200 SMBus interface"
-       depends on SOC_AU1550 || SOC_AU1200
-       help
-         If you say yes to this option, support will be included for the
-         Au1550 and Au1200 SMBus interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-au1550.
-
-config I2C_BLACKFIN_TWI
-       tristate "Blackfin TWI I2C support"
-       depends on BLACKFIN
-       depends on !BF561 && !BF531 && !BF532 && !BF533
-       help
-         This is the I2C bus driver for Blackfin on-chip TWI interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-bfin-twi.
-
-config I2C_BLACKFIN_TWI_CLK_KHZ
-       int "Blackfin TWI I2C clock (kHz)"
-       depends on I2C_BLACKFIN_TWI
-       range 21 400
-       default 50
-       help
-         The unit of the TWI clock is kHz.
-
-config I2C_CPM
-       tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
-       depends on (CPM1 || CPM2) && OF_I2C
-       help
-         This supports the use of the I2C interface on Freescale
-         processors with CPM1 or CPM2.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-cpm.
-
-config I2C_DAVINCI
-       tristate "DaVinci I2C driver"
-       depends on ARCH_DAVINCI
-       help
-         Support for TI DaVinci I2C controller driver.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-davinci.
-
-         Please note that this driver might be needed to bring up other
-         devices such as DaVinci NIC.
-         For details please see http://www.ti.com/davinci
-
-config I2C_DESIGNWARE
-       tristate "Synopsys DesignWare"
-       depends on HAVE_CLK
-       help
-         If you say yes to this option, support will be included for the
-         Synopsys DesignWare I2C adapter. Only master mode is supported.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-designware.
-
-config I2C_GPIO
-       tristate "GPIO-based bitbanging I2C"
-       depends on GENERIC_GPIO
-       select I2C_ALGOBIT
-       help
-         This is a very simple bitbanging I2C driver utilizing the
-         arch-neutral GPIO API to control the SCL and SDA lines.
-
-config I2C_HIGHLANDER
-       tristate "Highlander FPGA SMBus interface"
-       depends on SH_HIGHLANDER
-       help
-         If you say yes to this option, support will be included for
-         the SMBus interface located in the FPGA on various Highlander
-         boards, particularly the R0P7780LC0011RL and R0P7785LC0011RL
-         FPGAs. This is wholly unrelated to the SoC I2C.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-highlander.
-
-config I2C_IBM_IIC
-       tristate "IBM PPC 4xx on-chip I2C interface"
-       depends on 4xx
-       help
-         Say Y here if you want to use IIC peripheral found on
-         embedded IBM PPC 4xx based systems.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-ibm_iic.
-
-config I2C_IMX
-       tristate "IMX I2C interface"
-       depends on ARCH_MXC
-       help
-         Say Y here if you want to use the IIC bus controller on
-         the Freescale i.MX/MXC processors.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-imx.
-
-config I2C_IOP3XX
-       tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
-       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
-       help
-         Say Y here if you want to use the IIC bus controller on
-         the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-iop3xx.
-
-config I2C_IXP2000
-       tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
-       depends on ARCH_IXP2000
-       select I2C_ALGOBIT
-       help
-         Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
-         system and are using GPIO lines for an I2C bus.
-
-         This support is also available as a module. If so, the module
-         will be called i2c-ixp2000.
-
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         instead.
-
-config I2C_MPC
-       tristate "MPC107/824x/85xx/52xx/86xx"
-       depends on PPC32
-       help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-         MPC85xx/MPC8641 family processors. The driver may also work on 52xx
-         family processors, though interrupts are known not to work.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-mpc.
-
-config I2C_MV64XXX
-       tristate "Marvell mv64xxx I2C Controller"
-       depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
-       help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the Marvell 64xxx line of host bridges.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-mv64xxx.
-
-config I2C_OCORES
-       tristate "OpenCores I2C Controller"
-       depends on EXPERIMENTAL
-       help
-         If you say yes to this option, support will be included for the
-         OpenCores I2C controller. For details see
-         http://www.opencores.org/projects.cgi/web/i2c/overview
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-ocores.
-
-config I2C_OMAP
-       tristate "OMAP I2C adapter"
-       depends on ARCH_OMAP
-       default y if MACH_OMAP_H3 || MACH_OMAP_OSK
-       help
-         If you say yes to this option, support will be included for the
-         I2C interface on the Texas Instruments OMAP1/2 family of processors.
-         Like OMAP1510/1610/1710/5912 and OMAP242x.
-         For details see http://www.ti.com/omap.
-
-config I2C_PASEMI
-       tristate "PA Semi SMBus interface"
-       depends on PPC_PASEMI && PCI
-       help
-         Supports the PA Semi PWRficient on-chip SMBus interfaces.
-
-config I2C_PNX
-       tristate "I2C bus support for Philips PNX targets"
-       depends on ARCH_PNX4008
-       help
-         This driver supports the Philips IP3204 I2C IP block master and/or
-         slave controller
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pnx.
-
-config I2C_PXA
-       tristate "Intel PXA2XX I2C adapter"
-       depends on ARCH_PXA || ARCH_MMP
-       help
-         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
-         will be called i2c-pxa.
-
-config I2C_PXA_SLAVE
-       bool "Intel PXA2XX I2C Slave comms support"
-       depends on I2C_PXA
-       help
-         Support I2C slave mode communications on the PXA I2C bus.  This
-         is necessary for systems where the PXA may be a target on the
-         I2C bus.
-
-config I2C_S3C2410
-       tristate "S3C2410 I2C Driver"
-       depends on ARCH_S3C2410 || ARCH_S3C64XX
-       help
-         Say Y here to include support for I2C controller in the
-         Samsung S3C2410 based System-on-Chip devices.
-
-config I2C_S6000
-       tristate "S6000 I2C support"
-       depends on XTENSA_VARIANT_S6000
-       help
-         This driver supports the on chip I2C device on the
-         S6000 xtensa processor family.
-
-         To compile this driver as a module, choose M here. The module
-         will be called i2c-s6000.
-
-config I2C_SH7760
-       tristate "Renesas SH7760 I2C Controller"
-       depends on CPU_SUBTYPE_SH7760
-       help
-         This driver supports the 2 I2C interfaces on the Renesas SH7760.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sh7760.
-
-config I2C_SH_MOBILE
-       tristate "SuperH Mobile I2C Controller"
-       depends on SUPERH
-       help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the Renesas SH-Mobile processor.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sh_mobile.
-
-config I2C_SIMTEC
-       tristate "Simtec Generic I2C interface"
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for
-         the Simtec Generic I2C interface. This driver is for the
-         simple I2C bus used on newer Simtec products for general
-         I2C, such as DDC on the Simtec BBD2016A.
-
-         This driver can also be built as a module. If so, the module
-         will be called i2c-simtec.
-
-config I2C_STU300
-       tristate "ST Microelectronics DDC I2C interface"
-       depends on MACH_U300
-       default y if MACH_U300
-       help
-         If you say yes to this option, support will be included for the
-         I2C interface from ST Microelectronics simply called "DDC I2C"
-         supporting both I2C and DDC, used in e.g. the U300 series
-         mobile platforms.
-
-         This driver can also be built as a module. If so, the module
-         will be called i2c-stu300.
-
-config I2C_VERSATILE
-       tristate "ARM Versatile/Realview I2C bus support"
-       depends on ARCH_VERSATILE || ARCH_REALVIEW
-       select I2C_ALGOBIT
-       help
-         Say yes if you want to support the I2C serial bus on ARMs Versatile
-         range of platforms.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-versatile.
-
-comment "External I2C/SMBus adapter drivers"
-
-config I2C_PARPORT
-       tristate "Parallel port adapter"
-       depends on PARPORT
-       select I2C_ALGOBIT
-       help
-         This supports parallel port I2C adapters such as the ones made by
-         Philips or Velleman, Analog Devices evaluation boards, and more.
-         Basically any adapter using the parallel port as an I2C bus with
-         no extra chipset is supported by this driver, or could be.
-
-         This driver is a replacement for (and was inspired by) an older
-         driver named i2c-philips-par.  The new driver supports more devices,
-         and makes it easier to add support for new devices.
-
-         An adapter type parameter is now mandatory.  Please read the file
-         Documentation/i2c/busses/i2c-parport for details.
-
-         Another driver exists, named i2c-parport-light, which doesn't depend
-         on the parport driver.  This is meant for embedded systems. Don't say
-         Y here if you intend to say Y or M there.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-parport.
-
-config I2C_PARPORT_LIGHT
-       tristate "Parallel port adapter (light)"
-       select I2C_ALGOBIT
-       help
-         This supports parallel port I2C adapters such as the ones made by
-         Philips or Velleman, Analog Devices evaluation boards, and more.
-         Basically any adapter using the parallel port as an I2C bus with
-         no extra chipset is supported by this driver, or could be.
-
-         This driver is a light version of i2c-parport.  It doesn't depend
-         on the parport driver, and uses direct I/O access instead.  This
-         might be preferred on embedded systems where wasting memory for
-         the clean but heavy parport handling is not an option.  The
-         drawback is a reduced portability and the impossibility to
-         daisy-chain other parallel port devices.
-
-         Don't say Y here if you said Y or M to i2c-parport.  Saying M to
-         both is possible but both modules should not be loaded at the same
-         time.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-parport-light.
-
-config I2C_TAOS_EVM
-       tristate "TAOS evaluation module"
-       depends on EXPERIMENTAL
-       select SERIO
-       select SERIO_SERPORT
-       default n
-       help
-         This supports TAOS evaluation modules on serial port. In order to
-         use this driver, you will need the inputattach tool, which is part
-         of the input-utils package.
-
-         If unsure, say N.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-taos-evm.
-
-config I2C_TINY_USB
-       tristate "Tiny-USB adapter"
-       depends on USB
-       help
-         If you say yes to this option, support will be included for the
-         i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
-         http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-tiny-usb.
-
-comment "Graphics adapter I2C/DDC channel drivers"
-       depends on PCI
-
-config I2C_VOODOO3
-       tristate "Voodoo 3 (DEPRECATED)"
-       depends on PCI
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for the
-         Voodoo 3 I2C interface. This driver is deprecated and you should
-         use the tdfxfb driver instead, which additionally provides
-         framebuffer support.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-voodoo3.
-
-comment "Other I2C/SMBus bus drivers"
-
-config I2C_ACORN
-       tristate "Acorn IOC/IOMD I2C bus support"
-       depends on ARCH_ACORN
-       default y
-       select I2C_ALGOBIT
-       help
-         Say yes if you want to support the I2C bus on Acorn platforms.
-
-         If you don't know, say Y.
-
-config I2C_ELEKTOR
-       tristate "Elektor ISA card"
-       depends on ISA && BROKEN_ON_SMP
-       select I2C_ALGOPCF
-       help
-         This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
-         such an adapter.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-elektor.
-
-config I2C_PCA_ISA
-       tristate "PCA9564/PCA9665 on an ISA bus"
-       depends on ISA
-       select I2C_ALGOPCA
-       default n
-       help
-         This driver supports ISA boards using the Philips PCA9564/PCA9665
-         parallel bus to I2C bus controller.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pca-isa.
-
-         This device is almost undetectable and using this driver on a
-         system which doesn't have this device will result in long
-         delays when I2C/SMBus chip drivers are loaded (e.g. at boot
-         time).  If unsure, say N.
-
-config I2C_PCA_PLATFORM
-       tristate "PCA9564/PCA9665 as platform device"
-       select I2C_ALGOPCA
-       default n
-       help
-         This driver supports a memory mapped Philips PCA9564/PCA9665
-         parallel bus to I2C bus controller.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pca-platform.
-
-config I2C_PMCMSP
-       tristate "PMC MSP I2C TWI Controller"
-       depends on PMC_MSP
-       help
-         This driver supports the PMC TWI controller on MSP devices.
-
-         This driver can also be built as module. If so, the module
-         will be called i2c-pmcmsp.
-
-config I2C_SIBYTE
-       tristate "SiByte SMBus interface"
-       depends on SIBYTE_SB1xxx_SOC
-       help
-         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
-
-config I2C_STUB
-       tristate "I2C/SMBus Test Stub"
-       depends on EXPERIMENTAL && m
-       default 'n'
-       help
-         This module may be useful to developers of SMBus client drivers,
-         especially for certain kinds of sensor chips.
-
-         If you do build this module, be sure to read the notes and warnings
-         in <file:Documentation/i2c/i2c-stub>.
-
-         If you don't know what to do here, definitely say N.
-
-config SCx200_I2C
-       tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
-       depends on SCx200_GPIO
-       select I2C_ALGOBIT
-       help
-         Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
-
-         If you don't know what to do here, say N.
-
-         This support is also available as a module.  If so, the module
-         will be called scx200_i2c.
-
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         (or scx200_acb) instead.
-
-config SCx200_I2C_SCL
-       int "GPIO pin used for SCL"
-       depends on SCx200_I2C
-       default "12"
-       help
-         Enter the GPIO pin number used for the SCL signal.  This value can
-         also be specified with a module parameter.
-
-config SCx200_I2C_SDA
-       int "GPIO pin used for SDA"
-       depends on SCx200_I2C
-       default "13"
-       help
-         Enter the GPIO pin number used for the SSA signal.  This value can
-         also be specified with a module parameter.
-
-config SCx200_ACB
-       tristate "Geode ACCESS.bus support"
-       depends on X86_32 && PCI
-       help
-         Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
-         SC1100 processors and the CS5535 and CS5536 Geode companion devices.
-
-         If you don't know what to do here, say N.
-
-         This support is also available as a module.  If so, the module
-         will be called scx200_acb.
+config I2C_RK2818
+       tristate "RK2818 i2c interface (I2C)"
+       depends on ARCH_RK2818
+       help
+               This supports the use of the I2C interface on rk2818
+               processors.
+
+               Using low I2C clock rates may partially work around those issues
+               on some systems. Another serious problem is that there is no
+               documented way to issue repeated START conditions, as needed
+               to support combined I2C messages. Use the i2c-gpio driver
+               unless your system can cope with those limitations.
 
 endmenu
index ff937ac69f5b817c35bf7546006efe4735b8f8b8..479f8a8ed7148aea2f87ecceb240c7ec60703f39 100644 (file)
@@ -1,79 +1,7 @@
 #
 # Makefile for the i2c bus drivers.
 #
-
-# ACPI drivers
-obj-$(CONFIG_I2C_SCMI)         += i2c-scmi.o
-
-# PC SMBus host controller drivers
-obj-$(CONFIG_I2C_ALI1535)      += i2c-ali1535.o
-obj-$(CONFIG_I2C_ALI1563)      += i2c-ali1563.o
-obj-$(CONFIG_I2C_ALI15X3)      += i2c-ali15x3.o
-obj-$(CONFIG_I2C_AMD756)       += i2c-amd756.o
-obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
-obj-$(CONFIG_I2C_AMD8111)      += i2c-amd8111.o
-obj-$(CONFIG_I2C_I801)         += i2c-i801.o
-obj-$(CONFIG_I2C_ISCH)         += i2c-isch.o
-obj-$(CONFIG_I2C_NFORCE2)      += i2c-nforce2.o
-obj-$(CONFIG_I2C_NFORCE2_S4985)        += i2c-nforce2-s4985.o
-obj-$(CONFIG_I2C_PIIX4)                += i2c-piix4.o
-obj-$(CONFIG_I2C_SIS5595)      += i2c-sis5595.o
-obj-$(CONFIG_I2C_SIS630)       += i2c-sis630.o
-obj-$(CONFIG_I2C_SIS96X)       += i2c-sis96x.o
-obj-$(CONFIG_I2C_VIA)          += i2c-via.o
-obj-$(CONFIG_I2C_VIAPRO)       += i2c-viapro.o
-
-# Mac SMBus host controller drivers
-obj-$(CONFIG_I2C_HYDRA)                += i2c-hydra.o
-obj-$(CONFIG_I2C_POWERMAC)     += i2c-powermac.o
-
-# Embebbed system I2C/SMBus host controller drivers
-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_CPM)          += i2c-cpm.o
-obj-$(CONFIG_I2C_DAVINCI)      += i2c-davinci.o
-obj-$(CONFIG_I2C_DESIGNWARE)   += i2c-designware.o
-obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
-obj-$(CONFIG_I2C_HIGHLANDER)   += i2c-highlander.o
-obj-$(CONFIG_I2C_IBM_IIC)      += i2c-ibm_iic.o
-obj-$(CONFIG_I2C_IMX)          += i2c-imx.o
-obj-$(CONFIG_I2C_IOP3XX)       += i2c-iop3xx.o
-obj-$(CONFIG_I2C_IXP2000)      += i2c-ixp2000.o
-obj-$(CONFIG_I2C_MPC)          += i2c-mpc.o
-obj-$(CONFIG_I2C_MV64XXX)      += i2c-mv64xxx.o
-obj-$(CONFIG_I2C_OCORES)       += i2c-ocores.o
-obj-$(CONFIG_I2C_OMAP)         += i2c-omap.o
-obj-$(CONFIG_I2C_PASEMI)       += i2c-pasemi.o
-obj-$(CONFIG_I2C_PNX)          += i2c-pnx.o
-obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
-obj-$(CONFIG_I2C_S3C2410)      += i2c-s3c2410.o
-obj-$(CONFIG_I2C_S6000)                += i2c-s6000.o
-obj-$(CONFIG_I2C_SH7760)       += i2c-sh7760.o
-obj-$(CONFIG_I2C_SH_MOBILE)    += i2c-sh_mobile.o
-obj-$(CONFIG_I2C_SIMTEC)       += i2c-simtec.o
-obj-$(CONFIG_I2C_STU300)       += i2c-stu300.o
-obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
-
-# External I2C/SMBus adapter drivers
-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
-
-# Graphics adapter I2C/DDC channel drivers
-obj-$(CONFIG_I2C_VOODOO3)      += i2c-voodoo3.o
-
-# Other I2C/SMBus bus drivers
-obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
-obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
-obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
-obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
-obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
-obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
-obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
-obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
-obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
+obj-$(CONFIG_I2C_RK2818)       += i2c-rk2818.o
 
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-rk2818.c b/drivers/i2c/busses/i2c-rk2818.c
new file mode 100755 (executable)
index 0000000..5c6902f
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <mach/i2c.h>
+#include <asm/io.h>
+
+#define RK2818_I2C_TIMEOUT             (msecs_to_jiffies(500))
+
+enum rk2818_error {
+       RK2818_ERROR_NONE = 0,
+       RK2818_ERROR_ARBITR_LOSE,
+       RK2818_ERROR_UNKNOWN
+};
+
+enum rk2818_event {
+       RK2818_EVENT_NONE = 0,
+       /* master has received ack(MTX mode) 
+          means that data has been sent to slave.
+        */
+       RK2818_EVENT_MTX_RCVD_ACK,      
+       /* master needs to send ack to slave(MRX mode) 
+          means that data has been received from slave.
+        */
+       RK2818_EVENT_MRX_NEED_ACK,       
+       RK2818_EVENT_MAX
+};
+
+struct rk2818_i2c_data {
+       struct device                   *dev;  
+       struct i2c_adapter              adap;
+       void __iomem                    *regs;
+       struct resource                 *ioarea;
+
+       unsigned int                    suspended:1;
+       unsigned long                   scl_rate;
+       struct clk                              *clk;
+
+       unsigned int                    irq;
+
+       spinlock_t                              cmd_lock;
+       struct completion               cmd_complete;
+       enum rk2818_event               cmd_event;
+       enum rk2818_error               cmd_err;
+
+       unsigned int                    msg_idx;
+       unsigned int                    msg_num;
+};
+
+static int rk2818_i2c_init_hw(struct rk2818_i2c_data *i2c);
+
+static inline void rk2818_i2c_disable_irqs(struct rk2818_i2c_data *i2c)
+{
+       unsigned long tmp;
+
+       tmp = readl(i2c->regs + I2C_IER);
+       writel(tmp & IRQ_ALL_DISABLE, i2c->regs + I2C_IER);
+}
+static inline void rk2818_i2c_enable_irqs(struct rk2818_i2c_data *i2c)
+{
+       unsigned long tmp;
+
+       tmp = readl(i2c->regs + I2C_IER);
+       writel(tmp | IRQ_MST_ENABLE, i2c->regs + I2C_IER);
+}
+
+/* scl = pclk/(5 *(rem+1) * 2^(exp+1)) */
+static unsigned long rk2818_i2c_calcdivisor(unsigned long pclk, 
+                                                               unsigned long scl_rate, 
+                                                               unsigned long *real_rate,
+                                                               unsigned int *rem, unsigned int *exp)
+{
+       unsigned int calc_rem = pclk / (5 * scl_rate);
+       unsigned int calc_exp;
+
+       for(calc_exp = 0; calc_exp < I2CCDVR_EXP_MAX; calc_exp++)
+       {
+               if(calc_rem < I2CCDVR_REM_MAX)
+               {
+                       calc_exp--;
+                       break;
+               }
+               calc_rem = calc_rem >> 1;
+       }
+       if(calc_rem >= I2CCDVR_REM_MAX)
+               return -1;
+       *rem = calc_rem;
+       *exp = calc_exp;
+
+       *real_rate = pclk/(5 * (calc_rem + 1) * (1 <<(calc_exp +1)));
+       return 0;
+}
+/* set i2c bus scl rate */
+static unsigned long  rk2818_i2c_clockrate(struct rk2818_i2c_data *i2c)
+{
+       struct rk2818_i2c_platform_data *pdata = i2c->dev->platform_data;
+       unsigned int rem = 0, exp = 0;
+       unsigned long scl_rate, real_rate = 0, tmp, pclk;
+       int ret = 0;
+       struct clk *arm_pclk;
+
+       arm_pclk = clk_get_parent(i2c->clk);
+       if(IS_ERR(arm_pclk))            
+       {
+               dev_err(i2c->dev, "cannot get pclk\n");
+               ret = -ENOENT;
+       }
+       pclk = clk_get_rate(arm_pclk);
+
+       dev_dbg(i2c->dev, "pdata desired clkrate %lu\n", pdata->scl_rate);
+
+       scl_rate = pdata->scl_rate ? pdata->scl_rate : 100000;
+
+       ret = rk2818_i2c_calcdivisor(pclk, scl_rate, &real_rate, &rem, &exp);
+
+       if (ret < 0) 
+       {
+               dev_err(i2c->dev,
+                       "Unable to achieve desired clkrate %luHz.", scl_rate);
+               return -EINVAL;
+       }
+       
+
+       tmp = readl(i2c->regs + I2C_OPR);
+       tmp |= exp;
+       tmp |= rem<<I2CCDVR_EXP_BITS;   
+       writel(tmp, i2c->regs + I2C_OPR);
+       dev_dbg(i2c->dev, " Scl real rate is %lu\n", real_rate);
+
+       return ret;
+}
+static int rk2818_event_occurred(struct rk2818_i2c_data *i2c)
+{
+       unsigned long isr, lsr;
+
+       isr = readl(i2c->regs + I2C_ISR);
+       lsr = readl(i2c->regs + I2C_LSR);
+       if(isr & I2C_ISR_ARBITR_LOSE)
+       {
+               isr &= ~I2C_ISR_ARBITR_LOSE;
+               writel(isr, i2c->regs + I2C_ISR);
+               i2c->cmd_err = RK2818_ERROR_ARBITR_LOSE;
+               return 1;
+       }
+
+       switch(i2c->cmd_event)
+       {
+               case RK2818_EVENT_MTX_RCVD_ACK:
+                       if(isr & I2C_ISR_MTX_RCVD_ACK)
+                       {
+                               isr &= ~I2C_ISR_MTX_RCVD_ACK;
+                               writel(isr, i2c->regs + I2C_ISR);
+                               return 1;
+                       }
+               break;
+               case RK2818_EVENT_MRX_NEED_ACK:
+                       if(isr & I2C_ISR_MRX_NEED_ACK)
+                       {
+                               isr &= ~I2C_ISR_MRX_NEED_ACK;
+                               writel(isr, i2c->regs + I2C_ISR);
+                               return 1;
+                       }
+                       break;
+               default:
+                       break;
+       }
+       i2c->cmd_err = RK2818_ERROR_UNKNOWN;
+       dev_err(i2c->dev,"Unhandled interrupt!\n");
+       return 0;
+}
+
+static irqreturn_t rk2818_i2c_irq(int irq, void *data)
+{
+       struct rk2818_i2c_data *i2c = (struct rk2818_i2c_data *)data;
+       int res;
+       rk2818_i2c_disable_irqs(i2c);
+       spin_lock(&i2c->cmd_lock);
+       res = rk2818_event_occurred(i2c);
+       if(res || i2c->cmd_err != RK2818_ERROR_NONE)
+               complete(&i2c->cmd_complete);
+       spin_unlock(&i2c->cmd_lock);
+
+       return IRQ_HANDLED;
+}
+
+static int rk2818_wait_event(struct rk2818_i2c_data *i2c,
+                                       enum rk2818_event mr_event)
+{
+       int ret = 0;
+       if(unlikely(irqs_disabled()))
+       {
+               dev_err(i2c->dev, "irqs are disabled on this system!\n");
+               return -EIO;
+       }       
+       spin_lock_irq(&i2c->cmd_lock);
+       i2c->cmd_err = RK2818_ERROR_NONE;
+       i2c->cmd_event = mr_event;
+
+       init_completion(&i2c->cmd_complete);
+
+       spin_unlock_irq(&i2c->cmd_lock);
+
+       rk2818_i2c_enable_irqs(i2c);
+       ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete,
+                                                               RK2818_I2C_TIMEOUT);
+
+       if(ret < 0)
+       {
+               dev_err(i2c->dev, "wait_for_completion_interruptible_timeout(): "
+                                                               "retrun %d waiting for event %04x\n", ret,
+                                                               mr_event);
+               return ret;
+       }
+       if(ret == 0)
+       {
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+static int rk2818_wait_while_busy(struct rk2818_i2c_data *i2c)
+{
+       unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT;
+       unsigned long lsr;
+       dev_dbg(i2c->dev,"wait_while_busy");
+       while(!time_after(jiffies, timeout))
+       {
+               lsr = readl(i2c->regs + I2C_LSR);
+               if(!(lsr & I2C_LSR_BUSY))
+                       return 0;
+               udelay(100);
+       }
+       return -ETIMEDOUT;
+}
+
+static int rk2818_send_address(struct rk2818_i2c_data *i2c,
+                                               struct i2c_msg *msg)
+{
+       unsigned long addr_1st;
+       unsigned long addr_2nd;
+       unsigned long conr = readl(i2c->regs + I2C_CONR);
+       int ret = 0;
+       /*
+       if(msg->flags & I2C_M_TEN)
+               addr_1st = (0xf0 | (((unsigned long) msg->addr & 0x300) >> 7)) & 0xff;
+       else
+       */
+       addr_1st = ((msg->addr << 1) & 0xff);
+       if (msg->flags & I2C_M_RD) 
+               addr_1st |= 0x01;
+       else
+               addr_1st &= (~0x01);
+
+       conr |= I2C_CONR_MTX_MODE;
+       conr &= I2C_CONR_ACK;
+       writel(conr, i2c->regs + I2C_CONR);
+       dev_info(i2c->dev, "send addr: %lx\n", addr_1st);
+       writel(addr_1st, i2c->regs + I2C_MTXR);
+       if(i2c->msg_idx == 0)
+       {
+               ret = rk2818_wait_while_busy(i2c);
+               if(ret != 0)
+               {
+                       dev_err(i2c->dev, "send addr:wait_while_busy\n");
+                       conr = readl(i2c->regs + I2C_CONR);
+                       conr |= I2C_CONR_NAK;
+                       writel(conr, i2c->regs + I2C_CONR);
+                       writel(I2C_LCMR_STOP, i2c->regs + I2C_LCMR);
+                       return ret;
+               }
+       }
+       writel(I2C_LCMR_START, i2c->regs + I2C_LCMR);
+       /*
+       if(msg->flags & I2C_M_TEN)
+       {
+               ret = rk2818_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK);
+               if(ret != 0)
+               {
+                       return ret;
+               }
+               addr_2nd = msg->addr & 0xff;
+               writel(addr_2nd, i2c->regs + I2C_MTXR);
+               writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
+               if (msg->flags & I2C_M_RD)
+               {
+                       ret = rk2818_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK);
+                       if(ret != 0)
+                       {
+                               return ret;
+                       }
+
+                       writel(addr_1st, i2c->regs + I2C_MTXR);
+                       writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
+               }
+
+       }
+       */
+       ret = rk2818_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK);
+       if(ret != 0)
+               dev_err(i2c->dev, "send addr:wait ack timeout\n");
+       return ret;
+}
+
+static int rk2818_xfer_msg(struct i2c_adapter *adap, 
+                                                struct i2c_msg *msg, int stop)
+{
+       struct rk2818_i2c_data *i2c = (struct rk2818_i2c_data *)adap->algo_data;
+
+       int ret, i;
+       unsigned long conr = readl(i2c->regs + I2C_CONR);
+       conr |= I2C_CONR_MPORT_ENABLE;
+       writel(conr, i2c->regs + I2C_CONR);
+       if(msg->len == 0)
+       {
+               ret = -EINVAL;
+               goto exit_disable;
+       }
+
+       clk_enable(i2c->clk);
+       if(msg->scl_rate)
+               i2c->scl_rate = msg->scl_rate;
+       rk2818_i2c_clockrate(i2c);
+
+       ret = rk2818_send_address(i2c, msg);
+       if(ret != 0)
+       {
+               dev_err(i2c->dev, "send addr error\n");
+               goto exit_disable;
+       }
+       if(msg->flags & I2C_M_RD)
+       {       
+               conr = readl(i2c->regs + I2C_CONR);
+               conr &= I2C_CONR_MRX_MODE;
+               writel(conr, i2c->regs + I2C_CONR);
+
+               for(i = 0; i < msg->len; i++)
+               {
+                       writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
+                       ret = rk2818_wait_event(i2c, RK2818_EVENT_MRX_NEED_ACK);
+                       if(ret != 0)
+                       {
+                               dev_err(i2c->dev, "read data timeout\n");
+                               goto exit_disable;
+                       }
+                       msg->buf[i] = (uint8_t)readl(i2c->regs + I2C_MRXR);
+                       dev_info(i2c->dev, "receive data=%u\n",msg->buf[i]);
+                       if(i == msg->len - 1)
+                       {
+                               conr = readl(i2c->regs + I2C_CONR);
+                               conr &= I2C_CONR_ACK;
+                               writel(conr, i2c->regs + I2C_CONR);
+                       }
+               }
+       }
+       else
+       {
+               conr = readl(i2c->regs + I2C_CONR);
+               conr |= I2C_CONR_MTX_MODE;
+               writel(conr, i2c->regs + I2C_CONR);
+               for(i = 0; i < msg->len; i++)
+               {
+                       writel(msg->buf[i], i2c->regs + I2C_MTXR);
+                       dev_info(i2c->dev, "send data =%u\n", msg->buf[i]);
+                       conr = readl(i2c->regs + I2C_CONR);
+                       conr |= I2C_CONR_NAK;
+                       writel(conr, i2c->regs + I2C_CONR);
+                       writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
+
+                       ret = rk2818_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK);
+                       if(ret != 0)
+                       {
+                               dev_err(i2c->dev, "send data timeout\n");
+                               goto exit_disable;
+                       }
+               }
+               
+       }
+       if(i == msg->len)
+       {
+               conr = readl(i2c->regs + I2C_CONR);
+               conr |= I2C_CONR_NAK;
+               writel(conr, i2c->regs + I2C_CONR);
+               if(msg->flags & I2C_M_TEN)
+                       writel(I2C_LCMR_START|I2C_LCMR_RESUME , i2c->regs + I2C_LCMR);
+               else
+                       writel(I2C_LCMR_STOP|I2C_LCMR_RESUME , i2c->regs + I2C_LCMR);
+               if(i2c->msg_idx >= i2c->msg_num - 1)
+               {
+                       ret = rk2818_wait_while_busy(i2c);
+       
+                       if(ret != 0)
+                       {
+                               dev_err(i2c->dev, "tx success wait bus busy time out\n");
+                               return ret;
+                       }
+               }
+       }
+exit_disable:
+       conr = readl(i2c->regs + I2C_CONR);
+       conr &= I2C_CONR_MPORT_DISABLE;
+       writel(conr, i2c->regs + I2C_CONR);
+       clk_disable(i2c->clk);
+       return ret;
+
+}
+
+static int rk2818_i2c_xfer(struct i2c_adapter *adap,
+                       struct i2c_msg *msgs, int num)
+{
+       int ret = -1;
+       int i,retry;
+       struct rk2818_i2c_data *i2c = (struct rk2818_i2c_data *)adap->algo_data;
+       
+       if(i2c->suspended ==1)
+               return -EIO;
+       i2c->scl_rate = msgs[0].scl_rate;
+       ret = rk2818_i2c_init_hw(i2c);
+       if(ret < 0)
+               return ret;
+       i2c->msg_num = num;
+       for (i = 0; i < num; i++) 
+       {
+               i2c->msg_idx = i;
+               for(retry = 0; retry < adap->retries; retry ++)
+               {
+                       ret = rk2818_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+                       if(ret == 0)
+                               break;
+               }
+               if (ret != 0)
+               {
+                       num = ret;
+                       dev_err(i2c->dev, "rk2818_xfer_msg error, ret = %d\n", ret);
+                       break;
+               }
+       }
+       return num;
+}
+
+static u32 rk2818_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm rk2818_i2c_algorithm = {
+       .master_xfer            = rk2818_i2c_xfer,
+       .functionality          = rk2818_i2c_func,
+};
+
+
+
+#ifdef CONFIG_CPU_FREQ
+
+#define freq_to_i2c(_n) container_of(_n, struct rk2818_i2c, freq_transition)
+
+static int rk2818_i2c_cpufreq_transition(struct notifier_block *nb,
+                                         unsigned long val, void *data)
+{
+       struct rk2818_i2c_data *i2c = freq_to_i2c(nb);
+       unsigned long flags;
+       int delta_f;
+       int ret = 0;
+
+       delta_f = clk_get_rate(i2c->clk) - i2c->scl_rate;
+
+       if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
+           (val == CPUFREQ_PRECHANGE && delta_f > 0)) 
+       {
+               spin_lock_irqsave(&i2c->lock, flags);
+               ret = rk2818_i2c_clockrate(i2c);
+               spin_unlock_irqrestore(&i2c->lock, flags);
+       }
+
+       return ret;
+}
+
+static inline int rk2818_i2c_register_cpufreq(struct rk2818_i2c_data *i2c)
+{
+       i2c->freq_transition.notifier_call = rk2818_i2c_cpufreq_transition;
+
+       return cpufreq_register_notifier(&i2c->freq_transition,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void rk2818_i2c_deregister_cpufreq(struct rk2818_i2c_data *i2c)
+{
+       cpufreq_unregister_notifier(&i2c->freq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+static inline int rk2818_i2c_register_cpufreq(struct rk2818_i2c_data *i2c)
+{
+       return 0;
+}
+
+static inline void rk2818_i2c_unregister_cpufreq(struct rk2818_i2c_data *i2c)
+{
+       return;
+}
+#endif
+
+
+static int rk2818_i2c_init_hw(struct rk2818_i2c_data *i2c)
+{
+       unsigned long lcmr = 0x00000000;
+
+       unsigned long opr = readl(i2c->regs + I2C_OPR);
+       opr |= I2C_OPR_RESET_STATUS;
+       writel(opr, i2c->regs + I2C_OPR);
+       
+       writel(lcmr, i2c->regs + I2C_LCMR);
+
+       rk2818_i2c_disable_irqs(i2c);
+
+       if (rk2818_i2c_clockrate(i2c) < 0) {
+               dev_err(i2c->dev, "cannot meet bus clkrate required\n");
+               return -EINVAL;
+       }
+
+       opr = readl(i2c->regs + I2C_OPR);
+       //opr &= ~I2C_OPR_RESET_STATUS;
+       opr |= I2C_OPR_CORE_ENABLE;
+       writel(opr, i2c->regs + I2C_OPR);
+
+       return 0;
+}
+
+
+static int rk2818_i2c_probe(struct platform_device *pdev)
+{
+       struct rk2818_i2c_data *i2c;
+       struct rk2818_i2c_platform_data *pdata;
+       struct resource *res;
+       int ret;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) 
+       {
+               dev_err(&pdev->dev, "no platform data\n");
+               return -EINVAL;
+       }
+       i2c = kzalloc(sizeof(struct rk2818_i2c_data), GFP_KERNEL);
+       if (!i2c) 
+       {
+               dev_err(&pdev->dev, "no memory for state\n");
+               return -ENOMEM;
+       }
+
+       strlcpy(i2c->adap.name, "rk2818_i2c", sizeof(i2c->adap.name));
+       i2c->adap.owner         = THIS_MODULE;
+       i2c->adap.algo          = &rk2818_i2c_algorithm;
+       i2c->adap.class         = I2C_CLASS_HWMON;
+       spin_lock_init(&i2c->cmd_lock);
+
+       i2c->dev = &pdev->dev;
+       
+       i2c->clk = clk_get(&pdev->dev, pdata->clk_id);
+       if (IS_ERR(i2c->clk)) {
+               dev_err(&pdev->dev, "cannot get clock\n");
+               ret = -ENOENT;
+               goto err_noclk;
+       }
+
+       dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
+
+       clk_enable(i2c->clk);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "cannot find IO resource\n");
+               ret = -ENOENT;
+               goto err_clk;
+       }
+
+       i2c->ioarea = request_mem_region(res->start, res->end - res->start + 1,
+                                        pdev->name);
+
+       if (i2c->ioarea == NULL) {
+               dev_err(&pdev->dev, "cannot request IO\n");
+               ret = -ENXIO;
+               goto err_clk;
+       }
+
+       i2c->regs = ioremap(res->start, res->end - res->start + 1);
+
+       if (i2c->regs == NULL) {
+               dev_err(&pdev->dev, "cannot map IO\n");
+               ret = -ENXIO;
+               goto err_ioarea;
+       }
+
+       dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+               i2c->regs, i2c->ioarea, res);
+
+       i2c->adap.algo_data = i2c;
+       i2c->adap.retries = 4;
+       i2c->adap.dev.parent = &pdev->dev;
+
+       if(pdata->cfg_gpio)
+               pdata->cfg_gpio(pdev);
+       ret = rk2818_i2c_init_hw(i2c);
+       if (ret != 0)
+               goto err_iomap;
+
+       i2c->irq = ret = platform_get_irq(pdev, 0);
+       if (ret <= 0) {
+               dev_err(&pdev->dev, "cannot find IRQ\n");
+               goto err_iomap;
+       }
+
+       ret = request_irq(i2c->irq, rk2818_i2c_irq, IRQF_DISABLED,
+                         dev_name(&pdev->dev), i2c);
+
+       if (ret != 0) {
+               dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
+               goto err_iomap;
+       }
+
+       ret = rk2818_i2c_register_cpufreq(i2c);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
+               goto err_irq;
+       }
+
+       i2c->adap.nr = pdata->bus_num;
+       ret = i2c_add_numbered_adapter(&i2c->adap);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+               goto err_cpufreq;
+       }
+
+       platform_set_drvdata(pdev, i2c);
+
+       dev_dbg(&pdev->dev, "%s: RK2818 I2C adapter\n", dev_name(&i2c->adap.dev));
+       return 0;
+
+ err_cpufreq:
+       rk2818_i2c_unregister_cpufreq(i2c);
+
+ 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(i2c->clk);
+       clk_put(i2c->clk);
+
+ err_noclk:
+       kfree(i2c);
+       return ret;
+}
+
+
+static int rk2818_i2c_remove(struct platform_device *pdev)
+{
+       struct rk2818_i2c_data *i2c = platform_get_drvdata(pdev);
+
+       rk2818_i2c_unregister_cpufreq(i2c);
+
+       i2c_del_adapter(&i2c->adap);
+       free_irq(i2c->irq, i2c);
+
+       clk_disable(i2c->clk);
+       clk_put(i2c->clk);
+
+       iounmap(i2c->regs);
+
+       release_resource(i2c->ioarea);
+       kfree(i2c->ioarea);
+       kfree(i2c);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int rk2818_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rk2818_i2c_data *i2c = platform_get_drvdata(pdev);
+
+       i2c->suspended = 1;
+       return 0;
+}
+static int rk2818_i2c_resume(struct platform_device *pdev)
+{
+       struct rk2818_i2c_data *i2c = platform_get_drvdata(pdev);
+
+       i2c->suspended = 0;
+       rk2818_i2c_init_hw(i2c);
+
+       return 0;
+}
+#else
+#define rk2818_i2c_suspend             NULL
+#define rk2818_i2c_resume              NULL
+#endif
+
+
+static struct platform_driver rk2818_i2c_driver = {
+       .probe          = rk2818_i2c_probe,
+       .remove         = rk2818_i2c_remove,
+       .suspend        = rk2818_i2c_suspend,
+       .resume         = rk2818_i2c_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "rk2818_i2c",
+       },
+};
+
+static int __init rk2818_i2c_adap_init(void)
+{
+       return platform_driver_register(&rk2818_i2c_driver);
+}
+
+static void __exit rk2818_i2c_adap_exit(void)
+{
+       platform_driver_unregister(&rk2818_i2c_driver);
+}
+
+subsys_initcall(rk2818_i2c_adap_init);
+module_exit(rk2818_i2c_adap_exit);
+
+MODULE_DESCRIPTION("RK2818 I2C Bus driver");
+MODULE_AUTHOR("Rock-chips, <www.rock-chips.com>");
+MODULE_LICENSE("GPL");