This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3354: GPMC: multiple instances of same device on a single chip select

Part Number: AM3354


Hello Team,

We have a custom AM3354 based platform running kernel 5.10. On the GPMC bus, we've a NAND flash on the first chip select (CS0) and it works just fine. On the second chip select (CS1), we've multiple instances of an external UART (XR16M752) which is NS16550 compliant.

The GPMC chip select enables all the external UARTs and one of them should then be selected based on the values of GPMC_A3/4/5. I enabled just the first instance of the UART using the below snippet in my device tree

ext_uart@1,0 {
		compatible = "ns16550a";
		reg = <1 0 0x01000000>;

		#address-cells = <1>;
		#size-cells = <1>;

		fifo-size = <64>;

		clock-frequency = <3686400>;

		bank-width = <1>;
		gpmc,device-width = <1>;	/* 8-bit data width */
		gpmc,cs-on-ns = <0>;		/* Assertion time */
		gpmc,cs-rd-off-ns = <20>;	/* Read deassertion time */
		gpmc,cs-wr-off-ns = <20>;	/* Write deassertion time */
		gpmc,sync-clk-ps = <20000>;
	};

under the gpmc main node. At runtime, the device was probed successfully

[    2.320974] 9000000.ext_uart: ttyS1 at MMIO 0x9000000 (irq = 0, base_baud = 230400) is a 16550A

However, when I try to write to ttyS1

# echo 1 >/dev/ttyS1

the target hangs. I am continuing my investigation further but would like to get the expert's input early in the process.

I have the following initial questions

Regards,

Awais

  • Hi Awais,

    Are there any examples available for the GPMC bus which would be using multiple child devices on the same chip select?

    Not in the SDK. I am not aware of any other similar reference design either.

    Is sub-device selection possible using GPMC_A3/4/5?

    I think in theory it is possible, but it is up to the board design, how these address pins are used to control the sub-devices, and how the logic is implemented in your customized GPMC driver.

  • It turns out that the GPMC seems to be very sensitive to its CS timings. After going through the UART's datasheet and making adjustments to the timings I was able to make this work. The final node has the following settings

            compatible = "ns16550a";
    		reg = <1 0 8>; /* CS1, device offset in CS mem, size of device mem */
    		
    		/* UART settings */
    		reg-shift = <0>;
    		reg-io-width = <1>;
    		fifo-size = <64>;
    		clock-frequency = <3686400>;
    
    		bank-width = <1>;
    
    		/* For the same CS, timing data is only required in the first node */
    		gpmc,mux-add-data = <0>;
    		gpmc,device-width = <1>;
    		gpmc,cycle2cycle-samecsen;
    		gpmc,cycle2cycle-diffcsen;
    		gpmc,cs-on-ns = <10>;
    		gpmc,cs-rd-off-ns = <10>;
    		gpmc,cs-wr-off-ns = <10>;
    		gpmc,oe-on-ns = <10>;
    		gpmc,oe-off-ns = <10>;
    		gpmc,we-on-ns = <10>;
    		gpmc,we-off-ns = <10>;
    		gpmc,rd-cycle-ns = <50>;
    		gpmc,wr-cycle-ns = <50>;
    		gpmc,access-ns = <40>;
    		gpmc,bus-turnaround-ns = <40>;
    		gpmc,cycle2cycle-delay-ns = <40>;

    The GPMC interface seems to be very flexible and easy to use (at least on the Linux BSP). However, I do not think it is well documented anywhere how the overall flow (in principle) goes which took a lot of time here...

    Also there's a bug in the omap-gpmc.c driver where, per my understanding, it does not handle the CS naming correctly. Will try to submit a patch upstream and we'll see.