summary refs log tree commit diff
path: root/drivers/w1
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 13:57:13 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 13:57:13 -0800
commit7ed214ac2095f561a94335ca672b6c42a1ea40ff (patch)
treeda41901bff1d0d8d61170bf362384fdc61deb3ab /drivers/w1
parent21eaab6d19ed43e82ed39c8deb7f192134fb4a0e (diff)
parent29e5507ae4ab34397f538f06b7070c81a4e4a2bf (diff)
downloadlinux-7ed214ac2095f561a94335ca672b6c42a1ea40ff.tar.gz
Merge tag 'char-misc-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver patches from Greg Kroah-Hartman:
 "Here's the big char/misc driver patches for 3.9-rc1.

  Nothing major here, just lots of different driver updates (mei,
  hyperv, ipack, extcon, vmci, etc.).

  All of these have been in the linux-next tree for a while."

* tag 'char-misc-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (209 commits)
  w1: w1_therm: Add force-pullup option for "broken" sensors
  w1: ds2482: Added 1-Wire pull-up support to the driver
  vme: add missing put_device() after device_register() fails
  extcon: max8997: Use workqueue to check cable state after completing boot of platform
  extcon: max8997: Set default UART/USB path on probe
  extcon: max8997: Consolidate duplicate code for checking ADC/CHG cable type
  extcon: max8997: Set default of ADC debounce time during initialization
  extcon: max8997: Remove duplicate code related to set H/W line path
  extcon: max8997: Move defined constant to header file
  extcon: max77693: Make max77693_extcon_cable static
  extcon: max8997: Remove unreachable code
  extcon: max8997: Make max8997_extcon_cable static
  extcon: max77693: Remove unnecessary goto statement to improve readability
  extcon: max77693: Convert to devm_input_allocate_device()
  extcon: gpio: Rename filename of extcon-gpio.c according to kernel naming style
  CREDITS: update email and address of Harald Hoyer
  extcon: arizona: Use MICDET for final microphone identification
  extcon: arizona: Always take the first HPDET reading as the final one
  extcon: arizona: Clear _trig_sts bits after jack detection
  extcon: arizona: Don't HPDET magic when headphones are enabled
  ...
Diffstat (limited to 'drivers/w1')
-rw-r--r--drivers/w1/masters/ds1wm.c52
-rw-r--r--drivers/w1/masters/ds2482.c51
-rw-r--r--drivers/w1/masters/mxc_w1.c49
-rw-r--r--drivers/w1/masters/w1-gpio.c2
-rw-r--r--drivers/w1/slaves/w1_therm.c36
5 files changed, 90 insertions, 100 deletions
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 7c294f4dc0ed..96cab6ac2b4e 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -13,6 +13,7 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
@@ -459,43 +460,34 @@ static int ds1wm_probe(struct platform_device *pdev)
 	if (!pdev)
 		return -ENODEV;
 
-	ds1wm_data = kzalloc(sizeof(*ds1wm_data), GFP_KERNEL);
+	ds1wm_data = devm_kzalloc(&pdev->dev, sizeof(*ds1wm_data), GFP_KERNEL);
 	if (!ds1wm_data)
 		return -ENOMEM;
 
 	platform_set_drvdata(pdev, ds1wm_data);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENXIO;
-		goto err0;
-	}
-	ds1wm_data->map = ioremap(res->start, resource_size(res));
-	if (!ds1wm_data->map) {
-		ret = -ENOMEM;
-		goto err0;
-	}
+	if (!res)
+		return -ENXIO;
+	ds1wm_data->map = devm_ioremap(&pdev->dev, res->start,
+				       resource_size(res));
+	if (!ds1wm_data->map)
+		return -ENOMEM;
 
 	/* calculate bus shift from mem resource */
 	ds1wm_data->bus_shift = resource_size(res) >> 3;
 
 	ds1wm_data->pdev = pdev;
 	ds1wm_data->cell = mfd_get_cell(pdev);
-	if (!ds1wm_data->cell) {
-		ret = -ENODEV;
-		goto err1;
-	}
+	if (!ds1wm_data->cell)
+		return -ENODEV;
 	plat = pdev->dev.platform_data;
-	if (!plat) {
-		ret = -ENODEV;
-		goto err1;
-	}
+	if (!plat)
+		return -ENODEV;
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		ret = -ENXIO;
-		goto err1;
-	}
+	if (!res)
+		return -ENXIO;
 	ds1wm_data->irq = res->start;
 	ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0);
 	ds1wm_data->reset_recover_delay = plat->reset_recover_delay;
@@ -505,10 +497,10 @@ static int ds1wm_probe(struct platform_device *pdev)
 	if (res->flags & IORESOURCE_IRQ_LOWEDGE)
 		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
 
-	ret = request_irq(ds1wm_data->irq, ds1wm_isr,
+	ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr,
 			IRQF_DISABLED | IRQF_SHARED, "ds1wm", ds1wm_data);
 	if (ret)
-		goto err1;
+		return ret;
 
 	ds1wm_up(ds1wm_data);
 
@@ -516,17 +508,12 @@ static int ds1wm_probe(struct platform_device *pdev)
 
 	ret = w1_add_master_device(&ds1wm_master);
 	if (ret)
-		goto err2;
+		goto err;
 
 	return 0;
 
-err2:
+err:
 	ds1wm_down(ds1wm_data);
-	free_irq(ds1wm_data->irq, ds1wm_data);
-err1:
-	iounmap(ds1wm_data->map);
-err0:
-	kfree(ds1wm_data);
 
 	return ret;
 }
@@ -560,9 +547,6 @@ static int ds1wm_remove(struct platform_device *pdev)
 
 	w1_remove_master_device(&ds1wm_master);
 	ds1wm_down(ds1wm_data);
-	free_irq(ds1wm_data->irq, ds1wm_data);
-	iounmap(ds1wm_data->map);
-	kfree(ds1wm_data);
 
 	return 0;
 }
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index 6429b9e9fb82..e033491fe308 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -51,10 +51,10 @@
  * The top 4 bits always read 0.
  * To write, the top nibble must be the 1's compl. of the low nibble.
  */
-#define DS2482_REG_CFG_1WS		0x08
-#define DS2482_REG_CFG_SPU		0x04
-#define DS2482_REG_CFG_PPM		0x02
-#define DS2482_REG_CFG_APU		0x01
+#define DS2482_REG_CFG_1WS		0x08	/* 1-wire speed */
+#define DS2482_REG_CFG_SPU		0x04	/* strong pull-up */
+#define DS2482_REG_CFG_PPM		0x02	/* presence pulse masking */
+#define DS2482_REG_CFG_APU		0x01	/* active pull-up */
 
 
 /**
@@ -132,6 +132,17 @@ struct ds2482_data {
 
 
 /**
+ * Helper to calculate values for configuration register
+ * @param conf the raw config value
+ * @return the value w/ complements that can be written to register
+ */
+static inline u8 ds2482_calculate_config(u8 conf)
+{
+	return conf | ((~conf & 0x0f) << 4);
+}
+
+
+/**
  * Sets the read pointer.
  * @param pdev		The ds2482 client pointer
  * @param read_ptr	see DS2482_PTR_CODE_xxx above
@@ -399,7 +410,7 @@ static u8 ds2482_w1_reset_bus(void *data)
 		/* If the chip did reset since detect, re-config it */
 		if (err & DS2482_REG_STS_RST)
 			ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
-					     0xF0);
+					     ds2482_calculate_config(0x00));
 	}
 
 	mutex_unlock(&pdev->access_lock);
@@ -407,6 +418,32 @@ static u8 ds2482_w1_reset_bus(void *data)
 	return retval;
 }
 
+static u8 ds2482_w1_set_pullup(void *data, int delay)
+{
+	struct ds2482_w1_chan *pchan = data;
+	struct ds2482_data    *pdev = pchan->pdev;
+	u8 retval = 1;
+
+	/* if delay is non-zero activate the pullup,
+	 * the strong pullup will be automatically deactivated
+	 * by the master, so do not explicitly deactive it
+	 */
+	if (delay) {
+		/* both waits are crucial, otherwise devices might not be
+		 * powered long enough, causing e.g. a w1_therm sensor to
+		 * provide wrong conversion results
+		 */
+		ds2482_wait_1wire_idle(pdev);
+		/* note: it seems like both SPU and APU have to be set! */
+		retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
+			ds2482_calculate_config(DS2482_REG_CFG_SPU |
+						DS2482_REG_CFG_APU));
+		ds2482_wait_1wire_idle(pdev);
+	}
+
+	return retval;
+}
+
 
 static int ds2482_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
@@ -452,7 +489,8 @@ static int ds2482_probe(struct i2c_client *client,
 		data->w1_count = 8;
 
 	/* Set all config items to 0 (off) */
-	ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0);
+	ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG,
+		ds2482_calculate_config(0x00));
 
 	mutex_init(&data->access_lock);
 
@@ -468,6 +506,7 @@ static int ds2482_probe(struct i2c_client *client,
 		data->w1_ch[idx].w1_bm.touch_bit  = ds2482_w1_touch_bit;
 		data->w1_ch[idx].w1_bm.triplet    = ds2482_w1_triplet;
 		data->w1_ch[idx].w1_bm.reset_bus  = ds2482_w1_reset_bus;
+		data->w1_ch[idx].w1_bm.set_pullup = ds2482_w1_set_pullup;
 
 		err = w1_add_master_device(&data->w1_ch[idx].w1_bm);
 		if (err) {
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 708a25fc9961..372c8c0d54a0 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -109,34 +109,21 @@ static int mxc_w1_probe(struct platform_device *pdev)
 	struct resource *res;
 	int err = 0;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
-	mdev = kzalloc(sizeof(struct mxc_w1_device), GFP_KERNEL);
+	mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device),
+			    GFP_KERNEL);
 	if (!mdev)
 		return -ENOMEM;
 
-	mdev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(mdev->clk)) {
-		err = PTR_ERR(mdev->clk);
-		goto failed_clk;
-	}
+	mdev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mdev->clk))
+		return PTR_ERR(mdev->clk);
 
 	mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1;
 
-	res = request_mem_region(res->start, resource_size(res),
-				"mxc_w1");
-	if (!res) {
-		err = -EBUSY;
-		goto failed_req;
-	}
-
-	mdev->regs = ioremap(res->start, resource_size(res));
-	if (!mdev->regs) {
-		dev_err(&pdev->dev, "Cannot map mxc_w1 registers\n");
-		goto failed_ioremap;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mdev->regs = devm_request_and_ioremap(&pdev->dev, res);
+	if (!mdev->regs)
+		return -EBUSY;
 
 	clk_prepare_enable(mdev->clk);
 	__raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER);
@@ -148,20 +135,10 @@ static int mxc_w1_probe(struct platform_device *pdev)
 	err = w1_add_master_device(&mdev->bus_master);
 
 	if (err)
-		goto failed_add;
+		return err;
 
 	platform_set_drvdata(pdev, mdev);
 	return 0;
-
-failed_add:
-	iounmap(mdev->regs);
-failed_ioremap:
-	release_mem_region(res->start, resource_size(res));
-failed_req:
-	clk_put(mdev->clk);
-failed_clk:
-	kfree(mdev);
-	return err;
 }
 
 /*
@@ -170,16 +147,10 @@ failed_clk:
 static int mxc_w1_remove(struct platform_device *pdev)
 {
 	struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	w1_remove_master_device(&mdev->bus_master);
 
-	iounmap(mdev->regs);
-	release_mem_region(res->start, resource_size(res));
 	clk_disable_unprepare(mdev->clk);
-	clk_put(mdev->clk);
 
 	platform_set_drvdata(pdev, NULL);
 
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 85b363a5bd0f..d39dfa4cc235 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -72,7 +72,7 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
 	return 0;
 }
 
-static int __init w1_gpio_probe(struct platform_device *pdev)
+static int w1_gpio_probe(struct platform_device *pdev)
 {
 	struct w1_bus_master *master;
 	struct w1_gpio_platform_data *pdata;
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 92d08e7fcba2..c1a702f8c803 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -41,14 +41,18 @@ MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature famil
  * If it was disabled a parasite powered device might not get the require
  * current to do a temperature conversion.  If it is enabled parasite powered
  * devices have a better chance of getting the current required.
+ * In case the parasite power-detection is not working (seems to be the case
+ * for some DS18S20) the strong pullup can also be forced, regardless of the
+ * power state of the devices.
+ *
+ * Summary of options:
+ * - strong_pullup = 0	Disable strong pullup completely
+ * - strong_pullup = 1	Enable automatic strong pullup detection
+ * - strong_pullup = 2	Force strong pullup
  */
 static int w1_strong_pullup = 1;
 module_param_named(strong_pullup, w1_strong_pullup, int, 0);
 
-static u8 bad_roms[][9] = {
-				{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
-				{}
-			};
 
 static ssize_t w1_therm_read(struct device *device,
 	struct device_attribute *attr, char *buf);
@@ -168,16 +172,6 @@ static inline int w1_convert_temp(u8 rom[9], u8 fid)
 	return 0;
 }
 
-static int w1_therm_check_rom(u8 rom[9])
-{
-	int i;
-
-	for (i=0; i<sizeof(bad_roms)/9; ++i)
-		if (!memcmp(bad_roms[i], rom, 9))
-			return 1;
-
-	return 0;
-}
 
 static ssize_t w1_therm_read(struct device *device,
 	struct device_attribute *attr, char *buf)
@@ -194,10 +188,11 @@ static ssize_t w1_therm_read(struct device *device,
 
 	memset(rom, 0, sizeof(rom));
 
-	verdict = 0;
-	crc = 0;
-
 	while (max_trying--) {
+
+		verdict = 0;
+		crc = 0;
+
 		if (!w1_reset_select_slave(sl)) {
 			int count = 0;
 			unsigned int tm = 750;
@@ -210,7 +205,8 @@ static ssize_t w1_therm_read(struct device *device,
 				continue;
 
 			/* 750ms strong pullup (or delay) after the convert */
-			if (!external_power && w1_strong_pullup)
+			if (w1_strong_pullup == 2 ||
+					(!external_power && w1_strong_pullup))
 				w1_next_pullup(dev, tm);
 
 			w1_write_8(dev, W1_CONVERT_TEMP);
@@ -249,7 +245,7 @@ static ssize_t w1_therm_read(struct device *device,
 			}
 		}
 
-		if (!w1_therm_check_rom(rom))
+		if (verdict)
 			break;
 	}
 
@@ -260,7 +256,7 @@ static ssize_t w1_therm_read(struct device *device,
 	if (verdict)
 		memcpy(sl->rom, rom, sizeof(sl->rom));
 	else
-		dev_warn(device, "18S20 doesn't respond to CONVERT_TEMP.\n");
+		dev_warn(device, "Read failed CRC check\n");
 
 	for (i = 0; i < 9; ++i)
 		c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", sl->rom[i]);