h1940-bluetooth.c (3054B)
1// SPDX-License-Identifier: GPL-1.0+ 2// 3// Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org> 4// 5// S3C2410 bluetooth "driver" 6 7#include <linux/module.h> 8#include <linux/platform_device.h> 9#include <linux/delay.h> 10#include <linux/string.h> 11#include <linux/ctype.h> 12#include <linux/leds.h> 13#include <linux/gpio.h> 14#include <linux/rfkill.h> 15 16#include "gpio-cfg.h" 17#include "regs-gpio.h" 18#include "gpio-samsung.h" 19 20#include "h1940.h" 21 22#define DRV_NAME "h1940-bt" 23 24/* Bluetooth control */ 25static void h1940bt_enable(int on) 26{ 27 if (on) { 28 /* Power on the chip */ 29 gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 1); 30 /* Reset the chip */ 31 mdelay(10); 32 33 gpio_set_value(S3C2410_GPH(1), 1); 34 mdelay(10); 35 gpio_set_value(S3C2410_GPH(1), 0); 36 37 h1940_led_blink_set(NULL, GPIO_LED_BLINK, NULL, NULL); 38 } 39 else { 40 gpio_set_value(S3C2410_GPH(1), 1); 41 mdelay(10); 42 gpio_set_value(S3C2410_GPH(1), 0); 43 mdelay(10); 44 gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 0); 45 46 h1940_led_blink_set(NULL, GPIO_LED_NO_BLINK_LOW, NULL, NULL); 47 } 48} 49 50static int h1940bt_set_block(void *data, bool blocked) 51{ 52 h1940bt_enable(!blocked); 53 return 0; 54} 55 56static const struct rfkill_ops h1940bt_rfkill_ops = { 57 .set_block = h1940bt_set_block, 58}; 59 60static int h1940bt_probe(struct platform_device *pdev) 61{ 62 struct rfkill *rfk; 63 int ret = 0; 64 65 ret = gpio_request(S3C2410_GPH(1), dev_name(&pdev->dev)); 66 if (ret) { 67 dev_err(&pdev->dev, "could not get GPH1\n"); 68 return ret; 69 } 70 71 ret = gpio_request(H1940_LATCH_BLUETOOTH_POWER, dev_name(&pdev->dev)); 72 if (ret) { 73 gpio_free(S3C2410_GPH(1)); 74 dev_err(&pdev->dev, "could not get BT_POWER\n"); 75 return ret; 76 } 77 78 /* Configures BT serial port GPIOs */ 79 s3c_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0); 80 s3c_gpio_setpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE); 81 s3c_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT); 82 s3c_gpio_setpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE); 83 s3c_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0); 84 s3c_gpio_setpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE); 85 s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0); 86 s3c_gpio_setpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE); 87 88 rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH, 89 &h1940bt_rfkill_ops, NULL); 90 if (!rfk) { 91 ret = -ENOMEM; 92 goto err_rfk_alloc; 93 } 94 95 ret = rfkill_register(rfk); 96 if (ret) 97 goto err_rfkill; 98 99 platform_set_drvdata(pdev, rfk); 100 101 return 0; 102 103err_rfkill: 104 rfkill_destroy(rfk); 105err_rfk_alloc: 106 return ret; 107} 108 109static int h1940bt_remove(struct platform_device *pdev) 110{ 111 struct rfkill *rfk = platform_get_drvdata(pdev); 112 113 platform_set_drvdata(pdev, NULL); 114 gpio_free(S3C2410_GPH(1)); 115 116 if (rfk) { 117 rfkill_unregister(rfk); 118 rfkill_destroy(rfk); 119 } 120 rfk = NULL; 121 122 h1940bt_enable(0); 123 124 return 0; 125} 126 127 128static struct platform_driver h1940bt_driver = { 129 .driver = { 130 .name = DRV_NAME, 131 }, 132 .probe = h1940bt_probe, 133 .remove = h1940bt_remove, 134}; 135 136module_platform_driver(h1940bt_driver); 137 138MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); 139MODULE_DESCRIPTION("Driver for the iPAQ H1940 bluetooth chip"); 140MODULE_LICENSE("GPL");