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/pinctrl/consumer.h>
  20#include <linux/err.h>
  21#include <linux/of.h>
  22
  23#include "../w1.h"
  24#include "../w1_int.h"
  25
  26static void w1_gpio_write_bit_dir(void *data, u8 bit)
  27{
  28        struct w1_gpio_platform_data *pdata = data;
  29
  30        if (bit)
  31                gpio_direction_input(pdata->pin);
  32        else
  33                gpio_direction_output(pdata->pin, 0);
  34}
  35
  36static void w1_gpio_write_bit_val(void *data, u8 bit)
  37{
  38        struct w1_gpio_platform_data *pdata = data;
  39
  40        gpio_set_value(pdata->pin, bit);
  41}
  42
  43static u8 w1_gpio_read_bit(void *data)
  44{
  45        struct w1_gpio_platform_data *pdata = data;
  46
  47        return gpio_get_value(pdata->pin) ? 1 : 0;
  48}
  49
  50#if defined(CONFIG_OF)
  51static struct of_device_id w1_gpio_dt_ids[] = {
  52        { .compatible = "w1-gpio" },
  53        {}
  54};
  55MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
  56#endif
  57
  58static int w1_gpio_probe_dt(struct platform_device *pdev)
  59{
  60        struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
  61        struct device_node *np = pdev->dev.of_node;
  62
  63        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  64        if (!pdata)
  65                return -ENOMEM;
  66
  67        if (of_get_property(np, "linux,open-drain", NULL))
  68                pdata->is_open_drain = 1;
  69
  70        pdata->pin = of_get_gpio(np, 0);
  71        pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
  72        pdev->dev.platform_data = pdata;
  73
  74        return 0;
  75}
  76
  77static int w1_gpio_probe(struct platform_device *pdev)
  78{
  79        struct w1_bus_master *master;
  80        struct w1_gpio_platform_data *pdata;
  81        struct pinctrl *pinctrl;
  82        int err;
  83
  84        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
  85        if (IS_ERR(pinctrl))
  86                dev_warn(&pdev->dev, "unable to select pin group\n");
  87
  88        if (of_have_populated_dt()) {
  89                err = w1_gpio_probe_dt(pdev);
  90                if (err < 0) {
  91                        dev_err(&pdev->dev, "Failed to parse DT\n");
  92                        return err;
  93                }
  94        }
  95
  96        pdata = pdev->dev.platform_data;
  97
  98        if (!pdata) {
  99                dev_err(&pdev->dev, "No configuration data\n");
 100                return -ENXIO;
 101        }
 102
 103        master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
 104        if (!master) {
 105                dev_err(&pdev->dev, "Out of memory\n");
 106                return -ENOMEM;
 107        }
 108
 109        err = gpio_request(pdata->pin, "w1");
 110        if (err) {
 111                dev_err(&pdev->dev, "gpio_request (pin) failed\n");
 112                goto free_master;
 113        }
 114
 115        if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
 116                err = gpio_request_one(pdata->ext_pullup_enable_pin,
 117                                       GPIOF_INIT_LOW, "w1 pullup");
 118                if (err < 0) {
 119                        dev_err(&pdev->dev, "gpio_request_one "
 120                                        "(ext_pullup_enable_pin) failed\n");
 121                        goto free_gpio;
 122                }
 123        }
 124
 125        master->data = pdata;
 126        master->read_bit = w1_gpio_read_bit;
 127
 128        if (pdata->is_open_drain) {
 129                gpio_direction_output(pdata->pin, 1);
 130                master->write_bit = w1_gpio_write_bit_val;
 131        } else {
 132                gpio_direction_input(pdata->pin);
 133                master->write_bit = w1_gpio_write_bit_dir;
 134        }
 135
 136        err = w1_add_master_device(master);
 137        if (err) {
 138                dev_err(&pdev->dev, "w1_add_master device failed\n");
 139                goto free_gpio_ext_pu;
 140        }
 141
 142        if (pdata->enable_external_pullup)
 143                pdata->enable_external_pullup(1);
 144
 145        if (gpio_is_valid(pdata->ext_pullup_enable_pin))
 146                gpio_set_value(pdata->ext_pullup_enable_pin, 1);
 147
 148        platform_set_drvdata(pdev, master);
 149
 150        return 0;
 151
 152 free_gpio_ext_pu:
 153        if (gpio_is_valid(pdata->ext_pullup_enable_pin))
 154                gpio_free(pdata->ext_pullup_enable_pin);
 155 free_gpio:
 156        gpio_free(pdata->pin);
 157 free_master:
 158        kfree(master);
 159
 160        return err;
 161}
 162
 163static int w1_gpio_remove(struct platform_device *pdev)
 164{
 165        struct w1_bus_master *master = platform_get_drvdata(pdev);
 166        struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
 167
 168        if (pdata->enable_external_pullup)
 169                pdata->enable_external_pullup(0);
 170
 171        if (gpio_is_valid(pdata->ext_pullup_enable_pin))
 172                gpio_set_value(pdata->ext_pullup_enable_pin, 0);
 173
 174        w1_remove_master_device(master);
 175        gpio_free(pdata->pin);
 176        kfree(master);
 177
 178        return 0;
 179}
 180
 181#ifdef CONFIG_PM
 182
 183static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 184{
 185        struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
 186
 187        if (pdata->enable_external_pullup)
 188                pdata->enable_external_pullup(0);
 189
 190        return 0;
 191}
 192
 193static int w1_gpio_resume(struct platform_device *pdev)
 194{
 195        struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
 196
 197        if (pdata->enable_external_pullup)
 198                pdata->enable_external_pullup(1);
 199
 200        return 0;
 201}
 202
 203#else
 204#define w1_gpio_suspend NULL
 205#define w1_gpio_resume  NULL
 206#endif
 207
 208static struct platform_driver w1_gpio_driver = {
 209        .driver = {
 210                .name   = "w1-gpio",
 211                .owner  = THIS_MODULE,
 212                .of_match_table = of_match_ptr(w1_gpio_dt_ids),
 213        },
 214        .probe = w1_gpio_probe,
 215        .remove = w1_gpio_remove,
 216        .suspend = w1_gpio_suspend,
 217        .resume = w1_gpio_resume,
 218};
 219
 220module_platform_driver(w1_gpio_driver);
 221
 222MODULE_DESCRIPTION("GPIO w1 bus master driver");
 223MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
 224MODULE_LICENSE("GPL");
 225
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.