Commit 02d0a752 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:
 "For 3.14, the I2C subsystem has the following to offer:

   - new drivers for Renesas RIIC and RobotFuzz OSIF
   - driver cleanups & improvements & bugfixes

  Pretty standard stuff this time, I'd say.  There is more complex stuff
  coming up, but I didn't have the bandwidth between the years to pull
  it in for this release.  Sadly"

* 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (26 commits)
  i2c: s3c2410: fix quirk usage for 64-bit
  i2c: pnx: Use devm_*() functions
  i2c: at91: add a new compatibility string for the at91sam9261
  i2c-ismt: support I2C_SMBUS_I2C_BLOCK_DATA transaction type
  i2c: Add bus driver for for OSIF USB i2c device.
  i2c: i2c-tiny-usb: Remove RobotFuzz USB vendor:product ID
  i2c: designware: remove HAVE_CLK build dependecy
  Documentation: i2c: Remove obsolete example
  i2c: nomadik: remove platform data header
  i2c: nomadik: auto-calculate slave setup time
  i2c: viperboard: remove superfluous assignment
  i2c: xilinx: Use devm_* functions
  i2c: xilinx: Do not enable irq before irq handler
  i2c: xilinx: Fix i2c checkpatch warnings
  i2c: at91: document clock properties
  i2c: isch: Use devm_request_region()
  i2c: viperboard: Use devm_kzalloc() functions
  i2c: imx: propagate irq error code in probe
  i2c: s3c2410: dont need CPU_FREQ transitions for exynos series
  i2c: s3c2410: Add polling mode support
  ...
parents fb2e2c85 5f1b1155
...@@ -9,6 +9,7 @@ Required properties : ...@@ -9,6 +9,7 @@ Required properties :
- interrupts: interrupt number to the cpu. - interrupts: interrupt number to the cpu.
- #address-cells = <1>; - #address-cells = <1>;
- #size-cells = <0>; - #size-cells = <0>;
- clocks: phandles to input clocks.
Optional properties: Optional properties:
- Child nodes conforming to i2c bus binding - Child nodes conforming to i2c bus binding
...@@ -21,6 +22,7 @@ i2c0: i2c@fff84000 { ...@@ -21,6 +22,7 @@ i2c0: i2c@fff84000 {
interrupts = <12 4 6>; interrupts = <12 4 6>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
clocks = <&twi0_clk>;
24c512@50 { 24c512@50 {
compatible = "24c512"; compatible = "24c512";
......
* NXP PCA954x I2C bus switch
Required Properties:
- compatible: Must contain one of the following.
"nxp,pca9540", "nxp,pca9542", "nxp,pca9543", "nxp,pca9544",
"nxp,pca9545", "nxp,pca9546", "nxp,pca9547", "nxp,pca9548"
- reg: The I2C address of the device.
The following required properties are defined externally:
- Standard I2C mux properties. See i2c-mux.txt in this directory.
- I2C child bus nodes. See i2c-mux.txt in this directory.
Optional Properties:
- reset-gpios: Reference to the GPIO connected to the reset input.
Example:
i2c-switch@74 {
compatible = "nxp,pca9548";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x74>;
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
eeprom@54 {
compatible = "at,24c08";
reg = <0x54>;
};
};
i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
rtc@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
};
};
};
Device tree configuration for Renesas RIIC driver
Required properties:
- compatible : "renesas,riic-<soctype>". "renesas,riic-rz" as fallback
- reg : address start and address range size of device
- interrupts : 8 interrupts (TEI, RI, TI, SPI, STI, NAKI, ALI, TMOI)
- clock-frequency : frequency of bus clock in Hz
- #address-cells : should be <1>
- #size-cells : should be <0>
Pinctrl properties might be needed, too. See there.
Example:
i2c0: i2c@fcfee000 {
compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
reg = <0xfcfee000 0x44>;
interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>,
<0 158 IRQ_TYPE_EDGE_RISING>,
<0 159 IRQ_TYPE_EDGE_RISING>,
<0 160 IRQ_TYPE_LEVEL_HIGH>,
<0 161 IRQ_TYPE_LEVEL_HIGH>,
<0 162 IRQ_TYPE_LEVEL_HIGH>,
<0 163 IRQ_TYPE_LEVEL_HIGH>,
<0 164 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
};
...@@ -10,6 +10,8 @@ Required properties: ...@@ -10,6 +10,8 @@ Required properties:
inside HDMIPHY block found on several samsung SoCs inside HDMIPHY block found on several samsung SoCs
(d) "samsung, exynos5440-i2c", for s3c2440-like i2c used (d) "samsung, exynos5440-i2c", for s3c2440-like i2c used
on EXYNOS5440 which does not need GPIO configuration. on EXYNOS5440 which does not need GPIO configuration.
(e) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
a host to SATA PHY controller on an internal bus.
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- interrupts: interrupt number to the cpu. - interrupts: interrupt number to the cpu.
......
...@@ -64,9 +64,6 @@ EINVAL ...@@ -64,9 +64,6 @@ EINVAL
detected before any I/O operation was started. Use a more detected before any I/O operation was started. Use a more
specific fault code when you can. specific fault code when you can.
One example would be a driver trying an SMBus Block Write
with block size outside the range of 1-32 bytes.
EIO EIO
This rather vague error means something went wrong when This rather vague error means something went wrong when
performing an I/O operation. Use a more specific fault performing an I/O operation. Use a more specific fault
......
...@@ -412,7 +412,6 @@ config I2C_DESIGNWARE_CORE ...@@ -412,7 +412,6 @@ config I2C_DESIGNWARE_CORE
config I2C_DESIGNWARE_PLATFORM config I2C_DESIGNWARE_PLATFORM
tristate "Synopsys DesignWare Platform" tristate "Synopsys DesignWare Platform"
depends on HAVE_CLK
select I2C_DESIGNWARE_CORE select I2C_DESIGNWARE_CORE
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
...@@ -648,6 +647,16 @@ config I2C_PXA_SLAVE ...@@ -648,6 +647,16 @@ config I2C_PXA_SLAVE
is necessary for systems where the PXA may be a target on the is necessary for systems where the PXA may be a target on the
I2C bus. I2C bus.
config I2C_RIIC
tristate "Renesas RIIC adapter"
depends on ARCH_SHMOBILE || COMPILE_TEST
help
If you say yes to this option, support will be included for the
Renesas RIIC I2C interface.
This driver can also be built as a module. If so, the module
will be called i2c-riic.
config HAVE_S3C2410_I2C config HAVE_S3C2410_I2C
bool bool
help help
...@@ -683,7 +692,7 @@ config I2C_SH7760 ...@@ -683,7 +692,7 @@ config I2C_SH7760
config I2C_SH_MOBILE config I2C_SH_MOBILE
tristate "SuperH Mobile I2C Controller" tristate "SuperH Mobile I2C Controller"
depends on SUPERH || ARM || COMPILE_TEST depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
built-in I2C interface on the Renesas SH-Mobile processor. built-in I2C interface on the Renesas SH-Mobile processor.
...@@ -796,7 +805,7 @@ config I2C_XLR ...@@ -796,7 +805,7 @@ config I2C_XLR
config I2C_RCAR config I2C_RCAR
tristate "Renesas R-Car I2C Controller" tristate "Renesas R-Car I2C Controller"
depends on ARM || COMPILE_TEST depends on ARCH_SHMOBILE || COMPILE_TEST
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
R-Car I2C controller. R-Car I2C controller.
...@@ -865,6 +874,16 @@ config I2C_PARPORT_LIGHT ...@@ -865,6 +874,16 @@ config I2C_PARPORT_LIGHT
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-parport-light. will be called i2c-parport-light.
config I2C_ROBOTFUZZ_OSIF
tristate "RobotFuzz Open Source InterFace USB adapter"
depends on USB
help
If you say yes to this option, support will be included for the
RobotFuzz Open Source InterFace USB to I2C interface.
This driver can also be built as a module. If so, the module
will be called i2c-osif.
config I2C_TAOS_EVM config I2C_TAOS_EVM
tristate "TAOS evaluation module" tristate "TAOS evaluation module"
depends on TTY depends on TTY
......
...@@ -63,6 +63,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o ...@@ -63,6 +63,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_S6000) += i2c-s6000.o obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
...@@ -83,6 +84,7 @@ obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o ...@@ -83,6 +84,7 @@ obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_ROBOTFUZZ_OSIF) += i2c-robotfuzz-osif.o
obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o
......
...@@ -588,6 +588,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = { ...@@ -588,6 +588,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
} , { } , {
.compatible = "atmel,at91sam9260-i2c", .compatible = "atmel,at91sam9260-i2c",
.data = &at91sam9260_config, .data = &at91sam9260_config,
} , {
.compatible = "atmel,at91sam9261-i2c",
.data = &at91sam9261_config,
} , { } , {
.compatible = "atmel,at91sam9g20-i2c", .compatible = "atmel,at91sam9g20-i2c",
.data = &at91sam9g20_config, .data = &at91sam9g20_config,
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
* *
*/ */
#include <linux/export.h> #include <linux/export.h>
#include <linux/clk.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
......
...@@ -607,7 +607,7 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -607,7 +607,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "can't get irq number\n"); dev_err(&pdev->dev, "can't get irq number\n");
return -ENOENT; return irq;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -275,7 +275,8 @@ static int smbus_sch_probe(struct platform_device *dev) ...@@ -275,7 +275,8 @@ static int smbus_sch_probe(struct platform_device *dev)
if (!res) if (!res)
return -EBUSY; return -EBUSY;
if (!request_region(res->start, resource_size(res), dev->name)) { if (!devm_request_region(&dev->dev, res->start, resource_size(res),
dev->name)) {
dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
sch_smba); sch_smba);
return -EBUSY; return -EBUSY;
...@@ -294,7 +295,6 @@ static int smbus_sch_probe(struct platform_device *dev) ...@@ -294,7 +295,6 @@ static int smbus_sch_probe(struct platform_device *dev)
retval = i2c_add_adapter(&sch_adapter); retval = i2c_add_adapter(&sch_adapter);
if (retval) { if (retval) {
dev_err(&dev->dev, "Couldn't register adapter!\n"); dev_err(&dev->dev, "Couldn't register adapter!\n");
release_region(res->start, resource_size(res));
sch_smba = 0; sch_smba = 0;
} }
...@@ -303,11 +303,8 @@ static int smbus_sch_probe(struct platform_device *dev) ...@@ -303,11 +303,8 @@ static int smbus_sch_probe(struct platform_device *dev)
static int smbus_sch_remove(struct platform_device *pdev) static int smbus_sch_remove(struct platform_device *pdev)
{ {
struct resource *res;
if (sch_smba) { if (sch_smba) {
i2c_del_adapter(&sch_adapter); i2c_del_adapter(&sch_adapter);
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(res->start, resource_size(res));
sch_smba = 0; sch_smba = 0;
} }
......
...@@ -344,6 +344,7 @@ static int ismt_process_desc(const struct ismt_desc *desc, ...@@ -344,6 +344,7 @@ static int ismt_process_desc(const struct ismt_desc *desc,
data->word = dma_buffer[0] | (dma_buffer[1] << 8); data->word = dma_buffer[0] | (dma_buffer[1] << 8);
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_I2C_BLOCK_DATA:
memcpy(&data->block[1], dma_buffer, desc->rxbytes); memcpy(&data->block[1], dma_buffer, desc->rxbytes);
data->block[0] = desc->rxbytes; data->block[0] = desc->rxbytes;
break; break;
...@@ -509,6 +510,41 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, ...@@ -509,6 +510,41 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
} }
break; break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* Make sure the length is valid */
if (data->block[0] < 1)
data->block[0] = 1;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
data->block[0] = I2C_SMBUS_BLOCK_MAX;
if (read_write == I2C_SMBUS_WRITE) {
/* i2c Block Write */
dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: WRITE\n");
dma_size = data->block[0] + 1;
dma_direction = DMA_TO_DEVICE;
desc->wr_len_cmd = dma_size;
desc->control |= ISMT_DESC_I2C;
priv->dma_buffer[0] = command;
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
} else {
/* i2c Block Read */
dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n");
dma_size = data->block[0];
dma_direction = DMA_FROM_DEVICE;
desc->rd_len = dma_size;
desc->wr_len_cmd = command;
desc->control |= (ISMT_DESC_I2C | ISMT_DESC_CWRL);
/*
* Per the "Table 15-15. I2C Commands",
* in the External Design Specification (EDS),
* (Document Number: 508084, Revision: 2.0),
* the _rw bit must be 0
*/
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 0);
}
break;
default: default:
dev_err(dev, "Unsupported transaction %d\n", dev_err(dev, "Unsupported transaction %d\n",
size); size);
...@@ -582,6 +618,7 @@ static u32 ismt_func(struct i2c_adapter *adap) ...@@ -582,6 +618,7 @@ static u32 ismt_func(struct i2c_adapter *adap)
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PROC_CALL |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK |
I2C_FUNC_SMBUS_PEC; I2C_FUNC_SMBUS_PEC;
} }
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/platform_data/i2c-nomadik.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
...@@ -104,6 +103,29 @@ ...@@ -104,6 +103,29 @@
/* maximum threshold value */ /* maximum threshold value */
#define MAX_I2C_FIFO_THRESHOLD 15 #define MAX_I2C_FIFO_THRESHOLD 15
enum i2c_freq_mode {
I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */
I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */
I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */
I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */
};
/**
* struct nmk_i2c_controller - client specific controller configuration
* @clk_freq: clock frequency for the operation mode
* @tft: Tx FIFO Threshold in bytes
* @rft: Rx FIFO Threshold in bytes
* @timeout Slave response timeout(ms)
* @sm: speed mode
*/
struct nmk_i2c_controller {
u32 clk_freq;
unsigned char tft;
unsigned char rft;
int timeout;
enum i2c_freq_mode sm;
};
/** /**
* struct i2c_vendor_data - per-vendor variations * struct i2c_vendor_data - per-vendor variations
* @has_mtdws: variant has the MTDWS bit * @has_mtdws: variant has the MTDWS bit
...@@ -340,6 +362,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) ...@@ -340,6 +362,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
{ {
u32 brcr1, brcr2; u32 brcr1, brcr2;
u32 i2c_clk, div; u32 i2c_clk, div;
u32 ns;
u16 slsu;
writel(0x0, dev->virtbase + I2C_CR); writel(0x0, dev->virtbase + I2C_CR);
writel(0x0, dev->virtbase + I2C_HSMCR); writel(0x0, dev->virtbase + I2C_HSMCR);
...@@ -347,18 +371,38 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) ...@@ -347,18 +371,38 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
writel(0x0, dev->virtbase + I2C_RFTR); writel(0x0, dev->virtbase + I2C_RFTR);
writel(0x0, dev->virtbase + I2C_DMAR); writel(0x0, dev->virtbase + I2C_DMAR);
i2c_clk = clk_get_rate(dev->clk);
/* /*
* set the slsu: * set the slsu:
* *
* slsu defines the data setup time after SCL clock * slsu defines the data setup time after SCL clock
* stretching in terms of i2c clk cycles. The * stretching in terms of i2c clk cycles + 1 (zero means
* needed setup time for the three modes are 250ns, * "wait one cycle"), the needed setup time for the three
* 100ns, 10ns respectively thus leading to the values * modes are 250ns, 100ns, 10ns respectively.
* of 14, 6, 2 for a 48 MHz i2c clk. *
* As the time for one cycle T in nanoseconds is
* T = (1/f) * 1000000000 =>
* slsu = cycles / (1000000000 / f) + 1
*/ */
writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR); ns = DIV_ROUND_UP_ULL(1000000000ULL, i2c_clk);
switch (dev->cfg.sm) {
case I2C_FREQ_MODE_FAST:
case I2C_FREQ_MODE_FAST_PLUS:
slsu = DIV_ROUND_UP(100, ns); /* Fast */
break;
case I2C_FREQ_MODE_HIGH_SPEED:
slsu = DIV_ROUND_UP(10, ns); /* High */
break;
case I2C_FREQ_MODE_STANDARD:
default:
slsu = DIV_ROUND_UP(250, ns); /* Standard */
break;
}
slsu += 1;
i2c_clk = clk_get_rate(dev->clk); dev_dbg(&dev->adev->dev, "calculated SLSU = %04x\n", slsu);
writel(slsu << 16, dev->virtbase + I2C_SCR);
/* /*
* The spec says, in case of std. mode the divider is * The spec says, in case of std. mode the divider is
...@@ -915,11 +959,6 @@ static const struct i2c_algorithm nmk_i2c_algo = { ...@@ -915,11 +959,6 @@ static const struct i2c_algorithm nmk_i2c_algo = {
}; };
static struct nmk_i2c_controller u8500_i2c = { static struct nmk_i2c_controller u8500_i2c = {
/*
* Slave data setup time; 250ns, 100ns, and 10ns, which
* is 14, 6 and 2 respectively for a 48Mhz i2c clock.
*/
.slsu = 0xe,
.tft = 1, /* Tx FIFO threshold */ .tft = 1, /* Tx FIFO threshold */
.rft = 8, /* Rx FIFO threshold */ .rft = 8, /* Rx FIFO threshold */
.clk_freq = 400000, /* fast mode operation */ .clk_freq = 400000, /* fast mode operation */
...@@ -1027,7 +1066,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -1027,7 +1066,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
/* fetch the controller configuration from machine */ /* fetch the controller configuration from machine */
dev->cfg.clk_freq = pdata->clk_freq; dev->cfg.clk_freq = pdata->clk_freq;
dev->cfg.slsu = pdata->slsu;
dev->cfg.tft = pdata->tft; dev->cfg.tft = pdata->tft;
dev->cfg.rft = pdata->rft; dev->cfg.rft = pdata->rft;
dev->cfg.sm = pdata->sm; dev->cfg.sm = pdata->sm;
......
...@@ -628,11 +628,9 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -628,11 +628,9 @@ static int i2c_pnx_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000; u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000;
alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); alg_data = devm_kzalloc(&pdev->dev, sizeof(*alg_data), GFP_KERNEL);
if (!alg_data) { if (!alg_data)
ret = -ENOMEM; return -ENOMEM;
goto err_kzalloc;
}
platform_set_drvdata(pdev, alg_data); platform_set_drvdata(pdev, alg_data);
...@@ -657,11 +655,9 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -657,11 +655,9 @@ static int i2c_pnx_probe(struct platform_device *pdev)
*/ */
} }
#endif #endif
alg_data->clk = clk_get(&pdev->dev, NULL); alg_data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(alg_data->clk)) { if (IS_ERR(alg_data->clk))
ret = PTR_ERR(alg_data->clk); return PTR_ERR(alg_data->clk);
goto out_drvdata;
}
init_timer(&alg_data->mif.timer); init_timer(&alg_data->mif.timer);
alg_data->mif.timer.function = i2c_pnx_timeout; alg_data->mif.timer.function = i2c_pnx_timeout;
...@@ -672,31 +668,13 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -672,31 +668,13 @@ static int i2c_pnx_probe(struct platform_device *pdev)
/* Register I/O resource */ /* Register I/O resource */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { alg_data->ioaddr = devm_ioremap_resource(&pdev->dev, res);
dev_err(&pdev->dev, "Unable to get mem resource.\n"); if (IS_ERR(alg_data->ioaddr))
ret = -EBUSY; return PTR_ERR(alg_data->ioaddr);
goto out_clkget;
}
if (!request_mem_region(res->start, I2C_PNX_REGION_SIZE,
pdev->name)) {
dev_err(&pdev->dev,
"I/O region 0x%08x for I2C already in use.\n",
res->start);
ret = -ENOMEM;
goto out_clkget;
}
alg_data->base = res->start;
alg_data->ioaddr = ioremap(res->start, I2C_PNX_REGION_SIZE);
if (!alg_data->ioaddr) {
dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
ret = -ENOMEM;
goto out_release;
}
ret = clk_enable(alg_data->clk); ret = clk_enable(alg_data->clk);
if (ret) if (ret)
goto out_unmap; return ret;
freq = clk_get_rate(alg_data->clk); freq = clk_get_rate(alg_data->clk);
...@@ -730,8 +708,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -730,8 +708,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
ret = alg_data->irq; ret = alg_data->irq;
goto out_clock; goto out_clock;
} }
ret = request_irq(alg_data->irq, i2c_pnx_interrupt, ret = devm_request_irq(&pdev->dev, alg_data->irq, i2c_pnx_interrupt,
0, pdev->name, alg_data); 0, pdev->name, alg_data);
if (ret) if (ret)
goto out_clock; goto out_clock;
...@@ -739,7 +717,7 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -739,7 +717,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&alg_data->adapter); ret = i2c_add_numbered_adapter(&alg_data->adapter);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "I2C: Failed to add bus\n"); dev_err(&pdev->dev, "I2C: Failed to add bus\n");
goto out_irq; goto out_clock;
} }
dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
...@@ -747,19 +725,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -747,19 +725,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
return 0; return 0;
out_irq:
free_irq(alg_data->irq, alg_data);
out_clock: out_clock:
clk_disable(alg_data->clk); clk_disable(alg_data->clk);
out_unmap:
iounmap(alg_data->ioaddr);
out_release:
release_mem_region(res->start, I2C_PNX_REGION_SIZE);
out_clkget:
clk_put(alg_data->clk);
out_drvdata:
kfree(alg_data);
err_kzalloc:
return ret; return ret;
} }
...@@ -767,13 +734,8 @@ static int i2c_pnx_remove(struct platform_device *pdev) ...@@ -767,13 +734,8 @@ static int i2c_pnx_remove(struct platform_device *pdev)
{ {
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
free_irq(alg_data->irq, alg_data);
i2c_del_adapter(&alg_data->adapter); i2c_del_adapter(&alg_data->adapter);
clk_disable(alg_data->clk); clk_disable(alg_data->clk);
iounmap(alg_data->ioaddr);
release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE);
clk_put(alg_data->clk);
kfree(alg_data);
return 0; return 0;
} }
......
This diff is collapsed.
/*
* Driver for RobotFuzz OSIF
*
* Copyright (c) 2013 Andrew Lunn <andrew@lunn.ch>
* Copyright (c) 2007 Barry Carter <Barry.Carter@robotfuzz.com>
*
* Based on the i2c-tiny-usb by
*
* Copyright (C) 2006 Til Harbaum (Till@Harbaum.org)
*
* 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, version 2.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/usb.h>
#define OSIFI2C_READ 20
#define OSIFI2C_WRITE 21
#define OSIFI2C_STOP 22
#define OSIFI2C_STATUS 23
#define OSIFI2C_SET_BIT_RATE 24
#define STATUS_ADDRESS_ACK 0
#define STATUS_ADDRESS_NAK 2
struct osif_priv {
struct usb_device *usb_dev;
struct usb_interface *interface;
struct i2c_adapter adapter;
unsigned char status;
};
static int osif_usb_read(struct i2c_adapter *adapter, int cmd,
int value, int index, void *data, int len)
{
struct osif_priv *priv = adapter->algo_data;
return usb_control_msg(priv->usb_dev, usb_rcvctrlpipe(priv->usb_dev, 0),
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
USB_DIR_IN, value, index, data, len, 2000);
}
static int osif_usb_write(struct i2c_adapter *adapter, int cmd,
int value, int index, void *data, int len)
{
struct osif_priv *priv = adapter->algo_data;
return usb_control_msg(priv->usb_dev, usb_sndctrlpipe(priv->usb_dev, 0),
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value, index, data, len, 2000);
}
static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
int num)
{
struct osif_priv *priv = adapter->algo_data;
struct i2c_msg *pmsg;
int ret = 0;
int i, cmd;
for (i = 0; ret >= 0 && i < num; i++) {
pmsg = &msgs[i];
if (pmsg->flags & I2C_M_RD) {
cmd = OSIFI2C_READ;
ret = osif_usb_read(adapter, cmd, pmsg->flags,
pmsg->addr, pmsg->buf,
pmsg->len);
if (ret != pmsg->len) {
dev_err(&adapter->dev, "failure reading data\n");
return -EREMOTEIO;
}
} else {
cmd = OSIFI2C_WRITE;
ret = osif_usb_write(adapter, cmd, pmsg->flags,
pmsg->addr, pmsg->buf, pmsg->len);
if (ret != pmsg->len) {
dev_err(&adapter->dev, "failure writing data\n");
return -EREMOTEIO;
}
}
ret = osif_usb_read(adapter, OSIFI2C_STOP, 0, 0, NULL, 0);
if (ret) {
dev_err(&adapter->dev, "failure sending STOP\n");
return -EREMOTEIO;
}
/* read status */
ret = osif_usb_read(adapter, OSIFI2C_STATUS, 0, 0,
&priv->status, 1);
if (ret != 1) {
dev_err(&adapter->dev, "failure reading status\n");
return -EREMOTEIO;
}
if (priv->status != STATUS_ADDRESS_ACK) {
dev_dbg(&adapter->dev, "status = %d\n", priv->status);
return -EREMOTEIO;
}
}
return i;
}
static u32 osif_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm osif_algorithm = {
.master_xfer = osif_xfer,
.functionality = osif_func,
};
#define USB_OSIF_VENDOR_ID 0x1964
#define USB_OSIF_PRODUCT_ID 0x0001
static struct usb_device_id osif_table[] = {
{ USB_DEVICE(USB_OSIF_VENDOR_ID, USB_OSIF_PRODUCT_ID) },
{ }
};
MODULE_DEVICE_TABLE(usb, osif_table);
static int osif_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
int ret;
struct osif_priv *priv;
u16 version;
priv = devm_kzalloc(&interface->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->usb_dev = usb_get_dev(interface_to_usbdev(interface));
priv->interface = interface;
usb_set_intfdata(interface, priv);
priv->adapter.owner = THIS_MODULE;
priv->adapter.class = I2C_CLASS_HWMON;
priv->adapter.algo = &osif_algorithm;
priv->adapter.algo_data = priv;
snprintf(priv->adapter.name, sizeof(priv->adapter.name),
"OSIF at bus %03d device %03d",
priv->usb_dev->bus->busnum, priv->usb_dev->devnum);
/*
* Set bus frequency. The frequency is:
* 120,000,000 / ( 16 + 2 * div * 4^prescale).
* Using dev = 52, prescale = 0 give 100KHz */
ret = osif_usb_read(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0,
NULL, 0);
if (ret) {
dev_err(&interface->dev, "failure sending bit rate");
usb_put_dev(priv->usb_dev);
return ret;
}
i2c_add_adapter(&(priv->adapter));
version = le16_to_cpu(priv->usb_dev->descriptor.bcdDevice);
dev_info(&interface->dev,
"version %x.%02x found at bus %03d address %03d",
version >> 8, version & 0xff,
priv->usb_dev->bus->busnum, priv->usb_dev->devnum);
return 0;
}
static void osif_disconnect(struct usb_interface *interface)
{
struct osif_priv *priv = usb_get_intfdata(interface);
i2c_del_adapter(&(priv->adapter));
usb_set_intfdata(interface, NULL);
usb_put_dev(priv->usb_dev);
}
static struct usb_driver osif_driver = {
.name = "RobotFuzz Open Source InterFace, OSIF",
.probe = osif_probe,
.disconnect = osif_disconnect,
.id_table = osif_table,
};
module_usb_driver(osif_driver);
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
MODULE_AUTHOR("Barry Carter <barry.carter@robotfuzz.com>");
MODULE_DESCRIPTION("RobotFuzz OSIF driver");
MODULE_LICENSE("GPL v2");
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#define QUIRK_S3C2440 (1 << 0) #define QUIRK_S3C2440 (1 << 0)
#define QUIRK_HDMIPHY (1 << 1) #define QUIRK_HDMIPHY (1 << 1)
#define QUIRK_NO_GPIO (1 << 2) #define QUIRK_NO_GPIO (1 << 2)
#define QUIRK_POLL (1 << 3)
/* Max time to wait for bus to become idle after a xfer (in us) */ /* Max time to wait for bus to become idle after a xfer (in us) */
#define S3C2410_IDLE_TIMEOUT 5000 #define S3C2410_IDLE_TIMEOUT 5000
...@@ -101,7 +102,7 @@ enum s3c24xx_i2c_state { ...@@ -101,7 +102,7 @@ enum s3c24xx_i2c_state {
struct s3c24xx_i2c { struct s3c24xx_i2c {
wait_queue_head_t wait; wait_queue_head_t wait;
unsigned int quirks; kernel_ulong_t quirks;
unsigned int suspended:1; unsigned int suspended:1;
struct i2c_msg *msg; struct i2c_msg *msg;
...@@ -123,7 +124,7 @@ struct s3c24xx_i2c { ...@@ -123,7 +124,7 @@ struct s3c24xx_i2c {
struct s3c2410_platform_i2c *pdata; struct s3c2410_platform_i2c *pdata;
int gpios[2]; int gpios[2];
struct pinctrl *pctrl; struct pinctrl *pctrl;
#ifdef CONFIG_CPU_FREQ #if defined(CONFIG_ARM_S3C24XX_CPUFREQ)
struct notifier_block freq_transition; struct notifier_block freq_transition;
#endif #endif
}; };
...@@ -142,6 +143,8 @@ static struct platform_device_id s3c24xx_driver_ids[] = { ...@@ -142,6 +143,8 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
}; };
MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id s3c24xx_i2c_match[] = { static const struct of_device_id s3c24xx_i2c_match[] = {
{ .compatible = "samsung,s3c2410-i2c", .data = (void *)0 }, { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
...@@ -150,6 +153,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = { ...@@ -150,6 +153,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
.data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) }, .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
{ .compatible = "samsung,exynos5440-i2c", { .compatible = "samsung,exynos5440-i2c",
.data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) }, .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
{ .compatible = "samsung,exynos5-sata-phy-i2c",
.data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
...@@ -160,12 +165,12 @@ MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); ...@@ -160,12 +165,12 @@ MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
* Get controller type either from device tree or platform device variant. * Get controller type either from device tree or platform device variant.
*/ */
static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pdev) static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *pdev)
{ {
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node); match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node);
return (unsigned int)match->data; return (kernel_ulong_t)match->data;
} }
return platform_get_device_id(pdev)->driver_data; return platform_get_device_id(pdev)->driver_data;
...@@ -188,7 +193,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) ...@@ -188,7 +193,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
if (ret) if (ret)
i2c->msg_idx = ret; i2c->msg_idx = ret;
wake_up(&i2c->wait); if (!(i2c->quirks & QUIRK_POLL))
wake_up(&i2c->wait);
} }
static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
...@@ -225,6 +231,22 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) ...@@ -225,6 +231,22 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
} }
static bool is_ack(struct s3c24xx_i2c *i2c)
{
int tries;
for (tries = 50; tries; --tries) {
if (readl(i2c->regs + S3C2410_IICCON)
& S3C2410_IICCON_IRQPEND) {
if (!(readl(i2c->regs + S3C2410_IICSTAT)
& S3C2410_IICSTAT_LASTBIT))
return true;
}
usleep_range(1000, 2000);
}
dev_err(i2c->dev, "ack was not recieved\n");
return false;
}
/* s3c24xx_i2c_message_start /* s3c24xx_i2c_message_start
* *
...@@ -269,6 +291,16 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, ...@@ -269,6 +291,16 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
stat |= S3C2410_IICSTAT_START; stat |= S3C2410_IICSTAT_START;
writel(stat, i2c->regs + S3C2410_IICSTAT); writel(stat, i2c->regs + S3C2410_IICSTAT);
if (i2c->quirks & QUIRK_POLL) {
while ((i2c->msg_num != 0) && is_ack(i2c)) {
i2c_s3c_irq_nextbyte(i2c, stat);
stat = readl(i2c->regs + S3C2410_IICSTAT);
if (stat & S3C2410_IICSTAT_ARBITR)
dev_err(i2c->dev, "deal with arbitration loss\n");
}
}
} }
static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
...@@ -676,6 +708,15 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, ...@@ -676,6 +708,15 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs); s3c24xx_i2c_message_start(i2c, msgs);
if (i2c->quirks & QUIRK_POLL) {
ret = i2c->msg_idx;
if (ret != num)
dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
goto out;
}
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
ret = i2c->msg_idx; ret = i2c->msg_idx;
...@@ -821,6 +862,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) ...@@ -821,6 +862,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
if (div1 == 512) if (div1 == 512)
iiccon |= S3C2410_IICCON_TXDIV_512; iiccon |= S3C2410_IICCON_TXDIV_512;
if (i2c->quirks & QUIRK_POLL)
iiccon |= S3C2410_IICCON_SCALE(2);
writel(iiccon, i2c->regs + S3C2410_IICCON); writel(iiccon, i2c->regs + S3C2410_IICCON);
if (i2c->quirks & QUIRK_S3C2440) { if (i2c->quirks & QUIRK_S3C2440) {
...@@ -843,7 +887,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) ...@@ -843,7 +887,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
return 0; return 0;
} }
#ifdef CONFIG_CPU_FREQ #if defined(CONFIG_ARM_S3C24XX_CPUFREQ)
#define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) #define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition)
...@@ -1118,18 +1162,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -1118,18 +1162,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
* ensure no current IRQs pending * ensure no current IRQs pending
*/ */
i2c->irq = ret = platform_get_irq(pdev, 0); if (!(i2c->quirks & QUIRK_POLL)) {
if (ret <= 0) { i2c->irq = ret = platform_get_irq(pdev, 0);
dev_err(&pdev->dev, "cannot find IRQ\n"); if (ret <= 0) {
return ret; dev_err(&pdev->dev, "cannot find IRQ\n");
} return ret;
}
ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0,
dev_name(&pdev->dev), i2c); dev_name(&pdev->dev), i2c);
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
return ret; return ret;
}
} }
ret = s3c24xx_i2c_register_cpufreq(i2c); ret = s3c24xx_i2c_register_cpufreq(i2c);
......
...@@ -162,7 +162,6 @@ static const struct i2c_algorithm usb_algorithm = { ...@@ -162,7 +162,6 @@ static const struct i2c_algorithm usb_algorithm = {
static const struct usb_device_id i2c_tiny_usb_table[] = { static const struct usb_device_id i2c_tiny_usb_table[] = {
{ USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */
{ USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */
{ USB_DEVICE(0x1964, 0x0001) }, /* Robofuzz OSIF */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -118,8 +118,7 @@ static int vprbrd_i2c_addr(struct usb_device *usb_dev, ...@@ -118,8 +118,7 @@ static int vprbrd_i2c_addr(struct usb_device *usb_dev,
static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg) static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg)
{ {
int ret; int ret;
u16 remain_len, bytes_xfer, len1, len2, u16 remain_len, len1, len2, start = 0x0000;
start = 0x0000;
struct vprbrd_i2c_read_msg *rmsg = struct vprbrd_i2c_read_msg *rmsg =
(struct vprbrd_i2c_read_msg *)vb->buf; (struct vprbrd_i2c_read_msg *)vb->buf;
...@@ -166,7 +165,6 @@ static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg) ...@@ -166,7 +165,6 @@ static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg)
rmsg->header.len3 = remain_len - 512; rmsg->header.len3 = remain_len - 512;
rmsg->header.len4 = 0x00; rmsg->header.len4 = 0x00;
rmsg->header.len5 = 0x00; rmsg->header.len5 = 0x00;
bytes_xfer = remain_len;
remain_len = 0; remain_len = 0;
} else if (remain_len <= 1022) { } else if (remain_len <= 1022) {
len1 = 512; len1 = 512;
...@@ -367,7 +365,7 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) ...@@ -367,7 +365,7 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
int ret; int ret;
int pipe; int pipe;
vb_i2c = kzalloc(sizeof(*vb_i2c), GFP_KERNEL); vb_i2c = devm_kzalloc(&pdev->dev, sizeof(*vb_i2c), GFP_KERNEL);
if (vb_i2c == NULL) if (vb_i2c == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -394,14 +392,12 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) ...@@ -394,14 +392,12 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
if (ret != 1) { if (ret != 1) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"failure setting i2c_bus_freq to %d\n", i2c_bus_freq); "failure setting i2c_bus_freq to %d\n", i2c_bus_freq);
ret = -EIO; return -EIO;
goto error;
} }
} else { } else {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"invalid i2c_bus_freq setting:%d\n", i2c_bus_freq); "invalid i2c_bus_freq setting:%d\n", i2c_bus_freq);
ret = -EIO; return -EIO;
goto error;
} }
vb_i2c->i2c.dev.parent = &pdev->dev; vb_i2c->i2c.dev.parent = &pdev->dev;
...@@ -412,10 +408,6 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) ...@@ -412,10 +408,6 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, vb_i2c); platform_set_drvdata(pdev, vb_i2c);
return 0; return 0;
error:
kfree(vb_i2c);
return ret;
} }
static int vprbrd_i2c_remove(struct platform_device *pdev) static int vprbrd_i2c_remove(struct platform_device *pdev)
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -69,7 +70,7 @@ struct xiic_i2c { ...@@ -69,7 +70,7 @@ struct xiic_i2c {
struct i2c_adapter adap; struct i2c_adapter adap;
struct i2c_msg *tx_msg; struct i2c_msg *tx_msg;
spinlock_t lock; spinlock_t lock;
unsigned int tx_pos; unsigned int tx_pos;
unsigned int nmsgs; unsigned int nmsgs;
enum xilinx_i2c_state state; enum xilinx_i2c_state state;
struct i2c_msg *rx_msg; struct i2c_msg *rx_msg;
...@@ -272,8 +273,8 @@ static void xiic_read_rx(struct xiic_i2c *i2c) ...@@ -272,8 +273,8 @@ static void xiic_read_rx(struct xiic_i2c *i2c)
bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1;
dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d" dev_dbg(i2c->adap.dev.parent,
", SR: 0x%x, CR: 0x%x\n", "%s entry, bytes in fifo: %d, msg: %d, SR: 0x%x, CR: 0x%x\n",
__func__, bytes_in_fifo, xiic_rx_space(i2c), __func__, bytes_in_fifo, xiic_rx_space(i2c),
xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
...@@ -340,9 +341,10 @@ static void xiic_process(struct xiic_i2c *i2c) ...@@ -340,9 +341,10 @@ static void xiic_process(struct xiic_i2c *i2c)
ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
pend = isr & ier; pend = isr & ier;
dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, " dev_dbg(i2c->adap.dev.parent, "%s: IER: 0x%x, ISR: 0x%x, pend: 0x%x\n",
"pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n", __func__, ier, isr, pend);
__func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n",
__func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
i2c->tx_msg, i2c->nmsgs); i2c->tx_msg, i2c->nmsgs);
/* Do not processes a devices interrupts if the device has no /* Do not processes a devices interrupts if the device has no
...@@ -542,9 +544,10 @@ static void xiic_start_send(struct xiic_i2c *i2c) ...@@ -542,9 +544,10 @@ static void xiic_start_send(struct xiic_i2c *i2c)
xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK); xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK);
dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, " dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d",
"ISR: 0x%x, CR: 0x%x\n", __func__, msg, msg->len);
__func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET), dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n",
__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
if (!(msg->flags & I2C_M_NOSTART)) { if (!(msg->flags & I2C_M_NOSTART)) {
...@@ -695,33 +698,21 @@ static int xiic_i2c_probe(struct platform_device *pdev) ...@@ -695,33 +698,21 @@ static int xiic_i2c_probe(struct platform_device *pdev)
int ret, irq; int ret, irq;
u8 i; u8 i;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) i2c->base = devm_ioremap_resource(&pdev->dev, res);
goto resource_missing; if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
goto resource_missing; return irq;
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
dev_err(&pdev->dev, "Memory region busy\n");
ret = -EBUSY;
goto request_mem_failed;
}
i2c->base = ioremap(res->start, resource_size(res));
if (!i2c->base) {
dev_err(&pdev->dev, "Unable to map registers\n");
ret = -EIO;
goto map_failed;
}
/* hook up driver to tree */ /* hook up driver to tree */
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);
i2c->adap = xiic_adapter; i2c->adap = xiic_adapter;
...@@ -729,21 +720,23 @@ static int xiic_i2c_probe(struct platform_device *pdev) ...@@ -729,21 +720,23 @@ static int xiic_i2c_probe(struct platform_device *pdev)
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node; i2c->adap.dev.of_node = pdev->dev.of_node;
xiic_reinit(i2c);
spin_lock_init(&i2c->lock); spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
ret = request_irq(irq, xiic_isr, 0, pdev->name, i2c);
if (ret) { ret = devm_request_irq(&pdev->dev, irq, xiic_isr, 0, pdev->name, i2c);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot claim IRQ\n"); dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto request_irq_failed; return ret;
} }
xiic_reinit(i2c);
/* add i2c adapter to i2c tree */ /* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap); ret = i2c_add_adapter(&i2c->adap);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to add adapter\n"); dev_err(&pdev->dev, "Failed to add adapter\n");
goto add_adapter_failed; xiic_deinit(i2c);
return ret;
} }
if (pdata) { if (pdata) {
...@@ -753,43 +746,17 @@ static int xiic_i2c_probe(struct platform_device *pdev) ...@@ -753,43 +746,17 @@ static int xiic_i2c_probe(struct platform_device *pdev)
} }
return 0; return 0;
add_adapter_failed:
free_irq(irq, i2c);
request_irq_failed:
xiic_deinit(i2c);
iounmap(i2c->base);
map_failed:
release_mem_region(res->start, resource_size(res));
request_mem_failed:
kfree(i2c);
return ret;
resource_missing:
dev_err(&pdev->dev, "IRQ or Memory resource is missing\n");
return -ENOENT;
} }
static int xiic_i2c_remove(struct platform_device *pdev) static int xiic_i2c_remove(struct platform_device *pdev)
{ {
struct xiic_i2c *i2c = platform_get_drvdata(pdev); struct xiic_i2c *i2c = platform_get_drvdata(pdev);
struct resource *res;
/* remove adapter & data */ /* remove adapter & data */
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
xiic_deinit(i2c); xiic_deinit(i2c);
free_irq(platform_get_irq(pdev, 0), i2c);
iounmap(i2c->base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, resource_size(res));
kfree(i2c);
return 0; return 0;
} }
......
...@@ -35,14 +35,15 @@ ...@@ -35,14 +35,15 @@
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
#include <linux/i2c/pca954x.h> #include <linux/i2c/pca954x.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#define PCA954X_MAX_NCHANS 8 #define PCA954X_MAX_NCHANS 8
...@@ -186,28 +187,43 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -186,28 +187,43 @@ static int pca954x_probe(struct i2c_client *client,
{ {
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
struct device_node *np = client->dev.of_node;
int num, force, class; int num, force, class;
struct pca954x *data; struct pca954x *data;
int ret = -ENODEV; int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
goto err; return -ENODEV;
data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL);
if (!data) { if (!data)
ret = -ENOMEM; return -ENOMEM;
goto err;
}
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
if (IS_ENABLED(CONFIG_OF) && np) {
enum of_gpio_flags flags;
int gpio;
/* Get the mux out of reset if a reset GPIO is specified. */
gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
if (gpio_is_valid(gpio)) {
ret = devm_gpio_request_one(&client->dev, gpio,
flags & OF_GPIO_ACTIVE_LOW ?
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
"pca954x reset");
if (ret < 0)
return ret;
}
}
/* Write the mux register at addr to verify /* Write the mux register at addr to verify
* that the mux is in fact present. This also * that the mux is in fact present. This also
* initializes the mux to disconnected state. * initializes the mux to disconnected state.
*/ */
if (i2c_smbus_write_byte(client, 0) < 0) { if (i2c_smbus_write_byte(client, 0) < 0) {
dev_warn(&client->dev, "probe failed\n"); dev_warn(&client->dev, "probe failed\n");
goto exit_free; return -ENODEV;
} }
data->type = id->driver_data; data->type = id->driver_data;
...@@ -252,9 +268,6 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -252,9 +268,6 @@ static int pca954x_probe(struct i2c_client *client,
virt_reg_failed: virt_reg_failed:
for (num--; num >= 0; num--) for (num--; num >= 0; num--)
i2c_del_mux_adapter(data->virt_adaps[num]); i2c_del_mux_adapter(data->virt_adaps[num]);
exit_free:
kfree(data);
err:
return ret; return ret;
} }
...@@ -270,7 +283,6 @@ static int pca954x_remove(struct i2c_client *client) ...@@ -270,7 +283,6 @@ static int pca954x_remove(struct i2c_client *client)
data->virt_adaps[i] = NULL; data->virt_adaps[i] = NULL;
} }
kfree(data);
return 0; return 0;
} }
......
...@@ -31,7 +31,6 @@ struct i2c_pnx_algo_data { ...@@ -31,7 +31,6 @@ struct i2c_pnx_algo_data {
int last; int last;
struct clk *clk; struct clk *clk;
struct i2c_adapter adapter; struct i2c_adapter adapter;
phys_addr_t base;
int irq; int irq;
u32 timeout; u32 timeout;
}; };
......
/*
* Copyright (C) 2009 ST-Ericsson
*
* 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.
*/
#ifndef __PDATA_I2C_NOMADIK_H
#define __PDATA_I2C_NOMADIK_H
enum i2c_freq_mode {
I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */
I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */
I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */
I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */
};
/**
* struct nmk_i2c_controller - client specific controller configuration
* @clk_freq: clock frequency for the operation mode
* @slsu: Slave data setup time in ns.
* The needed setup time for three modes of operation
* are 250ns, 100ns and 10ns respectively thus leading
* to the values of 14, 6, 2 for a 48 MHz i2c clk
* @tft: Tx FIFO Threshold in bytes
* @rft: Rx FIFO Threshold in bytes
* @timeout Slave response timeout(ms)
* @sm: speed mode
*/
struct nmk_i2c_controller {
u32 clk_freq;
unsigned short slsu;
unsigned char tft;
unsigned char rft;
int timeout;
enum i2c_freq_mode sm;
};
#endif /* __PDATA_I2C_NOMADIK_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment