On 8.11.2016 11:19, Maxime Ripard wrote: > Add a bus driver for bitbanging a 1-Wire bus over a GPIO. > > Signed-off-by: Maxime Ripard <maxime.rip...@free-electrons.com> > --- > drivers/w1/Kconfig | 6 ++- > drivers/w1/Makefile | 1 +- > drivers/w1/w1-gpio.c | 160 ++++++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 167 insertions(+), 0 deletions(-) > create mode 100644 drivers/w1/w1-gpio.c > > diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig > index 0c056b4c06a9..ccc3ae15db86 100644 > --- a/drivers/w1/Kconfig > +++ b/drivers/w1/Kconfig > @@ -12,6 +12,12 @@ config W1 > > if W1 > > +config W1_GPIO > + bool "Enable 1-Wire GPIO bitbanging" > + depends on DM_GPIO > + help > + Emulate a 1-Wire bus using a GPIO. > + > endif > > endmenu > diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile > index 26820fa209e1..7fd8697f8419 100644 > --- a/drivers/w1/Makefile > +++ b/drivers/w1/Makefile > @@ -1,2 +1,3 @@ > obj-$(CONFIG_W1) += w1-uclass.o > > +obj-$(CONFIG_W1_GPIO) += w1-gpio.o > diff --git a/drivers/w1/w1-gpio.c b/drivers/w1/w1-gpio.c > new file mode 100644 > index 000000000000..091849162533 > --- /dev/null > +++ b/drivers/w1/w1-gpio.c > @@ -0,0 +1,160 @@ > +/* > + * Copyright (c) 2015 Free Electrons > + * Copyright (c) 2015 NextThing Co > + * > + * Maxime Ripard <maxime.rip...@free-electrons.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <w1.h> > + > +#include <asm/gpio.h> > + > + > +#define W1_TIMING_A 6 > +#define W1_TIMING_B 64 > +#define W1_TIMING_C 60 > +#define W1_TIMING_D 10 > +#define W1_TIMING_E 9 > +#define W1_TIMING_F 55 > +#define W1_TIMING_G 0 > +#define W1_TIMING_H 480 > +#define W1_TIMING_I 70 > +#define W1_TIMING_J 410 > + > +struct w1_gpio_pdata { > + struct gpio_desc gpio; > + u64 search_id; > +}; > + > +static bool w1_gpio_read_bit(struct udevice *dev) > +{ > + struct w1_gpio_pdata *pdata = dev_get_platdata(dev); > + int val; > + > + dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT); > + udelay(W1_TIMING_A); > + > + dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN); > + udelay(W1_TIMING_E); > + > + val = dm_gpio_get_value(&pdata->gpio); > + udelay(W1_TIMING_F); > + > + return val; > +} > + > +static u8 w1_gpio_read_byte(struct udevice *dev) > +{ > + int i; > + u8 ret = 0; > + > + for (i = 0; i < 8; ++i) > + ret |= (w1_gpio_read_bit(dev) ? 1 : 0) << i; > + > + return ret; > +} > + > +static void w1_gpio_write_bit(struct udevice *dev, bool bit) > +{ > + struct w1_gpio_pdata *pdata = dev_get_platdata(dev); > + > + dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT); > + > + bit ? udelay(W1_TIMING_A) : udelay(W1_TIMING_C); > + > + dm_gpio_set_value(&pdata->gpio, 1); > + > + bit ? udelay(W1_TIMING_B) : udelay(W1_TIMING_D); > +} > + > +static void w1_gpio_write_byte(struct udevice *dev, u8 byte) > +{ > + int i; > + > + for (i = 0; i < 8; ++i) > + w1_gpio_write_bit(dev, (byte >> i) & 0x1); > +} > + > +static bool w1_gpio_reset(struct udevice *dev) > +{ > + struct w1_gpio_pdata *pdata = dev_get_platdata(dev); > + int val; > + > + dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); > + udelay(W1_TIMING_G); > + > + dm_gpio_set_value(&pdata->gpio, 0); > + udelay(W1_TIMING_H); > + > + dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN); > + udelay(W1_TIMING_I); > + > + val = dm_gpio_get_value(&pdata->gpio); > + udelay(W1_TIMING_J); > + > + return val; > +} > + > +static u8 w1_gpio_triplet(struct udevice *dev, bool bdir) > +{ > + u8 id_bit = w1_gpio_read_bit(dev); > + u8 comp_bit = w1_gpio_read_bit(dev); > + u8 retval; > + > + if (id_bit && comp_bit) > + return 0x03; /* error */ > + > + if (!id_bit && !comp_bit) { > + /* Both bits are valid, take the direction given */ > + retval = bdir ? 0x04 : 0; > + } else { > + /* Only one bit is valid, take that direction */ > + bdir = id_bit; > + retval = id_bit ? 0x05 : 0x02; > + } > + > + w1_gpio_write_bit(dev, bdir); > + return retval; > +} > + > + > +static const struct w1_ops w1_gpio_ops = { > + .read_byte = w1_gpio_read_byte, > + .reset = w1_gpio_reset, > + .triplet = w1_gpio_triplet, > + .write_byte = w1_gpio_write_byte, > +}; > + > +static int w1_gpio_ofdata_to_platdata(struct udevice *dev) > +{ > + struct w1_gpio_pdata *pdata = dev_get_platdata(dev); > + int ret; > + > + ret = gpio_request_by_name(dev, "gpios", 0, &pdata->gpio, 0); > + if (ret < 0) > + goto error; > + > + return 0; > + > +error: > + printf("Error claiming GPIO %d\n", ret); > + return ret; > +}; > + > +static const struct udevice_id w1_gpio_id[] = { > + { "w1-gpio", 0 }, > + { }, > +}; > + > +U_BOOT_DRIVER(w1_gpio_drv) = { > + .id = UCLASS_W1, > + .name = "w1_gpio_drv", > + .of_match = w1_gpio_id, > + .ofdata_to_platdata = w1_gpio_ofdata_to_platdata, > + .ops = &w1_gpio_ops, > + .platdata_auto_alloc_size = sizeof(struct w1_gpio_pdata), > +}; >
Has someone test this on different HW? As I went through the series will be good to have cmd/w1.c to be able to test that devices. Thanks, Michal -- Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel - Xilinx Microblaze Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs
signature.asc
Description: OpenPGP digital signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot