forked from Minki/linux
Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: "Highlights: - OF and ACPI helpers are now included in the core, and not in external files anymore. This removes dependency problems for modules and is cleaner, in general. - mv64xxx-driver gains fifo usage to support mv78230 - imx-driver overhaul to support VF610 - various cleanups, most notably related to devm_* and CONFIG_PM usage - driver bugfixes and smaller feature additions" * 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (51 commits) i2c: rcar: add rcar-H2 support i2c: sirf: retry 3 times as sometimes we get random noack and timeout i2c: sirf: support reverse direction of address i2c: sirf: fix the typo for setting bitrate to less than 100k i2c: sirf: we need to wait I2C_RESET status in resume i2c: sirf: reset i2c controller early after we get a noack i2c: designware: get SDA hold time, HCNT and LCNT configuration from ACPI i2c: designware: make HCNT/LCNT values configurable i2c: mpc: cleanup clock API use i2c: pnx: fix error return code in i2c_pnx_probe() i2c: ismt: add error return code in probe() i2c: mv64xxx: fix typo in binding documentation i2c: imx: use exact SoC revision to document binding i2c: move ACPI helpers into the core i2c: move OF helpers into the core i2c: mv64xxx: Fix timing issue on Armada XP (errata FE-8471889) i2c: mv64xxx: Add I2C Transaction Generator support i2c: powermac: fix return path on error Documentation: i2c: Fix example in instantiating-devices i2c: tiny-usb: do not use stack as URB transfer_buffer ...
This commit is contained in:
commit
00341b5301
@ -228,19 +228,9 @@ ACPI handle like:
|
||||
I2C serial bus support
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
The slaves behind I2C bus controller only need to add the ACPI IDs like
|
||||
with the platform and SPI drivers. However the I2C bus controller driver
|
||||
needs to call acpi_i2c_register_devices() after it has added the adapter.
|
||||
|
||||
An I2C bus (controller) driver does:
|
||||
|
||||
...
|
||||
ret = i2c_add_numbered_adapter(adapter);
|
||||
if (ret)
|
||||
/* handle error */
|
||||
|
||||
of_i2c_register_devices(adapter);
|
||||
/* Enumerate the slave devices behind this bus via ACPI */
|
||||
acpi_i2c_register_devices(adapter);
|
||||
with the platform and SPI drivers. The I2C core automatically enumerates
|
||||
any slave devices behind the controller device once the adapter is
|
||||
registered.
|
||||
|
||||
Below is an example of how to add ACPI support to the existing mpu3050
|
||||
input driver:
|
||||
|
@ -1,7 +1,10 @@
|
||||
* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<chip>-i2c"
|
||||
- compatible :
|
||||
- "fsl,imx1-i2c" for I2C compatible with the one integrated on i.MX1 SoC
|
||||
- "fsl,imx21-i2c" for I2C compatible with the one integrated on i.MX21 SoC
|
||||
- "fsl,vf610-i2c" for I2C compatible with the one integrated on Vybrid vf610 SoC
|
||||
- reg : Should contain I2C/HS-I2C registers location and length
|
||||
- interrupts : Should contain I2C/HS-I2C interrupt
|
||||
|
||||
|
@ -5,6 +5,7 @@ Required properties :
|
||||
|
||||
- reg : Offset and length of the register set for the device
|
||||
- compatible : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c"
|
||||
or "marvell,mv78230-i2c"
|
||||
- interrupts : The interrupt number
|
||||
|
||||
Optional properties :
|
||||
@ -20,3 +21,12 @@ Examples:
|
||||
interrupts = <29>;
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
For the Armada XP:
|
||||
|
||||
i2c@11000 {
|
||||
compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
|
||||
reg = <0x11000 0x100>;
|
||||
interrupts = <29>;
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
@ -73,9 +73,10 @@ this driver on those mainboards.
|
||||
The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are
|
||||
identical to the PIIX4 in I2C/SMBus support.
|
||||
|
||||
The AMD SB700 and SP5100 chipsets implement two PIIX4-compatible SMBus
|
||||
controllers. If your BIOS initializes the secondary controller, it will
|
||||
be detected by this driver as an "Auxiliary SMBus Host Controller".
|
||||
The AMD SB700, SB800, SP5100 and Hudson-2 chipsets implement two
|
||||
PIIX4-compatible SMBus controllers. If your BIOS initializes the
|
||||
secondary controller, it will be detected by this driver as
|
||||
an "Auxiliary SMBus Host Controller".
|
||||
|
||||
If you own Force CPCI735 motherboard or other OSB4 based systems you may need
|
||||
to change the SMBus Interrupt Select register so the SMBus controller uses
|
||||
|
@ -19,7 +19,7 @@ i2c_board_info which is registered by calling i2c_register_board_info().
|
||||
|
||||
Example (from omap2 h4):
|
||||
|
||||
static struct i2c_board_info __initdata h4_i2c_board_info[] = {
|
||||
static struct i2c_board_info h4_i2c_board_info[] __initdata = {
|
||||
{
|
||||
I2C_BOARD_INFO("isp1301_omap", 0x2d),
|
||||
.irq = OMAP_GPIO_IRQ(125),
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
|
@ -162,12 +162,6 @@ config ACPI_DOCK
|
||||
This driver supports ACPI-controlled docking stations and removable
|
||||
drive bays such as the IBM Ultrabay and the Dell Module Bay.
|
||||
|
||||
config ACPI_I2C
|
||||
def_tristate I2C
|
||||
depends on I2C
|
||||
help
|
||||
ACPI I2C enumeration support.
|
||||
|
||||
config ACPI_PROCESSOR
|
||||
tristate "Processor"
|
||||
select THERMAL
|
||||
|
@ -73,7 +73,6 @@ obj-$(CONFIG_ACPI_HED) += hed.o
|
||||
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
|
||||
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
|
||||
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
|
||||
obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o
|
||||
|
||||
# processor has its own "processor." module_param namespace
|
||||
processor-y := processor_driver.o processor_throttling.o
|
||||
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* ACPI I2C enumeration support
|
||||
*
|
||||
* Copyright (C) 2012, Intel Corporation
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*
|
||||
* 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/acpi.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
ACPI_MODULE_NAME("i2c");
|
||||
|
||||
static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct i2c_board_info *info = data;
|
||||
|
||||
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||
struct acpi_resource_i2c_serialbus *sb;
|
||||
|
||||
sb = &ares->data.i2c_serial_bus;
|
||||
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
||||
info->addr = sb->slave_address;
|
||||
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
|
||||
info->flags |= I2C_CLIENT_TEN;
|
||||
}
|
||||
} else if (info->irq < 0) {
|
||||
struct resource r;
|
||||
|
||||
if (acpi_dev_resource_interrupt(ares, 0, &r))
|
||||
info->irq = r.start;
|
||||
}
|
||||
|
||||
/* Tell the ACPI core to skip this resource */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
|
||||
void *data, void **return_value)
|
||||
{
|
||||
struct i2c_adapter *adapter = data;
|
||||
struct list_head resource_list;
|
||||
struct i2c_board_info info;
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
|
||||
if (acpi_bus_get_device(handle, &adev))
|
||||
return AE_OK;
|
||||
if (acpi_bus_get_status(adev) || !adev->status.present)
|
||||
return AE_OK;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.acpi_node.handle = handle;
|
||||
info.irq = -1;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||
acpi_i2c_add_resource, &info);
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (ret < 0 || !info.addr)
|
||||
return AE_OK;
|
||||
|
||||
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
|
||||
if (!i2c_new_device(adapter, &info)) {
|
||||
dev_err(&adapter->dev,
|
||||
"failed to add I2C device %s from ACPI\n",
|
||||
dev_name(&adev->dev));
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
|
||||
* @adapter: pointer to adapter
|
||||
*
|
||||
* Enumerate all I2C slave devices behind this adapter by walking the ACPI
|
||||
* namespace. When a device is found it will be added to the Linux device
|
||||
* model and bound to the corresponding ACPI handle.
|
||||
*/
|
||||
void acpi_i2c_register_devices(struct i2c_adapter *adapter)
|
||||
{
|
||||
acpi_handle handle;
|
||||
acpi_status status;
|
||||
|
||||
handle = ACPI_HANDLE(adapter->dev.parent);
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
||||
acpi_i2c_add_device, NULL,
|
||||
adapter, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_i2c_register_devices);
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "drm.h"
|
||||
|
||||
|
@ -385,7 +385,7 @@ config I2C_CPM
|
||||
|
||||
config I2C_DAVINCI
|
||||
tristate "DaVinci I2C driver"
|
||||
depends on ARCH_DAVINCI
|
||||
depends on ARCH_DAVINCI || ARCH_KEYSTONE
|
||||
help
|
||||
Support for TI DaVinci I2C controller driver.
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_data/dma-atmel.h>
|
||||
@ -775,8 +774,6 @@ static int at91_twi_probe(struct platform_device *pdev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&dev->adapter);
|
||||
|
||||
dev_info(dev->dev, "AT91 i2c bus driver.\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -582,6 +582,7 @@ static struct i2c_algorithm bfin_twi_algorithm = {
|
||||
.functionality = bfin_twi_functionality,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int i2c_bfin_twi_suspend(struct device *dev)
|
||||
{
|
||||
struct bfin_twi_iface *iface = dev_get_drvdata(dev);
|
||||
@ -619,6 +620,10 @@ static int i2c_bfin_twi_resume(struct device *dev)
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(i2c_bfin_twi_pm,
|
||||
i2c_bfin_twi_suspend, i2c_bfin_twi_resume);
|
||||
#define I2C_BFIN_TWI_PM_OPS (&i2c_bfin_twi_pm)
|
||||
#else
|
||||
#define I2C_BFIN_TWI_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static int i2c_bfin_twi_probe(struct platform_device *pdev)
|
||||
{
|
||||
@ -669,8 +674,9 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
|
||||
p_adap->timeout = 5 * HZ;
|
||||
p_adap->retries = 3;
|
||||
|
||||
rc = peripheral_request_list((unsigned short *)pdev->dev.platform_data,
|
||||
"i2c-bfin-twi");
|
||||
rc = peripheral_request_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev),
|
||||
"i2c-bfin-twi");
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Can't setup pin mux!\n");
|
||||
goto out_error_pin_mux;
|
||||
@ -717,7 +723,7 @@ out_error_add_adapter:
|
||||
free_irq(iface->irq, iface);
|
||||
out_error_req_irq:
|
||||
out_error_no_irq:
|
||||
peripheral_free_list((unsigned short *)pdev->dev.platform_data);
|
||||
peripheral_free_list((unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
out_error_pin_mux:
|
||||
iounmap(iface->regs_base);
|
||||
out_error_ioremap:
|
||||
@ -733,7 +739,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
|
||||
|
||||
i2c_del_adapter(&(iface->adap));
|
||||
free_irq(iface->irq, iface);
|
||||
peripheral_free_list((unsigned short *)pdev->dev.platform_data);
|
||||
peripheral_free_list((unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
iounmap(iface->regs_base);
|
||||
kfree(iface);
|
||||
|
||||
@ -746,7 +752,7 @@ static struct platform_driver i2c_bfin_twi_driver = {
|
||||
.driver = {
|
||||
.name = "i2c-bfin-twi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &i2c_bfin_twi_pm,
|
||||
.pm = I2C_BFIN_TWI_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -233,8 +233,9 @@ static int cbus_i2c_probe(struct platform_device *pdev)
|
||||
chost->clk_gpio = of_get_gpio(dnode, 0);
|
||||
chost->dat_gpio = of_get_gpio(dnode, 1);
|
||||
chost->sel_gpio = of_get_gpio(dnode, 2);
|
||||
} else if (pdev->dev.platform_data) {
|
||||
struct i2c_cbus_platform_data *pdata = pdev->dev.platform_data;
|
||||
} else if (dev_get_platdata(&pdev->dev)) {
|
||||
struct i2c_cbus_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
chost->clk_gpio = pdata->clk_gpio;
|
||||
chost->dat_gpio = pdata->dat_gpio;
|
||||
chost->sel_gpio = pdata->sel_gpio;
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <asm/cpm.h>
|
||||
|
||||
@ -681,11 +680,6 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
|
||||
dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
|
||||
cpm->adap.name);
|
||||
|
||||
/*
|
||||
* register OF I2C devices
|
||||
*/
|
||||
of_i2c_register_devices(&cpm->adap);
|
||||
|
||||
return 0;
|
||||
out_shut:
|
||||
cpm_i2c_shutdown(cpm);
|
||||
|
@ -38,10 +38,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/platform_data/i2c-davinci.h>
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
@ -665,7 +662,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
dev->dev = &pdev->dev;
|
||||
dev->irq = irq->start;
|
||||
dev->pdata = dev->dev->platform_data;
|
||||
dev->pdata = dev_get_platdata(&dev->dev);
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
if (!dev->pdata && pdev->dev.of_node) {
|
||||
@ -728,7 +725,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "failure adding adapter\n");
|
||||
goto err_unuse_clocks;
|
||||
}
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -317,6 +317,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
|
||||
47, /* tLOW = 4.7 us */
|
||||
3, /* tf = 0.3 us */
|
||||
0); /* No offset */
|
||||
|
||||
/* Allow platforms to specify the ideal HCNT and LCNT values */
|
||||
if (dev->ss_hcnt && dev->ss_lcnt) {
|
||||
hcnt = dev->ss_hcnt;
|
||||
lcnt = dev->ss_lcnt;
|
||||
}
|
||||
dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
|
||||
dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
|
||||
dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
|
||||
@ -331,6 +337,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
|
||||
13, /* tLOW = 1.3 us */
|
||||
3, /* tf = 0.3 us */
|
||||
0); /* No offset */
|
||||
|
||||
if (dev->fs_hcnt && dev->fs_lcnt) {
|
||||
hcnt = dev->fs_hcnt;
|
||||
lcnt = dev->fs_lcnt;
|
||||
}
|
||||
dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
|
||||
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
|
||||
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
|
||||
@ -416,6 +427,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
||||
u32 addr = msgs[dev->msg_write_idx].addr;
|
||||
u32 buf_len = dev->tx_buf_len;
|
||||
u8 *buf = dev->tx_buf;
|
||||
bool need_restart = false;
|
||||
|
||||
intr_mask = DW_IC_INTR_DEFAULT_MASK;
|
||||
|
||||
@ -443,6 +455,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
||||
/* new i2c_msg */
|
||||
buf = msgs[dev->msg_write_idx].buf;
|
||||
buf_len = msgs[dev->msg_write_idx].len;
|
||||
|
||||
/* If both IC_EMPTYFIFO_HOLD_MASTER_EN and
|
||||
* IC_RESTART_EN are set, we must manually
|
||||
* set restart bit between messages.
|
||||
*/
|
||||
if ((dev->master_cfg & DW_IC_CON_RESTART_EN) &&
|
||||
(dev->msg_write_idx > 0))
|
||||
need_restart = true;
|
||||
}
|
||||
|
||||
tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
|
||||
@ -461,6 +481,11 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
||||
buf_len == 1)
|
||||
cmd |= BIT(9);
|
||||
|
||||
if (need_restart) {
|
||||
cmd |= BIT(10);
|
||||
need_restart = false;
|
||||
}
|
||||
|
||||
if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
|
||||
|
||||
/* avoid rx buffer overrun */
|
||||
|
@ -61,6 +61,14 @@
|
||||
* @tx_fifo_depth: depth of the hardware tx fifo
|
||||
* @rx_fifo_depth: depth of the hardware rx fifo
|
||||
* @rx_outstanding: current master-rx elements in tx fifo
|
||||
* @ss_hcnt: standard speed HCNT value
|
||||
* @ss_lcnt: standard speed LCNT value
|
||||
* @fs_hcnt: fast speed HCNT value
|
||||
* @fs_lcnt: fast speed LCNT value
|
||||
*
|
||||
* HCNT and LCNT parameters can be used if the platform knows more accurate
|
||||
* values than the one computed based only on the input clock frequency.
|
||||
* Leave them to be %0 if not used.
|
||||
*/
|
||||
struct dw_i2c_dev {
|
||||
struct device *dev;
|
||||
@ -91,6 +99,10 @@ struct dw_i2c_dev {
|
||||
unsigned int rx_fifo_depth;
|
||||
int rx_outstanding;
|
||||
u32 sda_hold_time;
|
||||
u16 ss_hcnt;
|
||||
u16 ss_lcnt;
|
||||
u16 fs_hcnt;
|
||||
u16 fs_lcnt;
|
||||
};
|
||||
|
||||
#define ACCESS_SWAP 0x00000001
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@ -54,9 +53,33 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
|
||||
u16 *hcnt, u16 *lcnt, u32 *sda_hold)
|
||||
{
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
|
||||
acpi_handle handle = ACPI_HANDLE(&pdev->dev);
|
||||
union acpi_object *obj;
|
||||
|
||||
if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
|
||||
return;
|
||||
|
||||
obj = (union acpi_object *)buf.pointer;
|
||||
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) {
|
||||
const union acpi_object *objs = obj->package.elements;
|
||||
|
||||
*hcnt = (u16)objs[0].integer.value;
|
||||
*lcnt = (u16)objs[1].integer.value;
|
||||
if (sda_hold)
|
||||
*sda_hold = (u32)objs[2].integer.value;
|
||||
}
|
||||
|
||||
kfree(buf.pointer);
|
||||
}
|
||||
|
||||
static int dw_i2c_acpi_configure(struct platform_device *pdev)
|
||||
{
|
||||
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
|
||||
bool fs_mode = dev->master_cfg & DW_IC_CON_SPEED_FAST;
|
||||
|
||||
if (!ACPI_HANDLE(&pdev->dev))
|
||||
return -ENODEV;
|
||||
@ -64,6 +87,16 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
|
||||
dev->adapter.nr = -1;
|
||||
dev->tx_fifo_depth = 32;
|
||||
dev->rx_fifo_depth = 32;
|
||||
|
||||
/*
|
||||
* Try to get SDA hold time and *CNT values from an ACPI method if
|
||||
* it exists for both supported speed modes.
|
||||
*/
|
||||
dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
|
||||
fs_mode ? NULL : &dev->sda_hold_time);
|
||||
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
|
||||
fs_mode ? &dev->sda_hold_time : NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -172,8 +205,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "failure adding adapter\n");
|
||||
return r;
|
||||
}
|
||||
of_i2c_register_devices(adap);
|
||||
acpi_i2c_register_devices(adap);
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
@ -207,7 +238,7 @@ static const struct of_device_id dw_i2c_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int dw_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
@ -228,9 +259,12 @@ static int dw_i2c_resume(struct device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
|
||||
#define DW_I2C_DEV_PM_OPS (&dw_i2c_dev_pm_ops)
|
||||
#else
|
||||
#define DW_I2C_DEV_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:i2c_designware");
|
||||
@ -242,7 +276,7 @@ static struct platform_driver dw_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(dw_i2c_of_match),
|
||||
.acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
|
||||
.pm = &dw_i2c_dev_pm_ops,
|
||||
.pm = DW_I2C_DEV_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
struct i2c_gpio_private_data {
|
||||
struct i2c_adapter adap;
|
||||
@ -137,9 +136,9 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (!pdev->dev.platform_data)
|
||||
if (!dev_get_platdata(&pdev->dev))
|
||||
return -ENXIO;
|
||||
pdata = pdev->dev.platform_data;
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
sda_pin = pdata->sda_pin;
|
||||
scl_pin = pdata->scl_pin;
|
||||
}
|
||||
@ -171,7 +170,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
||||
pdata->scl_pin = scl_pin;
|
||||
of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
|
||||
} else {
|
||||
memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
|
||||
memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));
|
||||
}
|
||||
|
||||
if (pdata->sda_is_open_drain) {
|
||||
@ -224,8 +223,6 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_add_bus;
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
|
||||
|
@ -87,7 +87,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
|
||||
defined CONFIG_DMI
|
||||
@ -1230,7 +1229,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
goto exit_free_irq;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&priv->adapter);
|
||||
i801_probe_optional_slaves(priv);
|
||||
/* We ignore errors - multiplexing is optional */
|
||||
i801_add_mux(priv);
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
#include "i2c-ibm_iic.h"
|
||||
|
||||
@ -759,9 +758,6 @@ static int iic_probe(struct platform_device *ofdev)
|
||||
dev_info(&ofdev->dev, "using %s mode\n",
|
||||
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
|
||||
|
||||
/* Now register all the child nodes */
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup:
|
||||
|
@ -30,6 +30,8 @@
|
||||
* Copyright (C) 2007 RightHand Technologies, Inc.
|
||||
* Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
|
||||
*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
/** Includes *******************************************************************
|
||||
@ -50,7 +52,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/platform_data/i2c-imx.h>
|
||||
|
||||
/** Defines ********************************************************************
|
||||
@ -62,12 +63,22 @@
|
||||
/* Default value */
|
||||
#define IMX_I2C_BIT_RATE 100000 /* 100kHz */
|
||||
|
||||
/* IMX I2C registers */
|
||||
/* IMX I2C registers:
|
||||
* the I2C register offset is different between SoCs,
|
||||
* to provid support for all these chips, split the
|
||||
* register offset into a fixed base address and a
|
||||
* variable shift value, then the full register offset
|
||||
* will be calculated by
|
||||
* reg_off = ( reg_base_addr << reg_shift)
|
||||
*/
|
||||
#define IMX_I2C_IADR 0x00 /* i2c slave address */
|
||||
#define IMX_I2C_IFDR 0x04 /* i2c frequency divider */
|
||||
#define IMX_I2C_I2CR 0x08 /* i2c control */
|
||||
#define IMX_I2C_I2SR 0x0C /* i2c status */
|
||||
#define IMX_I2C_I2DR 0x10 /* i2c transfer data */
|
||||
#define IMX_I2C_IFDR 0x01 /* i2c frequency divider */
|
||||
#define IMX_I2C_I2CR 0x02 /* i2c control */
|
||||
#define IMX_I2C_I2SR 0x03 /* i2c status */
|
||||
#define IMX_I2C_I2DR 0x04 /* i2c transfer data */
|
||||
|
||||
#define IMX_I2C_REGSHIFT 2
|
||||
#define VF610_I2C_REGSHIFT 0
|
||||
|
||||
/* Bits of IMX I2C registers */
|
||||
#define I2SR_RXAK 0x01
|
||||
@ -84,6 +95,19 @@
|
||||
#define I2CR_IIEN 0x40
|
||||
#define I2CR_IEN 0x80
|
||||
|
||||
/* register bits different operating codes definition:
|
||||
* 1) I2SR: Interrupt flags clear operation differ between SoCs:
|
||||
* - write zero to clear(w0c) INT flag on i.MX,
|
||||
* - but write one to clear(w1c) INT flag on Vybrid.
|
||||
* 2) I2CR: I2C module enable operation also differ between SoCs:
|
||||
* - set I2CR_IEN bit enable the module on i.MX,
|
||||
* - but clear I2CR_IEN bit enable the module on Vybrid.
|
||||
*/
|
||||
#define I2SR_CLR_OPCODE_W0C 0x0
|
||||
#define I2SR_CLR_OPCODE_W1C (I2SR_IAL | I2SR_IIF)
|
||||
#define I2CR_IEN_OPCODE_0 0x0
|
||||
#define I2CR_IEN_OPCODE_1 I2CR_IEN
|
||||
|
||||
/** Variables ******************************************************************
|
||||
*******************************************************************************/
|
||||
|
||||
@ -95,8 +119,12 @@
|
||||
*
|
||||
* Duplicated divider values removed from list
|
||||
*/
|
||||
struct imx_i2c_clk_pair {
|
||||
u16 div;
|
||||
u16 val;
|
||||
};
|
||||
|
||||
static u16 __initdata i2c_clk_div[50][2] = {
|
||||
static struct imx_i2c_clk_pair imx_i2c_clk_div[] = {
|
||||
{ 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 },
|
||||
{ 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 },
|
||||
{ 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 },
|
||||
@ -112,9 +140,38 @@ static u16 __initdata i2c_clk_div[50][2] = {
|
||||
{ 3072, 0x1E }, { 3840, 0x1F }
|
||||
};
|
||||
|
||||
/* Vybrid VF610 clock divider, register value pairs */
|
||||
static struct imx_i2c_clk_pair vf610_i2c_clk_div[] = {
|
||||
{ 20, 0x00 }, { 22, 0x01 }, { 24, 0x02 }, { 26, 0x03 },
|
||||
{ 28, 0x04 }, { 30, 0x05 }, { 32, 0x09 }, { 34, 0x06 },
|
||||
{ 36, 0x0A }, { 40, 0x07 }, { 44, 0x0C }, { 48, 0x0D },
|
||||
{ 52, 0x43 }, { 56, 0x0E }, { 60, 0x45 }, { 64, 0x12 },
|
||||
{ 68, 0x0F }, { 72, 0x13 }, { 80, 0x14 }, { 88, 0x15 },
|
||||
{ 96, 0x19 }, { 104, 0x16 }, { 112, 0x1A }, { 128, 0x17 },
|
||||
{ 136, 0x4F }, { 144, 0x1C }, { 160, 0x1D }, { 176, 0x55 },
|
||||
{ 192, 0x1E }, { 208, 0x56 }, { 224, 0x22 }, { 228, 0x24 },
|
||||
{ 240, 0x1F }, { 256, 0x23 }, { 288, 0x5C }, { 320, 0x25 },
|
||||
{ 384, 0x26 }, { 448, 0x2A }, { 480, 0x27 }, { 512, 0x2B },
|
||||
{ 576, 0x2C }, { 640, 0x2D }, { 768, 0x31 }, { 896, 0x32 },
|
||||
{ 960, 0x2F }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 },
|
||||
{ 1536, 0x36 }, { 1792, 0x3A }, { 1920, 0x37 }, { 2048, 0x3B },
|
||||
{ 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A },
|
||||
{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
|
||||
};
|
||||
|
||||
enum imx_i2c_type {
|
||||
IMX1_I2C,
|
||||
IMX21_I2C,
|
||||
VF610_I2C,
|
||||
};
|
||||
|
||||
struct imx_i2c_hwdata {
|
||||
enum imx_i2c_type devtype;
|
||||
unsigned regshift;
|
||||
struct imx_i2c_clk_pair *clk_div;
|
||||
unsigned ndivs;
|
||||
unsigned i2sr_clr_opcode;
|
||||
unsigned i2cr_ien_opcode;
|
||||
};
|
||||
|
||||
struct imx_i2c_struct {
|
||||
@ -126,16 +183,46 @@ struct imx_i2c_struct {
|
||||
unsigned int disable_delay;
|
||||
int stopped;
|
||||
unsigned int ifdr; /* IMX_I2C_IFDR */
|
||||
enum imx_i2c_type devtype;
|
||||
const struct imx_i2c_hwdata *hwdata;
|
||||
};
|
||||
|
||||
static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
|
||||
.devtype = IMX1_I2C,
|
||||
.regshift = IMX_I2C_REGSHIFT,
|
||||
.clk_div = imx_i2c_clk_div,
|
||||
.ndivs = ARRAY_SIZE(imx_i2c_clk_div),
|
||||
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C,
|
||||
.i2cr_ien_opcode = I2CR_IEN_OPCODE_1,
|
||||
|
||||
};
|
||||
|
||||
static const struct imx_i2c_hwdata imx21_i2c_hwdata = {
|
||||
.devtype = IMX21_I2C,
|
||||
.regshift = IMX_I2C_REGSHIFT,
|
||||
.clk_div = imx_i2c_clk_div,
|
||||
.ndivs = ARRAY_SIZE(imx_i2c_clk_div),
|
||||
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C,
|
||||
.i2cr_ien_opcode = I2CR_IEN_OPCODE_1,
|
||||
|
||||
};
|
||||
|
||||
static struct imx_i2c_hwdata vf610_i2c_hwdata = {
|
||||
.devtype = VF610_I2C,
|
||||
.regshift = VF610_I2C_REGSHIFT,
|
||||
.clk_div = vf610_i2c_clk_div,
|
||||
.ndivs = ARRAY_SIZE(vf610_i2c_clk_div),
|
||||
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C,
|
||||
.i2cr_ien_opcode = I2CR_IEN_OPCODE_0,
|
||||
|
||||
};
|
||||
|
||||
static struct platform_device_id imx_i2c_devtype[] = {
|
||||
{
|
||||
.name = "imx1-i2c",
|
||||
.driver_data = IMX1_I2C,
|
||||
.driver_data = (kernel_ulong_t)&imx1_i2c_hwdata,
|
||||
}, {
|
||||
.name = "imx21-i2c",
|
||||
.driver_data = IMX21_I2C,
|
||||
.driver_data = (kernel_ulong_t)&imx21_i2c_hwdata,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
@ -143,15 +230,28 @@ static struct platform_device_id imx_i2c_devtype[] = {
|
||||
MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
|
||||
|
||||
static const struct of_device_id i2c_imx_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx1-i2c", .data = &imx_i2c_devtype[IMX1_I2C], },
|
||||
{ .compatible = "fsl,imx21-i2c", .data = &imx_i2c_devtype[IMX21_I2C], },
|
||||
{ .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },
|
||||
{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
|
||||
{ .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids);
|
||||
|
||||
static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
|
||||
{
|
||||
return i2c_imx->devtype == IMX1_I2C;
|
||||
return i2c_imx->hwdata->devtype == IMX1_I2C;
|
||||
}
|
||||
|
||||
static inline void imx_i2c_write_reg(unsigned int val,
|
||||
struct imx_i2c_struct *i2c_imx, unsigned int reg)
|
||||
{
|
||||
writeb(val, i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
|
||||
}
|
||||
|
||||
static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
|
||||
unsigned int reg)
|
||||
{
|
||||
return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
|
||||
}
|
||||
|
||||
/** Functions for IMX I2C adapter driver ***************************************
|
||||
@ -165,7 +265,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
|
||||
|
||||
while (1) {
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2SR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
|
||||
if (for_busy && (temp & I2SR_IBB))
|
||||
break;
|
||||
if (!for_busy && !(temp & I2SR_IBB))
|
||||
@ -196,7 +296,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
|
||||
|
||||
static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
|
||||
{
|
||||
if (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_RXAK) {
|
||||
if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__);
|
||||
return -EIO; /* No ACK */
|
||||
}
|
||||
@ -213,25 +313,25 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
|
||||
|
||||
clk_prepare_enable(i2c_imx->clk);
|
||||
writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR);
|
||||
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
|
||||
/* Enable I2C controller */
|
||||
writeb(0, i2c_imx->base + IMX_I2C_I2SR);
|
||||
writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
|
||||
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR);
|
||||
|
||||
/* Wait controller to be stable */
|
||||
udelay(50);
|
||||
|
||||
/* Start I2C transaction */
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp |= I2CR_MSTA;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
result = i2c_imx_bus_busy(i2c_imx, 1);
|
||||
if (result)
|
||||
return result;
|
||||
i2c_imx->stopped = 0;
|
||||
|
||||
temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -242,9 +342,9 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
|
||||
if (!i2c_imx->stopped) {
|
||||
/* Stop I2C transaction */
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp &= ~(I2CR_MSTA | I2CR_MTX);
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
}
|
||||
if (is_imx1_i2c(i2c_imx)) {
|
||||
/*
|
||||
@ -260,13 +360,15 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
|
||||
}
|
||||
|
||||
/* Disable I2C controller */
|
||||
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
clk_disable_unprepare(i2c_imx->clk);
|
||||
}
|
||||
|
||||
static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
unsigned int rate)
|
||||
{
|
||||
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
|
||||
unsigned int i2c_clk_rate;
|
||||
unsigned int div;
|
||||
int i;
|
||||
@ -274,15 +376,15 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
/* Divider value calculation */
|
||||
i2c_clk_rate = clk_get_rate(i2c_imx->clk);
|
||||
div = (i2c_clk_rate + rate - 1) / rate;
|
||||
if (div < i2c_clk_div[0][0])
|
||||
if (div < i2c_clk_div[0].div)
|
||||
i = 0;
|
||||
else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0])
|
||||
i = ARRAY_SIZE(i2c_clk_div) - 1;
|
||||
else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
|
||||
i = i2c_imx->hwdata->ndivs - 1;
|
||||
else
|
||||
for (i = 0; i2c_clk_div[i][0] < div; i++);
|
||||
for (i = 0; i2c_clk_div[i].div < div; i++);
|
||||
|
||||
/* Store divider value */
|
||||
i2c_imx->ifdr = i2c_clk_div[i][1];
|
||||
i2c_imx->ifdr = i2c_clk_div[i].val;
|
||||
|
||||
/*
|
||||
* There dummy delay is calculated.
|
||||
@ -290,7 +392,7 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
* This delay is used in I2C bus disable function
|
||||
* to fix chip hardware bug.
|
||||
*/
|
||||
i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0]
|
||||
i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
|
||||
+ (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
|
||||
|
||||
/* dev_dbg() can't be used, because adapter is not yet registered */
|
||||
@ -298,7 +400,7 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
|
||||
__func__, i2c_clk_rate, div);
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
|
||||
__func__, i2c_clk_div[i][1], i2c_clk_div[i][0]);
|
||||
__func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -307,12 +409,13 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
|
||||
struct imx_i2c_struct *i2c_imx = dev_id;
|
||||
unsigned int temp;
|
||||
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2SR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
|
||||
if (temp & I2SR_IIF) {
|
||||
/* save status register */
|
||||
i2c_imx->i2csr = temp;
|
||||
temp &= ~I2SR_IIF;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2SR);
|
||||
temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
|
||||
wake_up(&i2c_imx->queue);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -328,7 +431,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
||||
__func__, msgs->addr << 1);
|
||||
|
||||
/* write slave address */
|
||||
writeb(msgs->addr << 1, i2c_imx->base + IMX_I2C_I2DR);
|
||||
imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
|
||||
result = i2c_imx_trx_complete(i2c_imx);
|
||||
if (result)
|
||||
return result;
|
||||
@ -342,7 +445,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> write byte: B%d=0x%X\n",
|
||||
__func__, i, msgs->buf[i]);
|
||||
writeb(msgs->buf[i], i2c_imx->base + IMX_I2C_I2DR);
|
||||
imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR);
|
||||
result = i2c_imx_trx_complete(i2c_imx);
|
||||
if (result)
|
||||
return result;
|
||||
@ -363,7 +466,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
||||
__func__, (msgs->addr << 1) | 0x01);
|
||||
|
||||
/* write slave address */
|
||||
writeb((msgs->addr << 1) | 0x01, i2c_imx->base + IMX_I2C_I2DR);
|
||||
imx_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_imx, IMX_I2C_I2DR);
|
||||
result = i2c_imx_trx_complete(i2c_imx);
|
||||
if (result)
|
||||
return result;
|
||||
@ -374,12 +477,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
|
||||
|
||||
/* setup bus to read data */
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp &= ~I2CR_MTX;
|
||||
if (msgs->len - 1)
|
||||
temp &= ~I2CR_TXAK;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
readb(i2c_imx->base + IMX_I2C_I2DR); /* dummy read */
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
|
||||
|
||||
@ -393,19 +496,19 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
||||
controller from generating another clock cycle */
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> clear MSTA\n", __func__);
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp &= ~(I2CR_MSTA | I2CR_MTX);
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
i2c_imx_bus_busy(i2c_imx, 0);
|
||||
i2c_imx->stopped = 1;
|
||||
} else if (i == (msgs->len - 2)) {
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> set TXAK\n", __func__);
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp |= I2CR_TXAK;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
}
|
||||
msgs->buf[i] = readb(i2c_imx->base + IMX_I2C_I2DR);
|
||||
msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> read byte: B%d=0x%X\n",
|
||||
__func__, i, msgs->buf[i]);
|
||||
@ -432,9 +535,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
|
||||
if (i) {
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> repeated start\n", __func__);
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp |= I2CR_RSTA;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
result = i2c_imx_bus_busy(i2c_imx, 1);
|
||||
if (result)
|
||||
goto fail0;
|
||||
@ -443,13 +546,13 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
|
||||
"<%s> transfer message: %d\n", __func__, i);
|
||||
/* write/read data */
|
||||
#ifdef CONFIG_I2C_DEBUG_BUS
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, "
|
||||
"MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__,
|
||||
(temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0),
|
||||
(temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0),
|
||||
(temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0));
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2SR);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, "
|
||||
"IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__,
|
||||
@ -492,7 +595,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
|
||||
&pdev->dev);
|
||||
struct imx_i2c_struct *i2c_imx;
|
||||
struct resource *res;
|
||||
struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
void __iomem *base;
|
||||
int irq, ret;
|
||||
u32 bitrate;
|
||||
@ -518,8 +621,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (of_id)
|
||||
pdev->id_entry = of_id->data;
|
||||
i2c_imx->devtype = pdev->id_entry->driver_data;
|
||||
i2c_imx->hwdata = of_id->data;
|
||||
else
|
||||
i2c_imx->hwdata = (struct imx_i2c_hwdata *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
/* Setup i2c_imx driver structure */
|
||||
strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
|
||||
@ -537,6 +642,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(i2c_imx->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(i2c_imx->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "can't enable I2C clock\n");
|
||||
return ret;
|
||||
}
|
||||
/* Request IRQ */
|
||||
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
|
||||
pdev->name, i2c_imx);
|
||||
@ -560,8 +670,9 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
|
||||
i2c_imx_set_clk(i2c_imx, bitrate);
|
||||
|
||||
/* Set up chip registers to defaults */
|
||||
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
|
||||
writeb(0, i2c_imx->base + IMX_I2C_I2SR);
|
||||
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
|
||||
i2c_imx, IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
|
||||
|
||||
/* Add I2C adapter */
|
||||
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
|
||||
@ -570,10 +681,9 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&i2c_imx->adapter);
|
||||
|
||||
/* Set up platform driver data */
|
||||
platform_set_drvdata(pdev, i2c_imx);
|
||||
clk_disable_unprepare(i2c_imx->clk);
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
|
||||
dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",
|
||||
@ -596,10 +706,10 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
|
||||
i2c_del_adapter(&i2c_imx->adapter);
|
||||
|
||||
/* setup chip registers to defaults */
|
||||
writeb(0, i2c_imx->base + IMX_I2C_IADR);
|
||||
writeb(0, i2c_imx->base + IMX_I2C_IFDR);
|
||||
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
|
||||
writeb(0, i2c_imx->base + IMX_I2C_I2SR);
|
||||
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
|
||||
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR);
|
||||
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
|
||||
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -879,6 +879,7 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
DMA_BIT_MASK(32)) != 0)) {
|
||||
dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n",
|
||||
pdev);
|
||||
err = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -64,9 +64,10 @@ struct mpc_i2c {
|
||||
struct i2c_adapter adap;
|
||||
int irq;
|
||||
u32 real_clk;
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
u8 fdr, dfsrr;
|
||||
#endif
|
||||
struct clk *clk_per;
|
||||
};
|
||||
|
||||
struct mpc_i2c_divider {
|
||||
@ -609,7 +610,6 @@ static const struct i2c_algorithm mpc_algo = {
|
||||
|
||||
static struct i2c_adapter mpc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "MPC adapter",
|
||||
.algo = &mpc_algo,
|
||||
.timeout = HZ,
|
||||
};
|
||||
@ -623,6 +623,9 @@ static int fsl_i2c_probe(struct platform_device *op)
|
||||
u32 clock = MPC_I2C_CLOCK_LEGACY;
|
||||
int result = 0;
|
||||
int plen;
|
||||
struct resource res;
|
||||
struct clk *clk;
|
||||
int err;
|
||||
|
||||
match = of_match_device(mpc_i2c_of_match, &op->dev);
|
||||
if (!match)
|
||||
@ -653,6 +656,21 @@ static int fsl_i2c_probe(struct platform_device *op)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* enable clock for the I2C peripheral (non fatal),
|
||||
* keep a reference upon successful allocation
|
||||
*/
|
||||
clk = devm_clk_get(&op->dev, NULL);
|
||||
if (!IS_ERR(clk)) {
|
||||
err = clk_prepare_enable(clk);
|
||||
if (err) {
|
||||
dev_err(&op->dev, "failed to enable clock\n");
|
||||
goto fail_request;
|
||||
} else {
|
||||
i2c->clk_per = clk;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) {
|
||||
clock = MPC_I2C_CLOCK_PRESERVE;
|
||||
} else {
|
||||
@ -682,6 +700,9 @@ static int fsl_i2c_probe(struct platform_device *op)
|
||||
platform_set_drvdata(op, i2c);
|
||||
|
||||
i2c->adap = mpc_ops;
|
||||
of_address_to_resource(op->dev.of_node, 0, &res);
|
||||
scnprintf(i2c->adap.name, sizeof(i2c->adap.name),
|
||||
"MPC adapter at 0x%llx", (unsigned long long)res.start);
|
||||
i2c_set_adapdata(&i2c->adap, i2c);
|
||||
i2c->adap.dev.parent = &op->dev;
|
||||
i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
|
||||
@ -691,11 +712,12 @@ static int fsl_i2c_probe(struct platform_device *op)
|
||||
dev_err(i2c->dev, "failed to add adapter\n");
|
||||
goto fail_add;
|
||||
}
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
|
||||
return result;
|
||||
|
||||
fail_add:
|
||||
if (i2c->clk_per)
|
||||
clk_disable_unprepare(i2c->clk_per);
|
||||
free_irq(i2c->irq, i2c);
|
||||
fail_request:
|
||||
irq_dispose_mapping(i2c->irq);
|
||||
@ -711,6 +733,9 @@ static int fsl_i2c_remove(struct platform_device *op)
|
||||
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
|
||||
if (i2c->clk_per)
|
||||
clk_disable_unprepare(i2c->clk_per);
|
||||
|
||||
if (i2c->irq)
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
@ -720,7 +745,7 @@ static int fsl_i2c_remove(struct platform_device *op)
|
||||
return 0;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mpc_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct mpc_i2c *i2c = dev_get_drvdata(dev);
|
||||
@ -741,7 +766,10 @@ static int mpc_i2c_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
|
||||
static SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
|
||||
#define MPC_I2C_PM_OPS (&mpc_i2c_pm_ops)
|
||||
#else
|
||||
#define MPC_I2C_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static const struct mpc_i2c_data mpc_i2c_data_512x = {
|
||||
@ -788,9 +816,7 @@ static struct platform_driver mpc_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = mpc_i2c_of_match,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &mpc_i2c_pm_ops,
|
||||
#endif
|
||||
.pm = MPC_I2C_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define MV64XXX_I2C_ADDR_ADDR(val) ((val & 0x7f) << 1)
|
||||
#define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7)
|
||||
@ -55,6 +55,32 @@
|
||||
#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8
|
||||
#define MV64XXX_I2C_STATUS_NO_STATUS 0xf8
|
||||
|
||||
/* Register defines (I2C bridge) */
|
||||
#define MV64XXX_I2C_REG_TX_DATA_LO 0xc0
|
||||
#define MV64XXX_I2C_REG_TX_DATA_HI 0xc4
|
||||
#define MV64XXX_I2C_REG_RX_DATA_LO 0xc8
|
||||
#define MV64XXX_I2C_REG_RX_DATA_HI 0xcc
|
||||
#define MV64XXX_I2C_REG_BRIDGE_CONTROL 0xd0
|
||||
#define MV64XXX_I2C_REG_BRIDGE_STATUS 0xd4
|
||||
#define MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xd8
|
||||
#define MV64XXX_I2C_REG_BRIDGE_INTR_MASK 0xdC
|
||||
#define MV64XXX_I2C_REG_BRIDGE_TIMING 0xe0
|
||||
|
||||
/* Bridge Control values */
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_WR 0x00000001
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_RD 0x00000002
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x00001000
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT 13
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT 16
|
||||
#define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x00080000
|
||||
|
||||
/* Bridge Status values */
|
||||
#define MV64XXX_I2C_BRIDGE_STATUS_ERROR 0x00000001
|
||||
#define MV64XXX_I2C_STATUS_OFFLOAD_ERROR 0xf0000001
|
||||
#define MV64XXX_I2C_STATUS_OFFLOAD_OK 0xf0000000
|
||||
|
||||
|
||||
/* Driver states */
|
||||
enum {
|
||||
MV64XXX_I2C_STATE_INVALID,
|
||||
@ -71,14 +97,17 @@ enum {
|
||||
enum {
|
||||
MV64XXX_I2C_ACTION_INVALID,
|
||||
MV64XXX_I2C_ACTION_CONTINUE,
|
||||
MV64XXX_I2C_ACTION_OFFLOAD_SEND_START,
|
||||
MV64XXX_I2C_ACTION_SEND_START,
|
||||
MV64XXX_I2C_ACTION_SEND_RESTART,
|
||||
MV64XXX_I2C_ACTION_OFFLOAD_RESTART,
|
||||
MV64XXX_I2C_ACTION_SEND_ADDR_1,
|
||||
MV64XXX_I2C_ACTION_SEND_ADDR_2,
|
||||
MV64XXX_I2C_ACTION_SEND_DATA,
|
||||
MV64XXX_I2C_ACTION_RCV_DATA,
|
||||
MV64XXX_I2C_ACTION_RCV_DATA_STOP,
|
||||
MV64XXX_I2C_ACTION_SEND_STOP,
|
||||
MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP,
|
||||
};
|
||||
|
||||
struct mv64xxx_i2c_regs {
|
||||
@ -117,6 +146,9 @@ struct mv64xxx_i2c_data {
|
||||
spinlock_t lock;
|
||||
struct i2c_msg *msg;
|
||||
struct i2c_adapter adapter;
|
||||
bool offload_enabled;
|
||||
/* 5us delay in order to avoid repeated start timing violation */
|
||||
bool errata_delay;
|
||||
};
|
||||
|
||||
static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
|
||||
@ -165,6 +197,77 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
|
||||
}
|
||||
}
|
||||
|
||||
static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data)
|
||||
{
|
||||
unsigned long data_reg_hi = 0;
|
||||
unsigned long data_reg_lo = 0;
|
||||
unsigned long ctrl_reg;
|
||||
struct i2c_msg *msg = drv_data->msgs;
|
||||
|
||||
drv_data->msg = msg;
|
||||
drv_data->byte_posn = 0;
|
||||
drv_data->bytes_left = msg->len;
|
||||
drv_data->aborting = 0;
|
||||
drv_data->rc = 0;
|
||||
/* Only regular transactions can be offloaded */
|
||||
if ((msg->flags & ~(I2C_M_TEN | I2C_M_RD)) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Only 1-8 byte transfers can be offloaded */
|
||||
if (msg->len < 1 || msg->len > 8)
|
||||
return -EINVAL;
|
||||
|
||||
/* Build transaction */
|
||||
ctrl_reg = MV64XXX_I2C_BRIDGE_CONTROL_ENABLE |
|
||||
(msg->addr << MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT);
|
||||
|
||||
if ((msg->flags & I2C_M_TEN) != 0)
|
||||
ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT;
|
||||
|
||||
if ((msg->flags & I2C_M_RD) == 0) {
|
||||
u8 local_buf[8] = { 0 };
|
||||
|
||||
memcpy(local_buf, msg->buf, msg->len);
|
||||
data_reg_lo = cpu_to_le32(*((u32 *)local_buf));
|
||||
data_reg_hi = cpu_to_le32(*((u32 *)(local_buf+4)));
|
||||
|
||||
ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR |
|
||||
(msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT;
|
||||
|
||||
writel_relaxed(data_reg_lo,
|
||||
drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO);
|
||||
writel_relaxed(data_reg_hi,
|
||||
drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI);
|
||||
|
||||
} else {
|
||||
ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_RD |
|
||||
(msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/* Execute transaction */
|
||||
writel(ctrl_reg, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mv64xxx_i2c_update_offload_data(struct mv64xxx_i2c_data *drv_data)
|
||||
{
|
||||
struct i2c_msg *msg = drv_data->msg;
|
||||
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
u32 data_reg_lo = readl(drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_RX_DATA_LO);
|
||||
u32 data_reg_hi = readl(drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_RX_DATA_HI);
|
||||
u8 local_buf[8] = { 0 };
|
||||
|
||||
*((u32 *)local_buf) = le32_to_cpu(data_reg_lo);
|
||||
*((u32 *)(local_buf+4)) = le32_to_cpu(data_reg_hi);
|
||||
memcpy(msg->buf, local_buf, msg->len);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
*****************************************************************************
|
||||
*
|
||||
@ -177,6 +280,15 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
|
||||
static void
|
||||
mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
|
||||
{
|
||||
if (drv_data->offload_enabled) {
|
||||
writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
|
||||
writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING);
|
||||
writel(0, drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE);
|
||||
writel(0, drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_BRIDGE_INTR_MASK);
|
||||
}
|
||||
|
||||
writel(0, drv_data->reg_base + drv_data->reg_offsets.soft_reset);
|
||||
writel(MV64XXX_I2C_BAUD_DIV_M(drv_data->freq_m) | MV64XXX_I2C_BAUD_DIV_N(drv_data->freq_n),
|
||||
drv_data->reg_base + drv_data->reg_offsets.clock);
|
||||
@ -283,6 +395,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
|
||||
drv_data->rc = -ENXIO;
|
||||
break;
|
||||
|
||||
case MV64XXX_I2C_STATUS_OFFLOAD_OK:
|
||||
if (drv_data->send_stop || drv_data->aborting) {
|
||||
drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP;
|
||||
drv_data->state = MV64XXX_I2C_STATE_IDLE;
|
||||
} else {
|
||||
drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_RESTART;
|
||||
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_RESTART;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&drv_data->adapter.dev,
|
||||
"mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, "
|
||||
@ -299,19 +421,29 @@ static void
|
||||
mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
{
|
||||
switch(drv_data->action) {
|
||||
case MV64XXX_I2C_ACTION_OFFLOAD_RESTART:
|
||||
mv64xxx_i2c_update_offload_data(drv_data);
|
||||
writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
|
||||
writel(0, drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE);
|
||||
/* FALLTHRU */
|
||||
case MV64XXX_I2C_ACTION_SEND_RESTART:
|
||||
/* We should only get here if we have further messages */
|
||||
BUG_ON(drv_data->num_msgs == 0);
|
||||
|
||||
drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
|
||||
writel(drv_data->cntl_bits,
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
|
||||
drv_data->msgs++;
|
||||
drv_data->num_msgs--;
|
||||
if (!(drv_data->offload_enabled &&
|
||||
mv64xxx_i2c_offload_msg(drv_data))) {
|
||||
drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
|
||||
writel(drv_data->cntl_bits,
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
|
||||
/* Setup for the next message */
|
||||
mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
|
||||
/* Setup for the next message */
|
||||
mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
|
||||
}
|
||||
if (drv_data->errata_delay)
|
||||
udelay(5);
|
||||
|
||||
/*
|
||||
* We're never at the start of the message here, and by this
|
||||
@ -326,6 +458,12 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
break;
|
||||
|
||||
case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START:
|
||||
if (!mv64xxx_i2c_offload_msg(drv_data))
|
||||
break;
|
||||
else
|
||||
drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
|
||||
/* FALLTHRU */
|
||||
case MV64XXX_I2C_ACTION_SEND_START:
|
||||
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
@ -366,6 +504,9 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
drv_data->block = 0;
|
||||
if (drv_data->errata_delay)
|
||||
udelay(5);
|
||||
|
||||
wake_up(&drv_data->waitq);
|
||||
break;
|
||||
|
||||
@ -375,6 +516,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
"mv64xxx_i2c_do_action: Invalid action: %d\n",
|
||||
drv_data->action);
|
||||
drv_data->rc = -EIO;
|
||||
|
||||
/* FALLTHRU */
|
||||
case MV64XXX_I2C_ACTION_SEND_STOP:
|
||||
drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
|
||||
@ -383,6 +525,15 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
drv_data->block = 0;
|
||||
wake_up(&drv_data->waitq);
|
||||
break;
|
||||
|
||||
case MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP:
|
||||
mv64xxx_i2c_update_offload_data(drv_data);
|
||||
writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL);
|
||||
writel(0, drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE);
|
||||
drv_data->block = 0;
|
||||
wake_up(&drv_data->waitq);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,6 +546,21 @@ mv64xxx_i2c_intr(int irq, void *dev_id)
|
||||
irqreturn_t rc = IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&drv_data->lock, flags);
|
||||
|
||||
if (drv_data->offload_enabled) {
|
||||
while (readl(drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) {
|
||||
int reg_status = readl(drv_data->reg_base +
|
||||
MV64XXX_I2C_REG_BRIDGE_STATUS);
|
||||
if (reg_status & MV64XXX_I2C_BRIDGE_STATUS_ERROR)
|
||||
status = MV64XXX_I2C_STATUS_OFFLOAD_ERROR;
|
||||
else
|
||||
status = MV64XXX_I2C_STATUS_OFFLOAD_OK;
|
||||
mv64xxx_i2c_fsm(drv_data, status);
|
||||
mv64xxx_i2c_do_action(drv_data);
|
||||
rc = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
while (readl(drv_data->reg_base + drv_data->reg_offsets.control) &
|
||||
MV64XXX_I2C_REG_CONTROL_IFLG) {
|
||||
status = readl(drv_data->reg_base + drv_data->reg_offsets.status);
|
||||
@ -459,11 +625,15 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drv_data->lock, flags);
|
||||
mv64xxx_i2c_prepare_for_io(drv_data, msg);
|
||||
|
||||
drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
|
||||
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
|
||||
if (drv_data->offload_enabled) {
|
||||
drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START;
|
||||
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
|
||||
} else {
|
||||
mv64xxx_i2c_prepare_for_io(drv_data, msg);
|
||||
|
||||
drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
|
||||
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
|
||||
}
|
||||
drv_data->send_stop = is_last;
|
||||
drv_data->block = 1;
|
||||
mv64xxx_i2c_do_action(drv_data);
|
||||
@ -521,6 +691,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
|
||||
static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
|
||||
{ .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i},
|
||||
{ .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
{ .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
|
||||
@ -601,6 +772,15 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
|
||||
|
||||
memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets));
|
||||
|
||||
/*
|
||||
* For controllers embedded in new SoCs activate the
|
||||
* Transaction Generator support and the errata fix.
|
||||
*/
|
||||
if (of_device_is_compatible(np, "marvell,mv78230-i2c")) {
|
||||
drv_data->offload_enabled = true;
|
||||
drv_data->errata_delay = true;
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
#endif
|
||||
@ -618,7 +798,7 @@ static int
|
||||
mv64xxx_i2c_probe(struct platform_device *pd)
|
||||
{
|
||||
struct mv64xxx_i2c_data *drv_data;
|
||||
struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data;
|
||||
struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev);
|
||||
struct resource *r;
|
||||
int rc;
|
||||
|
||||
@ -654,6 +834,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
|
||||
drv_data->freq_n = pdata->freq_n;
|
||||
drv_data->irq = platform_get_irq(pd, 0);
|
||||
drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
|
||||
drv_data->offload_enabled = false;
|
||||
memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets));
|
||||
} else if (pd->dev.of_node) {
|
||||
rc = mv64xxx_of_config(drv_data, &pd->dev);
|
||||
@ -689,8 +870,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
|
||||
goto exit_free_irq;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&drv_data->adapter);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_free_irq:
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/stmp_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
@ -114,18 +113,21 @@ struct mxs_i2c_dev {
|
||||
|
||||
uint32_t timing0;
|
||||
uint32_t timing1;
|
||||
uint32_t timing2;
|
||||
|
||||
/* DMA support components */
|
||||
struct dma_chan *dmach;
|
||||
struct dma_chan *dmach;
|
||||
uint32_t pio_data[2];
|
||||
uint32_t addr_data;
|
||||
struct scatterlist sg_io[2];
|
||||
bool dma_read;
|
||||
};
|
||||
|
||||
static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
|
||||
static int mxs_i2c_reset(struct mxs_i2c_dev *i2c)
|
||||
{
|
||||
stmp_reset_block(i2c->regs);
|
||||
int ret = stmp_reset_block(i2c->regs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Configure timing for the I2C block. The I2C TIMING2 register has to
|
||||
@ -136,9 +138,11 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
|
||||
*/
|
||||
writel(i2c->timing0, i2c->regs + MXS_I2C_TIMING0);
|
||||
writel(i2c->timing1, i2c->regs + MXS_I2C_TIMING1);
|
||||
writel(0x00300030, i2c->regs + MXS_I2C_TIMING2);
|
||||
writel(i2c->timing2, i2c->regs + MXS_I2C_TIMING2);
|
||||
|
||||
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
|
||||
@ -475,7 +479,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
int stop)
|
||||
{
|
||||
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
|
||||
int ret;
|
||||
int ret, err;
|
||||
int flags;
|
||||
|
||||
flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
|
||||
@ -495,8 +499,11 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
i2c->cmd_err = 0;
|
||||
if (0) { /* disable PIO mode until a proper fix is made */
|
||||
ret = mxs_i2c_pio_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
mxs_i2c_reset(i2c);
|
||||
if (ret) {
|
||||
err = mxs_i2c_reset(i2c);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
INIT_COMPLETION(i2c->cmd_complete);
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
@ -527,7 +534,10 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
timeout:
|
||||
dev_dbg(i2c->dev, "Timeout!\n");
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_reset(i2c);
|
||||
ret = mxs_i2c_reset(i2c);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -577,41 +587,79 @@ static const struct i2c_algorithm mxs_i2c_algo = {
|
||||
.functionality = mxs_i2c_func,
|
||||
};
|
||||
|
||||
static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, int speed)
|
||||
static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, uint32_t speed)
|
||||
{
|
||||
/* The I2C block clock run at 24MHz */
|
||||
/* The I2C block clock runs at 24MHz */
|
||||
const uint32_t clk = 24000000;
|
||||
uint32_t base;
|
||||
uint32_t divider;
|
||||
uint16_t high_count, low_count, rcv_count, xmit_count;
|
||||
uint32_t bus_free, leadin;
|
||||
struct device *dev = i2c->dev;
|
||||
|
||||
if (speed > 540000) {
|
||||
dev_warn(dev, "Speed too high (%d Hz), using 540 kHz\n", speed);
|
||||
speed = 540000;
|
||||
} else if (speed < 12000) {
|
||||
dev_warn(dev, "Speed too low (%d Hz), using 12 kHz\n", speed);
|
||||
speed = 12000;
|
||||
divider = DIV_ROUND_UP(clk, speed);
|
||||
|
||||
if (divider < 25) {
|
||||
/*
|
||||
* limit the divider, so that min(low_count, high_count)
|
||||
* is >= 1
|
||||
*/
|
||||
divider = 25;
|
||||
dev_warn(dev,
|
||||
"Speed too high (%u.%03u kHz), using %u.%03u kHz\n",
|
||||
speed / 1000, speed % 1000,
|
||||
clk / divider / 1000, clk / divider % 1000);
|
||||
} else if (divider > 1897) {
|
||||
/*
|
||||
* limit the divider, so that max(low_count, high_count)
|
||||
* cannot exceed 1023
|
||||
*/
|
||||
divider = 1897;
|
||||
dev_warn(dev,
|
||||
"Speed too low (%u.%03u kHz), using %u.%03u kHz\n",
|
||||
speed / 1000, speed % 1000,
|
||||
clk / divider / 1000, clk / divider % 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
* The timing derivation algorithm. There is no documentation for this
|
||||
* algorithm available, it was derived by using the scope and fiddling
|
||||
* with constants until the result observed on the scope was good enough
|
||||
* for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be
|
||||
* possible to assume the algorithm works for other frequencies as well.
|
||||
* The I2C spec specifies the following timing data:
|
||||
* standard mode fast mode Bitfield name
|
||||
* tLOW (SCL LOW period) 4700 ns 1300 ns
|
||||
* tHIGH (SCL HIGH period) 4000 ns 600 ns
|
||||
* tSU;DAT (data setup time) 250 ns 100 ns
|
||||
* tHD;STA (START hold time) 4000 ns 600 ns
|
||||
* tBUF (bus free time) 4700 ns 1300 ns
|
||||
*
|
||||
* Note it was necessary to cap the frequency on both ends as it's not
|
||||
* possible to configure completely arbitrary frequency for the I2C bus
|
||||
* clock.
|
||||
* The hardware (of the i.MX28 at least) seems to add 2 additional
|
||||
* clock cycles to the low_count and 7 cycles to the high_count.
|
||||
* This is compensated for by subtracting the respective constants
|
||||
* from the values written to the timing registers.
|
||||
*/
|
||||
base = ((clk / speed) - 38) / 2;
|
||||
high_count = base + 3;
|
||||
low_count = base - 3;
|
||||
rcv_count = (high_count * 3) / 4;
|
||||
xmit_count = low_count / 4;
|
||||
if (speed > 100000) {
|
||||
/* fast mode */
|
||||
low_count = DIV_ROUND_CLOSEST(divider * 13, (13 + 6));
|
||||
high_count = DIV_ROUND_CLOSEST(divider * 6, (13 + 6));
|
||||
leadin = DIV_ROUND_UP(600 * (clk / 1000000), 1000);
|
||||
bus_free = DIV_ROUND_UP(1300 * (clk / 1000000), 1000);
|
||||
} else {
|
||||
/* normal mode */
|
||||
low_count = DIV_ROUND_CLOSEST(divider * 47, (47 + 40));
|
||||
high_count = DIV_ROUND_CLOSEST(divider * 40, (47 + 40));
|
||||
leadin = DIV_ROUND_UP(4700 * (clk / 1000000), 1000);
|
||||
bus_free = DIV_ROUND_UP(4700 * (clk / 1000000), 1000);
|
||||
}
|
||||
rcv_count = high_count * 3 / 8;
|
||||
xmit_count = low_count * 3 / 8;
|
||||
|
||||
dev_dbg(dev,
|
||||
"speed=%u(actual %u) divider=%u low=%u high=%u xmit=%u rcv=%u leadin=%u bus_free=%u\n",
|
||||
speed, clk / divider, divider, low_count, high_count,
|
||||
xmit_count, rcv_count, leadin, bus_free);
|
||||
|
||||
low_count -= 2;
|
||||
high_count -= 7;
|
||||
i2c->timing0 = (high_count << 16) | rcv_count;
|
||||
i2c->timing1 = (low_count << 16) | xmit_count;
|
||||
i2c->timing2 = (bus_free << 16 | leadin);
|
||||
}
|
||||
|
||||
static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
||||
@ -683,7 +731,9 @@ static int mxs_i2c_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
/* Do reset to enforce correct startup after pinmuxing */
|
||||
mxs_i2c_reset(i2c);
|
||||
err = mxs_i2c_reset(i2c);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
adap = &i2c->adapter;
|
||||
strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
|
||||
@ -701,8 +751,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/platform_data/i2c-nomadik.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#define DRIVER_NAME "nmk-i2c"
|
||||
@ -943,7 +942,7 @@ static void nmk_i2c_of_probe(struct device_node *np,
|
||||
static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct nmk_i2c_controller *pdata = adev->dev.platform_data;
|
||||
struct nmk_i2c_controller *pdata = dev_get_platdata(&adev->dev);
|
||||
struct device_node *np = adev->dev.of_node;
|
||||
struct nmk_i2c_dev *dev;
|
||||
struct i2c_adapter *adap;
|
||||
@ -1045,8 +1044,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
goto err_add_adap;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return 0;
|
||||
|
@ -525,7 +525,7 @@ static int nuc900_i2c_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/i2c-ocores.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
struct ocores_i2c {
|
||||
@ -353,10 +352,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
@ -365,11 +360,12 @@ static int ocores_i2c_probe(struct platform_device *pdev)
|
||||
if (!i2c)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
i2c->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(i2c->base))
|
||||
return PTR_ERR(i2c->base);
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (pdata) {
|
||||
i2c->reg_shift = pdata->reg_shift;
|
||||
i2c->reg_io_width = pdata->reg_io_width;
|
||||
@ -435,8 +431,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)
|
||||
if (pdata) {
|
||||
for (i = 0; i < pdata->num_devices; i++)
|
||||
i2c_new_device(&i2c->adap, pdata->devices + i);
|
||||
} else {
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -456,7 +450,7 @@ static int ocores_i2c_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ocores_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct ocores_i2c *i2c = dev_get_drvdata(dev);
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
@ -599,8 +598,6 @@ static int octeon_i2c_probe(struct platform_device *pdev)
|
||||
}
|
||||
dev_info(i2c->dev, "version %s\n", DRV_VERSION);
|
||||
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
|
@ -38,12 +38,10 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
/* I2C controller revisions */
|
||||
#define OMAP_I2C_OMAP1_REV_2 0x20
|
||||
@ -216,8 +214,6 @@ struct omap_i2c_dev {
|
||||
u16 syscstate;
|
||||
u16 westate;
|
||||
u16 errata;
|
||||
|
||||
struct pinctrl *pins;
|
||||
};
|
||||
|
||||
static const u8 reg_map_ip_v1[] = {
|
||||
@ -618,11 +614,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
|
||||
if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
|
||||
if (msg->flags & I2C_M_IGNORE_NAK)
|
||||
return 0;
|
||||
if (stop) {
|
||||
w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
|
||||
w |= OMAP_I2C_CON_STP;
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
|
||||
}
|
||||
|
||||
w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
|
||||
w |= OMAP_I2C_CON_STP;
|
||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return -EIO;
|
||||
@ -1079,7 +1074,7 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
struct i2c_adapter *adap;
|
||||
struct resource *mem;
|
||||
const struct omap_i2c_bus_platform_data *pdata =
|
||||
pdev->dev.platform_data;
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
int irq;
|
||||
@ -1120,16 +1115,6 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
|
||||
}
|
||||
|
||||
dev->pins = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(dev->pins)) {
|
||||
if (PTR_ERR(dev->pins) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n",
|
||||
PTR_ERR(dev->pins));
|
||||
dev->pins = NULL;
|
||||
}
|
||||
|
||||
dev->dev = &pdev->dev;
|
||||
dev->irq = irq;
|
||||
|
||||
@ -1245,8 +1230,6 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
|
||||
major, minor, dev->speed);
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
pm_runtime_mark_last_busy(dev->dev);
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
|
||||
|
@ -136,7 +136,7 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
|
||||
struct i2c_pca_pf_data *i2c;
|
||||
struct resource *res;
|
||||
struct i2c_pca9564_pf_platform_data *platform_data =
|
||||
pdev->dev.platform_data;
|
||||
dev_get_platdata(&pdev->dev);
|
||||
int ret = 0;
|
||||
int irq;
|
||||
|
||||
|
@ -231,11 +231,11 @@ static int piix4_setup(struct pci_dev *PIIX4_dev,
|
||||
}
|
||||
|
||||
static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
||||
const struct pci_device_id *id)
|
||||
const struct pci_device_id *id, u8 aux)
|
||||
{
|
||||
unsigned short piix4_smba;
|
||||
unsigned short smba_idx = 0xcd6;
|
||||
u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;
|
||||
u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en;
|
||||
|
||||
/* SB800 and later SMBus does not support forcing address */
|
||||
if (force || force_addr) {
|
||||
@ -245,6 +245,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
smb_en = (aux) ? 0x28 : 0x2c;
|
||||
|
||||
if (!request_region(smba_idx, 2, "smba_idx")) {
|
||||
dev_err(&PIIX4_dev->dev, "SMBus base address index region "
|
||||
"0x%x already in use!\n", smba_idx);
|
||||
@ -272,6 +274,13 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Aux SMBus does not support IRQ information */
|
||||
if (aux) {
|
||||
dev_info(&PIIX4_dev->dev,
|
||||
"SMBus Host Controller at 0x%x\n", piix4_smba);
|
||||
return piix4_smba;
|
||||
}
|
||||
|
||||
/* Request the SMBus I2C bus config region */
|
||||
if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) {
|
||||
dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
|
||||
@ -597,7 +606,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
dev->revision >= 0x40) ||
|
||||
dev->vendor == PCI_VENDOR_ID_AMD)
|
||||
/* base address location etc changed in SB800 */
|
||||
retval = piix4_setup_sb800(dev, id);
|
||||
retval = piix4_setup_sb800(dev, id, 0);
|
||||
else
|
||||
retval = piix4_setup(dev, id);
|
||||
|
||||
@ -611,17 +620,29 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
return retval;
|
||||
|
||||
/* Check for auxiliary SMBus on some AMD chipsets */
|
||||
retval = -ENODEV;
|
||||
|
||||
if (dev->vendor == PCI_VENDOR_ID_ATI &&
|
||||
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
|
||||
dev->revision < 0x40) {
|
||||
retval = piix4_setup_aux(dev, id, 0x58);
|
||||
if (retval > 0) {
|
||||
/* Try to add the aux adapter if it exists,
|
||||
* piix4_add_adapter will clean up if this fails */
|
||||
piix4_add_adapter(dev, retval, &piix4_aux_adapter);
|
||||
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) {
|
||||
if (dev->revision < 0x40) {
|
||||
retval = piix4_setup_aux(dev, id, 0x58);
|
||||
} else {
|
||||
/* SB800 added aux bus too */
|
||||
retval = piix4_setup_sb800(dev, id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) {
|
||||
retval = piix4_setup_sb800(dev, id, 1);
|
||||
}
|
||||
|
||||
if (retval > 0) {
|
||||
/* Try to add the aux adapter if it exists,
|
||||
* piix4_add_adapter will clean up if this fails */
|
||||
piix4_add_adapter(dev, retval, &piix4_aux_adapter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
#define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */
|
||||
#define I2C_PNX_SPEED_KHZ_DEFAULT 100
|
||||
@ -595,7 +594,7 @@ static struct i2c_algorithm pnx_algorithm = {
|
||||
.functionality = i2c_pnx_func,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int i2c_pnx_controller_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
|
||||
@ -727,7 +726,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
|
||||
alg_data->irq = platform_get_irq(pdev, 0);
|
||||
if (alg_data->irq < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get IRQ from platform resource\n");
|
||||
goto out_irq;
|
||||
ret = alg_data->irq;
|
||||
goto out_clock;
|
||||
}
|
||||
ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
|
||||
0, pdev->name, alg_data);
|
||||
@ -741,8 +741,6 @@ static int i2c_pnx_probe(struct platform_device *pdev)
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&alg_data->adapter);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
|
||||
alg_data->adapter.name, res->start, alg_data->irq);
|
||||
|
||||
|
@ -398,7 +398,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap,
|
||||
|
||||
static int i2c_powermac_probe(struct platform_device *dev)
|
||||
{
|
||||
struct pmac_i2c_bus *bus = dev->dev.platform_data;
|
||||
struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev);
|
||||
struct device_node *parent = NULL;
|
||||
struct i2c_adapter *adapter;
|
||||
const char *basename;
|
||||
@ -440,22 +440,24 @@ static int i2c_powermac_probe(struct platform_device *dev)
|
||||
adapter->algo = &i2c_powermac_algorithm;
|
||||
i2c_set_adapdata(adapter, bus);
|
||||
adapter->dev.parent = &dev->dev;
|
||||
adapter->dev.of_node = dev->dev.of_node;
|
||||
|
||||
/* Clear of_node to skip automatic registration of i2c child nodes */
|
||||
adapter->dev.of_node = NULL;
|
||||
rc = i2c_add_adapter(adapter);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "i2c-powermac: Adapter %s registration "
|
||||
"failed\n", adapter->name);
|
||||
memset(adapter, 0, sizeof(*adapter));
|
||||
return rc;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
|
||||
|
||||
/* Cannot use of_i2c_register_devices() due to Apple device-tree
|
||||
* funkyness
|
||||
*/
|
||||
/* Use custom child registration due to Apple device-tree funkyness */
|
||||
adapter->dev.of_node = dev->dev.of_node;
|
||||
i2c_powermac_register_devices(adapter, bus);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver i2c_powermac_driver = {
|
||||
|
@ -245,7 +245,7 @@ static int puv3_i2c_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int puv3_i2c_suspend(struct device *dev)
|
||||
{
|
||||
int poll_count;
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <linux/i2c-pxa.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
@ -110,6 +109,8 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
|
||||
#define ICR_SADIE (1 << 13) /* slave address detected int enable */
|
||||
#define ICR_UR (1 << 14) /* unit reset */
|
||||
#define ICR_FM (1 << 15) /* fast mode */
|
||||
#define ICR_HS (1 << 16) /* High Speed mode */
|
||||
#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */
|
||||
|
||||
#define ISR_RWM (1 << 0) /* read/write mode */
|
||||
#define ISR_ACKNAK (1 << 1) /* ack/nak status */
|
||||
@ -155,6 +156,10 @@ struct pxa_i2c {
|
||||
int irq;
|
||||
unsigned int use_pio :1;
|
||||
unsigned int fast_mode :1;
|
||||
unsigned int high_mode:1;
|
||||
unsigned char master_code;
|
||||
unsigned long rate;
|
||||
bool highmode_enter;
|
||||
};
|
||||
|
||||
#define _IBMR(i2c) ((i2c)->reg_ibmr)
|
||||
@ -459,6 +464,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
|
||||
|
||||
/* set control register values */
|
||||
writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
|
||||
writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
|
||||
|
||||
#ifdef CONFIG_I2C_PXA_SLAVE
|
||||
dev_info(&i2c->adap.dev, "Enabling slave mode\n");
|
||||
@ -680,6 +686,34 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* PXA I2C send master code
|
||||
* 1. Load master code to IDBR and send it.
|
||||
* Note for HS mode, set ICR [GPIOEN].
|
||||
* 2. Wait until win arbitration.
|
||||
*/
|
||||
static int i2c_pxa_send_mastercode(struct pxa_i2c *i2c)
|
||||
{
|
||||
u32 icr;
|
||||
long timeout;
|
||||
|
||||
spin_lock_irq(&i2c->lock);
|
||||
i2c->highmode_enter = true;
|
||||
writel(i2c->master_code, _IDBR(i2c));
|
||||
|
||||
icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
|
||||
icr |= ICR_GPIOEN | ICR_START | ICR_TB | ICR_ITEIE;
|
||||
writel(icr, _ICR(i2c));
|
||||
|
||||
spin_unlock_irq(&i2c->lock);
|
||||
timeout = wait_event_timeout(i2c->wait,
|
||||
i2c->highmode_enter == false, HZ * 1);
|
||||
|
||||
i2c->highmode_enter = false;
|
||||
|
||||
return (timeout == 0) ? I2C_RETRY : 0;
|
||||
}
|
||||
|
||||
static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
|
||||
struct i2c_msg *msg, int num)
|
||||
{
|
||||
@ -743,6 +777,14 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (i2c->high_mode) {
|
||||
ret = i2c_pxa_send_mastercode(i2c);
|
||||
if (ret) {
|
||||
dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(&i2c->lock);
|
||||
|
||||
i2c->msg = msg;
|
||||
@ -990,11 +1032,14 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
|
||||
i2c_pxa_slave_txempty(i2c, isr);
|
||||
if (isr & ISR_IRF)
|
||||
i2c_pxa_slave_rxfull(i2c, isr);
|
||||
} else if (i2c->msg) {
|
||||
} else if (i2c->msg && (!i2c->highmode_enter)) {
|
||||
if (isr & ISR_ITE)
|
||||
i2c_pxa_irq_txempty(i2c, isr);
|
||||
if (isr & ISR_IRF)
|
||||
i2c_pxa_irq_rxfull(i2c, isr);
|
||||
} else if ((isr & ISR_ITE) && i2c->highmode_enter) {
|
||||
i2c->highmode_enter = false;
|
||||
wake_up(&i2c->wait);
|
||||
} else {
|
||||
i2c_pxa_scream_blue_murder(i2c, "spurious irq");
|
||||
}
|
||||
@ -1072,20 +1117,25 @@ static int i2c_pxa_probe_pdata(struct platform_device *pdev,
|
||||
struct pxa_i2c *i2c,
|
||||
enum pxa_i2c_types *i2c_types)
|
||||
{
|
||||
struct i2c_pxa_platform_data *plat = pdev->dev.platform_data;
|
||||
struct i2c_pxa_platform_data *plat = dev_get_platdata(&pdev->dev);
|
||||
const struct platform_device_id *id = platform_get_device_id(pdev);
|
||||
|
||||
*i2c_types = id->driver_data;
|
||||
if (plat) {
|
||||
i2c->use_pio = plat->use_pio;
|
||||
i2c->fast_mode = plat->fast_mode;
|
||||
i2c->high_mode = plat->high_mode;
|
||||
i2c->master_code = plat->master_code;
|
||||
if (!i2c->master_code)
|
||||
i2c->master_code = 0xe;
|
||||
i2c->rate = plat->rate;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_pxa_probe(struct platform_device *dev)
|
||||
{
|
||||
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
|
||||
struct i2c_pxa_platform_data *plat = dev_get_platdata(&dev->dev);
|
||||
enum pxa_i2c_types i2c_type;
|
||||
struct pxa_i2c *i2c;
|
||||
struct resource *res = NULL;
|
||||
@ -1151,6 +1201,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
|
||||
i2c->irq = irq;
|
||||
|
||||
i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
|
||||
i2c->highmode_enter = false;
|
||||
|
||||
if (plat) {
|
||||
#ifdef CONFIG_I2C_PXA_SLAVE
|
||||
@ -1160,6 +1211,16 @@ static int i2c_pxa_probe(struct platform_device *dev)
|
||||
i2c->adap.class = plat->class;
|
||||
}
|
||||
|
||||
if (i2c->high_mode) {
|
||||
if (i2c->rate) {
|
||||
clk_set_rate(i2c->clk, i2c->rate);
|
||||
pr_info("i2c: <%s> set rate to %ld\n",
|
||||
i2c->adap.name, clk_get_rate(i2c->clk));
|
||||
} else
|
||||
pr_warn("i2c: <%s> clock rate not set\n",
|
||||
i2c->adap.name);
|
||||
}
|
||||
|
||||
clk_prepare_enable(i2c->clk);
|
||||
|
||||
if (i2c->use_pio) {
|
||||
@ -1185,7 +1246,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
|
||||
printk(KERN_INFO "I2C: Failed to add bus\n");
|
||||
goto eadapt;
|
||||
}
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
|
||||
platform_set_drvdata(dev, i2c);
|
||||
|
||||
|
@ -101,6 +101,11 @@ enum {
|
||||
#define ID_ARBLOST (1 << 3)
|
||||
#define ID_NACK (1 << 4)
|
||||
|
||||
enum rcar_i2c_type {
|
||||
I2C_RCAR_H1,
|
||||
I2C_RCAR_H2,
|
||||
};
|
||||
|
||||
struct rcar_i2c_priv {
|
||||
void __iomem *io;
|
||||
struct i2c_adapter adap;
|
||||
@ -113,6 +118,7 @@ struct rcar_i2c_priv {
|
||||
int irq;
|
||||
u32 icccr;
|
||||
u32 flags;
|
||||
enum rcar_i2c_type devtype;
|
||||
};
|
||||
|
||||
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
|
||||
@ -224,12 +230,25 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
|
||||
u32 scgd, cdf;
|
||||
u32 round, ick;
|
||||
u32 scl;
|
||||
u32 cdf_width;
|
||||
|
||||
if (!clkp) {
|
||||
dev_err(dev, "there is no peripheral_clk\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
switch (priv->devtype) {
|
||||
case I2C_RCAR_H1:
|
||||
cdf_width = 2;
|
||||
break;
|
||||
case I2C_RCAR_H2:
|
||||
cdf_width = 3;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "device type error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate SCL clock
|
||||
* see
|
||||
@ -245,7 +264,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
|
||||
* clkp : peripheral_clk
|
||||
* F[] : integer up-valuation
|
||||
*/
|
||||
for (cdf = 0; cdf < 4; cdf++) {
|
||||
for (cdf = 0; cdf < (1 << cdf_width); cdf++) {
|
||||
ick = clk_get_rate(clkp) / (1 + cdf);
|
||||
if (ick < 20000000)
|
||||
goto ick_find;
|
||||
@ -287,7 +306,7 @@ scgd_find:
|
||||
/*
|
||||
* keep icccr value
|
||||
*/
|
||||
priv->icccr = (scgd << 2 | cdf);
|
||||
priv->icccr = (scgd << (cdf_width) | cdf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -615,7 +634,7 @@ static const struct i2c_algorithm rcar_i2c_algo = {
|
||||
|
||||
static int rcar_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_rcar_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct i2c_rcar_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct rcar_i2c_priv *priv;
|
||||
struct i2c_adapter *adap;
|
||||
struct resource *res;
|
||||
@ -632,6 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
||||
bus_speed = 100000; /* default 100 kHz */
|
||||
if (pdata && pdata->bus_speed)
|
||||
bus_speed = pdata->bus_speed;
|
||||
|
||||
priv->devtype = platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -686,6 +708,14 @@ static int rcar_i2c_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id rcar_i2c_id_table[] = {
|
||||
{ "i2c-rcar", I2C_RCAR_H1 },
|
||||
{ "i2c-rcar_h1", I2C_RCAR_H1 },
|
||||
{ "i2c-rcar_h2", I2C_RCAR_H2 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table);
|
||||
|
||||
static struct platform_driver rcar_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "i2c-rcar",
|
||||
@ -693,6 +723,7 @@ static struct platform_driver rcar_i2c_driver = {
|
||||
},
|
||||
.probe = rcar_i2c_probe,
|
||||
.remove = rcar_i2c_remove,
|
||||
.id_table = rcar_i2c_id_table,
|
||||
};
|
||||
|
||||
module_platform_driver(rcar_i2c_driver);
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
@ -1033,7 +1032,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node) {
|
||||
pdata = pdev->dev.platform_data;
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
@ -1154,7 +1153,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
@ -290,8 +290,9 @@ static int s6i2c_probe(struct platform_device *dev)
|
||||
|
||||
clock = 0;
|
||||
bus_num = -1;
|
||||
if (dev->dev.platform_data) {
|
||||
struct s6_i2c_platform_data *pdata = dev->dev.platform_data;
|
||||
if (dev_get_platdata(&dev->dev)) {
|
||||
struct s6_i2c_platform_data *pdata =
|
||||
dev_get_platdata(&dev->dev);
|
||||
bus_num = pdata->bus_num;
|
||||
clock = pdata->clock;
|
||||
}
|
||||
|
@ -437,7 +437,7 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
|
||||
struct cami2c *id;
|
||||
int ret;
|
||||
|
||||
pd = pdev->dev.platform_data;
|
||||
pd = dev_get_platdata(&pdev->dev);
|
||||
if (!pd) {
|
||||
dev_err(&pdev->dev, "no platform_data!\n");
|
||||
ret = -ENODEV;
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/clk.h>
|
||||
@ -658,7 +657,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
|
||||
|
||||
static int sh_mobile_i2c_probe(struct platform_device *dev)
|
||||
{
|
||||
struct i2c_sh_mobile_platform_data *pdata = dev->dev.platform_data;
|
||||
struct i2c_sh_mobile_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
struct sh_mobile_i2c_data *pd;
|
||||
struct i2c_adapter *adap;
|
||||
struct resource *res;
|
||||
@ -758,7 +757,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
|
||||
"I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
|
||||
adap->nr, pd->bus_speed, pd->iccl, pd->icch);
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
return 0;
|
||||
|
||||
err_all:
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
@ -65,6 +64,8 @@
|
||||
#define SIRFSOC_I2C_START BIT(7)
|
||||
|
||||
#define SIRFSOC_I2C_DEFAULT_SPEED 100000
|
||||
#define SIRFSOC_I2C_ERR_NOACK 1
|
||||
#define SIRFSOC_I2C_ERR_TIMEOUT 2
|
||||
|
||||
struct sirfsoc_i2c {
|
||||
void __iomem *base;
|
||||
@ -143,14 +144,24 @@ static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id)
|
||||
|
||||
if (i2c_stat & SIRFSOC_I2C_STAT_ERR) {
|
||||
/* Error conditions */
|
||||
siic->err_status = 1;
|
||||
siic->err_status = SIRFSOC_I2C_ERR_NOACK;
|
||||
writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS);
|
||||
|
||||
if (i2c_stat & SIRFSOC_I2C_STAT_NACK)
|
||||
dev_err(&siic->adapter.dev, "ACK not received\n");
|
||||
dev_dbg(&siic->adapter.dev, "ACK not received\n");
|
||||
else
|
||||
dev_err(&siic->adapter.dev, "I2C error\n");
|
||||
|
||||
/*
|
||||
* Due to hardware ANOMALY, we need to reset I2C earlier after
|
||||
* we get NOACK while accessing non-existing clients, otherwise
|
||||
* we will get errors even we access existing clients later
|
||||
*/
|
||||
writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET,
|
||||
siic->base + SIRFSOC_I2C_CTRL);
|
||||
while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
|
||||
cpu_relax();
|
||||
|
||||
complete(&siic->done);
|
||||
} else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) {
|
||||
/* CMD buffer execution complete */
|
||||
@ -183,6 +194,10 @@ static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic,
|
||||
if (msg->flags & I2C_M_RD)
|
||||
addr |= 1;
|
||||
|
||||
/* Reverse direction bit */
|
||||
if (msg->flags & I2C_M_REV_DIR_ADDR)
|
||||
addr ^= 1;
|
||||
|
||||
writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
|
||||
}
|
||||
|
||||
@ -191,7 +206,6 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg)
|
||||
u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL);
|
||||
/* timeout waiting for the xfer to finish or fail */
|
||||
int timeout = msecs_to_jiffies((msg->len + 1) * 50);
|
||||
int ret = 0;
|
||||
|
||||
i2c_sirfsoc_set_address(siic, msg);
|
||||
|
||||
@ -200,7 +214,7 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg)
|
||||
i2c_sirfsoc_queue_cmd(siic);
|
||||
|
||||
if (wait_for_completion_timeout(&siic->done, timeout) == 0) {
|
||||
siic->err_status = 1;
|
||||
siic->err_status = SIRFSOC_I2C_ERR_TIMEOUT;
|
||||
dev_err(&siic->adapter.dev, "Transfer timeout\n");
|
||||
}
|
||||
|
||||
@ -208,16 +222,14 @@ static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg)
|
||||
siic->base + SIRFSOC_I2C_CTRL);
|
||||
writel(0, siic->base + SIRFSOC_I2C_CMD_START);
|
||||
|
||||
if (siic->err_status) {
|
||||
/* i2c control doesn't response, reset it */
|
||||
if (siic->err_status == SIRFSOC_I2C_ERR_TIMEOUT) {
|
||||
writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET,
|
||||
siic->base + SIRFSOC_I2C_CTRL);
|
||||
while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
|
||||
cpu_relax();
|
||||
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return siic->err_status ? -EAGAIN : 0;
|
||||
}
|
||||
|
||||
static u32 i2c_sirfsoc_func(struct i2c_adapter *adap)
|
||||
@ -321,6 +333,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
|
||||
|
||||
adap->algo = &i2c_sirfsoc_algo;
|
||||
adap->algo_data = siic;
|
||||
adap->retries = 3;
|
||||
|
||||
adap->dev.of_node = pdev->dev.of_node;
|
||||
adap->dev.parent = &pdev->dev;
|
||||
@ -348,7 +361,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
|
||||
|
||||
if (bitrate < 100000)
|
||||
regval =
|
||||
(2 * ctrl_speed) / (2 * bitrate * 11);
|
||||
(2 * ctrl_speed) / (bitrate * 11);
|
||||
else
|
||||
regval = ctrl_speed / (bitrate * 5);
|
||||
|
||||
@ -366,8 +379,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
|
||||
|
||||
clk_disable(clk);
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
dev_info(&pdev->dev, " I2C adapter ready to operate\n");
|
||||
|
||||
return 0;
|
||||
@ -416,6 +427,8 @@ static int i2c_sirfsoc_resume(struct device *dev)
|
||||
|
||||
clk_enable(siic->clk);
|
||||
writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
|
||||
while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
|
||||
cpu_relax();
|
||||
writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE,
|
||||
siic->base + SIRFSOC_I2C_CTRL);
|
||||
writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL);
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
/* the name of this kernel module */
|
||||
#define NAME "stu300"
|
||||
@ -884,9 +883,6 @@ stu300_probe(struct platform_device *pdev)
|
||||
|
||||
dev->pdev = pdev;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENOENT;
|
||||
|
||||
dev->virtbase = devm_ioremap_resource(&pdev->dev, res);
|
||||
dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual "
|
||||
"base %p\n", bus_nr, dev->virtbase);
|
||||
@ -936,12 +932,11 @@ stu300_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, dev);
|
||||
dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",
|
||||
dev->virtbase, dev->irq);
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int stu300_suspend(struct device *device)
|
||||
{
|
||||
struct stu300_dev *dev = dev_get_drvdata(device);
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
@ -802,8 +801,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&i2c_dev->adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -54,12 +54,16 @@ static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||
|
||||
static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
||||
{
|
||||
unsigned char status;
|
||||
unsigned char *pstatus;
|
||||
struct i2c_msg *pmsg;
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
dev_dbg(&adapter->dev, "master xfer %d messages:\n", num);
|
||||
|
||||
pstatus = kmalloc(sizeof(*pstatus), GFP_KERNEL);
|
||||
if (!pstatus)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0 ; i < num ; i++) {
|
||||
int cmd = CMD_I2C_IO;
|
||||
|
||||
@ -84,7 +88,8 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
||||
pmsg->buf, pmsg->len) != pmsg->len) {
|
||||
dev_err(&adapter->dev,
|
||||
"failure reading data\n");
|
||||
return -EREMOTEIO;
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* write data */
|
||||
@ -93,36 +98,50 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
||||
pmsg->buf, pmsg->len) != pmsg->len) {
|
||||
dev_err(&adapter->dev,
|
||||
"failure writing data\n");
|
||||
return -EREMOTEIO;
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* read status */
|
||||
if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) {
|
||||
if (usb_read(adapter, CMD_GET_STATUS, 0, 0, pstatus, 1) != 1) {
|
||||
dev_err(&adapter->dev, "failure reading status\n");
|
||||
return -EREMOTEIO;
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(&adapter->dev, " status = %d\n", status);
|
||||
if (status == STATUS_ADDRESS_NAK)
|
||||
return -EREMOTEIO;
|
||||
dev_dbg(&adapter->dev, " status = %d\n", *pstatus);
|
||||
if (*pstatus == STATUS_ADDRESS_NAK) {
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
ret = i;
|
||||
out:
|
||||
kfree(pstatus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 usb_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
__le32 func;
|
||||
__le32 *pfunc;
|
||||
u32 ret;
|
||||
|
||||
pfunc = kmalloc(sizeof(*pfunc), GFP_KERNEL);
|
||||
|
||||
/* get functionality from adapter */
|
||||
if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) !=
|
||||
sizeof(func)) {
|
||||
if (!pfunc || usb_read(adapter, CMD_GET_FUNC, 0, 0, pfunc,
|
||||
sizeof(*pfunc)) != sizeof(*pfunc)) {
|
||||
dev_err(&adapter->dev, "failure reading functionality\n");
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return le32_to_cpu(func);
|
||||
ret = le32_to_cpup(pfunc);
|
||||
out:
|
||||
kfree(pfunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This is the actual algorithm we define */
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
#define I2C_CONTROL 0x00
|
||||
#define I2C_CONTROLS 0x00
|
||||
@ -108,7 +107,6 @@ static int i2c_versatile_probe(struct platform_device *dev)
|
||||
ret = i2c_bit_add_numbered_bus(&i2c->adap);
|
||||
if (ret >= 0) {
|
||||
platform_set_drvdata(dev, i2c);
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
@ -439,8 +438,6 @@ static int wmt_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, i2c_dev);
|
||||
|
||||
of_i2c_register_devices(adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <linux/i2c-xiic.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
#define DRIVER_NAME "xiic-i2c"
|
||||
|
||||
@ -703,7 +702,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
goto resource_missing;
|
||||
|
||||
pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
|
||||
pdata = (struct xiic_i2c_platform_data *)dev_get_platdata(&pdev->dev);
|
||||
|
||||
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
|
||||
if (!i2c)
|
||||
@ -752,8 +751,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
|
||||
i2c_new_device(&i2c->adap, pdata->devices + i);
|
||||
}
|
||||
|
||||
of_i2c_register_devices(&i2c->adap);
|
||||
|
||||
return 0;
|
||||
|
||||
add_adapter_failed:
|
||||
|
@ -23,7 +23,11 @@
|
||||
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
Mux support by Rodolfo Giometti <giometti@enneenne.com> and
|
||||
Michael Lawnick <michael.lawnick.ext@nsn.com> */
|
||||
Michael Lawnick <michael.lawnick.ext@nsn.com>
|
||||
OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
|
||||
(based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
|
||||
(c) 2013 Wolfram Sang <wsa@the-dreams.de>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -35,7 +39,9 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/irqflags.h>
|
||||
@ -954,6 +960,194 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
|
||||
up_read(&__i2c_board_lock);
|
||||
}
|
||||
|
||||
/* OF support code */
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static void of_i2c_register_devices(struct i2c_adapter *adap)
|
||||
{
|
||||
void *result;
|
||||
struct device_node *node;
|
||||
|
||||
/* Only register child devices if the adapter has a node pointer set */
|
||||
if (!adap->dev.of_node)
|
||||
return;
|
||||
|
||||
dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
|
||||
|
||||
for_each_available_child_of_node(adap->dev.of_node, node) {
|
||||
struct i2c_board_info info = {};
|
||||
struct dev_archdata dev_ad = {};
|
||||
const __be32 *addr;
|
||||
int len;
|
||||
|
||||
dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
|
||||
|
||||
if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
|
||||
dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
|
||||
node->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = of_get_property(node, "reg", &len);
|
||||
if (!addr || (len < sizeof(int))) {
|
||||
dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
|
||||
node->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
info.addr = be32_to_cpup(addr);
|
||||
if (info.addr > (1 << 10) - 1) {
|
||||
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
|
||||
info.addr, node->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
info.irq = irq_of_parse_and_map(node, 0);
|
||||
info.of_node = of_node_get(node);
|
||||
info.archdata = &dev_ad;
|
||||
|
||||
if (of_get_property(node, "wakeup-source", NULL))
|
||||
info.flags |= I2C_CLIENT_WAKE;
|
||||
|
||||
request_module("%s%s", I2C_MODULE_PREFIX, info.type);
|
||||
|
||||
result = i2c_new_device(adap, &info);
|
||||
if (result == NULL) {
|
||||
dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
|
||||
node->full_name);
|
||||
of_node_put(node);
|
||||
irq_dispose_mapping(info.irq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int of_dev_node_match(struct device *dev, void *data)
|
||||
{
|
||||
return dev->of_node == data;
|
||||
}
|
||||
|
||||
/* must call put_device() when done with returned i2c_client device */
|
||||
struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device(&i2c_bus_type, NULL, node,
|
||||
of_dev_node_match);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
return i2c_verify_client(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(of_find_i2c_device_by_node);
|
||||
|
||||
/* must call put_device() when done with returned i2c_adapter device */
|
||||
struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device(&i2c_bus_type, NULL, node,
|
||||
of_dev_node_match);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
return i2c_verify_adapter(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
|
||||
#else
|
||||
static void of_i2c_register_devices(struct i2c_adapter *adap) { }
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
/* ACPI support code */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct i2c_board_info *info = data;
|
||||
|
||||
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||
struct acpi_resource_i2c_serialbus *sb;
|
||||
|
||||
sb = &ares->data.i2c_serial_bus;
|
||||
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
||||
info->addr = sb->slave_address;
|
||||
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
|
||||
info->flags |= I2C_CLIENT_TEN;
|
||||
}
|
||||
} else if (info->irq < 0) {
|
||||
struct resource r;
|
||||
|
||||
if (acpi_dev_resource_interrupt(ares, 0, &r))
|
||||
info->irq = r.start;
|
||||
}
|
||||
|
||||
/* Tell the ACPI core to skip this resource */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
|
||||
void *data, void **return_value)
|
||||
{
|
||||
struct i2c_adapter *adapter = data;
|
||||
struct list_head resource_list;
|
||||
struct i2c_board_info info;
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
|
||||
if (acpi_bus_get_device(handle, &adev))
|
||||
return AE_OK;
|
||||
if (acpi_bus_get_status(adev) || !adev->status.present)
|
||||
return AE_OK;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.acpi_node.handle = handle;
|
||||
info.irq = -1;
|
||||
|
||||
INIT_LIST_HEAD(&resource_list);
|
||||
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||
acpi_i2c_add_resource, &info);
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (ret < 0 || !info.addr)
|
||||
return AE_OK;
|
||||
|
||||
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
|
||||
if (!i2c_new_device(adapter, &info)) {
|
||||
dev_err(&adapter->dev,
|
||||
"failed to add I2C device %s from ACPI\n",
|
||||
dev_name(&adev->dev));
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
|
||||
* @adap: pointer to adapter
|
||||
*
|
||||
* Enumerate all I2C slave devices behind this adapter by walking the ACPI
|
||||
* namespace. When a device is found it will be added to the Linux device
|
||||
* model and bound to the corresponding ACPI handle.
|
||||
*/
|
||||
static void acpi_i2c_register_devices(struct i2c_adapter *adap)
|
||||
{
|
||||
acpi_handle handle;
|
||||
acpi_status status;
|
||||
|
||||
handle = ACPI_HANDLE(adap->dev.parent);
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
||||
acpi_i2c_add_device, NULL,
|
||||
adap, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
|
||||
}
|
||||
#else
|
||||
static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static int i2c_do_add_adapter(struct i2c_driver *driver,
|
||||
struct i2c_adapter *adap)
|
||||
{
|
||||
@ -1058,6 +1252,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
||||
|
||||
exit_recovery:
|
||||
/* create pre-declared device nodes */
|
||||
of_i2c_register_devices(adap);
|
||||
acpi_i2c_register_devices(adap);
|
||||
|
||||
if (adap->nr < __i2c_first_dynamic_bus_num)
|
||||
i2c_scan_static_board_info(adap);
|
||||
|
||||
@ -1282,7 +1479,6 @@ void i2c_del_adapter(struct i2c_adapter *adap)
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_del_adapter);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
|
||||
@ -1665,7 +1861,8 @@ static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)
|
||||
err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
|
||||
I2C_SMBUS_BYTE, &dummy);
|
||||
else {
|
||||
dev_warn(&adap->dev, "No suitable probing method supported\n");
|
||||
dev_warn(&adap->dev, "No suitable probing method supported for address 0x%02X\n",
|
||||
addr);
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -1825,7 +2022,8 @@ EXPORT_SYMBOL(i2c_get_adapter);
|
||||
|
||||
void i2c_put_adapter(struct i2c_adapter *adap)
|
||||
{
|
||||
module_put(adap->owner);
|
||||
if (adap)
|
||||
module_put(adap->owner);
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_put_adapter);
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
|
||||
/* multiplexer per channel data */
|
||||
struct i2c_mux_priv {
|
||||
@ -185,8 +184,6 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
|
||||
dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
|
||||
i2c_adapter_id(&priv->adap));
|
||||
|
||||
of_i2c_register_devices(&priv->adap);
|
||||
|
||||
return &priv->adap;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
|
||||
|
@ -137,7 +137,7 @@ static irqreturn_t smbalert_irq(int irq, void *d)
|
||||
static int smbalert_probe(struct i2c_client *ara,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_smbus_alert_setup *setup = ara->dev.platform_data;
|
||||
struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
|
||||
struct i2c_smbus_alert *alert;
|
||||
struct i2c_adapter *adapter = ara->adapter;
|
||||
int res;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
@ -131,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "Cannot find device tree node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (dev->platform_data) {
|
||||
if (dev_get_platdata(dev)) {
|
||||
dev_err(dev, "Platform data is not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
struct gpiomux {
|
||||
@ -148,12 +147,14 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, mux);
|
||||
|
||||
if (!pdev->dev.platform_data) {
|
||||
if (!dev_get_platdata(&pdev->dev)) {
|
||||
ret = i2c_mux_gpio_probe_dt(mux, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else
|
||||
memcpy(&mux->data, pdev->dev.platform_data, sizeof(mux->data));
|
||||
} else {
|
||||
memcpy(&mux->data, dev_get_platdata(&pdev->dev),
|
||||
sizeof(mux->data));
|
||||
}
|
||||
|
||||
/*
|
||||
* If a GPIO chip name is provided, the GPIO pin numbers provided are
|
||||
|
@ -324,7 +324,7 @@ static int pca9541_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct pca954x_platform_data *pdata = client->dev.platform_data;
|
||||
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct pca9541 *data;
|
||||
int force;
|
||||
int ret = -ENODEV;
|
||||
|
@ -185,7 +185,7 @@ static int pca954x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
|
||||
struct pca954x_platform_data *pdata = client->dev.platform_data;
|
||||
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
int num, force, class;
|
||||
struct pca954x *data;
|
||||
int ret = -ENODEV;
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/i2c-mux-pinctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -145,7 +144,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
|
||||
|
||||
mux->dev = &pdev->dev;
|
||||
|
||||
mux->pdata = pdev->dev.platform_data;
|
||||
mux->pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!mux->pdata) {
|
||||
ret = i2c_mux_pinctrl_parse_dt(mux, pdev);
|
||||
if (ret < 0)
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
@ -67,8 +67,6 @@ static int fimc_is_i2c_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_enable(&i2c_adap->dev);
|
||||
|
||||
of_i2c_register_devices(i2c_adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -48,12 +48,6 @@ config OF_IRQ
|
||||
def_bool y
|
||||
depends on !SPARC
|
||||
|
||||
config OF_I2C
|
||||
def_tristate I2C
|
||||
depends on I2C
|
||||
help
|
||||
OpenFirmware I2C accessors
|
||||
|
||||
config OF_NET
|
||||
depends on NETDEVICES
|
||||
def_bool y
|
||||
|
@ -3,7 +3,6 @@ obj-$(CONFIG_OF_FLATTREE) += fdt.o
|
||||
obj-$(CONFIG_OF_PROMTREE) += pdt.o
|
||||
obj-$(CONFIG_OF_ADDRESS) += address.o
|
||||
obj-$(CONFIG_OF_IRQ) += irq.o
|
||||
obj-$(CONFIG_OF_I2C) += of_i2c.o
|
||||
obj-$(CONFIG_OF_NET) += of_net.o
|
||||
obj-$(CONFIG_OF_SELFTEST) += selftest.o
|
||||
obj-$(CONFIG_OF_MDIO) += of_mdio.o
|
||||
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* OF helpers for the I2C API
|
||||
*
|
||||
* Copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
|
||||
*
|
||||
* Based on a previous patch from Jon Smirl <jonsmirl@gmail.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/i2c.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
void of_i2c_register_devices(struct i2c_adapter *adap)
|
||||
{
|
||||
void *result;
|
||||
struct device_node *node;
|
||||
|
||||
/* Only register child devices if the adapter has a node pointer set */
|
||||
if (!adap->dev.of_node)
|
||||
return;
|
||||
|
||||
dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
|
||||
|
||||
for_each_available_child_of_node(adap->dev.of_node, node) {
|
||||
struct i2c_board_info info = {};
|
||||
struct dev_archdata dev_ad = {};
|
||||
const __be32 *addr;
|
||||
int len;
|
||||
|
||||
dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
|
||||
|
||||
if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
|
||||
dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
|
||||
node->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = of_get_property(node, "reg", &len);
|
||||
if (!addr || (len < sizeof(int))) {
|
||||
dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
|
||||
node->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
info.addr = be32_to_cpup(addr);
|
||||
if (info.addr > (1 << 10) - 1) {
|
||||
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
|
||||
info.addr, node->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
info.irq = irq_of_parse_and_map(node, 0);
|
||||
info.of_node = of_node_get(node);
|
||||
info.archdata = &dev_ad;
|
||||
|
||||
if (of_get_property(node, "wakeup-source", NULL))
|
||||
info.flags |= I2C_CLIENT_WAKE;
|
||||
|
||||
request_module("%s%s", I2C_MODULE_PREFIX, info.type);
|
||||
|
||||
result = i2c_new_device(adap, &info);
|
||||
if (result == NULL) {
|
||||
dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
|
||||
node->full_name);
|
||||
of_node_put(node);
|
||||
irq_dispose_mapping(info.irq);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(of_i2c_register_devices);
|
||||
|
||||
static int of_dev_node_match(struct device *dev, void *data)
|
||||
{
|
||||
return dev->of_node == data;
|
||||
}
|
||||
|
||||
/* must call put_device() when done with returned i2c_client device */
|
||||
struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device(&i2c_bus_type, NULL, node,
|
||||
of_dev_node_match);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
return i2c_verify_client(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(of_find_i2c_device_by_node);
|
||||
|
||||
/* must call put_device() when done with returned i2c_adapter device */
|
||||
struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device(&i2c_bus_type, NULL, node,
|
||||
of_dev_node_match);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
return i2c_verify_adapter(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
@ -21,7 +21,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -447,11 +447,13 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
|
||||
static inline struct i2c_adapter *
|
||||
i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
|
||||
{
|
||||
#if IS_ENABLED(I2C_MUX)
|
||||
struct device *parent = adapter->dev.parent;
|
||||
|
||||
if (parent != NULL && parent->type == &i2c_adapter_type)
|
||||
return to_i2c_adapter(parent);
|
||||
else
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -542,10 +544,24 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
|
||||
|
||||
#endif /* I2C */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI_I2C)
|
||||
extern void acpi_i2c_register_devices(struct i2c_adapter *adap);
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
/* must call put_device() when done with returned i2c_client device */
|
||||
extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
|
||||
|
||||
/* must call put_device() when done with returned i2c_adapter device */
|
||||
extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
|
||||
|
||||
#else
|
||||
static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
|
||||
#endif
|
||||
|
||||
static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#endif /* _LINUX_I2C_H */
|
||||
|
@ -67,6 +67,9 @@ struct i2c_pxa_platform_data {
|
||||
unsigned int class;
|
||||
unsigned int use_pio :1;
|
||||
unsigned int fast_mode :1;
|
||||
unsigned int high_mode:1;
|
||||
unsigned char master_code;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
||||
extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Generic I2C API implementation for PowerPC.
|
||||
*
|
||||
* Copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_OF_I2C_H
|
||||
#define __LINUX_OF_I2C_H
|
||||
|
||||
#if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE)
|
||||
#include <linux/i2c.h>
|
||||
|
||||
extern void of_i2c_register_devices(struct i2c_adapter *adap);
|
||||
|
||||
/* must call put_device() when done with returned i2c_client device */
|
||||
extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
|
||||
|
||||
/* must call put_device() when done with returned i2c_adapter device */
|
||||
extern struct i2c_adapter *of_find_i2c_adapter_by_node(
|
||||
struct device_node *node);
|
||||
|
||||
#else
|
||||
static inline void of_i2c_register_devices(struct i2c_adapter *adap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* must call put_device() when done with returned i2c_adapter device */
|
||||
static inline struct i2c_adapter *of_find_i2c_adapter_by_node(
|
||||
struct device_node *node)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_OF_I2C */
|
||||
|
||||
#endif /* __LINUX_OF_I2C_H */
|
@ -13,7 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/clk.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <sound/soc.h>
|
||||
|
Loading…
Reference in New Issue
Block a user