in masters/w1-gpio.c [69:152]
static int w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
struct w1_gpio_platform_data *pdata;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
/* Enforce open drain mode by default */
enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
int err;
if (of_have_populated_dt()) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
/*
* This parameter means that something else than the gpiolib has
* already set the line into open drain mode, so we should just
* driver it high/low like we are in full control of the line and
* open drain will happen transparently.
*/
if (of_get_property(np, "linux,open-drain", NULL))
gflags = GPIOD_OUT_LOW;
pdev->dev.platform_data = pdata;
}
pdata = dev_get_platdata(dev);
if (!pdata) {
dev_err(dev, "No configuration data\n");
return -ENXIO;
}
master = devm_kzalloc(dev, sizeof(struct w1_bus_master),
GFP_KERNEL);
if (!master) {
dev_err(dev, "Out of memory\n");
return -ENOMEM;
}
pdata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags);
if (IS_ERR(pdata->gpiod)) {
dev_err(dev, "gpio_request (pin) failed\n");
return PTR_ERR(pdata->gpiod);
}
pdata->pullup_gpiod =
devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_LOW);
if (IS_ERR(pdata->pullup_gpiod)) {
dev_err(dev, "gpio_request_one "
"(ext_pullup_enable_pin) failed\n");
return PTR_ERR(pdata->pullup_gpiod);
}
master->data = pdata;
master->read_bit = w1_gpio_read_bit;
gpiod_direction_output(pdata->gpiod, 1);
master->write_bit = w1_gpio_write_bit;
/*
* If we are using open drain emulation from the GPIO library,
* we need to use this pullup function that hammers the line
* high using a raw accessor to provide pull-up for the w1
* line.
*/
if (gflags == GPIOD_OUT_LOW_OPEN_DRAIN)
master->set_pullup = w1_gpio_set_pullup;
err = w1_add_master_device(master);
if (err) {
dev_err(dev, "w1_add_master device failed\n");
return err;
}
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1);
if (pdata->pullup_gpiod)
gpiod_set_value(pdata->pullup_gpiod, 1);
platform_set_drvdata(pdev, master);
return 0;
}