<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>i.MX Processors中的主题 Software Clock Gating on WiFi SDIO</title>
    <link>https://community.nxp.com/t5/i-MX-Processors/Software-Clock-Gating-on-WiFi-SDIO/m-p/2028960#M233048</link>
    <description>&lt;P&gt;We are using the NXP i.MX8MM processor with the 5.15.71 kernel and have ported Murata’s cyw-fmac backported driver(kirkstone Godzilla release) for Murata's Wi-Fi chip module (LBEE5XV2EA). Here, I want to discuss the issue of SDIO clock gating. Specifically, the SDIO clock for the Wi-Fi chip remains enabled continuously even when there is no communication happening over Wi-Fi. I want to enable &lt;STRONG&gt;software&lt;/STRONG&gt; clock gating support for the Wi-Fi SDIO interface.&lt;/P&gt;&lt;P&gt;Interestingly, on another SDIO interface where an eMMC is connected, clock gating is already functioning as expected.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Debugging Steps Performed&lt;/STRONG&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Driver and Function Analysis:&lt;/STRONG&gt;&lt;/LI&gt;&lt;UL&gt;&lt;LI&gt;The Murata Wi-Fi brcmfmac driver uses &lt;STRONG&gt;sdio_readl&lt;/STRONG&gt;/&lt;STRONG&gt;writel&lt;/STRONG&gt; APIs from “&lt;STRONG&gt;mmc/core/sdio_io.c”&lt;/STRONG&gt; for read/write operations with the SDIO interface. Which directly reads/writes from the address space of a given SDIO.&lt;/LI&gt;&lt;LI&gt;The i.MX8MM’s SDIO driver (“&lt;STRONG&gt;mmc/host/sdhci-esdhc-imx.c&lt;/STRONG&gt;”) performs these operations using readl() which uses IOMEM address with some offset.&lt;/LI&gt;&lt;/UL&gt;&lt;LI&gt;&lt;STRONG&gt;Kernel Patch Impact:&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;There is a specific patch in the kernel where SDIO clock gating support was removed from the SDIO. Here is the commit:&lt;/P&gt;&lt;P&gt;&lt;A href="https://patchwork.kernel.org/project/linux-mmc/patch/1443776171-7127-1-git-send-email-ulf.hansson@linaro.org/" target="_blank" rel="noopener"&gt;https://patchwork.kernel.org/project/linux-mmc/patch/1443776171-7127-1-git-send-email-ulf.hansson@linaro.org/&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;UL&gt;&lt;LI&gt;I attempted to re-implement clock hold and clock release functionality to gate the clock before every read/write operation from the above commit. However, the Wi-Fi module failed to operate correctly with this implementation.&lt;/LI&gt;&lt;/UL&gt;&lt;/OL&gt;&lt;P&gt;&lt;STRONG&gt;Attempted Approaches&lt;/STRONG&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Clock Gating via mmc_set_ios Operations&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;To manage the clock gating, I implemented the following functions in &lt;STRONG&gt;clock_hold&lt;/STRONG&gt; and&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;STRONG&gt;clock_release&lt;/STRONG&gt;:&lt;/P&gt;&lt;P&gt;void &lt;STRONG&gt;mmc_gate_clock&lt;/STRONG&gt;(struct mmc_host *host) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned long flags;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; spin_lock_irqsave(&amp;amp;host-&amp;gt;clk_lock, flags);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; host-&amp;gt;clk_old = host-&amp;gt;ios.clock;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; host-&amp;gt;ios.clock = 0;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; host-&amp;gt;clk_gated = true;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; spin_unlock_irqrestore(&amp;amp;host-&amp;gt;clk_lock, flags);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mmc_set_ios(host);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;void &lt;STRONG&gt;mmc_ungate_clock&lt;/STRONG&gt;(struct mmc_host *host) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (host-&amp;gt;clk_old) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BUG_ON(host-&amp;gt;ios.clock);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __mmc_set_clock(host, host-&amp;gt;clk_old);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Description:&lt;/STRONG&gt;&lt;/LI&gt;&lt;UL&gt;&lt;LI&gt;The mmc_gate_clock() function gates the clock by setting the ios.clock value to 0.&lt;/LI&gt;&lt;LI&gt;The mmc_ungate_clock() function restores the clock using a cached clock value (clk_old).&lt;/LI&gt;&lt;/UL&gt;&lt;LI&gt;&lt;STRONG&gt;Challenges:&lt;/STRONG&gt;&lt;/LI&gt;&lt;UL&gt;&lt;LI&gt;These functions rely on ios operations of the host driver.&lt;/LI&gt;&lt;LI&gt;In the i.MX MMC driver (&lt;STRONG&gt;mmc/host/sdhci-esdhc-imx.c&lt;/STRONG&gt;), ios operations are not fully implemented. However, there is a &lt;STRONG&gt;mmc_host_ops &lt;/STRONG&gt;struct in the driver that allows &lt;STRONG&gt;set_ios&lt;/STRONG&gt; partial implementation, which made this approach partially functional.&lt;/LI&gt;&lt;LI&gt;Despite these adjustments, the WiFi module failed to operate correctly.&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt;&lt;/P&gt;&lt;OL&gt;&lt;UL&gt;&lt;LI&gt;Is there any alternative approach to enable software clock gating on the WiFi SDIO interface?&lt;/LI&gt;&lt;/UL&gt;&lt;/OL&gt;</description>
    <pubDate>Thu, 16 Jan 2025 10:42:02 GMT</pubDate>
    <dc:creator>dhvani-champaneri</dc:creator>
    <dc:date>2025-01-16T10:42:02Z</dc:date>
    <item>
      <title>Software Clock Gating on WiFi SDIO</title>
      <link>https://community.nxp.com/t5/i-MX-Processors/Software-Clock-Gating-on-WiFi-SDIO/m-p/2028960#M233048</link>
      <description>&lt;P&gt;We are using the NXP i.MX8MM processor with the 5.15.71 kernel and have ported Murata’s cyw-fmac backported driver(kirkstone Godzilla release) for Murata's Wi-Fi chip module (LBEE5XV2EA). Here, I want to discuss the issue of SDIO clock gating. Specifically, the SDIO clock for the Wi-Fi chip remains enabled continuously even when there is no communication happening over Wi-Fi. I want to enable &lt;STRONG&gt;software&lt;/STRONG&gt; clock gating support for the Wi-Fi SDIO interface.&lt;/P&gt;&lt;P&gt;Interestingly, on another SDIO interface where an eMMC is connected, clock gating is already functioning as expected.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Debugging Steps Performed&lt;/STRONG&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Driver and Function Analysis:&lt;/STRONG&gt;&lt;/LI&gt;&lt;UL&gt;&lt;LI&gt;The Murata Wi-Fi brcmfmac driver uses &lt;STRONG&gt;sdio_readl&lt;/STRONG&gt;/&lt;STRONG&gt;writel&lt;/STRONG&gt; APIs from “&lt;STRONG&gt;mmc/core/sdio_io.c”&lt;/STRONG&gt; for read/write operations with the SDIO interface. Which directly reads/writes from the address space of a given SDIO.&lt;/LI&gt;&lt;LI&gt;The i.MX8MM’s SDIO driver (“&lt;STRONG&gt;mmc/host/sdhci-esdhc-imx.c&lt;/STRONG&gt;”) performs these operations using readl() which uses IOMEM address with some offset.&lt;/LI&gt;&lt;/UL&gt;&lt;LI&gt;&lt;STRONG&gt;Kernel Patch Impact:&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;There is a specific patch in the kernel where SDIO clock gating support was removed from the SDIO. Here is the commit:&lt;/P&gt;&lt;P&gt;&lt;A href="https://patchwork.kernel.org/project/linux-mmc/patch/1443776171-7127-1-git-send-email-ulf.hansson@linaro.org/" target="_blank" rel="noopener"&gt;https://patchwork.kernel.org/project/linux-mmc/patch/1443776171-7127-1-git-send-email-ulf.hansson@linaro.org/&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;UL&gt;&lt;LI&gt;I attempted to re-implement clock hold and clock release functionality to gate the clock before every read/write operation from the above commit. However, the Wi-Fi module failed to operate correctly with this implementation.&lt;/LI&gt;&lt;/UL&gt;&lt;/OL&gt;&lt;P&gt;&lt;STRONG&gt;Attempted Approaches&lt;/STRONG&gt;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Clock Gating via mmc_set_ios Operations&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;To manage the clock gating, I implemented the following functions in &lt;STRONG&gt;clock_hold&lt;/STRONG&gt; and&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;STRONG&gt;clock_release&lt;/STRONG&gt;:&lt;/P&gt;&lt;P&gt;void &lt;STRONG&gt;mmc_gate_clock&lt;/STRONG&gt;(struct mmc_host *host) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned long flags;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; spin_lock_irqsave(&amp;amp;host-&amp;gt;clk_lock, flags);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; host-&amp;gt;clk_old = host-&amp;gt;ios.clock;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; host-&amp;gt;ios.clock = 0;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; host-&amp;gt;clk_gated = true;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; spin_unlock_irqrestore(&amp;amp;host-&amp;gt;clk_lock, flags);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mmc_set_ios(host);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;void &lt;STRONG&gt;mmc_ungate_clock&lt;/STRONG&gt;(struct mmc_host *host) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (host-&amp;gt;clk_old) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BUG_ON(host-&amp;gt;ios.clock);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __mmc_set_clock(host, host-&amp;gt;clk_old);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Description:&lt;/STRONG&gt;&lt;/LI&gt;&lt;UL&gt;&lt;LI&gt;The mmc_gate_clock() function gates the clock by setting the ios.clock value to 0.&lt;/LI&gt;&lt;LI&gt;The mmc_ungate_clock() function restores the clock using a cached clock value (clk_old).&lt;/LI&gt;&lt;/UL&gt;&lt;LI&gt;&lt;STRONG&gt;Challenges:&lt;/STRONG&gt;&lt;/LI&gt;&lt;UL&gt;&lt;LI&gt;These functions rely on ios operations of the host driver.&lt;/LI&gt;&lt;LI&gt;In the i.MX MMC driver (&lt;STRONG&gt;mmc/host/sdhci-esdhc-imx.c&lt;/STRONG&gt;), ios operations are not fully implemented. However, there is a &lt;STRONG&gt;mmc_host_ops &lt;/STRONG&gt;struct in the driver that allows &lt;STRONG&gt;set_ios&lt;/STRONG&gt; partial implementation, which made this approach partially functional.&lt;/LI&gt;&lt;LI&gt;Despite these adjustments, the WiFi module failed to operate correctly.&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt;&lt;/P&gt;&lt;OL&gt;&lt;UL&gt;&lt;LI&gt;Is there any alternative approach to enable software clock gating on the WiFi SDIO interface?&lt;/LI&gt;&lt;/UL&gt;&lt;/OL&gt;</description>
      <pubDate>Thu, 16 Jan 2025 10:42:02 GMT</pubDate>
      <guid>https://community.nxp.com/t5/i-MX-Processors/Software-Clock-Gating-on-WiFi-SDIO/m-p/2028960#M233048</guid>
      <dc:creator>dhvani-champaneri</dc:creator>
      <dc:date>2025-01-16T10:42:02Z</dc:date>
    </item>
  </channel>
</rss>

