From patchwork Wed Feb 12 15:46:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alexis_Lothor=C3=A9?= X-Patchwork-Id: 864782 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB7BA20B210; Wed, 12 Feb 2025 15:47:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375273; cv=none; b=PgbaB36jVzxWo6i+YxXV4JRLZAbiKLnG0XtweCFEfbO1H+N6Qb4HkCIaGVT+/hqHDusIxbcqMgVJuVhwoAVOUYTSzXNn0Hh9eSq5lU9ik8P1Pr3NOfK5K1iswBfQNoYInGqgQy22NvcWpS3mhrynn0kRBx9ehu9YtJ6CwE5Gbsc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375273; c=relaxed/simple; bh=1jztkzYD9KJ/1fJA6MUcU0W065d9PyvnLOCcHtgK/nM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=R3Dqu8ITmfvqm1msPVnZGOXwaarNAI0PT4b5BXdHS8NC/rzlGvJlsDIGj7zp9JWZiaGGJ7v7GaOXnBmDaphfr3gB4d1cea4hUwzBonIapcVcf3Avno00TNZZKi4qsvW9YNAB3thvpru3pv3/RcVmMwrDBxVXnCrwcn64Vb1RlDc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=AsR2Kr+r; arc=none smtp.client-ip=217.70.183.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="AsR2Kr+r" Received: by mail.gandi.net (Postfix) with ESMTPSA id CC5D8440FF; Wed, 12 Feb 2025 15:47:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1739375268; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w7OFME9i2IUPBCJlachFUyekEY4wChv9lVNTlta/qgw=; b=AsR2Kr+r0EsfCT0bRR50j86StsO7qBNICof/C8pNBJ9MSjy+WFLvVLL5dcJDVzjlT1+q3r 57rTr179uIMOj88U4BHO1/nsJdJXgCOeFm6VxNOu5NGcHEJUjju9ZvFVAidGTBVIf9545+ JRaA5ObSMEGC0kM8OYoJ04DKOpS3eQmVTcQA2f4z4NPMPyhfDEUF5nt1aWJak5xeM8S+tI /7JAwzJWgqRI+KWpdgEEy/MAt26N34VUK0/SDa/IQiUyirEqvNuwMTA+KZg3Ur8KIFY5do wrwQ1rq0OHH7OQI2NLoVsGq8scg5HX5wHJxOPuDUSNJZh43HYrweV3mtIAXUUQ== From: =?utf-8?q?Alexis_Lothor=C3=A9?= Date: Wed, 12 Feb 2025 16:46:21 +0100 Subject: [PATCH 02/12] wifi: wilc1000: add a read-modify-write API for registers accesses Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250212-wilc3000_bt-v1-2-9609b784874e@bootlin.com> References: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> In-Reply-To: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> To: =?utf-8?q?Alexis_Lothor=C3=A9?= , Marcel Holtmann , Luiz Augusto von Dentz , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ajay Singh , Claudiu Beznea , Kalle Valo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nicolas Ferre , Alexandre Belloni Cc: Marek Vasut , Thomas Petazzoni , linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeggedvkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeetlhgvgihishcunfhothhhohhrrocuoegrlhgvgihishdrlhhothhhohhrvgessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepgeevgefhteffuefhheekkeelffffvdeugffgveejffdtvdffudehtedtieevteetnecukfhppedvrgdtvdemkeegvdekmehfleegtgemvgdttdemmehfkeehnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepvdgrtddvmeekgedvkeemfhelgegtmegvtddtmeemfhekhedphhgvlhhopegludelvddrudeikedruddrudeljegnpdhmrghilhhfrhhomheprghlvgigihhsrdhlohhthhhorhgvsegsohhothhlihhnrdgtohhmpdhnsggprhgtphhtthhopedvgedprhgtphhtthhopegtohhnohhrodgutheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhosghhsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopeguvghvihgtvghtrhgvvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdpr hgtphhtthhopehkrhiikhdoughtsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehkuhgsrgeskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqrghrmhdqkhgvrhhnvghlsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgpdhrtghpthhtoheplhhuihiirdguvghnthiisehgmhgrihhlrdgtohhm X-GND-Sasl: alexis.lothore@bootlin.com Many places in wilc driver need to modify a single bit in a register, and then perform the following sequence: read the register, set/reset the needed bit, write the register. This sequence is performed in multiple places in the driver, with a varying amount of checks around possible errors. Replace all those sequences with a new hif_rmw_reg helper. Make sure to perform the write only if needed. Signed-off-by: Alexis Lothoré --- Since the registers meaning and effect is pretty opaque, this commit tries to remain conservative and converts only the "real" read-modify-write sequences: bare writes seemingly trying to affect a single bit but actually affecting the whole register are left untouched. --- drivers/net/wireless/microchip/wilc1000/sdio.c | 68 ++++++------ drivers/net/wireless/microchip/wilc1000/spi.c | 18 +++ drivers/net/wireless/microchip/wilc1000/wlan.c | 145 +++++++++---------------- drivers/net/wireless/microchip/wilc1000/wlan.h | 3 + 4 files changed, 105 insertions(+), 129 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index af970f9991110807ebd880681ad0e8aaf8a0b9bc..7eab1c493774e197e43bdf265063aa8c5e6dff14 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -916,6 +916,7 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; + u32 int_en_mask = 0; if (nint > MAX_NUM_INT) { dev_err(&func->dev, "Too many interrupts (%d)...\n", nint); @@ -923,61 +924,42 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) } if (sdio_priv->irq_gpio) { - u32 reg; int ret, i; /** * interrupt pin mux select **/ - ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, ®); + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_PIN_MUX_0, BIT(8), + BIT(8)); if (ret) { - dev_err(&func->dev, "Failed read reg (%08x)...\n", - WILC_PIN_MUX_0); - return ret; - } - reg |= BIT(8); - ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg); - if (ret) { - dev_err(&func->dev, "Failed write reg (%08x)...\n", - WILC_PIN_MUX_0); + dev_err(&func->dev, "Failed to set interrupt mux\n"); return ret; } /** * interrupt enable **/ - ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, ®); - if (ret) { - dev_err(&func->dev, "Failed read reg (%08x)...\n", - WILC_INTR_ENABLE); - return ret; - } - for (i = 0; (i < 5) && (nint > 0); i++, nint--) - reg |= BIT((27 + i)); - ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg); + int_en_mask |= BIT(WILC_INTR_ENABLE_BIT_BASE + i); + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_INTR_ENABLE, + int_en_mask, int_en_mask); if (ret) { - dev_err(&func->dev, "Failed write reg (%08x)...\n", - WILC_INTR_ENABLE); + dev_err(&func->dev, "Failed to enable interrupts\n"); return ret; } - if (nint) { - ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); - if (ret) { - dev_err(&func->dev, - "Failed read reg (%08x)...\n", - WILC_INTR2_ENABLE); - return ret; - } + if (nint) { + int_en_mask = 0; for (i = 0; (i < 3) && (nint > 0); i++, nint--) - reg |= BIT(i); + int_en_mask |= BIT(i); - ret = wilc_sdio_write_reg(wilc, WILC_INTR2_ENABLE, reg); + ret = wilc->hif_func->hif_rmw_reg(wilc, + WILC_INTR2_ENABLE, + int_en_mask, + int_en_mask); if (ret) { dev_err(&func->dev, - "Failed write reg (%08x)...\n", - WILC_INTR2_ENABLE); + "Failed to enable internal interrupts\n"); return ret; } } @@ -985,6 +967,23 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) return 0; } +static int wilc_sdio_rmw_reg(struct wilc *wilc, u32 reg, u32 mask, u32 data) +{ + u32 old_val, new_val; + int ret = 0; + + ret = wilc_sdio_read_reg(wilc, reg, &old_val); + if (ret) + return ret; + + new_val = old_val & ~mask; + new_val |= data; + if (new_val != old_val) + ret = wilc_sdio_write_reg(wilc, reg, new_val); + + return ret; +} + /* Global sdio HIF function table */ static const struct wilc_hif_func wilc_hif_sdio = { .hif_init = wilc_sdio_init, @@ -1003,6 +1002,7 @@ static const struct wilc_hif_func wilc_hif_sdio = { .disable_interrupt = wilc_sdio_disable_interrupt, .hif_reset = wilc_sdio_reset, .hif_is_init = wilc_sdio_is_init, + .hif_rmw_reg = wilc_sdio_rmw_reg }; static int wilc_sdio_suspend(struct device *dev) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 5bcabb7decea0fc8d0065a240f4acefabca3346a..aae4262045ff3e5f3668493ef235486e601996f7 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -1355,6 +1355,23 @@ static int wilc_spi_sync_ext(struct wilc *wilc, int nint) return 0; } +static int wilc_spi_rmw_reg(struct wilc *wilc, u32 reg, u32 mask, u32 data) +{ + u32 old_val, new_val; + int ret = 0; + + ret = wilc_spi_read_reg(wilc, reg, &old_val); + if (ret) + return ret; + + new_val = old_val & ~mask; + new_val |= data; + if (new_val != old_val) + ret = wilc_spi_write_reg(wilc, reg, new_val); + + return ret; +} + /* Global spi HIF function table */ static const struct wilc_hif_func wilc_hif_spi = { .hif_init = wilc_spi_init, @@ -1371,4 +1388,5 @@ static const struct wilc_hif_func wilc_hif_spi = { .hif_sync_ext = wilc_spi_sync_ext, .hif_reset = wilc_spi_reset, .hif_is_init = wilc_spi_is_init, + .hif_rmw_reg = wilc_spi_rmw_reg }; diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index 9d80adc45d6be14c8818e8ef1643db6875cf57d2..f2b13bd44273ebe2ee474eda047e82bf1287bd6e 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -578,53 +578,27 @@ static int chip_allow_sleep_wilc1000(struct wilc *wilc) pr_warn("FW not responding\n"); /* Clear bit 1 */ - ret = hif_func->hif_read_reg(wilc, wakeup_reg, ®); + ret = wilc->hif_func->hif_rmw_reg(wilc, wakeup_reg, wakeup_bit, 0); if (ret) return ret; - if (reg & wakeup_bit) { - reg &= ~wakeup_bit; - ret = hif_func->hif_write_reg(wilc, wakeup_reg, reg); - if (ret) - return ret; - } - ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, ®); + ret = wilc->hif_func->hif_rmw_reg(wilc, from_host_to_fw_reg, + from_host_to_fw_bit, 0); if (ret) return ret; - if (reg & from_host_to_fw_bit) { - reg &= ~from_host_to_fw_bit; - ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, reg); - if (ret) - return ret; - } return 0; } static int chip_allow_sleep_wilc3000(struct wilc *wilc) { - u32 reg = 0; int ret; - const struct wilc_hif_func *hif_func = wilc->hif_func; + u32 wake_bit = wilc->io_type == WILC_HIF_SDIO ? WILC_SDIO_WAKEUP_BIT : + WILC_SPI_WAKEUP_BIT; - if (wilc->io_type == WILC_HIF_SDIO) { - ret = hif_func->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, ®); - if (ret) - return ret; - ret = hif_func->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG, - reg & ~WILC_SDIO_WAKEUP_BIT); - if (ret) - return ret; - } else { - ret = hif_func->hif_read_reg(wilc, WILC_SPI_WAKEUP_REG, ®); - if (ret) - return ret; - ret = hif_func->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG, - reg & ~WILC_SPI_WAKEUP_BIT); - if (ret) - return ret; - } - return 0; + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_SDIO_WAKEUP_REG, wake_bit, + 0); + return ret; } static int chip_allow_sleep(struct wilc *wilc) @@ -699,10 +673,10 @@ static int chip_wakeup_wilc1000(struct wilc *wilc) static int chip_wakeup_wilc3000(struct wilc *wilc) { - u32 wakeup_reg_val, clk_status_reg_val, trials = 0; - u32 wakeup_reg, wakeup_bit; + u32 clk_status_reg_val, trials = 0; u32 clk_status_reg, clk_status_bit; - int wake_seq_trials = 5; + int wake_seq_trials = 5, ret; + u32 wakeup_reg, wakeup_bit; const struct wilc_hif_func *hif_func = wilc->hif_func; if (wilc->io_type == WILC_HIF_SDIO) { @@ -717,10 +691,12 @@ static int chip_wakeup_wilc3000(struct wilc *wilc) clk_status_bit = WILC3000_SPI_CLK_STATUS_BIT; } - hif_func->hif_read_reg(wilc, wakeup_reg, &wakeup_reg_val); do { - hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_reg_val | - wakeup_bit); + ret = hif_func->hif_rmw_reg(wilc, wakeup_reg, wakeup_bit, + wakeup_bit); + if (ret) + dev_warn(wilc->dev, "Failed to set wake bit\n"); + /* Check the clock status */ hif_func->hif_read_reg(wilc, clk_status_reg, &clk_status_reg_val); @@ -745,8 +721,10 @@ static int chip_wakeup_wilc3000(struct wilc *wilc) * edge on the next loop */ if ((clk_status_reg_val & clk_status_bit) == 0) { - hif_func->hif_write_reg(wilc, wakeup_reg, - wakeup_reg_val & (~wakeup_bit)); + ret = hif_func->hif_rmw_reg(wilc, wakeup_reg, + wakeup_bit, 0); + if (ret) + dev_warn(wilc->dev, "Failed to set CLK bit\n"); /* added wait before wakeup sequence retry */ usleep_range(200, 300); } @@ -996,11 +974,11 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) break; if (entries == 0) { - ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); + ret = wilc->hif_func->hif_rmw_reg(wilc, + WILC_HOST_TX_CTRL, BIT(0), 0); if (ret) - break; - reg &= ~BIT(0); - ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); + dev_warn(wilc->dev, + "Failed to reset TX CTRL bit\n"); } } while (0); @@ -1267,9 +1245,12 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, if (ret) return ret; - wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_GLB_RESET_0, BIT(10), 0); + if (ret) { + dev_err(wilc->dev, "Failed to reset WLAN CPU\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return ret; + } wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (reg & BIT(10)) pr_err("%s: Failed to reset\n", __func__); @@ -1357,16 +1338,12 @@ int wilc_wlan_start(struct wilc *wilc) if (ret) goto release; - wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); - if ((reg & BIT(10)) == BIT(10)) { - reg &= ~BIT(10); - wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); - wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); - } - - reg |= BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); - wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_GLB_RESET_0, BIT(10), 0); + if (!ret) + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_GLB_RESET_0, + BIT(10), BIT(10)); + if (ret) + dev_warn(wilc->dev, "Failed to reset WLAN CPU\n"); release: rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY); @@ -1375,44 +1352,31 @@ int wilc_wlan_start(struct wilc *wilc) int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) { - u32 reg = 0; int ret, rv; ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); if (ret) return ret; - ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, ®); - if (ret) - goto release; - - reg &= ~WILC_GLOBAL_MODE_ENABLE_WIFI; - ret = wilc->hif_func->hif_write_reg(wilc, GLOBAL_MODE_CONTROL, reg); - if (ret) - goto release; - - ret = wilc->hif_func->hif_read_reg(wilc, PWR_SEQ_MISC_CTRL, ®); - if (ret) - goto release; - - reg &= ~WILC_PWR_SEQ_ENABLE_WIFI_SLEEP; - ret = wilc->hif_func->hif_write_reg(wilc, PWR_SEQ_MISC_CTRL, reg); - if (ret) - goto release; - - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); + ret = wilc->hif_func->hif_rmw_reg(wilc, GLOBAL_MODE_CONTROL, + WILC_GLOBAL_MODE_ENABLE_WIFI, 0); if (ret) { - netdev_err(vif->ndev, "Error while reading reg\n"); + netdev_err(vif->ndev, "Failed to disable wlan control\n"); goto release; } - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, - (reg | WILC_ABORT_REQ_BIT)); + ret = wilc->hif_func->hif_rmw_reg(wilc, PWR_SEQ_MISC_CTRL, + WILC_PWR_SEQ_ENABLE_WIFI_SLEEP, 0); if (ret) { - netdev_err(vif->ndev, "Error while writing reg\n"); + netdev_err(vif->ndev, "Failed to unmux wlan power seq\n"); goto release; } + ret = wilc->hif_func->hif_rmw_reg(wilc, WILC_GP_REG_0, + WILC_ABORT_REQ_BIT, 1); + if (ret) + netdev_err(vif->ndev, "Failed to stop wlan CPU\n"); + ret = 0; release: /* host comm is disabled - we can't issue sleep command anymore: */ @@ -1641,19 +1605,10 @@ static int init_chip(struct net_device *dev) goto release; if ((wilc->chipid & 0xfff) != 0xa0) { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_CORTUS_RESET_MUX_SEL, - ®); - if (ret) { - netdev_err(dev, "fail read reg 0x1118\n"); - goto release; - } - reg |= BIT(0); - ret = wilc->hif_func->hif_write_reg(wilc, - WILC_CORTUS_RESET_MUX_SEL, - reg); + ret = wilc->hif_func->hif_rmw_reg(wilc, + WILC_CORTUS_RESET_MUX_SEL, BIT(0), BIT(0)); if (ret) { - netdev_err(dev, "fail write reg 0x1118\n"); + netdev_err(dev, "Failed to enable WLAN global reset\n"); goto release; } ret = wilc->hif_func->hif_write_reg(wilc, diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index b9e7f9222eadde6d736e1d0a403f84ec19399632..65e79371014d9e60755cb0aa38e04d351e67bcfb 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -58,6 +58,7 @@ #define WILC_HOST_TX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x88) #define WILC_INTR_REG_BASE (WILC_PERIPH_REG_BASE + 0xa00) #define WILC_INTR_ENABLE WILC_INTR_REG_BASE +#define WILC_INTR_ENABLE_BIT_BASE 27 #define WILC_INTR2_ENABLE (WILC_INTR_REG_BASE + 4) #define WILC_INTR_POLARITY (WILC_INTR_REG_BASE + 0x10) @@ -403,6 +404,7 @@ struct wilc_hif_func { void (*disable_interrupt)(struct wilc *nic); int (*hif_reset)(struct wilc *wilc); bool (*hif_is_init)(struct wilc *wilc); + int (*hif_rmw_reg)(struct wilc *wilc, u32 reg, u32 mask, u32 data); }; #define WILC_MAX_CFG_FRAME_SIZE 1468 @@ -472,4 +474,5 @@ int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, int wilc_wlan_init(struct net_device *dev); int wilc_get_chipid(struct wilc *wilc); int wilc_load_mac_from_nv(struct wilc *wilc); + #endif From patchwork Wed Feb 12 15:46:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alexis_Lothor=C3=A9?= X-Patchwork-Id: 864781 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1408E212B06; Wed, 12 Feb 2025 15:47:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375275; cv=none; b=CaI6IsAUqXKo/Uj0IE0I9XpnXvNkOFYuQwMGFZ+Zyiojb2KmjIrtE/dxbteWvODMJGCAS6IUv7JH0Ei8c96oSIpBn8jdYcMXhioqNDbxyClNajbbrV4Il1mSBu2SJtVRPEmF4rllNo3D6/3YkXbfo+ythgczaZFxz3ZL6d3mWr8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375275; c=relaxed/simple; bh=GOvQNyUVl9fP6G1phuIP+FuJTr0gdmOmVl0+2mbeB0o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B/LBHxol6241R+rPF9jMwqb4nO4PimnMpIwh4/EA/sGAb4TcETY92V3wyZMLrECemwx5iR0BqZo9wkHxvf2iq0suRix7X63dR36E+iQU4ZWa/1QyrrSWUGy3Fs7lVJ8yNo/HSXja4NjdHs2seEesoAB9VTdWiOHISCvivy1Q8Sw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=OJGKYxq1; arc=none smtp.client-ip=217.70.183.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="OJGKYxq1" Received: by mail.gandi.net (Postfix) with ESMTPSA id 215B14318E; Wed, 12 Feb 2025 15:47:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1739375271; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=f0QDXdrnVYdl2WcxZmvLO4vqnkGNCkcX//xPR9QV5j4=; b=OJGKYxq1p8fQMxq/s+dbAehrnUH1vUoJgKdDfQzN/kLeINzgAdHGOH9scjrtLCWCJoCzdJ KPYnJ/+u856gAgcYxI0hMRNKgfH9FMQvubkV8fqnOqDJpzC/YBWyqE4iUFdUPQvHa2Lx8R XUJDmzm58mYI3QUxOvPIeJyalj2msDNUc+a24r+N2SCZIoedTj3FpHQ7QVQmtOc+mmHCsS C7XBTU2u2zpA3TMV+8nPxorGCQiVuhOvxEB8iHH9n5yZh/2NWgKusrHOtmGDRWRi3XHfJv 9gH68xFvZvOfotnHyP5zIAbnHCcyh3FzytHAh8UuBbRR1+Pak28+uT98Eq41aw== From: =?utf-8?q?Alexis_Lothor=C3=A9?= Date: Wed, 12 Feb 2025 16:46:23 +0100 Subject: [PATCH 04/12] wifi: wilc1000: allow to use acquire/release bus in other parts of driver Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250212-wilc3000_bt-v1-4-9609b784874e@bootlin.com> References: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> In-Reply-To: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> To: =?utf-8?q?Alexis_Lothor=C3=A9?= , Marcel Holtmann , Luiz Augusto von Dentz , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ajay Singh , Claudiu Beznea , Kalle Valo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nicolas Ferre , Alexandre Belloni Cc: Marek Vasut , Thomas Petazzoni , linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeggedvkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeetlhgvgihishcunfhothhhohhrrocuoegrlhgvgihishdrlhhothhhohhrvgessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepgeevgefhteffuefhheekkeelffffvdeugffgveejffdtvdffudehtedtieevteetnecukfhppedvrgdtvdemkeegvdekmehfleegtgemvgdttdemmehfkeehnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepvdgrtddvmeekgedvkeemfhelgegtmegvtddtmeemfhekhedphhgvlhhopegludelvddrudeikedruddrudeljegnpdhmrghilhhfrhhomheprghlvgigihhsrdhlohhthhhorhgvsegsohhothhlihhnrdgtohhmpdhnsggprhgtphhtthhopedvgedprhgtphhtthhopegtohhnohhrodgutheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhosghhsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopeguvghvihgtvghtrhgvvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdpr hgtphhtthhopehkrhiikhdoughtsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehkuhgsrgeskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqrghrmhdqkhgvrhhnvghlsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgpdhrtghpthhtoheplhhuihiirdguvghnthiisehgmhgrihhlrdgtohhm X-GND-Sasl: alexis.lothore@bootlin.com acquire_bus/release_bus is currently used only in wlan.c when needing to access the main bus (SDIO or SPI). For wilc3000, the bluetooth part will also need to perform some operations on the main bus (eg: bluetooth firmware loading), so expose acquire/release_bus. Signed-off-by: Alexis Lothoré --- drivers/net/wireless/microchip/wilc1000/wlan.c | 5 +++-- drivers/net/wireless/microchip/wilc1000/wlan.h | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index f2b13bd44273ebe2ee474eda047e82bf1287bd6e..a697caf73ac3ed06602c029c17773f50e3f8edb5 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -743,7 +743,7 @@ static int chip_wakeup(struct wilc *wilc) return chip_wakeup_wilc3000(wilc); } -static inline int acquire_bus(struct wilc *wilc, enum bus_acquire acquire) +int acquire_bus(struct wilc *wilc, enum bus_acquire acquire) { int ret = 0; @@ -757,12 +757,13 @@ static inline int acquire_bus(struct wilc *wilc, enum bus_acquire acquire) return ret; } -static inline int release_bus(struct wilc *wilc, enum bus_release release) +int release_bus(struct wilc *wilc, enum bus_release release) { int ret = 0; if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode) ret = chip_allow_sleep(wilc); + mutex_unlock(&wilc->hif_cs); return ret; diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index 65e79371014d9e60755cb0aa38e04d351e67bcfb..e45c2db0f5cd2de6844993dde15034ebbd93e73b 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -475,4 +475,7 @@ int wilc_wlan_init(struct net_device *dev); int wilc_get_chipid(struct wilc *wilc); int wilc_load_mac_from_nv(struct wilc *wilc); +int acquire_bus(struct wilc *wilc, enum bus_acquire acquire); +int release_bus(struct wilc *wilc, enum bus_release release); + #endif From patchwork Wed Feb 12 15:46:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alexis_Lothor=C3=A9?= X-Patchwork-Id: 864780 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB17E2566D7; Wed, 12 Feb 2025 15:47:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375277; cv=none; b=aAyTIJeLR0KZIcFGeGb7whkL6j9fjxy7NHgjpqo8e9m6AdiECO253puLK2Rrq1tytFkfQm1Ql6plzeoaQnp+cEPSVfJ04Nd+qoo1NytLXsfycZRfTTyZb8RisGXsvoqz1wod+eWcwhasCkA7kBi4fPEU9G7B+87+kH9ZWbAKakQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375277; c=relaxed/simple; bh=xAmGyU91V+m4Q7kGIo3hv+45LYipGVyiZmeFoNFG190=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HOwLCNm1ik/E+3nHJQBXKEBRwej6M/bV6x2YhF5TIGPWtckJR1AJhOKPuXHuwhgqg1Xmc56Fmo8pXTvqwnXYLSiSyxiluToHE8wcluFaI5p2s8YctrLmP9RJgyFVF54Jv2fMIOBKdpv1I14Mjf7Q9HLV3Zu6jSInvXodfWOKn3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=TjZ/AkzY; arc=none smtp.client-ip=217.70.183.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="TjZ/AkzY" Received: by mail.gandi.net (Postfix) with ESMTPSA id 6D0FA440FC; Wed, 12 Feb 2025 15:47:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1739375273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eSlKEKgzm/q54egNWa8O2T+4J35Hi0UxWaRxNxaH0z0=; b=TjZ/AkzYBhFedMs08HnK2oPOp6dXjcONfnjOmvCeVY5yD1HgW2rZK1tK9BIt9Q7pqBJYXM jYJbWmd+ejh+BLMlLWDafz5mHwh/O7xNF6pK/P8aDakRyOBG62CoB7YzeQGv83sOTcjApk SMWRhwtEVnVGV+bymbbS/YDY266W7IAXQYfm7N52QcqA9xD/CMc/odRIGEqCmv/K5CGAFH UBwMwGzp9Tvpt4awsN2oxlifbSxp7cEwZ1yRsNL1e0wZOx1fLVvenTvahnFd5AsTHz0D7n 602Uyye/ALCwG8XYAfhIBXoX04BI8r9In1S5/ai7cWsYZdzFuQri43BFeewxXQ== From: =?utf-8?q?Alexis_Lothor=C3=A9?= Date: Wed, 12 Feb 2025 16:46:25 +0100 Subject: [PATCH 06/12] wifi: wilc1000: remove timeout parameter from set_power_mgmt Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250212-wilc3000_bt-v1-6-9609b784874e@bootlin.com> References: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> In-Reply-To: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> To: =?utf-8?q?Alexis_Lothor=C3=A9?= , Marcel Holtmann , Luiz Augusto von Dentz , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ajay Singh , Claudiu Beznea , Kalle Valo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nicolas Ferre , Alexandre Belloni Cc: Marek Vasut , Thomas Petazzoni , linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeggedvkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeetlhgvgihishcunfhothhhohhrrocuoegrlhgvgihishdrlhhothhhohhrvgessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepgeevgefhteffuefhheekkeelffffvdeugffgveejffdtvdffudehtedtieevteetnecukfhppedvrgdtvdemkeegvdekmehfleegtgemvgdttdemmehfkeehnecuvehluhhsthgvrhfuihiivgepfeenucfrrghrrghmpehinhgvthepvdgrtddvmeekgedvkeemfhelgegtmegvtddtmeemfhekhedphhgvlhhopegludelvddrudeikedruddrudeljegnpdhmrghilhhfrhhomheprghlvgigihhsrdhlohhthhhorhgvsegsohhothhlihhnrdgtohhmpdhnsggprhgtphhtthhopedvgedprhgtphhtthhopegtohhnohhrodgutheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhosghhsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopeguvghvihgtvghtrhgvvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdpr hgtphhtthhopehkrhiikhdoughtsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehkuhgsrgeskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqrghrmhdqkhgvrhhnvghlsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgpdhrtghpthhtoheplhhuihiirdguvghnthiisehgmhgrihhlrdgtohhm X-GND-Sasl: alexis.lothore@bootlin.com While the timeout parameter is part for the cfg80211 ops set_power_mgmt, wilc currently does not uses it (it processes only the boolean value). Remove the unused parameter from the driver-specific function. Signed-off-by: Alexis Lothoré --- drivers/net/wireless/microchip/wilc1000/cfg80211.c | 2 +- drivers/net/wireless/microchip/wilc1000/hif.c | 2 +- drivers/net/wireless/microchip/wilc1000/hif.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index 393fff618f919c5a6d3f4a7d894b187399455fb8..ff8c1a40634cee9960777eb017f6b2905e6399a5 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -1348,7 +1348,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, if (!priv->hif_drv) return -EIO; - wilc_set_power_mgmt(vif, enabled, timeout); + wilc_set_power_mgmt(vif, enabled); return 0; } diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index bba53307b960d996032f56affead0cd0922902a4..3b14d560bc295844d873ed966592f031f6b50206 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c @@ -1932,7 +1932,7 @@ int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, return result; } -int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled) { struct wilc *wilc = vif->wilc; struct wid wid; diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h index 96eeaf31d23777e0392699240479b341529bfd42..5ecf6ba293a598823d09de43b597f8d54d375a7c 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.h +++ b/drivers/net/wireless/microchip/wilc1000/hif.h @@ -192,7 +192,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, struct station_parameters *params); -int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled); int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, u8 *mc_list); int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, u16 chan, From patchwork Wed Feb 12 15:46:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alexis_Lothor=C3=A9?= X-Patchwork-Id: 864779 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 58FCC25D54C; Wed, 12 Feb 2025 15:47:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375280; cv=none; b=EVjjrsudsdnsKSaaBSUD79I/s+yQlzRCuB1bWKKY8LEC6tAEyiQIGBOz1ZKCW03p+i03ohqfq66UXqf8aTwkCJcjQFFsQM0gw2KM/86tCfaOaTZPxfvxdSwfitt/wSmJEQxijiA8tnCXTxHznVa884EQCbFg8DbN8SRWQg745X8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375280; c=relaxed/simple; bh=z6QtgQals0nj68HfLj/ST7GjV9kzm8CLeT9eKOKoVVM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=G7IX0L+ebNhbGA5ML/AbjkvDBt2mZhXMB0Lr4xupi6WtzqEQgxSu1zxlfhREEQp9K3z1zh/UKxia0SvosNIPv3XEpwkNYls0yHDnpCWUvgZXLTkgpAzz1co8mt1nHSRg4boQwvguPDISdXMy737hdAgHGsa05QCs4A3rQ2fmgDA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=jrZVpFHW; arc=none smtp.client-ip=217.70.183.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="jrZVpFHW" Received: by mail.gandi.net (Postfix) with ESMTPSA id CCCFC44169; Wed, 12 Feb 2025 15:47:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1739375276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7E2aPfiJbXJ3tUrfXAYeEsTGlAb+ywwjD1zVqSfPHug=; b=jrZVpFHWxMTZVGPE3b26AtIMX6fFWPpy7jG9ONNAjya+xGWm/5ge/MptzCoRqa3QN/OuD3 EfYXG+yofXLpdkkI+kuN+wgNA1hXtxDre4kOAORGkMB0SVX9fhUpOHuZhvPZp1jdB2CWp2 PARvNi/nimMfnbzIJcNXCwiyO2jqn48JtxEVu2BH3IIxTxtFxIt+4wAKQkVIVDq8vIkEmn 3Zc+f67QkgmNME9khtV4sWwPnu23Q3Q1tsLwF8LN0OFRlqXjzjAMiVFoKfgSbxxBl0jSY1 dYE/ccQamdo1DsUN5+EZtjo21CglcBKydQcHFIoQGk29N51cMCo1aw+xXPS7AQ== From: =?utf-8?q?Alexis_Lothor=C3=A9?= Date: Wed, 12 Feb 2025 16:46:28 +0100 Subject: [PATCH 09/12] wifi: wilc1000: disable firmware power save if bluetooth is in use Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250212-wilc3000_bt-v1-9-9609b784874e@bootlin.com> References: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> In-Reply-To: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> To: =?utf-8?q?Alexis_Lothor=C3=A9?= , Marcel Holtmann , Luiz Augusto von Dentz , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ajay Singh , Claudiu Beznea , Kalle Valo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nicolas Ferre , Alexandre Belloni Cc: Marek Vasut , Thomas Petazzoni , linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeggedvkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeetlhgvgihishcunfhothhhohhrrocuoegrlhgvgihishdrlhhothhhohhrvgessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepgeevgefhteffuefhheekkeelffffvdeugffgveejffdtvdffudehtedtieevteetnecukfhppedvrgdtvdemkeegvdekmehfleegtgemvgdttdemmehfkeehnecuvehluhhsthgvrhfuihiivgepfeenucfrrghrrghmpehinhgvthepvdgrtddvmeekgedvkeemfhelgegtmegvtddtmeemfhekhedphhgvlhhopegludelvddrudeikedruddrudeljegnpdhmrghilhhfrhhomheprghlvgigihhsrdhlohhthhhorhgvsegsohhothhlihhnrdgtohhmpdhnsggprhgtphhtthhopedvgedprhgtphhtthhopegtohhnohhrodgutheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhosghhsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopeguvghvihgtvghtrhgvvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdpr hgtphhtthhopehkrhiikhdoughtsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehkuhgsrgeskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqrghrmhdqkhgvrhhnvghlsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgpdhrtghpthhtoheplhhuihiirdguvghnthiisehgmhgrihhlrdgtohhm X-GND-Sasl: alexis.lothore@bootlin.com If the wlan interface exposed by wilc driver has power save enabled (either explicitly with iw dev wlan set power_save on, or because kernel is built with CONFIG_CFG80211_DEFAULT_PS), it will send a power management command to the wlan firmware when corresponding interface is brought up. The bluetooth part, if used, is supposed to work independently from the WLAN CPU. Unfortunately, this power save management, if applied by the WLAN side, disrupts bluetooth operations (the bluetooth CPU does not answer any command anymore on the UART interface) Make sure that the bluetooth part can work independently by disabling power save in wlan firmware when bluetooth is in use. Signed-off-by: Alexis Lothoré --- drivers/net/wireless/microchip/wilc1000/bt.c | 29 +++++++++++++++++++--- drivers/net/wireless/microchip/wilc1000/cfg80211.c | 5 +++- drivers/net/wireless/microchip/wilc1000/netdev.h | 3 +++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/microchip/wilc1000/bt.c b/drivers/net/wireless/microchip/wilc1000/bt.c index b0f68a5479a5bd6f70e2390a35512037dc6c332b..f0eb5fb506eddf0f6f4f3f0b182eaa650c1c7a87 100644 --- a/drivers/net/wireless/microchip/wilc1000/bt.c +++ b/drivers/net/wireless/microchip/wilc1000/bt.c @@ -7,6 +7,7 @@ #include #include #include +#include "cfg80211.h" #include "netdev.h" #include "wlan_if.h" #include "wlan.h" @@ -261,22 +262,36 @@ static int wilc_bt_start(struct wilc *wilc) int wilc_bt_init(void *wilc_wl_priv) { struct wilc *wilc = (struct wilc *)wilc_wl_priv; + struct wilc_vif *vif; int ret; + wilc->bt_enabled = true; + if (!wilc->hif_func->hif_is_init(wilc)) { dev_info(wilc->dev, "Initializing bus before starting BT"); acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); ret = wilc->hif_func->hif_init(wilc, false); release_bus(wilc, WILC_BUS_RELEASE_ONLY); - if (ret) + if (ret) { + wilc->bt_enabled = false; return ret; + } } + /* Power save feature managed by WLAN firmware may disrupt + * operations from the bluetooth CPU, so disable it while bluetooth + * is in use (if enabled, it will be enabled back when bluetooth is + * not used anymore) + */ + vif = wilc_get_wl_to_vif(wilc); + if (wilc->power_save_mode && wilc_set_power_mgmt(vif, false)) + goto hif_deinit; + mutex_lock(&wilc->radio_fw_start); ret = wilc_bt_power_up(wilc); if (ret) { dev_err(wilc->dev, "Error powering up bluetooth chip\n"); - goto hif_deinit; + goto reenable_power_save; } ret = wilc_bt_firmware_download(wilc); if (ret) { @@ -293,10 +308,14 @@ int wilc_bt_init(void *wilc_wl_priv) power_down: wilc_bt_power_down(wilc); -hif_deinit: +reenable_power_save: + if (wilc->power_save_mode_request) + wilc_set_power_mgmt(vif, true); mutex_unlock(&wilc->radio_fw_start); +hif_deinit: if (!wilc->initialized) wilc->hif_func->hif_deinit(wilc); + wilc->bt_enabled = false; return ret; } EXPORT_SYMBOL(wilc_bt_init); @@ -304,6 +323,7 @@ EXPORT_SYMBOL(wilc_bt_init); int wilc_bt_shutdown(void *wilc_wl_priv) { struct wilc *wilc = (struct wilc *)wilc_wl_priv; + struct wilc_vif *vif; int ret; mutex_lock(&wilc->radio_fw_start); @@ -313,6 +333,9 @@ int wilc_bt_shutdown(void *wilc_wl_priv) dev_warn(wilc->dev, "Failed to disable BT CPU\n"); if (wilc_bt_power_down(wilc)) dev_warn(wilc->dev, "Failed to power down BT CPU\n"); + vif = wilc_get_wl_to_vif(wilc); + if (wilc->power_save_mode_request && wilc_set_power_mgmt(vif, true)) + dev_warn(wilc->dev, "Failed to set back wlan power save\n"); if (!wilc->initialized) wilc->hif_func->hif_deinit(wilc); mutex_unlock(&wilc->radio_fw_start); diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index ff8c1a40634cee9960777eb017f6b2905e6399a5..04cff3561aad847a3f58a09766d0ef0fa61603e0 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -1344,11 +1344,14 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, { struct wilc_vif *vif = netdev_priv(dev); struct wilc_priv *priv = &vif->priv; + struct wilc *wilc = vif->wilc; if (!priv->hif_drv) return -EIO; - wilc_set_power_mgmt(vif, enabled); + wilc->power_save_mode_request = enabled; + if (!wilc->bt_enabled) + wilc_set_power_mgmt(vif, enabled); return 0; } diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h index 5837f8ffe548dad1b756cdbd8543636f2be0e9b0..4c297eb95eeb143fc2f1248e616ee307afa52dbd 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.h +++ b/drivers/net/wireless/microchip/wilc1000/netdev.h @@ -213,6 +213,7 @@ struct wilc { struct clk *rtc_clk; bool initialized; u32 chipid; + bool power_save_mode_request; bool power_save_mode; int dev_irq_num; int close; @@ -289,6 +290,8 @@ struct wilc { u8 nv_mac_address[ETH_ALEN]; /* Lock to prevent concurrent start of wlan/bluetooth firmware */ struct mutex radio_fw_start; + /* Is the bluetooth part in use ? */ + bool bt_enabled; }; struct wilc_wfi_mon_priv { From patchwork Wed Feb 12 15:46:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alexis_Lothor=C3=A9?= X-Patchwork-Id: 864778 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8ECDE260A33; Wed, 12 Feb 2025 15:47:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375282; cv=none; b=NRPmzjIRF3xDW7sTwZSVo6i4/bde2S12OQ83htN5Fm+Wo3UkwVlw+XY0N+qDrp6W3CfW3ks1c0PNRx04Rhw0BLr32u3POevBsGoXYVfI41h63sMdh0UUwudwGg9/v0R3TILHjkZos1Fo7i1BWOg8bymPYgVSMVNdN5kMJPB9iK8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375282; c=relaxed/simple; bh=fYVaUjVpOZRNw0S/JxgOjIog5MTjm+jUX2SsawPqNx4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BmFibWZMWjhkIP7etAhrb1dmlevzQqOLwcZLU31H1Uooh2XJPwMfng0mBRTbA2s7cL87vftxjcAlP8KwkdxUAv9GysBklV3dHJHXREcDvA+7rB1264UWr1qNps6OmEBu73aOVzUZmc4kHXE7fCsQrSFsYmf19yNPnQzJGQS0vvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=nzQjBATA; arc=none smtp.client-ip=217.70.183.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="nzQjBATA" Received: by mail.gandi.net (Postfix) with ESMTPSA id DE26644166; Wed, 12 Feb 2025 15:47:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1739375277; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pUgTDBJ7HqgNU9e/B8PEjHEMHLmkvOsenNOHrVru48I=; b=nzQjBATAZ/NKCeU5kTh9nkowbvXCRZLIhBCTTt0Bq8Nkb3yfE9zitxrOfPhX+bp850tf14 wk2trk9a50Kbee3D1SrYegZfyiT23Af75q/kyNDr4jhG7L7yX94YgwUzlTwV3N6BlrW713 mXSoCinP5wxS/h6hiWdXcjOr41JpIsDFIOiYpBRZ2j9E4C/CRRwdEmjjKXMKnz0uyCTGxj OhnBLgmvJpow/yUMnYPBtD6GWN/ZmbTR8a8dEq9tdhXgNRfEPCvHjEi+PM4rtlZwKP6wli k0brz7y685H8tGkfZl/wm0Qcf4bMtd70t7vN0XfDZ2vJDcHWoxJvWt7aaDBPuw== From: =?utf-8?q?Alexis_Lothor=C3=A9?= Date: Wed, 12 Feb 2025 16:46:29 +0100 Subject: [PATCH 10/12] bluetooth: hci_wilc: add wilc hci driver Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250212-wilc3000_bt-v1-10-9609b784874e@bootlin.com> References: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> In-Reply-To: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> To: =?utf-8?q?Alexis_Lothor=C3=A9?= , Marcel Holtmann , Luiz Augusto von Dentz , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ajay Singh , Claudiu Beznea , Kalle Valo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nicolas Ferre , Alexandre Belloni Cc: Marek Vasut , Thomas Petazzoni , linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeggedvkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeetlhgvgihishcunfhothhhohhrrocuoegrlhgvgihishdrlhhothhhohhrvgessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepgeevgefhteffuefhheekkeelffffvdeugffgveejffdtvdffudehtedtieevteetnecukfhppedvrgdtvdemkeegvdekmehfleegtgemvgdttdemmehfkeehnecuvehluhhsthgvrhfuihiivgepfeenucfrrghrrghmpehinhgvthepvdgrtddvmeekgedvkeemfhelgegtmegvtddtmeemfhekhedphhgvlhhopegludelvddrudeikedruddrudeljegnpdhmrghilhhfrhhomheprghlvgigihhsrdhlohhthhhorhgvsegsohhothhlihhnrdgtohhmpdhnsggprhgtphhtthhopedvgedprhgtphhtthhopegtohhnohhrodgutheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhosghhsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopeguvghvihgtvghtrhgvvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdpr hgtphhtthhopehkrhiikhdoughtsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehkuhgsrgeskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqrghrmhdqkhgvrhhnvghlsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgpdhrtghpthhtoheplhhuihiirdguvghnthiisehgmhgrihhlrdgtohhm X-GND-Sasl: alexis.lothore@bootlin.com WILC3000 is a combo chip providing 802.11b/g/n and Bluetooth 5.0 capabilities. The wifi side is used either over SDIO or SPI, and the bluetooth side is used over uart, with standard hci. The wifi side is already supported by Linux. Add a dedicated bluetooth driver to support the bluetooth feature from wilc3000 chip. Similarly to other supported bluetooth chips, wilc devices need a firmware to be uploaded before being able to use bluetooth. However, the major difference is that the firmware needs to be uploaded through the wifi bus (SDIO or SPI). This constraint makes this new driver depends on the corresponding wilc wlan driver for the bluetooth setup. Once the basic BT initialization has been performed, both side can be used independently, and in parallel. Since this creates a dependency to some wlan driver, create a dedicated module (hci_wilc) rather than integrating wilc bluetooth support in hci_uart, to avoid propagating this dependency. Signed-off-by: Alexis Lothoré --- drivers/bluetooth/Kconfig | 13 ++ drivers/bluetooth/Makefile | 3 +- drivers/bluetooth/hci_uart.h | 1 + drivers/bluetooth/hci_wilc.c | 333 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 349 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 4ab32abf0f48644715d4c27ec0d2fdaccef62b76..a96607fb0cc8fed2ccb1811a4b1b4fe586396b07 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -147,6 +147,19 @@ config BT_HCIUART_NOKIA Say Y here to compile support for Nokia's H4+ protocol. +config BT_HCIUART_WILC + tristate "WILC protocol support" + depends on (WILC1000_SDIO || WILC1000_SPI) + select WILC_BT + depends on BT_HCIUART + depends on BT_HCIUART_SERDEV + select BT_HCIUART_H4 + help + The WILC uart protocol allows interacting with wilc3000 chips + with HCI over UART. The bluetooth firmware needs to be uploaded + to the chip through the main bus, so this driver needs the + corresponding wlan driver. + config BT_HCIUART_BCSP bool "BCSP protocol support" depends on BT_HCIUART diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 81856512ddd030ba8172ff106b80b4b951188cbd..a1e69884acf4ce91f02ff5592541616048b07e31 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -35,10 +35,11 @@ obj-$(CONFIG_BT_NXPUART) += btnxpuart.o obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o obj-$(CONFIG_BT_HCIRSI) += btrsi.o - btmrvl-y := btmrvl_main.o btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o +obj-$(CONFIG_BT_HCIUART_WILC) += hci_wilc.o + hci_uart-y := hci_ldisc.o hci_uart-$(CONFIG_BT_HCIUART_SERDEV) += hci_serdev.o hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index fbf3079b92a5339154f8847ff36b3c08ef49e2bb..83fc48be4335e0946853fdec32c38bf2fb195009 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -35,6 +35,7 @@ #define HCI_UART_NOKIA 10 #define HCI_UART_MRVL 11 #define HCI_UART_AML 12 +#define HCI_UART_WILC 13 #define HCI_UART_RAW_DEVICE 0 #define HCI_UART_RESET_ON_INIT 1 diff --git a/drivers/bluetooth/hci_wilc.c b/drivers/bluetooth/hci_wilc.c new file mode 100644 index 0000000000000000000000000000000000000000..97dc4620c74ef0733469839adda7890bda90406e --- /dev/null +++ b/drivers/bluetooth/hci_wilc.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Bluetooth HCI UART driver for WILC devices + * + */ +#include "linux/bitops.h" +#include "linux/byteorder/generic.h" +#include "linux/err.h" +#include "linux/gfp_types.h" +#include "net/bluetooth/bluetooth.h" +#include "net/bluetooth/hci.h" +#include +#include +#include +#include +#include +#include +#include + +#include "hci_uart.h" + +#define WILC_BT_UART_MANUFACTURER 205 +#define WILC_UART_DEFAULT_BAUDRATE 115200 +#define WILC_UART_BAUDRATE 460800 + +#define HCI_VERSION_BOOTROM 0xFF +#define HCI_VERSION_FIRMWARE 0x06 + +#define HCI_VENDOR_CMD_WRITE_MEM 0xFC52 +#define HCI_VENDOR_CMD_UPDATE_UART 0xFC53 +#define HCI_VENDOR_CMD_UPDATE_ADDR 0xFC54 +#define HCI_VENDOR_CMD_RESET 0xFC55 +#define HCI_VENDOR_CMD_READ_REG 0xFC01 + +struct wilc_adapter { + struct hci_uart hu; + struct device *dev; + void *wlan_priv; + bool flow_control; +}; + +struct wilc_data { + struct sk_buff *rx_skb; + struct sk_buff_head txq; +}; + +struct hci_update_uart_param { + __le32 baudrate; + __u8 flow_control; +} __packed; + +static int wilc_open(struct hci_uart *hu) +{ + struct wilc_data *wdata; + + BT_DBG("hci_wilc: open"); + wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); + if (!wdata) + return -ENOMEM; + skb_queue_head_init(&wdata->txq); + hu->priv = wdata; + + return 0; +} + +static int wilc_close(struct hci_uart *hu) +{ + struct wilc_data *wdata = hu->priv; + + BT_DBG("hci_wilc: close"); + skb_queue_purge(&wdata->txq); + kfree_skb(wdata->rx_skb); + kfree(wdata); + hu->priv = NULL; + return 0; +} + +static int wilc_flush(struct hci_uart *hu) +{ + struct wilc_data *wdata = hu->priv; + + BT_DBG("hci_wilc: flush"); + skb_queue_purge(&wdata->txq); + return 0; +} + +static const struct h4_recv_pkt wilc_bt_recv_pkts[] = { + { H4_RECV_ACL, .recv = hci_recv_frame }, + { H4_RECV_SCO, .recv = hci_recv_frame }, + { H4_RECV_EVENT, .recv = hci_recv_frame }, +}; + +static int wilc_recv(struct hci_uart *hu, const void *data, int len) +{ + struct wilc_data *wdata = hu->priv; + int err; + + if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) + return -EUNATCH; + wdata->rx_skb = h4_recv_buf(hu->hdev, wdata->rx_skb, data, len, + wilc_bt_recv_pkts, + ARRAY_SIZE(wilc_bt_recv_pkts)); + if (IS_ERR(wdata->rx_skb)) { + err = PTR_ERR(wdata->rx_skb); + bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err); + wdata->rx_skb = NULL; + } + + return len; +} + +static int wilc_enqueue(struct hci_uart *hu, struct sk_buff *skb) +{ + struct wilc_data *wdata = hu->priv; + + BT_DBG("hci_wilc: enqueue skb %pK", skb); + memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); + skb_queue_tail(&wdata->txq, skb); + return 0; +} + +static struct sk_buff *wilc_dequeue(struct hci_uart *hu) +{ + struct wilc_data *wdata = hu->priv; + + BT_DBG("hci_wilc: dequeue skb"); + return skb_dequeue(&wdata->txq); +} + +static int _set_uart_settings(struct hci_uart *hu, unsigned int speed, + bool flow_control) +{ + struct hci_update_uart_param param; + int ret; + + param.baudrate = cpu_to_le32(speed); + param.flow_control = flow_control ? 1 : 0; + ret = __hci_cmd_sync_status(hu->hdev, HCI_VENDOR_CMD_UPDATE_UART, + sizeof(param), ¶m, HCI_CMD_TIMEOUT); + if (ret) { + BT_ERR("Failed to update UART settings"); + return ret; + } + + serdev_device_set_baudrate(hu->serdev, speed); + serdev_device_set_flow_control(hu->serdev, flow_control); + + return 0; +} + +static int wilc_set_baudrate(struct hci_uart *hu, unsigned int speed) +{ + struct wilc_adapter *wilc_adapter; + + BT_INFO("WILC uart settings update request: speed=%d", speed); + wilc_adapter = serdev_device_get_drvdata(hu->serdev); + + return _set_uart_settings(hu, speed, wilc_adapter->flow_control); +} + +static int check_firmware_running(struct hci_uart *hu) +{ + struct hci_rp_read_local_version *version; + struct sk_buff *skb; + int ret = 0; + + BT_DBG("Resetting bluetooth chip"); + ret = __hci_cmd_sync_status(hu->hdev, HCI_OP_RESET, 0, NULL, + HCI_CMD_TIMEOUT); + if (ret) { + BT_ERR("Can not reset wilc"); + return ret; + } + + BT_DBG("Checking chip state"); + skb = __hci_cmd_sync(hu->hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, + HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("Error while checking bootrom"); + return PTR_ERR(skb); + } + + if (skb->len != sizeof(struct hci_rp_read_local_version)) { + BT_ERR("Can not read local version"); + return -1; + } + version = (struct hci_rp_read_local_version *)skb->data; + BT_DBG("Status: 0x%1X, HCI version: 0x%1X", version->status, + version->hci_ver); + kfree_skb(skb); + if (version->hci_ver != HCI_VERSION_FIRMWARE) { + BT_ERR("Bluetooth firmware is not running !"); + if (version->hci_ver == HCI_VERSION_BOOTROM) + BT_WARN("Bootrom is running"); + return 1; + } + BT_DBG("Firmware is running"); + return 0; +} + +static int wilc_setup(struct hci_uart *hu) +{ + struct wilc_adapter *wilc_adapter; + int ret; + + BT_DBG("hci_wilc: setup"); + serdev_device_set_baudrate(hu->serdev, WILC_UART_DEFAULT_BAUDRATE); + serdev_device_set_flow_control(hu->serdev, false); + ret = check_firmware_running(hu); + if (ret) + return ret; + + BT_DBG("Updating firmware uart settings"); + + wilc_adapter = serdev_device_get_drvdata(hu->serdev); + ret = _set_uart_settings(&wilc_adapter->hu, WILC_UART_BAUDRATE, true); + if (ret) { + BT_ERR("Failed to reconfigure firmware uart settings"); + return ret; + } + wilc_adapter->flow_control = true; + + BT_INFO("Wilc successfully initialized"); + return ret; +} + +static const struct hci_uart_proto wilc_bt_proto = { + .id = HCI_UART_WILC, + .name = "Microchip", + .manufacturer = WILC_BT_UART_MANUFACTURER, + .init_speed = WILC_UART_DEFAULT_BAUDRATE, + .open = wilc_open, + .close = wilc_close, + .flush = wilc_flush, + .recv = wilc_recv, + .enqueue = wilc_enqueue, + .dequeue = wilc_dequeue, + .setup = wilc_setup, + .set_baudrate = wilc_set_baudrate, +}; + +static int wilc_bt_serdev_probe(struct serdev_device *serdev) +{ + struct wilc_adapter *wilc_adapter; + struct device_node *wlan_node; + void *wlan = NULL; + int ret; + + wilc_adapter = kzalloc(sizeof(*wilc_adapter), GFP_KERNEL); + if (!wilc_adapter) + return -ENOMEM; + + wlan_node = of_parse_phandle(serdev->dev.of_node, "wlan", 0); + if (!wlan_node) { + BT_ERR("Can not run wilc bluetooth without wlan node"); + ret = -EINVAL; + goto exit_free_adapter; + } + +#if IS_ENABLED(CONFIG_WILC1000_SDIO) + wlan = wilc_sdio_get_byphandle(wlan_node); +#endif +#if IS_ENABLED(CONFIG_WILC1000_SPI) + if (!wlan || wlan == ERR_PTR(-EPROBE_DEFER)) + wlan = wilc_spi_get_byphandle(wlan_node); +#endif + if (IS_ERR(wlan)) { + pr_warn("Can not initialize bluetooth: %pe\n", wlan); + ret = PTR_ERR(wlan); + goto exit_put_wlan_node; + } + + of_node_put(wlan_node); + wilc_adapter->wlan_priv = wlan; + ret = wilc_bt_init(wlan); + if (ret) { + pr_err("Failed to initialize bluetooth firmware (%d)\n", ret); + goto exit_put_wlan; + } + + wilc_adapter->dev = &serdev->dev; + wilc_adapter->hu.serdev = serdev; + wilc_adapter->flow_control = false; + serdev_device_set_drvdata(serdev, wilc_adapter); + ret = hci_uart_register_device(&wilc_adapter->hu, &wilc_bt_proto); + if (ret) { + dev_err(&serdev->dev, "Failed to register hci device"); + goto exit_deinit_bt; + } + + dev_info(&serdev->dev, "WILC hci interface registered"); + return 0; + +exit_deinit_bt: + wilc_bt_shutdown(wlan); +exit_put_wlan: + wilc_put(wlan); +exit_put_wlan_node: + of_node_put(wlan_node); +exit_free_adapter: + kfree(wilc_adapter); + return ret; +} + +static void wilc_bt_serdev_remove(struct serdev_device *serdev) +{ + struct wilc_adapter *wilc_adapter = serdev_device_get_drvdata(serdev); + + hci_uart_unregister_device(&wilc_adapter->hu); + wilc_bt_shutdown(wilc_adapter->wlan_priv); + wilc_put(wilc_adapter->wlan_priv); + kfree(wilc_adapter); +} + +static const struct of_device_id wilc_bt_of_match[] = { + { .compatible = "microchip,wilc3000-bt" }, + {}, +}; +MODULE_DEVICE_TABLE(of, wilc_bt_of_match); + +static struct serdev_device_driver wilc_bt_serdev_driver = { + .probe = wilc_bt_serdev_probe, + .remove = wilc_bt_serdev_remove, + .driver = { + .name = "hci_uart_wilc", + .of_match_table = of_match_ptr(wilc_bt_of_match), + }, +}; + +module_serdev_device_driver(wilc_bt_serdev_driver) +MODULE_AUTHOR("Alexis Lothoré "); +MODULE_DESCRIPTION("Bluetooth HCI Uart for WILC devices"); +MODULE_LICENSE("GPL"); From patchwork Wed Feb 12 15:46:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alexis_Lothor=C3=A9?= X-Patchwork-Id: 864777 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 00D78262151; Wed, 12 Feb 2025 15:48:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375285; cv=none; b=E0/FHMWe2iP1OlQHy5rzfQss/UeXWjz6F5hd08ewyx87MntF34eq9xptZPW0FVnK2KP3ARqrZFqojSRm++DOZn1gQvK3xqu3ARN5ib/7nowGI8OH3kdVF70Rbt/de1ygqYmyTlKXa6UZJ+zDFZ57DQ9rfzWknctaz7kuStfGcVE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739375285; c=relaxed/simple; bh=osZmc1DPVoTq245gL1CMMReUC2xc6UC5A8bH+WgUWnc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qcxsns8x82jdNw5bJCUjjDzFLNXMbPL68wwDflEXh5AXz0kCDDZczttCZ8iyfyAP4XheWMEFYJ7xMShsYNO3mNcJ0Nu9cwMucxYK/nYq/Hr98x4sCyUT+ObhCJ3I1ftobM7SU4RxslAzq22Zch9KDsuoUQJyeWM2GgET9kxsetU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=mXvv70m2; arc=none smtp.client-ip=217.70.183.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="mXvv70m2" Received: by mail.gandi.net (Postfix) with ESMTPSA id 364144416E; Wed, 12 Feb 2025 15:47:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1739375280; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=P0G+yYadJWDhMsM9S6K3wOyG/oWy+c8825+nanSQpks=; b=mXvv70m2Am4yO9Kvh96qPNwuxJRncLele/NuEh6/2t4WDnmi3Z/YfV9XJ2Sc+NNlAW0FgG 7hxEycTIR8B7mq2rLD3m96VSZMlRCDVvtNR9IBwJNWyRy4Pn7VQaOeOhgeNU/N/dFdaHVl s+/443rY8H5dyrNEHa/6aNADLCq0wzn7oTBUF1MwUAdluXbD+hW2ESqaNHFvMtwvDuSLDg MYi+Ord8vFvRNsqeodt+svNBmSq85ft2DTI3BGiwtT0pIUpdrIoqKUTKpraxtbIn+5K08P hfH5ZQyps+2ZiKs537yNF+taQyBpbRY6dPth7dbiUyFT0Bhs7BFXZdYO6rVQtg== From: =?utf-8?q?Alexis_Lothor=C3=A9?= Date: Wed, 12 Feb 2025 16:46:31 +0100 Subject: [PATCH 12/12] MAINTAINERS: add entry for new wilc3000 bluetooth driver Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250212-wilc3000_bt-v1-12-9609b784874e@bootlin.com> References: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> In-Reply-To: <20250212-wilc3000_bt-v1-0-9609b784874e@bootlin.com> To: =?utf-8?q?Alexis_Lothor=C3=A9?= , Marcel Holtmann , Luiz Augusto von Dentz , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Ajay Singh , Claudiu Beznea , Kalle Valo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nicolas Ferre , Alexandre Belloni Cc: Marek Vasut , Thomas Petazzoni , linux-bluetooth@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-Mailer: b4 0.14.2 X-GND-State: clean X-GND-Score: -100 X-GND-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdeggedvkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfitefpfffkpdcuggftfghnshhusghstghrihgsvgenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephfffufggtgfgkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeetlhgvgihishcunfhothhhohhrrocuoegrlhgvgihishdrlhhothhhohhrvgessghoohhtlhhinhdrtghomheqnecuggftrfgrthhtvghrnhepgeevgefhteffuefhheekkeelffffvdeugffgveejffdtvdffudehtedtieevteetnecukfhppedvrgdtvdemkeegvdekmehfleegtgemvgdttdemmehfkeehnecuvehluhhsthgvrhfuihiivgepkeenucfrrghrrghmpehinhgvthepvdgrtddvmeekgedvkeemfhelgegtmegvtddtmeemfhekhedphhgvlhhopegludelvddrudeikedruddrudeljegnpdhmrghilhhfrhhomheprghlvgigihhsrdhlohhthhhorhgvsegsohhothhlihhnrdgtohhmpdhnsggprhgtphhtthhopedvgedprhgtphhtthhopegtohhnohhrodgutheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhosghhsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopeguvghvihgtvghtrhgvvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdpr hgtphhtthhopehkrhiikhdoughtsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehkuhgsrgeskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqrghrmhdqkhgvrhhnvghlsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgpdhrtghpthhtoheplhhuihiirdguvghnthiisehgmhgrihhlrdgtohhm X-GND-Sasl: alexis.lothore@bootlin.com Add MAINTAINERS entry for the new bluetooth driver in drivers/bluetooth/hci_wilc.c Signed-off-by: Alexis Lothoré --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 82b227c3939a49996498f4e829541eb5380ab2b3..2f02aecc21e96a2f9e6ff2de3864bb2d2b964127 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15526,6 +15526,13 @@ L: linux-wireless@vger.kernel.org S: Supported F: drivers/net/wireless/microchip/wilc1000/ +MICROCHIP WILC3000 BLUETOOTH DRIVER +M: Alexis Lothoré +L: linux-bluetooth@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/net/bluetooth/microchip,wilc3000-bt.yaml +F: drivers/bluetooth/hci_wilc.c + MICROSEMI MIPS SOCS M: Alexandre Belloni M: UNGLinuxDriver@microchip.com