config I2C_MPC
tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
-- depends on PPC32
++ depends on PPC
help
If you say yes to this option, support will be included for the
built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx,
This driver can also be built as a module. If so, the module
will be called i2c-mv64xxx.
+ config I2C_MXS
+ tristate "Freescale i.MX28 I2C interface"
+ depends on SOC_IMX28
+ help
+ Say Y here if you want to use the I2C bus controller on
+ the Freescale i.MX28 processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-mxs.
+
config I2C_NOMADIK
tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
depends on PLAT_NOMADIK
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
++config I2C_PUV3
++ tristate "PKUnity v3 I2C bus support"
++ depends on UNICORE32 && ARCH_PUV3
++ select I2C_ALGOBIT
++ help
++ This driver supports the I2C IP inside the PKUnity-v3 SoC.
++ This I2C bus controller is under AMBA/AXI bus.
++
++ This driver can also be built as a module. If so, the module
++ will be called i2c-puv3.
++
config I2C_PXA
tristate "Intel PXA2XX I2C adapter"
- -- depends on ARCH_PXA || ARCH_MMP
+ ++ depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
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_PCI
+ ++ def_bool I2C_PXA && X86_32 && PCI && OF
+ ++
config I2C_PXA_SLAVE
bool "Intel PXA2XX I2C Slave comms support"
- -- depends on I2C_PXA
+ ++ depends on I2C_PXA && !X86_32
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
This driver can also be built as a module. If so, the module
will be called i2c-stu300.
++config I2C_TEGRA
++ tristate "NVIDIA Tegra internal I2C controller"
++ depends on ARCH_TEGRA
++ help
++ If you say yes to this option, support will be included for the
++ I2C controller embedded in NVIDIA Tegra SOCs
++
config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support"
depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
will be called xilinx_i2c.
config I2C_EG20T
-- - tristate "PCH I2C of Intel EG20T"
-- - depends on PCI
-- - help
-- - This driver is for PCH(Platform controller Hub) I2C of EG20T which
-- - is an IOH(Input/Output Hub) for x86 embedded processor.
-- - This driver can access PCH I2C bus device.
++ + tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH"
++ + depends on PCI
++ + help
++ + This driver is for PCH(Platform controller Hub) I2C of EG20T which
++ + is an IOH(Input/Output Hub) for x86 embedded processor.
++ + 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"
+++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
tristate "Parallel port adapter"
depends on PARPORT
#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/ktime.h>
++#include <linux/slab.h>
#define PCH_EVENT_SET 0 /* I2C Interrupt Event Set Status */
#define PCH_EVENT_NONE 1 /* I2C Interrupt Event Clear Status */
#define pch_pci_dbg(pdev, fmt, 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
* @pch_adapter: stores the reference to i2c_adapter structure
* @pch_data: stores a list of i2c_algo_pch_data
* @pch_i2c_suspended: specifies whether the system is suspended or not
* perhaps with more lines and words.
++ + * @ch_num: specifies the number of i2c instance
*
* pch_data has as many elements as maximum I2C channels
*/
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;
++ + int ch_num;
};
static wait_queue_head_t pch_event;
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[] = {
-- - {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,}
};
/* Initialize I2C registers */
iowrite32(0x21, p + PCH_I2CNF);
-- - pch_setbit(adap->pch_base_address, PCH_I2CCTL,
-- - PCH_I2CCTL_I2CMEN);
++ + pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN);
if (pch_i2c_speed != 400)
pch_i2c_speed = 100;
* @timeout: waiting time counter (us).
*/
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;
* @last: specifies whether last message or not.
* @first: specifies whether first message or not.
*/
-- -s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
-- - u32 last, u32 first)
++ +static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
++ + u32 last, u32 first)
{
struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
}
/**
-- - * 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.
*/
-- -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;
void __iomem *p = adap->pch_base_address;
*/
static irqreturn_t pch_i2c_handler(int irq, void *pData)
{
-- - s32 reg_val;
-- -
-- - struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData;
-- - void __iomem *p = adap_data->pch_base_address;
-- - u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE);
-- -
-- - if (mode != NORMAL_MODE) {
-- - pch_err(adap_data, "I2C mode is not supported\n");
-- - return IRQ_NONE;
++ + u32 reg_val;
++ + int flag;
++ + int i;
++ + struct adapter_info *adap_info = pData;
++ + void __iomem *p;
++ + u32 mode;
++ +
++ + for (i = 0, flag = 0; i < adap_info->ch_num; i++) {
++ + p = adap_info->pch_data[i].pch_base_address;
++ + mode = ioread32(p + PCH_I2CMOD);
++ + mode &= BUFFER_MODE | EEPROM_SR_MODE;
++ + if (mode != NORMAL_MODE) {
++ + pch_err(adap_info->pch_data,
++ + "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);
-- - if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT))
-- - pch_i2c_cb_ch0(adap_data);
-- - else
-- - return IRQ_NONE;
-- -
-- - return IRQ_HANDLED;
++ + return flag ? IRQ_HANDLED : IRQ_NONE;
}
/**
* @num: number of messages.
*/
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;
u32 i = 0;
}
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;
-- - s32 ret;
++ + int ret;
++ + int i, j;
struct adapter_info *adap_info;
++ + struct i2c_adapter *pch_adap;
pch_pci_dbg(pdev, "Entered.\n");
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.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;
++ + adap_info->pch_data[i].p_adapter_info = adap_info;
-- - /* (i * 0x80) + base_addr; */
-- - adap_info->pch_data.pch_base_address = base_addr;
++ + pch_adap->owner = THIS_MODULE;
++ + 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) {
-- - pch_pci_err(pdev, "i2c_add_adapter FAILED\n");
-- - goto err_i2c_add_adapter;
-- - }
++ + ret = i2c_add_adapter(pch_adap);
++ + if (ret) {
++ + pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
++ + goto err_i2c_add_adapter;
++ + }
-- - pch_i2c_init(&adap_info->pch_data);
++ + pch_i2c_init(&adap_info->pch_data[i]);
++ + }
ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
-- - KBUILD_MODNAME, &adap_info->pch_data);
++ + KBUILD_MODNAME, adap_info);
if (ret) {
pch_pci_err(pdev, "request_irq FAILED\n");
-- - goto err_request_irq;
++ + goto err_i2c_add_adapter;
}
pci_set_drvdata(pdev, adap_info);
pch_pci_dbg(pdev, "returns %d.\n", ret);
return 0;
-- -err_request_irq:
-- - i2c_del_adapter(&(adap_info->pch_data.pch_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);
err_pci_iomap:
pci_release_regions(pdev);
static void __devexit pch_i2c_remove(struct pci_dev *pdev)
{
++ + int i;
struct adapter_info *adap_info = pci_get_drvdata(pdev);
-- - pch_i2c_disbl_int(&adap_info->pch_data);
-- - free_irq(pdev->irq, &adap_info->pch_data);
-- - i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
++ + free_irq(pdev->irq, adap_info);
-- - if (adap_info->pch_data.pch_base_address) {
-- - pci_iounmap(pdev, adap_info->pch_data.pch_base_address);
-- - adap_info->pch_data.pch_base_address = 0;
++ + for (i = 0; i < adap_info->ch_num; i++) {
++ + pch_i2c_disbl_int(&adap_info->pch_data[i]);
++ + 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_release_regions(pdev);
static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
{
int ret;
++ + int i;
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;
-- - while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) {
-- - /* Wait until all channel transfers are completed */
-- - msleep(20);
++ + for (i = 0; i < adap_info->ch_num; i++) {
++ + while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) {
++ + /* Wait until all channel transfers are completed */
++ + msleep(20);
++ + }
}
++ +
/* 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 "
"invoked function pch_i2c_disbl_int successfully\n",
static int pch_i2c_resume(struct pci_dev *pdev)
{
++ + int i;
struct adapter_info *adap_info = pci_get_drvdata(pdev);
pci_set_power_state(pdev, PCI_D0);
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;
}
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_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));