Marvel WLAN, SDIO, Linux and imx53

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Marvel WLAN, SDIO, Linux and imx53

Jump to solution
9,675 Views
Maddis
Contributor IV

Hi,

We have a imx53 based custom hw. It has Marvel 8686 WLAN module connected to imx53 SD2 instead of SD1. System is running Linux 2.6.35.3 and I've compiled Libertas - module and I have Libertas Firmware files in place (/lib/firmware/libertas).

The problem is that when loading the libertas drivers (even with the sdio) there is no traffic on SDIO bus. That's expected since I haven't found a way how to tie the libertas_sdio driver to certain SDIO-bus.

Does someone have working combo of Marvel 8686 and mx53 and/or know what is needed to get libertas_sdio driver to use SD2?

I have configured both SD1 and SD2 on board init and they appear during boot although I don't know why SD2 have irq 0:

[    1.448309] mmc0: SDHCI detect irq 129 irq 1 INTERNAL DMA

[    1.458958] mmc1: SDHCI detect irq 0 irq 2 INTERNAL DMA

System also uses SD1 for booting so if MMC debug is enabled there is lots of debug prints just from SD-card access.

-Teemu

Labels (2)
Tags (3)
1 Solution
3,724 Views
phuongdangminh
Contributor III

Hello,

We need to add some ESDHC2 init code into the mx53_loco.c

- Config mmc2 pinmux:
 static iomux_v3_cfg_t mx53_loco_pads[] = {
      ...
        MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
        MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
        MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
        MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
        MX53_PAD_SD2_CLK__ESDHC2_CLK,
        MX53_PAD_SD2_CMD__ESDHC2_CMD,
      ...
 }

- Add mmc2 init platform data:

 static struct mxc_mmc_platform_data mmc2_data = {
        .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
                | MMC_VDD_31_32,
        .caps = MMC_CAP_4_BIT_DATA,
        .min_clk = 400000,
        .max_clk = 50000000,
        .card_inserted_state = 1,
        .clock_mmc = "esdhc_clk",
        .power_mmc = NULL,
 };
- Add register:
 static void __init mxc_board_init(void)
 {
     ...
        mxc_register_device(&mxcsdhc1_device, &mmc1_data);
        mxc_register_device(&mxcsdhc2_device, &mmc2_data);
        mxc_register_device(&mxcsdhc3_device, &mmc3_data);
     ...
 }

For more detail checkout this link : https://code.google.com/p/km233/wiki/WIFI_TO_ANDROID

Hope it can help you.

Regards.

View solution in original post

0 Kudos
21 Replies
3,713 Views
zhuhaigang
Contributor I

:smileylaugh:

hai:

I do as Phuong Dang Minh sayed.but i failed;

can'n find mmc1: new SDIO card at address 0001.

can you help me?

i find that mmc_send_io_op_cond() return failure;

int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)

{

  struct mmc_command cmd;

  int i, err = 0;

  BUG_ON(!host);

  memset(&cmd, 0, sizeof(struct mmc_command));

  cmd.opcode = SD_IO_SEND_OP_COND;

  cmd.arg = ocr;

  cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR;

  for (i = 100; i; i--) {

  err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);

  printk("==============err = mmc_wait_for_cmd(),err: %d\n", err);//err = -110

  if (err)

  break;

  /* if we're just probing, do a single pass */

  if (ocr == 0)

  break;

  /* otherwise wait until reset completes */

  if (mmc_host_is_spi(host)) {

  /*

  * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate

  * an initialized card under SPI, but some cards

  * (Marvell's) only behave when looking at this

  * one.

  */

  if (cmd.resp[1] & MMC_CARD_BUSY)

  break;

  } else {

  if (cmd.resp[0] & MMC_CARD_BUSY)

  break;

  }

  err = -ETIMEDOUT;

  mmc_delay(10);

  }

  if (rocr)

  *rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0];

  return err;

}

my kernel log:

mxsdhci: MXC Secure Digital Host Controller Interface driver

mxsdhci: MXC SDHCI Controller Driver.

mmc0: SDHCI detect irq 0 irq 1 INTERNAL DMA

mxsdhci: MXC SDHCI Controller Driver.

================mmc_rescan

mmc1: SDHCI detect irq 0 irq 2 INTERNAL DMA

mxsdhci: MXC SDHCI Controller Driver.

mmc2: SDHCI detect irq 203 irq 3 INTERNAL DMA

usbcore: registered new interface driver usbhid

usbhid: USB HID core driver

Cirrus Logic CS42888 ALSA SoC Codec Driver

sgtl5000-i2c 1-000a: SGTL5000 revision 17

================First we search for SDIO...

==============err = mmc_wait_for_cmd(),err: -110

================...then normal SD...

==============err = mmc_wait_for_app_cmd,err: 0

==============err = mmc_wait_for_app_cmd,err: 0

mxc_spdif mxc_spdif.0: MXC SPDIF Audio Transmitter

No device for codec mxc spdif

No device for DAI mxc spdif

No device for DAI imx-ssi-1-0

No device for DAI imx-ssi-1-1

No device for DAI imx-ssi-2-0

No device for DAI imx-ssi-2-1

No device for DAI imx-spdif-dai

==============err = mmc_wait_for_app_cmd,err: 0

DMA Sound Buffer Allocated: Playback UseIram=1 ext_ram=0 buf->addr=f8016000 buf->area=e0856000 size=24576

DMA Sound Buffer Allocated: Capture  UseIram=1 ext_ram=1 buf->addr=cf370000 buf->area=fa8ad000 size=24576

asoc: SGTL5000 <-> imx-ssi-2-0 mapping ok

mmc0: new high speed SDHC card at address aaaa

mmcblk0: mmc0:aaaa SU04G 3.69 GiB

mmcblk0: p1

================mmc_rescan

DMA Sound Buffer Allocated: Playback UseIram=1 ext_ram=1 buf->addr=cf430000 buf->area=fa8b3000 size=24576

asoc: mxc spdif <-> imx-spdif-dai mapping ok

ALSA device list:

  #0: imx-3stack (SGTL5000)

  #1: imx-3stack-spdif (mxc spdif)

TCP cubic registered

NET: Registered protocol family 17

can: controller area network core (rev 20090105 abi 8)

NET: Registered protocol family 29

can: raw protocol (rev 20090105)

can: broadcast manager protocol (rev 20090105 t)

Bluetooth: L2CAP ver 2.14

Bluetooth: L2CAP socket layer initialized

Bluetooth: SCO (Voice Link) ver 0.6

Bluetooth: SCO socket layer initialized

Bluetooth: RFCOMM TTY layer initialized

Bluetooth: RFCOMM socket layer initialized

Bluetooth: RFCOMM ver 1.11

Bluetooth: BNEP (Ethernet Emulation) ver 1.3

Bluetooth: BNEP filters: protocol multicast

Bluetooth: HIDP (Human Interface Emulation) ver 1.2

lib80211: common routines for IEEE802.11 drivers

VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 2

================First we search for SDIO...

==============err = mmc_wait_for_cmd(),err: -110

================...then normal SD...

input: mxc_ts as /devices/virtual/input/input2

mxc input touchscreen loaded

mxc_rtc mxc_rtc.0: setting system clock to 1970-01-01 00:00:00 UTC (0)

==============err = mmc_wait_for_app_cmd,err: -110

================...and finally MMC.

================mmc_rescan

================First we search for SDIO...

==============err = mmc_wait_for_cmd(),err: -123

================...then normal SD...

==============err = mmc_wait_for_app_cmd,err: -123

================...and finally MMC.

0 Kudos
3,706 Views
phuongdangminh
Contributor III

Hi,

Look like your hardware had problem.

1> Try to check the SDIO slot works or not, simply test with a SD memory card.

2> If SDIO slot works, check the WIFI interface configuration, there are two modes, SDIO and GSPI.

Regards.

0 Kudos
3,716 Views
Maddis
Contributor IV

I finally got the WLAN working at some level. The initial problem was that I need to put both CD and WP - signal handling go through GPIO-pins instead on passing them eSDHC-controller. I don't know how this is done on Android example, but that how I needed to do it in our Linux.

The next problem is that when loading the libertas -driver and releasing the wlan-reset I got this error:

[  256.774400] mmc1: new SDIO card at address 0001

[  261.057866] libertas: command 0x0003 timed out

[  261.062333] libertas: Timeout submitting command 0x0003

[  261.067571] libertas: PREP_CMD: command 0x0003 failed: -110

[  261.075320] libertas_sdio: probe of mmc1:0001:1 failed with error -110

This can be 'fix' by putting one printk call to the function sdhci_data_irq in file mx_sdhci.c. Clearly it seems to be some sort of timing problem. Has someone else had similar problems and how did you manage to resolve it? It's mxc - specific driver so I don't think it has anything to do with the actual WLAN. We _should_ be using latest available patch for the kernel 2.6.35.3.

There was some mention in errata about eSDHC missing SDIO-interrupt when CINT is disabled (ENGcm11186). There is mentioned that workaround is in Linux BSP release 09.12.00, but I think we should already have it since we are using latest patches for the kernel.

It kinda messed up the usage when you keep having that printk-flood to console when using WLAN.

3,716 Views
phuongdangminh
Contributor III

Hello,

Congratulation,

Linux-2.6.35 for imx53 is not mature, there are many patch sources, so we maybe missing somethings, though.

BTW, there are some nice Realtek wifi modules which well supports on Linux and Android, their price is also cheaper than W8686 modules, but they're using USB interface instead SDIO. Here is the infomation

https://code.google.com/p/rtl8192cu/source/browse/#hg%2Fandroid_reference_codes

0 Kudos
3,716 Views
Maddis
Contributor IV

Hi,

I tested and noticed that printk can be replaced with udelay(200); Maybe the delay can be even shorter, I haven't yet tested.

Our hw has been certified with W8686 hw and I'm not sure if it's possible to change the WLAN-module without re-certifiying the hw since I'm only sw guy.

Would the 3.0.35 be better choice for the kernel? I briefly tried it, but there also was quite a lot of patches and it had changed so much that I don't know how to do the same things that are now done in our board-init - file. Maybe I should create new topic for that kernel.

0 Kudos
3,716 Views
phuongdangminh
Contributor III

Oh,

Now I have free time and make some experiments and met the same problem like you after changing external module to buidt-in kernel driver, the sdhci_data_irq() function should run fast as possible, if we add the delay it causes the system performance decrease.

So I think you should build the driver as external module (libertas_sdio.ko) instead kernel built-in driver.

# sudo export INSTALL_MOD_PATH=<imx53 rootfs>

# sudo make modules modules_install

After that the driver will work without modifying anything.

Regards,

0 Kudos
3,716 Views
Maddis
Contributor IV

That's interesting since I've build drivers are module from the start. What else did you built as module beside the libertas - modules?

I have the Wireless network drivers as module and wireless network device drivers as well.

I did some tests and it seems that udelay(20) is shortest when the driver still works. udelay(10) was too short. I managed to get about 1.6MB/s traffic through that driver with that fix. Of course it's not best, but still better than nothing.

It would be interesting to see what you built as module to get the WLAN working and how did you start up the WLAN (load the modules etc.) since it seems that my system needs that delay no matter what.

0 Kudos
3,716 Views
mfuzzey
Contributor I

Hi,

where exactly in the function do you put the udelay()

I'm having the same issue with a mainline kernel

Regards,

Martin

0 Kudos
3,716 Views
Maddis
Contributor IV

To file: drivers/mmc/host/mx_sdhci in function sdhci_data_irq at the begining. There I have udelay(20);

If you are using sd-card, make sure that you don't delay that irq as well so check the host->mmc->index. In my device the wlan is on index 1 and sd on index 0.

0 Kudos
3,716 Views
phuongdangminh
Contributor III

Well,

By using module, you don't need to insert it by hands. When booting up the Linux system will insert automatically for you. Suppose we are using the Ubuntu which is provided from Freescale. The easiest way is building linux kernel by using native gcc. The IMX53 is fast enough to do that. My brief description as bellow:

1> Copy your linux kernel souce in to the board.

2> Kernel configuration as bellow:

     Linux Kernel Configuration

             [*] Enable loadable module dupport

  

     Device Drivers

             [*] Network device support

                     [*] Wireless LAN

                            <*>   Marvell 8xxx Libertas WLAN driver support

                            <M> Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards

3> Build the kernel source and install the module driver

     # export ARCH=arm

     # make uImage

     # make modules

     # make modules_install

Cross compliling is the same that way, exept module installing we must specify the INSTALL_MOD_PATH variable which points to your rootfs path.

Regards,

0 Kudos
3,716 Views
Maddis
Contributor IV

Okay, there is one difference. We are using Buildroot to build our system from scratch and not any ready made distribution. Our system doesn't have udev so modules needs to be loaded manually.

Still, I don't know how the method how the module is loaded could effect the way module is working.

0 Kudos
3,716 Views
Maddis
Contributor IV

Hi,

Something going on.. I got the WLAN-module recognized. Had to modify the CD-signal handling since the one in the example didn't work on our hw.

Now I get this:

[  140.630086] mmc1: new SDIO card at address 0001

Then when I load the libertas_sdio I get this log. There are some debug-prints added by me.

[  264.849719] lib80211: common routines for IEEE802.11 drivers

[  264.904542] libertas enter: lbs_init_module()

[  264.914804] libertas leave: lbs_init_module()

[  264.964900] libertas enter: if_sdio_init_module()

[  264.974769] libertas_sdio: Libertas SDIO driver

[  264.984824] libertas_sdio: Copyright Pierre Ossman

[  264.995200] libertas enter: if_sdio_probe()

[  265.003022] libertas sdio: class = 0x7, vendor = 0x2DF, device = 0x9103, model = 0xB, ioport = 0x10000

[  265.012406] libertas enter: if_sdio_prog_firmware()

[  265.017573] if_sdio_read_scratch - coming...

[  265.022010] if_sdio_read_scratch - done...

[  265.026128] return value valid

[  265.029185] libertas sdio: firmware status = 0x8000

[  265.034064] libertas sdio: scratch ret = 0

[  265.038197] libertas enter: if_sdio_prog_helper()

[  265.073499] if_sdio_wait_status

[  265.092906] if_sdio_prog_helper: sending stuff

[  265.110955] libertas sdio: sending 60 bytes chunk

[  265.129875] sdio_io_rw_ext_helper

[  265.133207] sdio_io_rw_ext_helper: remainder transfer coming up...

[  275.175612] mmc1: Timeout waiting for hardware interrupt.

[  275.181026] mxsdhci: ============== REGISTER DUMP ==============

[  275.187039] mxsdhci: Sys addr: 0x7d287540 | Version:  0x00001201

[  275.193048] mxsdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001

[  275.199058] mxsdhci: Argument: 0x92000040 | Trn mode: 0x353a0003

[  275.205068] mxsdhci: Present:  0xff810008 | Host ctl: 0x000000ab

[  275.211076] mxsdhci: Clock:    0x000e013f

[  275.215085] mxsdhci: Int stat: 0x00000000

[  275.219097] mxsdhci: Int enab: 0x117f010f | Sig enab: 0x117f010f

[  275.225105] mxsdhci: Caps:     0x07f30000

[  275.229115] mxsdhci: ===========================================

[  275.240268] if_sdio_prog_helper: write ret -110

[  275.245178] libertas: failed to load helper firmware

[  275.250164] libertas leave: if_sdio_prog_helper(), ret -110

[  275.255970] libertas leave: if_sdio_prog_firmware(), ret -110

[  275.262265] libertas leave: if_sdio_probe(), ret -110

[  275.267367] libertas_sdio: probe of mmc1:0001:1 failed with error -110

[  275.274391] libertas leave: if_sdio_init_module(), ret 0

Any idea what might be cause in that? Our hw has controllable reset-pin, but I've also added the patch from example. I've checked and driver will find the firmware-files although it says that failed to load helper firmware.

0 Kudos
3,716 Views
phuongdangminh
Contributor III

[  275.245178] libertas: failed to load helper firmware


are you using ubuntu ? if the path is correct so let's try my firmware,

88w8686 has some firmware version, you can download at the link above.


Regards.

0 Kudos
3,716 Views
Maddis
Contributor IV

Hi,


I tried those firmware files with and without the if_sdio.c - patch. Didn't help. It seems that on your instructions the firmware files are put to the different place than what it needs to be in our Linux. In our case they need to be in /lib/firmware and not /system/etc/firmware. Might be Android thing.

Looking at the debug prints, it seems like the driver is able to communicate with the WLAN-module since this gets printed:  libertas sdio: class = 0x7, vendor = 0x2DF, device = 0x9103, model = 0xB, ioport = 0x10000 and those seems to be correct values for the 88w8686.

Still, anything beyond that won't work and I don't know why.

I don't think we need the if_sdio.c patch on our hw since the WLAN-reset is active and I disable it before loading the libertas_sdio - driver as I assume is the case in your example hw as well?

0 Kudos
3,716 Views
Maddis
Contributor IV

I noticed, that the firmware that we use is different from your's, but the helper-binary is the same. Still, no difference which firmware using. WLAN won't init properly.

0 Kudos
3,725 Views
phuongdangminh
Contributor III

Hello,

We need to add some ESDHC2 init code into the mx53_loco.c

- Config mmc2 pinmux:
 static iomux_v3_cfg_t mx53_loco_pads[] = {
      ...
        MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
        MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
        MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
        MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
        MX53_PAD_SD2_CLK__ESDHC2_CLK,
        MX53_PAD_SD2_CMD__ESDHC2_CMD,
      ...
 }

- Add mmc2 init platform data:

 static struct mxc_mmc_platform_data mmc2_data = {
        .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
                | MMC_VDD_31_32,
        .caps = MMC_CAP_4_BIT_DATA,
        .min_clk = 400000,
        .max_clk = 50000000,
        .card_inserted_state = 1,
        .clock_mmc = "esdhc_clk",
        .power_mmc = NULL,
 };
- Add register:
 static void __init mxc_board_init(void)
 {
     ...
        mxc_register_device(&mxcsdhc1_device, &mmc1_data);
        mxc_register_device(&mxcsdhc2_device, &mmc2_data);
        mxc_register_device(&mxcsdhc3_device, &mmc3_data);
     ...
 }

For more detail checkout this link : https://code.google.com/p/km233/wiki/WIFI_TO_ANDROID

Hope it can help you.

Regards.

0 Kudos
3,716 Views
Maddis
Contributor IV

Hi,

Thanks for the reply. It helped me some. Still the WLAN won't work and I think the problem is the same as before.

As in your instructions I compiled everything else to kernel except the libertas_sdio - driver which I compiled as module. I also enabled some debugs to see if anything happens. Now when I load the libertas_sdio - driver, only thing that gets printed is couple info lines saying "libertas_sdio: Libertas SDIO driver" and "libertas_sdio: Copyright Pierre Ossman". No indication that it has tried to access hardware and no indication that if it found any. On different hardware there were prints that new mmc-device was found.

So the problem now is that how do I tell the libertas driver to access the ESDHC2 - bus?

I also tried to use wpa_supplicant, but I think it needs that the wlan0 (or what ever it's called) interface exist and I don't have any wlan interfaces.

0 Kudos
3,716 Views
phuongdangminh
Contributor III

Hello,

Make sure the firmware be loaded properly after insert module in to the Linux kernel. There are two files (sd8686.bin and sd8686_helper.bin) which we need to copy into the rootfs. For Ubuntu, copy them into the /lib/firmware directory.

Regards,

0 Kudos
3,716 Views
Maddis
Contributor IV

How do I do that? There are no mention in log that driver ever tries to load firmware and no mention if its success or fail. The firmware is located in same directory as in Ubuntu.

I'm clearly missing some important part here, but I don't know what.

0 Kudos
3,716 Views
phuongdangminh
Contributor III

Try with dmesg command

0 Kudos