summaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 22:57:13 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 22:57:13 +0100
commit7ed214ac2095f561a94335ca672b6c42a1ea40ff (patch)
treeda41901bff1d0d8d61170bf362384fdc61deb3ab /drivers/w1
parentMerge tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/greg... (diff)
parentw1: w1_therm: Add force-pullup option for "broken" sensors (diff)
downloadlinux-7ed214ac2095f561a94335ca672b6c42a1ea40ff.tar.xz
linux-7ed214ac2095f561a94335ca672b6c42a1ea40ff.zip
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]);