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

Pull i2c updates from Wolfram Sang:
 "Quite some driver updates:
   - piix4 can now handle multiplexed adapters
   - brcmstb, xlr, eg20t, designware drivers support more SoCs
   - emev2 gained i2c slave support
   - img-scb and rcar got bigger refactoring to remove issues
   - lots of common driver updates

  i2c core changes:
   - new quirk flag when an adapter does not support clock stretching,
     so clients can be configured to avoid that if possible
   - added a helper function to retrieve timing parameters from firmware
     (with rcar being the first user)
   - "multi-master" DT binding added so drivers can adapt to this
     setting (like disabling PM to keep arbitration working)
   - RuntimePM for the logical adapter device is now always enabled by
     the core to ensure propagation from childs to the parent (the HW
     device)
   - new macro builtin_i2c_driver to reduce boilerplate"

* 'i2c/for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (70 commits)
  i2c: create builtin_i2c_driver to avoid registration boilerplate
  i2c: imx: fix i2c resource leak with dma transfer
  dt-bindings: i2c: eeprom: add another EEPROM device
  dt-bindings: move I2C eeprom descriptions to the proper file
  i2c: designware: Do not require clock when SSCN and FFCN are provided
  DT: i2c: trivial-devices: Add Epson RX8010 and MPL3115
  i2c: s3c2410: remove superfluous runtime PM calls
  i2c: always enable RuntimePM for the adapter device
  i2c: designware: retry transfer on transient failure
  i2c: ibm_iic: rename i2c_timings struct due to clash with generic version
  i2c: designware: Add support for AMD Seattle I2C
  i2c: imx: Remove unneeded comments
  i2c: st: use to_platform_device()
  i2c: designware: use to_pci_dev()
  i2c: brcmstb: Adding support for CM and DSL SoCs
  i2c: mediatek: fix i2c multi transfer issue in high speed mode
  i2c: imx: improve code readability
  i2c: imx: Improve message log when DMA is not used
  i2c: imx: add runtime pm support to improve the performance
  i2c: imx: init bus recovery info before adding i2c adapter
  ...
This commit is contained in:
Linus Torvalds
2016-01-14 11:25:37 -08:00
32 changed files with 1253 additions and 419 deletions

View File

@@ -617,6 +617,10 @@ const struct i2c_algorithm i2c_bit_algo = {
};
EXPORT_SYMBOL(i2c_bit_algo);
const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
.flags = I2C_AQ_NO_CLK_STRETCH,
};
/*
* registering functions to load algorithms at runtime
*/
@@ -635,6 +639,8 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
/* register new adapter to i2c module... */
adap->algo = &i2c_bit_algo;
adap->retries = 3;
if (bit_adap->getscl == NULL)
adap->quirks = &i2c_bit_quirk_no_clk_stretch;
ret = add_adapter(adap);
if (ret < 0)

View File

@@ -516,7 +516,7 @@ config I2C_EFM32
config I2C_EG20T
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
depends on PCI && (X86_32 || COMPILE_TEST)
depends on PCI && (X86_32 || MIPS || COMPILE_TEST)
help
This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -532,6 +532,7 @@ config I2C_EG20T
config I2C_EMEV2
tristate "EMMA Mobile series I2C adapter"
depends on HAVE_CLK
select I2C_SLAVE
help
If you say yes to this option, support will be included for the
I2C interface on the Renesas Electronics EM/EV family of processors.
@@ -963,11 +964,11 @@ config I2C_XILINX
will be called xilinx_i2c.
config I2C_XLR
tristate "XLR I2C support"
depends on CPU_XLR
tristate "Netlogic XLR and Sigma Designs I2C support"
depends on CPU_XLR || ARCH_TANGOX
help
This driver enables support for the on-chip I2C interface of
the Netlogic XLR/XLS MIPS processors.
the Netlogic XLR/XLS MIPS processors and Sigma Designs SOCs.
This driver can also be built as a module. If so, the module
will be called i2c-xlr.

View File

@@ -64,6 +64,8 @@
#define AT91_TWI_IADR 0x000c /* Internal Address Register */
#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */
#define AT91_TWI_CWGR_HOLD_MAX 0x1f
#define AT91_TWI_CWGR_HOLD(x) (((x) & AT91_TWI_CWGR_HOLD_MAX) << 24)
#define AT91_TWI_SR 0x0020 /* Status Register */
#define AT91_TWI_TXCOMP BIT(0) /* Transmission Complete */
@@ -110,6 +112,7 @@ struct at91_twi_pdata {
unsigned clk_offset;
bool has_unre_flag;
bool has_alt_cmd;
bool has_hold_field;
struct at_dma_slave dma_slave;
};
@@ -187,10 +190,11 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
*/
static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
{
int ckdiv, cdiv, div;
int ckdiv, cdiv, div, hold = 0;
struct at91_twi_pdata *pdata = dev->pdata;
int offset = pdata->clk_offset;
int max_ckdiv = pdata->clk_max_div;
u32 twd_hold_time_ns = 0;
div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
2 * twi_clk) - offset);
@@ -204,8 +208,33 @@ static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
cdiv = 255;
}
dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
if (pdata->has_hold_field) {
of_property_read_u32(dev->dev->of_node, "i2c-sda-hold-time-ns",
&twd_hold_time_ns);
/*
* hold time = HOLD + 3 x T_peripheral_clock
* Use clk rate in kHz to prevent overflows when computing
* hold.
*/
hold = DIV_ROUND_UP(twd_hold_time_ns
* (clk_get_rate(dev->clk) / 1000), 1000000);
hold -= 3;
if (hold < 0)
hold = 0;
if (hold > AT91_TWI_CWGR_HOLD_MAX) {
dev_warn(dev->dev,
"HOLD field set to its maximum value (%d instead of %d)\n",
AT91_TWI_CWGR_HOLD_MAX, hold);
hold = AT91_TWI_CWGR_HOLD_MAX;
}
}
dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv
| AT91_TWI_CWGR_HOLD(hold);
dev_dbg(dev->dev, "cdiv %d ckdiv %d hold %d (%d ns)\n",
cdiv, ckdiv, hold, twd_hold_time_ns);
}
static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
@@ -797,6 +826,7 @@ static struct at91_twi_pdata at91rm9200_config = {
.clk_offset = 3,
.has_unre_flag = true,
.has_alt_cmd = false,
.has_hold_field = false,
};
static struct at91_twi_pdata at91sam9261_config = {
@@ -804,6 +834,7 @@ static struct at91_twi_pdata at91sam9261_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
};
static struct at91_twi_pdata at91sam9260_config = {
@@ -811,6 +842,7 @@ static struct at91_twi_pdata at91sam9260_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
};
static struct at91_twi_pdata at91sam9g20_config = {
@@ -818,6 +850,7 @@ static struct at91_twi_pdata at91sam9g20_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
};
static struct at91_twi_pdata at91sam9g10_config = {
@@ -825,6 +858,7 @@ static struct at91_twi_pdata at91sam9g10_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
};
static const struct platform_device_id at91_twi_devtypes[] = {
@@ -854,6 +888,15 @@ static struct at91_twi_pdata at91sam9x5_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
};
static struct at91_twi_pdata sama5d4_config = {
.clk_max_div = 7,
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = true,
};
static struct at91_twi_pdata sama5d2_config = {
@@ -861,6 +904,7 @@ static struct at91_twi_pdata sama5d2_config = {
.clk_offset = 4,
.has_unre_flag = true,
.has_alt_cmd = true,
.has_hold_field = true,
};
static const struct of_device_id atmel_twi_dt_ids[] = {
@@ -882,6 +926,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
}, {
.compatible = "atmel,at91sam9x5-i2c",
.data = &at91sam9x5_config,
}, {
.compatible = "atmel,sama5d4-i2c",
.data = &sama5d4_config,
}, {
.compatible = "atmel,sama5d2-i2c",
.data = &sama5d2_config,

View File

@@ -222,6 +222,15 @@ static const struct i2c_algorithm bcm2835_i2c_algo = {
.functionality = bcm2835_i2c_func,
};
/*
* This HW was reported to have problems with clock stretching:
* http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html
* https://www.raspberrypi.org/forums/viewtopic.php?p=146272
*/
static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {
.flags = I2C_AQ_NO_CLK_STRETCH,
};
static int bcm2835_i2c_probe(struct platform_device *pdev)
{
struct bcm2835_i2c_dev *i2c_dev;
@@ -293,6 +302,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
adap->algo = &bcm2835_i2c_algo;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
adap->quirks = &bcm2835_i2c_quirks;
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);

View File

@@ -25,13 +25,16 @@
#include <linux/version.h>
#define N_DATA_REGS 8
#define N_DATA_BYTES (N_DATA_REGS * 4)
/* BSC count register field definitions */
#define BSC_CNT_REG1_MASK 0x0000003f
#define BSC_CNT_REG1_SHIFT 0
#define BSC_CNT_REG2_MASK 0x00000fc0
#define BSC_CNT_REG2_SHIFT 6
/*
* PER_I2C/BSC count register mask depends on 1 byte/4 byte data register
* size. Cable modem and DSL SoCs with Peripheral i2c cores use 1 byte per
* data register whereas STB SoCs use 4 byte per data register transfer,
* account for this difference in total count per transaction and mask to
* use.
*/
#define BSC_CNT_REG1_MASK(nb) (nb == 1 ? GENMASK(3, 0) : GENMASK(5, 0))
#define BSC_CNT_REG1_SHIFT 0
/* BSC CTL register field definitions */
#define BSC_CTL_REG_DTF_MASK 0x00000003
@@ -41,7 +44,7 @@
#define BSC_CTL_REG_INT_EN_SHIFT 6
#define BSC_CTL_REG_DIV_CLK_MASK 0x00000080
/* BSC_IIC_ENABLE r/w enable and interrupt field defintions */
/* BSC_IIC_ENABLE r/w enable and interrupt field definitions */
#define BSC_IIC_EN_RESTART_MASK 0x00000040
#define BSC_IIC_EN_NOSTART_MASK 0x00000020
#define BSC_IIC_EN_NOSTOP_MASK 0x00000010
@@ -169,6 +172,7 @@ struct brcmstb_i2c_dev {
struct completion done;
bool is_suspended;
u32 clk_freq_hz;
int data_regsz;
};
/* register accessors for both be and le cpu arch */
@@ -186,6 +190,16 @@ struct brcmstb_i2c_dev {
#define bsc_writel(_dev, _val, _reg) \
__bsc_writel(_val, _dev->base + offsetof(struct bsc_regs, _reg))
static inline int brcmstb_i2c_get_xfersz(struct brcmstb_i2c_dev *dev)
{
return (N_DATA_REGS * dev->data_regsz);
}
static inline int brcmstb_i2c_get_data_regsz(struct brcmstb_i2c_dev *dev)
{
return dev->data_regsz;
}
static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c_dev *dev,
bool int_en)
{
@@ -323,14 +337,16 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev,
u8 *buf, unsigned int len,
struct i2c_msg *pmsg)
{
int cnt, byte, rc;
int cnt, byte, i, rc;
enum bsc_xfer_cmd cmd;
u32 ctl_reg;
struct bsc_regs *pi2creg = dev->bsc_regmap;
int no_ack = pmsg->flags & I2C_M_IGNORE_NAK;
int data_regsz = brcmstb_i2c_get_data_regsz(dev);
int xfersz = brcmstb_i2c_get_xfersz(dev);
/* see if the transaction needs to check NACK conditions */
if (no_ack || len <= N_DATA_BYTES) {
if (no_ack || len <= xfersz) {
cmd = (pmsg->flags & I2C_M_RD) ? CMD_RD_NOACK
: CMD_WR_NOACK;
pi2creg->ctlhi_reg |= BSC_CTLHI_REG_IGNORE_ACK_MASK;
@@ -348,20 +364,22 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev,
pi2creg->ctl_reg = ctl_reg | DTF_RD_MASK;
/* set the read/write length */
bsc_writel(dev, BSC_CNT_REG1_MASK & (len << BSC_CNT_REG1_SHIFT),
cnt_reg);
bsc_writel(dev, BSC_CNT_REG1_MASK(data_regsz) &
(len << BSC_CNT_REG1_SHIFT), cnt_reg);
/* Write data into data_in register */
if (cmd == CMD_WR || cmd == CMD_WR_NOACK) {
for (cnt = 0; cnt < len; cnt += 4) {
for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) {
u32 word = 0;
for (byte = 0; byte < 4; byte++) {
word >>= 8;
for (byte = 0; byte < data_regsz; byte++) {
word >>= BITS_PER_BYTE;
if ((cnt + byte) < len)
word |= buf[cnt + byte] << 24;
word |= buf[cnt + byte] <<
(BITS_PER_BYTE * (data_regsz - 1));
}
bsc_writel(dev, word, data_in[cnt >> 2]);
bsc_writel(dev, word, data_in[i]);
}
}
@@ -373,14 +391,15 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev,
return rc;
}
/* Read data from data_out register */
if (cmd == CMD_RD || cmd == CMD_RD_NOACK) {
for (cnt = 0; cnt < len; cnt += 4) {
u32 data = bsc_readl(dev, data_out[cnt >> 2]);
for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) {
u32 data = bsc_readl(dev, data_out[i]);
for (byte = 0; byte < 4 &&
for (byte = 0; byte < data_regsz &&
(byte + cnt) < len; byte++) {
buf[cnt + byte] = data & 0xff;
data >>= 8;
data >>= BITS_PER_BYTE;
}
}
}
@@ -448,6 +467,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
int bytes_to_xfer;
u8 *tmp_buf;
int len = 0;
int xfersz = brcmstb_i2c_get_xfersz(dev);
if (dev->is_suspended)
return -EBUSY;
@@ -482,9 +502,9 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
/* Perform data transfer */
while (len) {
bytes_to_xfer = min(len, N_DATA_BYTES);
bytes_to_xfer = min(len, xfersz);
if (len <= N_DATA_BYTES && i == (num - 1))
if (len <= xfersz && i == (num - 1))
brcmstb_set_i2c_start_stop(dev,
~(COND_START_STOP));
@@ -542,8 +562,12 @@ static void brcmstb_i2c_set_bus_speed(struct brcmstb_i2c_dev *dev)
static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev)
{
/* 4 byte data register */
dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK;
if (brcmstb_i2c_get_data_regsz(dev) == sizeof(u32))
/* set 4 byte data in/out xfers */
dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK;
else
dev->bsc_regmap->ctlhi_reg &= ~BSC_CTLHI_REG_DATAREG_SIZE_MASK;
bsc_writel(dev, dev->bsc_regmap->ctlhi_reg, ctlhi_reg);
/* set bus speed */
brcmstb_i2c_set_bus_speed(dev);
@@ -608,6 +632,13 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
dev->clk_freq_hz = bsc_clk[0].hz;
}
/* set the data in/out register size for compatible SoCs */
if (of_device_is_compatible(dev->device->of_node,
"brcmstb,brcmper-i2c"))
dev->data_regsz = sizeof(u8);
else
dev->data_regsz = sizeof(u32);
brcmstb_i2c_set_bsc_reg_defaults(dev);
/* Add the i2c adapter */
@@ -674,6 +705,7 @@ static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend,
static const struct of_device_id brcmstb_i2c_of_match[] = {
{.compatible = "brcm,brcmstb-i2c"},
{.compatible = "brcm,brcmper-i2c"},
{},
};
MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match);

View File

@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
/* Register offsets for the I2C device. */
#define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */
@@ -96,6 +97,8 @@
CDNS_I2C_IXR_COMP)
#define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000)
/* timeout for pm runtime autosuspend */
#define CNDS_I2C_PM_TIMEOUT 1000 /* ms */
#define CDNS_I2C_FIFO_DEPTH 16
/* FIFO depth at which the DATA interrupt occurs */
@@ -128,7 +131,6 @@
* @xfer_done: Transfer complete status
* @p_send_buf: Pointer to transmit buffer
* @p_recv_buf: Pointer to receive buffer
* @suspended: Flag holding the device's PM status
* @send_count: Number of bytes still expected to send
* @recv_count: Number of bytes still expected to receive
* @curr_recv_count: Number of bytes to be received in current transfer
@@ -141,6 +143,7 @@
* @quirks: flag for broken hold bit usage in r1p10
*/
struct cdns_i2c {
struct device *dev;
void __iomem *membase;
struct i2c_adapter adap;
struct i2c_msg *p_msg;
@@ -148,7 +151,6 @@ struct cdns_i2c {
struct completion xfer_done;
unsigned char *p_send_buf;
unsigned char *p_recv_buf;
u8 suspended;
unsigned int send_count;
unsigned int recv_count;
unsigned int curr_recv_count;
@@ -569,9 +571,14 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
struct cdns_i2c *id = adap->algo_data;
bool hold_quirk;
ret = pm_runtime_get_sync(id->dev);
if (ret < 0)
return ret;
/* Check if the bus is free */
if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA)
return -EAGAIN;
if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) {
ret = -EAGAIN;
goto out;
}
hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
/*
@@ -590,7 +597,8 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
if (msgs[count].flags & I2C_M_RD) {
dev_warn(adap->dev.parent,
"Can't do repeated start after a receive message\n");
return -EOPNOTSUPP;
ret = -EOPNOTSUPP;
goto out;
}
}
id->bus_hold_flag = 1;
@@ -608,20 +616,26 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
ret = cdns_i2c_process_msg(id, msgs, adap);
if (ret)
return ret;
goto out;
/* Report the other error interrupts to application */
if (id->err_status) {
cdns_i2c_master_reset(adap);
if (id->err_status & CDNS_I2C_IXR_NACK)
return -ENXIO;
return -EIO;
if (id->err_status & CDNS_I2C_IXR_NACK) {
ret = -ENXIO;
goto out;
}
ret = -EIO;
goto out;
}
}
return num;
ret = num;
out:
pm_runtime_mark_last_busy(id->dev);
pm_runtime_put_autosuspend(id->dev);
return ret;
}
/**
@@ -760,7 +774,7 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
struct clk_notifier_data *ndata = data;
struct cdns_i2c *id = to_cdns_i2c(nb);
if (id->suspended)
if (pm_runtime_suspended(id->dev))
return NOTIFY_OK;
switch (event) {
@@ -808,14 +822,12 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
*
* Return: 0 always
*/
static int __maybe_unused cdns_i2c_suspend(struct device *_dev)
static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = container_of(_dev,
struct platform_device, dev);
struct platform_device *pdev = to_platform_device(dev);
struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
clk_disable(xi2c->clk);
xi2c->suspended = 1;
return 0;
}
@@ -828,26 +840,25 @@ static int __maybe_unused cdns_i2c_suspend(struct device *_dev)
*
* Return: 0 on success and error value on error
*/
static int __maybe_unused cdns_i2c_resume(struct device *_dev)
static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
{
struct platform_device *pdev = container_of(_dev,
struct platform_device, dev);
struct platform_device *pdev = to_platform_device(dev);
struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
int ret;
ret = clk_enable(xi2c->clk);
if (ret) {
dev_err(_dev, "Cannot enable clock.\n");
dev_err(dev, "Cannot enable clock.\n");
return ret;
}
xi2c->suspended = 0;
return 0;
}
static SIMPLE_DEV_PM_OPS(cdns_i2c_dev_pm_ops, cdns_i2c_suspend,
cdns_i2c_resume);
static const struct dev_pm_ops cdns_i2c_dev_pm_ops = {
SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend,
cdns_i2c_runtime_resume, NULL)
};
static const struct cdns_platform_data r1p10_i2c_def = {
.quirks = CDNS_I2C_BROKEN_HOLD_BIT,
@@ -881,6 +892,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
if (!id)
return -ENOMEM;
id->dev = &pdev->dev;
platform_set_drvdata(pdev, id);
match = of_match_node(cdns_i2c_of_match, pdev->dev.of_node);
@@ -913,10 +925,14 @@ static int cdns_i2c_probe(struct platform_device *pdev)
return PTR_ERR(id->clk);
}
ret = clk_prepare_enable(id->clk);
if (ret) {
if (ret)
dev_err(&pdev->dev, "Unable to enable clock.\n");
return ret;
}
pm_runtime_enable(id->dev);
pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(id->dev);
pm_runtime_set_active(id->dev);
id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb;
if (clk_notifier_register(id->clk, &id->clk_rate_change_nb))
dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
@@ -966,6 +982,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
err_clk_dis:
clk_disable_unprepare(id->clk);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return ret;
}
@@ -984,6 +1002,7 @@ static int cdns_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&id->adap);
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
clk_disable_unprepare(id->clk);
pm_runtime_disable(&pdev->dev);
return 0;
}

View File

@@ -271,6 +271,17 @@ static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
enable ? "en" : "dis");
}
static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
{
/*
* Clock is not necessary if we got LCNT/HCNT values directly from
* the platform code.
*/
if (WARN_ON_ONCE(!dev->get_clk_rate_khz))
return 0;
return dev->get_clk_rate_khz(dev);
}
/**
* i2c_dw_init() - initialize the designware i2c master hardware
* @dev: device private data
@@ -281,7 +292,6 @@ static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
*/
int i2c_dw_init(struct dw_i2c_dev *dev)
{
u32 input_clock_khz;
u32 hcnt, lcnt;
u32 reg;
u32 sda_falling_time, scl_falling_time;
@@ -295,8 +305,6 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
}
}
input_clock_khz = dev->get_clk_rate_khz(dev);
reg = dw_readl(dev, DW_IC_COMP_TYPE);
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
/* Configure register endianess access */
@@ -325,12 +333,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
hcnt = dev->ss_hcnt;
lcnt = dev->ss_lcnt;
} else {
hcnt = i2c_dw_scl_hcnt(input_clock_khz,
hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
4000, /* tHD;STA = tHIGH = 4.0 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
lcnt = i2c_dw_scl_lcnt(input_clock_khz,
lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
4700, /* tLOW = 4.7 us */
scl_falling_time,
0); /* No offset */
@@ -344,12 +352,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
hcnt = dev->fs_hcnt;
lcnt = dev->fs_lcnt;
} else {
hcnt = i2c_dw_scl_hcnt(input_clock_khz,
hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
600, /* tHD;STA = tHIGH = 0.6 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
lcnt = i2c_dw_scl_lcnt(input_clock_khz,
lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
1300, /* tLOW = 1.3 us */
scl_falling_time,
0); /* No offset */
@@ -860,6 +868,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
snprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C adapter");
adap->retries = 3;
adap->algo = &i2c_dw_algo;
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);

View File

@@ -162,7 +162,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
#ifdef CONFIG_PM
static int i2c_dw_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
struct pci_dev *pdev = to_pci_dev(dev);
i2c_dw_disable(pci_get_drvdata(pdev));
return 0;
@@ -170,7 +170,7 @@ static int i2c_dw_pci_suspend(struct device *dev)
static int i2c_dw_pci_resume(struct device *dev)
{
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
struct pci_dev *pdev = to_pci_dev(dev);
return i2c_dw_init(pci_get_drvdata(pdev));
}

View File

@@ -123,6 +123,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "80860F41", 0 },
{ "808622C1", 0 },
{ "AMD0010", ACCESS_INTR_MASK },
{ "AMDI0510", 0 },
{ "APMC0D0F", 0 },
{ }
};
@@ -134,6 +135,18 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
}
#endif
static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
{
if (IS_ERR(i_dev->clk))
return PTR_ERR(i_dev->clk);
if (prepare)
return clk_prepare_enable(i_dev->clk);
clk_disable_unprepare(i_dev->clk);
return 0;
}
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -206,16 +219,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
dev->clk = devm_clk_get(&pdev->dev, NULL);
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
if (IS_ERR(dev->clk))
return PTR_ERR(dev->clk);
clk_prepare_enable(dev->clk);
if (!i2c_dw_plat_prepare_clk(dev, true)) {
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
if (!dev->sda_hold_time && ht) {
u32 ic_clk = dev->get_clk_rate_khz(dev);
dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000,
1000000);
if (!dev->sda_hold_time && ht)
dev->sda_hold_time = div_u64(
(u64)dev->get_clk_rate_khz(dev) * ht + 500000,
1000000);
}
if (!dev->tx_fifo_depth) {
@@ -297,7 +307,7 @@ static int dw_i2c_plat_suspend(struct device *dev)
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
i2c_dw_disable(i_dev);
clk_disable_unprepare(i_dev->clk);
i2c_dw_plat_prepare_clk(i_dev, false);
return 0;
}
@@ -307,7 +317,7 @@ static int dw_i2c_plat_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
clk_prepare_enable(i_dev->clk);
i2c_dw_plat_prepare_clk(i_dev, true);
if (!i_dev->pm_runtime_disabled)
i2c_dw_init(i_dev);

View File

@@ -795,6 +795,7 @@ static int pch_i2c_probe(struct pci_dev *pdev,
/* base_addr + offset; */
adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
pch_adap->dev.of_node = pdev->dev.of_node;
pch_adap->dev.parent = &pdev->dev;
pch_i2c_init(&adap_info->pch_data[i]);

View File

@@ -71,6 +71,7 @@ struct em_i2c_device {
struct i2c_adapter adap;
struct completion msg_done;
struct clk *sclk;
struct i2c_client *slave;
};
static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
@@ -226,22 +227,131 @@ static int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
return num;
}
static bool em_i2c_slave_irq(struct em_i2c_device *priv)
{
u8 status, value;
enum i2c_slave_event event;
int ret;
if (!priv->slave)
return false;
status = readb(priv->base + I2C_OFS_IICSE0);
/* Extension code, do not participate */
if (status & I2C_BIT_EXC0) {
em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
return true;
}
/* Stop detected, we don't know if it's for slave or master */
if (status & I2C_BIT_SPD0) {
/* Notify slave device */
i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
/* Pretend we did not handle the interrupt */
return false;
}
/* Only handle interrupts addressed to us */
if (!(status & I2C_BIT_COI0))
return false;
/* Enable stop interrupts */
em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0);
/* Transmission or Reception */
if (status & I2C_BIT_TRC0) {
if (status & I2C_BIT_ACKD0) {
/* 9 bit interrupt mode */
em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0);
/* Send data */
event = status & I2C_BIT_STD0 ?
I2C_SLAVE_READ_REQUESTED :
I2C_SLAVE_READ_PROCESSED;
i2c_slave_event(priv->slave, event, &value);
writeb(value, priv->base + I2C_OFS_IIC0);
} else {
/* NACK, stop transmitting */
em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
}
} else {
/* 8 bit interrupt mode */
em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0,
I2C_OFS_IICC0);
em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0,
I2C_OFS_IICC0);
if (status & I2C_BIT_STD0) {
i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED,
&value);
} else {
/* Recv data */
value = readb(priv->base + I2C_OFS_IIC0);
ret = i2c_slave_event(priv->slave,
I2C_SLAVE_WRITE_RECEIVED, &value);
if (ret < 0)
em_clear_set_bit(priv, I2C_BIT_ACKE0, 0,
I2C_OFS_IICC0);
}
}
return true;
}
static irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id)
{
struct em_i2c_device *priv = dev_id;
if (em_i2c_slave_irq(priv))
return IRQ_HANDLED;
complete(&priv->msg_done);
return IRQ_HANDLED;
}
static u32 em_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE;
}
static int em_i2c_reg_slave(struct i2c_client *slave)
{
struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
if (priv->slave)
return -EBUSY;
if (slave->flags & I2C_CLIENT_TEN)
return -EAFNOSUPPORT;
priv->slave = slave;
/* Set slave address */
writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0);
return 0;
}
static int em_i2c_unreg_slave(struct i2c_client *slave)
{
struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
WARN_ON(!priv->slave);
writeb(0, priv->base + I2C_OFS_SVA0);
priv->slave = NULL;
return 0;
}
static struct i2c_algorithm em_i2c_algo = {
.master_xfer = em_i2c_xfer,
.functionality = em_i2c_func,
.reg_slave = em_i2c_reg_slave,
.unreg_slave = em_i2c_unreg_slave,
};
static int em_i2c_probe(struct platform_device *pdev)

View File

@@ -99,7 +99,7 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
#endif
/* Bus timings (in ns) for bit-banging */
static struct i2c_timings {
static struct ibm_iic_timings {
unsigned int hd_sta;
unsigned int su_sto;
unsigned int low;
@@ -241,7 +241,7 @@ static int iic_dc_wait(volatile struct iic_regs __iomem *iic, u8 mask)
static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p)
{
volatile struct iic_regs __iomem *iic = dev->vaddr;
const struct i2c_timings* t = &timings[dev->fast_mode ? 1 : 0];
const struct ibm_iic_timings *t = &timings[dev->fast_mode ? 1 : 0];
u8 mask, v, sda;
int i, res;

View File

@@ -151,10 +151,11 @@
#define INT_FIFO_EMPTYING BIT(12)
#define INT_TRANSACTION_DONE BIT(15)
#define INT_SLAVE_EVENT BIT(16)
#define INT_MASTER_HALTED BIT(17)
#define INT_TIMING BIT(18)
#define INT_STOP_DETECTED BIT(19)
#define INT_FIFO_FULL_FILLING (INT_FIFO_FULL | INT_FIFO_FILLING)
#define INT_FIFO_EMPTY_EMPTYING (INT_FIFO_EMPTY | INT_FIFO_EMPTYING)
/* Level interrupts need clearing after handling instead of before */
#define INT_LEVEL 0x01e00
@@ -177,7 +178,8 @@
INT_FIFO_FULL | \
INT_FIFO_FILLING | \
INT_FIFO_EMPTY | \
INT_FIFO_EMPTYING)
INT_MASTER_HALTED | \
INT_STOP_DETECTED)
#define INT_ENABLE_MASK_WAITSTOP (INT_SLAVE_EVENT | \
INT_ADDR_ACK_ERR | \
@@ -511,7 +513,17 @@ static void img_i2c_soft_reset(struct img_i2c *i2c)
SCB_CONTROL_CLK_ENABLE | SCB_CONTROL_SOFT_RESET);
}
/* enable or release transaction halt for control of repeated starts */
/*
* Enable or release transaction halt for control of repeated starts.
* In version 3.3 of the IP when transaction halt is set, an interrupt
* will be generated after each byte of a transfer instead of after
* every transfer but before the stop bit.
* Due to this behaviour we have to be careful that every time we
* release the transaction halt we have to re-enable it straight away
* so that we only process a single byte, not doing so will result in
* all remaining bytes been processed and a stop bit being issued,
* which will prevent us having a repeated start.
*/
static void img_i2c_transaction_halt(struct img_i2c *i2c, bool t_halt)
{
u32 val;
@@ -580,7 +592,6 @@ static void img_i2c_read(struct img_i2c *i2c)
img_i2c_writel(i2c, SCB_READ_ADDR_REG, i2c->msg.addr);
img_i2c_writel(i2c, SCB_READ_COUNT_REG, i2c->msg.len);
img_i2c_transaction_halt(i2c, false);
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
}
@@ -594,7 +605,6 @@ static void img_i2c_write(struct img_i2c *i2c)
img_i2c_writel(i2c, SCB_WRITE_ADDR_REG, i2c->msg.addr);
img_i2c_writel(i2c, SCB_WRITE_COUNT_REG, i2c->msg.len);
img_i2c_transaction_halt(i2c, false);
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
img_i2c_write_fifo(i2c);
@@ -750,7 +760,9 @@ static unsigned int img_i2c_atomic(struct img_i2c *i2c,
next_cmd = CMD_RET_ACK;
break;
case CMD_RET_ACK:
if (i2c->line_status & LINESTAT_ACK_DET) {
if (i2c->line_status & LINESTAT_ACK_DET ||
(i2c->line_status & LINESTAT_NACK_DET &&
i2c->msg.flags & I2C_M_IGNORE_NAK)) {
if (i2c->msg.len == 0) {
next_cmd = CMD_GEN_STOP;
} else if (i2c->msg.flags & I2C_M_RD) {
@@ -858,34 +870,42 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
/* Enable transaction halt on start bit */
if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) {
img_i2c_transaction_halt(i2c, true);
img_i2c_transaction_halt(i2c, !i2c->last_msg);
/* we're no longer interested in the slave event */
i2c->int_enable &= ~INT_SLAVE_EVENT;
}
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
if (int_status & INT_STOP_DETECTED) {
/* Drain remaining data in FIFO and complete transaction */
if (i2c->msg.flags & I2C_M_RD)
img_i2c_read_fifo(i2c);
return ISR_COMPLETE(0);
}
if (i2c->msg.flags & I2C_M_RD) {
if (int_status & INT_FIFO_FULL_FILLING) {
if (int_status & (INT_FIFO_FULL_FILLING | INT_MASTER_HALTED)) {
img_i2c_read_fifo(i2c);
if (i2c->msg.len == 0)
return ISR_WAITSTOP;
}
} else {
if (int_status & INT_FIFO_EMPTY_EMPTYING) {
/*
* The write fifo empty indicates that we're in the
* last byte so it's safe to start a new write
* transaction without losing any bytes from the
* previous one.
* see 2.3.7 Repeated Start Transactions.
*/
if (int_status & (INT_FIFO_EMPTY | INT_MASTER_HALTED)) {
if ((int_status & INT_FIFO_EMPTY) &&
i2c->msg.len == 0)
return ISR_WAITSTOP;
img_i2c_write_fifo(i2c);
}
}
if (int_status & INT_MASTER_HALTED) {
/*
* Release and then enable transaction halt, to
* allow only a single byte to proceed.
*/
img_i2c_transaction_halt(i2c, false);
img_i2c_transaction_halt(i2c, !i2c->last_msg);
}
return 0;
}
@@ -1017,20 +1037,23 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
return -EIO;
for (i = 0; i < num; i++) {
if (likely(msgs[i].len))
continue;
/*
* 0 byte reads are not possible because the slave could try
* and pull the data line low, preventing a stop bit.
*/
if (unlikely(msgs[i].flags & I2C_M_RD))
if (!msgs[i].len && msgs[i].flags & I2C_M_RD)
return -EIO;
/*
* 0 byte writes are possible and used for probing, but we
* cannot do them in automatic mode, so use atomic mode
* instead.
*
* Also, the I2C_M_IGNORE_NAK mode can only be implemented
* in atomic mode.
*/
atomic = true;
if (!msgs[i].len ||
(msgs[i].flags & I2C_M_IGNORE_NAK))
atomic = true;
}
ret = clk_prepare_enable(i2c->scb_clk);
@@ -1069,12 +1092,31 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0);
img_i2c_writel(i2c, SCB_CLEAR_REG, ~0);
if (atomic)
if (atomic) {
img_i2c_atomic_start(i2c);
else if (msg->flags & I2C_M_RD)
img_i2c_read(i2c);
else
img_i2c_write(i2c);
} else {
/*
* Enable transaction halt if not the last message in
* the queue so that we can control repeated starts.
*/
img_i2c_transaction_halt(i2c, !i2c->last_msg);
if (msg->flags & I2C_M_RD)
img_i2c_read(i2c);
else
img_i2c_write(i2c);
/*
* Release and then enable transaction halt, to
* allow only a single byte to proceed.
* This doesn't have an effect on the initial transfer
* but will allow the following transfers to start
* processing if the previous transfer was marked as
* complete while the i2c block was halted.
*/
img_i2c_transaction_halt(i2c, false);
img_i2c_transaction_halt(i2c, !i2c->last_msg);
}
spin_unlock_irqrestore(&i2c->lock, flags);
time_left = wait_for_completion_timeout(&i2c->msg_complete,

View File

@@ -29,9 +29,6 @@
*
*/
/** Includes *******************************************************************
*******************************************************************************/
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -53,12 +50,10 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/i2c-imx.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/slab.h>
/** Defines ********************************************************************
*******************************************************************************/
/* This will be the driver name the kernel reports */
#define DRIVER_NAME "imx-i2c"
@@ -120,8 +115,7 @@
#define I2CR_IEN_OPCODE_0 0x0
#define I2CR_IEN_OPCODE_1 I2CR_IEN
/** Variables ******************************************************************
*******************************************************************************/
#define I2C_PM_TIMEOUT 10 /* ms */
/*
* sorted list of clock divider, register value pairs
@@ -346,7 +340,7 @@ fail_tx:
dma_release_channel(dma->chan_tx);
fail_al:
devm_kfree(dev, dma);
dev_info(dev, "can't use DMA\n");
dev_info(dev, "can't use DMA, using PIO instead.\n");
}
static void i2c_imx_dma_callback(void *arg)
@@ -393,6 +387,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
return 0;
err_submit:
dmaengine_terminate_all(dma->chan_using);
err_desc:
dma_unmap_single(chan_dev, dma->dma_buf,
dma->dma_len, dma->dma_data_dir);
@@ -416,9 +411,6 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL;
}
/** Functions for IMX I2C adapter driver ***************************************
*******************************************************************************/
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
{
unsigned long orig_jiffies = jiffies;
@@ -527,9 +519,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
i2c_imx_set_clk(i2c_imx);
result = clk_prepare_enable(i2c_imx->clk);
if (result)
return result;
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
/* Enable I2C controller */
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
@@ -582,7 +571,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
/* Disable I2C controller */
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 irqreturn_t i2c_imx_isr(int irq, void *dev_id)
@@ -901,6 +889,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
if (result < 0)
goto out;
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx);
if (result) {
@@ -964,6 +956,10 @@ fail0:
/* Stop I2C transfer */
i2c_imx_stop(i2c_imx);
pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
out:
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
@@ -997,10 +993,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
PINCTRL_STATE_DEFAULT);
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
"gpio");
rinfo->sda_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
"sda-gpios", 0, NULL);
rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
"scl-gpios", 0, NULL);
rinfo->sda_gpio = of_get_named_gpio(pdev->dev.of_node, "sda-gpios", 0);
rinfo->scl_gpio = of_get_named_gpio(pdev->dev.of_node, "scl-gpios", 0);
if (!gpio_is_valid(rinfo->sda_gpio) ||
!gpio_is_valid(rinfo->scl_gpio) ||
@@ -1083,7 +1077,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
ret = clk_prepare_enable(i2c_imx->clk);
if (ret) {
dev_err(&pdev->dev, "can't enable I2C clock\n");
dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
return ret;
}
@@ -1107,6 +1101,18 @@ static int i2c_imx_probe(struct platform_device *pdev)
/* Set up adapter data */
i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
/* Set up platform driver data */
platform_set_drvdata(pdev, i2c_imx);
pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0)
goto rpm_disable;
/* Set up clock divider */
i2c_imx->bitrate = IMX_I2C_BIT_RATE;
ret = of_property_read_u32(pdev->dev.of_node,
@@ -1125,12 +1131,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) {
dev_err(&pdev->dev, "registration failed\n");
goto clk_disable;
goto rpm_disable;
}
/* Set up platform driver data */
platform_set_drvdata(pdev, i2c_imx);
clk_disable_unprepare(i2c_imx->clk);
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
@@ -1143,6 +1148,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
return 0; /* Return OK */
rpm_disable:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
clk_disable:
clk_disable_unprepare(i2c_imx->clk);
return ret;
@@ -1151,6 +1162,11 @@ clk_disable:
static int i2c_imx_remove(struct platform_device *pdev)
{
struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
int ret;
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0)
return ret;
/* remove adapter */
dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -1165,17 +1181,54 @@ static int i2c_imx_remove(struct platform_device *pdev)
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
clk_disable_unprepare(i2c_imx->clk);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM
static int i2c_imx_runtime_suspend(struct device *dev)
{
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
clk_disable_unprepare(i2c_imx->clk);
return 0;
}
static int i2c_imx_runtime_resume(struct device *dev)
{
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(i2c_imx->clk);
if (ret)
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
return ret;
}
static const struct dev_pm_ops i2c_imx_pm_ops = {
SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend,
i2c_imx_runtime_resume, NULL)
};
#define I2C_IMX_PM_OPS (&i2c_imx_pm_ops)
#else
#define I2C_IMX_PM_OPS NULL
#endif /* CONFIG_PM */
static struct platform_driver i2c_imx_driver = {
.probe = i2c_imx_probe,
.remove = i2c_imx_remove,
.driver = {
.name = DRIVER_NAME,
.driver = {
.name = DRIVER_NAME,
.pm = I2C_IMX_PM_OPS,
.of_match_table = i2c_imx_dt_ids,
},
.id_table = imx_i2c_devtype,
.id_table = imx_i2c_devtype,
};
static int __init i2c_adap_imx_init(void)

View File

@@ -132,6 +132,7 @@ struct mtk_i2c_compatible {
unsigned char pmic_i2c: 1;
unsigned char dcm: 1;
unsigned char auto_restart: 1;
unsigned char aux_len_reg: 1;
};
struct mtk_i2c {
@@ -153,6 +154,8 @@ struct mtk_i2c {
enum mtk_trans_op op;
u16 timing_reg;
u16 high_speed_reg;
unsigned char auto_restart;
bool ignore_restart_irq;
const struct mtk_i2c_compatible *dev_comp;
};
@@ -178,6 +181,7 @@ static const struct mtk_i2c_compatible mt6577_compat = {
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 0,
.aux_len_reg = 0,
};
static const struct mtk_i2c_compatible mt6589_compat = {
@@ -185,6 +189,7 @@ static const struct mtk_i2c_compatible mt6589_compat = {
.pmic_i2c = 1,
.dcm = 0,
.auto_restart = 0,
.aux_len_reg = 0,
};
static const struct mtk_i2c_compatible mt8173_compat = {
@@ -192,6 +197,7 @@ static const struct mtk_i2c_compatible mt8173_compat = {
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
};
static const struct of_device_id mtk_i2c_of_match[] = {
@@ -373,7 +379,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
i2c->irq_stat = 0;
if (i2c->dev_comp->auto_restart)
if (i2c->auto_restart)
restart_flag = I2C_RS_TRANSFER;
reinit_completion(&i2c->msg_complete);
@@ -411,8 +417,14 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
/* Set transfer and transaction len */
if (i2c->op == I2C_MASTER_WRRD) {
writew(msgs->len | ((msgs + 1)->len) << 8,
i2c->base + OFFSET_TRANSFER_LEN);
if (i2c->dev_comp->aux_len_reg) {
writew(msgs->len, i2c->base + OFFSET_TRANSFER_LEN);
writew((msgs + 1)->len, i2c->base +
OFFSET_TRANSFER_LEN_AUX);
} else {
writew(msgs->len | ((msgs + 1)->len) << 8,
i2c->base + OFFSET_TRANSFER_LEN);
}
writew(I2C_WRRD_TRANAC_VALUE, i2c->base + OFFSET_TRANSAC_LEN);
} else {
writew(msgs->len, i2c->base + OFFSET_TRANSFER_LEN);
@@ -461,7 +473,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN);
if (!i2c->dev_comp->auto_restart) {
if (!i2c->auto_restart) {
start_reg = I2C_TRANSAC_START;
} else {
start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
@@ -518,6 +530,24 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
if (ret)
return ret;
i2c->auto_restart = i2c->dev_comp->auto_restart;
/* checking if we can skip restart and optimize using WRRD mode */
if (i2c->auto_restart && num == 2) {
if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) &&
msgs[0].addr == msgs[1].addr) {
i2c->auto_restart = 0;
}
}
if (i2c->auto_restart && num >= 2 && i2c->speed_hz > MAX_FS_MODE_SPEED)
/* ignore the first restart irq after the master code,
* otherwise the first transfer will be discarded.
*/
i2c->ignore_restart_irq = true;
else
i2c->ignore_restart_irq = false;
while (left_num--) {
if (!msgs->buf) {
dev_dbg(i2c->dev, "data buffer is NULL.\n");
@@ -530,7 +560,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
else
i2c->op = I2C_MASTER_WR;
if (!i2c->dev_comp->auto_restart) {
if (!i2c->auto_restart) {
if (num > 1) {
/* combined two messages into one transaction */
i2c->op = I2C_MASTER_WRRD;
@@ -559,7 +589,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
u16 restart_flag = 0;
u16 intr_stat;
if (i2c->dev_comp->auto_restart)
if (i2c->auto_restart)
restart_flag = I2C_RS_TRANSFER;
intr_stat = readw(i2c->base + OFFSET_INTR_STAT);
@@ -571,8 +601,16 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
* i2c->irq_stat need keep the two interrupt value.
*/
i2c->irq_stat |= intr_stat;
if (i2c->irq_stat & (I2C_TRANSAC_COMP | restart_flag))
complete(&i2c->msg_complete);
if (i2c->ignore_restart_irq && (i2c->irq_stat & restart_flag)) {
i2c->ignore_restart_irq = false;
i2c->irq_stat = 0;
writew(I2C_RS_MUL_CNFG | I2C_RS_MUL_TRIG | I2C_TRANSAC_START,
i2c->base + OFFSET_START);
} else {
if (i2c->irq_stat & (I2C_TRANSAC_COMP | restart_flag))
complete(&i2c->msg_complete);
}
return IRQ_HANDLED;
}

View File

@@ -23,6 +23,9 @@
Note: we assume there can only be one device, with one or more
SMBus interfaces.
The device can register multiple i2c_adapters (up to PIIX4_MAX_ADAPTERS).
For devices supporting multiple ports the i2c_adapter should provide
an i2c_algorithm to access them.
*/
#include <linux/module.h>
@@ -37,6 +40,7 @@
#include <linux/dmi.h>
#include <linux/acpi.h>
#include <linux/io.h>
#include <linux/mutex.h>
/* PIIX4 SMBus address offsets */
@@ -75,6 +79,16 @@
#define PIIX4_WORD_DATA 0x0C
#define PIIX4_BLOCK_DATA 0x14
/* Multi-port constants */
#define PIIX4_MAX_ADAPTERS 4
/* SB800 constants */
#define SB800_PIIX4_SMB_IDX 0xcd6
/* SB800 port is selected by bits 2:1 of the smb_en register (0x2c) */
#define SB800_PIIX4_PORT_IDX 0x2c
#define SB800_PIIX4_PORT_IDX_MASK 0x06
/* insmod parameters */
/* If force is set to anything different from 0, we forcibly enable the
@@ -122,8 +136,19 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
{ },
};
/* SB800 globals */
static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
"SDA0", "SDA2", "SDA3", "SDA4"
};
static const char *piix4_aux_port_name_sb800 = "SDA1";
struct i2c_piix4_adapdata {
unsigned short smba;
/* SB800 */
bool sb800_main;
unsigned short port;
struct mutex *mutex;
};
static int piix4_setup(struct pci_dev *PIIX4_dev,
@@ -229,7 +254,6 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
const struct pci_device_id *id, u8 aux)
{
unsigned short piix4_smba;
unsigned short smba_idx = 0xcd6;
u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status;
u8 i2ccfg, i2ccfg_offset = 0x10;
@@ -251,16 +275,10 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
else
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);
return -EBUSY;
}
outb_p(smb_en, smba_idx);
smba_en_lo = inb_p(smba_idx + 1);
outb_p(smb_en + 1, smba_idx);
smba_en_hi = inb_p(smba_idx + 1);
release_region(smba_idx, 2);
outb_p(smb_en, SB800_PIIX4_SMB_IDX);
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
if (!smb_en) {
smb_en_status = smba_en_lo & 0x10;
@@ -483,7 +501,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
return -EINVAL;
outb_p(len, SMBHSTDAT0);
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++)
outb_p(data->block[i], SMBBLKDAT);
}
@@ -516,7 +534,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
data->block[0] = inb_p(SMBHSTDAT0);
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT);
break;
@@ -524,6 +542,43 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
return 0;
}
/*
* Handles access to multiple SMBus ports on the SB800.
* The port is selected by bits 2:1 of the smb_en register (0x2c).
* Returns negative errno on error.
*
* Note: The selected port must be returned to the initial selection to avoid
* problems on certain systems.
*/
static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
u8 smba_en_lo;
u8 port;
int retval;
mutex_lock(adapdata->mutex);
outb_p(SB800_PIIX4_PORT_IDX, SB800_PIIX4_SMB_IDX);
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
port = adapdata->port;
if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != (port << 1))
outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | (port << 1),
SB800_PIIX4_SMB_IDX + 1);
retval = piix4_access(adap, addr, flags, read_write,
command, size, data);
outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
mutex_unlock(adapdata->mutex);
return retval;
}
static u32 piix4_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
@@ -536,6 +591,11 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = piix4_func,
};
static const struct i2c_algorithm piix4_smbus_algorithm_sb800 = {
.smbus_xfer = piix4_access_sb800,
.functionality = piix4_func,
};
static const struct pci_device_id piix4_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
@@ -561,11 +621,11 @@ static const struct pci_device_id piix4_ids[] = {
MODULE_DEVICE_TABLE (pci, piix4_ids);
static struct i2c_adapter *piix4_main_adapter;
static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS];
static struct i2c_adapter *piix4_aux_adapter;
static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
struct i2c_adapter **padap)
const char *name, struct i2c_adapter **padap)
{
struct i2c_adapter *adap;
struct i2c_piix4_adapdata *adapdata;
@@ -594,7 +654,7 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
adap->dev.parent = &dev->dev;
snprintf(adap->name, sizeof(adap->name),
"SMBus PIIX4 adapter at %04x", smba);
"SMBus PIIX4 adapter %s at %04x", name, smba);
i2c_set_adapdata(adap, adapdata);
@@ -611,6 +671,54 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
return 0;
}
static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba)
{
struct mutex *mutex;
struct i2c_piix4_adapdata *adapdata;
int port;
int retval;
mutex = kzalloc(sizeof(*mutex), GFP_KERNEL);
if (mutex == NULL)
return -ENOMEM;
mutex_init(mutex);
for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) {
retval = piix4_add_adapter(dev, smba,
piix4_main_port_names_sb800[port],
&piix4_main_adapters[port]);
if (retval < 0)
goto error;
piix4_main_adapters[port]->algo = &piix4_smbus_algorithm_sb800;
adapdata = i2c_get_adapdata(piix4_main_adapters[port]);
adapdata->sb800_main = true;
adapdata->port = port;
adapdata->mutex = mutex;
}
return retval;
error:
dev_err(&dev->dev,
"Error setting up SB800 adapters. Unregistering!\n");
while (--port >= 0) {
adapdata = i2c_get_adapdata(piix4_main_adapters[port]);
if (adapdata->smba) {
i2c_del_adapter(piix4_main_adapters[port]);
kfree(adapdata);
kfree(piix4_main_adapters[port]);
piix4_main_adapters[port] = NULL;
}
}
kfree(mutex);
return retval;
}
static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int retval;
@@ -618,20 +726,41 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
if ((dev->vendor == PCI_VENDOR_ID_ATI &&
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
dev->revision >= 0x40) ||
dev->vendor == PCI_VENDOR_ID_AMD)
dev->vendor == PCI_VENDOR_ID_AMD) {
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
dev_err(&dev->dev,
"SMBus base address index region 0x%x already in use!\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
/* base address location etc changed in SB800 */
retval = piix4_setup_sb800(dev, id, 0);
else
if (retval < 0) {
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval;
}
/*
* Try to register multiplexed main SMBus adapter,
* give up if we can't
*/
retval = piix4_add_adapters_sb800(dev, retval);
if (retval < 0) {
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval;
}
} else {
retval = piix4_setup(dev, id);
if (retval < 0)
return retval;
/* If no main SMBus found, give up */
if (retval < 0)
return retval;
/* Try to register main SMBus adapter, give up if we can't */
retval = piix4_add_adapter(dev, retval, &piix4_main_adapter);
if (retval < 0)
return retval;
/* Try to register main SMBus adapter, give up if we can't */
retval = piix4_add_adapter(dev, retval, "main",
&piix4_main_adapters[0]);
if (retval < 0)
return retval;
}
/* Check for auxiliary SMBus on some AMD chipsets */
retval = -ENODEV;
@@ -654,7 +783,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
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);
piix4_add_adapter(dev, retval, piix4_aux_port_name_sb800,
&piix4_aux_adapter);
}
return 0;
@@ -666,7 +796,13 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
if (adapdata->smba) {
i2c_del_adapter(adap);
release_region(adapdata->smba, SMBIOSIZE);
if (adapdata->port == 0) {
release_region(adapdata->smba, SMBIOSIZE);
if (adapdata->sb800_main) {
kfree(adapdata->mutex);
release_region(SB800_PIIX4_SMB_IDX, 2);
}
}
kfree(adapdata);
kfree(adap);
}
@@ -674,9 +810,13 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
static void piix4_remove(struct pci_dev *dev)
{
if (piix4_main_adapter) {
piix4_adap_remove(piix4_main_adapter);
piix4_main_adapter = NULL;
int port = PIIX4_MAX_ADAPTERS;
while (--port >= 0) {
if (piix4_main_adapters[port]) {
piix4_adap_remove(piix4_main_adapters[port]);
piix4_main_adapters[port] = NULL;
}
}
if (piix4_aux_adapter) {

View File

@@ -1,7 +1,8 @@
/*
* Driver for the Renesas RCar I2C unit
*
* Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com>
* Copyright (C) 2014-15 Wolfram Sang <wsa@sang-engineering.com>
* Copyright (C) 2011-2015 Renesas Electronics Corporation
*
* Copyright (C) 2012-14 Renesas Solutions Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
@@ -9,9 +10,6 @@
* This file is based on the drivers/i2c/busses/i2c-sh7760.c
* (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
*
* This file used out-of-tree driver i2c-rcar.c
* Copyright (C) 2011-2012 Renesas Electronics Corporation
*
* 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 of the License.
@@ -33,7 +31,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
/* register offsets */
#define ICSCR 0x00 /* slave ctrl */
@@ -84,6 +81,7 @@
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
#define RCAR_BUS_MASK_DATA (~(ESG | FSB) & 0xFF)
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE)
@@ -94,10 +92,13 @@
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF)
#define ID_LAST_MSG (1 << 0)
#define ID_IOERROR (1 << 1)
#define ID_FIRST_MSG (1 << 1)
#define ID_DONE (1 << 2)
#define ID_ARBLOST (1 << 3)
#define ID_NACK (1 << 4)
/* persistent flags */
#define ID_P_PM_BLOCKED (1 << 31)
#define ID_P_MASK ID_P_PM_BLOCKED
enum rcar_i2c_type {
I2C_RCAR_GEN1,
@@ -108,10 +109,10 @@ enum rcar_i2c_type {
struct rcar_i2c_priv {
void __iomem *io;
struct i2c_adapter adap;
struct i2c_msg *msg;
struct i2c_msg *msg;
int msgs_left;
struct clk *clk;
spinlock_t lock;
wait_queue_head_t wait;
int pos;
@@ -124,9 +125,6 @@ struct rcar_i2c_priv {
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
#define rcar_i2c_is_recv(p) ((p)->msg->flags & I2C_M_RD)
#define rcar_i2c_flags_set(p, f) ((p)->flags |= (f))
#define rcar_i2c_flags_has(p, f) ((p)->flags & (f))
#define LOOP_TIMEOUT 1024
@@ -144,9 +142,10 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
{
/* reset master mode */
rcar_i2c_write(priv, ICMIER, 0);
rcar_i2c_write(priv, ICMCR, 0);
rcar_i2c_write(priv, ICMCR, MDBS);
rcar_i2c_write(priv, ICMSR, 0);
rcar_i2c_write(priv, ICMAR, 0);
/* start clock */
rcar_i2c_write(priv, ICCCR, priv->icccr);
}
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
@@ -163,15 +162,17 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
return -EBUSY;
}
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
u32 bus_speed,
struct device *dev)
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, struct i2c_timings *t)
{
u32 scgd, cdf;
u32 round, ick;
u32 scl;
u32 cdf_width;
u32 scgd, cdf, round, ick, sum, scl, cdf_width;
unsigned long rate;
struct device *dev = rcar_i2c_priv_to_dev(priv);
/* Fall back to previously used values if not supplied */
t->bus_freq_hz = t->bus_freq_hz ?: 100000;
t->scl_fall_ns = t->scl_fall_ns ?: 35;
t->scl_rise_ns = t->scl_rise_ns ?: 200;
t->scl_int_delay_ns = t->scl_int_delay_ns ?: 50;
switch (priv->devtype) {
case I2C_RCAR_GEN1:
@@ -195,9 +196,9 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
* SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
*
* ick : I2C internal clock < 20 MHz
* ticf : I2C SCL falling time = 35 ns here
* tr : I2C SCL rising time = 200 ns here
* intd : LSI internal delay = 50 ns here
* ticf : I2C SCL falling time
* tr : I2C SCL rising time
* intd : LSI internal delay
* clkp : peripheral_clk
* F[] : integer up-valuation
*/
@@ -213,12 +214,12 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
* it is impossible to calculate large scale
* number on u32. separate it
*
* F[(ticf + tr + intd) * ick]
* = F[(35 + 200 + 50)ns * ick]
* = F[285 * ick / 1000000000]
* = F[(ick / 1000000) * 285 / 1000]
* F[(ticf + tr + intd) * ick] with sum = (ticf + tr + intd)
* = F[sum * ick / 1000000000]
* = F[(ick / 1000000) * sum / 1000]
*/
round = (ick + 500000) / 1000000 * 285;
sum = t->scl_fall_ns + t->scl_rise_ns + t->scl_int_delay_ns;
round = (ick + 500000) / 1000000 * sum;
round = (round + 500) / 1000;
/*
@@ -235,7 +236,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
*/
for (scgd = 0; scgd < 0x40; scgd++) {
scl = ick / (20 + (scgd * 8) + round);
if (scl <= bus_speed)
if (scl <= t->bus_freq_hz)
goto scgd_find;
}
dev_err(dev, "it is impossible to calculate best SCL\n");
@@ -243,11 +244,9 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
scgd_find:
dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
scl, bus_speed, clk_get_rate(priv->clk), round, cdf, scgd);
scl, t->bus_freq_hz, clk_get_rate(priv->clk), round, cdf, scgd);
/*
* keep icccr value
*/
/* keep icccr value */
priv->icccr = scgd << cdf_width | cdf;
return 0;
@@ -257,33 +256,44 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
{
int read = !!rcar_i2c_is_recv(priv);
priv->pos = 0;
if (priv->msgs_left == 1)
priv->flags |= ID_LAST_MSG;
rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
rcar_i2c_write(priv, ICMSR, 0);
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
/*
* We don't have a testcase but the HW engineers say that the write order
* of ICMSR and ICMCR depends on whether we issue START or REP_START. Since
* it didn't cause a drawback for me, let's rather be safe than sorry.
*/
if (priv->flags & ID_FIRST_MSG) {
rcar_i2c_write(priv, ICMSR, 0);
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
} else {
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
rcar_i2c_write(priv, ICMSR, 0);
}
rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
}
static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)
{
priv->msg++;
priv->msgs_left--;
priv->flags &= ID_P_MASK;
rcar_i2c_prepare_msg(priv);
}
/*
* interrupt functions
*/
static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
{
struct i2c_msg *msg = priv->msg;
/*
* FIXME
* sometimes, unknown interrupt happened.
* Do nothing
*/
/* FIXME: sometimes, unknown interrupt happened. Do nothing */
if (!(msr & MDE))
return 0;
/*
* If address transfer phase finished,
* goto data phase.
*/
if (msr & MAT)
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
return;
if (priv->pos < msg->len) {
/*
@@ -305,67 +315,50 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
* [ICRXTX] -> [SHIFT] -> [I2C bus]
*/
if (priv->flags & ID_LAST_MSG)
if (priv->flags & ID_LAST_MSG) {
/*
* If current msg is the _LAST_ msg,
* prepare stop condition here.
* ID_DONE will be set on STOP irq.
*/
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
else
/*
* If current msg is _NOT_ last msg,
* it doesn't call stop phase.
* thus, there is no STOP irq.
* return ID_DONE here.
*/
return ID_DONE;
} else {
rcar_i2c_next_msg(priv);
return;
}
}
rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND);
return 0;
}
static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
{
struct i2c_msg *msg = priv->msg;
/*
* FIXME
* sometimes, unknown interrupt happened.
* Do nothing
*/
/* FIXME: sometimes, unknown interrupt happened. Do nothing */
if (!(msr & MDR))
return 0;
return;
if (msr & MAT) {
/*
* Address transfer phase finished,
* but, there is no data at this point.
* Do nothing.
*/
/* Address transfer phase finished, but no data at this point. */
} else if (priv->pos < msg->len) {
/*
* get received data
*/
/* get received data */
msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
priv->pos++;
}
/*
* If next received data is the _LAST_,
* go to STOP phase,
* otherwise, go to DATA phase.
* If next received data is the _LAST_, go to STOP phase. Might be
* overwritten by REP START when setting up a new msg. Not elegant
* but the only stable sequence for REP START I have found so far.
*/
if (priv->pos + 1 >= msg->len)
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG))
rcar_i2c_next_msg(priv);
else
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV);
return 0;
rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV);
}
static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
@@ -426,62 +419,57 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
{
struct rcar_i2c_priv *priv = ptr;
irqreturn_t result = IRQ_HANDLED;
u32 msr;
u32 msr, val;
/*-------------- spin lock -----------------*/
spin_lock(&priv->lock);
if (rcar_i2c_slave_irq(priv))
goto exit;
/* Clear START or STOP as soon as we can */
val = rcar_i2c_read(priv, ICMCR);
rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
msr = rcar_i2c_read(priv, ICMSR);
/* Only handle interrupts that are currently enabled */
msr &= rcar_i2c_read(priv, ICMIER);
if (!msr) {
result = IRQ_NONE;
goto exit;
if (rcar_i2c_slave_irq(priv))
return IRQ_HANDLED;
return IRQ_NONE;
}
/* Arbitration lost */
if (msr & MAL) {
rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
priv->flags |= ID_DONE | ID_ARBLOST;
goto out;
}
/* Nack */
if (msr & MNR) {
/* go to stop phase */
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
/* HW automatically sends STOP after received NACK */
rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP);
rcar_i2c_flags_set(priv, ID_NACK);
priv->flags |= ID_NACK;
goto out;
}
/* Stop */
if (msr & MST) {
rcar_i2c_flags_set(priv, ID_DONE);
priv->msgs_left--; /* The last message also made it */
priv->flags |= ID_DONE;
goto out;
}
if (rcar_i2c_is_recv(priv))
rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
rcar_i2c_irq_recv(priv, msr);
else
rcar_i2c_flags_set(priv, rcar_i2c_irq_send(priv, msr));
rcar_i2c_irq_send(priv, msr);
out:
if (rcar_i2c_flags_has(priv, ID_DONE)) {
if (priv->flags & ID_DONE) {
rcar_i2c_write(priv, ICMIER, 0);
rcar_i2c_write(priv, ICMSR, 0);
wake_up(&priv->wait);
}
exit:
spin_unlock(&priv->lock);
/*-------------- spin unlock -----------------*/
return result;
return IRQ_HANDLED;
}
static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
@@ -490,22 +478,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv);
unsigned long flags;
int i, ret;
long timeout;
long time_left;
pm_runtime_get_sync(dev);
/*-------------- spin lock -----------------*/
spin_lock_irqsave(&priv->lock, flags);
rcar_i2c_init(priv);
/* start clock */
rcar_i2c_write(priv, ICCCR, priv->icccr);
spin_unlock_irqrestore(&priv->lock, flags);
/*-------------- spin unlock -----------------*/
ret = rcar_i2c_bus_barrier(priv);
if (ret < 0)
goto out;
@@ -514,48 +491,27 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
/* This HW can't send STOP after address phase */
if (msgs[i].len == 0) {
ret = -EOPNOTSUPP;
break;
goto out;
}
}
/*-------------- spin lock -----------------*/
spin_lock_irqsave(&priv->lock, flags);
/* init first message */
priv->msg = msgs;
priv->msgs_left = num;
priv->flags = (priv->flags & ID_P_MASK) | ID_FIRST_MSG;
rcar_i2c_prepare_msg(priv);
/* init each data */
priv->msg = &msgs[i];
priv->pos = 0;
priv->flags = 0;
if (i == num - 1)
rcar_i2c_flags_set(priv, ID_LAST_MSG);
rcar_i2c_prepare_msg(priv);
spin_unlock_irqrestore(&priv->lock, flags);
/*-------------- spin unlock -----------------*/
timeout = wait_event_timeout(priv->wait,
rcar_i2c_flags_has(priv, ID_DONE),
adap->timeout);
if (!timeout) {
ret = -ETIMEDOUT;
break;
}
if (rcar_i2c_flags_has(priv, ID_NACK)) {
ret = -ENXIO;
break;
}
if (rcar_i2c_flags_has(priv, ID_ARBLOST)) {
ret = -EAGAIN;
break;
}
if (rcar_i2c_flags_has(priv, ID_IOERROR)) {
ret = -EIO;
break;
}
ret = i + 1; /* The number of transfer */
time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE,
num * adap->timeout);
if (!time_left) {
rcar_i2c_init(priv);
ret = -ETIMEDOUT;
} else if (priv->flags & ID_NACK) {
ret = -ENXIO;
} else if (priv->flags & ID_ARBLOST) {
ret = -EAGAIN;
} else {
ret = num - priv->msgs_left; /* The number of transfer */
}
out:
pm_runtime_put(dev);
@@ -637,7 +593,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *res;
struct device *dev = &pdev->dev;
u32 bus_speed;
struct i2c_timings i2c_t;
int irq, ret;
priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL);
@@ -650,23 +606,13 @@ static int rcar_i2c_probe(struct platform_device *pdev)
return PTR_ERR(priv->clk);
}
bus_speed = 100000; /* default 100 kHz */
of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed);
priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data;
ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
if (ret < 0)
return ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->io))
return PTR_ERR(priv->io);
irq = platform_get_irq(pdev, 0);
priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data;
init_waitqueue_head(&priv->wait);
spin_lock_init(&priv->lock);
adap = &priv->adap;
adap->nr = pdev->id;
@@ -678,26 +624,47 @@ static int rcar_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, priv);
strlcpy(adap->name, pdev->name, sizeof(adap->name));
ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0,
dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "cannot get irq %d\n", irq);
return ret;
}
i2c_parse_fw_timings(dev, &i2c_t, false);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
ret = rcar_i2c_clock_calculate(priv, &i2c_t);
if (ret < 0)
goto out_pm_put;
rcar_i2c_init(priv);
/* Don't suspend when multi-master to keep arbitration working */
if (of_property_read_bool(dev->of_node, "multi-master"))
priv->flags |= ID_P_PM_BLOCKED;
else
pm_runtime_put(dev);
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "cannot get irq %d\n", irq);
goto out_pm_disable;
}
platform_set_drvdata(pdev, priv);
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(dev, "reg adap failed: %d\n", ret);
pm_runtime_disable(dev);
return ret;
goto out_pm_disable;
}
dev_info(dev, "probed\n");
return 0;
out_pm_put:
pm_runtime_put(dev);
out_pm_disable:
pm_runtime_disable(dev);
return ret;
}
static int rcar_i2c_remove(struct platform_device *pdev)
@@ -706,6 +673,8 @@ static int rcar_i2c_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
i2c_del_adapter(&priv->adap);
if (priv->flags & ID_P_PM_BLOCKED)
pm_runtime_put(dev);
pm_runtime_disable(dev);
return 0;

View File

@@ -784,7 +784,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
int retry;
int ret;
pm_runtime_get_sync(&adap->dev);
ret = clk_enable(i2c->clk);
if (ret)
return ret;
@@ -795,7 +794,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
if (ret != -EAGAIN) {
clk_disable(i2c->clk);
pm_runtime_put(&adap->dev);
return ret;
}
@@ -805,7 +803,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
}
clk_disable(i2c->clk);
pm_runtime_put(&adap->dev);
return -EREMOTEIO;
}
@@ -1256,8 +1253,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return ret;
}
pm_runtime_enable(&i2c->adap.dev);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
}
@@ -1273,7 +1268,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
clk_unprepare(i2c->clk);
pm_runtime_disable(&i2c->adap.dev);
pm_runtime_disable(&pdev->dev);
s3c24xx_i2c_deregister_cpufreq(i2c);

View File

@@ -708,8 +708,7 @@ static int st_i2c_xfer(struct i2c_adapter *i2c_adap,
#ifdef CONFIG_PM_SLEEP
static int st_i2c_suspend(struct device *dev)
{
struct platform_device *pdev =
container_of(dev, struct platform_device, dev);
struct platform_device *pdev = to_platform_device(dev);
struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
if (i2c_dev->busy)

View File

@@ -130,7 +130,13 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
return 0;
} else {
if (p[0] == 'x') {
data->byte = simple_strtol(p + 1, NULL, 16);
/*
* Voluntarily dropping error code of kstrtou8 since all
* error code that it could return are invalid according
* to Documentation/i2c/fault-codes.
*/
if (kstrtou8(p + 1, 16, &data->byte))
return -EPROTO;
return 0;
}
}

View File

@@ -466,6 +466,11 @@ static int uniphier_fi2c_clk_init(struct device *dev,
if (of_property_read_u32(np, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;
if (!bus_speed) {
dev_err(dev, "clock-freqyency should not be zero\n");
return -EINVAL;
}
if (bus_speed > UNIPHIER_FI2C_MAX_SPEED)
bus_speed = UNIPHIER_FI2C_MAX_SPEED;
@@ -481,6 +486,10 @@ static int uniphier_fi2c_clk_init(struct device *dev,
return ret;
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
return -EINVAL;
}
uniphier_fi2c_reset(priv);
@@ -531,7 +540,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
ret = uniphier_fi2c_clk_init(dev, priv);
if (ret)
return ret;
goto err;
ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0,
pdev->name, priv);

View File

@@ -327,6 +327,11 @@ static int uniphier_i2c_clk_init(struct device *dev,
if (of_property_read_u32(np, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_I2C_DEFAULT_SPEED;
if (!bus_speed) {
dev_err(dev, "clock-freqyency should not be zero\n");
return -EINVAL;
}
if (bus_speed > UNIPHIER_I2C_MAX_SPEED)
bus_speed = UNIPHIER_I2C_MAX_SPEED;
@@ -342,6 +347,10 @@ static int uniphier_i2c_clk_init(struct device *dev,
return ret;
clk_rate = clk_get_rate(priv->clk);
if (!clk_rate) {
dev_err(dev, "input clock rate should not be zero\n");
return -EINVAL;
}
uniphier_i2c_reset(priv, true);
@@ -388,7 +397,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
ret = uniphier_i2c_clk_init(dev, priv);
if (ret)
return ret;
goto err;
ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name,
priv);

View File

@@ -70,7 +70,7 @@ struct xiic_i2c {
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_msg *tx_msg;
spinlock_t lock;
struct mutex lock;
unsigned int tx_pos;
unsigned int nmsgs;
enum xilinx_i2c_state state;
@@ -369,7 +369,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
* To find which interrupts are pending; AND interrupts pending with
* interrupts masked.
*/
spin_lock(&i2c->lock);
mutex_lock(&i2c->lock);
isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
pend = isr & ier;
@@ -497,7 +497,7 @@ out:
dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);
xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr);
spin_unlock(&i2c->lock);
mutex_unlock(&i2c->lock);
return IRQ_HANDLED;
}
@@ -662,10 +662,10 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)
static void xiic_start_xfer(struct xiic_i2c *i2c)
{
spin_lock(&i2c->lock);
mutex_lock(&i2c->lock);
xiic_reinit(i2c);
__xiic_start_xfer(i2c);
spin_unlock(&i2c->lock);
mutex_unlock(&i2c->lock);
}
static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
@@ -745,7 +745,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
spin_lock_init(&i2c->lock);
mutex_init(&i2c->lock);
init_waitqueue_head(&i2c->wait);
ret = devm_request_threaded_irq(&pdev->dev, irq, xiic_isr,

View File

@@ -17,6 +17,10 @@
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
/* XLR I2C REGISTERS */
#define XLR_I2C_CFG 0x00
@@ -30,6 +34,10 @@
#define XLR_I2C_BYTECNT 0x08
#define XLR_I2C_HDSTATIM 0x09
/* Sigma Designs additional registers */
#define XLR_I2C_INT_EN 0x09
#define XLR_I2C_INT_STAT 0x0a
/* XLR I2C REGISTERS FLAGS */
#define XLR_I2C_BUS_BUSY 0x01
#define XLR_I2C_SDOEMPTY 0x02
@@ -63,11 +71,98 @@ static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
return __raw_readl(base + reg);
}
#define XLR_I2C_FLAG_IRQ 1
struct xlr_i2c_config {
u32 flags; /* optional feature support */
u32 status_busy; /* value of STATUS[0] when busy */
u32 cfg_extra; /* extra CFG bits to set */
};
struct xlr_i2c_private {
struct i2c_adapter adap;
u32 __iomem *iobase;
int irq;
int pos;
struct i2c_msg *msg;
const struct xlr_i2c_config *cfg;
wait_queue_head_t wait;
struct clk *clk;
};
static int xlr_i2c_busy(struct xlr_i2c_private *priv, u32 status)
{
return (status & XLR_I2C_BUS_BUSY) == priv->cfg->status_busy;
}
static int xlr_i2c_idle(struct xlr_i2c_private *priv)
{
return !xlr_i2c_busy(priv, xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS));
}
static int xlr_i2c_wait(struct xlr_i2c_private *priv, unsigned long timeout)
{
int status;
int t;
t = wait_event_timeout(priv->wait, xlr_i2c_idle(priv),
msecs_to_jiffies(timeout));
if (!t)
return -ETIMEDOUT;
status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
return status & XLR_I2C_ACK_ERR ? -EIO : 0;
}
static void xlr_i2c_tx_irq(struct xlr_i2c_private *priv, u32 status)
{
struct i2c_msg *msg = priv->msg;
if (status & XLR_I2C_SDOEMPTY)
xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT,
msg->buf[priv->pos++]);
}
static void xlr_i2c_rx_irq(struct xlr_i2c_private *priv, u32 status)
{
struct i2c_msg *msg = priv->msg;
if (status & XLR_I2C_RXRDY)
msg->buf[priv->pos++] =
xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
}
static irqreturn_t xlr_i2c_irq(int irq, void *dev_id)
{
struct xlr_i2c_private *priv = dev_id;
struct i2c_msg *msg = priv->msg;
u32 int_stat, status;
int_stat = xlr_i2c_rdreg(priv->iobase, XLR_I2C_INT_STAT);
if (!int_stat)
return IRQ_NONE;
xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, int_stat);
if (!msg)
return IRQ_HANDLED;
status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
if (priv->pos < msg->len) {
if (msg->flags & I2C_M_RD)
xlr_i2c_rx_irq(priv, status);
else
xlr_i2c_tx_irq(priv, status);
}
if (!xlr_i2c_busy(priv, status))
wake_up(&priv->wait);
return IRQ_HANDLED;
}
static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
u8 *buf, u16 addr)
{
@@ -75,37 +170,48 @@ static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
unsigned long timeout, stoptime, checktime;
u32 i2c_status;
int pos, timedout;
u8 offset, byte;
u8 offset;
u32 xfer;
if (!len)
return -EOPNOTSUPP;
offset = buf[0];
xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
XLR_I2C_CFG_ADDR | priv->cfg->cfg_extra);
timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
stoptime = jiffies + timeout;
timedout = 0;
pos = 1;
retry:
if (len == 1) {
xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
XLR_I2C_STARTXFR_ND);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
xfer = XLR_I2C_STARTXFR_ND;
pos = 1;
} else {
xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
XLR_I2C_STARTXFR_WR);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 2);
xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[1]);
xfer = XLR_I2C_STARTXFR_WR;
pos = 2;
}
priv->pos = pos;
retry:
/* retry can only happen on the first byte */
xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, xfer);
if (priv->irq > 0)
return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
while (!timedout) {
checktime = jiffies;
i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
if (i2c_status & XLR_I2C_SDOEMPTY) {
pos++;
/* need to do a empty dataout after the last byte */
byte = (pos < len) ? buf[pos] : 0;
xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte);
if ((i2c_status & XLR_I2C_SDOEMPTY) && pos < len) {
xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos++]);
/* reset timeout on successful xmit */
stoptime = jiffies + timeout;
@@ -121,7 +227,7 @@ retry:
if (i2c_status & XLR_I2C_ACK_ERR)
return -EIO;
if ((i2c_status & XLR_I2C_BUS_BUSY) == 0 && pos >= len)
if (!xlr_i2c_busy(priv, i2c_status) && pos >= len)
return 0;
}
dev_err(&adap->dev, "I2C transmit timeout\n");
@@ -134,12 +240,17 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
u32 i2c_status;
unsigned long timeout, stoptime, checktime;
int nbytes, timedout;
u8 byte;
xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
if (!len)
return -EOPNOTSUPP;
xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
priv->pos = 0;
timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
stoptime = jiffies + timeout;
timedout = 0;
@@ -147,18 +258,18 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
retry:
xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
if (priv->irq > 0)
return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
while (!timedout) {
checktime = jiffies;
i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
if (i2c_status & XLR_I2C_RXRDY) {
if (nbytes > len)
if (nbytes >= len)
return -EIO; /* should not happen */
/* we need to do a dummy datain when nbytes == len */
byte = xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
if (nbytes < len)
buf[nbytes] = byte;
nbytes++;
buf[nbytes++] =
xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
/* reset timeout on successful read */
stoptime = jiffies + timeout;
@@ -174,7 +285,7 @@ retry:
if (i2c_status & XLR_I2C_ACK_ERR)
return -EIO;
if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
if (!xlr_i2c_busy(priv, i2c_status))
return 0;
}
@@ -190,8 +301,17 @@ static int xlr_i2c_xfer(struct i2c_adapter *adap,
int ret = 0;
struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
ret = clk_enable(priv->clk);
if (ret)
return ret;
if (priv->irq)
xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0xf);
for (i = 0; ret == 0 && i < num; i++) {
msg = &msgs[i];
priv->msg = msg;
if (msg->flags & I2C_M_RD)
ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
msg->addr);
@@ -200,13 +320,19 @@ static int xlr_i2c_xfer(struct i2c_adapter *adap,
msg->addr);
}
if (priv->irq)
xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
clk_disable(priv->clk);
priv->msg = NULL;
return (ret != 0) ? ret : num;
}
static u32 xlr_func(struct i2c_adapter *adap)
{
/* Emulate SMBUS over I2C */
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
return (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_I2C;
}
static struct i2c_algorithm xlr_i2c_algo = {
@@ -214,22 +340,89 @@ static struct i2c_algorithm xlr_i2c_algo = {
.functionality = xlr_func,
};
static const struct xlr_i2c_config xlr_i2c_config_default = {
.status_busy = XLR_I2C_BUS_BUSY,
.cfg_extra = 0,
};
static const struct xlr_i2c_config xlr_i2c_config_tangox = {
.flags = XLR_I2C_FLAG_IRQ,
.status_busy = 0,
.cfg_extra = 1 << 8,
};
static const struct of_device_id xlr_i2c_dt_ids[] = {
{
.compatible = "sigma,smp8642-i2c",
.data = &xlr_i2c_config_tangox,
},
{ }
};
static int xlr_i2c_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct xlr_i2c_private *priv;
struct resource *res;
struct clk *clk;
unsigned long clk_rate;
unsigned long clk_div;
u32 busfreq;
int irq;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
match = of_match_device(xlr_i2c_dt_ids, &pdev->dev);
if (match)
priv->cfg = match->data;
else
priv->cfg = &xlr_i2c_config_default;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->iobase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->iobase))
return PTR_ERR(priv->iobase);
irq = platform_get_irq(pdev, 0);
if (irq > 0 && (priv->cfg->flags & XLR_I2C_FLAG_IRQ)) {
priv->irq = irq;
xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, 0xf);
ret = devm_request_irq(&pdev->dev, priv->irq, xlr_i2c_irq,
IRQF_SHARED, dev_name(&pdev->dev),
priv);
if (ret)
return ret;
init_waitqueue_head(&priv->wait);
}
if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&busfreq))
busfreq = 100000;
clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) {
ret = clk_prepare_enable(clk);
if (ret)
return ret;
clk_rate = clk_get_rate(clk);
clk_div = DIV_ROUND_UP(clk_rate, 2 * busfreq);
xlr_i2c_wreg(priv->iobase, XLR_I2C_CLKDIV, clk_div);
clk_disable(clk);
priv->clk = clk;
}
priv->adap.dev.parent = &pdev->dev;
priv->adap.dev.of_node = pdev->dev.of_node;
priv->adap.owner = THIS_MODULE;
priv->adap.algo_data = priv;
priv->adap.algo = &xlr_i2c_algo;
@@ -255,6 +448,8 @@ static int xlr_i2c_remove(struct platform_device *pdev)
priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
clk_unprepare(priv->clk);
return 0;
}
@@ -263,6 +458,7 @@ static struct platform_driver xlr_i2c_driver = {
.remove = xlr_i2c_remove,
.driver = {
.name = "xlr-i2cbus",
.of_match_table = xlr_i2c_dt_ids,
},
};

View File

@@ -53,6 +53,7 @@
#include <linux/jump_label.h>
#include <asm/uaccess.h>
#include <linux/err.h>
#include <linux/property.h>
#include "i2c-core.h"
@@ -1563,6 +1564,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
pm_runtime_no_callbacks(&adap->dev);
pm_runtime_enable(&adap->dev);
#ifdef CONFIG_I2C_COMPAT
res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
@@ -1817,6 +1819,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
/* device name is gone after device_unregister */
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
pm_runtime_disable(&adap->dev);
/* wait until all references to the device are gone
*
* FIXME: This is old code and should ideally be replaced by an
@@ -1839,6 +1843,58 @@ void i2c_del_adapter(struct i2c_adapter *adap)
}
EXPORT_SYMBOL(i2c_del_adapter);
/**
* i2c_parse_fw_timings - get I2C related timing parameters from firmware
* @dev: The device to scan for I2C timing properties
* @t: the i2c_timings struct to be filled with values
* @use_defaults: bool to use sane defaults derived from the I2C specification
* when properties are not found, otherwise use 0
*
* Scan the device for the generic I2C properties describing timing parameters
* for the signal and fill the given struct with the results. If a property was
* not found and use_defaults was true, then maximum timings are assumed which
* are derived from the I2C specification. If use_defaults is not used, the
* results will be 0, so drivers can apply their own defaults later. The latter
* is mainly intended for avoiding regressions of existing drivers which want
* to switch to this function. New drivers almost always should use the defaults.
*/
void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults)
{
int ret;
memset(t, 0, sizeof(*t));
ret = device_property_read_u32(dev, "clock-frequency", &t->bus_freq_hz);
if (ret && use_defaults)
t->bus_freq_hz = 100000;
ret = device_property_read_u32(dev, "i2c-scl-rising-time-ns", &t->scl_rise_ns);
if (ret && use_defaults) {
if (t->bus_freq_hz <= 100000)
t->scl_rise_ns = 1000;
else if (t->bus_freq_hz <= 400000)
t->scl_rise_ns = 300;
else
t->scl_rise_ns = 120;
}
ret = device_property_read_u32(dev, "i2c-scl-falling-time-ns", &t->scl_fall_ns);
if (ret && use_defaults) {
if (t->bus_freq_hz <= 400000)
t->scl_fall_ns = 300;
else
t->scl_fall_ns = 120;
}
device_property_read_u32(dev, "i2c-scl-internal-delay-ns", &t->scl_int_delay_ns);
ret = device_property_read_u32(dev, "i2c-sda-falling-time-ns", &t->sda_fall_ns);
if (ret && use_defaults)
t->sda_fall_ns = t->scl_fall_ns;
}
EXPORT_SYMBOL_GPL(i2c_parse_fw_timings);
/* ------------------------------------------------------------------------- */
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))