Subject: need help with CompactFlash/PCMCIA

From: Ulrich Eckhardt <[email-masked]>
Date: Tue, 15 Mar 2005 12:45:15 +0100

Hi!

I have a board here which roughly resembles a DB1100, AFAICT. My problem is 
that I can't get the CompactFlash card to be recognized, and I don't even 
know where exactly it fails.
So, a few questions up front:
1. CompactFlash is accessed via PCMCIA, it does not use the MTD 
infrastructure, right? I also read that the CF then appears as a normal(?) 
ATA device. So, what should be the right drivers for it?
2. How can I find out if it's looking at the right addresses? I just need some 
kind of register which I can probe to find out if the device is where I think 
it should be.

Hmm, in fact I'd be happy about _any_ hint the would get me further. I'm 
slightly desparate...

Appended is a patch that removes an unused variable, something I found while 
trying to understand what's going on there.

thanks

Uli

---

Index: au1000_generic.c
===================================================================
RCS file: /home/cvs/linux/drivers/pcmcia/au1000_generic.c,v
retrieving revision 1.18
diff -u -r1.18 au1000_generic.c
--- au1000_generic.c 25 Jan 2005 04:28:38 -0000 1.18
+++ au1000_generic.c 15 Mar 2005 11:40:26 -0000
@@ -66,10 +66,6 @@
 #define PCMCIA_SOCKET(x) (au1000_pcmcia_socket + (x))
 #define to_au1000_socket(x) container_of(x, struct au1000_pcmcia_socket, 
socket)
 
-/* Some boards like to support CF cards as IDE root devices, so they
- * grab pcmcia sockets directly.
- */
-u32 *pcmcia_base_vaddrs[2];
 extern const unsigned long mips_io_port_base;
 
 DECLARE_MUTEX(pcmcia_sockets_lock);
@@ -437,7 +433,6 @@
    skt->phys_mem = AU1X_SOCK1_PSEUDO_PHYS_MEM;
   }
 #endif
-  pcmcia_base_vaddrs[i] = (u32 *)skt->virt_io;
   ret = ops->hw_init(skt);
 
   skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;

---

From: Pete Popov <[email-masked]>
Date: Tue, 15 Mar 2005 09:31:49 -0800

Ulrich Eckhardt wrote:
> infrastructure, right? 

Correct.

> I also read that the CF then appears as a normal(?) 

The au1x00_ss socket driver, the pcmcia stack modules or statically compiled, 
and ide-cs.o, which is the pcmcia ide client driver.

> Hmm, in fact I'd be happy about _any_ hint the would get me further. I'm 

Start with the low level routines that detect the card and set the voltage 
levels. When you plug in the card, is it detected? Are you setting the correct 
voltages? What happens next -- is the card at least recognized by the cardmgr, 
which means that the attribute memory is read correctly?

> trying to understand what's going on there.

Well, there is another patch for a custom board that uses those unused 
variables. Perhaps those variables should just be part of that external patch...

Pete

---

From: Ulrich Eckhardt <[email-masked]>
Date: Wed, 16 Mar 2005 06:51:42 +0100

On Tuesday 15 March 2005 18:31, Pete Popov wrote:
> > 2. How can I find out if it's looking at the right addresses? I just need
> > some kind of register which I can probe to find out if the device is
> > where I think it should be.
> >
> levels. When you plug in the card, is it detected? Are you setting the
> correct voltages? What happens next -- is the card at least recognized by 
> the cardmgr, which means that the attribute memory is read correctly?

I don't see any message that something is found, nor can I definitely say 
where an error happens. I mainly see two parts: one where cardservices are 
initialised and one where the driver registers itself. The former doesn't say 
it found anything at all, maybe that is already the problem... I'll 
investigate further.

Could you post the relevant messages of a working system, so I could compare 
that?

Hmmm, I just had a scary thought: I don't have any userspace programs running 
yet, meaning also no cardmgr, because I intend to boot from that CF card - is 
that possible at all? FYI, I don't need any hotplugging at all.

thanks

Uli

---

From: Pete Popov <[email-masked]>
Date: Tue, 15 Mar 2005 22:06:20 -0800

> it found anything at all, maybe that is already the problem... I'll 

What I meant to say is to add debug prints to the driver so you can see if it 
detects and powers on the slot.

> Could you post the relevant messages of a working system, so I could compare 

I can do that ... just don't know if I'll get to it in the next couple of days.

> that possible at all? FYI, I don't need any hotplugging at all.

Do you really mean "boot" from it or "root" from it? If you want to "boot" from 
it, you need to work on your boot loader to be able to fetch the kernel from CF. 
If you mean "root" from it, then you are approaching this the wrong way -- it 
won't work through the pcmcia stack and cardmgr because that means you already 
have a root fs up and mounted. You could do this by creating a small ramdisk to 
serve as the root fs, run a special script on startup that loads the driver, 
starts cardmgr, cardmgr then detects the card and loads ide-cs.o, and finally 
the script exits back to the kernel. At that point the kernel mounts the real 
rootfs which is on the card itself.

Or, you use the ide mode/feature of CF and get it to work that way, but I've 
never had to do that myself. Then the card looks like an ide device. That's 
something one of our guys at Embedded Alley has done in the past. Don't know how 
easy it is; I'll ping him.

Pete

---

From: Ulrich Eckhardt <[email-masked]>
Date: Wed, 16 Mar 2005 08:16:52 +0100

Pete Popov wrote:
> Ulrich Eckhardt wrote:
> > Hmmm, I just had a scary thought: I don't have any userspace programs
> > running yet, meaning also no cardmgr, because I intend to boot from that
> > CF card - is that possible at all? FYI, I don't need any hotplugging at
> > all.
>
> Do you really mean "boot" from it or "root" from it? If you want to "boot"
> from it, you need to work on your boot loader to be able to fetch the
> kernel from CF. 

I have two MiB of flash on board, which contains the bootloader (YAMON) and 
some free space for a kernel. This is used to boot from. IOW, I mean to root 
from the CF card, not to boot from it.

> If you mean "root" from it, then you are approaching this 
> the wrong way -- it won't work through the pcmcia stack and cardmgr because
> that means you already have a root fs up and mounted. You could do this by
> creating a small ramdisk to serve as the root fs, run a special script on
> startup that loads the driver, starts cardmgr, cardmgr then detects the
> card and loads ide-cs.o, and finally the script exits back to the kernel.
> At that point the kernel mounts the real rootfs which is on the card
> itself.

Sounds like the way to go.

> Or, you use the ide mode/feature of CF and get it to work that way, but
> I've never had to do that myself. Then the card looks like an ide device.
> That's something one of our guys at Embedded Alley has done in the past.
> Don't know how easy it is; I'll ping him.

Sounds like another way to go, in particular since I don't need hotplugging 
and other PCMCIA features (and their overhead).

Pete, I owe you a beer. I can see a few things much, much clearer now, thanks!

Uli

---

From: Pete Popov <[email-masked]>
Date: Wed, 16 Mar 2005 00:02:23 -0800

> and other PCMCIA features (and their overhead).

Right. And it shouldn't be that hard, but the support just isn't there so some 
work is involved. Finding an example would be the way to go.

> Pete, I owe you a beer. I can see a few things much, much clearer now, thanks!

So open source is indeed about free beer :)

Pete

---

From: Ulrich Eckhardt <[email-masked]>
Date: Wed, 16 Mar 2005 18:08:09 +0100

Pete Popov wrote:
> > Sounds like another way to go, in particular since I don't need
> > hotplugging and other PCMCIA features (and their overhead).
>
> Right. And it shouldn't be that hard, but the support just isn't there so
> some work is involved. Finding an example would be the way to go.

OK, I'm just giving a short update on what I've found. In 
asm-mips/mach-generic/ide.h is a function ide_probe_legacy() which is called 
to determine IDE support but which returns 0 for my setup. I simply 
hard-wired this value to 1 and now at least it tries to probe something.

However, it is looking at ioports in the range 366-3f6, which are already 
reserved by something else. Anyway, that is rather a legacy PC-style layout 
and thus probably doesn't apply to the PCMCIA version, if I'm not mistaken. I 
also tried simply removing the check whether they are reserved, but that just 
OOPSed.

Looking at EBOOT (a bootloader for win CE that boots off the compactflash), it 
tries to access the IDE interface at address 0x1a00000 for io_addr and 
0x1a00000e for control, let's see if I can find any IDE hardware at that 
address...

Uli

---

From: Pete Popov <[email-masked]>
Date: Wed, 16 Mar 2005 09:21:14 -0800

> 0x1a00000e for control, let's see if I can find any IDE hardware at that 

Uhm, I don't think you'll resolve this that easily. There is some code that 
needs to go in the au1x00 socket driver which means  you would have to 
understand pretty well how this thing works. Ultimately the addresses you'll 
probe are very high ioremapped addresses, since the pcmcia attribute, common 
mem, and i/o are 36 bit physical addresses.

Pete

---

From: Ulrich Eckhardt <[email-masked]>
Date: Thu, 17 Mar 2005 16:26:00 +0100

Pete Popov wrote:
>> Looking at EBOOT (a bootloader for win CE that boots off the
>> compactflash), it tries to access the IDE interface at address 0x1a00000
>> for io_addr and 0x1a00000e for control, let's see if I can find any IDE
>> hardware at that address...
>
> understand pretty well how this thing works. Ultimately the addresses
> you'll probe are very high ioremapped addresses, since the pcmcia
> attribute, common mem, and i/o are 36 bit physical addresses.

Looking at EBOOT, it creates these mappings here in the TLB:
  0xf 0000 0000  -> 0x1a00 0000 (IO)
  0xf 4000 0000  -> 0x1c00 0000 (attrib)
  0xf 8000 0000  -> 0x1e00 0000 (mem)
each time mapping 32MiB.

In the Linux PCMCIA code, I see that only the IO range above gets ioremap()ed, 
and only 4KiB thereof. For the other two ranges, it uses two addresses that 
are intended for use with fixup_bigphys_addr()[1] but seem to target the 
equivalent physical addresses as in EBOOT.

I tried simply ioremap()ing the IO region and looked for an ATA interface at 
the beginning of that range, but the contents of that memory seem to be 
rather random. I'll next try to remove both PCMCIA and IDE drivers, just to 
make sure they don't interact in any unforseeable way with my ad-hoc code, 
but that's scheduled for tuesday.

I also found www.ata-atapi.com/atadrvr.zip, which contains low-level driver 
sourcecode and examples, so I have something to read over the weekend. ;)

Thank you all for your help!

Uli

[1] Why the difference in the handling of the three ranges? Also, what 
additional effect does ioremap() have when compared to using the TLB? Is it 
that ioremap() is the Right Way(tm) on any architecture while TLB is the way 
that works only on MIPS?

---

From: Pete Popov <[email-masked]>
Date: Thu, 17 Mar 2005 20:13:01 -0800

> and only 4KiB thereof. 

That's all that's really needed.

> For the other two ranges, it uses two addresses that 

Correct. The pcmcia stack will call ioremap on those phys addresses when necessary.

> rather random. 

Well, that's the I/O registers. If you remapped them correctly and you are 
actually talking to the device, then the data should not be so random. But the 
attribute memory is a better first test. Hack up the driver to ioremap the attr 
space after a card is inserted, dump some of that data, and then free the region 
-- just a simple test to make sure the device is powered and you're actually 
talking to it.

> I'll next try to remove both PCMCIA and IDE drivers, just to 

> that ioremap() is the Right Way(tm) on any architecture 

Yes.

> while TLB is the way that works only on MIPS?

No, other processors have TLBs too. I assume you're refering to the yamon vs 
Linux kernel. Yamon just uses statically setup TLBs to access those addresses. 
When you call ioremap in the kernel, the kernel will setup the necessary tables 
to be able to map and handle those phys addresses only when needed. Those TLBs 
are flushed randomly, and then reentered by the kernel dynamically when needed 
because of a page fault.

Pete