浏览代码

Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

Pull i2c subsystem fixes from Jean Delvare.

* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  i2c-core: Fix for lockdep validator
  i2c-designware: Fix build error if CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y
  i2c-i801: Add Device IDs for Intel Lynx Point-LP PCH
Linus Torvalds 13 年之前
父节点
当前提交
6562271ae4

+ 1 - 0
Documentation/i2c/busses/i2c-i801

@@ -21,6 +21,7 @@ Supported adapters:
   * Intel DH89xxCC (PCH)
   * Intel DH89xxCC (PCH)
   * Intel Panther Point (PCH)
   * Intel Panther Point (PCH)
   * Intel Lynx Point (PCH)
   * Intel Lynx Point (PCH)
+  * Intel Lynx Point-LP (PCH)
    Datasheets: Publicly available at the Intel website
    Datasheets: Publicly available at the Intel website
 
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
 On Intel Patsburg and later chipsets, both the normal host SMBus controller

+ 6 - 0
drivers/i2c/busses/Kconfig

@@ -104,6 +104,7 @@ config I2C_I801
 	    DH89xxCC (PCH)
 	    DH89xxCC (PCH)
 	    Panther Point (PCH)
 	    Panther Point (PCH)
 	    Lynx Point (PCH)
 	    Lynx Point (PCH)
+	    Lynx Point-LP (PCH)
 
 
 	  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-i801.
 	  will be called i2c-i801.
@@ -354,9 +355,13 @@ config I2C_DAVINCI
 	  devices such as DaVinci NIC.
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 	  For details please see http://www.ti.com/davinci
 
 
+config I2C_DESIGNWARE_CORE
+	tristate
+
 config I2C_DESIGNWARE_PLATFORM
 config I2C_DESIGNWARE_PLATFORM
 	tristate "Synopsys DesignWare Platform"
 	tristate "Synopsys DesignWare Platform"
 	depends on HAVE_CLK
 	depends on HAVE_CLK
+	select I2C_DESIGNWARE_CORE
 	help
 	help
 	  If you say yes to this option, support will be included for the
 	  If you say yes to this option, support will be included for the
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.
@@ -367,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM
 config I2C_DESIGNWARE_PCI
 config I2C_DESIGNWARE_PCI
 	tristate "Synopsys DesignWare PCI"
 	tristate "Synopsys DesignWare PCI"
 	depends on PCI
 	depends on PCI
+	select I2C_DESIGNWARE_CORE
 	help
 	help
 	  If you say yes to this option, support will be included for the
 	  If you say yes to this option, support will be included for the
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.

+ 3 - 2
drivers/i2c/busses/Makefile

@@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
+obj-$(CONFIG_I2C_DESIGNWARE_CORE)	+= i2c-designware-core.o
 obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o
 obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o
-i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o
 obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o
 obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o
-i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o
 obj-$(CONFIG_I2C_EG20T)		+= i2c-eg20t.o
 obj-$(CONFIG_I2C_EG20T)		+= i2c-eg20t.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o

+ 11 - 0
drivers/i2c/busses/i2c-designware-core.c

@@ -25,6 +25,7 @@
  * ----------------------------------------------------------------------------
  * ----------------------------------------------------------------------------
  *
  *
  */
  */
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/err.h>
@@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
 	dw_writel(dev, dev->master_cfg , DW_IC_CON);
 	dw_writel(dev, dev->master_cfg , DW_IC_CON);
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_init);
 
 
 /*
 /*
  * Waiting for bus not busy
  * Waiting for bus not busy
@@ -568,12 +570,14 @@ done:
 
 
 	return ret;
 	return ret;
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_xfer);
 
 
 u32 i2c_dw_func(struct i2c_adapter *adap)
 u32 i2c_dw_func(struct i2c_adapter *adap)
 {
 {
 	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
 	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
 	return dev->functionality;
 	return dev->functionality;
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_func);
 
 
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 {
 {
@@ -678,17 +682,20 @@ tx_aborted:
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_isr);
 
 
 void i2c_dw_enable(struct dw_i2c_dev *dev)
 void i2c_dw_enable(struct dw_i2c_dev *dev)
 {
 {
        /* Enable the adapter */
        /* Enable the adapter */
 	dw_writel(dev, 1, DW_IC_ENABLE);
 	dw_writel(dev, 1, DW_IC_ENABLE);
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_enable);
 
 
 u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
 u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
 {
 {
 	return dw_readl(dev, DW_IC_ENABLE);
 	return dw_readl(dev, DW_IC_ENABLE);
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
 
 
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
 {
@@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
 	dw_writel(dev, 0, DW_IC_INTR_MASK);
 	dw_writel(dev, 0, DW_IC_INTR_MASK);
 	dw_readl(dev, DW_IC_CLR_INTR);
 	dw_readl(dev, DW_IC_CLR_INTR);
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_disable);
 
 
 void i2c_dw_clear_int(struct dw_i2c_dev *dev)
 void i2c_dw_clear_int(struct dw_i2c_dev *dev)
 {
 {
 	dw_readl(dev, DW_IC_CLR_INTR);
 	dw_readl(dev, DW_IC_CLR_INTR);
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_clear_int);
 
 
 void i2c_dw_disable_int(struct dw_i2c_dev *dev)
 void i2c_dw_disable_int(struct dw_i2c_dev *dev)
 {
 {
 	dw_writel(dev, 0, DW_IC_INTR_MASK);
 	dw_writel(dev, 0, DW_IC_INTR_MASK);
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_disable_int);
 
 
 u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
 u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
 {
 {
 	return dw_readl(dev, DW_IC_COMP_PARAM_1);
 	return dw_readl(dev, DW_IC_COMP_PARAM_1);
 }
 }
+EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);

+ 3 - 0
drivers/i2c/busses/i2c-i801.c

@@ -52,6 +52,7 @@
   DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
   DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
   Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
   Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
   Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
   Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
+  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes
 
 
   Features supported by this driver:
   Features supported by this driver:
   Software PEC                     no
   Software PEC                     no
@@ -155,6 +156,7 @@
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS	0x8c22
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS	0x8c22
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS	0x9c22
 
 
 struct i801_priv {
 struct i801_priv {
 	struct i2c_adapter adapter;
 	struct i2c_adapter adapter;
@@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },
 	{ 0, }
 	{ 0, }
 };
 };
 
 

+ 20 - 2
drivers/i2c/i2c-core.c

@@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev)
 	complete(&adap->dev_released);
 	complete(&adap->dev_released);
 }
 }
 
 
+/*
+ * This function is only needed for mutex_lock_nested, so it is never
+ * called unless locking correctness checking is enabled. Thus we
+ * make it inline to avoid a compiler warning. That's what gcc ends up
+ * doing anyway.
+ */
+static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
+{
+	unsigned int depth = 0;
+
+	while ((adapter = i2c_parent_is_i2c_adapter(adapter)))
+		depth++;
+
+	return depth;
+}
+
 /*
 /*
  * Let users instantiate I2C devices through sysfs. This can be used when
  * Let users instantiate I2C devices through sysfs. This can be used when
  * platform initialization code doesn't contain the proper data for
  * platform initialization code doesn't contain the proper data for
@@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
 
 
 	/* Make sure the device was added through sysfs */
 	/* Make sure the device was added through sysfs */
 	res = -ENOENT;
 	res = -ENOENT;
-	mutex_lock(&adap->userspace_clients_lock);
+	mutex_lock_nested(&adap->userspace_clients_lock,
+			  i2c_adapter_depth(adap));
 	list_for_each_entry_safe(client, next, &adap->userspace_clients,
 	list_for_each_entry_safe(client, next, &adap->userspace_clients,
 				 detected) {
 				 detected) {
 		if (client->addr == addr) {
 		if (client->addr == addr) {
@@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 		return res;
 		return res;
 
 
 	/* Remove devices instantiated from sysfs */
 	/* Remove devices instantiated from sysfs */
-	mutex_lock(&adap->userspace_clients_lock);
+	mutex_lock_nested(&adap->userspace_clients_lock,
+			  i2c_adapter_depth(adap));
 	list_for_each_entry_safe(client, next, &adap->userspace_clients,
 	list_for_each_entry_safe(client, next, &adap->userspace_clients,
 				 detected) {
 				 detected) {
 		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,
 		dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,