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
This commit is contained in:
commit
659dba3480
|
@ -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
|
||||
When: January 2007
|
||||
Why: The deferred output hooks are a layering violation causing unusual
|
||||
|
|
|
@ -5,7 +5,7 @@ Supported adapters:
|
|||
|
||||
Datasheets:
|
||||
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.
|
||||
|
||||
Author: Vojtech Pavlik <vojtech@suse.cz>
|
||||
|
|
|
@ -9,7 +9,10 @@ Supported adapters:
|
|||
* Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
|
||||
* Intel 6300ESB
|
||||
* 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
|
||||
|
||||
Authors:
|
||||
|
|
|
@ -10,11 +10,11 @@ Supported adapters:
|
|||
* nForce4 MCP51 10de:0264
|
||||
* 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.
|
||||
|
||||
Authors:
|
||||
Hans-Frieder Vogt <hfvogt@arcor.de>,
|
||||
Hans-Frieder Vogt <hfvogt@gmx.net>,
|
||||
Thomas Leibold <thomas@plx.com>,
|
||||
Patrick Dreker <patrick@dreker.de>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# 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-n :=
|
||||
obj- :=
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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 = {
|
|||
.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)
|
||||
|
||||
static unsigned int realview_mmc_status(struct device *dev)
|
||||
|
|
|
@ -108,6 +108,7 @@ static struct amba_device name##_device = { \
|
|||
|
||||
extern struct platform_device realview_flash_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_mmc1_plat_data;
|
||||
extern struct clk realview_clcd_clk;
|
||||
|
|
|
@ -155,6 +155,7 @@ static void __init realview_eb_init(void)
|
|||
|
||||
platform_device_register(&realview_flash_device);
|
||||
platform_device_register(&realview_smc91x_device);
|
||||
platform_device_register(&realview_i2c_device);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
struct amba_device *d = amba_devs[i];
|
||||
|
|
|
@ -325,6 +325,19 @@ static struct platform_device smc91x_device = {
|
|||
.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)
|
||||
|
||||
unsigned int mmc_status(struct device *dev)
|
||||
|
@ -775,6 +788,7 @@ void __init versatile_init(void)
|
|||
clk_register(&versatile_clcd_clk);
|
||||
|
||||
platform_device_register(&versatile_flash_device);
|
||||
platform_device_register(&versatile_i2c_device);
|
||||
platform_device_register(&smc91x_device);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
|
|
|
@ -360,7 +360,7 @@ static int __init i2c_ioc_init(void)
|
|||
if (ret >= 0){
|
||||
ret = misc_register(&rtc_dev);
|
||||
if(ret < 0)
|
||||
i2c_bit_del_bus(&ioc_ops);
|
||||
i2c_del_adapter(&ioc_ops);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -38,17 +38,6 @@ config I2C_ALGOPCA
|
|||
This support is also available as a module. If so, the module
|
||||
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
|
||||
tristate "MPC8xx CPM I2C interface"
|
||||
depends on 8xx && I2C
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
|
||||
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.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
|
||||
|
||||
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
|
||||
|
|
|
@ -540,15 +540,7 @@ int i2c_bit_add_bus(struct i2c_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_del_bus);
|
||||
|
||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
|
||||
|
|
|
@ -1,806 +0,0 @@
|
|||
/*
|
||||
-------------------------------------------------------------------------
|
||||
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 Kyösti Mälkki <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);
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
--------------------------------------------------------------------
|
||||
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)
|
|||
|
||||
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_del_bus);
|
||||
|
||||
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
|
||||
MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
|
||||
|
|
|
@ -486,15 +486,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
|
|||
|
||||
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_del_bus);
|
||||
|
||||
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
|
||||
MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
|
||||
|
|
|
@ -171,15 +171,7 @@ int i2c_sgi_add_bus(struct i2c_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_del_bus);
|
||||
|
||||
MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
|
||||
MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
|
||||
|
|
|
@ -74,6 +74,13 @@ config I2C_AMD8111
|
|||
This driver can also be built as a module. If so, the module
|
||||
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
|
||||
tristate "Au1550/Au1200 SMBus interface"
|
||||
depends on I2C && (SOC_AU1550 || SOC_AU1200)
|
||||
|
@ -209,18 +216,6 @@ config I2C_ISA
|
|||
tristate
|
||||
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
|
||||
tristate "IXP4xx GPIO-Based I2C Interface"
|
||||
depends on I2C && ARCH_IXP4XX
|
||||
|
@ -481,6 +476,17 @@ config I2C_STUB
|
|||
|
||||
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
|
||||
tristate "VIA 82C586B"
|
||||
depends on I2C && PCI && EXPERIMENTAL
|
||||
|
@ -548,4 +554,23 @@ config I2C_MV64XXX
|
|||
This driver can also be built as a module. If so, the module
|
||||
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
|
||||
|
|
|
@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
|
|||
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
|
||||
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
|
||||
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
|
||||
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
|
||||
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
|
||||
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
|
||||
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
|
||||
|
@ -16,7 +17,6 @@ obj-$(CONFIG_I2C_I810) += i2c-i810.o
|
|||
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
|
||||
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.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_IXP4XX) += i2c-ixp4xx.o
|
||||
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
|
||||
|
@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
|
|||
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
|
||||
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.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_PXA) += i2c-pxa.o
|
||||
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
|
||||
|
@ -39,6 +40,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
|
|||
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
|
||||
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.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_VIAPRO) += i2c-viapro.o
|
||||
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
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)
|
|||
|
||||
static void i2c_pcfisa_exit(void)
|
||||
{
|
||||
i2c_pcf_del_bus(&pcf_isa_ops);
|
||||
i2c_del_adapter(&pcf_isa_ops);
|
||||
|
||||
if (irq > 0) {
|
||||
disable_irq(irq);
|
||||
|
|
|
@ -146,7 +146,7 @@ static int __devinit hydra_probe(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 */
|
||||
i2c_bit_del_bus(&hydra_adap);
|
||||
i2c_del_adapter(&hydra_adap);
|
||||
iounmap(hydra_bit_data.data);
|
||||
release_mem_region(pci_resource_start(dev, 0)+
|
||||
offsetof(struct Hydra, CachePD), 4);
|
||||
|
|
|
@ -470,12 +470,20 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
|
|||
int err;
|
||||
|
||||
I801_dev = dev;
|
||||
if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
|
||||
(dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
|
||||
(dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
|
||||
switch (dev->device) {
|
||||
case PCI_DEVICE_ID_INTEL_82801DB_3:
|
||||
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;
|
||||
else
|
||||
break;
|
||||
default:
|
||||
isich4 = 0;
|
||||
}
|
||||
|
||||
err = pci_enable_device(dev);
|
||||
if (err) {
|
||||
|
|
|
@ -219,14 +219,14 @@ static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id
|
|||
return retval;
|
||||
retval = i2c_bit_add_bus(&i810_ddc_adapter);
|
||||
if (retval)
|
||||
i2c_bit_del_bus(&i810_i2c_adapter);
|
||||
i2c_del_adapter(&i810_i2c_adapter);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit i810_remove(struct pci_dev *dev)
|
||||
{
|
||||
i2c_bit_del_bus(&i810_ddc_adapter);
|
||||
i2c_bit_del_bus(&i810_i2c_adapter);
|
||||
i2c_del_adapter(&i810_ddc_adapter);
|
||||
i2c_del_adapter(&i810_i2c_adapter);
|
||||
iounmap(ioaddr);
|
||||
}
|
||||
|
||||
|
|
|
@ -680,6 +680,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){
|
|||
dev->idx = ocp->def->index;
|
||||
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)))){
|
||||
printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
|
||||
dev->idx);
|
||||
|
@ -750,6 +756,8 @@ fail:
|
|||
|
||||
iounmap(dev->vaddr);
|
||||
fail2:
|
||||
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
|
||||
fail1:
|
||||
ocp_set_drvdata(ocp, NULL);
|
||||
kfree(dev);
|
||||
return ret;
|
||||
|
@ -777,6 +785,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
|
|||
free_irq(dev->irq, dev);
|
||||
}
|
||||
iounmap(dev->vaddr);
|
||||
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
|
||||
kfree(dev);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,278 +0,0 @@
|
|||
/*
|
||||
-------------------------------------------------------------------------
|
||||
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 Kyösti Mälkki <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)
|
|||
|
||||
platform_set_drvdata(plat_dev, NULL);
|
||||
|
||||
i2c_bit_del_bus(&drv_data->adapter);
|
||||
i2c_del_adapter(&drv_data->adapter);
|
||||
|
||||
kfree(drv_data);
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ static int ixp4xx_i2c_remove(struct platform_device *plat_dev)
|
|||
|
||||
platform_set_drvdata(plat_dev, NULL);
|
||||
|
||||
i2c_bit_del_bus(&drv_data->adapter);
|
||||
i2c_del_adapter(&drv_data->adapter);
|
||||
|
||||
kfree(drv_data);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
nForce4 MCP55 0368
|
||||
|
||||
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 */
|
||||
|
@ -52,8 +52,8 @@
|
|||
#include <asm/io.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>");
|
||||
MODULE_DESCRIPTION("nForce2 SMBus driver");
|
||||
MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@gmx.net>");
|
||||
MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");
|
||||
|
||||
|
||||
struct nforce2_smbus {
|
||||
|
@ -80,9 +80,6 @@ struct nforce2_smbus {
|
|||
#define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */
|
||||
#define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */
|
||||
#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_ALRM 0x40
|
||||
|
@ -95,40 +92,17 @@ struct nforce2_smbus {
|
|||
#define NVIDIA_SMB_PRTCL_BYTE 0x04
|
||||
#define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06
|
||||
#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
|
||||
|
||||
static struct pci_driver nforce2_driver;
|
||||
|
||||
static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
|
||||
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 */
|
||||
/* Return -1 on error */
|
||||
static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
{
|
||||
struct nforce2_smbus *smbus = adap->algo_data;
|
||||
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 :
|
||||
NVIDIA_SMB_PRTCL_WRITE;
|
||||
|
@ -163,35 +137,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
|||
protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
|
||||
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:
|
||||
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
|
||||
return -1;
|
||||
|
@ -227,19 +172,8 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
|||
break;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
@ -250,10 +184,14 @@ static u32 nforce2_func(struct i2c_adapter *adapter)
|
|||
{
|
||||
/* other functionality might be possible, but is not tested */
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA */;
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.smbus_xfer = nforce2_access,
|
||||
.functionality = nforce2_func,
|
||||
};
|
||||
|
||||
|
||||
static struct pci_device_id nforce2_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
|
||||
|
@ -267,7 +205,6 @@ static struct pci_device_id nforce2_ids[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE (pci, nforce2_ids);
|
||||
|
||||
|
||||
|
@ -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->size = 8;
|
||||
smbus->size = 64;
|
||||
}
|
||||
smbus->dev = dev;
|
||||
|
||||
|
@ -300,7 +237,9 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
|
|||
smbus->base, smbus->base+smbus->size-1, name);
|
||||
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.dev.parent = &dev->dev;
|
||||
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
|
||||
|
|
|
@ -231,8 +231,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
|
|||
* 13 2 1
|
||||
* 19.2 2 1
|
||||
*/
|
||||
if (fclk_rate > 16000000)
|
||||
psc = (fclk_rate + 8000000) / 12000000;
|
||||
if (fclk_rate > 12000000)
|
||||
psc = fclk_rate / 12000000;
|
||||
}
|
||||
|
||||
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
|
||||
|
|
|
@ -163,7 +163,7 @@ static void __exit i2c_parport_exit(void)
|
|||
if (adapter_parm[type].init.val)
|
||||
line_set(0, &adapter_parm[type].init);
|
||||
|
||||
i2c_bit_del_bus(&parport_adapter);
|
||||
i2c_del_adapter(&parport_adapter);
|
||||
release_region(base, 3);
|
||||
}
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ static void i2c_parport_detach (struct parport *port)
|
|||
if (adapter_parm[type].init.val)
|
||||
line_set(port, 0, &adapter_parm[type].init);
|
||||
|
||||
i2c_bit_del_bus(&adapter->adapter);
|
||||
i2c_del_adapter(&adapter->adapter);
|
||||
parport_unregister_device(adapter->pdev);
|
||||
if (prev)
|
||||
prev->next = adapter->next;
|
||||
|
|
|
@ -156,7 +156,7 @@ static int __init pca_isa_init(void)
|
|||
|
||||
static void pca_isa_exit(void)
|
||||
{
|
||||
i2c_pca_del_bus(&pca_isa_ops);
|
||||
i2c_del_adapter(&pca_isa_ops);
|
||||
|
||||
if (irq > 0) {
|
||||
disable_irq(irq);
|
||||
|
|
|
@ -0,0 +1,708 @@
|
|||
/*
|
||||
* 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)
|
|||
if (chip->i2c_bus[i].adap_ok == 0)
|
||||
continue;
|
||||
|
||||
ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
|
||||
ret = i2c_del_adapter(&chip->i2c_bus[i].adap);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "%s not removed\n",
|
||||
chip->i2c_bus[i].adap.name);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
i2c_bit_del_bus(&savage4_i2c_adapter);
|
||||
i2c_del_adapter(&savage4_i2c_adapter);
|
||||
iounmap(ioaddr);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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
|
|||
|
||||
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);
|
||||
pm_io_base = 0;
|
||||
}
|
||||
|
|
|
@ -211,14 +211,14 @@ static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_
|
|||
return retval;
|
||||
retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
|
||||
if (retval)
|
||||
i2c_bit_del_bus(&voodoo3_i2c_adapter);
|
||||
i2c_del_adapter(&voodoo3_i2c_adapter);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit voodoo3_remove(struct pci_dev *dev)
|
||||
{
|
||||
i2c_bit_del_bus(&voodoo3_i2c_adapter);
|
||||
i2c_bit_del_bus(&voodoo3_ddc_adapter);
|
||||
i2c_del_adapter(&voodoo3_i2c_adapter);
|
||||
i2c_del_adapter(&voodoo3_ddc_adapter);
|
||||
iounmap(ioaddr);
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ static int scx200_i2c_init(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);
|
||||
|
|
|
@ -347,13 +347,19 @@ static void ds1337_init_client(struct i2c_client *client)
|
|||
|
||||
if ((status & 0x80) || (control & 0x80)) {
|
||||
/* RTC not running */
|
||||
u8 buf[16];
|
||||
u8 buf[1+16]; /* First byte is interpreted as address */
|
||||
struct i2c_msg msg[1];
|
||||
|
||||
dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
|
||||
|
||||
/* Initialize all, including STATUS and CONTROL to zero */
|
||||
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].flags = 0;
|
||||
msg[0].len = sizeof(buf);
|
||||
|
|
|
@ -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
|
||||
* different type of a device. So beware if the DEVICE_ATTR() macro ever
|
||||
* changes, this definition will also have to change.
|
||||
* We can't use the DEVICE_ATTR() macro here, as we used the same name for
|
||||
* an i2c adapter attribute (above).
|
||||
*/
|
||||
static struct device_attribute dev_attr_client_name = {
|
||||
.attr = {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE },
|
||||
.show = &show_client_name,
|
||||
};
|
||||
static struct device_attribute dev_attr_client_name =
|
||||
__ATTR(name, S_IRUGO, &show_client_name, NULL);
|
||||
|
||||
|
||||
/* ---------------------------------------------------
|
||||
|
@ -603,7 +600,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
|
|||
}
|
||||
#endif
|
||||
|
||||
mutex_lock(&adap->bus_lock);
|
||||
mutex_lock_nested(&adap->bus_lock, adap->level);
|
||||
ret = adap->algo->master_xfer(adap,msgs,num);
|
||||
mutex_unlock(&adap->bus_lock);
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
|
|||
spin_lock(&i2c_dev_list_lock);
|
||||
list_del(&i2c_dev->list);
|
||||
spin_unlock(&i2c_dev_list_lock);
|
||||
kfree(i2c_dev);
|
||||
}
|
||||
|
||||
static ssize_t show_adapter_name(struct device *dev,
|
||||
|
@ -193,8 +194,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
|
|||
return 0;
|
||||
case I2C_FUNCS:
|
||||
funcs = i2c_get_functionality(client->adapter);
|
||||
return (copy_to_user((unsigned long __user *)arg, &funcs,
|
||||
sizeof(unsigned long)))?-EFAULT:0;
|
||||
return put_user(funcs, (unsigned long __user *)arg);
|
||||
|
||||
case I2C_RDWR:
|
||||
if (copy_from_user(&rdwr_arg,
|
||||
|
@ -417,8 +417,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
|
|||
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
|
||||
MKDEV(I2C_MAJOR, adap->nr),
|
||||
"i2c-%d", adap->nr);
|
||||
if (!i2c_dev->dev) {
|
||||
res = -ENODEV;
|
||||
if (IS_ERR(i2c_dev->dev)) {
|
||||
res = PTR_ERR(i2c_dev->dev);
|
||||
goto error;
|
||||
}
|
||||
res = device_create_file(i2c_dev->dev, &dev_attr_name);
|
||||
|
@ -432,7 +432,6 @@ error_destroy:
|
|||
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
|
||||
error:
|
||||
return_i2c_dev(i2c_dev);
|
||||
kfree(i2c_dev);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -447,7 +446,6 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
|
|||
device_remove_file(i2c_dev->dev, &dev_attr_name);
|
||||
return_i2c_dev(i2c_dev);
|
||||
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
|
||||
kfree(i2c_dev);
|
||||
|
||||
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
|
||||
return 0;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -650,7 +650,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
|
|||
/* dvb */
|
||||
ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
|
||||
if (ret < 0)
|
||||
goto err_i2c_bit_del_bus;
|
||||
goto err_i2c_del_adapter;
|
||||
|
||||
dvb_adapter = &pluto->dvb_adapter;
|
||||
|
||||
|
@ -712,8 +712,8 @@ err_dvb_dmx_release:
|
|||
dvb_dmx_release(dvbdemux);
|
||||
err_dvb_unregister_adapter:
|
||||
dvb_unregister_adapter(dvb_adapter);
|
||||
err_i2c_bit_del_bus:
|
||||
i2c_bit_del_bus(&pluto->i2c_adap);
|
||||
err_i2c_del_adapter:
|
||||
i2c_del_adapter(&pluto->i2c_adap);
|
||||
err_pluto_hw_exit:
|
||||
pluto_hw_exit(pluto);
|
||||
err_free_irq:
|
||||
|
@ -748,7 +748,7 @@ static void __devexit pluto2_remove(struct pci_dev *pdev)
|
|||
dvb_dmxdev_release(&pluto->dmxdev);
|
||||
dvb_dmx_release(dvbdemux);
|
||||
dvb_unregister_adapter(dvb_adapter);
|
||||
i2c_bit_del_bus(&pluto->i2c_adap);
|
||||
i2c_del_adapter(&pluto->i2c_adap);
|
||||
pluto_hw_exit(pluto);
|
||||
free_irq(pdev->irq, pluto);
|
||||
pci_iounmap(pdev, pluto->io_mem);
|
||||
|
|
|
@ -479,11 +479,7 @@ int __devexit fini_bttv_i2c(struct bttv *btv)
|
|||
if (0 != btv->i2c_rc)
|
||||
return 0;
|
||||
|
||||
if (btv->use_i2c_hw) {
|
||||
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)
|
|||
mutex_lock(&devlist);
|
||||
cx88_ir_fini(core);
|
||||
if (0 == core->i2c_rc)
|
||||
i2c_bit_del_bus(&core->i2c_adap);
|
||||
i2c_del_adapter(&core->i2c_adap);
|
||||
list_del(&core->devlist);
|
||||
iounmap(core->lmmio);
|
||||
cx88_devcount--;
|
||||
|
|
|
@ -168,7 +168,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev)
|
|||
dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
|
||||
return;
|
||||
|
||||
i2c_bit_del_bus(&vp3054_i2c->adap);
|
||||
i2c_del_adapter(&vp3054_i2c->adap);
|
||||
kfree(vp3054_i2c);
|
||||
}
|
||||
|
||||
|
|
|
@ -782,7 +782,7 @@ static int vino_i2c_add_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)
|
||||
|
|
|
@ -849,7 +849,7 @@ zoran_register_i2c (struct zoran *zr)
|
|||
static void
|
||||
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 */
|
||||
|
|
|
@ -120,19 +120,19 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
|
|||
void radeon_delete_i2c_busses(struct radeonfb_info *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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,15 +137,15 @@ void i810_create_i2c_busses(struct i810fb_par *par)
|
|||
void i810_delete_i2c_busses(struct i810fb_par *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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -188,11 +188,11 @@ void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
|
|||
|
||||
for (i = 0; i < MAX_OUTPUTS; i++) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
if (b->initialized) {
|
||||
i2c_bit_del_bus(&b->adapter);
|
||||
i2c_del_adapter(&b->adapter);
|
||||
b->initialized = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,15 +147,15 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
|
|||
void nvidia_delete_i2c_busses(struct nvidia_par *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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
|
|
@ -144,15 +144,15 @@ void riva_create_i2c_busses(struct riva_par *par)
|
|||
void riva_delete_i2c_busses(struct riva_par *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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ void savagefb_delete_i2c_busses(struct fb_info *info)
|
|||
struct savagefb_par *par = info->par;
|
||||
|
||||
if (par->chan.par)
|
||||
i2c_bit_del_bus(&par->chan.adapter);
|
||||
i2c_del_adapter(&par->chan.adapter);
|
||||
|
||||
par->chan.par = NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 {
|
|||
};
|
||||
|
||||
int i2c_bit_add_bus(struct i2c_adapter *);
|
||||
int i2c_bit_del_bus(struct i2c_adapter *);
|
||||
|
||||
#endif /* _LINUX_I2C_ALGO_BIT_H */
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/* ------------------------------------------------------------------------- */
|
||||
/* 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 Kyösti Mälkki <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 {
|
|||
};
|
||||
|
||||
int i2c_pca_add_bus(struct i2c_adapter *);
|
||||
int i2c_pca_del_bus(struct i2c_adapter *);
|
||||
|
||||
#endif /* _LINUX_I2C_ALGO_PCA_H */
|
||||
|
|
|
@ -39,6 +39,5 @@ struct i2c_algo_pcf_data {
|
|||
};
|
||||
|
||||
int i2c_pcf_add_bus(struct i2c_adapter *);
|
||||
int i2c_pcf_del_bus(struct i2c_adapter *);
|
||||
|
||||
#endif /* _LINUX_I2C_ALGO_PCF_H */
|
||||
|
|
|
@ -22,6 +22,5 @@ struct i2c_algo_sgi_data {
|
|||
};
|
||||
|
||||
int i2c_sgi_add_bus(struct i2c_adapter *);
|
||||
int i2c_sgi_del_bus(struct i2c_adapter *);
|
||||
|
||||
#endif /* I2C_ALGO_SGI_H */
|
||||
|
|
|
@ -82,9 +82,8 @@
|
|||
#define I2C_DRIVERID_STM41T00 52 /* real time clock */
|
||||
#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */
|
||||
#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_SAA7191 57 /* video encoder */
|
||||
#define I2C_DRIVERID_SAA7191 57 /* video decoder */
|
||||
#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
|
||||
#define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */
|
||||
#define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */
|
||||
|
@ -132,7 +131,6 @@
|
|||
#define I2C_DRIVERID_ADM1021 1008
|
||||
#define I2C_DRIVERID_ADM9240 1009
|
||||
#define I2C_DRIVERID_LTC1710 1010
|
||||
#define I2C_DRIVERID_ICSPLL 1012
|
||||
#define I2C_DRIVERID_BT869 1013
|
||||
#define I2C_DRIVERID_MAXILIFE 1014
|
||||
#define I2C_DRIVERID_MATORB 1015
|
||||
|
@ -213,9 +211,6 @@
|
|||
/* --- MPC8xx PowerPC adapters */
|
||||
#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 */
|
||||
#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 {
|
|||
int (*client_unregister)(struct i2c_client *);
|
||||
|
||||
/* data fields that are valid for all devices */
|
||||
u8 level; /* nesting level for lockdep */
|
||||
struct mutex bus_lock;
|
||||
struct mutex clist_lock;
|
||||
|
||||
|
|
Loading…
Reference in New Issue