Commit 659dba34 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  i2c: Fix OMAP clock prescaler to match the comment
  i2c: Refactor a kfree in i2c-dev
  i2c: Fix return value check in i2c-dev
  i2c: Enable PEC on more i2c-i801 devices
  i2c: Discard the i2c algo del_bus wrappers
  i2c: New ARM Versatile/Realview bus driver
  i2c: fix broken ds1337 initialization
  i2c: i2c-i801 documentation update
  i2c: Use the __ATTR macro where possible
  i2c: Whitespace cleanups
  i2c: Use put_user instead of copy_to_user where possible
  i2c: New Atmel AT91 bus driver
  i2c: Add support for nested i2c bus locking
  i2c: Cleanups to the i2c-nforce2 bus driver
  i2c: Add request/release_mem_region to i2c-ibm_iic bus driver
  i2c: New Philips PNX bus driver
  i2c: Delete the broken i2c-ite bus driver
  i2c: Update the list of driver IDs
  i2c: Fix documentation typos
parents 3640543d d7aef138
...@@ -216,17 +216,6 @@ Who: Thomas Gleixner <tglx@linutronix.de> ...@@ -216,17 +216,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
--------------------------- ---------------------------
What: i2c-ite and i2c-algo-ite drivers
When: September 2006
Why: These drivers never compiled since they were added to the kernel
tree 5 years ago. This feature removal can be reevaluated if
someone shows interest in the drivers, fixes them and takes over
maintenance.
http://marc.theaimsgroup.com/?l=linux-mips&m=115040510817448
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
What: Bridge netfilter deferred IPv4/IPv6 output hook calling What: Bridge netfilter deferred IPv4/IPv6 output hook calling
When: January 2007 When: January 2007
Why: The deferred output hooks are a layering violation causing unusual Why: The deferred output hooks are a layering violation causing unusual
......
...@@ -5,7 +5,7 @@ Supported adapters: ...@@ -5,7 +5,7 @@ Supported adapters:
Datasheets: Datasheets:
AMD datasheet not yet available, but almost everything can be found AMD datasheet not yet available, but almost everything can be found
in publically available ACPI 2.0 specification, which the adapter in the publicly available ACPI 2.0 specification, which the adapter
follows. follows.
Author: Vojtech Pavlik <vojtech@suse.cz> Author: Vojtech Pavlik <vojtech@suse.cz>
......
...@@ -9,7 +9,10 @@ Supported adapters: ...@@ -9,7 +9,10 @@ Supported adapters:
* Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported) * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
* Intel 6300ESB * Intel 6300ESB
* Intel 82801FB/FR/FW/FRW (ICH6) * Intel 82801FB/FR/FW/FRW (ICH6)
* Intel ICH7 * Intel 82801G (ICH7)
* Intel 631xESB/632xESB (ESB2)
* Intel 82801H (ICH8)
* Intel ICH9
Datasheets: Publicly available at the Intel website Datasheets: Publicly available at the Intel website
Authors: Authors:
......
...@@ -10,11 +10,11 @@ Supported adapters: ...@@ -10,11 +10,11 @@ Supported adapters:
* nForce4 MCP51 10de:0264 * nForce4 MCP51 10de:0264
* nForce4 MCP55 10de:0368 * nForce4 MCP55 10de:0368
Datasheet: not publically available, but seems to be similar to the Datasheet: not publicly available, but seems to be similar to the
AMD-8111 SMBus 2.0 adapter. AMD-8111 SMBus 2.0 adapter.
Authors: Authors:
Hans-Frieder Vogt <hfvogt@arcor.de>, Hans-Frieder Vogt <hfvogt@gmx.net>,
Thomas Leibold <thomas@plx.com>, Thomas Leibold <thomas@plx.com>,
Patrick Dreker <patrick@dreker.de> Patrick Dreker <patrick@dreker.de>
...@@ -38,7 +38,7 @@ Notes ...@@ -38,7 +38,7 @@ Notes
----- -----
The SMBus adapter in the nForce2 chipset seems to be very similar to the The SMBus adapter in the nForce2 chipset seems to be very similar to the
SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get SMBus 2.0 adapter in the AMD-8111 south bridge. However, I could only get
the driver to work with direct I/O access, which is different to the EC the driver to work with direct I/O access, which is different to the EC
interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the
Asus A7N8X lists two SMBuses, both of which are supported by this driver. Asus A7N8X lists two SMBuses, both of which are supported by this driver.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
obj-m := obj-m :=
obj-n := obj-n :=
obj- := obj- :=
......
/*
* I2C initialization for PNX4008.
*
* Author: Vitaly Wool <vitalywool@gmail.com>
*
* 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/i2c-pnx.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <asm/arch/platform.h>
#include <asm/arch/i2c.h>
static int set_clock_run(struct platform_device *pdev)
{
struct clk *clk;
char name[10];
int retval = 0;
snprintf(name, 10, "i2c%d_ck", pdev->id);
clk = clk_get(&pdev->dev, name);
if (!IS_ERR(clk)) {
clk_set_rate(clk, 1);
clk_put(clk);
} else
retval = -ENOENT;
return retval;
}
static int set_clock_stop(struct platform_device *pdev)
{
struct clk *clk;
char name[10];
int retval = 0;
snprintf(name, 10, "i2c%d_ck", pdev->id);
clk = clk_get(&pdev->dev, name);
if (!IS_ERR(clk)) {
clk_set_rate(clk, 0);
clk_put(clk);
} else
retval = -ENOENT;
return retval;
}
static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
{
int retval = 0;
#ifdef CONFIG_PM
retval = set_clock_run(pdev);
#endif
return retval;
}
static int i2c_pnx_resume(struct platform_device *pdev)
{
int retval = 0;
#ifdef CONFIG_PM
retval = set_clock_run(pdev);
#endif
return retval;
}
static u32 calculate_input_freq(struct platform_device *pdev)
{
return HCLK_MHZ;
}
static struct i2c_pnx_algo_data pnx_algo_data0 = {
.base = PNX4008_I2C1_BASE,
.irq = I2C_1_INT,
};
static struct i2c_pnx_algo_data pnx_algo_data1 = {
.base = PNX4008_I2C2_BASE,
.irq = I2C_2_INT,
};
static struct i2c_pnx_algo_data pnx_algo_data2 = {
.base = (PNX4008_USB_CONFIG_BASE + 0x300),
.irq = USB_I2C_INT,
};
static struct i2c_adapter pnx_adapter0 = {
.name = I2C_CHIP_NAME "0",
.algo_data = &pnx_algo_data0,
};
static struct i2c_adapter pnx_adapter1 = {
.name = I2C_CHIP_NAME "1",
.algo_data = &pnx_algo_data1,
};
static struct i2c_adapter pnx_adapter2 = {
.name = "USB-I2C",
.algo_data = &pnx_algo_data2,
};
static struct i2c_pnx_data i2c0_data = {
.suspend = i2c_pnx_suspend,
.resume = i2c_pnx_resume,
.calculate_input_freq = calculate_input_freq,
.set_clock_run = set_clock_run,
.set_clock_stop = set_clock_stop,
.adapter = &pnx_adapter0,
};
static struct i2c_pnx_data i2c1_data = {
.suspend = i2c_pnx_suspend,
.resume = i2c_pnx_resume,
.calculate_input_freq = calculate_input_freq,
.set_clock_run = set_clock_run,
.set_clock_stop = set_clock_stop,
.adapter = &pnx_adapter1,
};
static struct i2c_pnx_data i2c2_data = {
.suspend = i2c_pnx_suspend,
.resume = i2c_pnx_resume,
.calculate_input_freq = calculate_input_freq,
.set_clock_run = set_clock_run,
.set_clock_stop = set_clock_stop,
.adapter = &pnx_adapter2,
};
static struct platform_device i2c0_device = {
.name = "pnx-i2c",
.id = 0,
.dev = {
.platform_data = &i2c0_data,
},
};
static struct platform_device i2c1_device = {
.name = "pnx-i2c",
.id = 1,
.dev = {
.platform_data = &i2c1_data,
},
};
static struct platform_device i2c2_device = {
.name = "pnx-i2c",
.id = 2,
.dev = {
.platform_data = &i2c2_data,
},
};
static struct platform_device *devices[] __initdata = {
&i2c0_device,
&i2c1_device,
&i2c2_device,
};
void __init pnx4008_register_i2c_devices(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
}
...@@ -141,6 +141,19 @@ struct platform_device realview_smc91x_device = { ...@@ -141,6 +141,19 @@ struct platform_device realview_smc91x_device = {
.resource = realview_smc91x_resources, .resource = realview_smc91x_resources,
}; };
static struct resource realview_i2c_resource = {
.start = REALVIEW_I2C_BASE,
.end = REALVIEW_I2C_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
};
struct platform_device realview_i2c_device = {
.name = "versatile-i2c",
.id = -1,
.num_resources = 1,
.resource = &realview_i2c_resource,
};
#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET) #define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
static unsigned int realview_mmc_status(struct device *dev) static unsigned int realview_mmc_status(struct device *dev)
......
...@@ -108,6 +108,7 @@ static struct amba_device name##_device = { \ ...@@ -108,6 +108,7 @@ static struct amba_device name##_device = { \
extern struct platform_device realview_flash_device; extern struct platform_device realview_flash_device;
extern struct platform_device realview_smc91x_device; extern struct platform_device realview_smc91x_device;
extern struct platform_device realview_i2c_device;
extern struct mmc_platform_data realview_mmc0_plat_data; extern struct mmc_platform_data realview_mmc0_plat_data;
extern struct mmc_platform_data realview_mmc1_plat_data; extern struct mmc_platform_data realview_mmc1_plat_data;
extern struct clk realview_clcd_clk; extern struct clk realview_clcd_clk;
......
...@@ -155,6 +155,7 @@ static void __init realview_eb_init(void) ...@@ -155,6 +155,7 @@ static void __init realview_eb_init(void)
platform_device_register(&realview_flash_device); platform_device_register(&realview_flash_device);
platform_device_register(&realview_smc91x_device); platform_device_register(&realview_smc91x_device);
platform_device_register(&realview_i2c_device);
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i]; struct amba_device *d = amba_devs[i];
......
...@@ -325,6 +325,19 @@ static struct platform_device smc91x_device = { ...@@ -325,6 +325,19 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources, .resource = smc91x_resources,
}; };
static struct resource versatile_i2c_resource = {
.start = VERSATILE_I2C_BASE,
.end = VERSATILE_I2C_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device versatile_i2c_device = {
.name = "versatile-i2c",
.id = -1,
.num_resources = 1,
.resource = &versatile_i2c_resource,
};
#define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) #define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
unsigned int mmc_status(struct device *dev) unsigned int mmc_status(struct device *dev)
...@@ -775,6 +788,7 @@ void __init versatile_init(void) ...@@ -775,6 +788,7 @@ void __init versatile_init(void)
clk_register(&versatile_clcd_clk); clk_register(&versatile_clcd_clk);
platform_device_register(&versatile_flash_device); platform_device_register(&versatile_flash_device);
platform_device_register(&versatile_i2c_device);
platform_device_register(&smc91x_device); platform_device_register(&smc91x_device);
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
......
...@@ -360,7 +360,7 @@ static int __init i2c_ioc_init(void) ...@@ -360,7 +360,7 @@ static int __init i2c_ioc_init(void)
if (ret >= 0){ if (ret >= 0){
ret = misc_register(&rtc_dev); ret = misc_register(&rtc_dev);
if(ret < 0) if(ret < 0)
i2c_bit_del_bus(&ioc_ops); i2c_del_adapter(&ioc_ops);
} }
return ret; return ret;
......
...@@ -38,17 +38,6 @@ config I2C_ALGOPCA ...@@ -38,17 +38,6 @@ config I2C_ALGOPCA
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-algo-pca. will be called i2c-algo-pca.
config I2C_ALGOITE
tristate "ITE I2C Algorithm"
depends on MIPS_ITE8172 && I2C
help
This supports the use of the ITE8172 I2C interface found on some MIPS
systems. Say Y if you have one of these. You should also say Y for
the ITE I2C peripheral driver support below.
This support is also available as a module. If so, the module
will be called i2c-algo-ite.
config I2C_ALGO8XX config I2C_ALGO8XX
tristate "MPC8xx CPM I2C interface" tristate "MPC8xx CPM I2C interface"
depends on 8xx && I2C depends on 8xx && I2C
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
......
...@@ -540,15 +540,7 @@ int i2c_bit_add_bus(struct i2c_adapter *adap) ...@@ -540,15 +540,7 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
return i2c_add_adapter(adap); return i2c_add_adapter(adap);
} }
int i2c_bit_del_bus(struct i2c_adapter *adap)
{
return i2c_del_adapter(adap);
}
EXPORT_SYMBOL(i2c_bit_add_bus); EXPORT_SYMBOL(i2c_bit_add_bus);
EXPORT_SYMBOL(i2c_bit_del_bus);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
......
/*
-------------------------------------------------------------------------
i2c-algo-ite.c i2c driver algorithms for ITE adapters
Hai-Pao Fan, MontaVista Software, Inc.
hpfan@mvista.com or source@mvista.com
Copyright 2000 MontaVista Software Inc.
---------------------------------------------------------------------------
This file was highly leveraged from i2c-algo-pcf.c, which was created
by Simon G. Vogl and Hans Berglund:
Copyright (C) 1995-1997 Simon G. Vogl
1998-2000 Hans Berglund
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
<mbailey@littlefeet-inc.com> */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-ite.h>
#include "i2c-algo-ite.h"
#define PM_DSR IT8172_PCI_IO_BASE + IT_PM_DSR
#define PM_IBSR IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04
#define GPIO_CCR IT8172_PCI_IO_BASE + IT_GPCCR
#define DEB2(x) if (i2c_debug>=2) x
#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
#define DEF_TIMEOUT 16
/* module parameters:
*/
static int i2c_debug;
static int iic_test; /* see if the line-setting functions work */
/* --- setting states on the bus with the right timing: --------------- */
#define get_clock(adap) adap->getclock(adap->data)
#define iic_outw(adap, reg, val) adap->setiic(adap->data, reg, val)
#define iic_inw(adap, reg) adap->getiic(adap->data, reg)
/* --- other auxiliary functions -------------------------------------- */
static void iic_start(struct i2c_algo_iic_data *adap)
{
iic_outw(adap,ITE_I2CHCR,ITE_CMD);
}
static void iic_stop(struct i2c_algo_iic_data *adap)
{
iic_outw(adap,ITE_I2CHCR,0);
iic_outw(adap,ITE_I2CHSR,ITE_I2CHSR_TDI);
}
static void iic_reset(struct i2c_algo_iic_data *adap)
{
iic_outw(adap, PM_IBSR, iic_inw(adap, PM_IBSR) | 0x80);
}
static int wait_for_bb(struct i2c_algo_iic_data *adap)
{
int timeout = DEF_TIMEOUT;
short status;
status = iic_inw(adap, ITE_I2CHSR);
#ifndef STUB_I2C
while (timeout-- && (status & ITE_I2CHSR_HB)) {
udelay(1000); /* How much is this? */
status = iic_inw(adap, ITE_I2CHSR);
}
#endif
if (timeout<=0) {
printk(KERN_ERR "Timeout, host is busy\n");
iic_reset(adap);
}
return(timeout<=0);
}
/* After we issue a transaction on the IIC bus, this function
* is called. It puts this process to sleep until we get an interrupt from
* from the controller telling us that the transaction we requested in complete.
*/
static int wait_for_pin(struct i2c_algo_iic_data *adap, short *status) {
int timeout = DEF_TIMEOUT;
timeout = wait_for_bb(adap);
if (timeout) {
DEB2(printk("Timeout waiting for host not busy\n");)
return -EIO;
}
timeout = DEF_TIMEOUT;
*status = iic_inw(adap, ITE_I2CHSR);
#ifndef STUB_I2C
while (timeout-- && !(*status & ITE_I2CHSR_TDI)) {
adap->waitforpin();
*status = iic_inw(adap, ITE_I2CHSR);
}
#endif
if (timeout <= 0)
return(-1);
else
return(0);
}
static int wait_for_fe(struct i2c_algo_iic_data *adap, short *status)
{
int timeout = DEF_TIMEOUT;
*status = iic_inw(adap, ITE_I2CFSR);
#ifndef STUB_I2C
while (timeout-- && (*status & ITE_I2CFSR_FE)) {
udelay(1000);
iic_inw(adap, ITE_I2CFSR);
}
#endif
if (timeout <= 0)
return(-1);
else
return(0);
}
static int iic_init (struct i2c_algo_iic_data *adap)
{
short i;
/* Clear bit 7 to set I2C to normal operation mode */
i=iic_inw(adap, PM_DSR)& 0xff7f;
iic_outw(adap, PM_DSR, i);
/* set IT_GPCCR port C bit 2&3 as function 2 */
i = iic_inw(adap, GPIO_CCR) & 0xfc0f;
iic_outw(adap,GPIO_CCR,i);
/* Clear slave address/sub-address */
iic_outw(adap,ITE_I2CSAR, 0);
iic_outw(adap,ITE_I2CSSAR, 0);
/* Set clock counter register */
iic_outw(adap,ITE_I2CCKCNT, get_clock(adap));
/* Set START/reSTART/STOP time registers */
iic_outw(adap,ITE_I2CSHDR, 0x0a);
iic_outw(adap,ITE_I2CRSUR, 0x0a);
iic_outw(adap,ITE_I2CPSUR, 0x0a);
/* Enable interrupts on completing the current transaction */
iic_outw(adap,ITE_I2CHCR, ITE_I2CHCR_IE | ITE_I2CHCR_HCE);
/* Clear transfer count */
iic_outw(adap,ITE_I2CFBCR, 0x0);
DEB2(printk("iic_init: Initialized IIC on ITE 0x%x\n",
iic_inw(adap, ITE_I2CHSR)));
return 0;
}
/*
* Sanity check for the adapter hardware - check the reaction of
* the bus lines only if it seems to be idle.
*/
static int test_bus(struct i2c_algo_iic_data *adap, char *name) {
#if 0
int scl,sda;
sda=getsda(adap);
if (adap->getscl==NULL) {
printk("test_bus: Warning: Adapter can't read from clock line - skipping test.\n");
return 0;
}
scl=getscl(adap);
printk("test_bus: Adapter: %s scl: %d sda: %d -- testing...\n",
name,getscl(adap),getsda(adap));
if (!scl || !sda ) {
printk("test_bus: %s seems to be busy.\n",adap->name);
goto bailout;
}
sdalo(adap);
printk("test_bus:1 scl: %d sda: %d\n", getscl(adap),
getsda(adap));
if ( 0 != getsda(adap) ) {
printk("test_bus: %s SDA stuck high!\n",name);
sdahi(adap);
goto bailout;
}
if ( 0 == getscl(adap) ) {
printk("test_bus: %s SCL unexpected low while pulling SDA low!\n",
name);
goto bailout;
}
sdahi(adap);
printk("test_bus:2 scl: %d sda: %d\n", getscl(adap),
getsda(adap));
if ( 0 == getsda(adap) ) {
printk("test_bus: %s SDA stuck low!\n",name);
sdahi(adap);
goto bailout;
}
if ( 0 == getscl(adap) ) {
printk("test_bus: %s SCL unexpected low while SDA high!\n",
adap->name);
goto bailout;
}
scllo(adap);
printk("test_bus:3 scl: %d sda: %d\n", getscl(adap),
getsda(adap));
if ( 0 != getscl(adap) ) {
sclhi(adap);
goto bailout;
}
if ( 0 == getsda(adap) ) {
printk("test_bus: %s SDA unexpected low while pulling SCL low!\n",
name);
goto bailout;
}
sclhi(adap);
printk("test_bus:4 scl: %d sda: %d\n", getscl(adap),
getsda(adap));
if ( 0 == getscl(adap) ) {
printk("test_bus: %s SCL stuck low!\n",name);
sclhi(adap);
goto bailout;
}
if ( 0 == getsda(adap) ) {
printk("test_bus: %s SDA unexpected low while SCL high!\n",
name);
goto bailout;
}
printk("test_bus: %s passed test.\n",name);
return 0;
bailout:
sdahi(adap);
sclhi(adap);
return -ENODEV;
#endif
return (0);
}
/* ----- Utility functions
*/
/* Verify the device we want to talk to on the IIC bus really exists. */
static inline int try_address(struct i2c_algo_iic_data *adap,
unsigned int addr, int retries)
{
int i, ret = -1;
short status;
for (i=0;i<retries;i++) {
iic_outw(adap, ITE_I2CSAR, addr);
iic_start(adap);
if (wait_for_pin(adap, &status) == 0) {
if ((status & ITE_I2CHSR_DNE) == 0) {
iic_stop(adap);
iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
ret=1;
break; /* success! */
}
}
iic_stop(adap);
udelay(adap->udelay);
}
DEB2(if (i) printk("try_address: needed %d retries for 0x%x\n",i,
addr));
return ret;
}
static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,
int count)
{
struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
int wrcount=0, timeout;
short status;
int loops, remainder, i, j;
union {
char byte[2];
unsigned short word;
} tmp;
iic_outw(adap, ITE_I2CSSAR, (unsigned short)buf[wrcount++]);
count--;
if (count == 0)
return -EIO;
loops = count / 32; /* 32-byte FIFO */
remainder = count % 32;
if(loops) {
for(i=0; i<loops; i++) {
iic_outw(adap, ITE_I2CFBCR, 32);
for(j=0; j<32/2; j++) {
tmp.byte[1] = buf[wrcount++];
tmp.byte[0] = buf[wrcount++];
iic_outw(adap, ITE_I2CFDR, tmp.word);
}
/* status FIFO overrun */
iic_inw(adap, ITE_I2CFSR);
iic_inw(adap, ITE_I2CFBCR);
iic_outw(adap, ITE_I2CHCR, ITE_WRITE); /* Issue WRITE command */
/* Wait for transmission to complete */
timeout = wait_for_pin(adap, &status);
if(timeout) {
iic_stop(adap);
printk("iic_sendbytes: %s write timeout.\n", i2c_adap->name);
return -EREMOTEIO; /* got a better one ?? */
}
if (status & ITE_I2CHSR_DB) {
iic_stop(adap);
printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name);
return -EREMOTEIO; /* got a better one ?? */
}
}
}
if(remainder) {
iic_outw(adap, ITE_I2CFBCR, remainder);
for(i=0; i<remainder/2; i++) {
tmp.byte[1] = buf[wrcount++];
tmp.byte[0] = buf[wrcount++];
iic_outw(adap, ITE_I2CFDR, tmp.word);
}
/* status FIFO overrun */
iic_inw(adap, ITE_I2CFSR);
iic_inw(adap, ITE_I2CFBCR);
iic_outw(adap, ITE_I2CHCR, ITE_WRITE); /* Issue WRITE command */
timeout = wait_for_pin(adap, &status);
if(timeout) {
iic_stop(adap);
printk("iic_sendbytes: %s write timeout.\n", i2c_adap->name);
return -EREMOTEIO; /* got a better one ?? */
}
#ifndef STUB_I2C
if (status & ITE_I2CHSR_DB) {
iic_stop(adap);
printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name);
return -EREMOTEIO; /* got a better one ?? */
}
#endif
}
iic_stop(adap);
return wrcount;
}
static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count,
int sread)
{
int rdcount=0, i, timeout;
short status;
struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
int loops, remainder, j;
union {
char byte[2];
unsigned short word;
} tmp;
loops = count / 32; /* 32-byte FIFO */
remainder = count % 32;
if(loops) {
for(i=0; i<loops; i++) {
iic_outw(adap, ITE_I2CFBCR, 32);
if (sread)
iic_outw(adap, ITE_I2CHCR, ITE_SREAD);
else
iic_outw(adap, ITE_I2CHCR, ITE_READ); /* Issue READ command */
timeout = wait_for_pin(adap, &status);
if(timeout) {
iic_stop(adap);
printk("iic_readbytes: %s read timeout.\n", i2c_adap->name);
return (-1);
}
#ifndef STUB_I2C
if (status & ITE_I2CHSR_DB) {
iic_stop(adap);
printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name);
return (-1);
}
#endif
timeout = wait_for_fe(adap, &status);
if(timeout) {
iic_stop(adap);
printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name);
return (-1);
}
for(j=0; j<32/2; j++) {
tmp.word = iic_inw(adap, ITE_I2CFDR);
buf[rdcount++] = tmp.byte[1];
buf[rdcount++] = tmp.byte[0];
}
/* status FIFO underrun */
iic_inw(adap, ITE_I2CFSR);
}
}
if(remainder) {
remainder=(remainder+1)/2 * 2;
iic_outw(adap, ITE_I2CFBCR, remainder);
if (sread)
iic_outw(adap, ITE_I2CHCR, ITE_SREAD);
else
iic_outw(adap, ITE_I2CHCR, ITE_READ); /* Issue READ command */
timeout = wait_for_pin(adap, &status);
if(timeout) {
iic_stop(adap);
printk("iic_readbytes: %s read timeout.\n", i2c_adap->name);
return (-1);
}
#ifndef STUB_I2C
if (status & ITE_I2CHSR_DB) {
iic_stop(adap);
printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name);
return (-1);
}
#endif
timeout = wait_for_fe(adap, &status);
if(timeout) {
iic_stop(adap);
printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name);
return (-1);
}
for(i=0; i<(remainder+1)/2; i++) {
tmp.word = iic_inw(adap, ITE_I2CFDR);
buf[rdcount++] = tmp.byte[1];
buf[rdcount++] = tmp.byte[0];
}
/* status FIFO underrun */
iic_inw(adap, ITE_I2CFSR);
}
iic_stop(adap);
return rdcount;
}
/* This function implements combined transactions. Combined
* transactions consist of combinations of reading and writing blocks of data.
* Each transfer (i.e. a read or a write) is separated by a repeated start
* condition.
*/
#if 0
static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{
int i;
struct i2c_msg *pmsg;
int ret;
DEB2(printk("Beginning combined transaction\n"));
for(i=0; i<(num-1); i++) {
pmsg = &msgs[i];
if(pmsg->flags & I2C_M_RD) {
DEB2(printk(" This one is a read\n"));
ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER);
}
else if(!(pmsg->flags & I2C_M_RD)) {
DEB2(printk("This one is a write\n"));
ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER);
}
}
/* Last read or write segment needs to be terminated with a stop */
pmsg = &msgs[i];
if(pmsg->flags & I2C_M_RD) {
DEB2(printk("Doing the last read\n"));
ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
}
else if(!(pmsg->flags & I2C_M_RD)) {
DEB2(printk("Doing the last write\n"));
ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
}
return ret;
}
#endif
/* Whenever we initiate a transaction, the first byte clocked
* onto the bus after the start condition is the address (7 bit) of the
* device we want to talk to. This function manipulates the address specified
* so that it makes sense to the hardware when written to the IIC peripheral.
*
* Note: 10 bit addresses are not supported in this driver, although they are
* supported by the hardware. This functionality needs to be implemented.
*/
static inline int iic_doAddress(struct i2c_algo_iic_data *adap,
struct i2c_msg *msg, int retries)
{
unsigned short flags = msg->flags;
unsigned int addr;
int ret;
/* Ten bit addresses not supported right now */
if ( (flags & I2C_M_TEN) ) {
#if 0
addr = 0xf0 | (( msg->addr >> 7) & 0x03);
DEB2(printk("addr0: %d\n",addr));
ret = try_address(adap, addr, retries);
if (ret!=1) {
printk("iic_doAddress: died at extended address code.\n");
return -EREMOTEIO;
}
iic_outw(adap,msg->addr & 0x7f);
if (ret != 1) {
printk("iic_doAddress: died at 2nd address code.\n");
return -EREMOTEIO;
}
if ( flags & I2C_M_RD ) {
i2c_repstart(adap);
addr |= 0x01;
ret = try_address(adap, addr, retries);
if (ret!=1) {
printk("iic_doAddress: died at extended address code.\n");
return -EREMOTEIO;
}
}
#endif
} else {
addr = ( msg->addr << 1 );
#if 0
if (flags & I2C_M_RD )
addr |= 1;
if (flags & I2C_M_REV_DIR_ADDR )
addr ^= 1;
#endif
if (iic_inw(adap, ITE_I2CSAR) != addr) {
iic_outw(adap, ITE_I2CSAR, addr);
ret = try_address(adap, addr, retries);
if (ret!=1) {
printk("iic_doAddress: died at address code.\n");
return -EREMOTEIO;
}
}
}
return 0;
}
/* Description: Prepares the controller for a transaction (clearing status
* registers, data buffers, etc), and then calls either iic_readbytes or
* iic_sendbytes to do the actual transaction.
*
* still to be done: Before we issue a transaction, we should
* verify that the bus is not busy or in some unknown state.
*/
static int iic_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs,
int num)
{
struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
struct i2c_msg *pmsg;
int i = 0;
int ret, timeout;
pmsg = &msgs[i];
if(!pmsg->len) {
DEB2(printk("iic_xfer: read/write length is 0\n");)
return -EIO;
}
if(!(pmsg->flags & I2C_M_RD) && (!(pmsg->len)%2) ) {
DEB2(printk("iic_xfer: write buffer length is not odd\n");)
return -EIO;
}
/* Wait for any pending transfers to complete */
timeout = wait_for_bb(adap);
if (timeout) {
DEB2(printk("iic_xfer: Timeout waiting for host not busy\n");)
return -EIO;
}
/* Flush FIFO */
iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
/* Load address */
ret = iic_doAddress(adap, pmsg, i2c_adap->retries);
if (ret)
return -EIO;
#if 0
/* Combined transaction (read and write) */
if(num > 1) {
DEB2(printk("iic_xfer: Call combined transaction\n"));
ret = iic_combined_transaction(i2c_adap, msgs, num);
}
#endif
DEB3(printk("iic_xfer: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
if(pmsg->flags & I2C_M_RD) /* Read */
ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, 0);
else { /* Write */
udelay(1000);
ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len);
}
if (ret != pmsg->len)
DEB3(printk("iic_xfer: error or fail on read/write %d bytes.\n",ret));
else
DEB3(printk("iic_xfer: read/write %d bytes.\n",ret));
return ret;
}
/* Implements device specific ioctls. Higher level ioctls can
* be found in i2c-core.c and are typical of any i2c controller (specifying
* slave address, timeouts, etc). These ioctls take advantage of any hardware
* features built into the controller for which this algorithm-adapter set
* was written. These ioctls allow you to take control of the data and clock
* lines and set the either high or low,
* similar to a GPIO pin.
*/
static int algo_control(struct i2c_adapter *adapter,
unsigned int cmd, unsigned long arg)
{
struct i2c_algo_iic_data *adap = adapter->algo_data;
struct i2c_iic_msg s_msg;
char *buf;
int ret;
if (cmd == I2C_SREAD) {
if(copy_from_user(&s_msg, (struct i2c_iic_msg *)arg,
sizeof(struct i2c_iic_msg)))
return -EFAULT;
buf = kmalloc(s_msg.len, GFP_KERNEL);
if (buf== NULL)
return -ENOMEM;
/* Flush FIFO */
iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
/* Load address */
iic_outw(adap, ITE_I2CSAR,s_msg.addr<<1);
iic_outw(adap, ITE_I2CSSAR,s_msg.waddr & 0xff);
ret = iic_readbytes(adapter, buf, s_msg.len, 1);
if (ret>=0) {
if(copy_to_user( s_msg.buf, buf, s_msg.len) )
ret = -EFAULT;
}
kfree(buf);
}
return 0;
}
static u32 iic_func(struct i2c_adapter *adap)
{
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
I2C_FUNC_PROTOCOL_MANGLING;
}
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm iic_algo = {
.master_xfer = iic_xfer,
.algo_control = algo_control, /* ioctl */
.functionality = iic_func,
};
/*
* registering functions to load algorithms at runtime
*/
int i2c_iic_add_bus(struct i2c_adapter *adap)
{
struct i2c_algo_iic_data *iic_adap = adap->algo_data;
if (iic_test) {
int ret = test_bus(iic_adap, adap->name);
if (ret<0)
return -ENODEV;
}
DEB2(printk("i2c-algo-ite: hw routines for %s registered.\n",
adap->name));
/* register new adapter to i2c module... */
adap->algo = &iic_algo;
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
adap->flags = 0;
iic_init(iic_adap);
return i2c_add_adapter(adap);
}
int i2c_iic_del_bus(struct i2c_adapter *adap)
{
int res;
if ((res = i2c_del_adapter(adap)) < 0)
return res;
DEB2(printk("i2c-algo-ite: adapter unregistered: %s\n",adap->name));
return 0;
}
int __init i2c_algo_iic_init (void)
{
printk(KERN_INFO "ITE iic (i2c) algorithm module\n");
return 0;
}
void i2c_algo_iic_exit(void)
{
return;
}
EXPORT_SYMBOL(i2c_iic_add_bus);
EXPORT_SYMBOL(i2c_iic_del_bus);
/* The MODULE_* macros resolve to nothing if MODULES is not defined
* when this file is compiled.
*/
MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
MODULE_DESCRIPTION("ITE iic algorithm");
MODULE_LICENSE("GPL");
module_param(iic_test, bool, 0);
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
/* This function resolves to init_module (the function invoked when a module
* is loaded via insmod) when this file is compiled with MODULES defined.
* Otherwise (i.e. if you want this driver statically linked to the kernel),
* a pointer to this function is stored in a table and called
* during the initialization of the kernel (in do_basic_setup in /init/main.c)
*
* All this functionality is complements of the macros defined in linux/init.h
*/
module_init(i2c_algo_iic_init);
/* If MODULES is defined when this file is compiled, then this function will
* resolved to cleanup_module.
*/
module_exit(i2c_algo_iic_exit);
/*
--------------------------------------------------------------------
i2c-ite.h: Global defines for the I2C controller on board the
ITE MIPS processor.
--------------------------------------------------------------------
Hai-Pao Fan, MontaVista Software, Inc.
hpfan@mvista.com or source@mvista.com
Copyright 2001 MontaVista Software Inc.
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef I2C_ITE_H
#define I2C_ITE_H 1
#include <asm/it8172/it8172.h>
/* I2C Registers */
#define ITE_I2CHCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x30
#define ITE_I2CHSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x34
#define ITE_I2CSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x38
#define ITE_I2CSSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x3c
#define ITE_I2CCKCNT IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x48
#define ITE_I2CSHDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x4c
#define ITE_I2CRSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x50
#define ITE_I2CPSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x54
#define ITE_I2CFDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x70
#define ITE_I2CFBCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x74
#define ITE_I2CFCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x78
#define ITE_I2CFSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x7c
/* Host Control Register ITE_I2CHCR */
#define ITE_I2CHCR_HCE 0x01 /* Enable I2C Host Controller */
#define ITE_I2CHCR_IE 0x02 /* Enable the interrupt after completing
the current transaction */
#define ITE_I2CHCR_CP_W 0x00 /* bit2-4 000 - Write */
#define ITE_I2CHCR_CP_R 0x08 /* 010 - Current address read */
#define ITE_I2CHCR_CP_S 0x10 /* 100 - Sequential read */
#define ITE_I2CHCR_ST 0x20 /* Initiates the I2C host controller to execute
the command and send the data programmed in
all required registers to I2C bus */
#define ITE_CMD ITE_I2CHCR_HCE | ITE_I2CHCR_IE | ITE_I2CHCR_ST
#define ITE_WRITE ITE_CMD | ITE_I2CHCR_CP_W
#define ITE_READ ITE_CMD | ITE_I2CHCR_CP_R
#define ITE_SREAD ITE_CMD | ITE_I2CHCR_CP_S
/* Host Status Register ITE_I2CHSR */
#define ITE_I2CHSR_DB 0x01 /* Device is busy, receives NACK response except
in the first and last bytes */
#define ITE_I2CHSR_DNE 0x02 /* Target address on I2C bus does not exist */
#define ITE_I2CHSR_TDI 0x04 /* R/W Transaction on I2C bus was completed */
#define ITE_I2CHSR_HB 0x08 /* Host controller is processing transactions */
#define ITE_I2CHSR_FER 0x10 /* Error occurs in the FIFO */
/* Slave Address Register ITE_I2CSAR */
#define ITE_I2CSAR_SA_MASK 0xfe /* Target I2C device address */
#define ITE_I2CSAR_ASO 0x0100 /* Output 1/0 to I2CAS port when the
next slave address is addressed */
/* Slave Sub-address Register ITE_I2CSSAR */
#define ITE_I2CSSAR_SUBA_MASK 0xff /* Target I2C device sub-address */
/* Clock Counter Register ITE_I2CCKCNT */
#define ITE_I2CCKCNT_STOP 0x00 /* stop I2C clock */
#define ITE_I2CCKCNT_HPCC_MASK 0x7f /* SCL high period counter */
#define ITE_I2CCKCNT_LPCC_MASK 0x7f00 /* SCL low period counter */
/* START Hold Time Register ITE_I2CSHDR */
/* value is counted based on 16 MHz internal clock */
#define ITE_I2CSHDR_FM 0x0a /* START condition at fast mode */
#define ITE_I2CSHDR_SM 0x47 /* START contition at standard mode */
/* (Repeated) START Setup Time Register ITE_I2CRSUR */
/* value is counted based on 16 MHz internal clock */
#define ITE_I2CRSUR_FM 0x0a /* repeated START condition at fast mode */
#define ITE_I2CRSUR_SM 0x50 /* repeated START condition at standard mode */
/* STOP setup Time Register ITE_I2CPSUR */
/* FIFO Data Register ITE_I2CFDR */
#define ITE_I2CFDR_MASK 0xff
/* FIFO Byte Count Register ITE_I2CFBCR */
#define ITE_I2CFBCR_MASK 0x3f
/* FIFO Control Register ITE_I2CFCR */
#define ITE_I2CFCR_FLUSH 0x01 /* Flush FIFO and reset the FIFO point
and I2CFSR */
/* FIFO Status Register ITE_I2CFSR */
#define ITE_I2CFSR_FO 0x01 /* FIFO is overrun when write */
#define ITE_I2CFSR_FU 0x02 /* FIFO is underrun when read */
#define ITE_I2CFSR_FF 0x04 /* FIFO is full when write */
#define ITE_I2CFSR_FE 0x08 /* FIFO is empty when read */
#endif /* I2C_ITE_H */
...@@ -381,14 +381,7 @@ int i2c_pca_add_bus(struct i2c_adapter *adap) ...@@ -381,14 +381,7 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
return rval; return rval;
} }
int i2c_pca_del_bus(struct i2c_adapter *adap)
{
return i2c_del_adapter(adap);
}
EXPORT_SYMBOL(i2c_pca_add_bus); EXPORT_SYMBOL(i2c_pca_add_bus);
EXPORT_SYMBOL(i2c_pca_del_bus);
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm"); MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
......
...@@ -486,15 +486,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap) ...@@ -486,15 +486,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
return rval; return rval;
} }
int i2c_pcf_del_bus(struct i2c_adapter *adap)
{
return i2c_del_adapter(adap);
}
EXPORT_SYMBOL(i2c_pcf_add_bus); EXPORT_SYMBOL(i2c_pcf_add_bus);
EXPORT_SYMBOL(i2c_pcf_del_bus);
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
......
...@@ -171,15 +171,7 @@ int i2c_sgi_add_bus(struct i2c_adapter *adap) ...@@ -171,15 +171,7 @@ int i2c_sgi_add_bus(struct i2c_adapter *adap)
return i2c_add_adapter(adap); return i2c_add_adapter(adap);
} }
int i2c_sgi_del_bus(struct i2c_adapter *adap)
{
return i2c_del_adapter(adap);
}
EXPORT_SYMBOL(i2c_sgi_add_bus); EXPORT_SYMBOL(i2c_sgi_add_bus);
EXPORT_SYMBOL(i2c_sgi_del_bus);
MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>"); MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
MODULE_DESCRIPTION("I2C-Bus SGI algorithm"); MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
......
...@@ -74,6 +74,13 @@ config I2C_AMD8111 ...@@ -74,6 +74,13 @@ config I2C_AMD8111
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-amd8111. will be called i2c-amd8111.
config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on I2C && ARCH_AT91 && EXPERIMENTAL
help
This supports the use of the I2C interface on Atmel AT91
processors.
config I2C_AU1550 config I2C_AU1550
tristate "Au1550/Au1200 SMBus interface" tristate "Au1550/Au1200 SMBus interface"
depends on I2C && (SOC_AU1550 || SOC_AU1200) depends on I2C && (SOC_AU1550 || SOC_AU1200)
...@@ -209,18 +216,6 @@ config I2C_ISA ...@@ -209,18 +216,6 @@ config I2C_ISA
tristate tristate
depends on I2C depends on I2C
config I2C_ITE
tristate "ITE I2C Adapter"
depends on I2C && MIPS_ITE8172
select I2C_ALGOITE
help
This supports the ITE8172 I2C peripheral found on some MIPS
systems. Say Y if you have one of these. You should also say Y for
the ITE I2C driver algorithm support above.
This support is also available as a module. If so, the module
will be called i2c-ite.
config I2C_IXP4XX config I2C_IXP4XX
tristate "IXP4xx GPIO-Based I2C Interface" tristate "IXP4xx GPIO-Based I2C Interface"
depends on I2C && ARCH_IXP4XX depends on I2C && ARCH_IXP4XX
...@@ -481,6 +476,17 @@ config I2C_STUB ...@@ -481,6 +476,17 @@ config I2C_STUB
If you don't know what to do here, definitely say N. If you don't know what to do here, definitely say N.
config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support"
depends on I2C && (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.
config I2C_VIA config I2C_VIA
tristate "VIA 82C586B" tristate "VIA 82C586B"
depends on I2C && PCI && EXPERIMENTAL depends on I2C && PCI && EXPERIMENTAL
...@@ -548,4 +554,23 @@ config I2C_MV64XXX ...@@ -548,4 +554,23 @@ config I2C_MV64XXX
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-mv64xxx. will be called i2c-mv64xxx.
config I2C_PNX
tristate "I2C bus support for Philips PNX targets"
depends on ARCH_PNX4008 && I2C
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_PNX_EARLY
bool "Early initialization for I2C on PNXxxxx"
depends on I2C_PNX=y
help
Under certain circumstances one may need to make sure I2C on PNXxxxx
is initialized earlier than some other driver that depends on it
(for instance, that might be USB in case of PNX4008). With this
option turned on you can guarantee that.
endmenu endmenu
...@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
...@@ -16,7 +17,6 @@ obj-$(CONFIG_I2C_I810) += i2c-i810.o ...@@ -16,7 +17,6 @@ obj-$(CONFIG_I2C_I810) += i2c-i810.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_ISA) += i2c-isa.o obj-$(CONFIG_I2C_ISA) += i2c-isa.o
obj-$(CONFIG_I2C_ITE) += i2c-ite.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
...@@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o ...@@ -29,6 +29,7 @@ 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_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
...@@ -39,6 +40,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o ...@@ -39,6 +40,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIA) += i2c-via.o
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
......
/*
i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
Copyright (C) 2004 Rick Bronson
Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
Borrowed heavily from original work by:
Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/arch/at91_twi.h>
#include <asm/arch/board.h>
#include <asm/arch/cpu.h>
#define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */
static struct clk *twi_clk;
static void __iomem *twi_base;
#define at91_twi_read(reg) __raw_readl(twi_base + (reg))
#define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg))
/*
* Initialize the TWI hardware registers.
*/
static void __devinit at91_twi_hwinit(void)
{
unsigned long cdiv, ckdiv;
at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */
at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */
at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); /* Set Master mode */
/* Calcuate clock dividers */
cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
cdiv = cdiv + 1; /* round up */
ckdiv = 0;
while (cdiv > 255) {
ckdiv++;
cdiv = cdiv >> 1;
}
if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */
if (ckdiv > 5) {
printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
ckdiv = 5;
}
}
at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
}
/*
* Poll the i2c status register until the specified bit is set.
* Returns 0 if timed out (100 msec).
*/
static short at91_poll_status(unsigned long bit)
{
int loop_cntr = 10000;
do {
udelay(10);
} while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
return (loop_cntr > 0);
}
static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
{
/* Send Start */
at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
/* Read data */
while (length--) {
if (!length) /* need to send Stop before reading last byte */
at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
if (!at91_poll_status(AT91_TWI_RXRDY)) {
dev_dbg(&adap->dev, "RXRDY timeout\n");
return -ETIMEDOUT;
}
*buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
}
return 0;
}
static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
{
/* Load first byte into transmitter */
at91_twi_write(AT91_TWI_THR, *buf++);
/* Send Start */
at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
do {
if (!at91_poll_status(AT91_TWI_TXRDY)) {
dev_dbg(&adap->dev, "TXRDY timeout\n");
return -ETIMEDOUT;
}
length--; /* byte was transmitted */
if (length > 0) /* more data to send? */
at91_twi_write(AT91_TWI_THR, *buf++);
} while (length);
/* Send Stop */
at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
return 0;
}
/*
* Generic i2c master transfer entrypoint.
*
* Note: We do not use Atmel's feature of storing the "internal device address".
* Instead the "internal device address" has to be written using a seperate
* i2c message.
* http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
*/
static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
{
int i, ret;
dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
for (i = 0; i < num; i++) {
dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
pmsg->flags & I2C_M_RD ? "read" : "writ",
pmsg->len, pmsg->len > 1 ? "s" : "",
pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
| ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
if (pmsg->len && pmsg->buf) { /* sanity check */
if (pmsg->flags & I2C_M_RD)
ret = xfer_read(adap, pmsg->buf, pmsg->len);
else
ret = xfer_write(adap, pmsg->buf, pmsg->len);
if (ret)
return ret;
/* Wait until transfer is finished */
if (!at91_poll_status(AT91_TWI_TXCOMP)) {
dev_dbg(&adap->dev, "TXCOMP timeout\n");
return -ETIMEDOUT;
}
}
dev_dbg(&adap->dev, "transfer complete\n");
pmsg++; /* next message */
}
return i;
}
/*
* Return list of supported functionality.
*/
static u32 at91_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm at91_algorithm = {
.master_xfer = at91_xfer,
.functionality = at91_func,
};
/*
* Main initialization routine.
*/
static int __devinit at91_i2c_probe(struct platform_device *pdev)
{
struct i2c_adapter *adapter;
struct resource *res;
int rc;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
if (!request_mem_region(res->start, res->end - res->start + 1, "at91_i2c"))
return -EBUSY;
twi_base = ioremap(res->start, res->end - res->start + 1);
if (!twi_base) {
rc = -ENOMEM;
goto fail0;
}
twi_clk = clk_get(NULL, "twi_clk");
if (IS_ERR(twi_clk)) {
dev_err(&pdev->dev, "no clock defined\n");
rc = -ENODEV;
goto fail1;
}
adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
if (adapter == NULL) {
dev_err(&pdev->dev, "can't allocate inteface!\n");
rc = -ENOMEM;
goto fail2;
}
sprintf(adapter->name, "AT91");
adapter->algo = &at91_algorithm;
adapter->class = I2C_CLASS_HWMON;
adapter->dev.parent = &pdev->dev;
platform_set_drvdata(pdev, adapter);
clk_enable(twi_clk); /* enable peripheral clock */
at91_twi_hwinit(); /* initialize TWI controller */
rc = i2c_add_adapter(adapter);
if (rc) {
dev_err(&pdev->dev, "Adapter %s registration failed\n",
adapter->name);
goto fail3;
}
dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
return 0;
fail3:
platform_set_drvdata(pdev, NULL);
kfree(adapter);
clk_disable(twi_clk);
fail2:
clk_put(twi_clk);
fail1:
iounmap(twi_base);
fail0:
release_mem_region(res->start, res->end - res->start + 1);
return rc;
}
static int __devexit at91_i2c_remove(struct platform_device *pdev)
{
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
struct resource *res;
int rc;
rc = i2c_del_adapter(adapter);
platform_set_drvdata(pdev, NULL);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap(twi_base);
release_mem_region(res->start, res->end - res->start + 1);
clk_disable(twi_clk); /* disable peripheral clock */
clk_put(twi_clk);
return rc;
}
#ifdef CONFIG_PM
/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg)
{
clk_disable(twi_clk);
return 0;
}
static int at91_i2c_resume(struct platform_device *pdev)
{
return clk_enable(twi_clk);
}
#else
#define at91_i2c_suspend NULL
#define at91_i2c_resume NULL
#endif
static struct platform_driver at91_i2c_driver = {
.probe = at91_i2c_probe,
.remove = __devexit_p(at91_i2c_remove),
.suspend = at91_i2c_suspend,
.resume = at91_i2c_resume,
.driver = {
.name = "at91_i2c",
.owner = THIS_MODULE,
},
};
static int __init at91_i2c_init(void)
{
return platform_driver_register(&at91_i2c_driver);
}
static void __exit at91_i2c_exit(void)
{
platform_driver_unregister(&at91_i2c_driver);
}
module_init(at91_i2c_init);
module_exit(at91_i2c_exit);
MODULE_AUTHOR("Rick Bronson");
MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
MODULE_LICENSE("GPL");
...@@ -293,7 +293,7 @@ static int __init i2c_pcfisa_init(void) ...@@ -293,7 +293,7 @@ static int __init i2c_pcfisa_init(void)
static void i2c_pcfisa_exit(void) static void i2c_pcfisa_exit(void)
{ {
i2c_pcf_del_bus(&pcf_isa_ops); i2c_del_adapter(&pcf_isa_ops);
if (irq > 0) { if (irq > 0) {
disable_irq(irq); disable_irq(irq);
......
...@@ -146,7 +146,7 @@ static int __devinit hydra_probe(struct pci_dev *dev, ...@@ -146,7 +146,7 @@ static int __devinit hydra_probe(struct pci_dev *dev,
static void __devexit hydra_remove(struct pci_dev *dev) static void __devexit hydra_remove(struct pci_dev *dev)
{ {
pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */
i2c_bit_del_bus(&hydra_adap); i2c_del_adapter(&hydra_adap);
iounmap(hydra_bit_data.data); iounmap(hydra_bit_data.data);
release_mem_region(pci_resource_start(dev, 0)+ release_mem_region(pci_resource_start(dev, 0)+
offsetof(struct Hydra, CachePD), 4); offsetof(struct Hydra, CachePD), 4);
......
...@@ -470,12 +470,20 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id ...@@ -470,12 +470,20 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
int err; int err;
I801_dev = dev; I801_dev = dev;
if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || switch (dev->device) {
(dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || case PCI_DEVICE_ID_INTEL_82801DB_3:
(dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) case PCI_DEVICE_ID_INTEL_82801EB_3:
case PCI_DEVICE_ID_INTEL_ESB_4:
case PCI_DEVICE_ID_INTEL_ICH6_16:
case PCI_DEVICE_ID_INTEL_ICH7_17:
case PCI_DEVICE_ID_INTEL_ESB2_17:
case PCI_DEVICE_ID_INTEL_ICH8_5:
case PCI_DEVICE_ID_INTEL_ICH9_6:
isich4 = 1; isich4 = 1;
else break;
default:
isich4 = 0; isich4 = 0;
}
err = pci_enable_device(dev); err = pci_enable_device(dev);
if (err) { if (err) {
......
...@@ -219,14 +219,14 @@ static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id ...@@ -219,14 +219,14 @@ static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id
return retval; return retval;
retval = i2c_bit_add_bus(&i810_ddc_adapter); retval = i2c_bit_add_bus(&i810_ddc_adapter);
if (retval) if (retval)
i2c_bit_del_bus(&i810_i2c_adapter); i2c_del_adapter(&i810_i2c_adapter);
return retval; return retval;
} }
static void __devexit i810_remove(struct pci_dev *dev) static void __devexit i810_remove(struct pci_dev *dev)
{ {
i2c_bit_del_bus(&i810_ddc_adapter); i2c_del_adapter(&i810_ddc_adapter);
i2c_bit_del_bus(&i810_i2c_adapter); i2c_del_adapter(&i810_i2c_adapter);
iounmap(ioaddr); iounmap(ioaddr);
} }
......
...@@ -680,6 +680,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){ ...@@ -680,6 +680,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){
dev->idx = ocp->def->index; dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev); ocp_set_drvdata(ocp, dev);
if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
"ibm_iic")) {
ret = -EBUSY;
goto fail1;
}
if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
dev->idx); dev->idx);
...@@ -750,6 +756,8 @@ static int __devinit iic_probe(struct ocp_device *ocp){ ...@@ -750,6 +756,8 @@ static int __devinit iic_probe(struct ocp_device *ocp){
iounmap(dev->vaddr); iounmap(dev->vaddr);
fail2: fail2:
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
fail1:
ocp_set_drvdata(ocp, NULL); ocp_set_drvdata(ocp, NULL);
kfree(dev); kfree(dev);
return ret; return ret;
...@@ -777,6 +785,7 @@ static void __devexit iic_remove(struct ocp_device *ocp) ...@@ -777,6 +785,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
} }
iounmap(dev->vaddr); iounmap(dev->vaddr);
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
kfree(dev); kfree(dev);
} }
} }
......
/*
-------------------------------------------------------------------------
i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system
-------------------------------------------------------------------------
Hai-Pao Fan, MontaVista Software, Inc.
hpfan@mvista.com or source@mvista.com
Copyright 2001 MontaVista Software Inc.
----------------------------------------------------------------------------
This file was highly leveraged from i2c-elektor.c, which was created
by Simon G. Vogl and Hans Berglund:
Copyright (C) 1995-97 Simon G. Vogl
1998-99 Hans Berglund
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-ite.h>
#include <linux/i2c-adap-ite.h>
#include "../i2c-ite.h"
#define DEFAULT_BASE 0x14014030
#define ITE_IIC_IO_SIZE 0x40
#define DEFAULT_IRQ 0
#define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */
#define DEFAULT_OWN 0x55
static int base;
static int irq;
static int clock;
static int own;
static struct iic_ite gpi;
static wait_queue_head_t iic_wait;
static int iic_pending;
static spinlock_t lock;
/* ----- local functions ---------------------------------------------- */
static void iic_ite_setiic(void *data, int ctl, short val)
{
unsigned long j = jiffies + 10;
pr_debug(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff);
#ifdef DEBUG
while (time_before(jiffies, j))
schedule();
#endif
outw(val,ctl);
}
static short iic_ite_getiic(void *data, int ctl)
{
short val;
val = inw(ctl);
pr_debug("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff);
return (val);
}
/* Return our slave address. This is the address
* put on the I2C bus when another master on the bus wants to address us
* as a slave
*/
static int iic_ite_getown(void *data)
{
return (gpi.iic_own);
}
static int iic_ite_getclock(void *data)
{
return (gpi.iic_clock);
}
/* Put this process to sleep. We will wake up when the
* IIC controller interrupts.
*/
static void iic_ite_waitforpin(void) {
DEFINE_WAIT(wait);
int timeout = 2;
unsigned long flags;
/* If interrupts are enabled (which they are), then put the process to
* sleep. This process will be awakened by two events -- either the
* the IIC peripheral interrupts or the timeout expires.
* If interrupts are not enabled then delay for a reasonable amount
* of time and return.
*/
if (gpi.iic_irq > 0) {
spin_lock_irqsave(&lock, flags);
if (iic_pending == 0) {
spin_unlock_irqrestore(&lock, flags);
prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE);
if (schedule_timeout(timeout*HZ)) {
spin_lock_irqsave(&lock, flags);
if (iic_pending == 1) {
iic_pending = 0;
}
spin_unlock_irqrestore(&lock, flags);
}
finish_wait(&iic_wait, &wait);
} else {
iic_pending = 0;
spin_unlock_irqrestore(&lock, flags);
}
} else {
udelay(100);
}
}
static irqreturn_t iic_ite_handler(int this_irq, void *dev_id)
{
spin_lock(&lock);
iic_pending = 1;
spin_unlock(&lock);
wake_up_interruptible(&iic_wait);
return IRQ_HANDLED;
}
/* Lock the region of memory where I/O registers exist. Request our
* interrupt line and register its associated handler.
*/
static int iic_hw_resrc_init(void)
{
if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c"))
return -ENODEV;
if (gpi.iic_irq <= 0)
return 0;
if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0)
gpi.iic_irq = 0;
else
enable_irq(gpi.iic_irq);
return 0;
}
static void iic_ite_release(void)
{
if (gpi.iic_irq > 0) {
disable_irq(gpi.iic_irq);
free_irq(gpi.iic_irq, 0);
}
release_region(gpi.iic_base , 2);
}
/* ------------------------------------------------------------------------
* Encapsulate the above functions in the correct operations structure.
* This is only done when more than one hardware adapter is supported.
*/
static struct i2c_algo_iic_data iic_ite_data = {
NULL,
iic_ite_setiic,
iic_ite_getiic,
iic_ite_getown,
iic_ite_getclock,
iic_ite_waitforpin,
80, 80, 100, /* waits, timeout */
};
static struct i2c_adapter iic_ite_ops = {
.owner = THIS_MODULE,
.id = I2C_HW_I_IIC,
.algo_data = &iic_ite_data,
.name = "ITE IIC adapter",
};
/* Called when the module is loaded. This function starts the
* cascade of calls up through the hierarchy of i2c modules (i.e. up to the
* algorithm layer and into to the core layer)
*/
static int __init iic_ite_init(void)
{
struct iic_ite *piic = &gpi;
printk(KERN_INFO "Initialize ITE IIC adapter module\n");
if (base == 0)
piic->iic_base = DEFAULT_BASE;
else
piic->iic_base = base;
if (irq == 0)
piic->iic_irq = DEFAULT_IRQ;
else
piic->iic_irq = irq;
if (clock == 0)
piic->iic_clock = DEFAULT_CLOCK;
else
piic->iic_clock = clock;
if (own == 0)
piic->iic_own = DEFAULT_OWN;
else
piic->iic_own = own;
iic_ite_data.data = (void *)piic;
init_waitqueue_head(&iic_wait);
spin_lock_init(&lock);
if (iic_hw_resrc_init() == 0) {
if (i2c_iic_add_bus(&iic_ite_ops) < 0)
return -ENODEV;
} else {
return -ENODEV;
}
printk(KERN_INFO " found device at %#x irq %d.\n",
piic->iic_base, piic->iic_irq);
return 0;
}
static void iic_ite_exit(void)
{
i2c_iic_del_bus(&iic_ite_ops);
iic_ite_release();
}
/* If modules is NOT defined when this file is compiled, then the MODULE_*
* macros will resolve to nothing
*/
MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter");
MODULE_LICENSE("GPL");
module_param(base, int, 0);
module_param(irq, int, 0);
module_param(clock, int, 0);
module_param(own, int, 0);
/* Called when module is loaded or when kernel is initialized.
* If MODULES is defined when this file is compiled, then this function will
* resolve to init_module (the function called when insmod is invoked for a
* module). Otherwise, this function is called early in the boot, when the
* kernel is intialized. Check out /include/init.h to see how this works.
*/
module_init(iic_ite_init);
/* Resolves to module_cleanup when MODULES is defined. */
module_exit(iic_ite_exit);
...@@ -90,7 +90,7 @@ static int ixp2000_i2c_remove(struct platform_device *plat_dev) ...@@ -90,7 +90,7 @@ static int ixp2000_i2c_remove(struct platform_device *plat_dev)
platform_set_drvdata(plat_dev, NULL); platform_set_drvdata(plat_dev, NULL);
i2c_bit_del_bus(&drv_data->adapter); i2c_del_adapter(&drv_data->adapter);
kfree(drv_data); kfree(drv_data);
......
...@@ -91,7 +91,7 @@ static int ixp4xx_i2c_remove(struct platform_device *plat_dev) ...@@ -91,7 +91,7 @@ static int ixp4xx_i2c_remove(struct platform_device *plat_dev)
platform_set_drvdata(plat_dev, NULL); platform_set_drvdata(plat_dev, NULL);
i2c_bit_del_bus(&drv_data->adapter); i2c_del_adapter(&drv_data->adapter);
kfree(drv_data); kfree(drv_data);
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
nForce4 MCP55 0368 nForce4 MCP55 0368
This driver supports the 2 SMBuses that are included in the MCP of the This driver supports the 2 SMBuses that are included in the MCP of the
nForce2/3/4 chipsets. nForce2/3/4/5xx chipsets.
*/ */
/* Note: we assume there can only be one nForce2, with two SMBus interfaces */ /* Note: we assume there can only be one nForce2, with two SMBus interfaces */
...@@ -52,8 +52,8 @@ ...@@ -52,8 +52,8 @@
#include <asm/io.h> #include <asm/io.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>"); MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@gmx.net>");
MODULE_DESCRIPTION("nForce2 SMBus driver"); MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");
struct nforce2_smbus { struct nforce2_smbus {
...@@ -80,9 +80,6 @@ struct nforce2_smbus { ...@@ -80,9 +80,6 @@ struct nforce2_smbus {
#define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */ #define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */
#define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */ #define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */
#define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */ #define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */
#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data bytes */
#define NVIDIA_SMB_ALRM_A (smbus->base + 0x25) /* alarm address */
#define NVIDIA_SMB_ALRM_D (smbus->base + 0x26) /* 2 bytes alarm data */
#define NVIDIA_SMB_STS_DONE 0x80 #define NVIDIA_SMB_STS_DONE 0x80
#define NVIDIA_SMB_STS_ALRM 0x40 #define NVIDIA_SMB_STS_ALRM 0x40
...@@ -95,40 +92,17 @@ struct nforce2_smbus { ...@@ -95,40 +92,17 @@ struct nforce2_smbus {
#define NVIDIA_SMB_PRTCL_BYTE 0x04 #define NVIDIA_SMB_PRTCL_BYTE 0x04
#define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06 #define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06
#define NVIDIA_SMB_PRTCL_WORD_DATA 0x08 #define NVIDIA_SMB_PRTCL_WORD_DATA 0x08
#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a
#define NVIDIA_SMB_PRTCL_PROC_CALL 0x0c
#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define NVIDIA_SMB_PRTCL_PEC 0x80 #define NVIDIA_SMB_PRTCL_PEC 0x80
static struct pci_driver nforce2_driver; static struct pci_driver nforce2_driver;
static s32 nforce2_access(struct i2c_adapter *adap, u16 addr, /* Return -1 on error */
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data);
static u32 nforce2_func(struct i2c_adapter *adapter);
static const struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = nforce2_access,
.functionality = nforce2_func,
};
static struct i2c_adapter nforce2_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
};
/* Return -1 on error. See smbus.h for more information */
static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data) u8 command, int size, union i2c_smbus_data * data)
{ {
struct nforce2_smbus *smbus = adap->algo_data; struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec, temp; unsigned char protocol, pec, temp;
unsigned char len = 0; /* to keep the compiler quiet */
int i;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
NVIDIA_SMB_PRTCL_WRITE; NVIDIA_SMB_PRTCL_WRITE;
...@@ -163,35 +137,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, ...@@ -163,35 +137,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec; protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
break; break;
case I2C_SMBUS_BLOCK_DATA:
outb_p(command, NVIDIA_SMB_CMD);
if (read_write == I2C_SMBUS_WRITE) {
len = min_t(u8, data->block[0], 32);
outb_p(len, NVIDIA_SMB_BCNT);
for (i = 0; i < len; i++)
outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
}
protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
len = min_t(u8, data->block[0], 32);
outb_p(command, NVIDIA_SMB_CMD);
outb_p(len, NVIDIA_SMB_BCNT);
if (read_write == I2C_SMBUS_WRITE)
for (i = 0; i < len; i++)
outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA;
break;
case I2C_SMBUS_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
return -1;
case I2C_SMBUS_BLOCK_PROC_CALL:
dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
return -1;
default: default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size); dev_err(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -1;
...@@ -227,19 +172,8 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, ...@@ -227,19 +172,8 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
break; break;
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
/* case I2C_SMBUS_PROC_CALL: not supported */
data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8); data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
break; break;
case I2C_SMBUS_BLOCK_DATA:
/* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */
len = inb_p(NVIDIA_SMB_BCNT);
len = min_t(u8, len, 32);
case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < len; i++)
data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
data->block[0] = len;
break;
} }
return 0; return 0;
...@@ -250,10 +184,14 @@ static u32 nforce2_func(struct i2c_adapter *adapter) ...@@ -250,10 +184,14 @@ static u32 nforce2_func(struct i2c_adapter *adapter)
{ {
/* other functionality might be possible, but is not tested */ /* other functionality might be possible, but is not tested */
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
I2C_FUNC_SMBUS_BLOCK_DATA */;
} }
static struct i2c_algorithm smbus_algorithm = {
.smbus_xfer = nforce2_access,
.functionality = nforce2_func,
};
static struct pci_device_id nforce2_ids[] = { static struct pci_device_id nforce2_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
...@@ -267,7 +205,6 @@ static struct pci_device_id nforce2_ids[] = { ...@@ -267,7 +205,6 @@ static struct pci_device_id nforce2_ids[] = {
{ 0 } { 0 }
}; };
MODULE_DEVICE_TABLE (pci, nforce2_ids); MODULE_DEVICE_TABLE (pci, nforce2_ids);
...@@ -291,7 +228,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, ...@@ -291,7 +228,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
} }
smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
smbus->size = 8; smbus->size = 64;
} }
smbus->dev = dev; smbus->dev = dev;
...@@ -300,7 +237,9 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, ...@@ -300,7 +237,9 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
smbus->base, smbus->base+smbus->size-1, name); smbus->base, smbus->base+smbus->size-1, name);
return -1; return -1;
} }
smbus->adapter = nforce2_adapter; smbus->adapter.owner = THIS_MODULE;
smbus->adapter.class = I2C_CLASS_HWMON;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
smbus->adapter.dev.parent = &dev->dev; smbus->adapter.dev.parent = &dev->dev;
snprintf(smbus->adapter.name, I2C_NAME_SIZE, snprintf(smbus->adapter.name, I2C_NAME_SIZE,
......
...@@ -231,8 +231,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) ...@@ -231,8 +231,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
* 13 2 1 * 13 2 1
* 19.2 2 1 * 19.2 2 1
*/ */
if (fclk_rate > 16000000) if (fclk_rate > 12000000)
psc = (fclk_rate + 8000000) / 12000000; psc = fclk_rate / 12000000;
} }
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
......
...@@ -163,7 +163,7 @@ static void __exit i2c_parport_exit(void) ...@@ -163,7 +163,7 @@ static void __exit i2c_parport_exit(void)
if (adapter_parm[type].init.val) if (adapter_parm[type].init.val)
line_set(0, &adapter_parm[type].init); line_set(0, &adapter_parm[type].init);
i2c_bit_del_bus(&parport_adapter); i2c_del_adapter(&parport_adapter);
release_region(base, 3); release_region(base, 3);
} }
......
...@@ -218,7 +218,7 @@ static void i2c_parport_detach (struct parport *port) ...@@ -218,7 +218,7 @@ static void i2c_parport_detach (struct parport *port)
if (adapter_parm[type].init.val) if (adapter_parm[type].init.val)
line_set(port, 0, &adapter_parm[type].init); line_set(port, 0, &adapter_parm[type].init);
i2c_bit_del_bus(&adapter->adapter); i2c_del_adapter(&adapter->adapter);
parport_unregister_device(adapter->pdev); parport_unregister_device(adapter->pdev);
if (prev) if (prev)
prev->next = adapter->next; prev->next = adapter->next;
......
...@@ -156,7 +156,7 @@ static int __init pca_isa_init(void) ...@@ -156,7 +156,7 @@ static int __init pca_isa_init(void)
static void pca_isa_exit(void) static void pca_isa_exit(void)
{ {
i2c_pca_del_bus(&pca_isa_ops); i2c_del_adapter(&pca_isa_ops);
if (irq > 0) { if (irq > 0) {
disable_irq(irq); disable_irq(irq);
......
/*
* Provides I2C support for Philips PNX010x/PNX4008 boards.
*
* Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
* Vitaly Wool <vwool@ru.mvista.com>
*
* 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/i2c-pnx.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#define I2C_PNX_TIMEOUT 10 /* msec */
#define I2C_PNX_SPEED_KHZ 100
#define I2C_PNX_REGION_SIZE 0x100
#define PNX_DEFAULT_FREQ 13 /* MHz */
static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
{
while (timeout > 0 &&
(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
mdelay(1);
timeout--;
}
return (timeout <= 0);
}
static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
{
while (timeout > 0 &&
(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
mdelay(1);
timeout--;
}
return (timeout <= 0);
}
static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *data = adap->algo_data;
struct timer_list *timer = &data->mif.timer;
int expires = I2C_PNX_TIMEOUT / (1000 / HZ);
del_timer_sync(timer);
dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n",
jiffies, expires);
timer->expires = jiffies + expires;
timer->data = (unsigned long)adap;
add_timer(timer);
}
/**
* i2c_pnx_start - start a device
* @slave_addr: slave address
* @adap: pointer to adapter structure
*
* Generate a START signal in the desired mode.
*/
static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__,
slave_addr, alg_data->mif.mode);
/* Check for 7 bit slave addresses only */
if (slave_addr & ~0x7f) {
dev_err(&adap->dev, "%s: Invalid slave address %x. "
"Only 7-bit addresses are supported\n",
adap->name, slave_addr);
return -EINVAL;
}
/* First, make sure bus is idle */
if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
/* Somebody else is monopolizing the bus */
dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, "
"cntrl = %x, stat = %x\n",
adap->name, slave_addr,
ioread32(I2C_REG_CTL(alg_data)),
ioread32(I2C_REG_STS(alg_data)));
return -EBUSY;
} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
/* Sorry, we lost the bus */
dev_err(&adap->dev, "%s: Arbitration failure. "
"Slave addr = %02x\n", adap->name, slave_addr);
return -EIO;
}
/*
* OK, I2C is enabled and we have the bus.
* Clear the current TDI and AFI status flags.
*/
iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
I2C_REG_STS(alg_data));
dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__,
(slave_addr << 1) | start_bit | alg_data->mif.mode);
/* Write the slave address, START bit and R/W bit */
iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
I2C_REG_TX(alg_data));
dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
return 0;
}
/**
* i2c_pnx_stop - stop a device
* @adap: pointer to I2C adapter structure
*
* Generate a STOP signal to terminate the master transaction.
*/
static void i2c_pnx_stop(struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
/* Only 1 msec max timeout due to interrupt context */
long timeout = 1000;
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
/* Write a STOP bit to TX FIFO */
iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
/* Wait until the STOP is seen. */
while (timeout > 0 &&
(ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
/* may be called from interrupt context */
udelay(1);
timeout--;
}
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
}
/**
* i2c_pnx_master_xmit - transmit data to slave
* @adap: pointer to I2C adapter structure
*
* Sends one byte of data to the slave
*/
static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
u32 val;
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
if (alg_data->mif.len > 0) {
/* We still have something to talk about... */
val = *alg_data->mif.buf++;
if (alg_data->mif.len == 1) {
val |= stop_bit;
if (!alg_data->last)
val |= start_bit;
}
alg_data->mif.len--;
iowrite32(val, I2C_REG_TX(alg_data));
dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__,
val, alg_data->mif.len + 1);
if (alg_data->mif.len == 0) {
if (alg_data->last) {
/* Wait until the STOP is seen. */
if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
dev_err(&adap->dev, "The bus is still "
"active after timeout\n");
}
/* Disable master interrupts */
iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
I2C_REG_CTL(alg_data));
del_timer_sync(&alg_data->mif.timer);
dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
__FUNCTION__);
complete(&alg_data->mif.complete);
}
} else if (alg_data->mif.len == 0) {
/* zero-sized transfer */
i2c_pnx_stop(adap);
/* Disable master interrupts. */
iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
I2C_REG_CTL(alg_data));
/* Stop timer. */
del_timer_sync(&alg_data->mif.timer);
dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
"zero-xfer.\n", __FUNCTION__);
complete(&alg_data->mif.complete);
}
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
return 0;
}
/**
* i2c_pnx_master_rcv - receive data from slave
* @adap: pointer to I2C adapter structure
*
* Reads one byte data from the slave
*/
static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
unsigned int val = 0;
u32 ctl = 0;
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
/* Check, whether there is already data,
* or we didn't 'ask' for it yet.
*/
if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
"Rx-fifo...\n", __FUNCTION__);
if (alg_data->mif.len == 1) {
/* Last byte, do not acknowledge next rcv. */
val |= stop_bit;
if (!alg_data->last)
val |= start_bit;
/*
* Enable interrupt RFDAIE (data in Rx fifo),
* and disable DRMIE (need data for Tx)
*/
ctl = ioread32(I2C_REG_CTL(alg_data));
ctl |= mcntrl_rffie | mcntrl_daie;
ctl &= ~mcntrl_drmie;
iowrite32(ctl, I2C_REG_CTL(alg_data));
}
/*
* Now we'll 'ask' for data:
* For each byte we want to receive, we must
* write a (dummy) byte to the Tx-FIFO.
*/
iowrite32(val, I2C_REG_TX(alg_data));
return 0;
}
/* Handle data. */
if (alg_data->mif.len > 0) {
val = ioread32(I2C_REG_RX(alg_data));
*alg_data->mif.buf++ = (u8) (val & 0xff);
dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val,
alg_data->mif.len);
alg_data->mif.len--;
if (alg_data->mif.len == 0) {
if (alg_data->last)
/* Wait until the STOP is seen. */
if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
dev_err(&adap->dev, "The bus is still "
"active after timeout\n");
/* Disable master interrupts */
ctl = ioread32(I2C_REG_CTL(alg_data));
ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
mcntrl_drmie | mcntrl_daie);
iowrite32(ctl, I2C_REG_CTL(alg_data));
/* Kill timer. */
del_timer_sync(&alg_data->mif.timer);
complete(&alg_data->mif.complete);
}
}
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
return 0;
}
static irqreturn_t
i2c_pnx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
u32 stat, ctl;
struct i2c_adapter *adap = dev_id;
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
__FUNCTION__,
ioread32(I2C_REG_STS(alg_data)),
ioread32(I2C_REG_CTL(alg_data)),
alg_data->mif.mode);
stat = ioread32(I2C_REG_STS(alg_data));
/* let's see what kind of event this is */
if (stat & mstatus_afi) {
/* We lost arbitration in the midst of a transfer */
alg_data->mif.ret = -EIO;
/* Disable master interrupts. */
ctl = ioread32(I2C_REG_CTL(alg_data));
ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
mcntrl_drmie);
iowrite32(ctl, I2C_REG_CTL(alg_data));
/* Stop timer, to prevent timeout. */
del_timer_sync(&alg_data->mif.timer);
complete(&alg_data->mif.complete);
} else if (stat & mstatus_nai) {
/* Slave did not acknowledge, generate a STOP */
dev_dbg(&adap->dev, "%s(): "
"Slave did not acknowledge, generating a STOP.\n",
__FUNCTION__);
i2c_pnx_stop(adap);
/* Disable master interrupts. */
ctl = ioread32(I2C_REG_CTL(alg_data));
ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
mcntrl_drmie);
iowrite32(ctl, I2C_REG_CTL(alg_data));
/* Our return value. */
alg_data->mif.ret = -EIO;
/* Stop timer, to prevent timeout. */
del_timer_sync(&alg_data->mif.timer);
complete(&alg_data->mif.complete);
} else {
/*
* Two options:
* - Master Tx needs data.
* - There is data in the Rx-fifo
* The latter is only the case if we have requested for data,
* via a dummy write. (See 'i2c_pnx_master_rcv'.)
* We therefore check, as a sanity check, whether that interrupt
* has been enabled.
*/
if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
i2c_pnx_master_xmit(adap);
} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
i2c_pnx_master_rcv(adap);
}
}
}
/* Clear TDI and AFI bits */
stat = ioread32(I2C_REG_STS(alg_data));
iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)),
ioread32(I2C_REG_CTL(alg_data)));
return IRQ_HANDLED;
}
static void i2c_pnx_timeout(unsigned long data)
{
struct i2c_adapter *adap = (struct i2c_adapter *)data;
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
u32 ctl;
dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. "
"Resetting master...\n",
ioread32(I2C_REG_STS(alg_data)),
ioread32(I2C_REG_CTL(alg_data)));
/* Reset master and disable interrupts */
ctl = ioread32(I2C_REG_CTL(alg_data));
ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
iowrite32(ctl, I2C_REG_CTL(alg_data));
ctl |= mcntrl_reset;
iowrite32(ctl, I2C_REG_CTL(alg_data));
wait_reset(I2C_PNX_TIMEOUT, alg_data);
alg_data->mif.ret = -EIO;
complete(&alg_data->mif.complete);
}
static inline void bus_reset_if_active(struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
u32 stat;
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
dev_err(&adap->dev,
"%s: Bus is still active after xfer. Reset it...\n",
adap->name);
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
I2C_REG_CTL(alg_data));
wait_reset(I2C_PNX_TIMEOUT, alg_data);
} else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
/* If there is data in the fifo's after transfer,
* flush fifo's by reset.
*/
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
I2C_REG_CTL(alg_data));
wait_reset(I2C_PNX_TIMEOUT, alg_data);
} else if (stat & mstatus_nai) {
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
I2C_REG_CTL(alg_data));
wait_reset(I2C_PNX_TIMEOUT, alg_data);
}
}
/**
* i2c_pnx_xfer - generic transfer entry point
* @adap: pointer to I2C adapter structure
* @msgs: array of messages
* @num: number of messages
*
* Initiates the transfer
*/
static int
i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
struct i2c_msg *pmsg;
int rc = 0, completed = 0, i;
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
u32 stat = ioread32(I2C_REG_STS(alg_data));
dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
__FUNCTION__, num, ioread32(I2C_REG_STS(alg_data)));
bus_reset_if_active(adap);
/* Process transactions in a loop. */
for (i = 0; rc >= 0 && i < num; i++) {
u8 addr;
pmsg = &msgs[i];
addr = pmsg->addr;
if (pmsg->flags & I2C_M_TEN) {
dev_err(&adap->dev,
"%s: 10 bits addr not supported!\n",
adap->name);
rc = -EINVAL;
break;
}
alg_data->mif.buf = pmsg->buf;
alg_data->mif.len = pmsg->len;
alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
I2C_SMBUS_READ : I2C_SMBUS_WRITE;
alg_data->mif.ret = 0;
alg_data->last = (i == num - 1);
dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__,
alg_data->mif.mode,
alg_data->mif.len);
i2c_pnx_arm_timer(adap);
/* initialize the completion var */
init_completion(&alg_data->mif.complete);
/* Enable master interrupt */
iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
mcntrl_naie | mcntrl_drmie,
I2C_REG_CTL(alg_data));
/* Put start-code and slave-address on the bus. */
rc = i2c_pnx_start(addr, adap);
if (rc < 0)
break;
/* Wait for completion */
wait_for_completion(&alg_data->mif.complete);
if (!(rc = alg_data->mif.ret))
completed++;
dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
__FUNCTION__, rc);
/* Clear TDI and AFI bits in case they are set. */
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
dev_dbg(&adap->dev,
"%s: TDI still set... clearing now.\n",
adap->name);
iowrite32(stat, I2C_REG_STS(alg_data));
}
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
dev_dbg(&adap->dev,
"%s: AFI still set... clearing now.\n",
adap->name);
iowrite32(stat, I2C_REG_STS(alg_data));
}
}
bus_reset_if_active(adap);
/* Cleanup to be sure... */
alg_data->mif.buf = NULL;
alg_data->mif.len = 0;
dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
if (completed != num)
return ((rc < 0) ? rc : -EREMOTEIO);
return num;
}
static u32 i2c_pnx_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm pnx_algorithm = {
.master_xfer = i2c_pnx_xfer,
.functionality = i2c_pnx_func,
};
static int i2c_pnx_controller_suspend(struct platform_device *pdev,
pm_message_t state)
{
struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
return i2c_pnx->suspend(pdev, state);
}
static int i2c_pnx_controller_resume(struct platform_device *pdev)
{
struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
return i2c_pnx->resume(pdev);
}
static int __devinit i2c_pnx_probe(struct platform_device *pdev)
{
unsigned long tmp;
int ret = 0;
struct i2c_pnx_algo_data *alg_data;
int freq_mhz;
struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
if (!i2c_pnx || !i2c_pnx->adapter) {
dev_err(&pdev->dev, "%s: no platform data supplied\n",
__FUNCTION__);
ret = -EINVAL;
goto out;
}
platform_set_drvdata(pdev, i2c_pnx);
if (i2c_pnx->calculate_input_freq)
freq_mhz = i2c_pnx->calculate_input_freq(pdev);
else {
freq_mhz = PNX_DEFAULT_FREQ;
dev_info(&pdev->dev, "Setting bus frequency to default value: "
"%d MHz", freq_mhz);
}
i2c_pnx->adapter->algo = &pnx_algorithm;
alg_data = i2c_pnx->adapter->algo_data;
init_timer(&alg_data->mif.timer);
alg_data->mif.timer.function = i2c_pnx_timeout;
alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter;
/* Register I/O resource */
if (!request_region(alg_data->base, I2C_PNX_REGION_SIZE, pdev->name)) {
dev_err(&pdev->dev,
"I/O region 0x%08x for I2C already in use.\n",
alg_data->base);
ret = -ENODEV;
goto out_drvdata;
}
if (!(alg_data->ioaddr =
(u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) {
dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
ret = -ENOMEM;
goto out_release;
}
i2c_pnx->set_clock_run(pdev);
/*
* Clock Divisor High This value is the number of system clocks
* the serial clock (SCL) will be high.
* For example, if the system clock period is 50 ns and the maximum
* desired serial period is 10000 ns (100 kHz), then CLKHI would be
* set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
* programmed into CLKHI will vary from this slightly due to
* variations in the output pad's rise and fall times as well as
* the deglitching filter length.
*/
tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
iowrite32(tmp, I2C_REG_CKH(alg_data));
iowrite32(tmp, I2C_REG_CKL(alg_data));
iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
ret = -ENODEV;
goto out_unmap;
}
init_completion(&alg_data->mif.complete);
ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
0, pdev->name, i2c_pnx->adapter);
if (ret)
goto out_clock;
/* Register this adapter with the I2C subsystem */
i2c_pnx->adapter->dev.parent = &pdev->dev;
ret = i2c_add_adapter(i2c_pnx->adapter);
if (ret < 0) {
dev_err(&pdev->dev, "I2C: Failed to add bus\n");
goto out_irq;
}
dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
i2c_pnx->adapter->name, alg_data->base, alg_data->irq);
return 0;
out_irq:
free_irq(alg_data->irq, alg_data);
out_clock:
i2c_pnx->set_clock_stop(pdev);
out_unmap:
iounmap((void *)alg_data->ioaddr);
out_release:
release_region(alg_data->base, I2C_PNX_REGION_SIZE);
out_drvdata:
platform_set_drvdata(pdev, NULL);
out:
return ret;
}
static int __devexit i2c_pnx_remove(struct platform_device *pdev)
{
struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
struct i2c_adapter *adap = i2c_pnx->adapter;
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
free_irq(alg_data->irq, alg_data);
i2c_del_adapter(adap);
i2c_pnx->set_clock_stop(pdev);
iounmap((void *)alg_data->ioaddr);
release_region(alg_data->base, I2C_PNX_REGION_SIZE);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver i2c_pnx_driver = {
.driver = {
.name = "pnx-i2c",
.owner = THIS_MODULE,
},
.probe = i2c_pnx_probe,
.remove = __devexit_p(i2c_pnx_remove),
.suspend = i2c_pnx_controller_suspend,
.resume = i2c_pnx_controller_resume,
};
static int __init i2c_adap_pnx_init(void)
{
return platform_driver_register(&i2c_pnx_driver);
}
static void __exit i2c_adap_pnx_exit(void)
{
platform_driver_unregister(&i2c_pnx_driver);
}
MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
MODULE_LICENSE("GPL");
#ifdef CONFIG_I2C_PNX_EARLY
/* We need to make sure I2C is initialized before USB */
subsys_initcall(i2c_adap_pnx_init);
#else
mudule_init(i2c_adap_pnx_init);
#endif
module_exit(i2c_adap_pnx_exit);
...@@ -212,7 +212,7 @@ static void prosavage_remove(struct pci_dev *dev) ...@@ -212,7 +212,7 @@ static void prosavage_remove(struct pci_dev *dev)
if (chip->i2c_bus[i].adap_ok == 0) if (chip->i2c_bus[i].adap_ok == 0)
continue; continue;
ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); ret = i2c_del_adapter(&chip->i2c_bus[i].adap);
if (ret) { if (ret) {
dev_err(&dev->dev, "%s not removed\n", dev_err(&dev->dev, "%s not removed\n",
chip->i2c_bus[i].adap.name); chip->i2c_bus[i].adap.name);
......
...@@ -173,7 +173,7 @@ static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_ ...@@ -173,7 +173,7 @@ static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_
static void __devexit savage4_remove(struct pci_dev *dev) static void __devexit savage4_remove(struct pci_dev *dev)
{ {
i2c_bit_del_bus(&savage4_i2c_adapter); i2c_del_adapter(&savage4_i2c_adapter);
iounmap(ioaddr); iounmap(ioaddr);
} }
......
/*
* i2c-versatile.c
*
* Copyright (C) 2006 ARM Ltd.
* written by Russell King, Deep Blue Solutions Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#define I2C_CONTROL 0x00
#define I2C_CONTROLS 0x00
#define I2C_CONTROLC 0x04
#define SCL (1 << 0)
#define SDA (1 << 1)
struct i2c_versatile {
struct i2c_adapter adap;
struct i2c_algo_bit_data algo;
void __iomem *base;
};
static void i2c_versatile_setsda(void *data, int state)
{
struct i2c_versatile *i2c = data;
writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
}
static void i2c_versatile_setscl(void *data, int state)
{
struct i2c_versatile *i2c = data;
writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
}
static int i2c_versatile_getsda(void *data)
{
struct i2c_versatile *i2c = data;
return !!(readl(i2c->base + I2C_CONTROL) & SDA);
}
static int i2c_versatile_getscl(void *data)
{
struct i2c_versatile *i2c = data;
return !!(readl(i2c->base + I2C_CONTROL) & SCL);
}
static struct i2c_algo_bit_data i2c_versatile_algo = {
.setsda = i2c_versatile_setsda,
.setscl = i2c_versatile_setscl,
.getsda = i2c_versatile_getsda,
.getscl = i2c_versatile_getscl,
.udelay = 30,
.timeout = HZ,
};
static int i2c_versatile_probe(struct platform_device *dev)
{
struct i2c_versatile *i2c;
struct resource *r;
int ret;
r = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!r) {
ret = -EINVAL;
goto err_out;
}
if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) {
ret = -EBUSY;
goto err_out;
}
i2c = kzalloc(sizeof(struct i2c_versatile), GFP_KERNEL);
if (!i2c) {
ret = -ENOMEM;
goto err_release;
}
i2c->base = ioremap(r->start, r->end - r->start + 1);
if (!i2c->base) {
ret = -ENOMEM;
goto err_free;
}
writel(SCL | SDA, i2c->base + I2C_CONTROLS);
i2c->adap.owner = THIS_MODULE;
strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
i2c->adap.algo_data = &i2c->algo;
i2c->adap.dev.parent = &dev->dev;
i2c->algo = i2c_versatile_algo;
i2c->algo.data = i2c;
ret = i2c_bit_add_bus(&i2c->adap);
if (ret >= 0) {
platform_set_drvdata(dev, i2c);
return 0;
}
iounmap(i2c->base);
err_free:
kfree(i2c);
err_release:
release_mem_region(r->start, r->end - r->start + 1);
err_out:
return ret;
}
static int i2c_versatile_remove(struct platform_device *dev)
{
struct i2c_versatile *i2c = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
i2c_del_adapter(&i2c->adap);
return 0;
}
static struct platform_driver i2c_versatile_driver = {
.probe = i2c_versatile_probe,
.remove = i2c_versatile_remove,
.driver = {
.name = "versatile-i2c",
.owner = THIS_MODULE,
},
};
static int __init i2c_versatile_init(void)
{
return platform_driver_register(&i2c_versatile_driver);
}
static void __exit i2c_versatile_exit(void)
{
platform_driver_unregister(&i2c_versatile_driver);
}
module_init(i2c_versatile_init);
module_exit(i2c_versatile_exit);
MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
MODULE_LICENSE("GPL");
...@@ -151,7 +151,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i ...@@ -151,7 +151,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
static void __devexit vt586b_remove(struct pci_dev *dev) static void __devexit vt586b_remove(struct pci_dev *dev)
{ {
i2c_bit_del_bus(&vt586b_adapter); i2c_del_adapter(&vt586b_adapter);
release_region(I2C_DIR, IOSPACE); release_region(I2C_DIR, IOSPACE);
pm_io_base = 0; pm_io_base = 0;
} }
......
...@@ -211,14 +211,14 @@ static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_ ...@@ -211,14 +211,14 @@ static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_
return retval; return retval;
retval = i2c_bit_add_bus(&voodoo3_ddc_adapter); retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
if (retval) if (retval)
i2c_bit_del_bus(&voodoo3_i2c_adapter); i2c_del_adapter(&voodoo3_i2c_adapter);
return retval; return retval;
} }
static void __devexit voodoo3_remove(struct pci_dev *dev) static void __devexit voodoo3_remove(struct pci_dev *dev)
{ {
i2c_bit_del_bus(&voodoo3_i2c_adapter); i2c_del_adapter(&voodoo3_i2c_adapter);
i2c_bit_del_bus(&voodoo3_ddc_adapter); i2c_del_adapter(&voodoo3_ddc_adapter);
iounmap(ioaddr); iounmap(ioaddr);
} }
......
...@@ -116,7 +116,7 @@ static int scx200_i2c_init(void) ...@@ -116,7 +116,7 @@ static int scx200_i2c_init(void)
static void scx200_i2c_cleanup(void) static void scx200_i2c_cleanup(void)
{ {
i2c_bit_del_bus(&scx200_i2c_ops); i2c_del_adapter(&scx200_i2c_ops);
} }
module_init(scx200_i2c_init); module_init(scx200_i2c_init);
......
...@@ -347,13 +347,19 @@ static void ds1337_init_client(struct i2c_client *client) ...@@ -347,13 +347,19 @@ static void ds1337_init_client(struct i2c_client *client)
if ((status & 0x80) || (control & 0x80)) { if ((status & 0x80) || (control & 0x80)) {
/* RTC not running */ /* RTC not running */
u8 buf[16]; u8 buf[1+16]; /* First byte is interpreted as address */
struct i2c_msg msg[1]; struct i2c_msg msg[1];
dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__); dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
/* Initialize all, including STATUS and CONTROL to zero */ /* Initialize all, including STATUS and CONTROL to zero */
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
/* Write valid values in the date/time registers */
buf[1+DS1337_REG_DAY] = 1;
buf[1+DS1337_REG_DATE] = 1;
buf[1+DS1337_REG_MONTH] = 1;
msg[0].addr = client->addr; msg[0].addr = client->addr;
msg[0].flags = 0; msg[0].flags = 0;
msg[0].len = sizeof(buf); msg[0].len = sizeof(buf);
......
...@@ -128,14 +128,11 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att ...@@ -128,14 +128,11 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att
} }
/* /*
* We can't use the DEVICE_ATTR() macro here as we want the same filename for a * We can't use the DEVICE_ATTR() macro here, as we used the same name for
* different type of a device. So beware if the DEVICE_ATTR() macro ever * an i2c adapter attribute (above).
* changes, this definition will also have to change.
*/ */
static struct device_attribute dev_attr_client_name = { static struct device_attribute dev_attr_client_name =
.attr = {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE }, __ATTR(name, S_IRUGO, &show_client_name, NULL);
.show = &show_client_name,
};
/* --------------------------------------------------- /* ---------------------------------------------------
...@@ -603,7 +600,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) ...@@ -603,7 +600,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
} }
#endif #endif
mutex_lock(&adap->bus_lock); mutex_lock_nested(&adap->bus_lock, adap->level);
ret = adap->algo->master_xfer(adap,msgs,num); ret = adap->algo->master_xfer(adap,msgs,num);
mutex_unlock(&adap->bus_lock); mutex_unlock(&adap->bus_lock);
......
...@@ -90,6 +90,7 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) ...@@ -90,6 +90,7 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_lock(&i2c_dev_list_lock); spin_lock(&i2c_dev_list_lock);
list_del(&i2c_dev->list); list_del(&i2c_dev->list);
spin_unlock(&i2c_dev_list_lock); spin_unlock(&i2c_dev_list_lock);
kfree(i2c_dev);
} }
static ssize_t show_adapter_name(struct device *dev, static ssize_t show_adapter_name(struct device *dev,
...@@ -193,8 +194,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, ...@@ -193,8 +194,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
return 0; return 0;
case I2C_FUNCS: case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter); funcs = i2c_get_functionality(client->adapter);
return (copy_to_user((unsigned long __user *)arg, &funcs, return put_user(funcs, (unsigned long __user *)arg);
sizeof(unsigned long)))?-EFAULT:0;
case I2C_RDWR: case I2C_RDWR:
if (copy_from_user(&rdwr_arg, if (copy_from_user(&rdwr_arg,
...@@ -417,8 +417,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) ...@@ -417,8 +417,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
MKDEV(I2C_MAJOR, adap->nr), MKDEV(I2C_MAJOR, adap->nr),
"i2c-%d", adap->nr); "i2c-%d", adap->nr);
if (!i2c_dev->dev) { if (IS_ERR(i2c_dev->dev)) {
res = -ENODEV; res = PTR_ERR(i2c_dev->dev);
goto error; goto error;
} }
res = device_create_file(i2c_dev->dev, &dev_attr_name); res = device_create_file(i2c_dev->dev, &dev_attr_name);
...@@ -432,7 +432,6 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) ...@@ -432,7 +432,6 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error: error:
return_i2c_dev(i2c_dev); return_i2c_dev(i2c_dev);
kfree(i2c_dev);
return res; return res;
} }
...@@ -447,7 +446,6 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) ...@@ -447,7 +446,6 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
device_remove_file(i2c_dev->dev, &dev_attr_name); device_remove_file(i2c_dev->dev, &dev_attr_name);
return_i2c_dev(i2c_dev); return_i2c_dev(i2c_dev);
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
return 0; return 0;
......
...@@ -1485,7 +1485,7 @@ static int __devinit add_card(struct pci_dev *dev, ...@@ -1485,7 +1485,7 @@ static int __devinit add_card(struct pci_dev *dev,
} }
i2c_bit_del_bus(i2c_ad); i2c_del_adapter(i2c_ad);
kfree(i2c_ad); kfree(i2c_ad);
} }
} }
......
...@@ -650,7 +650,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, ...@@ -650,7 +650,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
/* dvb */ /* dvb */
ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev); ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
if (ret < 0) if (ret < 0)
goto err_i2c_bit_del_bus; goto err_i2c_del_adapter;
dvb_adapter = &pluto->dvb_adapter; dvb_adapter = &pluto->dvb_adapter;
...@@ -712,8 +712,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, ...@@ -712,8 +712,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
dvb_dmx_release(dvbdemux); dvb_dmx_release(dvbdemux);
err_dvb_unregister_adapter: err_dvb_unregister_adapter:
dvb_unregister_adapter(dvb_adapter); dvb_unregister_adapter(dvb_adapter);
err_i2c_bit_del_bus: err_i2c_del_adapter:
i2c_bit_del_bus(&pluto->i2c_adap); i2c_del_adapter(&pluto->i2c_adap);
err_pluto_hw_exit: err_pluto_hw_exit:
pluto_hw_exit(pluto); pluto_hw_exit(pluto);
err_free_irq: err_free_irq:
...@@ -748,7 +748,7 @@ static void __devexit pluto2_remove(struct pci_dev *pdev) ...@@ -748,7 +748,7 @@ static void __devexit pluto2_remove(struct pci_dev *pdev)
dvb_dmxdev_release(&pluto->dmxdev); dvb_dmxdev_release(&pluto->dmxdev);
dvb_dmx_release(dvbdemux); dvb_dmx_release(dvbdemux);
dvb_unregister_adapter(dvb_adapter); dvb_unregister_adapter(dvb_adapter);
i2c_bit_del_bus(&pluto->i2c_adap); i2c_del_adapter(&pluto->i2c_adap);
pluto_hw_exit(pluto); pluto_hw_exit(pluto);
free_irq(pdev->irq, pluto); free_irq(pdev->irq, pluto);
pci_iounmap(pdev, pluto->io_mem); pci_iounmap(pdev, pluto->io_mem);
......
...@@ -479,11 +479,7 @@ int __devexit fini_bttv_i2c(struct bttv *btv) ...@@ -479,11 +479,7 @@ int __devexit fini_bttv_i2c(struct bttv *btv)
if (0 != btv->i2c_rc) if (0 != btv->i2c_rc)
return 0; return 0;
if (btv->use_i2c_hw) {
return i2c_del_adapter(&btv->c.i2c_adap); return i2c_del_adapter(&btv->c.i2c_adap);
} else {
return i2c_bit_del_bus(&btv->c.i2c_adap);
}
} }
/* /*
......
...@@ -1153,7 +1153,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) ...@@ -1153,7 +1153,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
mutex_lock(&devlist); mutex_lock(&devlist);
cx88_ir_fini(core); cx88_ir_fini(core);
if (0 == core->i2c_rc) if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap); i2c_del_adapter(&core->i2c_adap);
list_del(&core->devlist); list_del(&core->devlist);
iounmap(core->lmmio); iounmap(core->lmmio);
cx88_devcount--; cx88_devcount--;
......
...@@ -168,7 +168,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev) ...@@ -168,7 +168,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev)
dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
return; return;
i2c_bit_del_bus(&vp3054_i2c->adap); i2c_del_adapter(&vp3054_i2c->adap);
kfree(vp3054_i2c); kfree(vp3054_i2c);
} }
......
...@@ -782,7 +782,7 @@ static int vino_i2c_add_bus(void) ...@@ -782,7 +782,7 @@ static int vino_i2c_add_bus(void)
static int vino_i2c_del_bus(void) static int vino_i2c_del_bus(void)
{ {
return i2c_sgi_del_bus(&vino_i2c_adapter); return i2c_del_adapter(&vino_i2c_adapter);
} }
static int i2c_camera_command(unsigned int cmd, void *arg) static int i2c_camera_command(unsigned int cmd, void *arg)
......
...@@ -849,7 +849,7 @@ zoran_register_i2c (struct zoran *zr) ...@@ -849,7 +849,7 @@ zoran_register_i2c (struct zoran *zr)
static void static void
zoran_unregister_i2c (struct zoran *zr) zoran_unregister_i2c (struct zoran *zr)
{ {
i2c_bit_del_bus((&zr->i2c_adapter)); i2c_del_adapter(&zr->i2c_adapter);
} }
/* Check a zoran_params struct for correctness, insert default params */ /* Check a zoran_params struct for correctness, insert default params */
......
...@@ -120,19 +120,19 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo) ...@@ -120,19 +120,19 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
void radeon_delete_i2c_busses(struct radeonfb_info *rinfo) void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
{ {
if (rinfo->i2c[0].rinfo) if (rinfo->i2c[0].rinfo)
i2c_bit_del_bus(&rinfo->i2c[0].adapter); i2c_del_adapter(&rinfo->i2c[0].adapter);
rinfo->i2c[0].rinfo = NULL; rinfo->i2c[0].rinfo = NULL;
if (rinfo->i2c[1].rinfo) if (rinfo->i2c[1].rinfo)
i2c_bit_del_bus(&rinfo->i2c[1].adapter); i2c_del_adapter(&rinfo->i2c[1].adapter);
rinfo->i2c[1].rinfo = NULL; rinfo->i2c[1].rinfo = NULL;
if (rinfo->i2c[2].rinfo) if (rinfo->i2c[2].rinfo)
i2c_bit_del_bus(&rinfo->i2c[2].adapter); i2c_del_adapter(&rinfo->i2c[2].adapter);
rinfo->i2c[2].rinfo = NULL; rinfo->i2c[2].rinfo = NULL;
if (rinfo->i2c[3].rinfo) if (rinfo->i2c[3].rinfo)
i2c_bit_del_bus(&rinfo->i2c[3].adapter); i2c_del_adapter(&rinfo->i2c[3].adapter);
rinfo->i2c[3].rinfo = NULL; rinfo->i2c[3].rinfo = NULL;
} }
......
...@@ -137,15 +137,15 @@ void i810_create_i2c_busses(struct i810fb_par *par) ...@@ -137,15 +137,15 @@ void i810_create_i2c_busses(struct i810fb_par *par)
void i810_delete_i2c_busses(struct i810fb_par *par) void i810_delete_i2c_busses(struct i810fb_par *par)
{ {
if (par->chan[0].par) if (par->chan[0].par)
i2c_bit_del_bus(&par->chan[0].adapter); i2c_del_adapter(&par->chan[0].adapter);
par->chan[0].par = NULL; par->chan[0].par = NULL;
if (par->chan[1].par) if (par->chan[1].par)
i2c_bit_del_bus(&par->chan[1].adapter); i2c_del_adapter(&par->chan[1].adapter);
par->chan[1].par = NULL; par->chan[1].par = NULL;
if (par->chan[2].par) if (par->chan[2].par)
i2c_bit_del_bus(&par->chan[2].adapter); i2c_del_adapter(&par->chan[2].adapter);
par->chan[2].par = NULL; par->chan[2].par = NULL;
} }
......
...@@ -188,11 +188,11 @@ void intelfb_delete_i2c_busses(struct intelfb_info *dinfo) ...@@ -188,11 +188,11 @@ void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
for (i = 0; i < MAX_OUTPUTS; i++) { for (i = 0; i < MAX_OUTPUTS; i++) {
if (dinfo->output[i].i2c_bus.dinfo) { if (dinfo->output[i].i2c_bus.dinfo) {
i2c_bit_del_bus(&dinfo->output[i].i2c_bus.adapter); i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
dinfo->output[i].i2c_bus.dinfo = NULL; dinfo->output[i].i2c_bus.dinfo = NULL;
} }
if (dinfo->output[i].ddc_bus.dinfo) { if (dinfo->output[i].ddc_bus.dinfo) {
i2c_bit_del_bus(&dinfo->output[i].ddc_bus.adapter); i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
dinfo->output[i].ddc_bus.dinfo = NULL; dinfo->output[i].ddc_bus.dinfo = NULL;
} }
} }
......
...@@ -124,7 +124,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, ...@@ -124,7 +124,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
static void i2c_bit_bus_del(struct i2c_bit_adapter* b) { static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
if (b->initialized) { if (b->initialized) {
i2c_bit_del_bus(&b->adapter); i2c_del_adapter(&b->adapter);
b->initialized = 0; b->initialized = 0;
} }
} }
......
...@@ -147,15 +147,15 @@ void nvidia_create_i2c_busses(struct nvidia_par *par) ...@@ -147,15 +147,15 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
void nvidia_delete_i2c_busses(struct nvidia_par *par) void nvidia_delete_i2c_busses(struct nvidia_par *par)
{ {
if (par->chan[0].par) if (par->chan[0].par)
i2c_bit_del_bus(&par->chan[0].adapter); i2c_del_adapter(&par->chan[0].adapter);
par->chan[0].par = NULL; par->chan[0].par = NULL;
if (par->chan[1].par) if (par->chan[1].par)
i2c_bit_del_bus(&par->chan[1].adapter); i2c_del_adapter(&par->chan[1].adapter);
par->chan[1].par = NULL; par->chan[1].par = NULL;
if (par->chan[2].par) if (par->chan[2].par)
i2c_bit_del_bus(&par->chan[2].adapter); i2c_del_adapter(&par->chan[2].adapter);
par->chan[2].par = NULL; par->chan[2].par = NULL;
} }
......
...@@ -144,15 +144,15 @@ void riva_create_i2c_busses(struct riva_par *par) ...@@ -144,15 +144,15 @@ void riva_create_i2c_busses(struct riva_par *par)
void riva_delete_i2c_busses(struct riva_par *par) void riva_delete_i2c_busses(struct riva_par *par)
{ {
if (par->chan[0].par) if (par->chan[0].par)
i2c_bit_del_bus(&par->chan[0].adapter); i2c_del_adapter(&par->chan[0].adapter);
par->chan[0].par = NULL; par->chan[0].par = NULL;
if (par->chan[1].par) if (par->chan[1].par)
i2c_bit_del_bus(&par->chan[1].adapter); i2c_del_adapter(&par->chan[1].adapter);
par->chan[1].par = NULL; par->chan[1].par = NULL;
if (par->chan[2].par) if (par->chan[2].par)
i2c_bit_del_bus(&par->chan[2].adapter); i2c_del_adapter(&par->chan[2].adapter);
par->chan[2].par = NULL; par->chan[2].par = NULL;
} }
......
...@@ -208,7 +208,7 @@ void savagefb_delete_i2c_busses(struct fb_info *info) ...@@ -208,7 +208,7 @@ void savagefb_delete_i2c_busses(struct fb_info *info)
struct savagefb_par *par = info->par; struct savagefb_par *par = info->par;
if (par->chan.par) if (par->chan.par)
i2c_bit_del_bus(&par->chan.adapter); i2c_del_adapter(&par->chan.adapter);
par->chan.par = NULL; par->chan.par = NULL;
} }
......
/*
* PNX4008-specific tweaks for I2C IP3204 block
*
* Author: Vitaly Wool <vwool@ru.mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARCH_I2C_H__
#define __ASM_ARCH_I2C_H__
#include <linux/pm.h>
#include <linux/platform_device.h>
enum {
mstatus_tdi = 0x00000001,
mstatus_afi = 0x00000002,
mstatus_nai = 0x00000004,
mstatus_drmi = 0x00000008,
mstatus_active = 0x00000020,
mstatus_scl = 0x00000040,
mstatus_sda = 0x00000080,
mstatus_rff = 0x00000100,
mstatus_rfe = 0x00000200,
mstatus_tff = 0x00000400,
mstatus_tfe = 0x00000800,
};
enum {
mcntrl_tdie = 0x00000001,
mcntrl_afie = 0x00000002,
mcntrl_naie = 0x00000004,
mcntrl_drmie = 0x00000008,
mcntrl_daie = 0x00000020,
mcntrl_rffie = 0x00000040,
mcntrl_tffie = 0x00000080,
mcntrl_reset = 0x00000100,
mcntrl_cdbmode = 0x00000400,
};
enum {
rw_bit = 1 << 0,
start_bit = 1 << 8,
stop_bit = 1 << 9,
};
#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
#define HCLK_MHZ 13
#define I2C_CHIP_NAME "PNX4008-I2C"
#endif /* __ASM_ARCH_I2C_H___ */
...@@ -44,6 +44,5 @@ struct i2c_algo_bit_data { ...@@ -44,6 +44,5 @@ struct i2c_algo_bit_data {
}; };
int i2c_bit_add_bus(struct i2c_adapter *); int i2c_bit_add_bus(struct i2c_adapter *);
int i2c_bit_del_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_BIT_H */ #endif /* _LINUX_I2C_ALGO_BIT_H */
/* ------------------------------------------------------------------------- */
/* i2c-algo-ite.h i2c driver algorithms for ITE IIC adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-97 Simon G. Vogl
1998-99 Hans Berglund
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
/* Modifications by MontaVista Software, 2001
Changes made to support the ITE IIC peripheral */
#ifndef I2C_ALGO_ITE_H
#define I2C_ALGO_ITE_H 1
#include <linux/types.h>
/* Example of a sequential read request:
struct i2c_iic_msg s_msg;
s_msg.addr=device_address;
s_msg.len=length;
s_msg.buf=buffer;
s_msg.waddr=word_address;
ioctl(file,I2C_SREAD, &s_msg);
*/
#define I2C_SREAD 0x780 /* SREAD ioctl command */
struct i2c_iic_msg {
__u16 addr; /* device address */
__u16 waddr; /* word address */
short len; /* msg length */
char *buf; /* pointer to msg data */
};
#ifdef __KERNEL__
struct i2c_adapter;
struct i2c_algo_iic_data {
void *data; /* private data for lolevel routines */
void (*setiic) (void *data, int ctl, int val);
int (*getiic) (void *data, int ctl);
int (*getown) (void *data);
int (*getclock) (void *data);
void (*waitforpin) (void);
/* local settings */
int udelay;
int mdelay;
int timeout;
};
int i2c_iic_add_bus(struct i2c_adapter *);
int i2c_iic_del_bus(struct i2c_adapter *);
#endif /* __KERNEL__ */
#endif /* I2C_ALGO_ITE_H */
...@@ -10,6 +10,5 @@ struct i2c_algo_pca_data { ...@@ -10,6 +10,5 @@ struct i2c_algo_pca_data {
}; };
int i2c_pca_add_bus(struct i2c_adapter *); int i2c_pca_add_bus(struct i2c_adapter *);
int i2c_pca_del_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_PCA_H */ #endif /* _LINUX_I2C_ALGO_PCA_H */
...@@ -39,6 +39,5 @@ struct i2c_algo_pcf_data { ...@@ -39,6 +39,5 @@ struct i2c_algo_pcf_data {
}; };
int i2c_pcf_add_bus(struct i2c_adapter *); int i2c_pcf_add_bus(struct i2c_adapter *);
int i2c_pcf_del_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_PCF_H */ #endif /* _LINUX_I2C_ALGO_PCF_H */
...@@ -22,6 +22,5 @@ struct i2c_algo_sgi_data { ...@@ -22,6 +22,5 @@ struct i2c_algo_sgi_data {
}; };
int i2c_sgi_add_bus(struct i2c_adapter *); int i2c_sgi_add_bus(struct i2c_adapter *);
int i2c_sgi_del_bus(struct i2c_adapter *);
#endif /* I2C_ALGO_SGI_H */ #endif /* I2C_ALGO_SGI_H */
...@@ -82,9 +82,8 @@ ...@@ -82,9 +82,8 @@
#define I2C_DRIVERID_STM41T00 52 /* real time clock */ #define I2C_DRIVERID_STM41T00 52 /* real time clock */
#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */ #define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */
#define I2C_DRIVERID_ADV7170 54 /* video encoder */ #define I2C_DRIVERID_ADV7170 54 /* video encoder */
#define I2C_DRIVERID_RADEON 55 /* I2C bus on Radeon boards */
#define I2C_DRIVERID_MAX1617 56 /* temp sensor */ #define I2C_DRIVERID_MAX1617 56 /* temp sensor */
#define I2C_DRIVERID_SAA7191 57 /* video encoder */ #define I2C_DRIVERID_SAA7191 57 /* video decoder */
#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
#define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */ #define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */
#define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */ #define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */
...@@ -132,7 +131,6 @@ ...@@ -132,7 +131,6 @@
#define I2C_DRIVERID_ADM1021 1008 #define I2C_DRIVERID_ADM1021 1008
#define I2C_DRIVERID_ADM9240 1009 #define I2C_DRIVERID_ADM9240 1009
#define I2C_DRIVERID_LTC1710 1010 #define I2C_DRIVERID_LTC1710 1010
#define I2C_DRIVERID_ICSPLL 1012
#define I2C_DRIVERID_BT869 1013 #define I2C_DRIVERID_BT869 1013
#define I2C_DRIVERID_MAXILIFE 1014 #define I2C_DRIVERID_MAXILIFE 1014
#define I2C_DRIVERID_MATORB 1015 #define I2C_DRIVERID_MATORB 1015
...@@ -213,9 +211,6 @@ ...@@ -213,9 +211,6 @@
/* --- MPC8xx PowerPC adapters */ /* --- MPC8xx PowerPC adapters */
#define I2C_HW_MPC8XX_EPON 0x110000 /* Eponymous MPC8xx I2C adapter */ #define I2C_HW_MPC8XX_EPON 0x110000 /* Eponymous MPC8xx I2C adapter */
/* --- ITE based algorithms */
#define I2C_HW_I_IIC 0x080000 /* controller on the ITE */
/* --- PowerPC on-chip adapters */ /* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */ #define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
......
/*
* Header file for I2C support on PNX010x/4008.
*
* Author: Dennis Kovalev <dkovalev@ru.mvista.com>
*
* 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __I2C_PNX_H__
#define __I2C_PNX_H__
#include <asm/arch/i2c.h>
struct i2c_pnx_mif {
int ret; /* Return value */
int mode; /* Interface mode */
struct completion complete; /* I/O completion */
struct timer_list timer; /* Timeout */
char * buf; /* Data buffer */
int len; /* Length of data buffer */
};
struct i2c_pnx_algo_data {
u32 base;
u32 ioaddr;
int irq;
struct i2c_pnx_mif mif;
int last;
};
struct i2c_pnx_data {
int (*suspend) (struct platform_device *pdev, pm_message_t state);
int (*resume) (struct platform_device *pdev);
u32 (*calculate_input_freq) (struct platform_device *pdev);
int (*set_clock_run) (struct platform_device *pdev);
int (*set_clock_stop) (struct platform_device *pdev);
struct i2c_adapter *adapter;
};
#endif /* __I2C_PNX_H__ */
...@@ -216,6 +216,7 @@ struct i2c_adapter { ...@@ -216,6 +216,7 @@ struct i2c_adapter {
int (*client_unregister)(struct i2c_client *); int (*client_unregister)(struct i2c_client *);
/* data fields that are valid for all devices */ /* data fields that are valid for all devices */
u8 level; /* nesting level for lockdep */
struct mutex bus_lock; struct mutex bus_lock;
struct mutex clist_lock; struct mutex clist_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment