问题:Rockchip RV1109平台,系统软重启后,wifi模块不能正常工作;断电重启后,wifi模块正常。
Rockchip回复:RTL8821CS 这颗模块比较特别, 由于模块CHIP_EN 没有引出来,reboot时断电不完全。所以RK参考设计是有用单独gpio控电vbat,这个要看你们硬件设计,是否预留相应gpio。可打下面补丁进行控制。
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
index a4076b888f7d..1bd289e2b4bc 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
@@ -100,7 +100,7 @@
clocks = <&rk808 1>;
clock-names = "ext_clock";
pinctrl-names = "default";
- pinctrl-0 = <&wifi_enable_h>;
+ pinctrl-0 = <&wifi_enable_h &wifi_poweren_h>;
/*
* On the module itself this is one of these (depending
@@ -109,6 +109,7 @@
* - PDN (power down when low)
*/
reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; /* GPIO0_B2 */
+ poweren-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; /* GPIO0_B2 */
};
vcc3v3_sys: vcc3v3-sys {
@@ -731,4 +732,14 @@
rockchip,pins = <1 2 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
+
+ sdio-pwrseq {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_poweren_h: wifi-poweren-h {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
};
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
#include <linux/mmc/host.h>
@@ -24,12 +25,27 @@ struct mmc_pwrseq_simple {
bool clk_enabled;
struct clk *ext_clk;
struct gpio_descs *reset_gpios;
+ struct gpio_descs *poweren_gpios;
};
static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
int value)
{
struct gpio_descs *reset_gpios = pwrseq->reset_gpios;
+ struct gpio_descs *poweren_gpios = pwrseq->poweren_gpios;
+
+ if (!IS_ERR(poweren_gpios)) {
+ int i;
+ int values[poweren_gpios->ndescs];
+
+ for (i = 0; i < poweren_gpios->ndescs; i++)
+ values[i] = value;
+
+ gpiod_set_array_value_cansleep(
+ poweren_gpios->ndescs, poweren_gpios->desc, values);
+ }
+
+ msleep(200); //200ms
if (!IS_ERR(reset_gpios)) {
int i;
@@ -41,6 +57,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
gpiod_set_array_value_cansleep(
reset_gpios->ndescs, reset_gpios->desc, values);
}
+
}
static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
@@ -122,6 +139,14 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host,
ret = PTR_ERR(pwrseq->reset_gpios);
goto clk_put;
}
+
+ pwrseq->poweren_gpios = gpiod_get_array(dev, "poweren", GPIOD_OUT_HIGH);
+ if (IS_ERR(pwrseq->poweren_gpios) &&
+ PTR_ERR(pwrseq->poweren_gpios) != -ENOENT &&
+ PTR_ERR(pwrseq->poweren_gpios) != -ENOSYS) {
+ ret = PTR_ERR(pwrseq->poweren_gpios);
+ //goto clk_put;
+ }
pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;