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:
commit
5d1f7023fb
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue