aboutsummaryrefslogtreecommitdiff
path: root/drivers/w1/masters
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1/masters')
-rw-r--r--drivers/w1/masters/Kconfig3
-rw-r--r--drivers/w1/masters/ds1wm.c14
-rw-r--r--drivers/w1/masters/ds2490.c155
-rw-r--r--drivers/w1/masters/mxc_w1.c72
-rw-r--r--drivers/w1/masters/omap_hdq.c3
-rw-r--r--drivers/w1/masters/w1-gpio.c84
6 files changed, 221 insertions, 110 deletions
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index efc7f075fcb..1708b2300c7 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -36,13 +36,12 @@ config W1_MASTER_DS2482
config W1_MASTER_MXC
tristate "Freescale MXC 1-wire busmaster"
- depends on W1 && ARCH_MXC
+ depends on ARCH_MXC || COMPILE_TEST
help
Say Y here to enable MXC 1-wire host
config W1_MASTER_DS1WM
tristate "Maxim DS1WM 1-wire busmaster"
- depends on W1
help
Say Y here to enable the DS1WM 1-wire driver, such as that
in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 96cab6ac2b4..02df3b1381d 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -255,17 +255,17 @@ static int ds1wm_find_divisor(int gclk)
static void ds1wm_up(struct ds1wm_data *ds1wm_data)
{
int divisor;
- struct ds1wm_driver_data *plat = ds1wm_data->pdev->dev.platform_data;
+ struct device *dev = &ds1wm_data->pdev->dev;
+ struct ds1wm_driver_data *plat = dev_get_platdata(dev);
if (ds1wm_data->cell->enable)
ds1wm_data->cell->enable(ds1wm_data->pdev);
divisor = ds1wm_find_divisor(plat->clock_rate);
- dev_dbg(&ds1wm_data->pdev->dev,
- "found divisor 0x%x for clock %d\n", divisor, plat->clock_rate);
+ dev_dbg(dev, "found divisor 0x%x for clock %d\n",
+ divisor, plat->clock_rate);
if (divisor == 0) {
- dev_err(&ds1wm_data->pdev->dev,
- "no suitable divisor for %dHz clock\n",
+ dev_err(dev, "no suitable divisor for %dHz clock\n",
plat->clock_rate);
return;
}
@@ -481,7 +481,7 @@ static int ds1wm_probe(struct platform_device *pdev)
ds1wm_data->cell = mfd_get_cell(pdev);
if (!ds1wm_data->cell)
return -ENODEV;
- plat = pdev->dev.platform_data;
+ plat = dev_get_platdata(&pdev->dev);
if (!plat)
return -ENODEV;
@@ -498,7 +498,7 @@ static int ds1wm_probe(struct platform_device *pdev)
irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr,
- IRQF_DISABLED | IRQF_SHARED, "ds1wm", ds1wm_data);
+ IRQF_SHARED, "ds1wm", ds1wm_data);
if (ret)
return ret;
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 4f7e1d770f8..7404ad3062b 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -1,5 +1,5 @@
/*
- * dscore.c
+ * ds2490.c USB to one wire bridge
*
* Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
*
@@ -28,6 +28,10 @@
#include "../w1_int.h"
#include "../w1.h"
+/* USB Standard */
+/* USB Control request vendor type */
+#define VENDOR 0x40
+
/* COMMAND TYPE CODES */
#define CONTROL_CMD 0x00
#define COMM_CMD 0x01
@@ -107,6 +111,8 @@
#define ST_HALT 0x10 /* DS2490 is currently halted */
#define ST_IDLE 0x20 /* DS2490 is currently idle */
#define ST_EPOF 0x80
+/* Status transfer size, 16 bytes status, 16 byte result flags */
+#define ST_SIZE 0x20
/* Result Register flags */
#define RR_DETECT 0xA5 /* New device detected */
@@ -198,7 +204,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
int err;
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
- CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
+ CONTROL_CMD, VENDOR, value, index, NULL, 0, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
value, index, err);
@@ -213,7 +219,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
int err;
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
- MODE_CMD, 0x40, value, index, NULL, 0, 1000);
+ MODE_CMD, VENDOR, value, index, NULL, 0, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
value, index, err);
@@ -228,7 +234,7 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
int err;
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
- COMM_CMD, 0x40, value, index, NULL, 0, 1000);
+ COMM_CMD, VENDOR, value, index, NULL, 0, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
value, index, err);
@@ -246,7 +252,8 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
memset(st, 0, sizeof(*st));
count = 0;
- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+ err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev,
+ dev->ep[EP_STATUS]), buf, size, &count, 100);
if (err < 0) {
printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
return err;
@@ -353,7 +360,7 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
buf, size, &count, 1000);
if (err < 0) {
- u8 buf[0x20];
+ u8 buf[ST_SIZE];
int count;
printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
@@ -398,7 +405,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit)
{
struct ds_status st;
int count = 0, err = 0;
- u8 buf[0x20];
+ u8 buf[ST_SIZE];
do {
err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
@@ -450,10 +457,11 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
{
- u8 buf[0x20];
+ u8 buf[ST_SIZE];
int err, count = 0;
do {
+ st->status = 0;
err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
#if 0
if (err >= 0) {
@@ -464,7 +472,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
printk("\n");
}
#endif
- } while (!(buf[0x08] & ST_IDLE) && !(err < 0) && ++count < 100);
+ } while (!(st->status & ST_IDLE) && !(err < 0) && ++count < 100);
if (err >= 16 && st->status & ST_EPOF) {
printk(KERN_INFO "Resetting device after ST_EPOF.\n");
@@ -690,37 +698,106 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
return !(err == len);
}
-#if 0
-
-static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+static void ds9490r_search(void *data, struct w1_master *master,
+ u8 search_type, w1_slave_found_callback callback)
{
+ /* When starting with an existing id, the first id returned will
+ * be that device (if it is still on the bus most likely).
+ *
+ * If the number of devices found is less than or equal to the
+ * search_limit, that number of IDs will be returned. If there are
+ * more, search_limit IDs will be returned followed by a non-zero
+ * discrepency value.
+ */
+ struct ds_device *dev = data;
int err;
u16 value, index;
struct ds_status st;
+ u8 st_buf[ST_SIZE];
+ int search_limit;
+ int found = 0;
+ int i;
- memset(buf, 0, sizeof(buf));
+ /* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for
+ * discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time.
+ */
+ const unsigned long jtime = msecs_to_jiffies(1000*8/75);
+ /* FIFO 128 bytes, bulk packet size 64, read a multiple of the
+ * packet size.
+ */
+ u64 buf[2*64/8];
- err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
- if (err)
- return err;
+ mutex_lock(&master->bus_mutex);
- ds_wait_status(ds_dev, &st);
+ /* address to start searching at */
+ if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0)
+ goto search_out;
+ master->search_id = 0;
- value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
- index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
- err = ds_send_control(ds_dev, value, index);
- if (err)
- return err;
+ value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F |
+ COMM_RTS;
+ search_limit = master->max_slave_count;
+ if (search_limit > 255)
+ search_limit = 0;
+ index = search_type | (search_limit << 8);
+ if (ds_send_control(dev, value, index) < 0)
+ goto search_out;
- ds_wait_status(ds_dev, &st);
+ do {
+ schedule_timeout(jtime);
- err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
- if (err < 0)
- return err;
+ if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) <
+ sizeof(st)) {
+ break;
+ }
- return err/8;
+ if (st.data_in_buffer_status) {
+ /* Bulk in can receive partial ids, but when it does
+ * they fail crc and will be discarded anyway.
+ * That has only been seen when status in buffer
+ * is 0 and bulk is read anyway, so don't read
+ * bulk without first checking if status says there
+ * is data to read.
+ */
+ err = ds_recv_data(dev, (u8 *)buf, sizeof(buf));
+ if (err < 0)
+ break;
+ for (i = 0; i < err/8; ++i) {
+ ++found;
+ if (found <= search_limit)
+ callback(master, buf[i]);
+ /* can't know if there will be a discrepancy
+ * value after until the next id */
+ if (found == search_limit)
+ master->search_id = buf[i];
+ }
+ }
+
+ if (test_bit(W1_ABORT_SEARCH, &master->flags))
+ break;
+ } while (!(st.status & (ST_IDLE | ST_HALT)));
+
+ /* only continue the search if some weren't found */
+ if (found <= search_limit) {
+ master->search_id = 0;
+ } else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) {
+ /* Only max_slave_count will be scanned in a search,
+ * but it will start where it left off next search
+ * until all ids are identified and then it will start
+ * over. A continued search will report the previous
+ * last id as the first id (provided it is still on the
+ * bus).
+ */
+ dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, "
+ "will continue next search.\n", __func__,
+ master->max_slave_count);
+ set_bit(W1_WARN_MAX_COUNT, &master->flags);
+ }
+search_out:
+ mutex_unlock(&master->bus_mutex);
}
+#if 0
static int ds_match_access(struct ds_device *dev, u64 init)
{
int err;
@@ -894,6 +971,7 @@ static int ds_w1_init(struct ds_device *dev)
dev->master.write_block = &ds9490r_write_block;
dev->master.reset_bus = &ds9490r_reset;
dev->master.set_pullup = &ds9490r_set_pullup;
+ dev->master.search = &ds9490r_search;
return w1_add_master_device(&dev->master);
}
@@ -910,15 +988,13 @@ static int ds_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *endpoint;
struct usb_host_interface *iface_desc;
struct ds_device *dev;
- int i, err;
+ int i, err, alt;
- dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL);
if (!dev) {
printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
return -ENOMEM;
}
- dev->spu_sleep = 0;
- dev->spu_bit = 0;
dev->udev = usb_get_dev(udev);
if (!dev->udev) {
err = -ENOMEM;
@@ -928,20 +1004,25 @@ static int ds_probe(struct usb_interface *intf,
usb_set_intfdata(intf, dev);
- err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+ err = usb_reset_configuration(dev->udev);
if (err) {
- printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
- intf->altsetting[0].desc.bInterfaceNumber, err);
+ dev_err(&dev->udev->dev,
+ "Failed to reset configuration: err=%d.\n", err);
goto err_out_clear;
}
- err = usb_reset_configuration(dev->udev);
+ /* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */
+ alt = 3;
+ err = usb_set_interface(dev->udev,
+ intf->altsetting[alt].desc.bInterfaceNumber, alt);
if (err) {
- printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+ dev_err(&dev->udev->dev, "Failed to set alternative setting %d "
+ "for %d interface: err=%d.\n", alt,
+ intf->altsetting[alt].desc.bInterfaceNumber, err);
goto err_out_clear;
}
- iface_desc = &intf->altsetting[0];
+ iface_desc = &intf->altsetting[alt];
if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
err = -EINVAL;
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 15c7251b055..a5df5e89d45 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -10,24 +10,16 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
*/
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
-#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include "../w1.h"
#include "../w1_int.h"
-#include "../w1_log.h"
/* According to the mx27 Datasheet the reset procedure should take up to about
* 1350us. We set the timeout to 500*100us = 50ms for sure */
@@ -36,17 +28,16 @@
/*
* MXC W1 Register offsets
*/
-#define MXC_W1_CONTROL 0x00
-#define MXC_W1_TIME_DIVIDER 0x02
-#define MXC_W1_RESET 0x04
-#define MXC_W1_COMMAND 0x06
-#define MXC_W1_TXRX 0x08
-#define MXC_W1_INTERRUPT 0x0A
-#define MXC_W1_INTERRUPT_EN 0x0C
+#define MXC_W1_CONTROL 0x00
+# define MXC_W1_CONTROL_RDST BIT(3)
+# define MXC_W1_CONTROL_WR(x) BIT(5 - (x))
+# define MXC_W1_CONTROL_PST BIT(6)
+# define MXC_W1_CONTROL_RPP BIT(7)
+#define MXC_W1_TIME_DIVIDER 0x02
+#define MXC_W1_RESET 0x04
struct mxc_w1_device {
void __iomem *regs;
- unsigned int clkdiv;
struct clk *clk;
struct w1_bus_master bus_master;
};
@@ -62,12 +53,12 @@ static u8 mxc_w1_ds2_reset_bus(void *data)
unsigned int timeout_cnt = 0;
struct mxc_w1_device *dev = data;
- __raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL));
+ writeb(MXC_W1_CONTROL_RPP, (dev->regs + MXC_W1_CONTROL));
while (1) {
- reg_val = __raw_readb(dev->regs + MXC_W1_CONTROL);
+ reg_val = readb(dev->regs + MXC_W1_CONTROL);
- if (((reg_val >> 7) & 0x1) == 0 ||
+ if (!(reg_val & MXC_W1_CONTROL_RPP) ||
timeout_cnt > MXC_W1_RESET_TIMEOUT)
break;
else
@@ -75,7 +66,7 @@ static u8 mxc_w1_ds2_reset_bus(void *data)
udelay(100);
}
- return (reg_val >> 7) & 0x1;
+ return !(reg_val & MXC_W1_CONTROL_PST);
}
/*
@@ -91,23 +82,25 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
* datasheet.
*/
- __raw_writeb((1 << (5 - bit)), ctrl_addr);
+ writeb(MXC_W1_CONTROL_WR(bit), ctrl_addr);
while (timeout_cnt--) {
- if (!((__raw_readb(ctrl_addr) >> (5 - bit)) & 0x1))
+ if (!(readb(ctrl_addr) & MXC_W1_CONTROL_WR(bit)))
break;
udelay(1);
}
- return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
+ return !!(readb(ctrl_addr) & MXC_W1_CONTROL_RDST);
}
static int mxc_w1_probe(struct platform_device *pdev)
{
struct mxc_w1_device *mdev;
+ unsigned long clkrate;
struct resource *res;
- int err = 0;
+ unsigned int clkdiv;
+ int err;
mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device),
GFP_KERNEL);
@@ -118,27 +111,39 @@ static int mxc_w1_probe(struct platform_device *pdev)
if (IS_ERR(mdev->clk))
return PTR_ERR(mdev->clk);
- mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1;
+ clkrate = clk_get_rate(mdev->clk);
+ if (clkrate < 10000000)
+ dev_warn(&pdev->dev,
+ "Low clock frequency causes improper function\n");
+
+ clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000);
+ clkrate /= clkdiv;
+ if ((clkrate < 980000) || (clkrate > 1020000))
+ dev_warn(&pdev->dev,
+ "Incorrect time base frequency %lu Hz\n", clkrate);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mdev->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mdev->regs))
return PTR_ERR(mdev->regs);
- clk_prepare_enable(mdev->clk);
- __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER);
+ err = clk_prepare_enable(mdev->clk);
+ if (err)
+ return err;
+
+ writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER);
mdev->bus_master.data = mdev;
mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus;
mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit;
- err = w1_add_master_device(&mdev->bus_master);
+ platform_set_drvdata(pdev, mdev);
+ err = w1_add_master_device(&mdev->bus_master);
if (err)
- return err;
+ clk_disable_unprepare(mdev->clk);
- platform_set_drvdata(pdev, mdev);
- return 0;
+ return err;
}
/*
@@ -164,6 +169,7 @@ MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids);
static struct platform_driver mxc_w1_driver = {
.driver = {
.name = "mxc_w1",
+ .owner = THIS_MODULE,
.of_match_table = mxc_w1_dt_ids,
},
.probe = mxc_w1_probe,
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 6e94d8dd3d0..9900e8ec739 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -577,8 +577,7 @@ static int omap_hdq_probe(struct platform_device *pdev)
goto err_irq;
}
- ret = devm_request_irq(dev, irq, hdq_isr, IRQF_DISABLED,
- "omap_hdq", hdq_data);
+ ret = devm_request_irq(dev, irq, hdq_isr, 0, "omap_hdq", hdq_data);
if (ret < 0) {
dev_dbg(&pdev->dev, "could not request irq\n");
goto err_irq;
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index f54ece268c9..1d111e56c8c 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -18,10 +18,31 @@
#include <linux/of_gpio.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/delay.h>
#include "../w1.h"
#include "../w1_int.h"
+static u8 w1_gpio_set_pullup(void *data, int delay)
+{
+ struct w1_gpio_platform_data *pdata = data;
+
+ if (delay) {
+ pdata->pullup_duration = delay;
+ } else {
+ if (pdata->pullup_duration) {
+ gpio_direction_output(pdata->pin, 1);
+
+ msleep(pdata->pullup_duration);
+
+ gpio_direction_input(pdata->pin);
+ }
+ pdata->pullup_duration = 0;
+ }
+
+ return 0;
+}
+
static void w1_gpio_write_bit_dir(void *data, u8 bit)
{
struct w1_gpio_platform_data *pdata = data;
@@ -56,8 +77,9 @@ MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
static int w1_gpio_probe_dt(struct platform_device *pdev)
{
- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct device_node *np = pdev->dev.of_node;
+ int gpio;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -66,8 +88,23 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
if (of_get_property(np, "linux,open-drain", NULL))
pdata->is_open_drain = 1;
- pdata->pin = of_get_gpio(np, 0);
- pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
+ gpio = of_get_gpio(np, 0);
+ if (gpio < 0) {
+ if (gpio != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "Failed to parse gpio property for data pin (%d)\n",
+ gpio);
+
+ return gpio;
+ }
+ pdata->pin = gpio;
+
+ gpio = of_get_gpio(np, 1);
+ if (gpio == -EPROBE_DEFER)
+ return gpio;
+ /* ignore other errors as the pullup gpio is optional */
+ pdata->ext_pullup_enable_pin = gpio;
+
pdev->dev.platform_data = pdata;
return 0;
@@ -81,38 +118,38 @@ static int w1_gpio_probe(struct platform_device *pdev)
if (of_have_populated_dt()) {
err = w1_gpio_probe_dt(pdev);
- if (err < 0) {
- dev_err(&pdev->dev, "Failed to parse DT\n");
+ if (err < 0)
return err;
- }
}
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "No configuration data\n");
return -ENXIO;
}
- master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+ master = devm_kzalloc(&pdev->dev, sizeof(struct w1_bus_master),
+ GFP_KERNEL);
if (!master) {
dev_err(&pdev->dev, "Out of memory\n");
return -ENOMEM;
}
- err = gpio_request(pdata->pin, "w1");
+ err = devm_gpio_request(&pdev->dev, pdata->pin, "w1");
if (err) {
dev_err(&pdev->dev, "gpio_request (pin) failed\n");
- goto free_master;
+ return err;
}
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
- err = gpio_request_one(pdata->ext_pullup_enable_pin,
- GPIOF_INIT_LOW, "w1 pullup");
+ err = devm_gpio_request_one(&pdev->dev,
+ pdata->ext_pullup_enable_pin, GPIOF_INIT_LOW,
+ "w1 pullup");
if (err < 0) {
dev_err(&pdev->dev, "gpio_request_one "
"(ext_pullup_enable_pin) failed\n");
- goto free_gpio;
+ return err;
}
}
@@ -125,12 +162,13 @@ static int w1_gpio_probe(struct platform_device *pdev)
} else {
gpio_direction_input(pdata->pin);
master->write_bit = w1_gpio_write_bit_dir;
+ master->set_pullup = w1_gpio_set_pullup;
}
err = w1_add_master_device(master);
if (err) {
dev_err(&pdev->dev, "w1_add_master device failed\n");
- goto free_gpio_ext_pu;
+ return err;
}
if (pdata->enable_external_pullup)
@@ -142,22 +180,12 @@ static int w1_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
return 0;
-
- free_gpio_ext_pu:
- if (gpio_is_valid(pdata->ext_pullup_enable_pin))
- gpio_free(pdata->ext_pullup_enable_pin);
- free_gpio:
- gpio_free(pdata->pin);
- free_master:
- kfree(master);
-
- return err;
}
static int w1_gpio_remove(struct platform_device *pdev)
{
struct w1_bus_master *master = platform_get_drvdata(pdev);
- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0);
@@ -166,8 +194,6 @@ static int w1_gpio_remove(struct platform_device *pdev)
gpio_set_value(pdata->ext_pullup_enable_pin, 0);
w1_remove_master_device(master);
- gpio_free(pdata->pin);
- kfree(master);
return 0;
}
@@ -176,7 +202,7 @@ static int w1_gpio_remove(struct platform_device *pdev)
static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0);
@@ -186,7 +212,7 @@ static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
static int w1_gpio_resume(struct platform_device *pdev)
{
- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1);