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.

AM335x connecting SRAM and NAND by GPMC

Other Parts Discussed in Thread: AM3359

Hi,

We'd like to connect a SRAM(CS16LV40963 - www.chiplus.com) and a NAND (K9K8G08) to am3359's GPMC,  Is it possible to connect SRAM like Figure7-4 and NAND Figure7-5 in SPRUH73C, no latcher used.

By the way, a 16bit-LCD is also involved, it should does nothing with GPMC, is it?

Thanks a lot!

  • Hi,
     
    The NAND connection is quite straightforward, you just have to keep in mind that if you want to boot from it you should use GPMC_CS0 and connect the NAND R/B signal to GPMC_WAIT0 with an external pullup resistor.
     
    For the SRAM you can use any of the other chip-select signals. You will need to use the NOR non-multiplexed 16-bit mode
     
    For the necessary pins please see Table 7-5 in the AM335X TRM, Rev. J.
     
    The necessary address pins for the SRAM will however overlap with the LCD pins. I would suggest that you add an external address latch and use multiplexed 16-bit mode for the SRAM.
     
    You should use the AM335X pinmux utility (http://processors.wiki.ti.com/index.php/Pin_Mux_Utility_for_ARM_MPU_Processors) to determine the required pin combination for your design.
  • Hello

    I’m student and have a task to tune external memory  over GPMC. It’s my first experience and i’m looking for way how to do this correctly. If you have not yet tired on this line, I would be appreciated for your help.

    External memory  (nvsram cy62136esl : http://www.cypress.com/?docID=45522 ) is connected to Variscite SoC (am335x) as is shown on the image below. 
    There is a NAND (1G) on GPMC too on CS0.
    I understand how this memory works, but i couldn’t find any good example how to configure GPMC for it.
    I try to do this in device tree file using nand section as an example and can’t understand:
    1. where is pinmux  done for nand?
    2. where registers of GPMC (GPMC_CONFIG1 according TRM 7.1.5.11) are defined?
    3. am i on the right way using device tree file? :)

    thank's in advance!

  • Hi Marina,

    Please post which Linux version you are using. I will ask the SW team to help on this.

  • Hi Marina,

    Marina Egorova said:
    am i on the right way using device tree file? :)

    If you are using TI SDK release later than SDK7.0 (SDK07.00, SDK08.00 or SDK1.00) then, yes, all GPMC timing configurations & pin muxing is done in your dts.

    For example on how to set the GPMC parameters you can refer to Documentation/devicetree/bindings/mtd/gpmc-nand.txt. 

    Marina Egorova said:
    where is pinmux  done for nand?

     

    Again that would be your dts file. As a reference you can use: arch/arm/boot/dts/am335x-evm.dts file. Check the nandflash_pins_default: nandflash_pins_default {nandflash_pins_sleep: nandflash_pins_sleep { and the &gpmc { device tree nodes. 

    Marina Egorova said:
    where registers of GPMC (GPMC_CONFIG1 according TRM 7.1.5.11) are defined?

     

    The register definition is done in arch/arm/mach-omap2/gpmc.h file. Then the drivers (gpmc.c & gpmc-nand.c) take the timing values defined in the DTS file & write them into the GPMC registers. 

    Hope this helps. 

    Best Regards, 
    Yordan

  • Thank you. I use ti-sdk-am335x-evm-07.00.00.00
  • Thank you for information. Now i need some time to understand this information byte by byte :)
  • --> The register definition is done in arch/arm/mach-omap2/gpmc.h file. Then the drivers (gpmc.c & gpmc-nand.c) take the timing values defined

    --> in the DTS file & write them into the GPMC registers.

    Should i implement my own C-driver for access to SRAM through GMPC or only DTS-file's area is enough? Where can i get information how to do it?

  • Marina Egorova said:
    Should i implement my own C-driver for access to SRAM through GMPC or only DTS-file's area is enough? Where can i get information how to do it?

     

    I am afraid that there aren't any example codes. You should refer to AM335x Technical Reference Manual, Chapter 7.1 GPMC.  I think functions should be quite similar to the ones implemented in gpmc.c & gpmc-nand.c, so you can reuse that code or just do the modifications (IF SUCH ARE NEEDED) inside the existing drivers. 

    Best Regards, 

    Yordan

  • Yordan Kovachev said:

    I am afraid that there aren't any example codes. You should refer to AM335x Technical Reference Manual, Chapter 7.1 GPMC.  I think functions should be quite similar to the ones implemented in gpmc.c & gpmc-nand.c, so you can reuse that code or just do the modifications (IF SUCH ARE NEEDED) inside the existing drivers. 

    Thank you for your response!

    Yes i'm reading AM335x TRM, wiki and linux kernel documentation .  All sources say GPMC provide :

    Documentation/bus-devices/ti-gpmc.txt said:

    * Asynchronous SRAM like memories and application specific integrated circuit devices. * Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash * Pseudo-SRAM devices

    There are examples for linux DT file almost for all cases except first  Asynchronous SRAM case. Quite strange.  Thats why i try to find information of correct way to implement it and hope to find somebody with experience in this topic.

  • H Marina,

    In general:
    -you should leave the configuration of gpmc: gpmc@50000000 { in am33xx.dtsi as is, you shouldn't do any modifications there.
    -then in your dts file you should add something like:
    &gpmc {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&gpmc_pins>;

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

    /* chip select ranges */
    ranges = <1 0 0x01000000 0x1000000>;

    sram{
    reg = <1 0 0x01000000>; /*CSn1*/

    bank-width = <2>; /* GPMC_CONFIG1_DEVICESIZE(1) */

    /*gpmc,burst-write;*/
    /*gpmc,burst-read;*/
    /*gpmc,burst-wrap;*/
    gpmc,sync-read; /* GPMC_CONFIG1_READTYPE_ASYNC */
    gpmc,sync-write; /* GPMC_CONFIG1_WRITETYPE_ASYNC */
    gpmc,clk-activation-ns = <0>; /* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */
    gpmc,burst-length = <16>; /* GPMC_CONFIG1_PAGE_LEN(2) */
    gpmc,mux-add-data = <2>; /* GPMC_CONFIG1_MUXTYPE(2) */

    gpmc,sync-clk-ps = <20000>; /* CONFIG2 */

    gpmc,cs-on-ns = <0>;
    gpmc,cs-rd-off-ns = <100>;
    gpmc,cs-wr-off-ns = <40>;

    gpmc,adv-on-ns = <0>; /* CONFIG3 */
    gpmc,adv-rd-off-ns = <20>;
    gpmc,adv-wr-off-ns = <20>;

    gpmc,we-on-ns = <20>; /* CONFIG4 */
    gpmc,we-off-ns = <40>;
    gpmc,oe-on-ns = <20>;
    gpmc,oe-off-ns = <100>;

    gpmc,page-burst-access-ns = <20>; /* CONFIG 5 */
    gpmc,access-ns = <80>;
    gpmc,rd-cycle-ns = <120>;
    gpmc,wr-cycle-ns = <60>;
    gpmc,wr-access-ns = <40>; /* CONFIG 6 */
    gpmc,wr-data-mux-bus-ns = <20>;

    /*gpmc,bus-turnaround-ns = <40>;*/ /* CONFIG6:3:0 = 4 */
    gpmc,cycle2cycle-samecsen; /* CONFIG6:7 = 1 */
    gpmc,cycle2cycle-delay-ns = <20>; /* CONFIG6:11:8 = 4 */

    /* not using dma engine yet, but we can get the channel number here */

    };
    };

    You should have in mind that gpmc timing parameters should be calculated to match the timings of your SRAM (Switching Characteristics).

    Hope this helps.

    Best Regards,
    Yordan
  • Thank you for example! But i couldn't make it work :(

    My parts of dts. CS3 is last item of pinmux. It's most important for me now. Pinmux was done for nand+sram:

    	gpmc_pins_default: gpmc_pins_default {
    			pinctrl-single,pins = <
    				0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
    				0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
    				0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
    				0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
    				0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
    				0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
    				0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
    				0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
    				0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
    				0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
    				0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
    				0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
    				0x94 (PIN_OUTPUT | MUX_MODE0)		/*(T7) gpmc_oen_ren.gpmc_oen_ren */
    				0x98 (PIN_OUTPUT | MUX_MODE0)		/*(U6) gpmc_wen.gpmc_wen */
    				0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_ben0_cle.gpmc_ben0_cle */
    	
    				0xd4 ( PIN_OUTPUT | MUX_MODE1 ) /* (V3) lcd_data13.gpmc_a17 */
    				0xd0 ( PIN_OUTPUT | MUX_MODE1 ) /* (V2) lcd_data12.gpmc_a16 */
    				0xcc ( PIN_OUTPUT | MUX_MODE1 ) /* (U4) lcd_data11.gpmc_a15 */
    				0xc8 ( PIN_OUTPUT | MUX_MODE1 ) /* (U3) lcd_data10.gpmc_a14 */
    				0xc4 ( PIN_OUTPUT | MUX_MODE1 ) /* (U2) lcd_data9.gpmc_a13 */
    				0xc0 ( PIN_OUTPUT | MUX_MODE1 ) /* (U1) lcd_data8.gpmc_a12 */
    				0x6c ( PIN_OUTPUT | MUX_MODE0 ) /* (V17) gpmc_a11.gpmc_a11 */
    				0x68 ( PIN_OUTPUT | MUX_MODE0 ) /* (T16) gpmc_a10.gpmc_a10 */
    				0x64 ( PIN_OUTPUT | MUX_MODE0 ) /* (U16) gpmc_a9.gpmc_a9 */
    				0x60 ( PIN_OUTPUT | MUX_MODE0 ) /* (V16) gpmc_a8.gpmc_a8 */
    				0x5c ( PIN_OUTPUT | MUX_MODE0 ) /* (T15) gpmc_a7.gpmc_a7 */
    				0x58 ( PIN_OUTPUT | MUX_MODE0 ) /* (U15) gpmc_a6.gpmc_a6 */
    				0x54 ( PIN_OUTPUT | MUX_MODE0 ) /* (V15) gpmc_a5.gpmc_a5 */
    				0x50 ( PIN_OUTPUT | MUX_MODE0 ) /* (R14) gpmc_a4.gpmc_a4 */
    				0x4c ( PIN_OUTPUT | MUX_MODE0 ) /* (T14) gpmc_a3.gpmc_a3 */
    				0x48 ( PIN_OUTPUT | MUX_MODE0 ) /* (U14) gpmc_a2.gpmc_a2 */
    				0x44 ( PIN_OUTPUT | MUX_MODE0 ) /* (V14) gpmc_a1.gpmc_a1 */
    				0x40 ( PIN_OUTPUT | MUX_MODE0 ) /* (R13) gpmc_a0.gpmc_a0 */
    				0x3c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (U13) gpmc_ad15.gpmc_ad15 */
    				0x38 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (V13) gpmc_ad14.gpmc_ad14 */
    				0x34 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (R12) gpmc_ad13.gpmc_ad13 */
    				0x30 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (T12) gpmc_ad12.gpmc_ad12 */
    				0x2c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (U12) gpmc_ad11.gpmc_ad11 */
    				0x28 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (T11) gpmc_ad10.gpmc_ad10 */
    				0x24 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (T10) gpmc_ad9.gpmc_ad9 */
    				0x20 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (U10) gpmc_ad8.gpmc_ad8 */
    				0x88 ( PIN_OUTPUT | MUX_MODE0 ) /* (T13) gpmc_csn3.gpmc_csn3 */
    				
    			>;
    		};


    gpmc0: gpmc@50000000 {
    			status = "okay";
    			pinctrl-names = "default", "sleep";
    			pinctrl-0 = <&gpmc_pins_default>;
    			pinctrl-1 = <&gpmc_pins_sleep>;
    			#address-cells = <2>;
    			#size-cells = <1>;
    			ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
    			ranges = <3 0 0x01000000 0x00020000>;	/* CS3: SRAM */
    			
    			nand@0,0 {
    				reg = <0 0 0>; /* CS0, offset 0 */
    				...
    			};
    			
    			sram{
    				reg = <3 0 0x20000>; 
    				bank-width = <2>;	/* GPMC_CONFIG1_DEVICESIZE(1) */
    				gpmc,sync-read;	/* GPMC_CONFIG1_READTYPE_ASYNC */
    				gpmc,sync-write;	/* GPMC_CONFIG1_WRITETYPE_ASYNC */
    				gpmc,clk-activation-ns = <0>;	/* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */
    				gpmc,burst-length = <16>;	/* GPMC_CONFIG1_PAGE_LEN(2) */
    				gpmc,mux-add-data = <2>;	/* GPMC_CONFIG1_MUXTYPE(2) */
    
    				gpmc,sync-clk-ps = <20000>;	/* CONFIG2 */
    
    				gpmc,cs-on-ns = <0>;
    				gpmc,cs-rd-off-ns = <90>;
    				gpmc,cs-wr-off-ns = <90>;
    
    				gpmc,adv-on-ns = <6>;	/* CONFIG3 */
    				gpmc,adv-rd-off-ns = <50>;
    				gpmc,adv-wr-off-ns = <50>;
    
    				gpmc,we-on-ns = <20>;	/* CONFIG4 */
    				gpmc,we-off-ns = <55>;
    				gpmc,oe-on-ns = <24>;
    				gpmc,oe-off-ns = <70>;
    
    				gpmc,page-burst-access-ns = <20>;	/* CONFIG 5 */
    				gpmc,access-ns = <47>;
    				gpmc,rd-cycle-ns = <90>;
    				gpmc,wr-cycle-ns = <90>;
    				gpmc,wr-access-ns = <0>;	/* CONFIG 6 */
    				gpmc,wr-data-mux-bus-ns = <20>;
    
    				/*gpmc,bus-turnaround-ns = <40>;*/	/* CONFIG6:3:0 = 4 */  
    				gpmc,cycle2cycle-samecsen;	/* CONFIG6:7 = 1 */
    				gpmc,cycle2cycle-delay-ns = <20>;	/* CONFIG6:11:8 = 4 */
    
    			};
    
    
    		};

    My simple test:

    int main(int argc, char const *argv[])
    {
    	const uint32_t mem_address = 0x01000000;
    	const uint32_t mem_size = 0x20000;
    	uint32_t alloc_mem_size, page_mask, page_size;
    	void *mem_pointer, *virt_addr;
    
    	printf ("Test memory \n");
    
    	page_size = sysconf(_SC_PAGESIZE);
    	alloc_mem_size = (((mem_size / page_size) + 1) * page_size);
    	page_mask = (page_size - 1);
    
    	int mem_dev = open("/dev/mem", O_RDWR | O_SYNC);
    
    	mem_pointer = mmap(NULL,
                       alloc_mem_size,
                       PROT_READ | PROT_WRITE,
                       MAP_SHARED,
                       mem_dev,
                       (mem_address & ~page_mask)
                       );
    	if(mem_pointer == MAP_FAILED)
    	{  
    	      perror("Error mmap");
    	}
    
    	virt_addr = (mem_pointer + (mem_address & page_mask));
    
    	 uint i;
    	 unsigned char j;
    
    	 for (i=0; i<mem_size-1; i++)
    	 	//printf("content: 0x%x\n",*(unsigned char *)(virt_addr+i));
    	 	j = *(unsigned char *)(virt_addr+i);
    	
    	
    	if (munmap(mem_pointer, alloc_mem_size) == -1)
    		perror("Error un-mmapping the file");
    	
    	close(mem_dev);
    
    	return 0;
    }

    Ignoring all timings I expect only to see changing CS3 signal, but it doesn't happened. CS3 is always on the top level. OE and WE are ok  work as expected.  

    I tried use "sram@3.0" instead "sram" and reg=<3 0 0> the result is the same. CS3 doesn't works. 

    What did i miss?

  • I implemented kernel module. It sets params for GPMC CS3 requests and shares memory. And it works very well. It's make me sure:
    1) hardware is ok
    2) timings is ok
    3) pinmux is ok

    But i can't make the Device Tree work ( except pinmux it was done it DT) using your example. My device appears with params here: /proc/device-tree/ocp/gpmc\@50000000/sram/ . The range of memory of this device doesn't appears in /proc/iomem and clients cant get access to this range.

    Could you say what i'm missing?
    my DT :

    gpmc: gpmc@50000000 {
    status = "okay";
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&nandflash_pins_default>;
    pinctrl-1 = <&nandflash_pins_sleep>;
    ranges = <0 0 0x08000000 0x10000000  /* CS0: NAND */
                     3 0 0x02000000 0x40000>;

    sram {
    reg = <3 0 0x40000>; /*CSn3*/
    bank-width = <2>;
    gpmc,cs-on-ns = <0>;
    gpmc,cs-rd-off-ns = <46>;
    gpmc,cs-wr-off-ns = <45>;
    gpmc,adv-on-ns = <0>;
    gpmc,adv-rd-off-ns = <46>;
    gpmc,adv-wr-off-ns = <45>;
    gpmc,we-on-ns = <0>;
    gpmc,we-off-ns = <45>;
    gpmc,oe-on-ns = <0>;
    gpmc,oe-off-ns = <45>;
    gpmc,access-ns = <46>;
    gpmc,rd-cycle-ns = <63>;
    gpmc,wr-cycle-ns = <45>;
    };

    nand@0,0 {
    reg = <0 0 0>; /* CS0, offset 0 */
    nand-bus-width = <8>;
    ...

    thanks

  • Hi Marina,

    Sorry for the delayed response.

    I think your dts configuration is wrong, that is why you cant see gpmc in /proc/iomem

    In am33xx.dtsi you have:
    gpmc: gpmc@50000000 {
    compatible = "ti,am3352-gpmc";
    ti,hwmods = "gpmc";
    ti, no-idle-on-init;
    reg = <0x50000000 0x2000>;
    interrupts = <100>;
    gpmc,num-cs = <7>;
    gpmc,num-waitpins = <2>;
    #address-cells = <2>;
    #size-cells = <1>;
    status = "disabled";
    };

    This SHOULD NOT BE CHANGED.
    Then in your dts file (am335x-boneblack.dts or whatever .dts you are using), you should add:
    ggpmc_pins: pinmux_gpmc_pins {
    pinctrl-single,pins = <
    0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
    0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
    0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
    0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
    0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
    0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
    0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
    0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
    0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
    0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */
    0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
    0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
    0x94 (PIN_OUTPUT | MUX_MODE0) /*(T7) gpmc_oen_ren.gpmc_oen_ren */
    0x98 (PIN_OUTPUT | MUX_MODE0) /*(U6) gpmc_wen.gpmc_wen */
    0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0_cle.gpmc_ben0_cle */

    0xd4 ( PIN_OUTPUT | MUX_MODE1 ) /* (V3) lcd_data13.gpmc_a17 */
    0xd0 ( PIN_OUTPUT | MUX_MODE1 ) /* (V2) lcd_data12.gpmc_a16 */
    0xcc ( PIN_OUTPUT | MUX_MODE1 ) /* (U4) lcd_data11.gpmc_a15 */
    0xc8 ( PIN_OUTPUT | MUX_MODE1 ) /* (U3) lcd_data10.gpmc_a14 */
    0xc4 ( PIN_OUTPUT | MUX_MODE1 ) /* (U2) lcd_data9.gpmc_a13 */
    0xc0 ( PIN_OUTPUT | MUX_MODE1 ) /* (U1) lcd_data8.gpmc_a12 */
    0x6c ( PIN_OUTPUT | MUX_MODE0 ) /* (V17) gpmc_a11.gpmc_a11 */
    0x68 ( PIN_OUTPUT | MUX_MODE0 ) /* (T16) gpmc_a10.gpmc_a10 */
    0x64 ( PIN_OUTPUT | MUX_MODE0 ) /* (U16) gpmc_a9.gpmc_a9 */
    0x60 ( PIN_OUTPUT | MUX_MODE0 ) /* (V16) gpmc_a8.gpmc_a8 */
    0x5c ( PIN_OUTPUT | MUX_MODE0 ) /* (T15) gpmc_a7.gpmc_a7 */
    0x58 ( PIN_OUTPUT | MUX_MODE0 ) /* (U15) gpmc_a6.gpmc_a6 */
    0x54 ( PIN_OUTPUT | MUX_MODE0 ) /* (V15) gpmc_a5.gpmc_a5 */
    0x50 ( PIN_OUTPUT | MUX_MODE0 ) /* (R14) gpmc_a4.gpmc_a4 */
    0x4c ( PIN_OUTPUT | MUX_MODE0 ) /* (T14) gpmc_a3.gpmc_a3 */
    0x48 ( PIN_OUTPUT | MUX_MODE0 ) /* (U14) gpmc_a2.gpmc_a2 */
    0x44 ( PIN_OUTPUT | MUX_MODE0 ) /* (V14) gpmc_a1.gpmc_a1 */
    0x40 ( PIN_OUTPUT | MUX_MODE0 ) /* (R13) gpmc_a0.gpmc_a0 */
    0x3c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (U13) gpmc_ad15.gpmc_ad15 */
    0x38 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (V13) gpmc_ad14.gpmc_ad14 */
    0x34 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (R12) gpmc_ad13.gpmc_ad13 */
    0x30 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (T12) gpmc_ad12.gpmc_ad12 */
    0x2c ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (U12) gpmc_ad11.gpmc_ad11 */
    0x28 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (T11) gpmc_ad10.gpmc_ad10 */
    0x24 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (T10) gpmc_ad9.gpmc_ad9 */
    0x20 ( PIN_INPUT_PULLUP | MUX_MODE0 ) /* (U10) gpmc_ad8.gpmc_ad8 */
    0x88 ( PIN_OUTPUT | MUX_MODE0 ) /* (T13) gpmc_csn3.gpmc_csn3 */

    >;
    };

    &gpmc {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&gpmc_pins>;
    #address-cells = <2>;
    #size-cells = <1>;
    ranges = <0 0 0x01000000 0x1000000>;
    sram {
    reg = <3 0 0x40000>; /*CSn3*/
    bank-width = <2>;
    gpmc,cs-on-ns = <0>;
    gpmc,cs-rd-off-ns = <46>;
    gpmc,cs-wr-off-ns = <45>;
    gpmc,adv-on-ns = <0>;
    gpmc,adv-rd-off-ns = <46>;
    gpmc,adv-wr-off-ns = <45>;
    gpmc,we-on-ns = <0>;
    gpmc,we-off-ns = <45>;
    gpmc,oe-on-ns = <0>;
    gpmc,oe-off-ns = <45>;
    gpmc,access-ns = <46>;
    gpmc,rd-cycle-ns = <63>;
    gpmc,wr-cycle-ns = <45>;
    };
    };
    Configured this way I was able to get the gpmc working on beaglebone, & the controller was visible in /proc/iomem.
    I've also succeeded in configuring the GPMC interface from userspace using the following address remapping & macros:
    #define MMAP_OFFSET 0x44c00000
    #define HWREG(x) __mmapl[(x-MMAP_OFFSET)/4] /*Macro for setting registers from USERSPCE*/
    volatile uint32_t *__mmapl;
    int fd = open("/dev/mem", O_RDWR|O_SYNC); //O_SYNC makes the memory uncacheable
    #if 1
    __mmapl = (uint32_t*) mmap(NULL, 0x10000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, MMAP_OFFSET);

    gpmc_init(); /*Function using HWREG to set GPMC, PRCM & PINMUX Registers*/
    #endif

    Hope this helps.

    Best Regards,
    Yordan
  • thanks a lot for your response!

    I didn’t change am33xx.dtsi. But it has some differences from your example. 

    My  am33xx.dtsi:

    gpmc: gpmc@50000000 {
    compatible = "ti,am3352-gpmc";
    ti,hwmods = "gpmc";
    ti,no-idle;
    clocks = <&l3s_gclk>;
    clock-names = "fck";
    reg = <0x50000000 0x2000>;
    interrupts = <100>;
    gpmc,num-cs = <7>;
    gpmc,num-waitpins = <2>;
    #address-cells = <2>;
    #size-cells = <1>;
    status = "disabled";
    };

    And all variants based on examples posted here give the same result:

    root@am335x-evm:~# ./devmem2 0x2000000 h
    
    /dev/mem opened.
    
    Memory mapped at address 0xb6fb4[   58.452916] Unhandled fault: external abort on non-linefetch (0x1018) at 0xb6fb4000000.
    
    Bus error

    But i looked at gpmc.c (line 1585):

    for_each_child_of_node(pdev->dev.of_node, child) {
    
    		if (!child->name)
    			continue;
    
    		if (of_node_cmp(child->name, "nand") == 0)
    			ret = gpmc_probe_nand_child(pdev, child);
    		else if (of_node_cmp(child->name, "onenand") == 0)
    			ret = gpmc_probe_onenand_child(pdev, child);
    		else if (of_node_cmp(child->name, "ethernet") == 0 ||
    			 of_node_cmp(child->name, "nor") == 0)
    			ret = gpmc_probe_generic_child(pdev, child);
    
    		if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
    			 __func__, child->full_name))
    			of_node_put(child);
    	}

    it looks like it doesn’t register any device out of list nand, onenand, ethernet and nor.

    I tried use the name «nor@3,0» instead «sram» in my  dis-file  and it works, and your example works with the name "nor" too!

    root@am335x-evm:~# ./devmem2 0x2000000 h
    
    /dev/mem opened.
    
    Memory mapped at address 0xb6f57000.
    
    Value at address 0x2000000 (0xb6f57000): 0x0

    But /proc/iomem doesn't have item about region of 0x2000000. But it works exactly where it is expected. 

    Is it correct or not? i don't now, but it really works.