From: Xinming Hu <[email protected]>
Platform device and driver provide easy way to
interact with device-tree-enabled system.
This patch registers platform driver and reorganise
existing device tree specific code.
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Add NULL check for 'btmrvl_plt_dev'
---
Documentation/devicetree/bindings/btmrvl.txt | 8 ++--
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/btmrvl_drv.h | 16 ++++++++
drivers/bluetooth/btmrvl_main.c | 8 +++-
drivers/bluetooth/btmrvl_platform.c | 60 ++++++++++++++++++++++++++++
5 files changed, 88 insertions(+), 5 deletions(-)
create mode 100644 drivers/bluetooth/btmrvl_platform.c
diff --git a/Documentation/devicetree/bindings/btmrvl.txt b/Documentation/devicetree/bindings/btmrvl.txt
index 58f964b..25b804b 100644
--- a/Documentation/devicetree/bindings/btmrvl.txt
+++ b/Documentation/devicetree/bindings/btmrvl.txt
@@ -3,7 +3,7 @@ btmrvl
Required properties:
- - compatible : must be "btmrvl,cfgdata"
+ - compatible : must be "marvell,btmrvl"
Optional properties:
@@ -15,11 +15,11 @@ Optional properties:
Example:
-GPIO pin 13 is configured as a wakeup source and GAP is set to 100 msecs
-in below example.
+GPIO pin 13 and gap 100ms are configured for host wakeup, calibration
+data is also available in below example.
btmrvl {
- compatible = "btmrvl,cfgdata";
+ compatible = "marvell,btmrvl";
btmrvl,cal-data = /bits/ 8 <
0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 07c9cf3..9bc3828 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_BT_RTL) += btrtl.o
obj-$(CONFIG_BT_QCA) += btqca.o
btmrvl-y := btmrvl_main.o
+btmrvl-y += btmrvl_platform.o
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
hci_uart-y := hci_ldisc.o
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 0590473..de6309b 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -22,8 +22,22 @@
#include <linux/kthread.h>
#include <linux/bitops.h>
#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <net/bluetooth/bluetooth.h>
+extern struct platform_device *btmrvl_plt_dev;
+
#define BTM_HEADER_LEN 4
#define BTM_UPLD_SIZE 2312
@@ -174,6 +188,8 @@ int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv);
int btmrvl_enable_hs(struct btmrvl_private *priv);
void btmrvl_firmware_dump(struct btmrvl_private *priv);
+int btmrvl_platform_drv_init(void);
+void btmrvl_platform_drv_exit(void);
#ifdef CONFIG_DEBUG_FS
void btmrvl_debugfs_init(struct hci_dev *hdev);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index f25a825..34a0b61 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -514,7 +514,9 @@ static int btmrvl_check_device_tree(struct btmrvl_private *priv)
int ret;
u32 val;
- for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") {
+ dt_node = btmrvl_plt_dev ?
+ btmrvl_plt_dev->dev.of_node : NULL;
+ if (dt_node) {
ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val);
if (!ret)
priv->btmrvl_dev.gpio_gap = val;
@@ -733,6 +735,8 @@ struct btmrvl_private *btmrvl_add_card(void *card)
goto err_adapter;
}
+ btmrvl_platform_drv_init();
+
btmrvl_init_adapter(priv);
BT_DBG("Starting kthread...");
@@ -776,6 +780,8 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
btmrvl_debugfs_remove(hdev);
#endif
+ btmrvl_platform_drv_exit();
+
hci_unregister_dev(hdev);
hci_free_dev(hdev);
diff --git a/drivers/bluetooth/btmrvl_platform.c b/drivers/bluetooth/btmrvl_platform.c
new file mode 100644
index 0000000..4e91d27
--- /dev/null
+++ b/drivers/bluetooth/btmrvl_platform.c
@@ -0,0 +1,60 @@
+/* Marvell Bluetooth driver: platform specific driver
+ *
+ * Copyright (C) 2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "btmrvl_drv.h"
+
+struct platform_device *btmrvl_plt_dev;
+
+static int btmrvl_plt_probe(struct platform_device *pdev)
+{
+ btmrvl_plt_dev = pdev;
+ return 0;
+}
+
+static int btmrvl_plt_remove(struct platform_device *pdev)
+{
+ btmrvl_plt_dev = NULL;
+ return 0;
+}
+
+static const struct of_device_id btmrvl_dt_match[] = {
+ {
+ .compatible = "marvell,btmrvl",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, btmrvl_dt_match);
+
+static struct platform_driver btmrvl_platform_driver = {
+ .probe = btmrvl_plt_probe,
+ .remove = btmrvl_plt_remove,
+ .driver = {
+ .name = "btmrvl_plt",
+ .of_match_table = btmrvl_dt_match,
+ }
+};
+
+int btmrvl_platform_drv_init(void)
+{
+ return platform_driver_register(&btmrvl_platform_driver);
+}
+
+void btmrvl_platform_drv_exit(void)
+{
+ platform_driver_unregister(&btmrvl_platform_driver);
+}
--
1.8.1.4
Hi Rob,
> From: Rob Herring [mailto:[email protected]]
> Sent: Tuesday, February 09, 2016 3:35 AM
> To: Amitkumar Karwar
> Cc: [email protected]; Nishant Sarmukadam;
> [email protected]; [email protected]; linux-
> [email protected]; Xinming Hu
> Subject: Re: [PATCH v3 1/2] bluetooth: btmrvl: register platform
> specific driver
>
> On Mon, Feb 08, 2016 at 02:27:10AM -0800, Amitkumar Karwar wrote:
> > From: Xinming Hu <[email protected]>
> >
> > Platform device and driver provide easy way to interact with
> > device-tree-enabled system.
> >
> > This patch registers platform driver and reorganise existing device
> > tree specific code.
> >
> > Signed-off-by: Xinming Hu <[email protected]>
> > Signed-off-by: Amitkumar Karwar <[email protected]>
> > ---
> > v3: Add NULL check for 'btmrvl_plt_dev'
> > ---
> > Documentation/devicetree/bindings/btmrvl.txt | 8 ++--
>
> This needs to move somewhere else.
>
> > drivers/bluetooth/Makefile | 1 +
> > drivers/bluetooth/btmrvl_drv.h | 16 ++++++++
> > drivers/bluetooth/btmrvl_main.c | 8 +++-
> > drivers/bluetooth/btmrvl_platform.c | 60
> ++++++++++++++++++++++++++++
> > 5 files changed, 88 insertions(+), 5 deletions(-) create mode 100644
> > drivers/bluetooth/btmrvl_platform.c
> >
> > diff --git a/Documentation/devicetree/bindings/btmrvl.txt
> > b/Documentation/devicetree/bindings/btmrvl.txt
> > index 58f964b..25b804b 100644
> > --- a/Documentation/devicetree/bindings/btmrvl.txt
> > +++ b/Documentation/devicetree/bindings/btmrvl.txt
> > @@ -3,7 +3,7 @@ btmrvl
> >
> > Required properties:
> >
> > - - compatible : must be "btmrvl,cfgdata"
> > + - compatible : must be "marvell,btmrvl"
>
> While the new name is less worse than the old one, I'm not inclined to
> take any changes for this binding because it is problematic. Given you
> don't care this is an incompatible change, then the binding can be
> completely redone.
>
> It should reflect the actual chip name (e.g. sd8???) and be a child node
> of its connection to the host (a UART). See UART slave discussions.
>
> >
I have corrected the name as per your inputs for WLAN driver and submitted updated version.
The connection here is not via UART. It's through SDIO bus. We will add it as a child node of MMC in DTSI config file.
Let me know if you have any further comments for the improvements.
Regards,
Amitkumar
On Mon, Feb 08, 2016 at 02:27:10AM -0800, Amitkumar Karwar wrote:
> From: Xinming Hu <[email protected]>
>
> Platform device and driver provide easy way to
> interact with device-tree-enabled system.
>
> This patch registers platform driver and reorganise
> existing device tree specific code.
>
> Signed-off-by: Xinming Hu <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> ---
> v3: Add NULL check for 'btmrvl_plt_dev'
> ---
> Documentation/devicetree/bindings/btmrvl.txt | 8 ++--
This needs to move somewhere else.
> drivers/bluetooth/Makefile | 1 +
> drivers/bluetooth/btmrvl_drv.h | 16 ++++++++
> drivers/bluetooth/btmrvl_main.c | 8 +++-
> drivers/bluetooth/btmrvl_platform.c | 60 ++++++++++++++++++++++++++++
> 5 files changed, 88 insertions(+), 5 deletions(-)
> create mode 100644 drivers/bluetooth/btmrvl_platform.c
>
> diff --git a/Documentation/devicetree/bindings/btmrvl.txt b/Documentation/devicetree/bindings/btmrvl.txt
> index 58f964b..25b804b 100644
> --- a/Documentation/devicetree/bindings/btmrvl.txt
> +++ b/Documentation/devicetree/bindings/btmrvl.txt
> @@ -3,7 +3,7 @@ btmrvl
>
> Required properties:
>
> - - compatible : must be "btmrvl,cfgdata"
> + - compatible : must be "marvell,btmrvl"
While the new name is less worse than the old one, I'm not inclined to
take any changes for this binding because it is problematic. Given you
don't care this is an incompatible change, then the binding can be
completely redone.
It should reflect the actual chip name (e.g. sd8???) and be a child node
of its connection to the host (a UART). See UART slave discussions.
>
> Optional properties:
>
> @@ -15,11 +15,11 @@ Optional properties:
>
> Example:
>
> -GPIO pin 13 is configured as a wakeup source and GAP is set to 100 msecs
> -in below example.
> +GPIO pin 13 and gap 100ms are configured for host wakeup, calibration
> +data is also available in below example.
From: Xinming Hu <[email protected]>
This patch implements a framework for board specific wakeup.
driver parse irq/gpio number from device tree, corresponding
resources will be allocated, and used for host suspend/resume.
Device tree binding file is also updated in the patch.
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v2: Fixed build error reported by kbuild test robot
drivers/bluetooth/btmrvl_platform.c:141:22: error:
'btmrvl_plt_pm_ops' undeclared here (not in a function)
---
Documentation/devicetree/bindings/btmrvl.txt | 17 ++++-
drivers/bluetooth/btmrvl_platform.c | 95 ++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/btmrvl.txt b/Documentation/devicetree/bindings/btmrvl.txt
index 25b804b..887c7ff 100644
--- a/Documentation/devicetree/bindings/btmrvl.txt
+++ b/Documentation/devicetree/bindings/btmrvl.txt
@@ -12,11 +12,19 @@ Optional properties:
- btmrvl,gpio-gap : gpio and gap (in msecs) combination to be
configured.
+ - interrupt-parent: phandle of the parent interrupt controller
+ - interrupts : interrupt number to the cpu
+ - gpios: specify GPIO respectively. gpio here is board specific pin.
+ while above gpio-gap represents the device side pin used to
+ wakeup host.
+ - pinctrl-names : a pinctrl state named "default" must be defined
+ - pinctrl-0 : pin control group to be used for this controller
Example:
-GPIO pin 13 and gap 100ms are configured for host wakeup, calibration
-data is also available in below example.
+GPIO pin 119 and gap 100ms are configured for host wakeup,
+pin 13 is configured so that firmware can wakeup host using this device side
+pin, calibration data is also available in below example.
btmrvl {
compatible = "marvell,btmrvl";
@@ -26,4 +34,9 @@ btmrvl {
0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0xf0 0x00>;
btmrvl,gpio-gap = <0x0d64>;
+ interrupt-parent = <&pio>;
+ interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
+ gpios = <&pio 119 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wake_pins>;
};
diff --git a/drivers/bluetooth/btmrvl_platform.c b/drivers/bluetooth/btmrvl_platform.c
index 4e91d27..6f64922 100644
--- a/drivers/bluetooth/btmrvl_platform.c
+++ b/drivers/bluetooth/btmrvl_platform.c
@@ -19,9 +19,63 @@
struct platform_device *btmrvl_plt_dev;
+struct btmrvl_wake_dev {
+ struct device *dev;
+ int irq_bt;
+ bool wake_by_bt;
+};
+
+static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
+{
+ struct btmrvl_wake_dev *ctx = priv;
+
+ if (ctx->irq_bt >= 0) {
+ ctx->wake_by_bt = true;
+ disable_irq_nosync(ctx->irq_bt);
+ }
+
+ return IRQ_HANDLED;
+}
+
static int btmrvl_plt_probe(struct platform_device *pdev)
{
+ int ret;
+ struct btmrvl_wake_dev *ctx;
+ int gpio;
+
btmrvl_plt_dev = pdev;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->dev = &pdev->dev;
+ ctx->irq_bt = platform_get_irq(pdev, 0);
+ if (ctx->irq_bt < 0)
+ dev_err(&pdev->dev, "Failed to get irq_bt\n");
+
+ gpio = of_get_gpio(pdev->dev.of_node, 0);
+ if (gpio_is_valid(gpio))
+ gpio_direction_input(gpio);
+ else
+ dev_err(&pdev->dev, "gpio bt is invalid\n");
+
+ if (ctx->irq_bt >= 0) {
+ ret = devm_request_irq(&pdev->dev, ctx->irq_bt,
+ btmrvl_wake_irq_bt,
+ IRQF_TRIGGER_LOW,
+ "bt_wake", ctx);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to request irq_bt %d (%d)\n",
+ ctx->irq_bt, ret);
+ return -EINVAL;
+ }
+ disable_irq(ctx->irq_bt);
+ }
+
+ platform_set_drvdata(pdev, ctx);
+
return 0;
}
@@ -31,6 +85,44 @@ static int btmrvl_plt_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int btmrvl_plt_suspend(struct device *dev)
+{
+ struct btmrvl_wake_dev *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ if (ctx->irq_bt >= 0) {
+ ctx->wake_by_bt = false;
+ enable_irq(ctx->irq_bt);
+ ret = enable_irq_wake(ctx->irq_bt);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int btmrvl_plt_resume(struct device *dev)
+{
+ struct btmrvl_wake_dev *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ if (ctx->irq_bt >= 0) {
+ ret = disable_irq_wake(ctx->irq_bt);
+ if (!ctx->wake_by_bt)
+ disable_irq(ctx->irq_bt);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops btmrvl_plt_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(btmrvl_plt_suspend, btmrvl_plt_resume)
+};
+#endif /* CONFIG_PM_SLEEP */
+
static const struct of_device_id btmrvl_dt_match[] = {
{
.compatible = "marvell,btmrvl",
@@ -46,6 +138,9 @@ static struct platform_driver btmrvl_platform_driver = {
.driver = {
.name = "btmrvl_plt",
.of_match_table = btmrvl_dt_match,
+#ifdef CONFIG_PM_SLEEP
+ .pm = &btmrvl_plt_pm_ops,
+#endif
}
};
--
1.8.1.4