From patchwork Sun Jul 16 11:21:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Molton X-Patchwork-Id: 9842907 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E2C9860393 for ; Sun, 16 Jul 2017 11:44:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA61228484 for ; Sun, 16 Jul 2017 11:44:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF417284FE; Sun, 16 Jul 2017 11:44:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C87C28484 for ; Sun, 16 Jul 2017 11:44:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751276AbdGPLoR (ORCPT ); Sun, 16 Jul 2017 07:44:17 -0400 Received: from [217.148.43.144] ([217.148.43.144]:46908 "EHLO mnementh.co.uk" rhost-flags-FAIL-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1751087AbdGPLoQ (ORCPT ); Sun, 16 Jul 2017 07:44:16 -0400 Received: from 12.3.208.46.dyn.plus.net ([46.208.3.12] helo=localhost.localdomain) by mnementh.co.uk with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.80) (envelope-from ) id 1dWhcX-00083y-Hn; Sun, 16 Jul 2017 11:21:54 +0000 From: Ian Molton To: linux-wireless@vger.kernel.org Cc: arend.vanspriel@broadcom.com, franky.lin@broadcom.com, hante.meuleman@broadcom.com Subject: [PATCH 06/21] brcmfmac: Clean up SDIO IO functions. Date: Sun, 16 Jul 2017 12:21:14 +0100 Message-Id: <20170716112129.10206-7-ian@mnementh.co.uk> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170716112129.10206-1-ian@mnementh.co.uk> References: <20170716112129.10206-1-ian@mnementh.co.uk> X-Spam_score: -2.9 X-Spam_score_int: -28 X-Spam_bar: -- X-Spam_report: Spam detection software, running on the system "mnementh.co.uk", has identified this incoming email as possible spam. The original message has been attached to this so you can view it (if it isn't spam) or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: --- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 266 ++++++++ 1 file changed, 105 insertions(+), 161 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 2b527d2a2f8a..06e6a72245a7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -232, 6 +232, 52 @@ void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, sdiodev->state = state; } [...] Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP 0.0 TVD_RCVD_IP Message was received from an IP address -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP --- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 266 ++++++++------------- 1 file changed, 105 insertions(+), 161 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 2b527d2a2f8a..06e6a72245a7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -232,6 +232,52 @@ void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, sdiodev->state = state; } +static int +brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) +{ + int err = 0, i; + u32 addr; + + addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; + + for (i = 0; i < 3; i++) { + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr & 0xff, + &err); + if (err) + break; + + addr = addr >> 8; + } + + return err; +} + +// bar0 = top 17 bits. lowest of which seems to be SBSDIO_SB_ACCESS_2_4B_FLAG +// if accessing a different bar, program the bar0 value into SBSDIO_FUNC1_SBADDRLOW +// addr loses its top 17 bits and is ORed with SBSDIO_SB_ACCESS_2_4B_FLAG +// Appears to only be required for 4 byte operations. +// Value of sdiodev->sbwad is set here and used elsewhere (Why?) +static int +brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr) +{ + uint bar0 = *addr & SBSDIO_SBWINDOW_MASK; + int err = 0; + + if (bar0 != sdiodev->sbwad) { + printk("WTAF? %08x %08x\n", bar0, sdiodev->sbwad); + err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0); + if (err) + return err; + + sdiodev->sbwad = bar0; + } + + *addr &= SBSDIO_SB_OFT_ADDR_MASK; + *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + return 0; +} + static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte, uint regaddr) { int err_ret; @@ -250,93 +296,45 @@ static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte, uint re return err_ret; } -static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, - u32 addr, u8 regsz, void *data, bool write) -{ - struct sdio_func *func; - int ret = -EINVAL; - - brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", - write, fn, addr, regsz); - - /* only allow byte access on F0 */ - if (WARN_ON(regsz > 1 && !fn)) - return -EINVAL; - func = sdiodev->func[fn]; - - switch (regsz) { - case 1: - if (write) { - if (fn) - sdio_writeb(func, *(u8 *)data, addr, &ret); - else - ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data, addr); - } else { - if (fn) - *(u8 *)data = sdio_readb(func, addr, &ret); - else - *(u8 *)data = sdio_f0_readb(func, addr, &ret); - } - break; - case 2: - if (write) - sdio_writew(func, *(u16 *)data, addr, &ret); - else - *(u16 *)data = sdio_readw(func, addr, &ret); - break; - case 4: - if (write) - sdio_writel(func, *(u32 *)data, addr, &ret); - else - *(u32 *)data = sdio_readl(func, addr, &ret); - break; - default: - brcmf_err("invalid size: %d\n", regsz); - break; - } - - if (ret) - brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", - write ? "write" : "read", fn, addr, ret); - - return ret; -} - static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 regsz, void *data) { - u8 func; - s32 retry = 0; int ret; - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) - return -ENOMEDIUM; - /* * figure out how to read the register based on address range * 0x00 ~ 0x7FF: function 0 CCCR and FBR * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers * The rest: function 1 silicon backplane core registers + * f0 writes must be bytewise */ - if ((addr & ~REG_F0_REG_MASK) == 0) - func = SDIO_FUNC_0; - else - func = SDIO_FUNC_1; - do { - /* for retry wait for 1 ms till bus get settled down */ - if (retry) - usleep_range(1000, 2000); - - ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, - data, true); + if ((addr & ~REG_F0_REG_MASK) == 0) { + if (WARN_ON(regsz > 1)) + return -EINVAL; + ret = brcmf_sdiod_f0_writeb(sdiodev->func[0], *(u8 *)data, addr); + } + else { + switch (regsz) { + case 1: + sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret); + break; + case 4: + ret = brcmf_sdiod_addrprep(sdiodev, &addr); + if (ret) + goto done; - } while (ret != 0 && ret != -ENOMEDIUM && - retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); + sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret); + break; + default: + BUG(); + ret = -EINVAL; + break; + } + } - if (ret == -ENOMEDIUM) - brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); - else if (ret != 0) { +#if 0 + if (ret != 0) { /* * SleepCSR register access can fail when * waking up the device so reduce this noise @@ -349,47 +347,50 @@ static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n", func, addr, ret); } +#endif +done: return ret; } static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 regsz, void *data) { - u8 func; - s32 retry = 0; int ret; - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) - return -ENOMEDIUM; - /* * figure out how to read the register based on address range * 0x00 ~ 0x7FF: function 0 CCCR and FBR * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers * The rest: function 1 silicon backplane core registers + * f0 reads must be bytewise */ - if ((addr & ~REG_F0_REG_MASK) == 0) - func = SDIO_FUNC_0; - else - func = SDIO_FUNC_1; - - do { - memset(data, 0, regsz); - - /* for retry wait for 1 ms till bus get settled down */ - if (retry) - usleep_range(1000, 2000); - - ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, - data, false); + if ((addr & ~REG_F0_REG_MASK) == 0) { + if (WARN_ON(regsz > 1)) + return -EINVAL; + *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret); + } + else { + switch (regsz) { + case 1: + *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret); + break; + case 4: + ret = brcmf_sdiod_addrprep(sdiodev, &addr); + if (ret) + goto done; - } while (ret != 0 && ret != -ENOMEDIUM && - retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); + *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret); + break; + default: + BUG(); + ret = -EINVAL; + break; + } + } - if (ret == -ENOMEDIUM) - brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); - else if (ret != 0) { +#if 0 + if (ret != 0) { /* * SleepCSR register access can fail when * waking up the device so reduce this noise @@ -402,62 +403,19 @@ static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n", func, addr, ret); } +#endif +done: return ret; } -static int -brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) -{ - int err = 0, i; - u32 addr; - - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) - return -ENOMEDIUM; - - addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; - - for (i = 0; i < 3; i++) { - brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr & 0xff, - &err); - if (err) - break; - - addr = addr >> 8; - } - - return err; -} - -static int -brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr) -{ - uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; - int err = 0; - - if (bar0 != sdiodev->sbwad) { - err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0); - if (err) - return err; - - sdiodev->sbwad = bar0; - } - - *addr &= SBSDIO_SB_OFT_ADDR_MASK; - - *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - return 0; -} u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) { - u8 data; + u8 data = 0; int retval; - brcmf_dbg(SDIO, "addr:0x%08x\n", addr); - retval = brcmf_sdiod_reg_read(sdiodev, addr, sizeof(data), &data); - brcmf_dbg(SDIO, "data:0x%02x\n", data); + retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data); if (ret) *ret = retval; @@ -470,15 +428,8 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) u32 data = 0; int retval; - brcmf_dbg(SDIO, "addr:0x%08x\n", addr); - retval = brcmf_sdiod_addrprep(sdiodev, &addr); - if (retval) - goto done; - retval = brcmf_sdiod_reg_read(sdiodev, addr, sizeof(data), &data); - - brcmf_dbg(SDIO, "data:0x%08x\n", data); + retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data); -done: if (ret) *ret = retval; @@ -490,8 +441,7 @@ void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, { int retval; - brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); - retval = brcmf_sdiod_reg_write(sdiodev, addr, sizeof(data), &data); + retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data); if (ret) *ret = retval; @@ -502,14 +452,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, { int retval; - brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); - retval = brcmf_sdiod_addrprep(sdiodev, &addr); - if (retval) - goto done; - - retval = brcmf_sdiod_reg_write(sdiodev, addr, sizeof(data), &data); + retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data); -done: if (ret) *ret = retval; }