1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * w1-gpio - GPIO w1 bus master driver 4 * 5 * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi> 6 */ 7 8 #include <linux/init.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/slab.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/of_platform.h> 14 #include <linux/err.h> 15 #include <linux/of.h> 16 #include <linux/delay.h> 17 18 #include <linux/w1.h> 19 20 struct w1_gpio_ddata { 21 struct gpio_desc *gpiod; 22 struct gpio_desc *pullup_gpiod; 23 unsigned int pullup_duration; 24 }; 25 26 static u8 w1_gpio_set_pullup(void *data, int delay) 27 { 28 struct w1_gpio_ddata *ddata = data; 29 30 if (delay) { 31 ddata->pullup_duration = delay; 32 } else { 33 if (ddata->pullup_duration) { 34 /* 35 * This will OVERRIDE open drain emulation and force-pull 36 * the line high for some time. 37 */ 38 gpiod_set_raw_value(ddata->gpiod, 1); 39 msleep(ddata->pullup_duration); 40 /* 41 * This will simply set the line as input since we are doing 42 * open drain emulation in the GPIO library. 43 */ 44 gpiod_set_value(ddata->gpiod, 1); 45 } 46 ddata->pullup_duration = 0; 47 } 48 49 return 0; 50 } 51 52 static void w1_gpio_write_bit(void *data, u8 bit) 53 { 54 struct w1_gpio_ddata *ddata = data; 55 56 gpiod_set_value(ddata->gpiod, bit); 57 } 58 59 static u8 w1_gpio_read_bit(void *data) 60 { 61 struct w1_gpio_ddata *ddata = data; 62 63 return gpiod_get_value(ddata->gpiod) ? 1 : 0; 64 } 65 66 #if defined(CONFIG_OF) 67 static const struct of_device_id w1_gpio_dt_ids[] = { 68 { .compatible = "w1-gpio" }, 69 {} 70 }; 71 MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); 72 #endif 73 74 static int w1_gpio_probe(struct platform_device *pdev) 75 { 76 struct w1_bus_master *master; 77 struct w1_gpio_ddata *ddata; 78 struct device *dev = &pdev->dev; 79 struct device_node *np = dev->of_node; 80 /* Enforce open drain mode by default */ 81 enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN; 82 int err; 83 84 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); 85 if (!ddata) 86 return -ENOMEM; 87 88 /* 89 * This parameter means that something else than the gpiolib has 90 * already set the line into open drain mode, so we should just 91 * driver it high/low like we are in full control of the line and 92 * open drain will happen transparently. 93 */ 94 if (of_property_present(np, "linux,open-drain")) 95 gflags = GPIOD_OUT_LOW; 96 97 master = devm_kzalloc(dev, sizeof(struct w1_bus_master), 98 GFP_KERNEL); 99 if (!master) 100 return -ENOMEM; 101 102 ddata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags); 103 if (IS_ERR(ddata->gpiod)) { 104 dev_err(dev, "gpio_request (pin) failed\n"); 105 return PTR_ERR(ddata->gpiod); 106 } 107 108 ddata->pullup_gpiod = 109 devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_LOW); 110 if (IS_ERR(ddata->pullup_gpiod)) { 111 dev_err(dev, "gpio_request_one " 112 "(ext_pullup_enable_pin) failed\n"); 113 return PTR_ERR(ddata->pullup_gpiod); 114 } 115 116 master->data = ddata; 117 master->read_bit = w1_gpio_read_bit; 118 gpiod_direction_output(ddata->gpiod, 1); 119 master->write_bit = w1_gpio_write_bit; 120 121 /* 122 * If we are using open drain emulation from the GPIO library, 123 * we need to use this pullup function that hammers the line 124 * high using a raw accessor to provide pull-up for the w1 125 * line. 126 */ 127 if (gflags == GPIOD_OUT_LOW_OPEN_DRAIN) 128 master->set_pullup = w1_gpio_set_pullup; 129 130 err = w1_add_master_device(master); 131 if (err) { 132 dev_err(dev, "w1_add_master device failed\n"); 133 return err; 134 } 135 136 if (ddata->pullup_gpiod) 137 gpiod_set_value(ddata->pullup_gpiod, 1); 138 139 platform_set_drvdata(pdev, master); 140 141 return 0; 142 } 143 144 static int w1_gpio_remove(struct platform_device *pdev) 145 { 146 struct w1_bus_master *master = platform_get_drvdata(pdev); 147 struct w1_gpio_ddata *ddata = master->data; 148 149 if (ddata->pullup_gpiod) 150 gpiod_set_value(ddata->pullup_gpiod, 0); 151 152 w1_remove_master_device(master); 153 154 return 0; 155 } 156 157 static struct platform_driver w1_gpio_driver = { 158 .driver = { 159 .name = "w1-gpio", 160 .of_match_table = of_match_ptr(w1_gpio_dt_ids), 161 }, 162 .probe = w1_gpio_probe, 163 .remove = w1_gpio_remove, 164 }; 165 166 module_platform_driver(w1_gpio_driver); 167 168 MODULE_DESCRIPTION("GPIO w1 bus master driver"); 169 MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); 170 MODULE_LICENSE("GPL"); 171