Skip to content

Commit 75d1167

Browse files
wensholtmann
authored andcommitted
Bluetooth: hci_bcm: Add support for regulator supplies
The Broadcom Bluetooth chips have two power inputs, VBAT and VDDIO. The former provides overall power for the chip, while the latter powers the I/O pins and buffers. Model these two as regulator supplies, and let the driver manage them in the same way as it does the clock supply. Tested-by: Ondrej Jirman <[email protected]> Signed-off-by: Chen-Yu Tsai <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 90bc07c commit 75d1167

File tree

1 file changed

+30
-9
lines changed

1 file changed

+30
-9
lines changed

drivers/bluetooth/hci_bcm.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/property.h>
3232
#include <linux/platform_data/x86/apple.h>
3333
#include <linux/platform_device.h>
34+
#include <linux/regulator/consumer.h>
3435
#include <linux/clk.h>
3536
#include <linux/gpio/consumer.h>
3637
#include <linux/tty.h>
@@ -53,6 +54,8 @@
5354

5455
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
5556

57+
#define BCM_NUM_SUPPLIES 2
58+
5659
/**
5760
* struct bcm_device - device driver resources
5861
* @serdev_hu: HCI UART controller struct
@@ -73,7 +76,8 @@
7376
* @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down")
7477
* @txco_clk: external reference frequency clock used by Bluetooth device
7578
* @lpo_clk: external LPO clock used by Bluetooth device
76-
* @clk_enabled: whether clocks are prepared and enabled
79+
* @supplies: VBAT and VDDIO supplies used by Bluetooth device
80+
* @res_enabled: whether clocks and supplies are prepared and enabled
7781
* @init_speed: default baudrate of Bluetooth device;
7882
* the host UART is initially set to this baudrate so that
7983
* it can configure the Bluetooth device for @oper_speed
@@ -105,7 +109,8 @@ struct bcm_device {
105109

106110
struct clk *txco_clk;
107111
struct clk *lpo_clk;
108-
bool clk_enabled;
112+
struct regulator_bulk_data supplies[BCM_NUM_SUPPLIES];
113+
bool res_enabled;
109114

110115
u32 init_speed;
111116
u32 oper_speed;
@@ -216,17 +221,21 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
216221
{
217222
int err;
218223

219-
if (powered && !dev->clk_enabled) {
224+
if (powered && !dev->res_enabled) {
225+
err = regulator_bulk_enable(BCM_NUM_SUPPLIES, dev->supplies);
226+
if (err)
227+
return err;
228+
220229
/* LPO clock needs to be 32.768 kHz */
221230
err = clk_set_rate(dev->lpo_clk, 32768);
222231
if (err) {
223232
dev_err(dev->dev, "Could not set LPO clock rate\n");
224-
return err;
233+
goto err_regulator_disable;
225234
}
226235

227236
err = clk_prepare_enable(dev->lpo_clk);
228237
if (err)
229-
return err;
238+
goto err_regulator_disable;
230239

231240
err = clk_prepare_enable(dev->txco_clk);
232241
if (err)
@@ -241,23 +250,27 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
241250
if (err)
242251
goto err_revert_shutdown;
243252

244-
if (!powered && dev->clk_enabled) {
253+
if (!powered && dev->res_enabled) {
245254
clk_disable_unprepare(dev->txco_clk);
246255
clk_disable_unprepare(dev->lpo_clk);
256+
regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies);
247257
}
248258

249-
dev->clk_enabled = powered;
259+
dev->res_enabled = powered;
250260

251261
return 0;
252262

253263
err_revert_shutdown:
254264
dev->set_shutdown(dev, !powered);
255265
err_txco_clk_disable:
256-
if (powered && !dev->clk_enabled)
266+
if (powered && !dev->res_enabled)
257267
clk_disable_unprepare(dev->txco_clk);
258268
err_lpo_clk_disable:
259-
if (powered && !dev->clk_enabled)
269+
if (powered && !dev->res_enabled)
260270
clk_disable_unprepare(dev->lpo_clk);
271+
err_regulator_disable:
272+
if (powered && !dev->res_enabled)
273+
regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies);
261274
return err;
262275
}
263276

@@ -936,6 +949,7 @@ static struct clk *bcm_get_txco(struct device *dev)
936949
static int bcm_get_resources(struct bcm_device *dev)
937950
{
938951
const struct dmi_system_id *dmi_id;
952+
int err;
939953

940954
dev->name = dev_name(dev->dev);
941955

@@ -978,6 +992,13 @@ static int bcm_get_resources(struct bcm_device *dev)
978992
dev->set_device_wakeup = bcm_gpio_set_device_wakeup;
979993
dev->set_shutdown = bcm_gpio_set_shutdown;
980994

995+
dev->supplies[0].supply = "vbat";
996+
dev->supplies[1].supply = "vddio";
997+
err = devm_regulator_bulk_get(dev->dev, BCM_NUM_SUPPLIES,
998+
dev->supplies);
999+
if (err)
1000+
return err;
1001+
9811002
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
9821003
if (dev->irq <= 0) {
9831004
struct gpio_desc *gpio;

0 commit comments

Comments
 (0)