linux/arch/arm/mach-pxa/tosa-bt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Bluetooth built-in chip control
   4 *
   5 * Copyright (c) 2008 Dmitry Baryshkov
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/platform_device.h>
  11#include <linux/gpio.h>
  12#include <linux/delay.h>
  13#include <linux/rfkill.h>
  14
  15#include "tosa_bt.h"
  16
  17static void tosa_bt_on(struct tosa_bt_data *data)
  18{
  19        gpio_set_value(data->gpio_reset, 0);
  20        gpio_set_value(data->gpio_pwr, 1);
  21        gpio_set_value(data->gpio_reset, 1);
  22        mdelay(20);
  23        gpio_set_value(data->gpio_reset, 0);
  24}
  25
  26static void tosa_bt_off(struct tosa_bt_data *data)
  27{
  28        gpio_set_value(data->gpio_reset, 1);
  29        mdelay(10);
  30        gpio_set_value(data->gpio_pwr, 0);
  31        gpio_set_value(data->gpio_reset, 0);
  32}
  33
  34static int tosa_bt_set_block(void *data, bool blocked)
  35{
  36        pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
  37
  38        if (!blocked) {
  39                pr_info("TOSA_BT: going ON\n");
  40                tosa_bt_on(data);
  41        } else {
  42                pr_info("TOSA_BT: going OFF\n");
  43                tosa_bt_off(data);
  44        }
  45
  46        return 0;
  47}
  48
  49static const struct rfkill_ops tosa_bt_rfkill_ops = {
  50        .set_block = tosa_bt_set_block,
  51};
  52
  53static int tosa_bt_probe(struct platform_device *dev)
  54{
  55        int rc;
  56        struct rfkill *rfk;
  57
  58        struct tosa_bt_data *data = dev->dev.platform_data;
  59
  60        rc = gpio_request(data->gpio_reset, "Bluetooth reset");
  61        if (rc)
  62                goto err_reset;
  63        rc = gpio_direction_output(data->gpio_reset, 0);
  64        if (rc)
  65                goto err_reset_dir;
  66        rc = gpio_request(data->gpio_pwr, "Bluetooth power");
  67        if (rc)
  68                goto err_pwr;
  69        rc = gpio_direction_output(data->gpio_pwr, 0);
  70        if (rc)
  71                goto err_pwr_dir;
  72
  73        rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
  74                           &tosa_bt_rfkill_ops, data);
  75        if (!rfk) {
  76                rc = -ENOMEM;
  77                goto err_rfk_alloc;
  78        }
  79
  80        rc = rfkill_register(rfk);
  81        if (rc)
  82                goto err_rfkill;
  83
  84        platform_set_drvdata(dev, rfk);
  85
  86        return 0;
  87
  88err_rfkill:
  89        rfkill_destroy(rfk);
  90err_rfk_alloc:
  91        tosa_bt_off(data);
  92err_pwr_dir:
  93        gpio_free(data->gpio_pwr);
  94err_pwr:
  95err_reset_dir:
  96        gpio_free(data->gpio_reset);
  97err_reset:
  98        return rc;
  99}
 100
 101static int tosa_bt_remove(struct platform_device *dev)
 102{
 103        struct tosa_bt_data *data = dev->dev.platform_data;
 104        struct rfkill *rfk = platform_get_drvdata(dev);
 105
 106        platform_set_drvdata(dev, NULL);
 107
 108        if (rfk) {
 109                rfkill_unregister(rfk);
 110                rfkill_destroy(rfk);
 111        }
 112        rfk = NULL;
 113
 114        tosa_bt_off(data);
 115
 116        gpio_free(data->gpio_pwr);
 117        gpio_free(data->gpio_reset);
 118
 119        return 0;
 120}
 121
 122static struct platform_driver tosa_bt_driver = {
 123        .probe = tosa_bt_probe,
 124        .remove = tosa_bt_remove,
 125
 126        .driver = {
 127                .name = "tosa-bt",
 128        },
 129};
 130module_platform_driver(tosa_bt_driver);
 131
 132MODULE_LICENSE("GPL");
 133MODULE_AUTHOR("Dmitry Baryshkov");
 134MODULE_DESCRIPTION("Bluetooth built-in chip control");
 135