Received: by 10.213.65.68 with SMTP id h4csp1081965imn; Wed, 14 Mar 2018 09:04:41 -0700 (PDT) X-Google-Smtp-Source: AG47ELsJTZAxg5ZeGtF48MxWWM+zAjEDrNlZPeUZvZvwlLeP/xPfHOVKOdBS+2KIx9FvOw7h7bB2 X-Received: by 2002:a17:902:a516:: with SMTP id s22-v6mr2230200plq.191.1521043481744; Wed, 14 Mar 2018 09:04:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521043481; cv=none; d=google.com; s=arc-20160816; b=gxLRcb1XlQLdL52IWCKb6L/Omhr7amHlCh6el3a+hkQjlHH//eyD4wRyLyZCF8vk8p FgnJdp80vE5QY8YsAcE0mqOcps4PR1VPWgtmvQSju2qezJcvIxu8EuAOSEicTpiax7QQ cyFpgc6SIGRRvboijYPBBOkuv9u2fZtacSGNil/RenmJjGj3DlPI1HWHpA6POLG8HWoz En9myy+F1WRzaqQmYdexFqOdaT5LDt+/AaBvuPK7VE5Ygs5fh2daQYym/vu6xg0lLosz jPOWoFafWCrwL68rHZ7VlYBkgOV+WxBZeXb/rLdXG6XqJ/jWBc2TFtXPL5oEoBgAA/EL IXzg== 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=2xDT7V9dxtUKJIXoVyOwTDbv/7YWRIJSnIXW79gzrVU=; b=Msvg3FoTOx7N3hdFEXyjMVA5qM2+leUD6EnmGiBAmQOv+IrYT+5P53ESKantk3jC62 2+iNA8CTubLDPhuFgZrAPeApworoaQzzoi0PqR7Rk6+qRXhWU0TcX/6XOu9/ihpR3//H JLyMjq1eaA+hBiMThIvXsG2o2s09xwrydkQokiLDYpomLEfef3GxG0sshPEMb+MFf5H1 4Mvc1i+Fv/pOOiiL4FWnBdjadVIb9Mv2DG4aVW4qC13i5GZ6iQBZLJs8KvWsIqgy1BsS qZSVgcUblcIwQ/mDe9WU+z/v3upvelHMSdKVvddm1RDS0hoUKb/kgAOpFaOWfWPk7q/t Ekcg== 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 t18si2259908pfg.246.2018.03.14.09.04.24; Wed, 14 Mar 2018 09:04:41 -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 S1752302AbeCNQBY (ORCPT + 99 others); Wed, 14 Mar 2018 12:01:24 -0400 Received: from mga14.intel.com ([192.55.52.115]:29988 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751755AbeCNQBW (ORCPT ); Wed, 14 Mar 2018 12:01:22 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Mar 2018 09:01:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,470,1515484800"; d="scan'208";a="41990308" Received: from smile.fi.intel.com (HELO smile) ([10.237.72.86]) by orsmga002.jf.intel.com with ESMTP; 14 Mar 2018 09:01:17 -0700 Message-ID: <1521043276.10722.645.camel@linux.intel.com> Subject: Re: [PATCH v4 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 , Loic Poulain , Bjorn Andersson Cc: Srinivas Kandagatla , linux-bluetooth@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Date: Wed, 14 Mar 2018 18:01:16 +0200 In-Reply-To: <20180314155514.3374-4-thierry.escande@linaro.org> References: <20180314155514.3374-1-thierry.escande@linaro.org> <20180314155514.3374-4-thierry.escande@linaro.org> Organization: Intel Finland Oy Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.26.5-1 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 Wed, 2018-03-14 at 16:55 +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. > FWIW, Reviewed-by: Andy Shevchenko > Signed-off-by: Thierry Escande > --- > > 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..6cf0d1d4595a 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, "bt-disable-n", > + 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