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

Pull i2c fixes from Wolfram Sang:

 - a bigger fix for i801 to finally be able to be loaded on some
   machines again

 - smaller driver fixes

 - documentation update because of a renamed file

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: mux: reg: Provide of_match_table
  i2c: mux: refer to i2c-mux.txt
  i2c: octeon: Avoid printk after too long SMBUS message
  i2c: octeon: Missing AAK flag in case of I2C_M_RECV_LEN
  i2c: i801: Allow ACPI SystemIO OpRegion to conflict with PCI BAR
This commit is contained in:
Linus Torvalds 2016-06-11 11:24:54 -07:00
commit 5d1f7023fb
8 changed files with 119 additions and 21 deletions

View File

@ -44,8 +44,8 @@ Required properties:
- our-claim-gpio: The GPIO that we use to claim the bus.
- their-claim-gpios: The GPIOs that the other sides use to claim the bus.
Note that some implementations may only support a single other master.
- Standard I2C mux properties. See mux.txt in this directory.
- Single I2C child bus node at reg 0. See mux.txt in this directory.
- Standard I2C mux properties. See i2c-mux.txt in this directory.
- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
Optional properties:
- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.

View File

@ -27,7 +27,8 @@ Required properties:
- i2c-bus-name: The name of this bus. Also needed as pinctrl-name for the I2C
parents.
Furthermore, I2C mux properties and child nodes. See mux.txt in this directory.
Furthermore, I2C mux properties and child nodes. See i2c-mux.txt in this
directory.
Example:

View File

@ -22,8 +22,8 @@ Required properties:
- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
port is connected to.
- mux-gpios: list of gpios used to control the muxer
* Standard I2C mux properties. See mux.txt in this directory.
* I2C child bus nodes. See mux.txt in this directory.
* Standard I2C mux properties. See i2c-mux.txt in this directory.
* I2C child bus nodes. See i2c-mux.txt in this directory.
Optional properties:
- idle-state: value to set the muxer to when idle. When no value is
@ -33,7 +33,7 @@ For each i2c child node, an I2C child bus will be created. They will
be numbered based on their order in the device tree.
Whenever an access is made to a device on a child bus, the value set
in the revelant node's reg property will be output using the list of
in the relevant node's reg property will be output using the list of
GPIOs, the first in the list holding the least-significant value.
If an idle state is defined, using the idle-state (optional) property,

View File

@ -28,9 +28,9 @@ Also required are:
* Standard pinctrl properties that specify the pin mux state for each child
bus. See ../pinctrl/pinctrl-bindings.txt.
* Standard I2C mux properties. See mux.txt in this directory.
* Standard I2C mux properties. See i2c-mux.txt in this directory.
* I2C child bus nodes. See mux.txt in this directory.
* I2C child bus nodes. See i2c-mux.txt in this directory.
For each named state defined in the pinctrl-names property, an I2C child bus
will be created. I2C child bus numbers are assigned based on the index into

View File

@ -7,8 +7,8 @@ Required properties:
- compatible: i2c-mux-reg
- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
port is connected to.
* Standard I2C mux properties. See mux.txt in this directory.
* I2C child bus nodes. See mux.txt in this directory.
* Standard I2C mux properties. See i2c-mux.txt in this directory.
* I2C child bus nodes. See i2c-mux.txt in this directory.
Optional properties:
- reg: this pair of <offset size> specifies the register to control the mux.
@ -24,7 +24,7 @@ Optional properties:
given, it defaults to the last value used.
Whenever an access is made to a device on a child bus, the value set
in the revelant node's reg property will be output to the register.
in the relevant node's reg property will be output to the register.
If an idle state is defined, using the idle-state (optional) property,
whenever an access is not being made to a device on a child bus, the

View File

@ -245,6 +245,13 @@ struct i801_priv {
struct platform_device *mux_pdev;
#endif
struct platform_device *tco_pdev;
/*
* If set to true the host controller registers are reserved for
* ACPI AML use. Protected by acpi_lock.
*/
bool acpi_reserved;
struct mutex acpi_lock;
};
#define FEATURE_SMBUS_PEC (1 << 0)
@ -718,6 +725,12 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
int ret = 0, xact = 0;
struct i801_priv *priv = i2c_get_adapdata(adap);
mutex_lock(&priv->acpi_lock);
if (priv->acpi_reserved) {
mutex_unlock(&priv->acpi_lock);
return -EBUSY;
}
pm_runtime_get_sync(&priv->pci_dev->dev);
hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
@ -820,6 +833,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
out:
pm_runtime_mark_last_busy(&priv->pci_dev->dev);
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
mutex_unlock(&priv->acpi_lock);
return ret;
}
@ -1257,6 +1271,83 @@ static void i801_add_tco(struct i801_priv *priv)
priv->tco_pdev = pdev;
}
#ifdef CONFIG_ACPI
static acpi_status
i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
u64 *value, void *handler_context, void *region_context)
{
struct i801_priv *priv = handler_context;
struct pci_dev *pdev = priv->pci_dev;
acpi_status status;
/*
* Once BIOS AML code touches the OpRegion we warn and inhibit any
* further access from the driver itself. This device is now owned
* by the system firmware.
*/
mutex_lock(&priv->acpi_lock);
if (!priv->acpi_reserved) {
priv->acpi_reserved = true;
dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n");
dev_warn(&pdev->dev, "Driver SMBus register access inhibited\n");
/*
* BIOS is accessing the host controller so prevent it from
* suspending automatically from now on.
*/
pm_runtime_get_sync(&pdev->dev);
}
if ((function & ACPI_IO_MASK) == ACPI_READ)
status = acpi_os_read_port(address, (u32 *)value, bits);
else
status = acpi_os_write_port(address, (u32)*value, bits);
mutex_unlock(&priv->acpi_lock);
return status;
}
static int i801_acpi_probe(struct i801_priv *priv)
{
struct acpi_device *adev;
acpi_status status;
adev = ACPI_COMPANION(&priv->pci_dev->dev);
if (adev) {
status = acpi_install_address_space_handler(adev->handle,
ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler,
NULL, priv);
if (ACPI_SUCCESS(status))
return 0;
}
return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]);
}
static void i801_acpi_remove(struct i801_priv *priv)
{
struct acpi_device *adev;
adev = ACPI_COMPANION(&priv->pci_dev->dev);
if (!adev)
return;
acpi_remove_address_space_handler(adev->handle,
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
static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
static inline void i801_acpi_remove(struct i801_priv *priv) { }
#endif
static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned char temp;
@ -1274,6 +1365,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
priv->adapter.dev.parent = &dev->dev;
ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
priv->adapter.retries = 3;
mutex_init(&priv->acpi_lock);
priv->pci_dev = dev;
switch (dev->device) {
@ -1336,10 +1428,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
}
err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
if (err) {
if (i801_acpi_probe(priv))
return -ENODEV;
}
err = pcim_iomap_regions(dev, 1 << SMBBAR,
dev_driver_string(&dev->dev));
@ -1348,6 +1438,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
"Failed to request SMBus region 0x%lx-0x%Lx\n",
priv->smba,
(unsigned long long)pci_resource_end(dev, SMBBAR));
i801_acpi_remove(priv);
return err;
}
@ -1412,6 +1503,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
err = i2c_add_adapter(&priv->adapter);
if (err) {
dev_err(&dev->dev, "Failed to add SMBus adapter\n");
i801_acpi_remove(priv);
return err;
}
@ -1438,6 +1530,7 @@ static void i801_remove(struct pci_dev *dev)
i801_del_mux(priv);
i2c_del_adapter(&priv->adapter);
i801_acpi_remove(priv);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
platform_device_unregister(priv->tco_pdev);

View File

@ -934,8 +934,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
return result;
for (i = 0; i < length; i++) {
/* for the last byte TWSI_CTL_AAK must not be set */
if (i + 1 == length)
/*
* For the last byte to receive TWSI_CTL_AAK must not be set.
*
* A special case is I2C_M_RECV_LEN where we don't know the
* additional length yet. If recv_len is set we assume we're
* not reading the final byte and therefore need to set
* TWSI_CTL_AAK.
*/
if ((i + 1 == length) && !(recv_len && i == 0))
final_read = true;
/* clear iflg to allow next event */
@ -950,12 +957,8 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
data[i] = octeon_i2c_data_read(i2c);
if (recv_len && i == 0) {
if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) {
dev_err(i2c->dev,
"%s: read len > I2C_SMBUS_BLOCK_MAX %d\n",
__func__, data[i]);
if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
return -EPROTO;
}
length += data[i];
}

View File

@ -260,6 +260,7 @@ static struct platform_driver i2c_mux_reg_driver = {
.remove = i2c_mux_reg_remove,
.driver = {
.name = "i2c-mux-reg",
.of_match_table = of_match_ptr(i2c_mux_reg_of_match),
},
};