[OpenWrt-Devel] ath9k_platform_data, endianness, misidentified device

Luca Olivetti luca at ventoso.org
Wed Dec 8 12:53:21 CET 2010


Al 05/12/10 15:38, En/na Luca Olivetti ha escrit:

>>>> This router has an ar9223, with the calibration data stored in flash. I
>>>> copied the data in ath9k_platform_data (btw, I noticed that ar71xx
>>>> redefines it adding fields, should I copy the .h to my platform or is
>>>> there a better way to avoid incongruencies?).
>>>>
>>>> The first problem is that the device is (incorrectly?) identified as
>>>> 168c:ff1d instead of 168c:0029. I saw a similar problem here
>>>>
>>>> https://forum.openwrt.org/viewtopic.php?pid=97839#p97839
>>>>
>>>> with a bug report here
>>>>
>>>> https://dev.openwrt.org/ticket/6171
>>>>
>>>> unfortunately I don't think it applies to my platform (ifxmips), so for
>>>> the time being I patched compat-wireless to accept ff1d as a valid id.
>>>
>>> I think I have to do something similar to what it's done in
>>> ar71xx/files/arch/mips/ar71xx/pci-ath9k-fixup.c, the big problem I have
>>> is I don't know how to adapt it to the ifxmips/danube, since I don't
>>> know what the various calls to ioremap, pci_write_config_dword,
>>> pci_read_config_dword are supposed to do (I'm not into driver
>>> development):
>>
>> Well, while waiting for an answer, I tried it.
>> It almost works but I seem to have an endianness issue, while
>> pci-ath9-fixup.c did
>>
>>
>> pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
>> dev->vendor = val & 0xffff;
>> dev->device = (val >> 16) & 0xffff;
>>
>>
>> I had to do
>>
>> pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
>> dev->device = swab16(val & 0xffff);
>> dev->vendor = swab16((val >> 16) & 0xffff);
>>
>>
>> i.e everything was swapped (device<->vendor and the bytes inside each of
>> them).
>
> Now I swapped the values written to the registers instead, e.g. instead of
>
> /* set pointer to first reg address */
> cal_data += 3;
> while (*cal_data != 0xffff) {
> u32 reg;
> reg = *cal_data++;
> val = *cal_data++;
> val |= (*cal_data++) << 16;
>
> __raw_writel(val, mem + reg);
> udelay(100);
> }
>
>
> I do
>
> /* set pointer to first reg address */
> cal_data += 3;
> while (*cal_data != 0xffff) {
> u32 reg;
> reg = *cal_data++;
> val = swab16(*cal_data++) << 16;
> val |= swab16(*cal_data++);
>
> __raw_writel(val, mem + reg);
> udelay(100);
> }
>
>
> Since the endianness of the ar71xx and the danube should be the same,
> maybe the key is the layout of the data in caldata.
>
> This is what I have, byte by byte:
>
> A5 5A (magic)
> 00 00 00 03 (bytes skipped by the above routine)
> 60 00 16 8C 00 29 (it appears vid:pid, at register 0x6000)
> 60 08 00 01 02 80
> 60 2C 16 8C 20 91 (another vid:pid?)
> 50 00 16 8C 00 2A (yet another?)
> 50 08 00 01 02 80 (same data as at 0x6008)
> 50 2C 16 8C 20 91 (same data as at 0x602C)
> 50 64 0C C0 05 04
> 50 6C 38 11 00 03
> 40 04 07 3B 00 40
> 40 74 00 03 00 00
> 40 00 00 00 01 C2
> 60 34 00 44 00 00
> FF FF 00 00 00 00 (end of data)
>
>
> what I end up writing with the above loop is
>
> 0x6000 -> 8c162900
> 0x6008 -> 10008002
>
> etc.
>
> and with that I seem to get the correct vid:pid with
>
> pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
> dev->vendor = val & 0xffff;
> dev->device = (val >> 16) & 0xffff;

I could really use some help here :-/
Wifi is working but performance is atrocious (10% the throughput of a 
nearby card), so I'm not sure what I did is correct (even if the 
calibration data checksums ok).

Bye
-- 
Luca


More information about the openwrt-devel mailing list