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
  34        pr_debug("%s: blocked: %d\n", __func__, blocked);
  35
  36        if (blocked) {
  37                if (rfkill_data->reg_enabled) {
  38                        regulator_disable(rfkill_data->vcc);
  39                        rfkill_data->reg_enabled = false;
  40                }
  41        } else {
  42                if (!rfkill_data->reg_enabled) {
  43                        regulator_enable(rfkill_data->vcc);
  44                        rfkill_data->reg_enabled = true;
  45                }
  46        }
  47
  48        pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__,
  49                regulator_is_enabled(rfkill_data->vcc));
  50
  51        return 0;
  52}
  53
  54struct rfkill_ops rfkill_regulator_ops = {
  55        .set_block = rfkill_regulator_set_block,
  56};
  57
  58static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
  59{
  60        struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
  61        struct rfkill_regulator_data *rfkill_data;
  62        struct regulator *vcc;
  63        struct rfkill *rf_kill;
  64        int ret = 0;
  65
  66        if (pdata == NULL) {
  67                dev_err(&pdev->dev, "no platform data\n");
  68                return -ENODEV;
  69        }
  70
  71        if (pdata->name == NULL || pdata->type == 0) {
  72                dev_err(&pdev->dev, "invalid name or type in platform data\n");
  73                return -EINVAL;
  74        }
  75
  76        vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
  77        if (IS_ERR(vcc)) {
  78                dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
  79                ret = PTR_ERR(vcc);
  80                goto out;
  81        }
  82
  83        rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL);
  84        if (rfkill_data == NULL) {
  85                ret = -ENOMEM;
  86                goto err_data_alloc;
  87        }
  88
  89        rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
  90                                pdata->type,
  91                                &rfkill_regulator_ops, rfkill_data);
  92        if (rf_kill == NULL) {
  93                ret = -ENOMEM;
  94                goto err_rfkill_alloc;
  95        }
  96
  97        if (regulator_is_enabled(vcc)) {
  98                dev_dbg(&pdev->dev, "Regulator already enabled\n");
  99                rfkill_data->reg_enabled = true;
 100        }
 101        rfkill_data->vcc = vcc;
 102        rfkill_data->rf_kill = rf_kill;
 103
 104        ret = rfkill_register(rf_kill);
 105        if (ret) {
 106                dev_err(&pdev->dev, "Cannot register rfkill device\n");
 107                goto err_rfkill_register;
 108        }
 109
 110        platform_set_drvdata(pdev, rfkill_data);
 111        dev_info(&pdev->dev, "%s initialized\n", pdata->name);
 112
 113        return 0;
 114
 115err_rfkill_register:
 116        rfkill_destroy(rf_kill);
 117err_rfkill_alloc:
 118        kfree(rfkill_data);
 119err_data_alloc:
 120        regulator_put(vcc);
 121out:
 122        return ret;
 123}
 124
 125static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
 126{
 127        struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
 128        struct rfkill *rf_kill = rfkill_data->rf_kill;
 129
 130        rfkill_unregister(rf_kill);
 131        rfkill_destroy(rf_kill);
 132        regulator_put(rfkill_data->vcc);
 133        kfree(rfkill_data);
 134
 135        return 0;
 136}
 137
 138static struct platform_driver rfkill_regulator_driver = {
 139        .probe = rfkill_regulator_probe,
 140        .remove = __devexit_p(rfkill_regulator_remove),
 141        .driver = {
 142                .name = "rfkill-regulator",
 143                .owner = THIS_MODULE,
 144        },
 145};
 146
 147module_platform_driver(rfkill_regulator_driver);
 148
 149MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
 150MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
 151MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
 152MODULE_LICENSE("GPL");
 153MODULE_ALIAS("platform:rfkill-regulator");
 154
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.