Commit 871dda46 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c updates from Wolfram Sang:
 "I2C has a smaller pull reuest this time:

   - new driver for I2C virtio

   - removal of PMC SMP driver because platform is already gone

   - IRQ probing and DMAENGINE API cleanups

   - add SI metric prefix definitions to units.h

   - beginning of i801 refactorization

   - a few driver improvements"

* 'i2c/for-mergewindow' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (28 commits)
  i2c: cadence: Implement save restore
  i2c: xlp9xx: fix main IRQ check
  i2c: mt65xx: fix IRQ check
  i2c: virtio: add a virtio i2c frontend driver
  i2c: hix5hd2: fix IRQ check
  i2c: s3c2410: fix IRQ check
  i2c: iop3xx: fix deferred probing
  i2c: synquacer: fix deferred probing
  i2c: sun6i-pw2i: Prefer strscpy over strlcpy
  i2c: remove dead PMC MSP TWI/SMBus/I2C driver
  i2c: dev: Use sysfs_emit() in "show" functions
  i2c: dev: Define pr_fmt() and drop duplication substrings
  i2c: designware: Fix indentation in the header
  i2c: designware: Use DIV_ROUND_CLOSEST() macro
  units: Add SI metric prefix definitions
  i2c: at91: mark PM ops as __maybe unused
  i2c: sh_mobile: : use proper DMAENGINE API for termination
  i2c: qup: : use proper DMAENGINE API for termination
  i2c: mxs: : use proper DMAENGINE API for termination
  i2c: imx: : use proper DMAENGINE API for termination
  ...
parents 359f3d74 8b51a8e6
...@@ -19736,6 +19736,15 @@ S: Maintained ...@@ -19736,6 +19736,15 @@ S: Maintained
F: include/uapi/linux/virtio_snd.h F: include/uapi/linux/virtio_snd.h
F: sound/virtio/* F: sound/virtio/*
VIRTIO I2C DRIVER
M: Jie Deng <jie.deng@intel.com>
M: Viresh Kumar <viresh.kumar@linaro.org>
L: linux-i2c@vger.kernel.org
L: virtualization@lists.linux-foundation.org
S: Maintained
F: drivers/i2c/busses/i2c-virtio.c
F: include/uapi/linux/virtio_i2c.h
VIRTUAL BOX GUEST DEVICE DRIVER VIRTUAL BOX GUEST DEVICE DRIVER
M: Hans de Goede <hdegoede@redhat.com> M: Hans de Goede <hdegoede@redhat.com>
M: Arnd Bergmann <arnd@arndb.de> M: Arnd Bergmann <arnd@arndb.de>
......
...@@ -866,15 +866,6 @@ config I2C_PCA_PLATFORM ...@@ -866,15 +866,6 @@ config I2C_PCA_PLATFORM
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-pca-platform. will be called i2c-pca-platform.
config I2C_PMCMSP
tristate "PMC MSP I2C TWI Controller"
depends on PMC_MSP || COMPILE_TEST
help
This driver supports the PMC TWI controller on MSP devices.
This driver can also be built as module. If so, the module
will be called i2c-pmcmsp.
config I2C_PNX config I2C_PNX
tristate "I2C bus support for Philips PNX and NXP LPC targets" tristate "I2C bus support for Philips PNX and NXP LPC targets"
depends on ARCH_LPC32XX || COMPILE_TEST depends on ARCH_LPC32XX || COMPILE_TEST
...@@ -1402,4 +1393,15 @@ config I2C_FSI ...@@ -1402,4 +1393,15 @@ config I2C_FSI
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called as i2c-fsi. called as i2c-fsi.
config I2C_VIRTIO
tristate "Virtio I2C Adapter"
select VIRTIO
help
If you say yes to this option, support will be included for the virtio
I2C adapter driver. The hardware can be emulated by any device model
software according to the virtio protocol.
This driver can also be built as a module. If so, the module
will be called i2c-virtio.
endmenu endmenu
...@@ -86,7 +86,6 @@ obj-$(CONFIG_I2C_OMAP) += i2c-omap.o ...@@ -86,7 +86,6 @@ obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_OWL) += i2c-owl.o obj-$(CONFIG_I2C_OWL) += i2c-owl.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
...@@ -146,5 +145,6 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o ...@@ -146,5 +145,6 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_I2C_FSI) += i2c-fsi.o obj-$(CONFIG_I2C_FSI) += i2c-fsi.o
obj-$(CONFIG_I2C_VIRTIO) += i2c-virtio.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
...@@ -286,9 +286,7 @@ static int at91_twi_remove(struct platform_device *pdev) ...@@ -286,9 +286,7 @@ static int at91_twi_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused at91_twi_runtime_suspend(struct device *dev)
static int at91_twi_runtime_suspend(struct device *dev)
{ {
struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
...@@ -299,7 +297,7 @@ static int at91_twi_runtime_suspend(struct device *dev) ...@@ -299,7 +297,7 @@ static int at91_twi_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static int at91_twi_runtime_resume(struct device *dev) static int __maybe_unused at91_twi_runtime_resume(struct device *dev)
{ {
struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
...@@ -308,7 +306,7 @@ static int at91_twi_runtime_resume(struct device *dev) ...@@ -308,7 +306,7 @@ static int at91_twi_runtime_resume(struct device *dev)
return clk_prepare_enable(twi_dev->clk); return clk_prepare_enable(twi_dev->clk);
} }
static int at91_twi_suspend_noirq(struct device *dev) static int __maybe_unused at91_twi_suspend_noirq(struct device *dev)
{ {
if (!pm_runtime_status_suspended(dev)) if (!pm_runtime_status_suspended(dev))
at91_twi_runtime_suspend(dev); at91_twi_runtime_suspend(dev);
...@@ -316,7 +314,7 @@ static int at91_twi_suspend_noirq(struct device *dev) ...@@ -316,7 +314,7 @@ static int at91_twi_suspend_noirq(struct device *dev)
return 0; return 0;
} }
static int at91_twi_resume_noirq(struct device *dev) static int __maybe_unused at91_twi_resume_noirq(struct device *dev)
{ {
struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
int ret; int ret;
...@@ -335,18 +333,13 @@ static int at91_twi_resume_noirq(struct device *dev) ...@@ -335,18 +333,13 @@ static int at91_twi_resume_noirq(struct device *dev)
return 0; return 0;
} }
static const struct dev_pm_ops at91_twi_pm = { static const struct dev_pm_ops __maybe_unused at91_twi_pm = {
.suspend_noirq = at91_twi_suspend_noirq, .suspend_noirq = at91_twi_suspend_noirq,
.resume_noirq = at91_twi_resume_noirq, .resume_noirq = at91_twi_resume_noirq,
.runtime_suspend = at91_twi_runtime_suspend, .runtime_suspend = at91_twi_runtime_suspend,
.runtime_resume = at91_twi_runtime_resume, .runtime_resume = at91_twi_runtime_resume,
}; };
#define at91_twi_pm_ops (&at91_twi_pm)
#else
#define at91_twi_pm_ops NULL
#endif
static struct platform_driver at91_twi_driver = { static struct platform_driver at91_twi_driver = {
.probe = at91_twi_probe, .probe = at91_twi_probe,
.remove = at91_twi_remove, .remove = at91_twi_remove,
...@@ -354,7 +347,7 @@ static struct platform_driver at91_twi_driver = { ...@@ -354,7 +347,7 @@ static struct platform_driver at91_twi_driver = {
.driver = { .driver = {
.name = "at91_i2c", .name = "at91_i2c",
.of_match_table = of_match_ptr(atmel_twi_dt_ids), .of_match_table = of_match_ptr(atmel_twi_dt_ids),
.pm = at91_twi_pm_ops, .pm = pm_ptr(&at91_twi_pm),
}, },
}; };
......
...@@ -138,9 +138,9 @@ static void at91_twi_dma_cleanup(struct at91_twi_dev *dev) ...@@ -138,9 +138,9 @@ static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
if (dma->xfer_in_progress) { if (dma->xfer_in_progress) {
if (dma->direction == DMA_FROM_DEVICE) if (dma->direction == DMA_FROM_DEVICE)
dmaengine_terminate_all(dma->chan_rx); dmaengine_terminate_sync(dma->chan_rx);
else else
dmaengine_terminate_all(dma->chan_tx); dmaengine_terminate_sync(dma->chan_tx);
dma->xfer_in_progress = false; dma->xfer_in_progress = false;
} }
if (dma->buf_mapped) { if (dma->buf_mapped) {
......
...@@ -178,6 +178,7 @@ enum cdns_i2c_slave_state { ...@@ -178,6 +178,7 @@ enum cdns_i2c_slave_state {
* @clk: Pointer to struct clk * @clk: Pointer to struct clk
* @clk_rate_change_nb: Notifier block for clock rate changes * @clk_rate_change_nb: Notifier block for clock rate changes
* @quirks: flag for broken hold bit usage in r1p10 * @quirks: flag for broken hold bit usage in r1p10
* @ctrl_reg: Cached value of the control register.
* @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register * @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register
* @slave: Registered slave instance. * @slave: Registered slave instance.
* @dev_mode: I2C operating role(master/slave). * @dev_mode: I2C operating role(master/slave).
...@@ -202,6 +203,7 @@ struct cdns_i2c { ...@@ -202,6 +203,7 @@ struct cdns_i2c {
struct clk *clk; struct clk *clk;
struct notifier_block clk_rate_change_nb; struct notifier_block clk_rate_change_nb;
u32 quirks; u32 quirks;
u32 ctrl_reg;
#if IS_ENABLED(CONFIG_I2C_SLAVE) #if IS_ENABLED(CONFIG_I2C_SLAVE)
u16 ctrl_reg_diva_divb; u16 ctrl_reg_diva_divb;
struct i2c_client *slave; struct i2c_client *slave;
...@@ -1071,10 +1073,11 @@ static int cdns_i2c_setclk(unsigned long clk_in, struct cdns_i2c *id) ...@@ -1071,10 +1073,11 @@ static int cdns_i2c_setclk(unsigned long clk_in, struct cdns_i2c *id)
if (ret) if (ret)
return ret; return ret;
ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); ctrl_reg = id->ctrl_reg;
ctrl_reg &= ~(CDNS_I2C_CR_DIVA_MASK | CDNS_I2C_CR_DIVB_MASK); ctrl_reg &= ~(CDNS_I2C_CR_DIVA_MASK | CDNS_I2C_CR_DIVB_MASK);
ctrl_reg |= ((div_a << CDNS_I2C_CR_DIVA_SHIFT) | ctrl_reg |= ((div_a << CDNS_I2C_CR_DIVA_SHIFT) |
(div_b << CDNS_I2C_CR_DIVB_SHIFT)); (div_b << CDNS_I2C_CR_DIVB_SHIFT));
id->ctrl_reg = ctrl_reg;
cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
#if IS_ENABLED(CONFIG_I2C_SLAVE) #if IS_ENABLED(CONFIG_I2C_SLAVE)
id->ctrl_reg_diva_divb = ctrl_reg & (CDNS_I2C_CR_DIVA_MASK | id->ctrl_reg_diva_divb = ctrl_reg & (CDNS_I2C_CR_DIVA_MASK |
...@@ -1162,6 +1165,26 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) ...@@ -1162,6 +1165,26 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
return 0; return 0;
} }
/**
* cdns_i2c_init - Controller initialisation
* @id: Device private data structure
*
* Initialise the i2c controller.
*
*/
static void cdns_i2c_init(struct cdns_i2c *id)
{
cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
/*
* Cadence I2C controller has a bug wherein it generates
* invalid read transaction after HW timeout in master receiver mode.
* HW timeout is not used by this driver and the interrupt is disabled.
* But the feature itself cannot be disabled. Hence maximum value
* is written to this register to reduce the chances of error.
*/
cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
}
/** /**
* cdns_i2c_runtime_resume - Runtime resume * cdns_i2c_runtime_resume - Runtime resume
* @dev: Address of the platform_device structure * @dev: Address of the platform_device structure
...@@ -1180,6 +1203,7 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) ...@@ -1180,6 +1203,7 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
dev_err(dev, "Cannot enable clock.\n"); dev_err(dev, "Cannot enable clock.\n");
return ret; return ret;
} }
cdns_i2c_init(xi2c);
return 0; return 0;
} }
...@@ -1279,7 +1303,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) ...@@ -1279,7 +1303,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
id->dev_mode = CDNS_I2C_MODE_MASTER; id->dev_mode = CDNS_I2C_MODE_MASTER;
id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE; id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE;
#endif #endif
cdns_i2c_writereg(CDNS_I2C_CR_MASTER_EN_MASK, CDNS_I2C_CR_OFFSET); id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS;
ret = cdns_i2c_setclk(id->input_clk, id); ret = cdns_i2c_setclk(id->input_clk, id);
if (ret) { if (ret) {
...@@ -1294,15 +1318,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) ...@@ -1294,15 +1318,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
goto err_clk_dis; goto err_clk_dis;
} }
cdns_i2c_init(id);
/*
* Cadence I2C controller has a bug wherein it generates
* invalid read transaction after HW timeout in master receiver mode.
* HW timeout is not used by this driver and the interrupt is disabled.
* But the feature itself cannot be disabled. Hence maximum value
* is written to this register to reduce the chances of error.
*/
cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
ret = i2c_add_adapter(&id->adap); ret = i2c_add_adapter(&id->adap);
if (ret < 0) if (ret < 0)
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/swab.h> #include <linux/swab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/units.h>
#include "i2c-designware-core.h" #include "i2c-designware-core.h"
...@@ -350,7 +351,7 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) ...@@ -350,7 +351,7 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
* *
* If your hardware is free from tHD;STA issue, try this one. * If your hardware is free from tHD;STA issue, try this one.
*/ */
return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset; return DIV_ROUND_CLOSEST(ic_clk * tSYMBOL, MICRO) - 8 + offset;
else else
/* /*
* Conditional expression: * Conditional expression:
...@@ -366,8 +367,7 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) ...@@ -366,8 +367,7 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
* The reason why we need to take into account "tf" here, * The reason why we need to take into account "tf" here,
* is the same as described in i2c_dw_scl_lcnt(). * is the same as described in i2c_dw_scl_lcnt().
*/ */
return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000 return DIV_ROUND_CLOSEST(ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset;
- 3 + offset;
} }
u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
...@@ -383,7 +383,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) ...@@ -383,7 +383,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
* account the fall time of SCL signal (tf). Default tf value * account the fall time of SCL signal (tf). Default tf value
* should be 0.3 us, for safety. * should be 0.3 us, for safety.
*/ */
return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; return DIV_ROUND_CLOSEST(ic_clk * (tLOW + tf), MICRO) - 1 + offset;
} }
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev) int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
......
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
#define DW_IC_ERR_TX_ABRT 0x1 #define DW_IC_ERR_TX_ABRT 0x1
#define DW_IC_TAR_10BITADDR_MASTER BIT(12) #define DW_IC_TAR_10BITADDR_MASTER BIT(12)
#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3)) #define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3))
#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2) #define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2)
...@@ -245,7 +245,7 @@ struct dw_i2c_dev { ...@@ -245,7 +245,7 @@ struct dw_i2c_dev {
struct clk *clk; struct clk *clk;
struct clk *pclk; struct clk *pclk;
struct reset_control *rst; struct reset_control *rst;
struct i2c_client *slave; struct i2c_client *slave;
u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev); u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev);
int cmd_err; int cmd_err;
struct i2c_msg *msgs; struct i2c_msg *msgs;
......
...@@ -31,12 +31,13 @@ ...@@ -31,12 +31,13 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/units.h>
#include "i2c-designware-core.h" #include "i2c-designware-core.h"
static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
{ {
return clk_get_rate(dev->clk)/1000; return clk_get_rate(dev->clk) / KILO;
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
...@@ -270,7 +271,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) ...@@ -270,7 +271,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
if (!dev->sda_hold_time && t->sda_hold_ns) if (!dev->sda_hold_time && t->sda_hold_ns)
dev->sda_hold_time = dev->sda_hold_time =
div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000); DIV_S64_ROUND_CLOSEST(clk_khz * t->sda_hold_ns, MICRO);
} }
adap = &dev->adapter; adap = &dev->adapter;
......
...@@ -379,7 +379,7 @@ static int highlander_i2c_probe(struct platform_device *pdev) ...@@ -379,7 +379,7 @@ static int highlander_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
dev->irq = platform_get_irq(pdev, 0); dev->irq = platform_get_irq(pdev, 0);
if (iic_force_poll) if (dev->irq < 0 || iic_force_poll)
dev->irq = 0; dev->irq = 0;
if (dev->irq) { if (dev->irq) {
......
...@@ -413,7 +413,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) ...@@ -413,7 +413,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
return PTR_ERR(priv->regs); return PTR_ERR(priv->regs);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq <= 0) if (irq < 0)
return irq; return irq;
priv->clk = devm_clk_get(&pdev->dev, NULL); priv->clk = devm_clk_get(&pdev->dev, NULL);
......
...@@ -110,6 +110,7 @@ ...@@ -110,6 +110,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/itco_wdt.h> #include <linux/platform_data/itco_wdt.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/mutex.h>
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
#include <linux/gpio/machine.h> #include <linux/gpio/machine.h>
...@@ -503,19 +504,16 @@ static int i801_transaction(struct i801_priv *priv, int xact) ...@@ -503,19 +504,16 @@ static int i801_transaction(struct i801_priv *priv, int xact)
static int i801_block_transaction_by_block(struct i801_priv *priv, static int i801_block_transaction_by_block(struct i801_priv *priv,
union i2c_smbus_data *data, union i2c_smbus_data *data,
char read_write, int command, char read_write, int command)
int hwpec)
{ {
int i, len; int i, len, status, xact;
int status;
int xact = hwpec ? SMBHSTCNT_PEC_EN : 0;
switch (command) { switch (command) {
case I2C_SMBUS_BLOCK_PROC_CALL: case I2C_SMBUS_BLOCK_PROC_CALL:
xact |= I801_BLOCK_PROC_CALL; xact = I801_BLOCK_PROC_CALL;
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
xact |= I801_BLOCK_DATA; xact = I801_BLOCK_DATA;
break; break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -561,10 +559,6 @@ static void i801_isr_byte_done(struct i801_priv *priv) ...@@ -561,10 +559,6 @@ static void i801_isr_byte_done(struct i801_priv *priv)
priv->len); priv->len);
/* FIXME: Recover */ /* FIXME: Recover */
priv->len = I2C_SMBUS_BLOCK_MAX; priv->len = I2C_SMBUS_BLOCK_MAX;
} else {
dev_dbg(&priv->pci_dev->dev,
"SMBus block read size is %d\n",
priv->len);
} }
priv->data[-1] = priv->len; priv->data[-1] = priv->len;
} }
...@@ -665,8 +659,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id) ...@@ -665,8 +659,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
*/ */
static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
union i2c_smbus_data *data, union i2c_smbus_data *data,
char read_write, int command, char read_write, int command)
int hwpec)
{ {
int i, len; int i, len;
int smbcmd; int smbcmd;
...@@ -764,9 +757,8 @@ static int i801_set_block_buffer_mode(struct i801_priv *priv) ...@@ -764,9 +757,8 @@ static int i801_set_block_buffer_mode(struct i801_priv *priv)
} }
/* Block transaction function */ /* Block transaction function */
static int i801_block_transaction(struct i801_priv *priv, static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
union i2c_smbus_data *data, char read_write, char read_write, int command)
int command, int hwpec)
{ {
int result = 0; int result = 0;
unsigned char hostc; unsigned char hostc;
...@@ -802,11 +794,11 @@ static int i801_block_transaction(struct i801_priv *priv, ...@@ -802,11 +794,11 @@ static int i801_block_transaction(struct i801_priv *priv,
&& i801_set_block_buffer_mode(priv) == 0) && i801_set_block_buffer_mode(priv) == 0)
result = i801_block_transaction_by_block(priv, data, result = i801_block_transaction_by_block(priv, data,
read_write, read_write,
command, hwpec); command);
else else
result = i801_block_transaction_byte_by_byte(priv, data, result = i801_block_transaction_byte_by_byte(priv, data,
read_write, read_write,
command, hwpec); command);
if (command == I2C_SMBUS_I2C_BLOCK_DATA if (command == I2C_SMBUS_I2C_BLOCK_DATA
&& read_write == I2C_SMBUS_WRITE) { && read_write == I2C_SMBUS_WRITE) {
...@@ -917,8 +909,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, ...@@ -917,8 +909,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
SMBAUXCTL(priv)); SMBAUXCTL(priv));
if (block) if (block)
ret = i801_block_transaction(priv, data, read_write, size, ret = i801_block_transaction(priv, data, read_write, size);
hwpec);
else else
ret = i801_transaction(priv, xact); ret = i801_transaction(priv, xact);
...@@ -1498,12 +1489,11 @@ static const struct itco_wdt_platform_data spt_tco_platform_data = { ...@@ -1498,12 +1489,11 @@ static const struct itco_wdt_platform_data spt_tco_platform_data = {
.version = 4, .version = 4,
}; };
static DEFINE_SPINLOCK(p2sb_spinlock);
static struct platform_device * static struct platform_device *
i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
struct resource *tco_res) struct resource *tco_res)
{ {
static DEFINE_MUTEX(p2sb_mutex);
struct resource *res; struct resource *res;
unsigned int devfn; unsigned int devfn;
u64 base64_addr; u64 base64_addr;
...@@ -1516,7 +1506,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, ...@@ -1516,7 +1506,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
* enumerated by the PCI subsystem, so we need to unhide/hide it * enumerated by the PCI subsystem, so we need to unhide/hide it
* to lookup the P2SB BAR. * to lookup the P2SB BAR.
*/ */
spin_lock(&p2sb_spinlock); mutex_lock(&p2sb_mutex);
devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1); devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1);
...@@ -1534,7 +1524,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, ...@@ -1534,7 +1524,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
/* Hide the P2SB device, if it was hidden before */ /* Hide the P2SB device, if it was hidden before */
if (hidden) if (hidden)
pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden); pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);
spin_unlock(&p2sb_spinlock); mutex_unlock(&p2sb_mutex);
res = &tco_res[1]; res = &tco_res[1];
if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
...@@ -1634,7 +1624,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, ...@@ -1634,7 +1624,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
* BIOS is accessing the host controller so prevent it from * BIOS is accessing the host controller so prevent it from
* suspending automatically from now on. * suspending automatically from now on.
*/ */
pm_runtime_get_sync(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
} }
if ((function & ACPI_IO_MASK) == ACPI_READ) if ((function & ACPI_IO_MASK) == ACPI_READ)
...@@ -1674,11 +1664,6 @@ static void i801_acpi_remove(struct i801_priv *priv) ...@@ -1674,11 +1664,6 @@ static void i801_acpi_remove(struct i801_priv *priv)
acpi_remove_address_space_handler(adev->handle, acpi_remove_address_space_handler(adev->handle,
ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler); ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler);
mutex_lock(&priv->acpi_lock);
if (priv->acpi_reserved)
pm_runtime_put(&priv->pci_dev->dev);
mutex_unlock(&priv->acpi_lock);
} }
#else #else
static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; } static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
...@@ -1690,6 +1675,7 @@ static void i801_setup_hstcfg(struct i801_priv *priv) ...@@ -1690,6 +1675,7 @@ static void i801_setup_hstcfg(struct i801_priv *priv)
unsigned char hstcfg = priv->original_hstcfg; unsigned char hstcfg = priv->original_hstcfg;
hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
hstcfg &= ~SMBHSTCNT_PEC_EN; /* Disable software PEC */
hstcfg |= SMBHSTCFG_HST_EN; hstcfg |= SMBHSTCFG_HST_EN;
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg); pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
} }
......
...@@ -423,7 +423,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx, ...@@ -423,7 +423,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
return 0; return 0;
err_submit: err_submit:
dmaengine_terminate_all(dma->chan_using); dmaengine_terminate_sync(dma->chan_using);
err_desc: err_desc:
dma_unmap_single(chan_dev, dma->dma_buf, dma_unmap_single(chan_dev, dma->dma_buf,
dma->dma_len, dma->dma_data_dir); dma->dma_len, dma->dma_data_dir);
...@@ -894,7 +894,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx, ...@@ -894,7 +894,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
&i2c_imx->dma->cmd_complete, &i2c_imx->dma->cmd_complete,
msecs_to_jiffies(DMA_TIMEOUT)); msecs_to_jiffies(DMA_TIMEOUT));
if (time_left == 0) { if (time_left == 0) {
dmaengine_terminate_all(dma->chan_using); dmaengine_terminate_sync(dma->chan_using);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -949,7 +949,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, ...@@ -949,7 +949,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
&i2c_imx->dma->cmd_complete, &i2c_imx->dma->cmd_complete,
msecs_to_jiffies(DMA_TIMEOUT)); msecs_to_jiffies(DMA_TIMEOUT));
if (time_left == 0) { if (time_left == 0) {
dmaengine_terminate_all(dma->chan_using); dmaengine_terminate_sync(dma->chan_using);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
......
...@@ -469,16 +469,14 @@ iop3xx_i2c_probe(struct platform_device *pdev) ...@@ -469,16 +469,14 @@ iop3xx_i2c_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
ret = -ENXIO; ret = irq;
goto unmap; goto unmap;
} }
ret = request_irq(irq, iop3xx_i2c_irq_handler, 0, ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
pdev->name, adapter_data); pdev->name, adapter_data);
if (ret) { if (ret)
ret = -EIO;
goto unmap; goto unmap;
}
memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
new_adapter->owner = THIS_MODULE; new_adapter->owner = THIS_MODULE;
......
...@@ -1211,7 +1211,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) ...@@ -1211,7 +1211,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c->pdmabase); return PTR_ERR(i2c->pdmabase);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq <= 0) if (irq < 0)
return irq; return irq;
init_completion(&i2c->msg_complete); init_completion(&i2c->msg_complete);
......
...@@ -290,14 +290,14 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, ...@@ -290,14 +290,14 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
select_init_dma_fail: select_init_dma_fail:
dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
select_init_pio_fail: select_init_pio_fail:
dmaengine_terminate_all(i2c->dmach); dmaengine_terminate_sync(i2c->dmach);
return -EINVAL; return -EINVAL;
/* Write failpath. */ /* Write failpath. */
write_init_dma_fail: write_init_dma_fail:
dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
write_init_pio_fail: write_init_pio_fail:
dmaengine_terminate_all(i2c->dmach); dmaengine_terminate_sync(i2c->dmach);
return -EINVAL; return -EINVAL;
} }
......
...@@ -267,6 +267,16 @@ static void i2c_parport_attach(struct parport *port) ...@@ -267,6 +267,16 @@ static void i2c_parport_attach(struct parport *port)
int i; int i;
struct pardev_cb i2c_parport_cb; struct pardev_cb i2c_parport_cb;
if (type < 0) {
pr_warn("adapter type unspecified\n");
return;
}
if (type >= ARRAY_SIZE(adapter_parm)) {
pr_warn("invalid type (%d)\n", type);
return;
}
for (i = 0; i < MAX_DEVICE; i++) { for (i = 0; i < MAX_DEVICE; i++) {
if (parport[i] == -1) if (parport[i] == -1)
continue; continue;
...@@ -392,32 +402,8 @@ static struct parport_driver i2c_parport_driver = { ...@@ -392,32 +402,8 @@ static struct parport_driver i2c_parport_driver = {
.detach = i2c_parport_detach, .detach = i2c_parport_detach,
.devmodel = true, .devmodel = true,
}; };
module_parport_driver(i2c_parport_driver);
/* ----- Module loading, unloading and information ------------------------ */
static int __init i2c_parport_init(void)
{
if (type < 0) {
pr_warn("adapter type unspecified\n");
return -ENODEV;
}
if (type >= ARRAY_SIZE(adapter_parm)) {
pr_warn("invalid type (%d)\n", type);
return -ENODEV;
}
return parport_register_driver(&i2c_parport_driver);
}
static void __exit i2c_parport_exit(void)
{
parport_unregister_driver(&i2c_parport_driver);
}
MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
MODULE_DESCRIPTION("I2C bus over parallel port"); MODULE_DESCRIPTION("I2C bus over parallel port");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(i2c_parport_init);
module_exit(i2c_parport_exit);
This diff is collapsed.
...@@ -778,7 +778,7 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup) ...@@ -778,7 +778,7 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)
ret = -EINVAL; ret = -EINVAL;
/* abort TX descriptors */ /* abort TX descriptors */
dmaengine_terminate_all(qup->btx.dma); dmaengine_terminate_sync(qup->btx.dma);
goto desc_err; goto desc_err;
} }
......
...@@ -1137,7 +1137,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -1137,7 +1137,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
*/ */
if (!(i2c->quirks & QUIRK_POLL)) { if (!(i2c->quirks & QUIRK_POLL)) {
i2c->irq = ret = platform_get_irq(pdev, 0); i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) { if (ret < 0) {
dev_err(&pdev->dev, "cannot find IRQ\n"); dev_err(&pdev->dev, "cannot find IRQ\n");
clk_unprepare(i2c->clk); clk_unprepare(i2c->clk);
return ret; return ret;
......
...@@ -458,9 +458,9 @@ static void sh_mobile_i2c_cleanup_dma(struct sh_mobile_i2c_data *pd) ...@@ -458,9 +458,9 @@ static void sh_mobile_i2c_cleanup_dma(struct sh_mobile_i2c_data *pd)
if (pd->dma_direction == DMA_NONE) if (pd->dma_direction == DMA_NONE)
return; return;
else if (pd->dma_direction == DMA_FROM_DEVICE) else if (pd->dma_direction == DMA_FROM_DEVICE)
dmaengine_terminate_all(pd->dma_rx); dmaengine_terminate_sync(pd->dma_rx);
else if (pd->dma_direction == DMA_TO_DEVICE) else if (pd->dma_direction == DMA_TO_DEVICE)
dmaengine_terminate_all(pd->dma_tx); dmaengine_terminate_sync(pd->dma_tx);
sh_mobile_i2c_dma_unmap(pd); sh_mobile_i2c_dma_unmap(pd);
} }
......
...@@ -234,7 +234,7 @@ static int p2wi_probe(struct platform_device *pdev) ...@@ -234,7 +234,7 @@ static int p2wi_probe(struct platform_device *pdev)
if (IS_ERR(p2wi->regs)) if (IS_ERR(p2wi->regs))
return PTR_ERR(p2wi->regs); return PTR_ERR(p2wi->regs);
strlcpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name)); strscpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name));
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
return irq; return irq;
......
...@@ -578,7 +578,7 @@ static int synquacer_i2c_probe(struct platform_device *pdev) ...@@ -578,7 +578,7 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
i2c->irq = platform_get_irq(pdev, 0); i2c->irq = platform_get_irq(pdev, 0);
if (i2c->irq < 0) if (i2c->irq < 0)
return -ENODEV; return i2c->irq;
ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr, ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr,
0, dev_name(&pdev->dev), i2c); 0, dev_name(&pdev->dev), i2c);
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Virtio I2C Bus Driver
*
* The Virtio I2C Specification:
* https://raw.githubusercontent.com/oasis-tcs/virtio-spec/master/virtio-i2c.tex
*
* Copyright (c) 2021 Intel Corporation. All rights reserved.
*/
#include <linux/acpi.h>
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
#include <linux/virtio_i2c.h>
/**
* struct virtio_i2c - virtio I2C data
* @vdev: virtio device for this controller
* @completion: completion of virtio I2C message
* @adap: I2C adapter for this controller
* @vq: the virtio virtqueue for communication
*/
struct virtio_i2c {
struct virtio_device *vdev;
struct completion completion;
struct i2c_adapter adap;
struct virtqueue *vq;
};
/**
* struct virtio_i2c_req - the virtio I2C request structure
* @out_hdr: the OUT header of the virtio I2C message
* @buf: the buffer into which data is read, or from which it's written
* @in_hdr: the IN header of the virtio I2C message
*/
struct virtio_i2c_req {
struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned;
uint8_t *buf ____cacheline_aligned;
struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned;
};
static void virtio_i2c_msg_done(struct virtqueue *vq)
{
struct virtio_i2c *vi = vq->vdev->priv;
complete(&vi->completion);
}
static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
struct virtio_i2c_req *reqs,
struct i2c_msg *msgs, int num)
{
struct scatterlist *sgs[3], out_hdr, msg_buf, in_hdr;
int i;
for (i = 0; i < num; i++) {
int outcnt = 0, incnt = 0;
/*
* We don't support 0 length messages and so filter out
* 0 length transfers by using i2c_adapter_quirks.
*/
if (!msgs[i].len)
break;
/*
* Only 7-bit mode supported for this moment. For the address
* format, Please check the Virtio I2C Specification.
*/
reqs[i].out_hdr.addr = cpu_to_le16(msgs[i].addr << 1);
if (i != num - 1)
reqs[i].out_hdr.flags = cpu_to_le32(VIRTIO_I2C_FLAGS_FAIL_NEXT);
sg_init_one(&out_hdr, &reqs[i].out_hdr, sizeof(reqs[i].out_hdr));
sgs[outcnt++] = &out_hdr;
reqs[i].buf = i2c_get_dma_safe_msg_buf(&msgs[i], 1);
if (!reqs[i].buf)
break;
sg_init_one(&msg_buf, reqs[i].buf, msgs[i].len);
if (msgs[i].flags & I2C_M_RD)
sgs[outcnt + incnt++] = &msg_buf;
else
sgs[outcnt++] = &msg_buf;
sg_init_one(&in_hdr, &reqs[i].in_hdr, sizeof(reqs[i].in_hdr));
sgs[outcnt + incnt++] = &in_hdr;
if (virtqueue_add_sgs(vq, sgs, outcnt, incnt, &reqs[i], GFP_KERNEL)) {
i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], false);
break;
}
}
return i;
}
static int virtio_i2c_complete_reqs(struct virtqueue *vq,
struct virtio_i2c_req *reqs,
struct i2c_msg *msgs, int num,
bool timedout)
{
struct virtio_i2c_req *req;
bool failed = timedout;
unsigned int len;
int i, j = 0;
for (i = 0; i < num; i++) {
/* Detach the ith request from the vq */
req = virtqueue_get_buf(vq, &len);
/*
* Condition req == &reqs[i] should always meet since we have
* total num requests in the vq. reqs[i] can never be NULL here.
*/
if (!failed && (WARN_ON(req != &reqs[i]) ||
req->in_hdr.status != VIRTIO_I2C_MSG_OK))
failed = true;
i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);
if (!failed)
j++;
}
return timedout ? -ETIMEDOUT : j;
}
static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct virtio_i2c *vi = i2c_get_adapdata(adap);
struct virtqueue *vq = vi->vq;
struct virtio_i2c_req *reqs;
unsigned long time_left;
int count;
reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL);
if (!reqs)
return -ENOMEM;
count = virtio_i2c_prepare_reqs(vq, reqs, msgs, num);
if (!count)
goto err_free;
/*
* For the case where count < num, i.e. we weren't able to queue all the
* msgs, ideally we should abort right away and return early, but some
* of the messages are already sent to the remote I2C controller and the
* virtqueue will be left in undefined state in that case. We kick the
* remote here to clear the virtqueue, so we can try another set of
* messages later on.
*/
reinit_completion(&vi->completion);
virtqueue_kick(vq);
time_left = wait_for_completion_timeout(&vi->completion, adap->timeout);
if (!time_left)
dev_err(&adap->dev, "virtio i2c backend timeout.\n");
count = virtio_i2c_complete_reqs(vq, reqs, msgs, count, !time_left);
err_free:
kfree(reqs);
return count;
}
static void virtio_i2c_del_vqs(struct virtio_device *vdev)
{
vdev->config->reset(vdev);
vdev->config->del_vqs(vdev);
}
static int virtio_i2c_setup_vqs(struct virtio_i2c *vi)
{
struct virtio_device *vdev = vi->vdev;
vi->vq = virtio_find_single_vq(vdev, virtio_i2c_msg_done, "msg");
return PTR_ERR_OR_ZERO(vi->vq);
}
static u32 virtio_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
}
static struct i2c_algorithm virtio_algorithm = {
.master_xfer = virtio_i2c_xfer,
.functionality = virtio_i2c_func,
};
static const struct i2c_adapter_quirks virtio_i2c_quirks = {
.flags = I2C_AQ_NO_ZERO_LEN,
};
static int virtio_i2c_probe(struct virtio_device *vdev)
{
struct virtio_i2c *vi;
int ret;
vi = devm_kzalloc(&vdev->dev, sizeof(*vi), GFP_KERNEL);
if (!vi)
return -ENOMEM;
vdev->priv = vi;
vi->vdev = vdev;
init_completion(&vi->completion);
ret = virtio_i2c_setup_vqs(vi);
if (ret)
return ret;
vi->adap.owner = THIS_MODULE;
snprintf(vi->adap.name, sizeof(vi->adap.name),
"i2c_virtio at virtio bus %d", vdev->index);
vi->adap.algo = &virtio_algorithm;
vi->adap.quirks = &virtio_i2c_quirks;
vi->adap.dev.parent = &vdev->dev;
vi->adap.dev.of_node = vdev->dev.of_node;
i2c_set_adapdata(&vi->adap, vi);
/*
* Setup ACPI node for controlled devices which will be probed through
* ACPI.
*/
ACPI_COMPANION_SET(&vi->adap.dev, ACPI_COMPANION(vdev->dev.parent));
ret = i2c_add_adapter(&vi->adap);
if (ret)
virtio_i2c_del_vqs(vdev);
return ret;
}
static void virtio_i2c_remove(struct virtio_device *vdev)
{
struct virtio_i2c *vi = vdev->priv;
i2c_del_adapter(&vi->adap);
virtio_i2c_del_vqs(vdev);
}
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_I2C_ADAPTER, VIRTIO_DEV_ANY_ID },
{}
};
MODULE_DEVICE_TABLE(virtio, id_table);
#ifdef CONFIG_PM_SLEEP
static int virtio_i2c_freeze(struct virtio_device *vdev)
{
virtio_i2c_del_vqs(vdev);
return 0;
}
static int virtio_i2c_restore(struct virtio_device *vdev)
{
return virtio_i2c_setup_vqs(vdev->priv);
}
#endif
static struct virtio_driver virtio_i2c_driver = {
.id_table = id_table,
.probe = virtio_i2c_probe,
.remove = virtio_i2c_remove,
.driver = {
.name = "i2c_virtio",
},
#ifdef CONFIG_PM_SLEEP
.freeze = virtio_i2c_freeze,
.restore = virtio_i2c_restore,
#endif
};
module_virtio_driver(virtio_i2c_driver);
MODULE_AUTHOR("Jie Deng <jie.deng@intel.com>");
MODULE_AUTHOR("Conghui Chen <conghui.chen@intel.com>");
MODULE_DESCRIPTION("Virtio i2c bus driver");
MODULE_LICENSE("GPL");
...@@ -517,7 +517,7 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev) ...@@ -517,7 +517,7 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
return PTR_ERR(priv->base); return PTR_ERR(priv->base);
priv->irq = platform_get_irq(pdev, 0); priv->irq = platform_get_irq(pdev, 0);
if (priv->irq <= 0) if (priv->irq < 0)
return priv->irq; return priv->irq;
/* SMBAlert irq */ /* SMBAlert irq */
priv->alert_data.irq = platform_get_irq(pdev, 1); priv->alert_data.irq = platform_get_irq(pdev, 1);
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */ /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -68,8 +70,7 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap) ...@@ -68,8 +70,7 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
struct i2c_dev *i2c_dev; struct i2c_dev *i2c_dev;
if (adap->nr >= I2C_MINORS) { if (adap->nr >= I2C_MINORS) {
printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n", pr_err("Out of device minors (%d)\n", adap->nr);
adap->nr);
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
...@@ -101,7 +102,7 @@ static ssize_t name_show(struct device *dev, ...@@ -101,7 +102,7 @@ static ssize_t name_show(struct device *dev,
if (!i2c_dev) if (!i2c_dev)
return -ENODEV; return -ENODEV;
return sprintf(buf, "%s\n", i2c_dev->adap->name); return sysfs_emit(buf, "%s\n", i2c_dev->adap->name);
} }
static DEVICE_ATTR_RO(name); static DEVICE_ATTR_RO(name);
...@@ -145,8 +146,7 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count, ...@@ -145,8 +146,7 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
if (tmp == NULL) if (tmp == NULL)
return -ENOMEM; return -ENOMEM;
pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n", pr_debug("i2c-%d reading %zu bytes.\n", iminor(file_inode(file)), count);
iminor(file_inode(file)), count);
ret = i2c_master_recv(client, tmp, count); ret = i2c_master_recv(client, tmp, count);
if (ret >= 0) if (ret >= 0)
...@@ -170,8 +170,7 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf, ...@@ -170,8 +170,7 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf,
if (IS_ERR(tmp)) if (IS_ERR(tmp))
return PTR_ERR(tmp); return PTR_ERR(tmp);
pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", pr_debug("i2c-%d writing %zu bytes.\n", iminor(file_inode(file)), count);
iminor(file_inode(file)), count);
ret = i2c_master_send(client, tmp, count); ret = i2c_master_send(client, tmp, count);
kfree(tmp); kfree(tmp);
...@@ -674,8 +673,7 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy) ...@@ -674,8 +673,7 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
return res; return res;
} }
pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", pr_debug("adapter [%s] registered as minor %d\n", adap->name, adap->nr);
adap->name, adap->nr);
return 0; return 0;
} }
...@@ -694,7 +692,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy) ...@@ -694,7 +692,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
put_i2c_dev(i2c_dev, true); put_i2c_dev(i2c_dev, true);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); pr_debug("adapter [%s] unregistered\n", adap->name);
return 0; return 0;
} }
...@@ -727,7 +725,7 @@ static int __init i2c_dev_init(void) ...@@ -727,7 +725,7 @@ static int __init i2c_dev_init(void)
{ {
int res; int res;
printk(KERN_INFO "i2c /dev entries driver\n"); pr_info("i2c /dev entries driver\n");
res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c"); res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c");
if (res) if (res)
...@@ -755,7 +753,7 @@ static int __init i2c_dev_init(void) ...@@ -755,7 +753,7 @@ static int __init i2c_dev_init(void)
out_unreg_chrdev: out_unreg_chrdev:
unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS); unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
out: out:
printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); pr_err("Driver Initialisation failed\n");
return res; return res;
} }
......
...@@ -4,6 +4,22 @@ ...@@ -4,6 +4,22 @@
#include <linux/math.h> #include <linux/math.h>
/* Metric prefixes in accordance with Système international (d'unités) */
#define PETA 1000000000000000ULL
#define TERA 1000000000000ULL
#define GIGA 1000000000UL
#define MEGA 1000000UL
#define KILO 1000UL
#define HECTO 100UL
#define DECA 10UL
#define DECI 10UL
#define CENTI 100UL
#define MILLI 1000UL
#define MICRO 1000000UL
#define NANO 1000000000UL
#define PICO 1000000000000ULL
#define FEMTO 1000000000000000ULL
#define MILLIWATT_PER_WATT 1000L #define MILLIWATT_PER_WATT 1000L
#define MICROWATT_PER_MILLIWATT 1000L #define MICROWATT_PER_MILLIWATT 1000L
#define MICROWATT_PER_WATT 1000000L #define MICROWATT_PER_WATT 1000000L
......
/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
/*
* Definitions for virtio I2C Adpter
*
* Copyright (c) 2021 Intel Corporation. All rights reserved.
*/
#ifndef _UAPI_LINUX_VIRTIO_I2C_H
#define _UAPI_LINUX_VIRTIO_I2C_H
#include <linux/const.h>
#include <linux/types.h>
/* The bit 0 of the @virtio_i2c_out_hdr.@flags, used to group the requests */
#define VIRTIO_I2C_FLAGS_FAIL_NEXT _BITUL(0)
/**
* struct virtio_i2c_out_hdr - the virtio I2C message OUT header
* @addr: the controlled device address
* @padding: used to pad to full dword
* @flags: used for feature extensibility
*/
struct virtio_i2c_out_hdr {
__le16 addr;
__le16 padding;
__le32 flags;
};
/**
* struct virtio_i2c_in_hdr - the virtio I2C message IN header
* @status: the processing result from the backend
*/
struct virtio_i2c_in_hdr {
__u8 status;
};
/* The final status written by the device */
#define VIRTIO_I2C_MSG_OK 0
#define VIRTIO_I2C_MSG_ERR 1
#endif /* _UAPI_LINUX_VIRTIO_I2C_H */
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#define VIRTIO_ID_FS 26 /* virtio filesystem */ #define VIRTIO_ID_FS 26 /* virtio filesystem */
#define VIRTIO_ID_PMEM 27 /* virtio pmem */ #define VIRTIO_ID_PMEM 27 /* virtio pmem */
#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */
#define VIRTIO_ID_BT 40 /* virtio bluetooth */ #define VIRTIO_ID_BT 40 /* virtio bluetooth */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment