Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp2578663rdh; Sun, 26 Nov 2023 11:19:27 -0800 (PST) X-Google-Smtp-Source: AGHT+IGx0lzpucPLdT5ZpWSd9EWR9rRAIdtpwxM5FSwlh5zyr3aNoiQh55Ie5Z40KIKncExcXvUi X-Received: by 2002:a17:902:db11:b0:1cc:5833:cf5e with SMTP id m17-20020a170902db1100b001cc5833cf5emr10185377plx.27.1701026367073; Sun, 26 Nov 2023 11:19:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701026367; cv=none; d=google.com; s=arc-20160816; b=F+Bs3BT4imdx2HwcyTcsBTnDwKWd0bEHrO5Mg0+ok+5XLwqfwjdD3wffuy5os7M1Kh S+5PxIRzO7VuIotts6AqYUkButUo0CaOimSl3xOL9/RM89G9EsdMTEeYj/uL76ZxTShA mdgECJWuUPUytrP8g0b+klye8UjHi1hpoeQMptN5iTBXVX3X5u7Uv7TURAFdzvoFQdqV McV/sQyXc+uuCW5ih8mTXde1f3D6CHJV6Rob68Aa/7yBSAom5QAnVyi+B1kkMRscQvkQ NNqR9aeZrK10EkbOeLApJs55AhV/O8+yIXrFHZ7njAmFYhwkIybVKmgQzbPC+UMFS9S/ Re5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:to:from; bh=6gLybCdX69r7cEaSvHCfVev4zTUTcPjpuHtD7ccqz1A=; fh=LG9dKayB47Aw5OhgE4A33oFKes3+TtS9nbezIo8wrtw=; b=QCB9aNU3v45+jzNyCRV6fM0go16DGRctMvV9ey7FxcqYqYm0U6r6DJOHcGkwhbwwaY W9V+gG6TOwGlA1SgWGM2p5sCYWWkjtltZn6lM5xlD0dailKKYe69IiXm1ZSXIY4jtT1G LvUhMekTWNqteFPkbkB+bKcWeN+RWxn0B+jCcAdQ/8FdW5+5qZMkIAxBuDq4ae5WFYrR 2BNBL8LTwSm4oBPdfc3MC7v7QY0DI9QJwEdPGXX58VsfPHzZywszzLLQs7mcyp7h03ne evPTtWUhbk/MoV3t79RXFh2lzLjoNakb3q1Iu9leq1vw6M5DtbjgSeLGa1c/ComQR9d0 sUrg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id h9-20020a170902748900b001cfba7c561fsi2933683pll.249.2023.11.26.11.19.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Nov 2023 11:19:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 339A9808405A; Sun, 26 Nov 2023 11:19:23 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231201AbjKZTS6 (ORCPT + 99 others); Sun, 26 Nov 2023 14:18:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229489AbjKZTSt (ORCPT ); Sun, 26 Nov 2023 14:18:49 -0500 Received: from mail.andi.de1.cc (mail.andi.de1.cc [IPv6:2a02:c205:3004:2154::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 33A1DF5 for ; Sun, 26 Nov 2023 11:18:53 -0800 (PST) Received: from p200301077700a9001a3da2fffebfd33a.dip0.t-ipconnect.de ([2003:107:7700:a900:1a3d:a2ff:febf:d33a] helo=aktux) by mail.andi.de1.cc with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r7KeT-006khQ-0v; Sun, 26 Nov 2023 20:18:45 +0100 Received: from andi by aktux with local (Exim 4.96) (envelope-from ) id 1r7KeS-000Slj-2U; Sun, 26 Nov 2023 20:18:44 +0100 From: Andreas Kemnade To: marcel@holtmann.org, johan.hedberg@gmail.com, luiz.dentz@gmail.com, johan@kernel.org, arnd@arndb.de, gregkh@linuxfoundation.org, andreas@kemnade.info, linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, tomi.valkeinen@ideasonboard.com, Tony Lindgren , =?UTF-8?q?P=C3=A9ter=20Ujfalusi?= , robh@kernel.org Subject: [RFC PATCH 2/3] bluetooth: ti-st: add GNSS support for TI Wilink chips Date: Sun, 26 Nov 2023 20:18:39 +0100 Message-Id: <20231126191840.110564-3-andreas@kemnade.info> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231126191840.110564-1-andreas@kemnade.info> References: <20231126191840.110564-1-andreas@kemnade.info> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Sun, 26 Nov 2023 11:19:23 -0800 (PST) Some of these chips have GNSS support. GNSS support is available through channel 9 whilst FM is through channel 8. Add support for it. A driver providing a /dev/tigps device is found in some vendor-kernels. The GNSS device provided by this patch seems to be compatible. Signed-off-by: Andreas Kemnade --- drivers/bluetooth/hci_ll.c | 154 ++++++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 4a0b5c3160c2b..718dab0f529a7 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -68,6 +69,10 @@ struct ll_device { struct gpio_desc *enable_gpio; struct clk *ext_clk; bdaddr_t bdaddr; + + struct mutex gdev_mutex; + bool gdev_open; + struct gnss_device *gdev; }; struct ll_struct { @@ -78,6 +83,20 @@ struct ll_struct { struct sk_buff_head tx_wait_q; /* HCILL wait queue */ }; +/* Channel-9 details for GPS */ +#define GPS_CH9_PKT_HDR_SIZE 4 +#define GPS_CH9_PKT_NUMBER 0x9 +#define GPS_CH9_OP_WRITE 0x1 +#define GPS_CH9_OP_READ 0x2 +#define GPS_CH9_OP_COMPLETED_EVT 0x3 + +struct gnssdrv_event_hdr { + uint8_t opcode; + uint16_t plen; +} __packed; + + +static int gnss_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); /* * Builds and sends an HCILL command packet. * These are very simple packets with only 1 cmd byte @@ -411,6 +430,13 @@ static int ll_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) .lsize = 0, \ .maxlen = 0 +#define LL_RECV_GNSS \ + .type = GPS_CH9_PKT_NUMBER, \ + .hlen = 3, \ + .loff = 1, \ + .lsize = 2 \ + + static const struct h4_recv_pkt ll_recv_pkts[] = { { H4_RECV_ACL, .recv = hci_recv_frame }, { H4_RECV_SCO, .recv = hci_recv_frame }, @@ -419,6 +445,7 @@ static const struct h4_recv_pkt ll_recv_pkts[] = { { LL_RECV_SLEEP_ACK, .recv = ll_recv_frame }, { LL_RECV_WAKE_IND, .recv = ll_recv_frame }, { LL_RECV_WAKE_ACK, .recv = ll_recv_frame }, + { LL_RECV_GNSS, .recv = gnss_recv_frame }, }; /* Recv data */ @@ -682,12 +709,124 @@ static int ll_setup(struct hci_uart *hu) static const struct hci_uart_proto llp; +static int gnss_lldev_open(struct gnss_device *gdev) +{ + struct ll_device *lldev = gnss_get_drvdata(gdev); + + mutex_lock(&lldev->gdev_mutex); + lldev->gdev_open = true; + mutex_unlock(&lldev->gdev_mutex); + + return 0; +} + +static void gnss_lldev_close(struct gnss_device *gdev) +{ + struct ll_device *lldev = gnss_get_drvdata(gdev); + + mutex_lock(&lldev->gdev_mutex); + lldev->gdev_open = false; + mutex_unlock(&lldev->gdev_mutex); +} + +static int gnss_lldev_write_raw(struct gnss_device *gdev, + const unsigned char *buf, size_t count) +{ + struct ll_device *lldev = gnss_get_drvdata(gdev); + int err = 0; + struct sk_buff *skb = NULL; + struct gnssdrv_event_hdr gnssdrv_hdr = { GPS_CH9_OP_WRITE, 0x0000 }; + + /* allocate packet */ + skb = bt_skb_alloc(sizeof(gnssdrv_hdr) + count, GFP_ATOMIC); + if (!skb) { + BT_ERR("cannot allocate memory for HCILL packet"); + err = -ENOMEM; + goto out; + } + + /* GPS channel */ + + gnssdrv_hdr.plen = count; + hci_skb_pkt_type(skb) = GPS_CH9_PKT_NUMBER; + skb_put_data(skb, &gnssdrv_hdr, sizeof(gnssdrv_hdr)); + skb_put_data(skb, buf, count); + + lldev->hu.hdev->send(lldev->hu.hdev, skb); + + /* TODO: wait on completion? */ + return count; +out: + return err; +} + +static const struct gnss_operations gnss_lldev_ops = { + .open = gnss_lldev_open, + .close = gnss_lldev_close, + .write_raw = gnss_lldev_write_raw, +}; + +static int gnss_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_uart *hu = hci_get_drvdata(hdev); + struct ll_device *lldev = container_of(hu, struct ll_device, hu); + + if (!IS_ENABLED(CONFIG_GNSS)) + return 0; + + if (!lldev->gdev) + return 0; + + if (hci_skb_pkt_type(skb) == GPS_CH9_PKT_NUMBER) { + struct gnssdrv_event_hdr *gnss_hdr = + (struct gnssdrv_event_hdr *)skb->data; + void *data = skb_pull(skb, sizeof(*gnss_hdr)); + /* + * REVISIT: maybe do something with the completed + * event + */ + if (gnss_hdr->opcode == GPS_CH9_OP_READ) { + mutex_lock(&lldev->gdev_mutex); + if (lldev->gdev_open) + gnss_insert_raw(lldev->gdev, data, skb->len); + mutex_unlock(&lldev->gdev_mutex); + } + } + kfree_skb(skb); + + return 0; +} + +static int ll_gnss_register(struct ll_device *lldev) +{ + struct gnss_device *gdev; + int ret; + + gdev = gnss_allocate_device(&lldev->serdev->dev); + if (!gdev) + return -ENOMEM; + + gdev->ops = &gnss_lldev_ops; + gdev->type = GNSS_TYPE_AI2; + gnss_set_drvdata(gdev, lldev); + mutex_init(&lldev->gdev_mutex); + + ret = gnss_register_device(gdev); + if (ret == 0) { + lldev->gdev = gdev; + return 0; + } + gnss_put_device(gdev); + return ret; +} + static int hci_ti_probe(struct serdev_device *serdev) { struct hci_uart *hu; struct ll_device *lldev; struct nvmem_cell *bdaddr_cell; u32 max_speed = 3000000; + int ret; lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL); if (!lldev) @@ -756,14 +895,27 @@ static int hci_ti_probe(struct serdev_device *serdev) kfree(bdaddr); } - return hci_uart_register_device(hu, &llp); + ret = hci_uart_register_device(hu, &llp); + if (ret) + return ret; + + if (IS_ENABLED(CONFIG_GNSS) && + strstr(of_node_full_name(serdev->dev.of_node), "gnss")) + ll_gnss_register(lldev); + + return 0; } + static void hci_ti_remove(struct serdev_device *serdev) { struct ll_device *lldev = serdev_device_get_drvdata(serdev); hci_uart_unregister_device(&lldev->hu); + if (IS_ENABLED(CONFIG_GNSS) && lldev->gdev) { + gnss_deregister_device(lldev->gdev); + gnss_put_device(lldev->gdev); + } } static const struct of_device_id hci_ti_of_match[] = { -- 2.39.2