diff options
author | Anantha Idapalapati <aidapalapati@nvidia.com> | 2010-12-29 13:15:11 +0530 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2011-01-02 20:06:40 -0800 |
commit | b345636320804a378bc748cb0c10e9e35517cb46 (patch) | |
tree | 9c44646e71184d5d182db1877162ae4cc1d21a8f /drivers/misc | |
parent | 3dba2bed8216623e281409788de8c7c322959421 (diff) |
[bt/rfkill]: make either RST/SHUTDOWN GPIO usage optional.
the current BCM4329 rfkill driver assumes usage of 2 GPIOs
known as RST and SHUTDOWN and the driver makes a particular
GPIO mandatory. Some of the platforms does not define both
GPIOs, instead a single either RST/SHUTDOWN GPIO is used to
setup the chip.
This change makes driver to consider any of the two GPIOs
as optional and use any of the RST/SHUTDOWN GPIOs.
Simultaneous usage of both GPIOs is also allowed.
Change-Id: Ib66ea350e78642082f639514ef7a9def6e460e28
Reviewed-on: http://git-master/r/14534
Reviewed-by: Anantha Idapalapati <aidapalapati@nvidia.com>
Tested-by: Anantha Idapalapati <aidapalapati@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/bcm4329_rfkill.c | 74 |
1 files changed, 42 insertions, 32 deletions
diff --git a/drivers/misc/bcm4329_rfkill.c b/drivers/misc/bcm4329_rfkill.c index eeb4047631f3..c266195a6db9 100644 --- a/drivers/misc/bcm4329_rfkill.c +++ b/drivers/misc/bcm4329_rfkill.c @@ -44,15 +44,19 @@ static struct bcm4329_rfkill_data *bcm4329_rfkill; static int bcm4329_bt_rfkill_set_power(void *data, bool blocked) { if (blocked) { - gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 0); - gpio_direction_output(bcm4329_rfkill->gpio_reset, 0); + if (bcm4329_rfkill->gpio_shutdown) + gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 0); + if (bcm4329_rfkill->gpio_reset) + gpio_direction_output(bcm4329_rfkill->gpio_reset, 0); if (bcm4329_rfkill->bt_32k_clk) clk_disable(bcm4329_rfkill->bt_32k_clk); } else { if (bcm4329_rfkill->bt_32k_clk) clk_enable(bcm4329_rfkill->bt_32k_clk); - gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 1); - gpio_direction_output(bcm4329_rfkill->gpio_reset, 1); + if (bcm4329_rfkill->gpio_shutdown) + gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 1); + if (bcm4329_rfkill->gpio_reset) + gpio_direction_output(bcm4329_rfkill->gpio_reset, 1); } return 0; @@ -76,42 +80,45 @@ static int bcm4329_rfkill_probe(struct platform_device *pdev) bcm4329_rfkill->bt_32k_clk = clk_get(&pdev->dev, "bcm4329_32k_clk"); if (IS_ERR(bcm4329_rfkill->bt_32k_clk)) { - pr_warn("can't find bcm4329_32k_clk. assuming clock to chip\n"); + pr_warn("%s: can't find bcm4329_32k_clk.\ + assuming 32k clock to chip\n", __func__); bcm4329_rfkill->bt_32k_clk = NULL; } res = platform_get_resource_byname(pdev, IORESOURCE_IO, "bcm4329_nreset_gpio"); - if (!res) { - pr_err("couldn't find reset gpio\n"); - goto free_bcm_32k_clk; + if (res) { + bcm4329_rfkill->gpio_reset = res->start; + tegra_gpio_enable(bcm4329_rfkill->gpio_reset); + ret = gpio_request(bcm4329_rfkill->gpio_reset, + "bcm4329_nreset_gpio"); + } else { + pr_warn("%s : can't find reset gpio.\n", __func__); + bcm4329_rfkill->gpio_reset = 0; } - bcm4329_rfkill->gpio_reset = res->start; - tegra_gpio_enable(bcm4329_rfkill->gpio_reset); - ret = gpio_request(bcm4329_rfkill->gpio_reset, - "bcm4329_nreset_gpio"); - if (unlikely(ret)) - goto free_bcm_32k_clk; res = platform_get_resource_byname(pdev, IORESOURCE_IO, "bcm4329_nshutdown_gpio"); - if (!res) { - pr_err("couldn't find shutdown gpio\n"); - gpio_free(bcm4329_rfkill->gpio_reset); - goto free_bcm_32k_clk; - } - tegra_gpio_enable(bcm4329_rfkill->gpio_shutdown); - ret = gpio_request(bcm4329_rfkill->gpio_shutdown, - "bcm4329_nshutdown_gpio"); - if (unlikely(ret)) { - gpio_free(bcm4329_rfkill->gpio_reset); - goto free_bcm_32k_clk; + if (res) { + bcm4329_rfkill->gpio_shutdown = res->start; + tegra_gpio_enable(bcm4329_rfkill->gpio_shutdown); + ret = gpio_request(bcm4329_rfkill->gpio_shutdown, + "bcm4329_nshutdown_gpio"); + } else { + pr_warn("%s : can't find shutdown gpio.\n", __func__); + bcm4329_rfkill->gpio_shutdown = 0; } + /* make sure at-least one of the GPIO is defined */ + if (!bcm4329_rfkill->gpio_reset && !bcm4329_rfkill->gpio_shutdown) + goto free_bcm_res; + if (bcm4329_rfkill->bt_32k_clk && enable) clk_enable(bcm4329_rfkill->bt_32k_clk); - gpio_direction_output(bcm4329_rfkill->gpio_shutdown, enable); - gpio_direction_output(bcm4329_rfkill->gpio_reset, enable); + if (bcm4329_rfkill->gpio_shutdown) + gpio_direction_output(bcm4329_rfkill->gpio_shutdown, enable); + if (bcm4329_rfkill->gpio_reset) + gpio_direction_output(bcm4329_rfkill->gpio_reset, enable); bt_rfkill = rfkill_alloc("bcm4329 Bluetooth", &pdev->dev, RFKILL_TYPE_BLUETOOTH, &bcm4329_bt_rfkill_ops, @@ -133,9 +140,10 @@ static int bcm4329_rfkill_probe(struct platform_device *pdev) return 0; free_bcm_res: - gpio_free(bcm4329_rfkill->gpio_shutdown); - gpio_free(bcm4329_rfkill->gpio_reset); -free_bcm_32k_clk: + if (bcm4329_rfkill->gpio_shutdown) + gpio_free(bcm4329_rfkill->gpio_shutdown); + if (bcm4329_rfkill->gpio_reset) + gpio_free(bcm4329_rfkill->gpio_reset); if (bcm4329_rfkill->bt_32k_clk && enable) clk_disable(bcm4329_rfkill->bt_32k_clk); if (bcm4329_rfkill->bt_32k_clk) @@ -152,8 +160,10 @@ static int bcm4329_rfkill_remove(struct platform_device *pdev) clk_put(bcm4329_rfkill->bt_32k_clk); rfkill_unregister(bt_rfkill); rfkill_destroy(bt_rfkill); - gpio_free(bcm4329_rfkill->gpio_shutdown); - gpio_free(bcm4329_rfkill->gpio_reset); + if (bcm4329_rfkill->gpio_shutdown) + gpio_free(bcm4329_rfkill->gpio_shutdown); + if (bcm4329_rfkill->gpio_reset) + gpio_free(bcm4329_rfkill->gpio_reset); kfree(bcm4329_rfkill); return 0; |