Commit d3dca690 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c fixes from Wolfram Sang:
 "I2C has quite some regression fixes this time.

  One is also related to watchdogs, we have proper acks from Guenter for
  them"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: acpi: put device when verifying client fails
  misc: eeprom: at24: fix regulator underflow
  i2c: gpio: suppress error on probe defer
  macintosh: windfarm: fix MODINFO regression
  i2c: designware-pci: Fix BUG_ON during device removal
  i2c: i801: Do not add ICH_RES_IO_SMI for the iTCO_wdt device
  watchdog: iTCO_wdt: Make ICH_RES_IO_SMI optional
  watchdog: iTCO_wdt: Export vendorsupport
parents 3086ae07 92bd1f2e
...@@ -313,6 +313,7 @@ static void i2c_dw_pci_remove(struct pci_dev *pdev) ...@@ -313,6 +313,7 @@ static void i2c_dw_pci_remove(struct pci_dev *pdev)
pm_runtime_get_noresume(&pdev->dev); pm_runtime_get_noresume(&pdev->dev);
i2c_del_adapter(&dev->adapter); i2c_del_adapter(&dev->adapter);
devm_free_irq(&pdev->dev, dev->irq, dev);
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
} }
......
...@@ -348,7 +348,7 @@ static struct gpio_desc *i2c_gpio_get_desc(struct device *dev, ...@@ -348,7 +348,7 @@ static struct gpio_desc *i2c_gpio_get_desc(struct device *dev,
if (ret == -ENOENT) if (ret == -ENOENT)
retdesc = ERR_PTR(-EPROBE_DEFER); retdesc = ERR_PTR(-EPROBE_DEFER);
if (ret != -EPROBE_DEFER) if (PTR_ERR(retdesc) != -EPROBE_DEFER)
dev_err(dev, "error trying to get descriptor: %d\n", ret); dev_err(dev, "error trying to get descriptor: %d\n", ret);
return retdesc; return retdesc;
......
...@@ -132,11 +132,6 @@ ...@@ -132,11 +132,6 @@
#define TCOBASE 0x050 #define TCOBASE 0x050
#define TCOCTL 0x054 #define TCOCTL 0x054
#define ACPIBASE 0x040
#define ACPIBASE_SMI_OFF 0x030
#define ACPICTRL 0x044
#define ACPICTRL_EN 0x080
#define SBREG_BAR 0x10 #define SBREG_BAR 0x10
#define SBREG_SMBCTRL 0xc6000c #define SBREG_SMBCTRL 0xc6000c
#define SBREG_SMBCTRL_DNV 0xcf000c #define SBREG_SMBCTRL_DNV 0xcf000c
...@@ -1553,7 +1548,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, ...@@ -1553,7 +1548,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
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); spin_unlock(&p2sb_spinlock);
res = &tco_res[ICH_RES_MEM_OFF]; res = &tco_res[1];
if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV; res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV;
else else
...@@ -1563,7 +1558,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, ...@@ -1563,7 +1558,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,
tco_res, 3, &spt_tco_platform_data, tco_res, 2, &spt_tco_platform_data,
sizeof(spt_tco_platform_data)); sizeof(spt_tco_platform_data));
} }
...@@ -1576,17 +1571,16 @@ static struct platform_device * ...@@ -1576,17 +1571,16 @@ static struct platform_device *
i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev, i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev,
struct resource *tco_res) struct resource *tco_res)
{ {
return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, return platform_device_register_resndata(&pci_dev->dev,
tco_res, 2, &cnl_tco_platform_data, "iTCO_wdt", -1, tco_res, 1, &cnl_tco_platform_data,
sizeof(cnl_tco_platform_data)); sizeof(cnl_tco_platform_data));
} }
static void i801_add_tco(struct i801_priv *priv) static void i801_add_tco(struct i801_priv *priv)
{ {
u32 base_addr, tco_base, tco_ctl, ctrl_val;
struct pci_dev *pci_dev = priv->pci_dev; struct pci_dev *pci_dev = priv->pci_dev;
struct resource tco_res[3], *res; struct resource tco_res[2], *res;
unsigned int devfn; u32 tco_base, tco_ctl;
/* If we have ACPI based watchdog use that instead */ /* If we have ACPI based watchdog use that instead */
if (acpi_has_watchdog()) if (acpi_has_watchdog())
...@@ -1601,30 +1595,15 @@ static void i801_add_tco(struct i801_priv *priv) ...@@ -1601,30 +1595,15 @@ static void i801_add_tco(struct i801_priv *priv)
return; return;
memset(tco_res, 0, sizeof(tco_res)); memset(tco_res, 0, sizeof(tco_res));
res = &tco_res[ICH_RES_IO_TCO];
res->start = tco_base & ~1;
res->end = res->start + 32 - 1;
res->flags = IORESOURCE_IO;
/* /*
* Power Management registers. * Always populate the main iTCO IO resource here. The second entry
* for NO_REBOOT MMIO is filled by the SPT specific function.
*/ */
devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 2); res = &tco_res[0];
pci_bus_read_config_dword(pci_dev->bus, devfn, ACPIBASE, &base_addr); res->start = tco_base & ~1;
res->end = res->start + 32 - 1;
res = &tco_res[ICH_RES_IO_SMI];
res->start = (base_addr & ~1) + ACPIBASE_SMI_OFF;
res->end = res->start + 3;
res->flags = IORESOURCE_IO; res->flags = IORESOURCE_IO;
/*
* Enable the ACPI I/O space.
*/
pci_bus_read_config_dword(pci_dev->bus, devfn, ACPICTRL, &ctrl_val);
ctrl_val |= ACPICTRL_EN;
pci_bus_write_config_dword(pci_dev->bus, devfn, ACPICTRL, ctrl_val);
if (priv->features & FEATURE_TCO_CNL) if (priv->features & FEATURE_TCO_CNL)
priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res); priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res);
else else
......
...@@ -394,9 +394,17 @@ EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle); ...@@ -394,9 +394,17 @@ EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle);
static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev) static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
{ {
struct device *dev; struct device *dev;
struct i2c_client *client;
dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
return dev ? i2c_verify_client(dev) : NULL; if (!dev)
return NULL;
client = i2c_verify_client(dev);
if (!client)
put_device(dev);
return client;
} }
static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
......
...@@ -312,9 +312,16 @@ static const struct i2c_device_id wf_ad7417_id[] = { ...@@ -312,9 +312,16 @@ static const struct i2c_device_id wf_ad7417_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wf_ad7417_id); MODULE_DEVICE_TABLE(i2c, wf_ad7417_id);
static const struct of_device_id wf_ad7417_of_id[] = {
{ .compatible = "ad7417", },
{ }
};
MODULE_DEVICE_TABLE(of, wf_ad7417_of_id);
static struct i2c_driver wf_ad7417_driver = { static struct i2c_driver wf_ad7417_driver = {
.driver = { .driver = {
.name = "wf_ad7417", .name = "wf_ad7417",
.of_match_table = wf_ad7417_of_id,
}, },
.probe = wf_ad7417_probe, .probe = wf_ad7417_probe,
.remove = wf_ad7417_remove, .remove = wf_ad7417_remove,
......
...@@ -580,9 +580,16 @@ static const struct i2c_device_id wf_fcu_id[] = { ...@@ -580,9 +580,16 @@ static const struct i2c_device_id wf_fcu_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wf_fcu_id); MODULE_DEVICE_TABLE(i2c, wf_fcu_id);
static const struct of_device_id wf_fcu_of_id[] = {
{ .compatible = "fcu", },
{ }
};
MODULE_DEVICE_TABLE(of, wf_fcu_of_id);
static struct i2c_driver wf_fcu_driver = { static struct i2c_driver wf_fcu_driver = {
.driver = { .driver = {
.name = "wf_fcu", .name = "wf_fcu",
.of_match_table = wf_fcu_of_id,
}, },
.probe = wf_fcu_probe, .probe = wf_fcu_probe,
.remove = wf_fcu_remove, .remove = wf_fcu_remove,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of_device.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -91,9 +92,14 @@ static int wf_lm75_probe(struct i2c_client *client, ...@@ -91,9 +92,14 @@ static int wf_lm75_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct wf_lm75_sensor *lm; struct wf_lm75_sensor *lm;
int rc, ds1775 = id->driver_data; int rc, ds1775;
const char *name, *loc; const char *name, *loc;
if (id)
ds1775 = id->driver_data;
else
ds1775 = !!of_device_get_match_data(&client->dev);
DBG("wf_lm75: creating %s device at address 0x%02x\n", DBG("wf_lm75: creating %s device at address 0x%02x\n",
ds1775 ? "ds1775" : "lm75", client->addr); ds1775 ? "ds1775" : "lm75", client->addr);
...@@ -164,9 +170,17 @@ static const struct i2c_device_id wf_lm75_id[] = { ...@@ -164,9 +170,17 @@ static const struct i2c_device_id wf_lm75_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wf_lm75_id); MODULE_DEVICE_TABLE(i2c, wf_lm75_id);
static const struct of_device_id wf_lm75_of_id[] = {
{ .compatible = "lm75", .data = (void *)0},
{ .compatible = "ds1775", .data = (void *)1 },
{ }
};
MODULE_DEVICE_TABLE(of, wf_lm75_of_id);
static struct i2c_driver wf_lm75_driver = { static struct i2c_driver wf_lm75_driver = {
.driver = { .driver = {
.name = "wf_lm75", .name = "wf_lm75",
.of_match_table = wf_lm75_of_id,
}, },
.probe = wf_lm75_probe, .probe = wf_lm75_probe,
.remove = wf_lm75_remove, .remove = wf_lm75_remove,
......
...@@ -166,9 +166,16 @@ static const struct i2c_device_id wf_lm87_id[] = { ...@@ -166,9 +166,16 @@ static const struct i2c_device_id wf_lm87_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wf_lm87_id); MODULE_DEVICE_TABLE(i2c, wf_lm87_id);
static const struct of_device_id wf_lm87_of_id[] = {
{ .compatible = "lm87cimt", },
{ }
};
MODULE_DEVICE_TABLE(of, wf_lm87_of_id);
static struct i2c_driver wf_lm87_driver = { static struct i2c_driver wf_lm87_driver = {
.driver = { .driver = {
.name = "wf_lm87", .name = "wf_lm87",
.of_match_table = wf_lm87_of_id,
}, },
.probe = wf_lm87_probe, .probe = wf_lm87_probe,
.remove = wf_lm87_remove, .remove = wf_lm87_remove,
......
...@@ -120,9 +120,16 @@ static const struct i2c_device_id wf_max6690_id[] = { ...@@ -120,9 +120,16 @@ static const struct i2c_device_id wf_max6690_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wf_max6690_id); MODULE_DEVICE_TABLE(i2c, wf_max6690_id);
static const struct of_device_id wf_max6690_of_id[] = {
{ .compatible = "max6690", },
{ }
};
MODULE_DEVICE_TABLE(of, wf_max6690_of_id);
static struct i2c_driver wf_max6690_driver = { static struct i2c_driver wf_max6690_driver = {
.driver = { .driver = {
.name = "wf_max6690", .name = "wf_max6690",
.of_match_table = wf_max6690_of_id,
}, },
.probe = wf_max6690_probe, .probe = wf_max6690_probe,
.remove = wf_max6690_remove, .remove = wf_max6690_remove,
......
...@@ -341,9 +341,16 @@ static const struct i2c_device_id wf_sat_id[] = { ...@@ -341,9 +341,16 @@ static const struct i2c_device_id wf_sat_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wf_sat_id); MODULE_DEVICE_TABLE(i2c, wf_sat_id);
static const struct of_device_id wf_sat_of_id[] = {
{ .compatible = "smu-sat", },
{ }
};
MODULE_DEVICE_TABLE(of, wf_sat_of_id);
static struct i2c_driver wf_sat_driver = { static struct i2c_driver wf_sat_driver = {
.driver = { .driver = {
.name = "wf_smu_sat", .name = "wf_smu_sat",
.of_match_table = wf_sat_of_id,
}, },
.probe = wf_sat_probe, .probe = wf_sat_probe,
.remove = wf_sat_remove, .remove = wf_sat_remove,
......
...@@ -712,13 +712,14 @@ static int at24_probe(struct i2c_client *client) ...@@ -712,13 +712,14 @@ static int at24_probe(struct i2c_client *client)
* chip is functional. * chip is functional.
*/ */
err = at24_read(at24, 0, &test_byte, 1); err = at24_read(at24, 0, &test_byte, 1);
pm_runtime_idle(dev);
if (err) { if (err) {
pm_runtime_disable(dev); pm_runtime_disable(dev);
regulator_disable(at24->vcc_reg); regulator_disable(at24->vcc_reg);
return -ENODEV; return -ENODEV;
} }
pm_runtime_idle(dev);
if (writable) if (writable)
dev_info(dev, "%u byte %s EEPROM, writable, %u bytes/write\n", dev_info(dev, "%u byte %s EEPROM, writable, %u bytes/write\n",
byte_len, client->name, at24->write_max); byte_len, client->name, at24->write_max);
......
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/* iTCO Vendor Specific Support hooks */ /* iTCO Vendor Specific Support hooks */
#ifdef CONFIG_ITCO_VENDOR_SUPPORT #ifdef CONFIG_ITCO_VENDOR_SUPPORT
extern int iTCO_vendorsupport;
extern void iTCO_vendor_pre_start(struct resource *, unsigned int); extern void iTCO_vendor_pre_start(struct resource *, unsigned int);
extern void iTCO_vendor_pre_stop(struct resource *); extern void iTCO_vendor_pre_stop(struct resource *);
extern int iTCO_vendor_check_noreboot_on(void); extern int iTCO_vendor_check_noreboot_on(void);
#else #else
#define iTCO_vendorsupport 0
#define iTCO_vendor_pre_start(acpibase, heartbeat) {} #define iTCO_vendor_pre_start(acpibase, heartbeat) {}
#define iTCO_vendor_pre_stop(acpibase) {} #define iTCO_vendor_pre_stop(acpibase) {}
#define iTCO_vendor_check_noreboot_on() 1 #define iTCO_vendor_check_noreboot_on() 1
......
...@@ -39,8 +39,10 @@ ...@@ -39,8 +39,10 @@
/* Broken BIOS */ /* Broken BIOS */
#define BROKEN_BIOS 911 #define BROKEN_BIOS 911
static int vendorsupport; int iTCO_vendorsupport;
module_param(vendorsupport, int, 0); EXPORT_SYMBOL(iTCO_vendorsupport);
module_param_named(vendorsupport, iTCO_vendorsupport, int, 0);
MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=" MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default="
"0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS"); "0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS");
...@@ -152,7 +154,7 @@ static void broken_bios_stop(struct resource *smires) ...@@ -152,7 +154,7 @@ static void broken_bios_stop(struct resource *smires)
void iTCO_vendor_pre_start(struct resource *smires, void iTCO_vendor_pre_start(struct resource *smires,
unsigned int heartbeat) unsigned int heartbeat)
{ {
switch (vendorsupport) { switch (iTCO_vendorsupport) {
case SUPERMICRO_OLD_BOARD: case SUPERMICRO_OLD_BOARD:
supermicro_old_pre_start(smires); supermicro_old_pre_start(smires);
break; break;
...@@ -165,7 +167,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_start); ...@@ -165,7 +167,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_start);
void iTCO_vendor_pre_stop(struct resource *smires) void iTCO_vendor_pre_stop(struct resource *smires)
{ {
switch (vendorsupport) { switch (iTCO_vendorsupport) {
case SUPERMICRO_OLD_BOARD: case SUPERMICRO_OLD_BOARD:
supermicro_old_pre_stop(smires); supermicro_old_pre_stop(smires);
break; break;
...@@ -178,7 +180,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_stop); ...@@ -178,7 +180,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_stop);
int iTCO_vendor_check_noreboot_on(void) int iTCO_vendor_check_noreboot_on(void)
{ {
switch (vendorsupport) { switch (iTCO_vendorsupport) {
case SUPERMICRO_OLD_BOARD: case SUPERMICRO_OLD_BOARD:
return 0; return 0;
default: default:
...@@ -189,13 +191,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on); ...@@ -189,13 +191,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
static int __init iTCO_vendor_init_module(void) static int __init iTCO_vendor_init_module(void)
{ {
if (vendorsupport == SUPERMICRO_NEW_BOARD) { if (iTCO_vendorsupport == SUPERMICRO_NEW_BOARD) {
pr_warn("Option vendorsupport=%d is no longer supported, " pr_warn("Option vendorsupport=%d is no longer supported, "
"please use the w83627hf_wdt driver instead\n", "please use the w83627hf_wdt driver instead\n",
SUPERMICRO_NEW_BOARD); SUPERMICRO_NEW_BOARD);
return -EINVAL; return -EINVAL;
} }
pr_info("vendor-support=%d\n", vendorsupport); pr_info("vendor-support=%d\n", iTCO_vendorsupport);
return 0; return 0;
} }
......
...@@ -459,13 +459,25 @@ static int iTCO_wdt_probe(struct platform_device *pdev) ...@@ -459,13 +459,25 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
if (!p->tco_res) if (!p->tco_res)
return -ENODEV; return -ENODEV;
p->smi_res = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_IO_SMI);
if (!p->smi_res)
return -ENODEV;
p->iTCO_version = pdata->version; p->iTCO_version = pdata->version;
p->pci_dev = to_pci_dev(dev->parent); p->pci_dev = to_pci_dev(dev->parent);
p->smi_res = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_IO_SMI);
if (p->smi_res) {
/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
if (!devm_request_region(dev, p->smi_res->start,
resource_size(p->smi_res),
pdev->name)) {
pr_err("I/O address 0x%04llx already in use, device disabled\n",
(u64)SMI_EN(p));
return -EBUSY;
}
} else if (iTCO_vendorsupport ||
turn_SMI_watchdog_clear_off >= p->iTCO_version) {
pr_err("SMI I/O resource is missing\n");
return -ENODEV;
}
iTCO_wdt_no_reboot_bit_setup(p, pdata); iTCO_wdt_no_reboot_bit_setup(p, pdata);
/* /*
...@@ -492,14 +504,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev) ...@@ -492,14 +504,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */ /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
p->update_no_reboot_bit(p->no_reboot_priv, true); p->update_no_reboot_bit(p->no_reboot_priv, true);
/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
if (!devm_request_region(dev, p->smi_res->start,
resource_size(p->smi_res),
pdev->name)) {
pr_err("I/O address 0x%04llx already in use, device disabled\n",
(u64)SMI_EN(p));
return -EBUSY;
}
if (turn_SMI_watchdog_clear_off >= p->iTCO_version) { if (turn_SMI_watchdog_clear_off >= p->iTCO_version) {
/* /*
* Bit 13: TCO_EN -> 0 * Bit 13: TCO_EN -> 0
......
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