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

Pull i2c updates from Wolfram Sang:

 - Peter Rosin did some major rework on the locking of i2c muxes by
   seperating parent-locked muxes and mux-locked muxes.

   This avoids deadlocks/workarounds when the mux itself needs i2c
   commands for muxing.  And as a side-effect, other workarounds in the
   media layer could be eliminated.  Also, Peter stepped up as the i2c
   mux maintainer and will keep an eye on these changes.

 - major updates to the octeon driver

 - add a helper to the core to generate the address+rw_bit octal and
   make drivers use it

 - quite a bunch of driver updates

* 'i2c/for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (84 commits)
  i2c: rcar: add DMA support
  i2c: st: Implement bus clear
  i2c: only check scl functions when using generic recovery
  i2c: algo-bit: declare i2c_bit_quirk_no_clk_stretch as static
  i2c: tegra: disable clock before returning error
  [media] rtl2832: regmap is aware of lockdep, drop local locking hack
  [media] rtl2832_sdr: get rid of empty regmap wrappers
  [media] rtl2832: change the i2c gate to be mux-locked
  [media] si2168: change the i2c gate to be mux-locked
  iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
  i2c: mux: document i2c muxes and elaborate on parent-/mux-locked muxes
  i2c: mux: relax locking of the top i2c adapter during mux-locked muxing
  i2c: muxes always lock the parent adapter
  i2c: allow adapter drivers to override the adapter locking
  i2c: uniphier: add "\n" at the end of error log
  i2c: mv64xxx: remove CONFIG_HAVE_CLK conditionals
  i2c: mv64xxx: use clk_{prepare_enable,disable_unprepare}
  i2c: mv64xxx: handle probe deferral for the clock
  i2c: mv64xxx: enable the driver on ARCH_MVEBU
  i2c: octeon: Add workaround for broken irqs on CN3860
  ...
This commit is contained in:
Linus Torvalds
2016-05-19 17:48:12 -07:00
67 changed files with 2709 additions and 1506 deletions

View File

@@ -617,7 +617,7 @@ const struct i2c_algorithm i2c_bit_algo = {
};
EXPORT_SYMBOL(i2c_bit_algo);
const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
static const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
.flags = I2C_AQ_NO_CLK_STRETCH,
};

View File

@@ -663,7 +663,7 @@ config I2C_MT65XX
config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller"
depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
depends on MV64X60 || PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Marvell 64xxx line of host bridges.

View File

@@ -267,7 +267,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c,
iproc_i2c->msg = msg;
/* format and load slave address into the TX FIFO */
addr = msg->addr << 1 | (msg->flags & I2C_M_RD ? 1 : 0);
addr = i2c_8bit_addr_from_msg(msg);
writel(addr, iproc_i2c->base + M_TX_OFFSET);
/*

View File

@@ -501,10 +501,7 @@ static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev,
return -EREMOTEIO;
}
} else {
addr = msg->addr << 1;
if (msg->flags & I2C_M_RD)
addr |= 1;
addr = i2c_8bit_addr_from_msg(msg);
if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
return -EREMOTEIO;

View File

@@ -446,9 +446,7 @@ static int brcmstb_i2c_do_addr(struct brcmstb_i2c_dev *dev,
}
} else {
addr = msg->addr << 1;
if (msg->flags & I2C_M_RD)
addr |= 1;
addr = i2c_8bit_addr_from_msg(msg);
bsc_writel(dev, addr, chip_address);
}

View File

@@ -197,9 +197,7 @@ static void cpm_i2c_parse_message(struct i2c_adapter *adap,
tbdf = cpm->tbase + tx;
rbdf = cpm->rbase + rx;
addr = pmsg->addr << 1;
if (pmsg->flags & I2C_M_RD)
addr |= 1;
addr = i2c_8bit_addr_from_msg(pmsg);
tb = cpm->txbuf[tx];
rb = cpm->rxbuf[rx];

View File

@@ -19,6 +19,7 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/mfd/dln2.h>
#include <linux/acpi.h>
#define DLN2_I2C_MODULE_ID 0x03
#define DLN2_I2C_CMD(cmd) DLN2_CMD(cmd, DLN2_I2C_MODULE_ID)
@@ -210,6 +211,7 @@ static int dln2_i2c_probe(struct platform_device *pdev)
dln2->adapter.algo = &dln2_i2c_usb_algorithm;
dln2->adapter.quirks = &dln2_i2c_quirks;
dln2->adapter.dev.parent = dev;
ACPI_COMPANION_SET(&dln2->adapter.dev, ACPI_COMPANION(&pdev->dev));
dln2->adapter.dev.of_node = dev->of_node;
i2c_set_adapdata(&dln2->adapter, dln2);
snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",

View File

@@ -861,14 +861,8 @@ static int exynos5_i2c_resume_noirq(struct device *dev)
#endif
static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend_noirq = exynos5_i2c_suspend_noirq,
.resume_noirq = exynos5_i2c_resume_noirq,
.freeze_noirq = exynos5_i2c_suspend_noirq,
.thaw_noirq = exynos5_i2c_resume_noirq,
.poweroff_noirq = exynos5_i2c_suspend_noirq,
.restore_noirq = exynos5_i2c_resume_noirq,
#endif
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos5_i2c_suspend_noirq,
exynos5_i2c_resume_noirq)
};
static struct platform_driver exynos5_i2c_driver = {

View File

@@ -94,6 +94,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/platform_data/itco_wdt.h>
#include <linux/pm_runtime.h>
#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
defined CONFIG_DMI
@@ -714,9 +715,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
{
int hwpec;
int block = 0;
int ret, xact = 0;
int ret = 0, xact = 0;
struct i801_priv *priv = i2c_get_adapdata(adap);
pm_runtime_get_sync(&priv->pci_dev->dev);
hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
&& size != I2C_SMBUS_QUICK
&& size != I2C_SMBUS_I2C_BLOCK_DATA;
@@ -773,7 +776,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
default:
dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
size);
return -EOPNOTSUPP;
ret = -EOPNOTSUPP;
goto out;
}
if (hwpec) /* enable/disable hardware PEC */
@@ -796,11 +800,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
if (block)
return ret;
goto out;
if (ret)
return ret;
goto out;
if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
return 0;
goto out;
switch (xact & 0x7f) {
case I801_BYTE: /* Result put in SMBHSTDAT0 */
@@ -812,7 +816,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
(inb_p(SMBHSTDAT1(priv)) << 8);
break;
}
return 0;
out:
pm_runtime_mark_last_busy(&priv->pci_dev->dev);
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
return ret;
}
@@ -1413,6 +1421,11 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
pci_set_drvdata(dev, priv);
pm_runtime_set_autosuspend_delay(&dev->dev, 1000);
pm_runtime_use_autosuspend(&dev->dev);
pm_runtime_put_autosuspend(&dev->dev);
pm_runtime_allow(&dev->dev);
return 0;
}
@@ -1420,6 +1433,9 @@ static void i801_remove(struct pci_dev *dev)
{
struct i801_priv *priv = pci_get_drvdata(dev);
pm_runtime_forbid(&dev->dev);
pm_runtime_get_noresume(&dev->dev);
i801_del_mux(priv);
i2c_del_adapter(&priv->adapter);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
@@ -1433,34 +1449,32 @@ static void i801_remove(struct pci_dev *dev)
}
#ifdef CONFIG_PM
static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
static int i801_suspend(struct device *dev)
{
struct i801_priv *priv = pci_get_drvdata(dev);
struct pci_dev *pci_dev = to_pci_dev(dev);
struct i801_priv *priv = pci_get_drvdata(pci_dev);
pci_save_state(dev);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
pci_set_power_state(dev, pci_choose_state(dev, mesg));
pci_write_config_byte(pci_dev, SMBHSTCFG, priv->original_hstcfg);
return 0;
}
static int i801_resume(struct pci_dev *dev)
static int i801_resume(struct device *dev)
{
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
return 0;
}
#else
#define i801_suspend NULL
#define i801_resume NULL
#endif
static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend,
i801_resume, NULL);
static struct pci_driver i801_driver = {
.name = "i801_smbus",
.id_table = i801_ids,
.probe = i801_probe,
.remove = i801_remove,
.suspend = i801_suspend,
.resume = i801_resume,
.driver = {
.pm = &i801_pm_ops,
},
};
static int __init i2c_i801_init(void)

View File

@@ -269,7 +269,7 @@ static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p)
ndelay(t->hd_sta);
/* Send address */
v = (u8)((p->addr << 1) | ((p->flags & I2C_M_RD) ? 1 : 0));
v = i2c_8bit_addr_from_msg(p);
for (i = 0, mask = 0x80; i < 8; ++i, mask >>= 1){
out_8(&iic->directcntl, sda);
ndelay(t->low / 2);

View File

@@ -751,9 +751,7 @@ static unsigned int img_i2c_atomic(struct img_i2c *i2c,
switch (i2c->at_cur_cmd) {
case CMD_GEN_START:
next_cmd = CMD_GEN_DATA;
next_data = (i2c->msg.addr << 1);
if (i2c->msg.flags & I2C_M_RD)
next_data |= 0x1;
next_data = i2c_8bit_addr_from_msg(&i2c->msg);
break;
case CMD_GEN_DATA:
if (i2c->line_status & LINESTAT_INPUT_HELD_V)

View File

@@ -525,7 +525,7 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR);
/* Wait controller to be stable */
udelay(50);
usleep_range(50, 150);
/* Start I2C transaction */
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);

View File

@@ -50,10 +50,7 @@ iic_cook_addr(struct i2c_msg *msg)
{
unsigned char addr;
addr = (msg->addr << 1);
if (msg->flags & I2C_M_RD)
addr |= 1;
addr = i2c_8bit_addr_from_msg(msg);
return addr;
}

View File

@@ -133,9 +133,7 @@ static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c)
case M_START:
case M_REPSTART:
/* Start bit was just sent out, send out addr and dir */
data = i2c->msg->addr << 1;
if (i2c->msg->flags & I2C_M_RD)
data |= 1;
data = i2c_8bit_addr_from_msg(i2c->msg);
writel(data, i2c->base + LPC24XX_I2DAT);
writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR);

View File

@@ -413,10 +413,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
else
writew(I2C_FS_START_CON, i2c->base + OFFSET_EXT_CONF);
addr_reg = msgs->addr << 1;
if (i2c->op == I2C_MASTER_RD)
addr_reg |= 0x1;
addr_reg = i2c_8bit_addr_from_msg(msgs);
writew(addr_reg, i2c->base + OFFSET_SLAVE_ADDR);
/* Clear interrupt status */

View File

@@ -134,9 +134,7 @@ struct mv64xxx_i2c_data {
int rc;
u32 freq_m;
u32 freq_n;
#if defined(CONFIG_HAVE_CLK)
struct clk *clk;
#endif
wait_queue_head_t waitq;
spinlock_t lock;
struct i2c_msg *msg;
@@ -757,7 +755,6 @@ static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
#ifdef CONFIG_OF
#ifdef CONFIG_HAVE_CLK
static int
mv64xxx_calc_freq(struct mv64xxx_i2c_data *drv_data,
const int tclk, const int n, const int m)
@@ -791,25 +788,20 @@ mv64xxx_find_baud_factors(struct mv64xxx_i2c_data *drv_data,
return false;
return true;
}
#endif /* CONFIG_HAVE_CLK */
static int
mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
struct device *dev)
{
/* CLK is mandatory when using DT to describe the i2c bus. We
* need to know tclk in order to calculate bus clock
* factors.
*/
#if !defined(CONFIG_HAVE_CLK)
/* Have OF but no CLK */
return -ENODEV;
#else
const struct of_device_id *device;
struct device_node *np = dev->of_node;
u32 bus_freq, tclk;
int rc = 0;
/* CLK is mandatory when using DT to describe the i2c bus. We
* need to know tclk in order to calculate bus clock
* factors.
*/
if (IS_ERR(drv_data->clk)) {
rc = -ENODEV;
goto out;
@@ -869,7 +861,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
out:
return rc;
#endif
}
#else /* CONFIG_OF */
static int
@@ -907,14 +898,13 @@ mv64xxx_i2c_probe(struct platform_device *pd)
init_waitqueue_head(&drv_data->waitq);
spin_lock_init(&drv_data->lock);
#if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */
drv_data->clk = devm_clk_get(&pd->dev, NULL);
if (!IS_ERR(drv_data->clk)) {
clk_prepare(drv_data->clk);
clk_enable(drv_data->clk);
}
#endif
if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(drv_data->clk))
clk_prepare_enable(drv_data->clk);
if (pdata) {
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
@@ -964,13 +954,10 @@ exit_reset:
if (!IS_ERR_OR_NULL(drv_data->rstc))
reset_control_assert(drv_data->rstc);
exit_clk:
#if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk)) {
clk_disable(drv_data->clk);
clk_unprepare(drv_data->clk);
}
#endif
if (!IS_ERR(drv_data->clk))
clk_disable_unprepare(drv_data->clk);
return rc;
}
@@ -983,13 +970,9 @@ mv64xxx_i2c_remove(struct platform_device *dev)
free_irq(drv_data->irq, drv_data);
if (!IS_ERR_OR_NULL(drv_data->rstc))
reset_control_assert(drv_data->rstc);
#if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk)) {
clk_disable(drv_data->clk);
clk_unprepare(drv_data->clk);
}
#endif
if (!IS_ERR(drv_data->clk))
clk_disable_unprepare(drv_data->clk);
return 0;
}

View File

@@ -127,7 +127,7 @@ static struct pci_driver nforce2_driver;
/* For multiplexing support, we need a global reference to the 1st
SMBus channel */
#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE
#if IS_ENABLED(CONFIG_I2C_NFORCE2_S4985)
struct i2c_adapter *nforce2_smbus;
EXPORT_SYMBOL_GPL(nforce2_smbus);

View File

@@ -178,10 +178,7 @@ static void ocores_process(struct ocores_i2c *i2c)
if (i2c->nmsgs) { /* end? */
/* send start? */
if (!(msg->flags & I2C_M_NOSTART)) {
u8 addr = (msg->addr << 1);
if (msg->flags & I2C_M_RD)
addr |= 1;
u8 addr = i2c_8bit_addr_from_msg(msg);
i2c->state = STATE_START;

File diff suppressed because it is too large Load Diff

View File

@@ -185,7 +185,6 @@ enum {
#define OMAP_I2C_IP_V2_INTERRUPTS_MASK 0x6FFF
struct omap_i2c_dev {
spinlock_t lock; /* IRQ synchronization */
struct device *dev;
void __iomem *base; /* virtual */
int irq;
@@ -995,15 +994,12 @@ omap_i2c_isr(int irq, void *dev_id)
u16 mask;
u16 stat;
spin_lock(&omap->lock);
mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
if (stat & mask)
ret = IRQ_WAKE_THREAD;
spin_unlock(&omap->lock);
return ret;
}
@@ -1011,12 +1007,10 @@ static irqreturn_t
omap_i2c_isr_thread(int this_irq, void *dev_id)
{
struct omap_i2c_dev *omap = dev_id;
unsigned long flags;
u16 bits;
u16 stat;
int err = 0, count = 0;
spin_lock_irqsave(&omap->lock, flags);
do {
bits = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
@@ -1142,8 +1136,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
omap_i2c_complete_cmd(omap, err);
out:
spin_unlock_irqrestore(&omap->lock, flags);
return IRQ_HANDLED;
}
@@ -1330,8 +1322,6 @@ omap_i2c_probe(struct platform_device *pdev)
omap->dev = &pdev->dev;
omap->irq = irq;
spin_lock_init(&omap->lock);
platform_set_drvdata(pdev, omap);
init_completion(&omap->cmd_complete);

View File

@@ -150,13 +150,11 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
{
struct pmac_i2c_bus *bus = i2c_get_adapdata(adap);
int rc = 0;
int read;
int addrdir;
if (msgs->flags & I2C_M_TEN)
return -EINVAL;
read = (msgs->flags & I2C_M_RD) != 0;
addrdir = (msgs->addr << 1) | read;
addrdir = i2c_8bit_addr_from_msg(msgs);
rc = pmac_i2c_open(bus, 0);
if (rc) {

View File

@@ -515,7 +515,7 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
struct i2c_msg *msg, int is_dma)
{
u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
u16 addr = i2c_8bit_addr_from_msg(msg);
int len = 0;
int data_len;

View File

@@ -21,6 +21,8 @@
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -43,6 +45,8 @@
#define ICSAR 0x1C /* slave address */
#define ICMAR 0x20 /* master address */
#define ICRXTX 0x24 /* data port */
#define ICDMAER 0x3c /* DMA enable */
#define ICFBSCR 0x38 /* first bit setup cycle */
/* ICSCR */
#define SDBS (1 << 3) /* slave data buffer select */
@@ -78,6 +82,16 @@
#define MDR (1 << 1)
#define MAT (1 << 0) /* slave addr xfer done */
/* ICDMAER */
#define RSDMAE (1 << 3) /* DMA Slave Received Enable */
#define TSDMAE (1 << 2) /* DMA Slave Transmitted Enable */
#define RMDMAE (1 << 1) /* DMA Master Received Enable */
#define TMDMAE (1 << 0) /* DMA Master Transmitted Enable */
/* ICFBSCR */
#define TCYC06 0x04 /* 6*Tcyc delay 1st bit between SDA and SCL */
#define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
@@ -120,6 +134,12 @@ struct rcar_i2c_priv {
u32 flags;
enum rcar_i2c_type devtype;
struct i2c_client *slave;
struct resource *res;
struct dma_chan *dma_tx;
struct dma_chan *dma_rx;
struct scatterlist sg;
enum dma_data_direction dma_direction;
};
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
@@ -287,6 +307,118 @@ static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)
/*
* interrupt functions
*/
static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)
{
struct dma_chan *chan = priv->dma_direction == DMA_FROM_DEVICE
? priv->dma_rx : priv->dma_tx;
/* Disable DMA Master Received/Transmitted */
rcar_i2c_write(priv, ICDMAER, 0);
/* Reset default delay */
rcar_i2c_write(priv, ICFBSCR, TCYC06);
dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
priv->msg->len, priv->dma_direction);
priv->dma_direction = DMA_NONE;
}
static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv)
{
if (priv->dma_direction == DMA_NONE)
return;
else if (priv->dma_direction == DMA_FROM_DEVICE)
dmaengine_terminate_all(priv->dma_rx);
else if (priv->dma_direction == DMA_TO_DEVICE)
dmaengine_terminate_all(priv->dma_tx);
rcar_i2c_dma_unmap(priv);
}
static void rcar_i2c_dma_callback(void *data)
{
struct rcar_i2c_priv *priv = data;
priv->pos += sg_dma_len(&priv->sg);
rcar_i2c_dma_unmap(priv);
}
static void rcar_i2c_dma(struct rcar_i2c_priv *priv)
{
struct device *dev = rcar_i2c_priv_to_dev(priv);
struct i2c_msg *msg = priv->msg;
bool read = msg->flags & I2C_M_RD;
enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
struct dma_chan *chan = read ? priv->dma_rx : priv->dma_tx;
struct dma_async_tx_descriptor *txdesc;
dma_addr_t dma_addr;
dma_cookie_t cookie;
unsigned char *buf;
int len;
/* Do not use DMA if it's not available or for messages < 8 bytes */
if (IS_ERR(chan) || msg->len < 8)
return;
if (read) {
/*
* The last two bytes needs to be fetched using PIO in
* order for the STOP phase to work.
*/
buf = priv->msg->buf;
len = priv->msg->len - 2;
} else {
/*
* First byte in message was sent using PIO.
*/
buf = priv->msg->buf + 1;
len = priv->msg->len - 1;
}
dma_addr = dma_map_single(chan->device->dev, buf, len, dir);
if (dma_mapping_error(dev, dma_addr)) {
dev_dbg(dev, "dma map failed, using PIO\n");
return;
}
sg_dma_len(&priv->sg) = len;
sg_dma_address(&priv->sg) = dma_addr;
priv->dma_direction = dir;
txdesc = dmaengine_prep_slave_sg(chan, &priv->sg, 1,
read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc) {
dev_dbg(dev, "dma prep slave sg failed, using PIO\n");
rcar_i2c_cleanup_dma(priv);
return;
}
txdesc->callback = rcar_i2c_dma_callback;
txdesc->callback_param = priv;
cookie = dmaengine_submit(txdesc);
if (dma_submit_error(cookie)) {
dev_dbg(dev, "submitting dma failed, using PIO\n");
rcar_i2c_cleanup_dma(priv);
return;
}
/* Set delay for DMA operations */
rcar_i2c_write(priv, ICFBSCR, TCYC17);
/* Enable DMA Master Received/Transmitted */
if (read)
rcar_i2c_write(priv, ICDMAER, RMDMAE);
else
rcar_i2c_write(priv, ICDMAER, TMDMAE);
dma_async_issue_pending(chan);
}
static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
{
struct i2c_msg *msg = priv->msg;
@@ -306,6 +438,12 @@ static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
rcar_i2c_write(priv, ICRXTX, msg->buf[priv->pos]);
priv->pos++;
/*
* Try to use DMA to transmit the rest of the data if
* address transfer pashe just finished.
*/
if (msr & MAT)
rcar_i2c_dma(priv);
} else {
/*
* The last data was pushed to ICRXTX on _PREV_ empty irq.
@@ -340,7 +478,11 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
return;
if (msr & MAT) {
/* Address transfer phase finished, but no data at this point. */
/*
* Address transfer phase finished, but no data at this point.
* Try to use DMA to receive data.
*/
rcar_i2c_dma(priv);
} else if (priv->pos < msg->len) {
/* get received data */
msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
@@ -472,6 +614,81 @@ out:
return IRQ_HANDLED;
}
static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev,
enum dma_transfer_direction dir,
dma_addr_t port_addr)
{
struct dma_chan *chan;
struct dma_slave_config cfg;
char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx";
int ret;
chan = dma_request_slave_channel_reason(dev, chan_name);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
dev_dbg(dev, "request_channel failed for %s (%d)\n",
chan_name, ret);
return chan;
}
memset(&cfg, 0, sizeof(cfg));
cfg.direction = dir;
if (dir == DMA_MEM_TO_DEV) {
cfg.dst_addr = port_addr;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
} else {
cfg.src_addr = port_addr;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
}
ret = dmaengine_slave_config(chan, &cfg);
if (ret) {
dev_dbg(dev, "slave_config failed for %s (%d)\n",
chan_name, ret);
dma_release_channel(chan);
return ERR_PTR(ret);
}
dev_dbg(dev, "got DMA channel for %s\n", chan_name);
return chan;
}
static void rcar_i2c_request_dma(struct rcar_i2c_priv *priv,
struct i2c_msg *msg)
{
struct device *dev = rcar_i2c_priv_to_dev(priv);
bool read;
struct dma_chan *chan;
enum dma_transfer_direction dir;
read = msg->flags & I2C_M_RD;
chan = read ? priv->dma_rx : priv->dma_tx;
if (PTR_ERR(chan) != -EPROBE_DEFER)
return;
dir = read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
chan = rcar_i2c_request_dma_chan(dev, dir, priv->res->start + ICRXTX);
if (read)
priv->dma_rx = chan;
else
priv->dma_tx = chan;
}
static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)
{
if (!IS_ERR(priv->dma_tx)) {
dma_release_channel(priv->dma_tx);
priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
}
if (!IS_ERR(priv->dma_rx)) {
dma_release_channel(priv->dma_rx);
priv->dma_rx = ERR_PTR(-EPROBE_DEFER);
}
}
static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs,
int num)
@@ -493,6 +710,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
ret = -EOPNOTSUPP;
goto out;
}
rcar_i2c_request_dma(priv, msgs + i);
}
/* init first message */
@@ -504,6 +722,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE,
num * adap->timeout);
if (!time_left) {
rcar_i2c_cleanup_dma(priv);
rcar_i2c_init(priv);
ret = -ETIMEDOUT;
} else if (priv->flags & ID_NACK) {
@@ -591,7 +810,6 @@ static int rcar_i2c_probe(struct platform_device *pdev)
{
struct rcar_i2c_priv *priv;
struct i2c_adapter *adap;
struct resource *res;
struct device *dev = &pdev->dev;
struct i2c_timings i2c_t;
int irq, ret;
@@ -606,8 +824,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
return PTR_ERR(priv->clk);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io = devm_ioremap_resource(dev, res);
priv->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io = devm_ioremap_resource(dev, priv->res);
if (IS_ERR(priv->io))
return PTR_ERR(priv->io);
@@ -626,6 +845,11 @@ static int rcar_i2c_probe(struct platform_device *pdev)
i2c_parse_fw_timings(dev, &i2c_t, false);
/* Init DMA */
sg_init_table(&priv->sg, 1);
priv->dma_direction = DMA_NONE;
priv->dma_rx = priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
ret = rcar_i2c_clock_calculate(priv, &i2c_t);
@@ -673,6 +897,7 @@ static int rcar_i2c_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
i2c_del_adapter(&priv->adap);
rcar_i2c_release_dma(priv);
if (priv->flags & ID_P_PM_BLOCKED)
pm_runtime_put(dev);
pm_runtime_disable(dev);

View File

@@ -101,10 +101,7 @@ struct rk3x_i2c {
struct notifier_block clk_rate_nb;
/* Settings */
unsigned int scl_frequency;
unsigned int scl_rise_ns;
unsigned int scl_fall_ns;
unsigned int sda_fall_ns;
struct i2c_timings t;
/* Synchronization & notification */
spinlock_t lock;
@@ -437,10 +434,7 @@ out:
* Calculate divider values for desired SCL frequency
*
* @clk_rate: I2C input clock rate
* @scl_rate: Desired SCL rate
* @scl_rise_ns: How many ns it takes for SCL to rise.
* @scl_fall_ns: How many ns it takes for SCL to fall.
* @sda_fall_ns: How many ns it takes for SDA to fall.
* @t: Known I2C timing information.
* @div_low: Divider output for low
* @div_high: Divider output for high
*
@@ -448,11 +442,10 @@ out:
* a best-effort divider value is returned in divs. If the target rate is
* too high, we silently use the highest possible rate.
*/
static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
unsigned long scl_rise_ns,
unsigned long scl_fall_ns,
unsigned long sda_fall_ns,
unsigned long *div_low, unsigned long *div_high)
static int rk3x_i2c_calc_divs(unsigned long clk_rate,
struct i2c_timings *t,
unsigned long *div_low,
unsigned long *div_high)
{
unsigned long spec_min_low_ns, spec_min_high_ns;
unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -472,12 +465,12 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
int ret = 0;
/* Only support standard-mode and fast-mode */
if (WARN_ON(scl_rate > 400000))
scl_rate = 400000;
if (WARN_ON(t->bus_freq_hz > 400000))
t->bus_freq_hz = 400000;
/* prevent scl_rate_khz from becoming 0 */
if (WARN_ON(scl_rate < 1000))
scl_rate = 1000;
if (WARN_ON(t->bus_freq_hz < 1000))
t->bus_freq_hz = 1000;
/*
* min_low_ns: The minimum number of ns we need to hold low to
@@ -491,7 +484,7 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
* This is because the i2c host on Rockchip holds the data line
* for half the low time.
*/
if (scl_rate <= 100000) {
if (t->bus_freq_hz <= 100000) {
/* Standard-mode */
spec_min_low_ns = 4700;
spec_setup_start = 4700;
@@ -506,7 +499,7 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
spec_max_data_hold_ns = 900;
data_hold_buffer_ns = 50;
}
min_high_ns = scl_rise_ns + spec_min_high_ns;
min_high_ns = t->scl_rise_ns + spec_min_high_ns;
/*
* Timings for repeated start:
@@ -517,18 +510,18 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
* we meet tSU;STA and tHD;STA times.
*/
min_high_ns = max(min_high_ns,
DIV_ROUND_UP((scl_rise_ns + spec_setup_start) * 1000, 875));
DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875));
min_high_ns = max(min_high_ns,
DIV_ROUND_UP((scl_rise_ns + spec_setup_start +
sda_fall_ns + spec_min_high_ns), 2));
DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start +
t->sda_fall_ns + spec_min_high_ns), 2));
min_low_ns = scl_fall_ns + spec_min_low_ns;
min_low_ns = t->scl_fall_ns + spec_min_low_ns;
max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns;
min_total_ns = min_low_ns + min_high_ns;
/* Adjust to avoid overflow */
clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
scl_rate_khz = scl_rate / 1000;
scl_rate_khz = t->bus_freq_hz / 1000;
/*
* We need the total div to be >= this number
@@ -616,14 +609,13 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
{
struct i2c_timings *t = &i2c->t;
unsigned long div_low, div_high;
u64 t_low_ns, t_high_ns;
int ret;
ret = rk3x_i2c_calc_divs(clk_rate, i2c->scl_frequency, i2c->scl_rise_ns,
i2c->scl_fall_ns, i2c->sda_fall_ns,
&div_low, &div_high);
WARN_ONCE(ret != 0, "Could not reach SCL freq %u", i2c->scl_frequency);
ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
clk_enable(i2c->clk);
i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
@@ -634,7 +626,7 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
dev_dbg(i2c->dev,
"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
clk_rate / 1000,
1000000000 / i2c->scl_frequency,
1000000000 / t->bus_freq_hz,
t_low_ns, t_high_ns);
}
@@ -664,9 +656,7 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
switch (event) {
case PRE_RATE_CHANGE:
if (rk3x_i2c_calc_divs(ndata->new_rate, i2c->scl_frequency,
i2c->scl_rise_ns, i2c->scl_fall_ns,
i2c->sda_fall_ns,
if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
&div_low, &div_high) != 0)
return NOTIFY_STOP;
@@ -880,37 +870,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
match = of_match_node(rk3x_i2c_match, np);
i2c->soc_data = (struct rk3x_i2c_soc_data *)match->data;
if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&i2c->scl_frequency)) {
dev_info(&pdev->dev, "using default SCL frequency: %d\n",
DEFAULT_SCL_RATE);
i2c->scl_frequency = DEFAULT_SCL_RATE;
}
if (i2c->scl_frequency == 0 || i2c->scl_frequency > 400 * 1000) {
dev_warn(&pdev->dev, "invalid SCL frequency specified.\n");
dev_warn(&pdev->dev, "using default SCL frequency: %d\n",
DEFAULT_SCL_RATE);
i2c->scl_frequency = DEFAULT_SCL_RATE;
}
/*
* Read rise and fall time from device tree. If not available use
* the default maximum timing from the specification.
*/
if (of_property_read_u32(pdev->dev.of_node, "i2c-scl-rising-time-ns",
&i2c->scl_rise_ns)) {
if (i2c->scl_frequency <= 100000)
i2c->scl_rise_ns = 1000;
else
i2c->scl_rise_ns = 300;
}
if (of_property_read_u32(pdev->dev.of_node, "i2c-scl-falling-time-ns",
&i2c->scl_fall_ns))
i2c->scl_fall_ns = 300;
if (of_property_read_u32(pdev->dev.of_node, "i2c-sda-falling-time-ns",
&i2c->sda_fall_ns))
i2c->sda_fall_ns = i2c->scl_fall_ns;
/* use common interface to get I2C timing properties */
i2c_parse_fw_timings(&pdev->dev, &i2c->t, true);
strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;

View File

@@ -163,15 +163,14 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
#endif
/* s3c24xx_get_device_quirks
*
/*
* Get controller type either from device tree or platform device variant.
*/
*/
static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *pdev)
{
if (pdev->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node);
return (kernel_ulong_t)match->data;
}
@@ -179,12 +178,10 @@ static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *p
return platform_get_device_id(pdev)->driver_data;
}
/* s3c24xx_i2c_master_complete
*
* complete the message and wake up the caller, using the given return code,
/*
* Complete the message and wake up the caller, using the given return code,
* or zero to mean ok.
*/
*/
static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
{
dev_dbg(i2c->dev, "master_complete %d\n", ret);
@@ -217,7 +214,6 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
}
/* irq enable/disable functions */
static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
@@ -251,11 +247,9 @@ static bool is_ack(struct s3c24xx_i2c *i2c)
return false;
}
/* s3c24xx_i2c_message_start
*
/*
* put the start of a message onto the bus
*/
*/
static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
struct i2c_msg *msg)
{
@@ -284,9 +278,10 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS);
/* delay here to ensure the data byte has gotten onto the bus
* before the transaction is started */
/*
* delay here to ensure the data byte has gotten onto the bus
* before the transaction is started
*/
ndelay(i2c->tx_setup);
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
@@ -361,50 +356,46 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
s3c24xx_i2c_disable_irq(i2c);
}
/* helper functions to determine the current state in the set of
* messages we are sending */
/*
* helper functions to determine the current state in the set of
* messages we are sending
*/
/* is_lastmsg()
*
/*
* returns TRUE if the current message is the last in the set
*/
*/
static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
{
return i2c->msg_idx >= (i2c->msg_num - 1);
}
/* is_msglast
*
/*
* returns TRUE if we this is the last byte in the current message
*/
*/
static inline int is_msglast(struct s3c24xx_i2c *i2c)
{
/* msg->len is always 1 for the first byte of smbus block read.
/*
* msg->len is always 1 for the first byte of smbus block read.
* Actual length will be read from slave. More bytes will be
* read according to the length then. */
* read according to the length then.
*/
if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1)
return 0;
return i2c->msg_ptr == i2c->msg->len-1;
}
/* is_msgend
*
/*
* returns TRUE if we reached the end of the current message
*/
*/
static inline int is_msgend(struct s3c24xx_i2c *i2c)
{
return i2c->msg_ptr >= i2c->msg->len;
}
/* i2c_s3c_irq_nextbyte
*
/*
* process an interrupt and work out what to do
*/
static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
{
unsigned long tmp;
@@ -423,14 +414,13 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
goto out_ack;
case STATE_START:
/* last thing we did was send a start condition on the
/*
* last thing we did was send a start condition on the
* bus, or started a new i2c message
*/
if (iicstat & S3C2410_IICSTAT_LASTBIT &&
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */
dev_dbg(i2c->dev, "ack was not received\n");
s3c24xx_i2c_stop(i2c, -ENXIO);
goto out_ack;
@@ -441,9 +431,10 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
else
i2c->state = STATE_WRITE;
/* terminate the transfer if there is nothing to do
* as this is used by the i2c probe to find devices. */
/*
* Terminate the transfer if there is nothing to do
* as this is used by the i2c probe to find devices.
*/
if (is_lastmsg(i2c) && i2c->msg->len == 0) {
s3c24xx_i2c_stop(i2c, 0);
goto out_ack;
@@ -452,14 +443,16 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (i2c->state == STATE_READ)
goto prepare_read;
/* fall through to the write state, as we will need to
* send a byte as well */
case STATE_WRITE:
/* we are writing data to the device... check for the
* end of the message, and if so, work out what to do
/*
* fall through to the write state, as we will need to
* send a byte as well
*/
case STATE_WRITE:
/*
* we are writing data to the device... check for the
* end of the message, and if so, work out what to do
*/
if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
if (iicstat & S3C2410_IICSTAT_LASTBIT) {
dev_dbg(i2c->dev, "WRITE: No Ack\n");
@@ -475,12 +468,13 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = i2c->msg->buf[i2c->msg_ptr++];
writeb(byte, i2c->regs + S3C2410_IICDS);
/* delay after writing the byte to allow the
/*
* delay after writing the byte to allow the
* data setup time on the bus, as writing the
* data to the register causes the first bit
* to appear on SDA, and SCL will change as
* soon as the interrupt is acknowledged */
* soon as the interrupt is acknowledged
*/
ndelay(i2c->tx_setup);
} else if (!is_lastmsg(i2c)) {
@@ -496,10 +490,11 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (i2c->msg->flags & I2C_M_NOSTART) {
if (i2c->msg->flags & I2C_M_RD) {
/* cannot do this, the controller
/*
* cannot do this, the controller
* forces us to send a new START
* when we change direction */
* when we change direction
*/
s3c24xx_i2c_stop(i2c, -EINVAL);
}
@@ -512,17 +507,16 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
} else {
/* send stop */
s3c24xx_i2c_stop(i2c, 0);
}
break;
case STATE_READ:
/* we have a byte of data in the data register, do
/*
* we have a byte of data in the data register, do
* something with it, and then work out whether we are
* going to do any more read/write
*/
byte = readb(i2c->regs + S3C2410_IICDS);
i2c->msg->buf[i2c->msg_ptr++] = byte;
@@ -537,9 +531,10 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
s3c24xx_i2c_disable_ack(i2c);
} else if (is_msgend(i2c)) {
/* ok, we've read the entire buffer, see if there
* is anything else we need to do */
/*
* ok, we've read the entire buffer, see if there
* is anything else we need to do
*/
if (is_lastmsg(i2c)) {
/* last message, send stop and complete */
dev_dbg(i2c->dev, "READ: Send Stop\n");
@@ -568,11 +563,9 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
return ret;
}
/* s3c24xx_i2c_irq
*
/*
* top level IRQ servicing routine
*/
*/
static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
{
struct s3c24xx_i2c *i2c = dev_id;
@@ -595,9 +588,10 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
goto out;
}
/* pretty much this leaves us with the fact that we've
* transmitted or received whatever byte we last sent */
/*
* pretty much this leaves us with the fact that we've
* transmitted or received whatever byte we last sent
*/
i2c_s3c_irq_nextbyte(i2c, status);
out:
@@ -630,11 +624,9 @@ static inline void s3c24xx_i2c_disable_bus(struct s3c24xx_i2c *i2c)
}
/* s3c24xx_i2c_set_master
*
/*
* get the i2c bus for a master transaction
*/
*/
static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
{
unsigned long iicstat;
@@ -652,11 +644,9 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
return -ETIMEDOUT;
}
/* s3c24xx_i2c_wait_idle
*
/*
* wait for the i2c bus to become idle.
*/
*/
static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
{
unsigned long iicstat;
@@ -706,11 +696,9 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
dev_warn(i2c->dev, "timeout waiting for bus idle\n");
}
/* s3c24xx_i2c_doxfer
*
/*
* this starts an i2c transfer
*/
*/
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
struct i2c_msg *msgs, int num)
{
@@ -749,9 +737,10 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
ret = i2c->msg_idx;
/* having these next two as dev_err() makes life very
* noisy when doing an i2cdetect */
/*
* Having these next two as dev_err() makes life very
* noisy when doing an i2cdetect
*/
if (timeout == 0)
dev_dbg(i2c->dev, "timeout\n");
else if (ret != num)
@@ -771,12 +760,10 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
return ret;
}
/* s3c24xx_i2c_xfer
*
/*
* first port of call from the i2c bus code when an message needs
* transferring across the i2c bus.
*/
*/
static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
@@ -814,17 +801,14 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
}
/* i2c bus registration info */
static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.master_xfer = s3c24xx_i2c_xfer,
.functionality = s3c24xx_i2c_func,
};
/* s3c24xx_i2c_calcdivisor
*
/*
* return the divisor settings for a given frequency
*/
*/
static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted,
unsigned int *div1, unsigned int *divs)
{
@@ -850,13 +834,11 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted,
return clkin / (calc_divs * calc_div1);
}
/* s3c24xx_i2c_clockrate
*
/*
* work out a divisor for the user requested frequency setting,
* either by the requested frequency, or scanning the acceptable
* range of frequencies until something is found
*/
*/
static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
{
struct s3c2410_platform_i2c *pdata = i2c->pdata;
@@ -944,7 +926,7 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
i2c_unlock_adapter(&i2c->adap);
if (ret < 0)
dev_err(i2c->dev, "cannot find frequency\n");
dev_err(i2c->dev, "cannot find frequency (%d)\n", ret);
else
dev_info(i2c->dev, "setting freq %d\n", got);
}
@@ -995,7 +977,8 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
ret = gpio_request(gpio, "i2c-bus");
if (ret) {
dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
dev_err(i2c->dev, "gpio [%d] request failed (%d)\n",
gpio, ret);
goto free_gpio;
}
}
@@ -1028,11 +1011,9 @@ static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
}
#endif
/* s3c24xx_i2c_init
*
/*
* initialise the controller, set the IO lines and frequency
*/
*/
static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
{
struct s3c2410_platform_i2c *pdata;
@@ -1068,11 +1049,9 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
}
#ifdef CONFIG_OF
/* s3c24xx_i2c_parse_dt
*
/*
* Parse the device tree node and retreive the platform data.
*/
*/
static void
s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
{
@@ -1105,17 +1084,9 @@ s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
}
#else
static void
s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
{
return;
}
s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) { }
#endif
/* s3c24xx_i2c_probe
*
* called by the bus driver when a suitable device is found
*/
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c;
@@ -1156,7 +1127,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
init_waitqueue_head(&i2c->wait);
/* find the clock and enable it */
i2c->dev = &pdev->dev;
i2c->clk = devm_clk_get(&pdev->dev, "i2c");
if (IS_ERR(i2c->clk)) {
@@ -1166,9 +1136,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
/* map the registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c->regs = devm_ioremap_resource(&pdev->dev, res);
@@ -1179,33 +1147,35 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
i2c->regs, res);
/* setup info block for the i2c core */
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &pdev->dev;
i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev);
/* inititalise the i2c gpio lines */
if (i2c->pdata->cfg_gpio) {
if (i2c->pdata->cfg_gpio)
i2c->pdata->cfg_gpio(to_platform_device(i2c->dev));
} else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) {
else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c))
return -EINVAL;
}
/* initialise the i2c controller */
ret = clk_prepare_enable(i2c->clk);
if (ret) {
dev_err(&pdev->dev, "I2C clock enable failed\n");
return ret;
}
clk_prepare_enable(i2c->clk);
ret = s3c24xx_i2c_init(i2c);
clk_disable(i2c->clk);
if (ret != 0) {
dev_err(&pdev->dev, "I2C controller init failed\n");
clk_unprepare(i2c->clk);
return ret;
}
/* find the IRQ for this unit (note, this relies on the init call to
/*
* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending
*/
if (!(i2c->quirks & QUIRK_POLL)) {
i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
@@ -1214,9 +1184,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return ret;
}
ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0,
dev_name(&pdev->dev), i2c);
ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq,
0, dev_name(&pdev->dev), i2c);
if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
clk_unprepare(i2c->clk);
@@ -1231,12 +1200,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return ret;
}
/* Note, previous versions of the driver used i2c_add_adapter()
/*
* Note, previous versions of the driver used i2c_add_adapter()
* to add the bus at any number. We now pass the bus number via
* the platform data, so if unset it will now default to always
* being bus 0.
*/
i2c->adap.nr = i2c->pdata->bus_num;
i2c->adap.dev.of_node = pdev->dev.of_node;
@@ -1257,11 +1226,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return 0;
}
/* s3c24xx_i2c_remove
*
* called when device is removed from the bus
*/
static int s3c24xx_i2c_remove(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
@@ -1316,14 +1280,8 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev)
#ifdef CONFIG_PM
static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend_noirq = s3c24xx_i2c_suspend_noirq,
.resume_noirq = s3c24xx_i2c_resume_noirq,
.freeze_noirq = s3c24xx_i2c_suspend_noirq,
.thaw_noirq = s3c24xx_i2c_resume_noirq,
.poweroff_noirq = s3c24xx_i2c_suspend_noirq,
.restore_noirq = s3c24xx_i2c_resume_noirq,
#endif
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(s3c24xx_i2c_suspend_noirq,
s3c24xx_i2c_resume_noirq)
};
#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)
@@ -1331,8 +1289,6 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
#define S3C24XX_DEV_PM_OPS NULL
#endif
/* device driver for platform bus bits */
static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,

View File

@@ -398,8 +398,7 @@ static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd,
{
switch (pd->pos) {
case -1:
*buf = (pd->msg->addr & 0x7f) << 1;
*buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0;
*buf = i2c_8bit_addr_from_msg(pd->msg);
break;
default:
*buf = pd->msg->buf[pd->pos];

View File

@@ -190,9 +190,7 @@ static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic,
writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
addr = msg->addr << 1; /* Generate address */
if (msg->flags & I2C_M_RD)
addr |= 1;
addr = i2c_8bit_addr_from_msg(msg);
/* Reverse direction bit */
if (msg->flags & I2C_M_REV_DIR_ADDR)

View File

@@ -337,10 +337,42 @@ static void st_i2c_hw_config(struct st_i2c_dev *i2c_dev)
writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT);
}
static int st_i2c_recover_bus(struct i2c_adapter *i2c_adap)
{
struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
u32 ctl;
dev_dbg(i2c_dev->dev, "Trying to recover bus\n");
/*
* SSP IP is dual role SPI/I2C to generate 9 clock pulses
* we switch to SPI node, 9 bit words and write a 0. This
* has been validate with a oscilloscope and is easier
* than switching to GPIO mode.
*/
/* Disable interrupts */
writel_relaxed(0, i2c_dev->base + SSC_IEN);
st_i2c_hw_config(i2c_dev);
ctl = SSC_CTL_EN | SSC_CTL_MS | SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO;
st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl);
st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
usleep_range(8000, 10000);
writel_relaxed(0, i2c_dev->base + SSC_TBUF);
usleep_range(2000, 4000);
st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
return 0;
}
static int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev)
{
u32 sta;
int i;
int i, ret;
for (i = 0; i < 10; i++) {
sta = readl_relaxed(i2c_dev->base + SSC_STA);
@@ -352,6 +384,12 @@ static int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev)
dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta);
ret = i2c_recover_bus(&i2c_dev->adap);
if (ret) {
dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
return ret;
}
return -EBUSY;
}
@@ -614,8 +652,7 @@ static int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg,
unsigned long timeout;
int ret;
c->addr = (u8)(msg->addr << 1);
c->addr |= (msg->flags & I2C_M_RD);
c->addr = i2c_8bit_addr_from_msg(msg);
c->buf = msg->buf;
c->count = msg->len;
c->xfered = 0;
@@ -744,6 +781,10 @@ static struct i2c_algorithm st_i2c_algo = {
.functionality = st_i2c_func,
};
static struct i2c_bus_recovery_info st_i2c_recovery_info = {
.recover_bus = st_i2c_recover_bus,
};
static int st_i2c_of_get_deglitch(struct device_node *np,
struct st_i2c_dev *i2c_dev)
{
@@ -826,6 +867,7 @@ static int st_i2c_probe(struct platform_device *pdev)
adap->timeout = 2 * HZ;
adap->retries = 0;
adap->algo = &st_i2c_algo;
adap->bus_recovery_info = &st_i2c_recovery_info;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;

View File

@@ -38,6 +38,7 @@
#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12
#define I2C_CNFG_PACKET_MODE_EN (1<<10)
#define I2C_CNFG_NEW_MASTER_FSM (1<<11)
#define I2C_CNFG_MULTI_MASTER_MODE (1<<17)
#define I2C_STATUS 0x01C
#define I2C_SL_CNFG 0x020
#define I2C_SL_CNFG_NACK (1<<1)
@@ -106,6 +107,9 @@
#define I2C_SLV_CONFIG_LOAD (1 << 1)
#define I2C_TIMEOUT_CONFIG_LOAD (1 << 2)
#define I2C_CLKEN_OVERRIDE 0x090
#define I2C_MST_CORE_CLKEN_OVR (1 << 0)
/*
* msg_end_type: The bus control which need to be send at end of transfer.
* @MSG_END_STOP: Send stop pulse at end of transfer.
@@ -143,6 +147,8 @@ struct tegra_i2c_hw_feature {
int clk_divisor_hs_mode;
int clk_divisor_std_fast_mode;
u16 clk_divisor_fast_plus_mode;
bool has_multi_master_mode;
bool has_slcg_override_reg;
};
/**
@@ -184,6 +190,7 @@ struct tegra_i2c_dev {
u32 bus_clk_rate;
u16 clk_divisor_non_hs_mode;
bool is_suspended;
bool is_multimaster_mode;
};
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg)
@@ -438,6 +445,10 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
(0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
if (i2c_dev->hw->has_multi_master_mode)
val |= I2C_CNFG_MULTI_MASTER_MODE;
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
@@ -463,25 +474,29 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (tegra_i2c_flush_fifos(i2c_dev))
err = -ETIMEDOUT;
if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
if (i2c_dev->hw->has_config_load_reg) {
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) {
if (time_after(jiffies, timeout)) {
dev_warn(i2c_dev->dev,
"timeout waiting for config load\n");
return -ETIMEDOUT;
err = -ETIMEDOUT;
goto err;
}
msleep(1);
}
}
tegra_i2c_clock_disable(i2c_dev);
if (i2c_dev->irq_disabled) {
i2c_dev->irq_disabled = 0;
enable_irq(i2c_dev->irq);
}
err:
tegra_i2c_clock_disable(i2c_dev);
return err;
}
@@ -688,6 +703,20 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
return ret;
}
static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
{
struct device_node *np = i2c_dev->dev->of_node;
int ret;
ret = of_property_read_u32(np, "clock-frequency",
&i2c_dev->bus_clk_rate);
if (ret)
i2c_dev->bus_clk_rate = 100000; /* default clock rate */
i2c_dev->is_multimaster_mode = of_property_read_bool(np,
"multi-master");
}
static const struct i2c_algorithm tegra_i2c_algo = {
.master_xfer = tegra_i2c_xfer,
.functionality = tegra_i2c_func,
@@ -707,6 +736,8 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
.clk_divisor_std_fast_mode = 0,
.clk_divisor_fast_plus_mode = 0,
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
};
static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -717,6 +748,8 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
.clk_divisor_std_fast_mode = 0,
.clk_divisor_fast_plus_mode = 0,
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
};
static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -727,6 +760,8 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
.clk_divisor_std_fast_mode = 0x19,
.clk_divisor_fast_plus_mode = 0x10,
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
};
static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -737,10 +772,25 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
.clk_divisor_std_fast_mode = 0x19,
.clk_divisor_fast_plus_mode = 0x10,
.has_config_load_reg = true,
.has_multi_master_mode = false,
.has_slcg_override_reg = true,
};
static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
.has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true,
.has_single_clk_source = true,
.clk_divisor_hs_mode = 1,
.clk_divisor_std_fast_mode = 0x19,
.clk_divisor_fast_plus_mode = 0x10,
.has_config_load_reg = true,
.has_multi_master_mode = true,
.has_slcg_override_reg = true,
};
/* Match table for of_platform binding */
static const struct of_device_id tegra_i2c_of_match[] = {
{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
@@ -797,10 +847,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c_dev->rst);
}
ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency",
&i2c_dev->bus_clk_rate);
if (ret)
i2c_dev->bus_clk_rate = 100000; /* default clock rate */
tegra_i2c_parse_dt(i2c_dev);
i2c_dev->hw = &tegra20_i2c_hw;
@@ -853,6 +900,15 @@ static int tegra_i2c_probe(struct platform_device *pdev)
goto unprepare_fast_clk;
}
if (i2c_dev->is_multimaster_mode) {
ret = clk_enable(i2c_dev->div_clk);
if (ret < 0) {
dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
ret);
goto unprepare_div_clk;
}
}
ret = tegra_i2c_init(i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize i2c controller");
@@ -863,7 +919,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
goto unprepare_div_clk;
goto disable_div_clk;
}
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
@@ -878,11 +934,15 @@ static int tegra_i2c_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) {
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
goto unprepare_div_clk;
goto disable_div_clk;
}
return 0;
disable_div_clk:
if (i2c_dev->is_multimaster_mode)
clk_disable(i2c_dev->div_clk);
unprepare_div_clk:
clk_unprepare(i2c_dev->div_clk);
@@ -898,6 +958,9 @@ static int tegra_i2c_remove(struct platform_device *pdev)
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adapter);
if (i2c_dev->is_multimaster_mode)
clk_disable(i2c_dev->div_clk);
clk_unprepare(i2c_dev->div_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_unprepare(i2c_dev->fast_clk);

View File

@@ -524,7 +524,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to get IRQ number");
dev_err(dev, "failed to get IRQ number\n");
return irq;
}

View File

@@ -381,7 +381,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to get IRQ number");
dev_err(dev, "failed to get IRQ number\n");
return irq;
}

View File

@@ -954,48 +954,40 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
}
/**
* i2c_lock_adapter - Get exclusive access to an I2C bus segment
* i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
* @adapter: Target I2C bus segment
* @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
* locks only this branch in the adapter tree
*/
void i2c_lock_adapter(struct i2c_adapter *adapter)
static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
if (parent)
i2c_lock_adapter(parent);
else
rt_mutex_lock(&adapter->bus_lock);
}
EXPORT_SYMBOL_GPL(i2c_lock_adapter);
/**
* i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment
* @adapter: Target I2C bus segment
*/
static int i2c_trylock_adapter(struct i2c_adapter *adapter)
{
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
if (parent)
return i2c_trylock_adapter(parent);
else
return rt_mutex_trylock(&adapter->bus_lock);
rt_mutex_lock(&adapter->bus_lock);
}
/**
* i2c_unlock_adapter - Release exclusive access to an I2C bus segment
* i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment
* @adapter: Target I2C bus segment
* @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT
* trylocks only this branch in the adapter tree
*/
void i2c_unlock_adapter(struct i2c_adapter *adapter)
static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
if (parent)
i2c_unlock_adapter(parent);
else
rt_mutex_unlock(&adapter->bus_lock);
return rt_mutex_trylock(&adapter->bus_lock);
}
/**
* i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment
* @adapter: Target I2C bus segment
* @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
* unlocks only this branch in the adapter tree
*/
static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
rt_mutex_unlock(&adapter->bus_lock);
}
EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
static void i2c_dev_set_name(struct i2c_adapter *adap,
struct i2c_client *client)
@@ -1541,7 +1533,14 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return -EINVAL;
}
if (!adap->lock_bus) {
adap->lock_bus = i2c_adapter_lock_bus;
adap->trylock_bus = i2c_adapter_trylock_bus;
adap->unlock_bus = i2c_adapter_unlock_bus;
}
rt_mutex_init(&adap->bus_lock);
rt_mutex_init(&adap->mux_lock);
mutex_init(&adap->userspace_clients_lock);
INIT_LIST_HEAD(&adap->userspace_clients);
@@ -1559,6 +1558,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_suspend_ignore_children(&adap->dev, true);
pm_runtime_enable(&adap->dev);
#ifdef CONFIG_I2C_COMPAT
@@ -1594,10 +1594,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
bri->get_scl = get_scl_gpio_value;
bri->set_scl = set_scl_gpio_value;
} else if (!bri->set_scl || !bri->get_scl) {
} else if (bri->recover_bus == i2c_generic_scl_recovery) {
/* Generic SCL recovery */
dev_err(&adap->dev, "No {get|set}_gpio() found, not using recovery\n");
adap->bus_recovery_info = NULL;
if (!bri->set_scl || !bri->get_scl) {
dev_err(&adap->dev, "No {get|set}_scl() found, not using recovery\n");
adap->bus_recovery_info = NULL;
}
}
}
@@ -2309,16 +2311,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
#endif
if (in_atomic() || irqs_disabled()) {
ret = i2c_trylock_adapter(adap);
ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
i2c_lock_adapter(adap);
i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
}
ret = __i2c_transfer(adap, msgs, num);
i2c_unlock_adapter(adap);
i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
return ret;
} else {
@@ -2646,7 +2648,7 @@ static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
{
/* The address will be sent first */
u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
u8 addr = i2c_8bit_addr_from_msg(msg);
pec = i2c_smbus_pec(pec, &addr, 1);
/* The data buffer follows */
@@ -3093,7 +3095,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
if (adapter->algo->smbus_xfer) {
i2c_lock_adapter(adapter);
i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
@@ -3107,7 +3109,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
orig_jiffies + adapter->timeout))
break;
}
i2c_unlock_adapter(adapter);
i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
goto trace;

View File

@@ -31,30 +31,66 @@
struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
struct i2c_adapter *parent;
struct device *mux_dev;
void *mux_priv;
struct i2c_mux_core *muxc;
u32 chan_id;
int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
};
static int __i2c_mux_master_xfer(struct i2c_adapter *adap,
struct i2c_msg msgs[], int num)
{
struct i2c_mux_priv *priv = adap->algo_data;
struct i2c_mux_core *muxc = priv->muxc;
struct i2c_adapter *parent = muxc->parent;
int ret;
/* Switch to the right mux port and perform the transfer. */
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
ret = __i2c_transfer(parent, msgs, num);
if (muxc->deselect)
muxc->deselect(muxc, priv->chan_id);
return ret;
}
static int i2c_mux_master_xfer(struct i2c_adapter *adap,
struct i2c_msg msgs[], int num)
{
struct i2c_mux_priv *priv = adap->algo_data;
struct i2c_adapter *parent = priv->parent;
struct i2c_mux_core *muxc = priv->muxc;
struct i2c_adapter *parent = muxc->parent;
int ret;
/* Switch to the right mux port and perform the transfer. */
ret = priv->select(parent, priv->mux_priv, priv->chan_id);
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
ret = __i2c_transfer(parent, msgs, num);
if (priv->deselect)
priv->deselect(parent, priv->mux_priv, priv->chan_id);
ret = i2c_transfer(parent, msgs, num);
if (muxc->deselect)
muxc->deselect(muxc, priv->chan_id);
return ret;
}
static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
u16 addr, unsigned short flags,
char read_write, u8 command,
int size, union i2c_smbus_data *data)
{
struct i2c_mux_priv *priv = adap->algo_data;
struct i2c_mux_core *muxc = priv->muxc;
struct i2c_adapter *parent = muxc->parent;
int ret;
/* Select the right mux port and perform the transfer. */
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
ret = parent->algo->smbus_xfer(parent, addr, flags,
read_write, command, size, data);
if (muxc->deselect)
muxc->deselect(muxc, priv->chan_id);
return ret;
}
@@ -65,17 +101,18 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
int size, union i2c_smbus_data *data)
{
struct i2c_mux_priv *priv = adap->algo_data;
struct i2c_adapter *parent = priv->parent;
struct i2c_mux_core *muxc = priv->muxc;
struct i2c_adapter *parent = muxc->parent;
int ret;
/* Select the right mux port and perform the transfer. */
ret = priv->select(parent, priv->mux_priv, priv->chan_id);
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
ret = parent->algo->smbus_xfer(parent, addr, flags,
read_write, command, size, data);
if (priv->deselect)
priv->deselect(parent, priv->mux_priv, priv->chan_id);
ret = i2c_smbus_xfer(parent, addr, flags,
read_write, command, size, data);
if (muxc->deselect)
muxc->deselect(muxc, priv->chan_id);
return ret;
}
@@ -84,7 +121,7 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
static u32 i2c_mux_functionality(struct i2c_adapter *adap)
{
struct i2c_mux_priv *priv = adap->algo_data;
struct i2c_adapter *parent = priv->parent;
struct i2c_adapter *parent = priv->muxc->parent;
return parent->algo->functionality(parent);
}
@@ -102,38 +139,167 @@ static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
return class;
}
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
unsigned int class,
int (*select) (struct i2c_adapter *,
void *, u32),
int (*deselect) (struct i2c_adapter *,
void *, u32))
static void i2c_mux_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
struct i2c_mux_priv *priv = adapter->algo_data;
struct i2c_adapter *parent = priv->muxc->parent;
rt_mutex_lock(&parent->mux_lock);
if (!(flags & I2C_LOCK_ROOT_ADAPTER))
return;
i2c_lock_bus(parent, flags);
}
static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
struct i2c_mux_priv *priv = adapter->algo_data;
struct i2c_adapter *parent = priv->muxc->parent;
if (!rt_mutex_trylock(&parent->mux_lock))
return 0; /* mux_lock not locked, failure */
if (!(flags & I2C_LOCK_ROOT_ADAPTER))
return 1; /* we only want mux_lock, success */
if (parent->trylock_bus(parent, flags))
return 1; /* parent locked too, success */
rt_mutex_unlock(&parent->mux_lock);
return 0; /* parent not locked, failure */
}
static void i2c_mux_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
struct i2c_mux_priv *priv = adapter->algo_data;
struct i2c_adapter *parent = priv->muxc->parent;
if (flags & I2C_LOCK_ROOT_ADAPTER)
i2c_unlock_bus(parent, flags);
rt_mutex_unlock(&parent->mux_lock);
}
static void i2c_parent_lock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct i2c_mux_priv *priv = adapter->algo_data;
struct i2c_adapter *parent = priv->muxc->parent;
rt_mutex_lock(&parent->mux_lock);
i2c_lock_bus(parent, flags);
}
static int i2c_parent_trylock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct i2c_mux_priv *priv = adapter->algo_data;
struct i2c_adapter *parent = priv->muxc->parent;
if (!rt_mutex_trylock(&parent->mux_lock))
return 0; /* mux_lock not locked, failure */
if (parent->trylock_bus(parent, flags))
return 1; /* parent locked too, success */
rt_mutex_unlock(&parent->mux_lock);
return 0; /* parent not locked, failure */
}
static void i2c_parent_unlock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct i2c_mux_priv *priv = adapter->algo_data;
struct i2c_adapter *parent = priv->muxc->parent;
i2c_unlock_bus(parent, flags);
rt_mutex_unlock(&parent->mux_lock);
}
struct i2c_adapter *i2c_root_adapter(struct device *dev)
{
struct device *i2c;
struct i2c_adapter *i2c_root;
/*
* Walk up the device tree to find an i2c adapter, indicating
* that this is an i2c client device. Check all ancestors to
* handle mfd devices etc.
*/
for (i2c = dev; i2c; i2c = i2c->parent) {
if (i2c->type == &i2c_adapter_type)
break;
}
if (!i2c)
return NULL;
/* Continue up the tree to find the root i2c adapter */
i2c_root = to_i2c_adapter(i2c);
while (i2c_parent_is_i2c_adapter(i2c_root))
i2c_root = i2c_parent_is_i2c_adapter(i2c_root);
return i2c_root;
}
EXPORT_SYMBOL_GPL(i2c_root_adapter);
struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
struct device *dev, int max_adapters,
int sizeof_priv, u32 flags,
int (*select)(struct i2c_mux_core *, u32),
int (*deselect)(struct i2c_mux_core *, u32))
{
struct i2c_mux_core *muxc;
muxc = devm_kzalloc(dev, sizeof(*muxc)
+ max_adapters * sizeof(muxc->adapter[0])
+ sizeof_priv, GFP_KERNEL);
if (!muxc)
return NULL;
if (sizeof_priv)
muxc->priv = &muxc->adapter[max_adapters];
muxc->parent = parent;
muxc->dev = dev;
if (flags & I2C_MUX_LOCKED)
muxc->mux_locked = true;
muxc->select = select;
muxc->deselect = deselect;
muxc->max_adapters = max_adapters;
return muxc;
}
EXPORT_SYMBOL_GPL(i2c_mux_alloc);
int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
u32 force_nr, u32 chan_id,
unsigned int class)
{
struct i2c_adapter *parent = muxc->parent;
struct i2c_mux_priv *priv;
char symlink_name[20];
int ret;
priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL);
if (muxc->num_adapters >= muxc->max_adapters) {
dev_err(muxc->dev, "No room for more i2c-mux adapters\n");
return -EINVAL;
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return NULL;
return -ENOMEM;
/* Set up private adapter data */
priv->parent = parent;
priv->mux_dev = mux_dev;
priv->mux_priv = mux_priv;
priv->muxc = muxc;
priv->chan_id = chan_id;
priv->select = select;
priv->deselect = deselect;
/* Need to do algo dynamically because we don't know ahead
* of time what sort of physical adapter we'll be dealing with.
*/
if (parent->algo->master_xfer)
priv->algo.master_xfer = i2c_mux_master_xfer;
if (parent->algo->smbus_xfer)
priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
if (parent->algo->master_xfer) {
if (muxc->mux_locked)
priv->algo.master_xfer = i2c_mux_master_xfer;
else
priv->algo.master_xfer = __i2c_mux_master_xfer;
}
if (parent->algo->smbus_xfer) {
if (muxc->mux_locked)
priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
else
priv->algo.smbus_xfer = __i2c_mux_smbus_xfer;
}
priv->algo.functionality = i2c_mux_functionality;
/* Now fill out new adapter structure */
@@ -146,6 +312,15 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
priv->adap.retries = parent->retries;
priv->adap.timeout = parent->timeout;
priv->adap.quirks = parent->quirks;
if (muxc->mux_locked) {
priv->adap.lock_bus = i2c_mux_lock_bus;
priv->adap.trylock_bus = i2c_mux_trylock_bus;
priv->adap.unlock_bus = i2c_mux_unlock_bus;
} else {
priv->adap.lock_bus = i2c_parent_lock_bus;
priv->adap.trylock_bus = i2c_parent_trylock_bus;
priv->adap.unlock_bus = i2c_parent_unlock_bus;
}
/* Sanity check on class */
if (i2c_mux_parent_classes(parent) & class)
@@ -159,11 +334,11 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
* Try to populate the mux adapter's of_node, expands to
* nothing if !CONFIG_OF.
*/
if (mux_dev->of_node) {
if (muxc->dev->of_node) {
struct device_node *child;
u32 reg;
for_each_child_of_node(mux_dev->of_node, child) {
for_each_child_of_node(muxc->dev->of_node, child) {
ret = of_property_read_u32(child, "reg", &reg);
if (ret)
continue;
@@ -177,8 +352,9 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
/*
* Associate the mux channel with an ACPI node.
*/
if (has_acpi_companion(mux_dev))
acpi_preset_companion(&priv->adap.dev, ACPI_COMPANION(mux_dev),
if (has_acpi_companion(muxc->dev))
acpi_preset_companion(&priv->adap.dev,
ACPI_COMPANION(muxc->dev),
chan_id);
if (force_nr) {
@@ -192,35 +368,45 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
"failed to add mux-adapter (error=%d)\n",
ret);
kfree(priv);
return NULL;
return ret;
}
WARN(sysfs_create_link(&priv->adap.dev.kobj, &mux_dev->kobj, "mux_device"),
"can't create symlink to mux device\n");
WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
"mux_device"),
"can't create symlink to mux device\n");
snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
WARN(sysfs_create_link(&mux_dev->kobj, &priv->adap.dev.kobj, symlink_name),
"can't create symlink for channel %u\n", chan_id);
WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
symlink_name),
"can't create symlink for channel %u\n", chan_id);
dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
i2c_adapter_id(&priv->adap));
return &priv->adap;
muxc->adapter[muxc->num_adapters++] = &priv->adap;
return 0;
}
EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
void i2c_del_mux_adapter(struct i2c_adapter *adap)
void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
{
struct i2c_mux_priv *priv = adap->algo_data;
char symlink_name[20];
snprintf(symlink_name, sizeof(symlink_name), "channel-%u", priv->chan_id);
sysfs_remove_link(&priv->mux_dev->kobj, symlink_name);
while (muxc->num_adapters) {
struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
struct i2c_mux_priv *priv = adap->algo_data;
sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
i2c_del_adapter(adap);
kfree(priv);
muxc->adapter[muxc->num_adapters] = NULL;
snprintf(symlink_name, sizeof(symlink_name),
"channel-%u", priv->chan_id);
sysfs_remove_link(&muxc->dev->kobj, symlink_name);
sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
i2c_del_adapter(adap);
kfree(priv);
}
}
EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");

View File

@@ -28,8 +28,6 @@
/**
* struct i2c_arbitrator_data - Driver data for I2C arbitrator
*
* @parent: Parent adapter
* @child: Child bus
* @our_gpio: GPIO we'll use to claim.
* @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
* this then consider it released.
@@ -42,8 +40,6 @@
*/
struct i2c_arbitrator_data {
struct i2c_adapter *parent;
struct i2c_adapter *child;
int our_gpio;
int our_gpio_release;
int their_gpio;
@@ -59,9 +55,9 @@ struct i2c_arbitrator_data {
*
* Use the GPIO-based signalling protocol; return -EBUSY if we fail.
*/
static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
{
const struct i2c_arbitrator_data *arb = data;
const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
unsigned long stop_retry, stop_time;
/* Start a round of trying to claim the bus */
@@ -93,7 +89,7 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
/* Give up, release our claim */
gpio_set_value(arb->our_gpio, arb->our_gpio_release);
udelay(arb->slew_delay_us);
dev_err(&adap->dev, "Could not claim bus, timeout\n");
dev_err(muxc->dev, "Could not claim bus, timeout\n");
return -EBUSY;
}
@@ -102,10 +98,9 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
*
* Release the I2C bus using the GPIO-based signalling protocol.
*/
static int i2c_arbitrator_deselect(struct i2c_adapter *adap, void *data,
u32 chan)
static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
{
const struct i2c_arbitrator_data *arb = data;
const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
/* Release the bus and wait for the other master to notice */
gpio_set_value(arb->our_gpio, arb->our_gpio_release);
@@ -119,6 +114,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct device_node *parent_np;
struct i2c_mux_core *muxc;
struct i2c_arbitrator_data *arb;
enum of_gpio_flags gpio_flags;
unsigned long out_init;
@@ -134,12 +130,13 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
return -EINVAL;
}
arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
if (!arb) {
dev_err(dev, "Cannot allocate i2c_arbitrator_data\n");
muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0,
i2c_arbitrator_select, i2c_arbitrator_deselect);
if (!muxc)
return -ENOMEM;
}
platform_set_drvdata(pdev, arb);
arb = i2c_mux_priv(muxc);
platform_set_drvdata(pdev, muxc);
/* Request GPIOs */
ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
@@ -196,21 +193,18 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
dev_err(dev, "Cannot parse i2c-parent\n");
return -EINVAL;
}
arb->parent = of_get_i2c_adapter_by_node(parent_np);
muxc->parent = of_get_i2c_adapter_by_node(parent_np);
of_node_put(parent_np);
if (!arb->parent) {
if (!muxc->parent) {
dev_err(dev, "Cannot find parent bus\n");
return -EPROBE_DEFER;
}
/* Actually add the mux adapter */
arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0,
i2c_arbitrator_select,
i2c_arbitrator_deselect);
if (!arb->child) {
ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
if (ret) {
dev_err(dev, "Failed to add adapter\n");
ret = -ENODEV;
i2c_put_adapter(arb->parent);
i2c_put_adapter(muxc->parent);
}
return ret;
@@ -218,11 +212,10 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
static int i2c_arbitrator_remove(struct platform_device *pdev)
{
struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev);
i2c_del_mux_adapter(arb->child);
i2c_put_adapter(arb->parent);
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
return 0;
}

View File

@@ -15,11 +15,10 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include "../../gpio/gpiolib.h"
#include <linux/of_gpio.h>
struct gpiomux {
struct i2c_adapter *parent;
struct i2c_adapter **adap; /* child busses */
struct i2c_mux_gpio_platform_data data;
unsigned gpio_base;
};
@@ -33,18 +32,18 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
val & (1 << i));
}
static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
{
struct gpiomux *mux = data;
struct gpiomux *mux = i2c_mux_priv(muxc);
i2c_mux_gpio_set(mux, chan);
return 0;
}
static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
{
struct gpiomux *mux = data;
struct gpiomux *mux = i2c_mux_priv(muxc);
i2c_mux_gpio_set(mux, mux->data.idle);
@@ -136,19 +135,16 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
static int i2c_mux_gpio_probe(struct platform_device *pdev)
{
struct i2c_mux_core *muxc;
struct gpiomux *mux;
struct i2c_adapter *parent;
int (*deselect) (struct i2c_adapter *, void *, u32);
struct i2c_adapter *root;
unsigned initial_state, gpio_base;
int i, ret;
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
if (!mux)
return -ENOMEM;
}
platform_set_drvdata(pdev, mux);
if (!dev_get_platdata(&pdev->dev)) {
ret = i2c_mux_gpio_probe_dt(mux, pdev);
@@ -180,27 +176,32 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
if (!parent)
return -EPROBE_DEFER;
mux->parent = parent;
mux->gpio_base = gpio_base;
mux->adap = devm_kzalloc(&pdev->dev,
sizeof(*mux->adap) * mux->data.n_values,
GFP_KERNEL);
if (!mux->adap) {
dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
i2c_mux_gpio_select, NULL);
if (!muxc) {
ret = -ENOMEM;
goto alloc_failed;
}
muxc->priv = mux;
platform_set_drvdata(pdev, muxc);
root = i2c_root_adapter(&parent->dev);
muxc->mux_locked = true;
mux->gpio_base = gpio_base;
if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = mux->data.idle;
deselect = i2c_mux_gpio_deselect;
muxc->deselect = i2c_mux_gpio_deselect;
} else {
initial_state = mux->data.values[0];
deselect = NULL;
}
for (i = 0; i < mux->data.n_gpios; i++) {
struct device *gpio_dev;
struct gpio_desc *gpio_desc;
ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
if (ret) {
dev_err(&pdev->dev, "Failed to request GPIO %d\n",
@@ -217,17 +218,24 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
i++; /* gpio_request above succeeded, so must free */
goto err_request_gpio;
}
if (!muxc->mux_locked)
continue;
gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]);
gpio_dev = &gpio_desc->gdev->dev;
muxc->mux_locked = i2c_root_adapter(gpio_dev) == root;
}
if (muxc->mux_locked)
dev_info(&pdev->dev, "mux-locked i2c mux\n");
for (i = 0; i < mux->data.n_values; i++) {
u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
mux->data.values[i], class,
i2c_mux_gpio_select, deselect);
if (!mux->adap[i]) {
ret = -ENODEV;
ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
if (ret) {
dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
goto add_adapter_failed;
}
@@ -239,8 +247,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
return 0;
add_adapter_failed:
for (; i > 0; i--)
i2c_del_mux_adapter(mux->adap[i - 1]);
i2c_mux_del_adapters(muxc);
i = mux->data.n_gpios;
err_request_gpio:
for (; i > 0; i--)
@@ -253,16 +260,16 @@ alloc_failed:
static int i2c_mux_gpio_remove(struct platform_device *pdev)
{
struct gpiomux *mux = platform_get_drvdata(pdev);
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
struct gpiomux *mux = i2c_mux_priv(muxc);
int i;
for (i = 0; i < mux->data.n_values; i++)
i2c_del_mux_adapter(mux->adap[i]);
i2c_mux_del_adapters(muxc);
for (i = 0; i < mux->data.n_gpios; i++)
gpio_free(mux->gpio_base + mux->data.gpios[i]);
i2c_put_adapter(mux->parent);
i2c_put_adapter(muxc->parent);
return 0;
}

View File

@@ -73,7 +73,7 @@
#define SELECT_DELAY_LONG 1000
struct pca9541 {
struct i2c_adapter *mux_adap;
struct i2c_client *client;
unsigned long select_timeout;
unsigned long arb_timeout;
};
@@ -217,7 +217,8 @@ static const u8 pca9541_control[16] = {
*/
static int pca9541_arbitrate(struct i2c_client *client)
{
struct pca9541 *data = i2c_get_clientdata(client);
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
struct pca9541 *data = i2c_mux_priv(muxc);
int reg;
reg = pca9541_reg_read(client, PCA9541_CONTROL);
@@ -285,9 +286,10 @@ static int pca9541_arbitrate(struct i2c_client *client)
return 0;
}
static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
{
struct pca9541 *data = i2c_get_clientdata(client);
struct pca9541 *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
int ret;
unsigned long timeout = jiffies + ARB2_TIMEOUT;
/* give up after this time */
@@ -309,9 +311,11 @@ static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
return -ETIMEDOUT;
}
static int pca9541_release_chan(struct i2c_adapter *adap,
void *client, u32 chan)
static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
{
struct pca9541 *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
pca9541_release_bus(client);
return 0;
}
@@ -324,20 +328,13 @@ static int pca9541_probe(struct i2c_client *client,
{
struct i2c_adapter *adap = client->adapter;
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
struct i2c_mux_core *muxc;
struct pca9541 *data;
int force;
int ret = -ENODEV;
int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
goto err;
data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto err;
}
i2c_set_clientdata(client, data);
return -ENODEV;
/*
* I2C accesses are unprotected here.
@@ -352,34 +349,33 @@ static int pca9541_probe(struct i2c_client *client,
force = 0;
if (pdata)
force = pdata->modes[0].adap_id;
data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
force, 0, 0,
pca9541_select_chan,
pca9541_release_chan);
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0,
pca9541_select_chan, pca9541_release_chan);
if (!muxc)
return -ENOMEM;
if (data->mux_adap == NULL) {
data = i2c_mux_priv(muxc);
data->client = client;
i2c_set_clientdata(client, muxc);
ret = i2c_mux_add_adapter(muxc, force, 0, 0);
if (ret) {
dev_err(&client->dev, "failed to register master selector\n");
goto exit_free;
return ret;
}
dev_info(&client->dev, "registered master selector for I2C %s\n",
client->name);
return 0;
exit_free:
kfree(data);
err:
return ret;
}
static int pca9541_remove(struct i2c_client *client)
{
struct pca9541 *data = i2c_get_clientdata(client);
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
i2c_del_mux_adapter(data->mux_adap);
kfree(data);
i2c_mux_del_adapters(muxc);
return 0;
}

View File

@@ -60,9 +60,10 @@ enum pca_type {
struct pca954x {
enum pca_type type;
struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
u8 last_chan; /* last register value */
u8 deselect;
struct i2c_client *client;
};
struct chip_desc {
@@ -146,10 +147,10 @@ static int pca954x_reg_write(struct i2c_adapter *adap,
return ret;
}
static int pca954x_select_chan(struct i2c_adapter *adap,
void *client, u32 chan)
static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
{
struct pca954x *data = i2c_get_clientdata(client);
struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
const struct chip_desc *chip = &chips[data->type];
u8 regval;
int ret = 0;
@@ -162,21 +163,24 @@ static int pca954x_select_chan(struct i2c_adapter *adap,
/* Only select the channel if its different from the last channel */
if (data->last_chan != regval) {
ret = pca954x_reg_write(adap, client, regval);
ret = pca954x_reg_write(muxc->parent, client, regval);
data->last_chan = regval;
}
return ret;
}
static int pca954x_deselect_mux(struct i2c_adapter *adap,
void *client, u32 chan)
static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
{
struct pca954x *data = i2c_get_clientdata(client);
struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
if (!(data->deselect & (1 << chan)))
return 0;
/* Deselect active channel */
data->last_chan = 0;
return pca954x_reg_write(adap, client, data->last_chan);
return pca954x_reg_write(muxc->parent, client, data->last_chan);
}
/*
@@ -191,17 +195,22 @@ static int pca954x_probe(struct i2c_client *client,
bool idle_disconnect_dt;
struct gpio_desc *gpio;
int num, force, class;
struct i2c_mux_core *muxc;
struct pca954x *data;
int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
return -ENODEV;
data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL);
if (!data)
muxc = i2c_mux_alloc(adap, &client->dev,
PCA954X_MAX_NCHANS, sizeof(*data), 0,
pca954x_select_chan, pca954x_deselect_mux);
if (!muxc)
return -ENOMEM;
data = i2c_mux_priv(muxc);
i2c_set_clientdata(client, data);
i2c_set_clientdata(client, muxc);
data->client = client;
/* Get the mux out of reset if a reset GPIO is specified. */
gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
@@ -238,16 +247,13 @@ static int pca954x_probe(struct i2c_client *client,
/* discard unconfigured channels */
break;
idle_disconnect_pd = pdata->modes[num].deselect_on_exit;
data->deselect |= (idle_disconnect_pd
|| idle_disconnect_dt) << num;
}
data->virt_adaps[num] =
i2c_add_mux_adapter(adap, &client->dev, client,
force, num, class, pca954x_select_chan,
(idle_disconnect_pd || idle_disconnect_dt)
? pca954x_deselect_mux : NULL);
ret = i2c_mux_add_adapter(muxc, force, num, class);
if (data->virt_adaps[num] == NULL) {
ret = -ENODEV;
if (ret) {
dev_err(&client->dev,
"failed to register multiplexed adapter"
" %d as bus %d\n", num, force);
@@ -263,23 +269,15 @@ static int pca954x_probe(struct i2c_client *client,
return 0;
virt_reg_failed:
for (num--; num >= 0; num--)
i2c_del_mux_adapter(data->virt_adaps[num]);
i2c_mux_del_adapters(muxc);
return ret;
}
static int pca954x_remove(struct i2c_client *client)
{
struct pca954x *data = i2c_get_clientdata(client);
const struct chip_desc *chip = &chips[data->type];
int i;
for (i = 0; i < chip->nchans; ++i)
if (data->virt_adaps[i]) {
i2c_del_mux_adapter(data->virt_adaps[i]);
data->virt_adaps[i] = NULL;
}
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
i2c_mux_del_adapters(muxc);
return 0;
}
@@ -287,7 +285,8 @@ static int pca954x_remove(struct i2c_client *client)
static int pca954x_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pca954x *data = i2c_get_clientdata(client);
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
struct pca954x *data = i2c_mux_priv(muxc);
data->last_chan = 0;
return i2c_smbus_write_byte(client, 0);

View File

@@ -24,36 +24,32 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of.h>
#include "../../pinctrl/core.h"
struct i2c_mux_pinctrl {
struct device *dev;
struct i2c_mux_pinctrl_platform_data *pdata;
struct pinctrl *pinctrl;
struct pinctrl_state **states;
struct pinctrl_state *state_idle;
struct i2c_adapter *parent;
struct i2c_adapter **busses;
};
static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data,
u32 chan)
static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
{
struct i2c_mux_pinctrl *mux = data;
struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
return pinctrl_select_state(mux->pinctrl, mux->states[chan]);
}
static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data,
u32 chan)
static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
{
struct i2c_mux_pinctrl *mux = data;
struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
return pinctrl_select_state(mux->pinctrl, mux->state_idle);
}
#ifdef CONFIG_OF
static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
struct platform_device *pdev)
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int num_names, i, ret;
@@ -64,15 +60,12 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
return 0;
mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL);
if (!mux->pdata) {
dev_err(mux->dev,
"Cannot allocate i2c_mux_pinctrl_platform_data\n");
if (!mux->pdata)
return -ENOMEM;
}
num_names = of_property_count_strings(np, "pinctrl-names");
if (num_names < 0) {
dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
num_names);
return num_names;
}
@@ -80,23 +73,22 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev,
sizeof(*mux->pdata->pinctrl_states) * num_names,
GFP_KERNEL);
if (!mux->pdata->pinctrl_states) {
dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
if (!mux->pdata->pinctrl_states)
return -ENOMEM;
}
for (i = 0; i < num_names; i++) {
ret = of_property_read_string_index(np, "pinctrl-names", i,
&mux->pdata->pinctrl_states[mux->pdata->bus_count]);
if (ret < 0) {
dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
ret);
return ret;
}
if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
"idle")) {
if (i != num_names - 1) {
dev_err(mux->dev, "idle state must be last\n");
dev_err(&pdev->dev,
"idle state must be last\n");
return -EINVAL;
}
mux->pdata->pinctrl_state_idle = "idle";
@@ -107,13 +99,13 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
adapter_np = of_parse_phandle(np, "i2c-parent", 0);
if (!adapter_np) {
dev_err(mux->dev, "Cannot parse i2c-parent\n");
dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
return -ENODEV;
}
adapter = of_find_i2c_adapter_by_node(adapter_np);
of_node_put(adapter_np);
if (!adapter) {
dev_err(mux->dev, "Cannot find parent bus\n");
dev_err(&pdev->dev, "Cannot find parent bus\n");
return -EPROBE_DEFER;
}
mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
@@ -129,21 +121,38 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
}
#endif
static struct i2c_adapter *i2c_mux_pinctrl_root_adapter(
struct pinctrl_state *state)
{
struct i2c_adapter *root = NULL;
struct pinctrl_setting *setting;
struct i2c_adapter *pin_root;
list_for_each_entry(setting, &state->settings, node) {
pin_root = i2c_root_adapter(setting->pctldev->dev);
if (!pin_root)
return NULL;
if (!root)
root = pin_root;
else if (root != pin_root)
return NULL;
}
return root;
}
static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
{
struct i2c_mux_core *muxc;
struct i2c_mux_pinctrl *mux;
int (*deselect)(struct i2c_adapter *, void *, u32);
struct i2c_adapter *root;
int i, ret;
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n");
ret = -ENOMEM;
goto err;
}
platform_set_drvdata(pdev, mux);
mux->dev = &pdev->dev;
mux->pdata = dev_get_platdata(&pdev->dev);
if (!mux->pdata) {
@@ -166,14 +175,15 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
goto err;
}
mux->busses = devm_kzalloc(&pdev->dev,
sizeof(*mux->busses) * mux->pdata->bus_count,
GFP_KERNEL);
if (!mux->busses) {
dev_err(&pdev->dev, "Cannot allocate busses\n");
muxc = i2c_mux_alloc(NULL, &pdev->dev, mux->pdata->bus_count, 0, 0,
i2c_mux_pinctrl_select, NULL);
if (!muxc) {
ret = -ENOMEM;
goto err;
}
muxc->priv = mux;
platform_set_drvdata(pdev, muxc);
mux->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(mux->pinctrl)) {
@@ -184,13 +194,13 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
for (i = 0; i < mux->pdata->bus_count; i++) {
mux->states[i] = pinctrl_lookup_state(mux->pinctrl,
mux->pdata->pinctrl_states[i]);
if (IS_ERR(mux->states[i])) {
ret = PTR_ERR(mux->states[i]);
dev_err(&pdev->dev,
"Cannot look up pinctrl state %s: %d\n",
mux->pdata->pinctrl_states[i], ret);
goto err;
}
if (IS_ERR(mux->states[i])) {
ret = PTR_ERR(mux->states[i]);
dev_err(&pdev->dev,
"Cannot look up pinctrl state %s: %d\n",
mux->pdata->pinctrl_states[i], ret);
goto err;
}
}
if (mux->pdata->pinctrl_state_idle) {
mux->state_idle = pinctrl_lookup_state(mux->pinctrl,
@@ -203,29 +213,39 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
goto err;
}
deselect = i2c_mux_pinctrl_deselect;
} else {
deselect = NULL;
muxc->deselect = i2c_mux_pinctrl_deselect;
}
mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
if (!mux->parent) {
muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
if (!muxc->parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
mux->pdata->parent_bus_num);
ret = -EPROBE_DEFER;
goto err;
}
root = i2c_root_adapter(&muxc->parent->dev);
muxc->mux_locked = true;
for (i = 0; i < mux->pdata->bus_count; i++) {
if (root != i2c_mux_pinctrl_root_adapter(mux->states[i])) {
muxc->mux_locked = false;
break;
}
}
if (muxc->mux_locked && mux->pdata->pinctrl_state_idle &&
root != i2c_mux_pinctrl_root_adapter(mux->state_idle))
muxc->mux_locked = false;
if (muxc->mux_locked)
dev_info(&pdev->dev, "mux-locked i2c mux\n");
for (i = 0; i < mux->pdata->bus_count; i++) {
u32 bus = mux->pdata->base_bus_num ?
(mux->pdata->base_bus_num + i) : 0;
mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev,
mux, bus, i, 0,
i2c_mux_pinctrl_select,
deselect);
if (!mux->busses[i]) {
ret = -ENODEV;
ret = i2c_mux_add_adapter(muxc, bus, i, 0);
if (ret) {
dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
goto err_del_adapter;
}
@@ -234,23 +254,18 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
return 0;
err_del_adapter:
for (; i > 0; i--)
i2c_del_mux_adapter(mux->busses[i - 1]);
i2c_put_adapter(mux->parent);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
err:
return ret;
}
static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
{
struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev);
int i;
for (i = 0; i < mux->pdata->bus_count; i++)
i2c_del_mux_adapter(mux->busses[i]);
i2c_put_adapter(mux->parent);
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
return 0;
}

View File

@@ -21,8 +21,6 @@
#include <linux/slab.h>
struct regmux {
struct i2c_adapter *parent;
struct i2c_adapter **adap; /* child busses */
struct i2c_mux_reg_platform_data data;
};
@@ -64,18 +62,16 @@ static int i2c_mux_reg_set(const struct regmux *mux, unsigned int chan_id)
return 0;
}
static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data,
unsigned int chan)
static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan)
{
struct regmux *mux = data;
struct regmux *mux = i2c_mux_priv(muxc);
return i2c_mux_reg_set(mux, chan);
}
static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
unsigned int chan)
static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
{
struct regmux *mux = data;
struct regmux *mux = i2c_mux_priv(muxc);
if (mux->data.idle_in_use)
return i2c_mux_reg_set(mux, mux->data.idle);
@@ -85,7 +81,7 @@ static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
#ifdef CONFIG_OF
static int i2c_mux_reg_probe_dt(struct regmux *mux,
struct platform_device *pdev)
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *adapter_np, *child;
@@ -107,7 +103,6 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
if (!adapter)
return -EPROBE_DEFER;
mux->parent = adapter;
mux->data.parent = i2c_adapter_id(adapter);
put_device(&adapter->dev);
@@ -161,7 +156,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
}
#else
static int i2c_mux_reg_probe_dt(struct regmux *mux,
struct platform_device *pdev)
struct platform_device *pdev)
{
return 0;
}
@@ -169,10 +164,10 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
static int i2c_mux_reg_probe(struct platform_device *pdev)
{
struct i2c_mux_core *muxc;
struct regmux *mux;
struct i2c_adapter *parent;
struct resource *res;
int (*deselect)(struct i2c_adapter *, void *, u32);
unsigned int class;
int i, ret, nr;
@@ -180,17 +175,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
if (!mux)
return -ENOMEM;
platform_set_drvdata(pdev, mux);
if (dev_get_platdata(&pdev->dev)) {
memcpy(&mux->data, dev_get_platdata(&pdev->dev),
sizeof(mux->data));
parent = i2c_get_adapter(mux->data.parent);
if (!parent)
return -EPROBE_DEFER;
mux->parent = parent;
} else {
ret = i2c_mux_reg_probe_dt(mux, pdev);
if (ret < 0) {
@@ -199,6 +186,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
}
}
parent = i2c_get_adapter(mux->data.parent);
if (!parent)
return -EPROBE_DEFER;
if (!mux->data.reg) {
dev_info(&pdev->dev,
"Register not set, using platform resource\n");
@@ -215,55 +206,45 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
return -EINVAL;
}
mux->adap = devm_kzalloc(&pdev->dev,
sizeof(*mux->adap) * mux->data.n_values,
GFP_KERNEL);
if (!mux->adap) {
dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
i2c_mux_reg_select, NULL);
if (!muxc)
return -ENOMEM;
}
muxc->priv = mux;
platform_set_drvdata(pdev, muxc);
if (mux->data.idle_in_use)
deselect = i2c_mux_reg_deselect;
else
deselect = NULL;
muxc->deselect = i2c_mux_reg_deselect;
for (i = 0; i < mux->data.n_values; i++) {
nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
class = mux->data.classes ? mux->data.classes[i] : 0;
mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux,
nr, mux->data.values[i],
class, i2c_mux_reg_select,
deselect);
if (!mux->adap[i]) {
ret = -ENODEV;
ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
if (ret) {
dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
goto add_adapter_failed;
}
}
dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
mux->data.n_values, mux->parent->name);
mux->data.n_values, muxc->parent->name);
return 0;
add_adapter_failed:
for (; i > 0; i--)
i2c_del_mux_adapter(mux->adap[i - 1]);
i2c_mux_del_adapters(muxc);
return ret;
}
static int i2c_mux_reg_remove(struct platform_device *pdev)
{
struct regmux *mux = platform_get_drvdata(pdev);
int i;
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
for (i = 0; i < mux->data.n_values; i++)
i2c_del_mux_adapter(mux->adap[i]);
i2c_put_adapter(mux->parent);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
return 0;
}