1 /* SPDX-License-Identifier: GPL-2.0+ 2 * 3 * Copyright (c) 2015 Free Electrons 4 * Copyright (c) 2015 NextThing Co 5 * 6 * Maxime Ripard <maxime.ripard@free-electrons.com> 7 * 8 */ 9 10 #include <common.h> 11 #include <dm.h> 12 #include <w1.h> 13 14 #include <asm/gpio.h> 15 16 #define W1_TIMING_A 6 17 #define W1_TIMING_B 64 18 #define W1_TIMING_C 60 19 #define W1_TIMING_D 10 20 #define W1_TIMING_E 9 21 #define W1_TIMING_F 55 22 #define W1_TIMING_G 0 23 #define W1_TIMING_H 480 24 #define W1_TIMING_I 70 25 #define W1_TIMING_J 410 26 27 struct w1_gpio_pdata { 28 struct gpio_desc gpio; 29 u64 search_id; 30 }; 31 32 static bool w1_gpio_read_bit(struct udevice *dev) 33 { 34 struct w1_gpio_pdata *pdata = dev_get_platdata(dev); 35 int val; 36 37 dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT); 38 udelay(W1_TIMING_A); 39 40 dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN); 41 udelay(W1_TIMING_E); 42 43 val = dm_gpio_get_value(&pdata->gpio); 44 if (val < 0) 45 debug("error in retrieving GPIO value"); 46 udelay(W1_TIMING_F); 47 48 return val; 49 } 50 51 static u8 w1_gpio_read_byte(struct udevice *dev) 52 { 53 int i; 54 u8 ret = 0; 55 56 for (i = 0; i < 8; ++i) 57 ret |= (w1_gpio_read_bit(dev) ? 1 : 0) << i; 58 59 return ret; 60 } 61 62 static void w1_gpio_write_bit(struct udevice *dev, bool bit) 63 { 64 struct w1_gpio_pdata *pdata = dev_get_platdata(dev); 65 66 dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT); 67 68 bit ? udelay(W1_TIMING_A) : udelay(W1_TIMING_C); 69 70 dm_gpio_set_value(&pdata->gpio, 1); 71 72 bit ? udelay(W1_TIMING_B) : udelay(W1_TIMING_D); 73 } 74 75 static void w1_gpio_write_byte(struct udevice *dev, u8 byte) 76 { 77 int i; 78 79 for (i = 0; i < 8; ++i) 80 w1_gpio_write_bit(dev, (byte >> i) & 0x1); 81 } 82 83 static bool w1_gpio_reset(struct udevice *dev) 84 { 85 struct w1_gpio_pdata *pdata = dev_get_platdata(dev); 86 int val; 87 88 /* initiate the reset pulse. first we must pull the bus to low */ 89 dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 90 udelay(W1_TIMING_G); 91 92 dm_gpio_set_value(&pdata->gpio, 0); 93 /* wait for the specified time with the bus kept low */ 94 udelay(W1_TIMING_H); 95 96 /* now we must read the presence pulse */ 97 dm_gpio_set_dir_flags(&pdata->gpio, GPIOD_IS_IN); 98 udelay(W1_TIMING_I); 99 100 val = dm_gpio_get_value(&pdata->gpio); 101 if (val < 0) 102 debug("error in retrieving GPIO value"); 103 104 /* if nobody pulled the bus down , it means nobody is on the bus */ 105 if (val != 0) 106 return 1; 107 /* we have the bus pulled down, let's wait for the specified presence time */ 108 udelay(W1_TIMING_J); 109 110 /* read again, the other end should leave the bus free */ 111 val = dm_gpio_get_value(&pdata->gpio); 112 if (val < 0) 113 debug("error in retrieving GPIO value"); 114 115 /* bus is not going up again, so we have an error */ 116 if (val != 1) 117 return 1; 118 119 /* all good, presence detected */ 120 return 0; 121 } 122 123 static u8 w1_gpio_triplet(struct udevice *dev, bool bdir) 124 { 125 u8 id_bit = w1_gpio_read_bit(dev); 126 u8 comp_bit = w1_gpio_read_bit(dev); 127 u8 retval; 128 129 if (id_bit && comp_bit) 130 return 0x03; /* error */ 131 132 if (!id_bit && !comp_bit) { 133 /* Both bits are valid, take the direction given */ 134 retval = bdir ? 0x04 : 0; 135 } else { 136 /* Only one bit is valid, take that direction */ 137 bdir = id_bit; 138 retval = id_bit ? 0x05 : 0x02; 139 } 140 141 w1_gpio_write_bit(dev, bdir); 142 return retval; 143 } 144 145 static const struct w1_ops w1_gpio_ops = { 146 .read_byte = w1_gpio_read_byte, 147 .reset = w1_gpio_reset, 148 .triplet = w1_gpio_triplet, 149 .write_byte = w1_gpio_write_byte, 150 }; 151 152 static int w1_gpio_ofdata_to_platdata(struct udevice *dev) 153 { 154 struct w1_gpio_pdata *pdata = dev_get_platdata(dev); 155 int ret; 156 157 ret = gpio_request_by_name(dev, "gpios", 0, &pdata->gpio, 0); 158 if (ret < 0) 159 printf("Error claiming GPIO %d\n", ret); 160 161 return ret; 162 }; 163 164 static const struct udevice_id w1_gpio_id[] = { 165 { "w1-gpio", 0 }, 166 { }, 167 }; 168 169 U_BOOT_DRIVER(w1_gpio_drv) = { 170 .id = UCLASS_W1, 171 .name = "w1_gpio_drv", 172 .of_match = w1_gpio_id, 173 .ofdata_to_platdata = w1_gpio_ofdata_to_platdata, 174 .ops = &w1_gpio_ops, 175 .platdata_auto_alloc_size = sizeof(struct w1_gpio_pdata), 176 }; 177