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