Received: by 10.213.65.68 with SMTP id h4csp296099imn; Tue, 20 Mar 2018 03:55:52 -0700 (PDT) X-Google-Smtp-Source: AG47ELtdw926+a8cKaL6AVpfH7Q4I0kK3fTqHtOAt02W0x4YltAB/8wUEev/njr1r7aehTnaH0j7 X-Received: by 10.99.146.30 with SMTP id o30mr3771577pgd.115.1521543352832; Tue, 20 Mar 2018 03:55:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521543352; cv=none; d=google.com; s=arc-20160816; b=JNYY274tK5B6RUyR7r+OERtkf9g+fx9Lr3y19Dcf1x5boDaSvwvwMZIY1wpox5q5Y2 I+/7xYBcTWmtwfymeBoRRLxS3vDvFHLPCoovMlVfMFHXyFcqfEB3EIFvI5ddB0grlD4d 5R7OiQIZIBPsfxeoE+WM4IB7SWsYVcJNAz+mTwESQ4GAvBVU4QHkAJM3352LKGpoMz5j xqqoepYY31ZrE4qubaqqBaKyeK4PQSXbCcdNW0N1SCc7P1NDuQTCSm2rLPCqxQj0bWTM CZHxCnLEozZFUbnGIvm3rFquijzuxJx4phPY19nx6tUwQM92lsRkUXRpE2t3xK4kYlZd Pq7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :organization:references:in-reply-to:date:cc:to:from:subject :message-id:arc-authentication-results; bh=72nvMSMN4eLOK4QI9hPaPXMVvn6A6gC4JNHHc8prscM=; b=dqVPNmr4SWmsOIG7nvev0Fww2BRJ8lUfFtvcwL7qfn5Z+Z4CNSjzbWcJujY3PTa8J6 p0pvu8bkEV9bI0bTyT8Rp9hT9gXZmeGHEdDjSSTB0hW3yUNUfnBpgSQoV+bL3akDhm0l jszVjlnda/dq1G3U5Yr8E0o3aF2Gbi5xgtTZcj0QzSWr7KFcisp19/ytzsEyW5Tv2KbB FLuAYGLx2RCrC90fvXvubLmpw8AN/fy9yqOPGdybRCunnBzIDMICb75Og8zTnlDjY33l sRN3Roya+YVa128X5hIxR//0cuQRtfQefGLK3bEo6t8M452zCnCRTGl1/gZvRRCLW/Jf Fu7Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h127si1034008pgc.238.2018.03.20.03.55.38; Tue, 20 Mar 2018 03:55:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752769AbeCTKy1 (ORCPT + 99 others); Tue, 20 Mar 2018 06:54:27 -0400 Received: from mga17.intel.com ([192.55.52.151]:47726 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752161AbeCTKyX (ORCPT ); Tue, 20 Mar 2018 06:54:23 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Mar 2018 03:54:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,335,1517904000"; d="scan'208";a="26002902" Received: from smile.fi.intel.com (HELO smile) ([10.237.72.86]) by fmsmga008.fm.intel.com with ESMTP; 20 Mar 2018 03:54:19 -0700 Message-ID: <1521543258.23017.61.camel@linux.intel.com> Subject: Re: [PATCH v5 3/3] Bluetooth: hci_qca: Add serdev support From: Andy Shevchenko To: Thierry Escande , Rob Herring , Andy Gross , Marcel Holtmann , Johan Hedberg , David Brown , Mark Rutland Cc: Loic Poulain , Bjorn Andersson , Srinivas Kandagatla , linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Date: Tue, 20 Mar 2018 12:54:18 +0200 In-Reply-To: <20180320032331.29865-4-thierry.escande@linaro.org> References: <20180320032331.29865-1-thierry.escande@linaro.org> <20180320032331.29865-4-thierry.escande@linaro.org> Organization: Intel Finland Oy Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.26.5-1+b1 Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, 2018-03-20 at 04:23 +0100, Thierry Escande wrote: > Add support for Qualcomm serial slave devices. Probe the serial > device, > retrieve its maximum speed and register a new hci uart device. > Tell me, if I'm not mistaken, I gave you my tag for this. If no, FWIW, Reviewed-by: Andy Shevchenko > Signed-off-by: Thierry Escande > --- > > v5: > - Use gpio new name 'enable' > > v4: > - Rename divclk4 as susclk (its name in the bt chip) > - Use gpiod_set_value_cansleep() > - Replace #include with > - Restore dependency on BT_HCIUART > > v3: > - Remove redundant call to gpiod_set_value() after devm_gpiod_get() > - Check returned values for clk_set_rate() and clk_prepare_enable() > - Use clk_disable_unprepare() > > v2: > - Fix author email > > drivers/bluetooth/Kconfig | 1 + > drivers/bluetooth/hci_qca.c | 109 > +++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 108 insertions(+), 2 deletions(-) > > diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig > index 07e55cd8f8c8..e0f1a6609b68 100644 > --- a/drivers/bluetooth/Kconfig > +++ b/drivers/bluetooth/Kconfig > @@ -196,6 +196,7 @@ config BT_HCIUART_BCM > config BT_HCIUART_QCA > bool "Qualcomm Atheros protocol support" > depends on BT_HCIUART > + depends on BT_HCIUART_SERDEV > select BT_HCIUART_H4 > select BT_QCA > help > diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c > index 05ec530b8a3a..6e6042f77784 100644 > --- a/drivers/bluetooth/hci_qca.c > +++ b/drivers/bluetooth/hci_qca.c > @@ -29,7 +29,11 @@ > */ > > #include > +#include > #include > +#include > +#include > +#include > > #include > #include > @@ -50,6 +54,9 @@ > #define IBS_TX_IDLE_TIMEOUT_MS 2000 > #define BAUDRATE_SETTLE_TIMEOUT_MS 300 > > +/* susclk rate */ > +#define SUSCLK_RATE_32KHZ 32768 > + > /* HCI_IBS transmit side sleep protocol states */ > enum tx_ibs_states { > HCI_IBS_TX_ASLEEP, > @@ -111,6 +118,12 @@ struct qca_data { > u64 votes_off; > }; > > +struct qca_serdev { > + struct hci_uart serdev_hu; > + struct gpio_desc *bt_en; > + struct clk *susclk; > +}; > + > static void __serial_clock_on(struct tty_struct *tty) > { > /* TODO: Some chipset requires to enable UART clock on client > @@ -386,6 +399,7 @@ static void hci_ibs_wake_retrans_timeout(struct > timer_list *t) > /* Initialize protocol */ > static int qca_open(struct hci_uart *hu) > { > + struct qca_serdev *qcadev; > struct qca_data *qca; > > BT_DBG("hu %p qca_open", hu); > @@ -444,6 +458,13 @@ static int qca_open(struct hci_uart *hu) > timer_setup(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, 0); > qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS; > > + if (hu->serdev) { > + serdev_device_open(hu->serdev); > + > + qcadev = serdev_device_get_drvdata(hu->serdev); > + gpiod_set_value_cansleep(qcadev->bt_en, 1); > + } > + > BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, > wake_retrans=%u", > qca->tx_idle_delay, qca->wake_retrans); > > @@ -512,6 +533,7 @@ static int qca_flush(struct hci_uart *hu) > /* Close protocol */ > static int qca_close(struct hci_uart *hu) > { > + struct qca_serdev *qcadev; > struct qca_data *qca = hu->priv; > > BT_DBG("hu %p qca close", hu); > @@ -525,6 +547,13 @@ static int qca_close(struct hci_uart *hu) > destroy_workqueue(qca->workqueue); > qca->hu = NULL; > > + if (hu->serdev) { > + serdev_device_close(hu->serdev); > + > + qcadev = serdev_device_get_drvdata(hu->serdev); > + gpiod_set_value_cansleep(qcadev->bt_en, 0); > + } > + > kfree_skb(qca->rx_skb); > > hu->priv = NULL; > @@ -885,6 +914,14 @@ static int qca_set_baudrate(struct hci_dev *hdev, > uint8_t baudrate) > return 0; > } > > +static inline void host_set_baudrate(struct hci_uart *hu, unsigned > int speed) > +{ > + if (hu->serdev) > + serdev_device_set_baudrate(hu->serdev, speed); > + else > + hci_uart_set_baudrate(hu, speed); > +} > + > static int qca_setup(struct hci_uart *hu) > { > struct hci_dev *hdev = hu->hdev; > @@ -905,7 +942,7 @@ static int qca_setup(struct hci_uart *hu) > speed = hu->proto->init_speed; > > if (speed) > - hci_uart_set_baudrate(hu, speed); > + host_set_baudrate(hu, speed); > > /* Setup user speed if needed */ > speed = 0; > @@ -924,7 +961,7 @@ static int qca_setup(struct hci_uart *hu) > ret); > return ret; > } > - hci_uart_set_baudrate(hu, speed); > + host_set_baudrate(hu, speed); > } > > /* Setup patch / NVM configurations */ > @@ -958,12 +995,80 @@ static struct hci_uart_proto qca_proto = { > .dequeue = qca_dequeue, > }; > > +static int qca_serdev_probe(struct serdev_device *serdev) > +{ > + struct qca_serdev *qcadev; > + int err; > + > + qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), > GFP_KERNEL); > + if (!qcadev) > + return -ENOMEM; > + > + qcadev->serdev_hu.serdev = serdev; > + serdev_device_set_drvdata(serdev, qcadev); > + > + qcadev->bt_en = devm_gpiod_get(&serdev->dev, "enable", > + GPIOD_OUT_LOW); > + if (IS_ERR(qcadev->bt_en)) { > + dev_err(&serdev->dev, "failed to acquire bt-disable-n > gpio\n"); > + return PTR_ERR(qcadev->bt_en); > + } > + > + qcadev->susclk = devm_clk_get(&serdev->dev, NULL); > + if (IS_ERR(qcadev->susclk)) { > + dev_err(&serdev->dev, "failed to acquire clk\n"); > + return PTR_ERR(qcadev->susclk); > + } > + > + err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ); > + if (err) > + return err; > + > + err = clk_prepare_enable(qcadev->susclk); > + if (err) > + return err; > + > + err = hci_uart_register_device(&qcadev->serdev_hu, > &qca_proto); > + if (err) > + clk_disable_unprepare(qcadev->susclk); > + > + return err; > +} > + > +static void qca_serdev_remove(struct serdev_device *serdev) > +{ > + struct qca_serdev *qcadev = > serdev_device_get_drvdata(serdev); > + > + hci_uart_unregister_device(&qcadev->serdev_hu); > + > + clk_disable_unprepare(qcadev->susclk); > +} > + > +static const struct of_device_id qca_bluetooth_of_match[] = { > + { .compatible = "qcom,qca6174-bt" }, > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); > + > +static struct serdev_device_driver qca_serdev_driver = { > + .probe = qca_serdev_probe, > + .remove = qca_serdev_remove, > + .driver = { > + .name = "hci_uart_qca", > + .of_match_table = qca_bluetooth_of_match, > + }, > +}; > + > int __init qca_init(void) > { > + serdev_device_driver_register(&qca_serdev_driver); > + > return hci_uart_register_proto(&qca_proto); > } > > int __exit qca_deinit(void) > { > + serdev_device_driver_unregister(&qca_serdev_driver); > + > return hci_uart_unregister_proto(&qca_proto); > } -- Andy Shevchenko Intel Finland Oy