linux/net/rfkill/rfkill-regulator.c
<<
>>
Prefs
   1/*
   2 * rfkill-regulator.c - Regulator consumer driver for rfkill
   3 *
   4 * Copyright (C) 2009  Guiming Zhuo <gmzhuo@gmail.com>
   5 * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it>
   6 *
   7 * Implementation inspired by leds-regulator driver.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/err.h>
  17#include <linux/slab.h>
  18#include <linux/platform_device.h>
  19#include <linux/regulator/consumer.h>
  20#include <linux/rfkill.h>
  21#include <linux/rfkill-regulator.h>
  22
  23struct rfkill_regulator_data {
  24        struct rfkill *rf_kill;
  25        bool reg_enabled;
  26
  27        struct regulator *vcc;
  28};
  29
  30static int rfkill_regulator_set_block(void *data, bool blocked)
  31{
  32        struct rfkill_regulator_data *rfkill_data = data;
  33        int ret = 0;
  34
  35        pr_debug("%s: blocked: %d\n", __func__, blocked);
  36
  37        if (blocked) {
  38                if (rfkill_data->reg_enabled) {
  39                        regulator_disable(rfkill_data->vcc);
  40                        rfkill_data->reg_enabled = false;
  41                }
  42        } else {
  43                if (!rfkill_data->reg_enabled) {
  44                        ret = regulator_enable(rfkill_data->vcc);
  45                        if (!ret)
  46                                rfkill_data->reg_enabled = true;
  47                }
  48        }
  49
  50        pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__,
  51                regulator_is_enabled(rfkill_data->vcc));
  52
  53        return ret;
  54}
  55
  56static struct rfkill_ops rfkill_regulator_ops = {
  57        .set_block = rfkill_regulator_set_block,
  58};
  59
  60static int rfkill_regulator_probe(struct platform_device *pdev)
  61{
  62        struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
  63        struct rfkill_regulator_data *rfkill_data;
  64        struct regulator *vcc;
  65        struct rfkill *rf_kill;
  66        int ret = 0;
  67
  68        if (pdata == NULL) {
  69                dev_err(&pdev->dev, "no platform data\n");
  70                return -ENODEV;
  71        }
  72
  73        if (pdata->name == NULL || pdata->type == 0) {
  74                dev_err(&pdev->dev, "invalid name or type in platform data\n");
  75                return -EINVAL;
  76        }
  77
  78        vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
  79        if (IS_ERR(vcc)) {
  80                dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
  81                ret = PTR_ERR(vcc);
  82                goto out;
  83        }
  84
  85        rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL);
  86        if (rfkill_data == NULL) {
  87                ret = -ENOMEM;
  88                goto err_data_alloc;
  89        }
  90
  91        rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
  92                                pdata->type,
  93                                &rfkill_regulator_ops, rfkill_data);
  94        if (rf_kill == NULL) {
  95                ret = -ENOMEM;
  96                goto err_rfkill_alloc;
  97        }
  98
  99        if (regulator_is_enabled(vcc)) {
 100                dev_dbg(&pdev->dev, "Regulator already enabled\n");
 101                rfkill_data->reg_enabled = true;
 102        }
 103        rfkill_data->vcc = vcc;
 104        rfkill_data->rf_kill = rf_kill;
 105
 106        ret = rfkill_register(rf_kill);
 107        if (ret) {
 108                dev_err(&pdev->dev, "Cannot register rfkill device\n");
 109                goto err_rfkill_register;
 110        }
 111
 112        platform_set_drvdata(pdev, rfkill_data);
 113        dev_info(&pdev->dev, "%s initialized\n", pdata->name);
 114
 115        return 0;
 116
 117err_rfkill_register:
 118        rfkill_destroy(rf_kill);
 119err_rfkill_alloc:
 120        kfree(rfkill_data);
 121err_data_alloc:
 122        regulator_put(vcc);
 123out:
 124        return ret;
 125}
 126
 127static int rfkill_regulator_remove(struct platform_device *pdev)
 128{
 129        struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
 130        struct rfkill *rf_kill = rfkill_data->rf_kill;
 131
 132        rfkill_unregister(rf_kill);
 133        rfkill_destroy(rf_kill);
 134        regulator_put(rfkill_data->vcc);
 135        kfree(rfkill_data);
 136
 137        return 0;
 138}
 139
 140static struct platform_driver rfkill_regulator_driver = {
 141        .probe = rfkill_regulator_probe,
 142        .remove = rfkill_regulator_remove,
 143        .driver = {
 144                .name = "rfkill-regulator",
 145        },
 146};
 147
 148module_platform_driver(rfkill_regulator_driver);
 149
 150MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
 151MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
 152MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
 153MODULE_LICENSE("GPL");
 154MODULE_ALIAS("platform:rfkill-regulator");
 155