Access chip Select register with 8bit bus size

669 views Asked by At

We have a problem to communicate with a register, CS4, at at 0x10020000. In U-boot that reg has the value 0x45fab3c1, but when we try to access it we get: 0x10101010 and we are not able to write too.

With CS3 everything seems ok, we can read and write. CS3 is at: 0x10000000.

The main/only differences between cs3 and cs4 are:

Chip Select: Lp_cs3 Bus size: 32 bit Bus control: 2 wait state R/W ACK disabled Allocated size 32Kbyte

Chip Select: Lp_cs4 Bus size: 8 bit Bus control: 2 wait state R/W ACK disabled Allocated size: 4 KByte

In userspace we use:

/*————————————————————————————————*/
//code from memedit.c
int fd;
fd = open("/dev/mem", O_SYNC | O_RDWR);
mem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset & (~4095));
printf("/dev/mem[0x%08x] = 0x%08x", offset, *(unsigned int*)&mem[offset & 4095]);

//to write
*((unsigned int *)&mem[offset & 4095]) = input;
/*————————————————————————————————*/

In our kernel module:

/*————————————————————————————————*/
#define CS4_START    0x10020000U
#define CS4_STOP     0x10040000U
#define CS4_SIZE     0x00020000U
#define CS3_START    0x10000000U
#define CS3_STOP     0x10020000U
#define CS3_SIZE     0x00020000U

void __iomem *cs3_ioaddr   = ioremap ((volatile unsigned long)(CS3_START), CS3_SIZE);
printk("We read value at CS3: %x \n\n\n",in_be32(cs3_ioaddr+0x0018));
out_be32(cs3_ioaddr+0x0018,0x00000001);
printk("We read written value: %x \n\n\n",in_be32(cs3_ioaddr+0x0018));
/*————————————————————————————————*/

Chip Select are correctly initialized...

Platform is based on mpc5200b CPU and fpga is a Xilinx Virtex4. Kernel we use: 2.6.33

More information:

i've tried inn/outb, in_8/out_8... but when i try to read/write with this code inside kernel:

/*----------------*/
static struct device_node *memoria_cs4;
static void __iomem *reg_cs4;
memoria_cs4 = of_find_node_by_path("/localbus/fpga@0,0/cs@0");
reg_cs4 = of_iomap(memoria_cs4, 0);

printk("Value before, at reg_cs4+0x001: %x \n",in_8(reg_cs4+0x323));
out_8(reg_cs4+0x001,0xFA);
printk("Value after, at reg_cs4+0x001: %x \n",in_8(reg_cs4+0x323));
/*----------------*/

i get before and after the same value: 0x10. But the value, i see in uboot, is: 0xFB. i've tried also inb/outb... That code, with cs3, but with in_be32/out_be 32, works... naturally i've changed memory location in device tree from cs4 to cs3... But i've tried it also with ioremap(), and the same: cs3 works, but cs4 not...

Thanks again in advance…

neorf

1

There are 1 answers

4
alexander On

Just to clarify the situation. You have a board with following architecture:

+------------------+                     
|                  | BUS3 (CS3)          +------------------+
|                  +------ 32 bit -------+      xilinx      |
|                  |                     +------------------+
|                  |                     
|     mpc5200b     |                     
|                  | BUS4 (CS4)          +------------------+
|                  +------- ? bit -------+      xilinx      |
|                  |                     +------------------+
|                  |
+------------------

The board has mpc5200b and xilinx connected throw 2 buses. Bus3 and bus4 are connected via 'Multi-Function External LocalPlus Bus'.

To write to xilinx via BUS4 (CS4) you must to write to some virtual address, that will be translated to some physical address.

Virtual addresses for BUS4 inside u-boot and kernel doesn't match.

Then the physical address will be compared with registers 'CS3 Start' / 'CS3 Stop'. If match, physical transfer will be started on BUS4 (this could be simple checked using oscilloscope).

Physical transfer has a lot of configurable options (address size, data size, read only, write only). All that options must match hardware design. (Chip Select 4 Configuration Register, Chip Select 4 Control Register).

You told, what in u-boot BUS3 and BUS4 works. You can write and read correct data.

After that linux kernel starts.

BUS3 continue to work as expected, but BUS4 stop work.

You access CS4 space inside mpc5200b using correct instruction (the same, like in u-boot: out_be32) using correct Virtual and physical addresses, but BUS4 doesn't work.

The kind of failure, you mentioned, is like an access to wrong address or like an access to correct address, but with wrong access mode.

I think, that LocalPlus Bus registers content is changed by kernel code during kernel boot.

Chip Selects (active low), CS[4] and CS[5] shared with ATA. May be conflict with another kernel driver.

Without hardware design, without kernel source and compilation options, without dts-file content, without u-boot source I can't find more specific answer.