Skip to contentSkip to conversation

Port SDIO GPIO to DTS

DISCUSSION Kyle Evans 2 participants 6 messages Jan 17, 2018 – Feb 3, 2018 5 messages not in the archive Tegra architecture support

lore
Share & tools
lore

Kyle Evans

author
#0 lore raw

I have an ASUS TF101(ventana) that I am trying to get running on mainline. It is mostly there, but there are a few issues that I believe to be dts related. I am focusing on one at a time. Currently, when I warm boot/reboot, the wireless SDIO device fails to initialize. It works great on cold boot. I'm fairly certain the problem is in the dts, but I'd like some feedback on the correct way.

From a working, pre-dts kernel I have stuff like this.

arch/arm/mach-tegra/board-tf101-sdhci.c:
...

#define TF101_WLAN_RST  TEGRA_GPIO_PK6
#define TF101_WLAN_WOW  TEGRA_GPIO_PS0
#define TF101_SDIO_WOW  TEGRA_GPIO_PY6

...
static struct embedded_sdio_data embedded_sdio_data1 = {
.cccr = {
.sdio_vsn = 2,
.multi_block = 1,
.low_speed = 0,
.wide_bus = 0,
.high_power = 1,
.high_speed = 1,
},
.cis = {
.vendor = 0x02d0,
.device = 0x4329,
},

static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = {
        .mmc_data = {
                .register_status_notify = tf101_wifi_status_register,
                .embedded_sdio = &embedded_sdio_data1,
                .built_in = 0,
        },
        .wow_gpio = TF101_SDIO_WOW,
        .cd_gpio = -1,
        .wp_gpio = -1,
        .power_gpio = -1,
        .max_clk_limit = 40000000,
};
...
static int tf101_wifi_power(int on)
{
        pr_debug("%s: %d\n", __func__, on);
#if 0
        gpio_set_value(TF101_WLAN_PWR, on);
        mdelay(100);
#endif
        gpio_set_value(TF101_WLAN_RST, on);
        mdelay(200);

        return 0;
}

static int tf101_wifi_reset(int on)

{
        pr_debug("%s: do nothing\n", __func__);
        return 0;
}

static int __init tf101_wifi_init(void)

{
        //gpio_request(TF101_WLAN_PWR, "wlan_power");
        gpio_request(TF101_WLAN_RST, "wlan_rst");
        gpio_request(TF101_WLAN_WOW, "bcmsdh_sdmmc");

        //tegra_gpio_enable(TF101_WLAN_PWR);
        tegra_gpio_enable(TF101_WLAN_RST);
        tegra_gpio_enable(TF101_WLAN_WOW);

        //gpio_direction_output(TF101_WLAN_PWR, 0);
        gpio_direction_output(TF101_WLAN_RST, 0);
        gpio_direction_input(TF101_WLAN_WOW);

        platform_device_register(&tf101_wifi_device);

        device_init_wakeup(&tf101_wifi_device.dev, 1);
        device_set_wakeup_enable(&tf101_wifi_device.dev, 0);

        return 0;
}

...

It looks like I have three GPIO lines dealing with mmc0/wlan. Can I assume WOW is Wireless pOWer?

I'm not sure of the difference between WLAN_WOW & SDIO_WOW. I'm assuming one for chip, one for radio, but I don't know their place in the dts.

From tegra20-ventana.dts I've got:

	sdhci@c8000000 {
                status = "okay";
                power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
                bus-width = <4>;
                keep-power-in-suspend;
        };

I'm guessing I need to add the other pins to power-gpois and set up mmc-pwrseq?

Regards,
Kyle

A message that is not in the archive (sent off-list or not yet received): 20180117221318.GA1594-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]

#2 lore raw

Hello Kyle,

Quoted 83 lines · Kyle Evans

I have an ASUS TF101(ventana) that I am trying to get running on mainline. It is mostly there, but there are a few issues that I believe to be dts related. I am focusing on one at a time. Currently, when I warm boot/reboot, the wireless SDIO device fails to initialize. It works great on cold boot. I'm fairly certain the problem is in the dts, but I'd like some feedback on the correct way.

From a working, pre-dts kernel I have stuff like this.

arch/arm/mach-tegra/board-tf101-sdhci.c:
...

#define TF101_WLAN_RST  TEGRA_GPIO_PK6
#define TF101_WLAN_WOW  TEGRA_GPIO_PS0
#define TF101_SDIO_WOW  TEGRA_GPIO_PY6

...
static struct embedded_sdio_data embedded_sdio_data1 = {
.cccr = {
.sdio_vsn = 2,
.multi_block = 1,
.low_speed = 0,
.wide_bus = 0,
.high_power = 1,
.high_speed = 1,
},
.cis = {
.vendor = 0x02d0,
.device = 0x4329,
},

static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = {
        .mmc_data = {
                .register_status_notify = tf101_wifi_status_register,
                .embedded_sdio = &embedded_sdio_data1,
                .built_in = 0,
        },
        .wow_gpio = TF101_SDIO_WOW,
        .cd_gpio = -1,
        .wp_gpio = -1,
        .power_gpio = -1,
        .max_clk_limit = 40000000,
};
...
static int tf101_wifi_power(int on)
{
        pr_debug("%s: %d\n", __func__, on);
#if 0
        gpio_set_value(TF101_WLAN_PWR, on);
        mdelay(100);
#endif
        gpio_set_value(TF101_WLAN_RST, on);
        mdelay(200);

        return 0;
}

static int tf101_wifi_reset(int on)

{
        pr_debug("%s: do nothing\n", __func__);
        return 0;
}

static int __init tf101_wifi_init(void)

{
        //gpio_request(TF101_WLAN_PWR, "wlan_power");
        gpio_request(TF101_WLAN_RST, "wlan_rst");
        gpio_request(TF101_WLAN_WOW, "bcmsdh_sdmmc");

        //tegra_gpio_enable(TF101_WLAN_PWR);
        tegra_gpio_enable(TF101_WLAN_RST);
        tegra_gpio_enable(TF101_WLAN_WOW);

        //gpio_direction_output(TF101_WLAN_PWR, 0);
        gpio_direction_output(TF101_WLAN_RST, 0);
        gpio_direction_input(TF101_WLAN_WOW);

        platform_device_register(&tf101_wifi_device);

        device_init_wakeup(&tf101_wifi_device.dev, 1);
        device_set_wakeup_enable(&tf101_wifi_device.dev, 0);

        return 0;
}
Quoted 4 lines

...

It looks like I have three GPIO lines dealing with mmc0/wlan. Can I assume WOW is Wireless pOWer?

WoW should stand for Wake on Wireless [0]. You could ping your TF101 while it is suspended and it will wake up.

[0] https://wireless.wiki.kernel.org/en/users/documentation/wowlan

Quoted 13 lines

I'm not sure of the difference between WLAN_WOW & SDIO_WOW. I'm assuming one for chip, one for radio, but I don't know their place in the dts.

From tegra20-ventana.dts I've got:

	sdhci@c8000000 {
                status = "okay";
                power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
                bus-width = <4>;
                keep-power-in-suspend;
        };
Quoted 2 lines

I'm guessing I need to add the other pins to power-gpois and set up mmc-pwrseq?

The 'power-gpois' that you've defined looks fine and probably sufficient to get WiFi up and running.

Take a look at the changes that were needed to get WiFi working on Acer A500, maybe some of it also applicable to TF101:

https://github.com/digetx/picasso_upstream_support/commit/beab29d4f172836c5faad91d3232a7c77c5fc6fb
https://github.com/digetx/picasso_upstream_support/commit/165e488e82c97fa1da6ccfe832a43569136000bc
https://github.com/digetx/picasso_upstream_support/commit/7e584ca4108707c6469a04bf92d9b659ce76c5cc
https://github.com/digetx/picasso_upstream_support/commit/4f0d7ac43592826e03f766005a3720ecc5ad1476#diff-4ce775d33b1aadd3981ea13ea140eca6R702

Also note that (at least on A500) BCM chip also provides Bluetooth and the 'power/rst' GPIO affects both Wifi and Bluetooth.

A message that is not in the archive (sent off-list or not yet received): 91eab00b-9cfa-f150-369e-2426f9b9dc42-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

author
#4 lore raw

* Dmitry Osipenko <[email protected]>:

Quoted 24 lines

Hello Kyle,

Quoted 21 lines · Kyle Evans

I have an ASUS TF101(ventana) that I am trying to get running on mainline. It is mostly there, but there are a few issues that I believe to be dts related. I am focusing on one at a time. Currently, when I warm boot/reboot, the wireless SDIO device fails to initialize. It works great on cold boot. I'm fairly certain the problem is in the dts, but I'd like some feedback on the correct way.

I'm not sure of the difference between WLAN_WOW & SDIO_WOW. I'm assuming one for chip, one for radio, but I don't know their place in the dts.

From tegra20-ventana.dts I've got:

	sdhci@c8000000 {
                status = "okay";
                power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
                bus-width = <4>;
                keep-power-in-suspend;
        };
Quoted 8 lines
Quoted 2 lines

I'm guessing I need to add the other pins to power-gpois and set up mmc-pwrseq?

The 'power-gpois' that you've defined looks fine and probably sufficient to get WiFi up and running.

Take a look at the changes that were needed to get WiFi working on Acer A500, maybe some of it also applicable to TF101:

Thanks for this. I have made some progress by adding regulator nodes for pins D,1 & K,6, but am now getting the following error on second boot.

[    2.425281] mmc2: Invalid maximum block size, assuming 512 bytes
[    2.480692] mmc2: SDHCI controller on c8000000.sdhci [c8000000.sdhci] using ADMA
[    2.494647] mmc2: error -110 whilst initialising SDIO card
Quoted 2 lines

https://github.com/digetx/picasso_upstream_support/commit/beab29d4f172836c5faad91d3232a7c77c5fc6fb

HACK: mmc: sdio: Add workaround for wrongly reported CCCR

Would you recommend this over setting cap-sd-highspeed in the DT? Without either communication has been trouble free thus far.

Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/165e488e82c97fa1da6ccfe832a43569136000bc

mmc: Add "ignore mmc pm notify" functionality

This does not apply cleanly, what are the symptoms?

Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/7e584ca4108707c6469a04bf92d9b659ce76c5cc

ARM: tegra: Add Picasso board file

I am trying to implement this, but as-is boot hangs before u-boot clears.

static struct gpiod_lookup_table bluetooth_gpio_lookup = {
       .dev_id = "rfkill_gpio.1",
       .table = {
               GPIO_LOOKUP("tegra-gpio", 160, "reset", 0),
               { },
       },
}

Where does 160 come from?

static int __init tegra_picasso_wifi_pwr_and_reset(void)

{
       if (!of_machine_is_compatible("acer,picasso"))
               return 0;

       writel(0x00004000, IO_TO_VIRT(0x6000D928));
       writel(0x00004040, IO_TO_VIRT(0x6000D918));
       writel(0x00004040, IO_TO_VIRT(0x6000D908));

       writel(0x00000200, IO_TO_VIRT(0x6000D82C));
       writel(0x00000202, IO_TO_VIRT(0x6000D81C));
       writel(0x00000202, IO_TO_VIRT(0x6000D80C));

       writel(0x00004040, IO_TO_VIRT(0x6000D928));
       mdelay(100);

       writel(0x00000202, IO_TO_VIRT(0x6000D82C));
       mdelay(200);

       return 0;
}

What is this magic, or where to find it in a stock kernel?

Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/4f0d7ac43592826e03f766005a3720ecc5ad1476#diff-4ce775d33b1aadd3981ea13ea140eca6R702

ARM: dt: tegra: Add Picasso board dts

Quoted 3 lines

Also note that (at least on A500) BCM chip also provides Bluetooth and the 'power/rst' GPIO affects both Wifi and Bluetooth.

A message that is not in the archive (sent off-list or not yet received): 20180130025229.GA1183-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]

#6 lore raw
Quoted 43 lines · Kyle Evans

* Dmitry Osipenko <[email protected]>:

Quoted 24 lines

Hello Kyle,

Quoted 21 lines · Kyle Evans

I have an ASUS TF101(ventana) that I am trying to get running on mainline. It is mostly there, but there are a few issues that I believe to be dts related. I am focusing on one at a time. Currently, when I warm boot/reboot, the wireless SDIO device fails to initialize. It works great on cold boot. I'm fairly certain the problem is in the dts, but I'd like some feedback on the correct way.

I'm not sure of the difference between WLAN_WOW & SDIO_WOW. I'm assuming one for chip, one for radio, but I don't know their place in the dts.

From tegra20-ventana.dts I've got:

	sdhci@c8000000 {
                status = "okay";
                power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
                bus-width = <4>;
                keep-power-in-suspend;
        };
Quoted 8 lines
Quoted 2 lines

I'm guessing I need to add the other pins to power-gpois and set up mmc-pwrseq?

The 'power-gpois' that you've defined looks fine and probably sufficient to get WiFi up and running.

Take a look at the changes that were needed to get WiFi working on Acer A500, maybe some of it also applicable to TF101:

Thanks for this. I have made some progress by adding regulator nodes for pins D,1 & K,6, but am now getting the following error on second boot.

[    2.425281] mmc2: Invalid maximum block size, assuming 512 bytes
[    2.480692] mmc2: SDHCI controller on c8000000.sdhci [c8000000.sdhci] using ADMA
[    2.494647] mmc2: error -110 whilst initialising SDIO card
Quoted 1 line
Quoted 5 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/beab29d4f172836c5faad91d3232a7c77c5fc6fb

HACK: mmc: sdio: Add workaround for wrongly reported CCCR

Would you recommend this over setting cap-sd-highspeed in the DT? Without either communication has been trouble free thus far.

Looks like cap-sd-highspeed should work, but I don't remember whether I've tried it before or not, maybe there some obstacle with it. I'm recalling that WiFi somewhat worked without the high speed CAP, but WiFi bandwidth sucked without it, like it was 100 KB/s at max or something like that.

Quoted 4 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/165e488e82c97fa1da6ccfe832a43569136000bc

mmc: Add "ignore mmc pm notify" functionality

This does not apply cleanly, what are the symptoms?

MMC code got refactored since then, you'll have to rebase the patch. Basically s/of_property_read_bool/device_property_read_bool/. I'm now recalling that this patch is only needed for the WiFi suspend/resume to work correctly.

Quoted 4 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/7e584ca4108707c6469a04bf92d9b659ce76c5cc

ARM: tegra: Add Picasso board file

I am trying to implement this, but as-is boot hangs before u-boot clears.

You may skip the board file, it's not really needed to make WiFi working. It's likely that GPIO's are wired differently on your device, that code is A500 specific.

Quoted 9 lines
static struct gpiod_lookup_table bluetooth_gpio_lookup = {
       .dev_id = "rfkill_gpio.1",
       .table = {
               GPIO_LOOKUP("tegra-gpio", 160, "reset", 0),
               { },
       },
}

Where does 160 come from?

From stock kernel. That's just a raw GPIO number.

Quoted 22 lines

static int __init tegra_picasso_wifi_pwr_and_reset(void)

{
       if (!of_machine_is_compatible("acer,picasso"))
               return 0;

       writel(0x00004000, IO_TO_VIRT(0x6000D928));
       writel(0x00004040, IO_TO_VIRT(0x6000D918));
       writel(0x00004040, IO_TO_VIRT(0x6000D908));

       writel(0x00000200, IO_TO_VIRT(0x6000D82C));
       writel(0x00000202, IO_TO_VIRT(0x6000D81C));
       writel(0x00000202, IO_TO_VIRT(0x6000D80C));

       writel(0x00004040, IO_TO_VIRT(0x6000D928));
       mdelay(100);

       writel(0x00000202, IO_TO_VIRT(0x6000D82C));
       mdelay(200);

       return 0;
}
Quoted 1 line

What is this magic, or where to find it in a stock kernel?

It should power-cycle BCM chip on boot, the code just writes GPIO controller registers directly. I think there wasn't better place to do it in the code without much effort, so I just hacked it that way. Sometimes brcmfmac driver fails to probe the HW on boot and I think that power-cycle helps a tad. Although I suppose that it's upstream driver fault, it looks like it doesn't perform HW initialization properly because I haven't had any issues like that with the downstream BCMHD driver ported to upstream kernel, literally using same DT / board code.

In stock kernel it should be ventana_wifi_power() that does the same.

Quoted 7 lines
Quoted 2 lines

https://github.com/digetx/picasso_upstream_support/commit/4f0d7ac43592826e03f766005a3720ecc5ad1476#diff-4ce775d33b1aadd3981ea13ea140eca6R702

ARM: dt: tegra: Add Picasso board dts

Quoted 3 lines

Also note that (at least on A500) BCM chip also provides Bluetooth and the 'power/rst' GPIO affects both Wifi and Bluetooth.

A message that is not in the archive (sent off-list or not yet received): c899990a-822b-ebd0-4ccb-2d4d117de8f6-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

author
#8 lore raw

* Dmitry Osipenko <[email protected]>:

Quoted 55 lines · Kyle Evans
Quoted 43 lines

* Dmitry Osipenko <[email protected]>:

Quoted 24 lines

Hello Kyle,

Quoted 21 lines · Kyle Evans

I have an ASUS TF101(ventana) that I am trying to get running on mainline. It is mostly there, but there are a few issues that I believe to be dts related. I am focusing on one at a time. Currently, when I warm boot/reboot, the wireless SDIO device fails to initialize. It works great on cold boot. I'm fairly certain the problem is in the dts, but I'd like some feedback on the correct way.

I'm not sure of the difference between WLAN_WOW & SDIO_WOW. I'm assuming one for chip, one for radio, but I don't know their place in the dts.

From tegra20-ventana.dts I've got:

	sdhci@c8000000 {
                status = "okay";
                power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
                bus-width = <4>;
                keep-power-in-suspend;
        };
Quoted 8 lines
Quoted 2 lines

I'm guessing I need to add the other pins to power-gpois and set up mmc-pwrseq?

The 'power-gpois' that you've defined looks fine and probably sufficient to get WiFi up and running.

Take a look at the changes that were needed to get WiFi working on Acer A500, maybe some of it also applicable to TF101:

Thanks for this. I have made some progress by adding regulator nodes for pins D,1 & K,6, but am now getting the following error on second boot.

[    2.425281] mmc2: Invalid maximum block size, assuming 512 bytes
[    2.480692] mmc2: SDHCI controller on c8000000.sdhci [c8000000.sdhci] using ADMA
[    2.494647] mmc2: error -110 whilst initialising SDIO card
Quoted 1 line
Quoted 5 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/beab29d4f172836c5faad91d3232a7c77c5fc6fb

HACK: mmc: sdio: Add workaround for wrongly reported CCCR

Would you recommend this over setting cap-sd-highspeed in the DT? Without either communication has been trouble free thus far.

Looks like cap-sd-highspeed should work, but I don't remember whether I've tried it before or not, maybe there some obstacle with it. I'm recalling that WiFi somewhat worked without the high speed CAP, but WiFi bandwidth sucked without it, like it was 100 KB/s at max or something like that.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/165e488e82c97fa1da6ccfe832a43569136000bc

mmc: Add "ignore mmc pm notify" functionality

This does not apply cleanly, what are the symptoms?

MMC code got refactored since then, you'll have to rebase the patch. Basically s/of_property_read_bool/device_property_read_bool/. I'm now recalling that this patch is only needed for the WiFi suspend/resume to work correctly.

Ok, good to know. I have not tried suspend yet.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

https://github.com/digetx/picasso_upstream_support/commit/7e584ca4108707c6469a04bf92d9b659ce76c5cc

ARM: tegra: Add Picasso board file

I am trying to implement this, but as-is boot hangs before u-boot clears.

You may skip the board file, it's not really needed to make WiFi working. It's likely that GPIO's are wired differently on your device, that code is A500 specific.

Good, I'm pretty sure that upstream would not accept a board file for a wifi bug.

Quoted 9 lines
Quoted 9 lines
static struct gpiod_lookup_table bluetooth_gpio_lookup = {
       .dev_id = "rfkill_gpio.1",
       .table = {
               GPIO_LOOKUP("tegra-gpio", 160, "reset", 0),
               { },
       },
}
Quoted 3 lines
Quoted 1 line

Where does 160 come from?

From stock kernel. That's just a raw GPIO number.

I have determined it to be U,0, which is rfkill here as well.

Quoted 34 lines
Quoted 23 lines

static int __init tegra_picasso_wifi_pwr_and_reset(void)

{
       if (!of_machine_is_compatible("acer,picasso"))
               return 0;

       writel(0x00004000, IO_TO_VIRT(0x6000D928));
       writel(0x00004040, IO_TO_VIRT(0x6000D918));
       writel(0x00004040, IO_TO_VIRT(0x6000D908));

       writel(0x00000200, IO_TO_VIRT(0x6000D82C));
       writel(0x00000202, IO_TO_VIRT(0x6000D81C));
       writel(0x00000202, IO_TO_VIRT(0x6000D80C));

       writel(0x00004040, IO_TO_VIRT(0x6000D928));
       mdelay(100);

       writel(0x00000202, IO_TO_VIRT(0x6000D82C));
       mdelay(200);

       return 0;
}
Quoted 1 line

What is this magic, or where to find it in a stock kernel?

It should power-cycle BCM chip on boot, the code just writes GPIO controller registers directly. I think there wasn't better place to do it in the code without much effort, so I just hacked it that way. Sometimes brcmfmac driver fails to probe the HW on boot and I think that power-cycle helps a tad. Although I suppose that it's upstream driver fault, it looks like it doesn't perform HW initialization properly because I haven't had any issues like that with the downstream BCMHD driver ported to upstream kernel, literally using same DT / board code.

Quoted 1 line

In stock kernel it should be ventana_wifi_power() that does the same.

I see that the ventana_wifi_power() calls clk_enable(wifi_32k_clk). So, the problem could be clock related. However, I do not see any dts trees that use compatible = "brcm,bcm4329-fmac" also call out any special clocks.

I am inclined to second it as a driver issue becuase I have done everything suggested with no success. I started out by posting to linux-wireless and came here when I discovered that modprobe -r sdhci-tegra; modprobe shci-tegra; brought the interface up after failure. Unfortunately, I do not use a ramdisk so such a workaround is not possible because then I would get a VFS panic.

Although it would be nice to have a system fully functional after reboot with all of the code porting and testing that is required, I think I shall put this issue on the back burner. I am excited for all of the work you are doing with the grate driver.

Thank you for your help,
Kyle

A message that is not in the archive (sent off-list or not yet received): 20180202160635.GA1275-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]

#10 lore raw
Quoted 128 lines · Kyle Evans

* Dmitry Osipenko <[email protected]>:

Quoted 55 lines · Kyle Evans
Quoted 43 lines

* Dmitry Osipenko <[email protected]>:

Quoted 24 lines

Hello Kyle,

Quoted 21 lines · Kyle Evans

I have an ASUS TF101(ventana) that I am trying to get running on mainline. It is mostly there, but there are a few issues that I believe to be dts related. I am focusing on one at a time. Currently, when I warm boot/reboot, the wireless SDIO device fails to initialize. It works great on cold boot. I'm fairly certain the problem is in the dts, but I'd like some feedback on the correct way.

I'm not sure of the difference between WLAN_WOW & SDIO_WOW. I'm assuming one for chip, one for radio, but I don't know their place in the dts.

From tegra20-ventana.dts I've got:

	sdhci@c8000000 {
                status = "okay";
                power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
                bus-width = <4>;
                keep-power-in-suspend;
        };
Quoted 8 lines
Quoted 2 lines

I'm guessing I need to add the other pins to power-gpois and set up mmc-pwrseq?

The 'power-gpois' that you've defined looks fine and probably sufficient to get WiFi up and running.

Take a look at the changes that were needed to get WiFi working on Acer A500, maybe some of it also applicable to TF101:

Thanks for this. I have made some progress by adding regulator nodes for pins D,1 & K,6, but am now getting the following error on second boot.

[    2.425281] mmc2: Invalid maximum block size, assuming 512 bytes
[    2.480692] mmc2: SDHCI controller on c8000000.sdhci [c8000000.sdhci] using ADMA
[    2.494647] mmc2: error -110 whilst initialising SDIO card
Quoted 1 line
Quoted 5 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/beab29d4f172836c5faad91d3232a7c77c5fc6fb

HACK: mmc: sdio: Add workaround for wrongly reported CCCR

Would you recommend this over setting cap-sd-highspeed in the DT? Without either communication has been trouble free thus far.

Looks like cap-sd-highspeed should work, but I don't remember whether I've tried it before or not, maybe there some obstacle with it. I'm recalling that WiFi somewhat worked without the high speed CAP, but WiFi bandwidth sucked without it, like it was 100 KB/s at max or something like that.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

https://github.com/digetx/picasso_upstream_support/commit/165e488e82c97fa1da6ccfe832a43569136000bc

mmc: Add "ignore mmc pm notify" functionality

This does not apply cleanly, what are the symptoms?

MMC code got refactored since then, you'll have to rebase the patch. Basically s/of_property_read_bool/device_property_read_bool/. I'm now recalling that this patch is only needed for the WiFi suspend/resume to work correctly.

Ok, good to know. I have not tried suspend yet.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

https://github.com/digetx/picasso_upstream_support/commit/7e584ca4108707c6469a04bf92d9b659ce76c5cc

ARM: tegra: Add Picasso board file

I am trying to implement this, but as-is boot hangs before u-boot clears.

You may skip the board file, it's not really needed to make WiFi working. It's likely that GPIO's are wired differently on your device, that code is A500 specific.

Good, I'm pretty sure that upstream would not accept a board file for a wifi bug.

Quoted 9 lines
Quoted 9 lines
static struct gpiod_lookup_table bluetooth_gpio_lookup = {
       .dev_id = "rfkill_gpio.1",
       .table = {
               GPIO_LOOKUP("tegra-gpio", 160, "reset", 0),
               { },
       },
}
Quoted 3 lines
Quoted 1 line

Where does 160 come from?

From stock kernel. That's just a raw GPIO number.

I have determined it to be U,0, which is rfkill here as well.

Quoted 34 lines
Quoted 23 lines

static int __init tegra_picasso_wifi_pwr_and_reset(void)

{
       if (!of_machine_is_compatible("acer,picasso"))
               return 0;

       writel(0x00004000, IO_TO_VIRT(0x6000D928));
       writel(0x00004040, IO_TO_VIRT(0x6000D918));
       writel(0x00004040, IO_TO_VIRT(0x6000D908));

       writel(0x00000200, IO_TO_VIRT(0x6000D82C));
       writel(0x00000202, IO_TO_VIRT(0x6000D81C));
       writel(0x00000202, IO_TO_VIRT(0x6000D80C));

       writel(0x00004040, IO_TO_VIRT(0x6000D928));
       mdelay(100);

       writel(0x00000202, IO_TO_VIRT(0x6000D82C));
       mdelay(200);

       return 0;
}
Quoted 1 line

What is this magic, or where to find it in a stock kernel?

It should power-cycle BCM chip on boot, the code just writes GPIO controller registers directly. I think there wasn't better place to do it in the code without much effort, so I just hacked it that way. Sometimes brcmfmac driver fails to probe the HW on boot and I think that power-cycle helps a tad. Although I suppose that it's upstream driver fault, it looks like it doesn't perform HW initialization properly because I haven't had any issues like that with the downstream BCMHD driver ported to upstream kernel, literally using same DT / board code.

Quoted 6 lines
Quoted 1 line

In stock kernel it should be ventana_wifi_power() that does the same.

I see that the ventana_wifi_power() calls clk_enable(wifi_32k_clk). So, the problem could be clock related. However, I do not see any dts trees that use compatible = "brcm,bcm4329-fmac" also call out any special clocks.

This clock is always "on" with the upstream kernel, it shouldn't cause any problems.

Quoted 6 lines

I am inclined to second it as a driver issue becuase I have done everything suggested with no success. I started out by posting to linux-wireless and came here when I discovered that modprobe -r sdhci-tegra; modprobe shci-tegra; brought the interface up after failure. Unfortunately, I do not use a ramdisk so such a workaround is not possible because then I would get a VFS panic.

Just the WiFi driver module reload also usually helps.

Quoted 4 lines

Although it would be nice to have a system fully functional after reboot with all of the code porting and testing that is required, I think I shall put this issue on the back burner. I am excited for all of the work you are doing with the grate driver.

Well, in my case the unrecoverable failure happens quite rare, I'd say it is mostly working fine. Indeed somebody would have to invest some time and effort to figure out why it happens at all.

Yeah, grate hacking is a lot of fun. You should try it too :)