linux/drivers/w1/masters/w1-gpio.c
<<
>>
Prefs
   1/*
   2 * w1-gpio - GPIO w1 bus master driver
   3 *
   4 * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2
   8 * as published by the Free Software Foundation.
   9 */
  10
  11#include <linux/init.h>
  12#include <linux/module.h>
  13#include <linux/platform_device.h>
  14#include <linux/slab.h>
  15#include <linux/w1-gpio.h>
  16#include <linux/gpio.h>
  17#include <linux/of_platform.h>
  18#include <linux/of_gpio.h>
  19#include <linux/err.h>
  20#include <linux/of.h>
  21#include <linux/delay.h>
  22
  23#include "../w1.h"
  24#include "../w1_int.h"
  25
  26static u8 w1_gpio_set_pullup(void *data, int delay)
  27{
  28        struct w1_gpio_platform_data *pdata = data;
  29
  30        if (delay) {
  31                pdata->pullup_duration = delay;
  32        } else {
  33                if (pdata->pullup_duration) {
  34                        gpio_direction_output(pdata->pin, 1);
  35
  36                        msleep(pdata->pullup_duration);
  37
  38                        gpio_direction_input(pdata->pin);
  39                }
  40                pdata->pullup_duration = 0;
  41        }
  42
  43        return 0;
  44}
  45
  46static void w1_gpio_write_bit_dir(void *data, u8 bit)
  47{
  48        struct w1_gpio_platform_data *pdata = data;
  49
  50        if (bit)
  51                gpio_direction_input(pdata->pin);
  52        else
  53                gpio_direction_output(pdata->pin, 0);
  54}
  55
  56static void w1_gpio_write_bit_val(void *data, u8 bit)
  57{
  58        struct w1_gpio_platform_data *pdata = data;
  59
  60        gpio_set_value(pdata->pin, bit);
  61}
  62
  63static u8 w1_gpio_read_bit(void *data)
  64{
  65        struct w1_gpio_platform_data *pdata = data;
  66
  67        return gpio_get_value(pdata->pin) ? 1 : 0;
  68}
  69
  70#if defined(CONFIG_OF)
  71static const struct of_device_id w1_gpio_dt_ids[] = {
  72        { .compatible = "w1-gpio" },
  73        {}
  74};
  75MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
  76#endif
  77
  78static int w1_gpio_probe_dt(struct platform_device *pdev)
  79{
  80        struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
  81        struct device_node *np = pdev->dev.of_node;
  82        int gpio;
  83
  84        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  85        if (!pdata)
  86                return -ENOMEM;
  87
  88        if (of_get_property(np, "linux,open-drain", NULL))
  89                pdata->is_open_drain = 1;
  90
  91        gpio = of_get_gpio(np, 0);
  92        if (gpio < 0) {
  93                if (gpio != -EPROBE_DEFER)
  94                        dev_err(&pdev->dev,
  95                                        "Failed to parse gpio property for data pin (%d)\n",
  96                                        gpio);
  97
  98                return gpio;
  99        }
 100        pdata->pin = gpio;
 101
 102        gpio = of_get_gpio(np, 1);
 103        if (gpio == -EPROBE_DEFER)
 104                return gpio;
 105        /* ignore other errors as the pullup gpio is optional */
 106        pdata->ext_pullup_enable_pin = gpio;
 107
 108        pdev->dev.platform_data = pdata;
 109
 110        return 0;
 111}
 112
 113static int w1_gpio_probe(struct platform_device *pdev)
 114{
 115        struct w1_bus_master *master;
 116        struct w1_gpio_platform_data *pdata;
 117        int err;
 118
 119        if (of_have_populated_dt()) {
 120                err = w1_gpio_probe_dt(pdev);
 121                if (err < 0)
 122                        return err;
 123        }
 124
 125        pdata = dev_get_platdata(&pdev->dev);
 126
 127        if (!pdata) {
 128                dev_err(&pdev->dev, "No configuration data\n");
 129                return -ENXIO;
 130        }
 131
 132        master = devm_kzalloc(&pdev->dev, sizeof(struct w1_bus_master),
 133                        GFP_KERNEL);
 134        if (!master) {
 135                dev_err(&pdev->dev, "Out of memory\n");
 136                return -ENOMEM;
 137        }
 138
 139        err = devm_gpio_request(&pdev->dev, pdata->pin, "w1");
 140        if (err) {
 141                dev_err(&pdev->dev, "gpio_request (pin) failed\n");
 142                return err;
 143        }
 144
 145        if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
 146                err = devm_gpio_request_one(&pdev->dev,
 147                                pdata->ext_pullup_enable_pin, GPIOF_INIT_LOW,
 148                                "w1 pullup");
 149                if (err < 0) {
 150                        dev_err(&pdev->dev, "gpio_request_one "
 151                                        "(ext_pullup_enable_pin) failed\n");
 152                        return err;
 153                }
 154        }
 155
 156        master->data = pdata;
 157        master->read_bit = w1_gpio_read_bit;
 158
 159        if (pdata->is_open_drain) {
 160                gpio_direction_output(pdata->pin, 1);
 161                master->write_bit = w1_gpio_write_bit_val;
 162        } else {
 163                gpio_direction_input(pdata->pin);
 164                master->write_bit = w1_gpio_write_bit_dir;
 165                master->set_pullup = w1_gpio_set_pullup;
 166        }
 167
 168        err = w1_add_master_device(master);
 169        if (err) {
 170                dev_err(&pdev->dev, "w1_add_master device failed\n");
 171                return err;
 172        }
 173
 174        if (pdata->enable_external_pullup)
 175                pdata->enable_external_pullup(1);
 176
 177        if (gpio_is_valid(pdata->ext_pullup_enable_pin))
 178                gpio_set_value(pdata->ext_pullup_enable_pin, 1);
 179
 180        platform_set_drvdata(pdev, master);
 181
 182        return 0;
 183}
 184
 185static int w1_gpio_remove(struct platform_device *pdev)
 186{
 187        struct w1_bus_master *master = platform_get_drvdata(pdev);
 188        struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
 189
 190        if (pdata->enable_external_pullup)
 191                pdata->enable_external_pullup(0);
 192
 193        if (gpio_is_valid(pdata->ext_pullup_enable_pin))
 194                gpio_set_value(pdata->ext_pullup_enable_pin, 0);
 195
 196        w1_remove_master_device(master);
 197
 198        return 0;
 199}
 200
 201static int __maybe_unused w1_gpio_suspend(struct device *dev)
 202{
 203        struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
 204
 205        if (pdata->enable_external_pullup)
 206                pdata->enable_external_pullup(0);
 207
 208        return 0;
 209}
 210
 211static int __maybe_unused w1_gpio_resume(struct device *dev)
 212{
 213        struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
 214
 215        if (pdata->enable_external_pullup)
 216                pdata->enable_external_pullup(1);
 217
 218        return 0;
 219}
 220
 221static SIMPLE_DEV_PM_OPS(w1_gpio_pm_ops, w1_gpio_suspend, w1_gpio_resume);
 222
 223static struct platform_driver w1_gpio_driver = {
 224        .driver = {
 225                .name   = "w1-gpio",
 226                .pm     = &w1_gpio_pm_ops,
 227                .of_match_table = of_match_ptr(w1_gpio_dt_ids),
 228        },
 229        .probe = w1_gpio_probe,
 230        .remove = w1_gpio_remove,
 231};
 232
 233module_platform_driver(w1_gpio_driver);
 234
 235MODULE_DESCRIPTION("GPIO w1 bus master driver");
 236MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
 237MODULE_LICENSE("GPL");
 238