NWR04B: Module works

Welp, I've got my module working...at least, in the sense that it makes Baby Linus cry. It's pretty ugly, but it loads and unloads and PEEKs and POKEs memory the way I want it to, which is all I need. (Used to have a VIC-20 when I was a kid, where you'd have to POKE different bits of memory to make it play a tune. Never thought I'd be duplicating that 20 -- no, closer to 30 -- years later.)

Of course, I'm still having no luck at all actually probing for flash. What I'm doing should match up with both the datasheets and what the firmware does, but it's just not working; instead of getting 0xAD back (the manufacturer code) I just see the bit of memory that's actually there.

I've come up with a few reasons this might be happening:

  1. The flash datasheet lies. Unlikely, since the firmware seems to follow the same sequence I'm doing.
  2. The CPU datasheet lies about where the flash memory is. Possible, but it doesn't strike me as all that likely either; what I see at that location (0x2000.0000 for those of you playing the home game) is firmware that does exactly what you'd expect booting firmware to do: set up memory, clear some registers, print a menu, and generally get the thing ready to go.
  3. The CPU datasheet lies about what's needed to program the flash. Possible. I know there's at least one write-protect bit; unless I turn it off, any attempt to write to flash results in a protection fault. It's possible there's more.
  4. Timing problems. Sounds reasonable.
  5. The process is different once you've booted. Okay, maybe. I haven't looked at the original firmware from the manufacturer (the stuff that comes after the bootloader, I mean); it's possible there's a different sequence that needs to happen.
  6. I'm not doing what I think I'm doing. I'm thinking about endianness here, which always confuses me. Dunno about this. I've tried disassembling my module, and though I don't understand a lot of what's going on, it still looks pretty familiar and pretty much what I'd expect.
  7. I've missed something. Bingo, because I definitely don't know what I'm doing.

For example: the flash datasheet says that one of the locations you POKE to is 0x555 -- yet both the firmware and the AMD-compatible flash driver in the kernel POKE to 0x554. Why? Obviously it's a 4-aligned (word-aligned?) address, but why does that still work? (For the firmware, I mean, which can obviously still write to flash.)

Or there's the whole question of bus or map width, which is important to the Linux drivers. Take this bit, again from the AMD-compatible driver:

static inline void send_unlock(struct map_info *map, unsigned long base)
{
    wide_write(map, (CMD_UNLOCK_DATA_1 < < 16) | CMD_UNLOCK_DATA_1,
           base + (map->buswidth * ADDR_UNLOCK_1));
    wide_write(map, (CMD_UNLOCK_DATA_2 < < 16) | CMD_UNLOCK_DATA_2,
           base + (map->buswidth * ADDR_UNLOCK_2));
}

Dead simple routine -- but why is ADDR_UNLOCK being multiplied by the buswidth? According to the (suspect) driver in Codeman's kernel for the CX84200 flash, the buswidth was 2 -- which means that instead of writing to (say) 0x554, it would write to 0xAA8. Wha'?

I may have to break down and set up a JTAG interface on this thing. I've been avoiding it 'til now out of stubbornness and lack of soldering skill, but it may be the only way to figure out what the hell is going on.