diff options
Diffstat (limited to 'drivers/w1/masters')
-rw-r--r-- | drivers/w1/masters/mxc_w1.c | 31 | ||||
-rw-r--r-- | drivers/w1/masters/w1-gpio.c | 22 |
2 files changed, 44 insertions, 9 deletions
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 15c7251b055..1e5d94c5afc 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -46,7 +46,6 @@ struct mxc_w1_device { void __iomem *regs; - unsigned int clkdiv; struct clk *clk; struct w1_bus_master bus_master; }; @@ -106,8 +105,10 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) 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 +119,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; + + __raw_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; } /* diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index e36b18b2817..9709b8b484b 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; @@ -132,6 +153,7 @@ 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); |