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.

Linux/PROCESSOR-SDK-AM335X: Avoid NAND reconfiguration in kernel

Part Number: PROCESSOR-SDK-AM335X

Tool/software: Linux

Hi,

In a  previous thread I asked how to stop the kernel from reconfiguring the GPMC parameters set by the bootloader (the thread was locked due to inactivity, I had to stay away from work and just got around recently to investigating this issue further). I received a reply telling me to use the "ti,no-reset-on-init" setting in the .dts file, but this seems to cause the kernel to crash because it can't mount /.

Original .dts node:

&gpmc {
   status = "okay";
   ranges = <0 0 0x01000000 0x10000000>;  /* CS0: 256MB */
   nand@0,0 {
      compatible = "ti,omap2-nand";
      reg = <0 0 8>; /* CS0, offset 0, IO size 4 */
      interrupt-parent = <&gpmc>;
      interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
                   <1 IRQ_TYPE_NONE>;  /* termcount */
      rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
      ti,nand-ecc-opt = "bch8";
      ti,elm-id = <&elm>;
      nand-bus-width = <8>;
      gpmc,device-width = <1>;
      gpmc,sync-clk-ps = <0>;
      gpmc,cs-on-ns = <0>;
      gpmc,cs-rd-off-ns = <25>;
      gpmc,cs-wr-off-ns = <25>;
      gpmc,adv-on-ns = <0>;
      gpmc,adv-rd-off-ns = <25>;
      gpmc,adv-wr-off-ns = <25>;
      gpmc,we-on-ns = <0>;
      gpmc,we-off-ns = <10>;
      gpmc,oe-on-ns = <0>;
      gpmc,oe-off-ns = <10>;
      gpmc,access-ns = <20>;
      gpmc,rd-cycle-ns = <25>;
      gpmc,wr-cycle-ns = <25>;
      gpmc,wr-access-ns = <0>;
      gpmc,wr-data-mux-bus-ns = <0>;
      /* MTD partition table */
      /* All SPL-* partitions are sized to minimal length
       * which can be independently programmable. For
       * NAND flash this is equal to size of erase-block */
      #address-cells = <1>;
      #size-cells = <1>;
      partition@0 {
         label = "SPL";
         reg = <0x00000000 0x000020000>;
      };
      partition@1 {
         label = "SPL.backup1";
         reg = <0x00020000 0x00020000>;
      };
      partition@2 {
         label = "SPL.backup2";
         reg = <0x00040000 0x00020000>;
      };
      partition@3 {
         label = "SPL.backup3";
         reg = <0x00060000 0x00020000>;
      };
      partition@4 {
         label = "u-boot";
         reg = <0x00080000 0x00080000>;
      };
      partition@5 {
         label = "u-boot.backup1";
         reg = <0x00100000 0x00080000>;
      };
      partition@6 {
         label = "u-boot.backup2";
         reg = <0x00180000 0x00080000>;
      };
      partition@7 {
         label = "u-boot.backup3";
         reg = <0x00200000 0x00080000>;
      };
      partition@8 {
         label = "kernel";
         reg = <0x00280000 0x00500000>;
      };
      partition@9 {
         label = "fs";
         reg = <0x00780000 0x01400000>;
      };
      partition@10 {
         label = "drivers";
         reg = <0x01b80000 0x004e0000>;
      };
      partition@11 {
         label = "dtb";
         reg = <0x02060000 0x00020000>;
      };
      partition@12 {
         label = "app";
         reg = <0x02080000 0x00a00000>;
      };
      partition@13 {
         label = "upgd";
         reg = <0x02a80000 0x00200000>;
      };
      partition@14 {
         label = "hwinfo";
         reg = <0x02c80000 0x00100000>;
      };
      partition@15 {
         label = "dmin";
         reg = <0x02d80000 0x00a00000>;
      };
      partition@16 {
         label = "dgen";
         reg = <0x03780000 0x0c880000>;
      };
   };
};

Modified .dts node:

&gpmc {
    status = "okay";
    ranges = <0 0 0x01000000 0x10000000>;  /* CS0: 256MB */
    ti,no-reset-on-init;
    nand@0,0 {
       compatible = "ti,omap2-nand";
       reg = <0 0 8>; /* CS0, offset 0, IO size 4 */
       interrupt-parent = <&gpmc>;
       interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
                    <1 IRQ_TYPE_NONE>;  /* termcount */
       rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
       ti,nand-ecc-opt = "bch8";
       ti,elm-id = <&elm>;
       nand-bus-width = <8>;
       gpmc,device-width = <1>;
       /* MTD partition table */
       /* All SPL-* partitions are sized to minimal length
        * which can be independently programmable. For
        * NAND flash this is equal to size of erase-block */
       #address-cells = <1>;
       #size-cells = <1>;
       partition@0 {
          label = "SPL";
          reg = <0x00000000 0x000020000>;
       };
       partition@1 {
          label = "SPL.backup1";
          reg = <0x00020000 0x00020000>;
       };
       partition@2 {
          label = "SPL.backup2";
          reg = <0x00040000 0x00020000>;
       };
       partition@3 {
          label = "SPL.backup3";
          reg = <0x00060000 0x00020000>;
       };
       partition@4 {
          label = "u-boot";
          reg = <0x00080000 0x00080000>;
       };
       partition@5 {
          label = "u-boot.backup1";
          reg = <0x00100000 0x00080000>;
       };
       partition@6 {
          label = "u-boot.backup2";
          reg = <0x00180000 0x00080000>;
       };
       partition@7 {
          label = "u-boot.backup3";
          reg = <0x00200000 0x00080000>;
       };
       partition@8 {
          label = "kernel";
          reg = <0x00280000 0x00500000>;
       };
       partition@9 {
          label = "fs";
          reg = <0x00780000 0x01400000>;
       };
       partition@10 {
          label = "drivers";
          reg = <0x01b80000 0x004e0000>;
       };
       partition@11 {
          label = "dtb";
          reg = <0x02060000 0x00020000>;
       };
       partition@12 {
          label = "app";
          reg = <0x02080000 0x00a00000>;
       };
       partition@13 {
          label = "upgd";
          reg = <0x02a80000 0x00200000>;
       };
       partition@14 {
          label = "hwinfo";
          reg = <0x02c80000 0x00100000>;
       };
       partition@15 {
          label = "dmin";
          reg = <0x02d80000 0x00a00000>;
       };
       partition@16 {
          label = "dgen";
          reg = <0x03780000 0x0c880000>;
       };
    };
};

Is this modification correct? I tried it with the 'ti,no-reset-on-init' only in the gpmc node and only in the nand node, but both ways caused the same error: 'Kernel panic - not syncing: Fatal exception'

Regards,

Guilherme

  • Guilherme,

    I can suggest you to try several things:

    1. In kernel DTS file, add also "ti,no-idle-on-init" and "ti,no-idle" for the GPMC node
    2. Put these 3 entries in u-boot DTS file also: "ti,no-reset-on-init", "ti-no-idle-on-init" and "ti,no-idle"
    3. remove the "SYSC_HAS_SOFTRESET" flag from gpmc_sysc struct in below file:

    linux-kernel/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c

    4. Dump the GPMC registers at linux kernel stage and check if you will have the expected values there.

    Regards,
    Pavel
  • Pavel,

    I tried your suggestion, but it's still not working. I might be doing something wrong... Here is kernel DTS:

    &gpmc {
        status = "okay";
        ranges = <0 0 0x01000000 0x10000000>;  /* CS0: 256MB */
        ti,no-idle-on-init;
        ti,no-reset-on-init;
        ti,no-idle;
        nand@0,0 {
           compatible = "ti,omap2-nand";
           reg = <0 0 8>; /* CS0, offset 0, IO size 4 */
           interrupt-parent = <&gpmc>;
           interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
                        <1 IRQ_TYPE_NONE>;  /* termcount */
           rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
           ti,nand-ecc-opt = "bch8";
           ti,elm-id = <&elm>;
           nand-bus-width = <8>;
           gpmc,device-width = <1>;
           /* MTD partition table */
           /* All SPL-* partitions are sized to minimal length
            * which can be independently programmable. For
            * NAND flash this is equal to size of erase-block */
           #address-cells = <1>;
           #size-cells = <1>;
           partition@0 {
              label = "SPL";
              reg = <0x00000000 0x000020000>;
           };
           partition@1 {
              label = "SPL.backup1";
              reg = <0x00020000 0x00020000>;
           };
           partition@2 {
              label = "SPL.backup2";
              reg = <0x00040000 0x00020000>;
           };
           partition@3 {
              label = "SPL.backup3";
              reg = <0x00060000 0x00020000>;
           };
           partition@4 {
              label = "u-boot";
              reg = <0x00080000 0x00080000>;
           };
           partition@5 {
              label = "u-boot.backup1";
              reg = <0x00100000 0x00080000>;
           };
           partition@6 {
              label = "u-boot.backup2";
              reg = <0x00180000 0x00080000>;
           };
           partition@7 {
              label = "u-boot.backup3";
              reg = <0x00200000 0x00080000>;
           };
           partition@8 {
              label = "kernel";
              reg = <0x00280000 0x00500000>;
           };
           partition@9 {
              label = "fs";
              reg = <0x00780000 0x01400000>;
           };
           partition@10 {
              label = "drivers";
              reg = <0x01b80000 0x004e0000>;
           };
           partition@11 {
              label = "dtb";
              reg = <0x02060000 0x00020000>;
           };
           partition@12 {
              label = "app";
              reg = <0x02080000 0x00a00000>;
           };
           partition@13 {
              label = "upgd";
              reg = <0x02a80000 0x00200000>;
           };
           partition@14 {
              label = "hwinfo";
              reg = <0x02c80000 0x00100000>;
           };
           partition@15 {
              label = "dmin";
              reg = <0x02d80000 0x00a00000>;
           };
           partition@16 {
              label = "dgen";
              reg = <0x03780000 0x0c880000>;
           };
        };
    };

    This version causes a kernel panic in the omap_nand_probe function:

    [    0.864084] Unhandled fault: external abort on non-linefetch (0x1008) at 0xc805d000
    [    0.872113] pgd = c0004000
    [    0.874944] [c805d000] *pgd=87834811, *pte=01000653, *ppte=01000453
    [    0.881525] Internal error: Oops - BUG: 1008 [#1] PREEMPT ARM
    [    0.887538] Modules linked in:
    [    0.890745] CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.51.UCC3.R01-ltsi-R01-Beta+ #26
    [    0.899030] Hardware name: Generic AM33XX (Flattened Device Tree)
    [    0.905406] task: c783c000 task.stack: c783e000
    [    0.910158] PC is at nand_read_byte+0x10/0x20
    [    0.914724] LR is at nand_scan_ident+0x28c/0x159c
    [    0.919647] pc : [<c035623c>]    lr : [<c035afb4>]    psr: 20000013
    [    0.919647] sp : c783fce8  ip : c783fcf8  fp : c783fcf4
    [    0.931662] r10: 00000000  r9 : c783fd2b  r8 : c783fd23
    [    0.937129] r7 : c7df6bf8  r6 : ffffffea  r5 : 00000000  r4 : c79ee810
    [    0.943959] r3 : c805d000  r2 : 00000001  r1 : 00000008  r0 : c79ee810
    [    0.950791] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
    [    0.958258] Control: 10c5387d  Table: 80004019  DAC: 00000055
    [    0.964270] Process swapper (pid: 1, stack limit = 0xc783e210)
    [    0.970373] Stack: (0xc783fce8 to 0xc7840000)
    [    0.974937] fce0:                   c783fd5c c783fcf8 c035afb4 c0356238 00000000 00000001
    [    0.983500] fd00: c7a6a610 c78f4e10 00000000 00000001 c0702808 00000000 c783fd4c c783fd28
    [    0.992063] fd20: 00000008 c031c5bc 00000001 d3053b52 c78f4e00 c79ee810 c78f4e00 c0702808
    [    1.000626] fd40: 00000000 c78f4e10 c7948380 00000000 c783fdcc c783fd60 c0361834 c035ad34
    [    1.009190] fd60: 00000000 00000001 c783fd94 c7a6b370 c78f7f50 c3ed7d18 00000000 c7a6b410
    [    1.017753] fd80: c0702808 c0624830 c783fdbc c783fd98 c02221f8 c021e978 00000001 d3053b52
    [    1.026316] fda0: 00000000 c075dfa0 c78f4e10 c07354ec fffffdfb 00000000 c0702808 c0624830
    [    1.034879] fdc0: c783fdec c783fdd0 c031ac4c c0361550 c075dfa0 c78f4e10 00000000 c07354ec
    [    1.043441] fde0: c783fe14 c783fdf0 c031934c c031ac04 00000000 c78f4e10 c07354ec c78f4e44
    [    1.052004] fe00: c03193e4 00000000 c783fe34 c783fe18 c0319498 c031914c c03193e4 00000000
    [    1.060568] fe20: c07354ec c0702808 c783fe64 c783fe38 c0317348 c03193f0 c783fe70 c781eb8c
    [    1.069131] fe40: c7948530 d3053b52 c07354ec c79a7200 c0731e00 00000000 c783fe74 c783fe68
    [    1.077694] fe60: c0318d14 c03172cc c783fe9c c783fe78 c03188b0 c0318cfc c0521d8c c783fe88
    [    1.086257] fe80: c07354ec c061e0d0 c073b600 c073b600 c783feb4 c783fea0 c0319be8 c031871c
    [    1.094820] fea0: c0630cac c061e0d0 c783fec4 c783feb8 c031abac c0319b74 c783fed4 c783fec8
    [    1.103384] fec0: c061e0ec c031ab70 c783ff54 c783fed8 c010173c c061e0dc 00000002 0000004b
    [    1.111946] fee0: c783ff0c c783fef0 c783ff0c c783fe00 00000000 c0581698 c04bf888 0000004b
    [    1.120509] ff00: c783ff54 c783ff10 c013f854 c0600638 00000006 00000006 00000000 c05810bc
    [    1.129072] ff20: c05510d8 00000000 00000000 d3053b52 c0630cac 00000006 c073b600 c073b600
    [    1.137635] ff40: 0000004b c060062c c783ff94 c783ff58 c0600e28 c01016f0 00000006 00000006
    [    1.146198] ff60: 00000000 c060062c c783c000 00000000 c0494d04 00000000 00000000 00000000
    [    1.154761] ff80: 00000000 00000000 c783ffac c783ff98 c0494d14 c0600cf4 ffffffff 00000000
    [    1.163323] ffa0: 00000000 c783ffb0 c0107ce8 c0494d10 00000000 00000000 00000000 00000000
    [    1.171885] ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    [    1.180448] ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 c13bd557 ea3fc123
    [    1.189003] Backtrace:
    [    1.191574] [<c035622c>] (nand_read_byte) from [<c035afb4>] (nand_scan_ident+0x28c/0x159c)
    [    1.200235] [<c035ad28>] (nand_scan_ident) from [<c0361834>] (omap_nand_probe+0x2f0/0xc40)
    [    1.208891]  r10:00000000 r9:c7948380 r8:c78f4e10 r7:00000000 r6:c0702808 r5:c78f4e00
    [    1.217084]  r4:c79ee810
    [    1.219742] [<c0361544>] (omap_nand_probe) from [<c031ac4c>] (platform_drv_probe+0x54/0xb8)
    [    1.228489]  r10:c0624830 r9:c0702808 r8:00000000 r7:fffffdfb r6:c07354ec r5:c78f4e10
    [    1.236681]  r4:c075dfa0
    [    1.239346] [<c031abf8>] (platform_drv_probe) from [<c031934c>] (driver_probe_device+0x20c/0x2a4)
    [    1.248635]  r7:c07354ec r6:00000000 r5:c78f4e10 r4:c075dfa0
    [    1.254565] [<c0319140>] (driver_probe_device) from [<c0319498>] (__driver_attach+0xb4/0xb8)
    [    1.263402]  r8:00000000 r7:c03193e4 r6:c78f4e44 r5:c07354ec r4:c78f4e10 r3:00000000
    [    1.271514] [<c03193e4>] (__driver_attach) from [<c0317348>] (bus_for_each_dev+0x88/0xcc)
    [    1.280076]  r6:c0702808 r5:c07354ec r4:00000000 r3:c03193e4
    [    1.286005] [<c03172c0>] (bus_for_each_dev) from [<c0318d14>] (driver_attach+0x24/0x28)
    [    1.294384]  r7:00000000 r6:c0731e00 r5:c79a7200 r4:c07354ec
    [    1.300314] [<c0318cf0>] (driver_attach) from [<c03188b0>] (bus_add_driver+0x1a0/0x218)
    [    1.308699] [<c0318710>] (bus_add_driver) from [<c0319be8>] (driver_register+0x80/0x100)
    [    1.317170]  r7:c073b600 r6:c073b600 r5:c061e0d0 r4:c07354ec
    [    1.323099] [<c0319b68>] (driver_register) from [<c031abac>] (__platform_driver_register+0x48/0x50)
    [    1.332566]  r5:c061e0d0 r4:c0630cac
    [    1.336314] [<c031ab64>] (__platform_driver_register) from [<c061e0ec>] (omap_nand_driver_init+0x1c/0x20)
    [    1.346336] [<c061e0d0>] (omap_nand_driver_init) from [<c010173c>] (do_one_initcall+0x58/0x168)
    [    1.355449] [<c01016e4>] (do_one_initcall) from [<c0600e28>] (kernel_init_freeable+0x140/0x1e0)
    [    1.364559]  r9:c060062c r8:0000004b r7:c073b600 r6:c073b600 r5:00000006 r4:c0630cac
    [    1.372678] [<c0600ce8>] (kernel_init_freeable) from [<c0494d14>] (kernel_init+0x10/0x11c)
    [    1.381334]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c0494d04
    [    1.389527]  r4:00000000
    [    1.392187] [<c0494d04>] (kernel_init) from [<c0107ce8>] (ret_from_fork+0x14/0x2c)
    [    1.400109]  r4:00000000 r3:ffffffff
    [    1.403854] Code: e1a0c00d e92dd800 e24cb004 e5903240 (e5d30000)
    [    1.410243] ---[ end trace 5ad7f0d3e1b19da6 ]---

    We use an older version of u-boot that doesn't use DTS...

    I'll dump the timing registers value and post it here soon.

    Thanks for the help!

  • Guilherme,

    You have updated your kernel DTS file, but what about omap_hwmod_33xx_43xx_ipblock_data.c file?

    Please make GPMC registers dump at kernel stage, just before the kernel panic. Make the dump with the modified DTS file and with the default DTS file (with timings included) and provide the result.

    Regards,
    Pavel
  • Pavel,

    After some fiddling, we confirmed that by simply adding the "ti,no-reset-on-init" property to the GPMC node solves the issue of the module losing its configuration when switching from u-boot to kernel. However, this takes us to the kernel panic I mentioned above. We started inspecting the code, and it seems the issue is in this function:

    /**
     * gpmc_probe_generic_child - configures the gpmc for a child device
     * @pdev:	pointer to gpmc platform device
     * @child:	pointer to device-tree node for child device
     *
     * Allocates and configures a GPMC chip-select for a child device.
     * Returns 0 on success and appropriate negative error code on failure.
     */
    static int gpmc_probe_generic_child(struct platform_device *pdev,
    				struct device_node *child)
    {
    	struct gpmc_settings gpmc_s;
    	struct gpmc_timings gpmc_t;
    	struct resource res;
    	unsigned long base;
    	const char *name;
    	int ret, cs;
    	u32 val;
    	struct gpio_desc *waitpin_desc = NULL;
    	struct gpmc_device *gpmc = platform_get_drvdata(pdev);
    
    	if (of_property_read_u32(child, "reg", &cs) < 0) {
    		dev_err(&pdev->dev, "%s has no 'reg' property\n",
    			child->full_name);
    		return -ENODEV;
    	}
    
    	if (of_address_to_resource(child, 0, &res) < 0) {
    		dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
    			child->full_name);
    		return -ENODEV;
    	}
    
    	/*
    	 * Check if we have multiple instances of the same device
    	 * on a single chip select. If so, use the already initialized
    	 * timings.
    	 */
    	name = gpmc_cs_get_name(cs);
    	if (name && child->name && of_node_cmp(child->name, name) == 0)
    			goto no_timings;
    
    	ret = gpmc_cs_request(cs, resource_size(&res), &base);
    	if (ret < 0) {
    		dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
    		return ret;
    	}
    	gpmc_cs_set_name(cs, child->name);
    
    	gpmc_read_settings_dt(child, &gpmc_s);
    	gpmc_read_timings_dt(child, &gpmc_t);
    
    	/*
    	 * For some GPMC devices we still need to rely on the bootloader
    	 * timings because the devices can be connected via FPGA.
    	 * REVISIT: Add timing support from slls644g.pdf.
    	 */
    	if (!gpmc_t.cs_rd_off) {
    		WARN(1, "enable GPMC debug to configure .dts timings for CS%i\n",
    			cs);
    		gpmc_cs_show_timings(cs,
    				     "please add GPMC bootloader timings to .dts");
    		goto no_timings;
    	}
    
    	/* CS must be disabled while making changes to gpmc configuration */
    	gpmc_cs_disable_mem(cs);
    
    	/*
    	 * FIXME: gpmc_cs_request() will map the CS to an arbitary
    	 * location in the gpmc address space. When booting with
    	 * device-tree we want the NOR flash to be mapped to the
    	 * location specified in the device-tree blob. So remap the
    	 * CS to this location. Once DT migration is complete should
    	 * just make gpmc_cs_request() map a specific address.
    	 */
    	ret = gpmc_cs_remap(cs, res.start);
    	if (ret < 0) {
    		dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
    			cs, &res.start);
    		if (res.start < GPMC_MEM_START) {
    			dev_info(&pdev->dev,
    				 "GPMC CS %d start cannot be lesser than 0x%x\n",
    				 cs, GPMC_MEM_START);
    		} else if (res.end > GPMC_MEM_END) {
    			dev_info(&pdev->dev,
    				 "GPMC CS %d end cannot be greater than 0x%x\n",
    				 cs, GPMC_MEM_END);
    		}
    		goto err;
    	}
    
    	if (of_node_cmp(child->name, "nand") == 0) {
    		/* Warn about older DT blobs with no compatible property */
    		if (!of_property_read_bool(child, "compatible")) {
    			dev_warn(&pdev->dev,
    				 "Incompatible NAND node: missing compatible");
    			ret = -EINVAL;
    			goto err;
    		}
    	}
    
    	if (of_device_is_compatible(child, "ti,omap2-nand")) {
    		/* NAND specific setup */
    		val = 8;
    		of_property_read_u32(child, "nand-bus-width", &val);
    		switch (val) {
    		case 8:
    			gpmc_s.device_width = GPMC_DEVWIDTH_8BIT;
    			break;
    		case 16:
    			gpmc_s.device_width = GPMC_DEVWIDTH_16BIT;
    			break;
    		default:
    			dev_err(&pdev->dev, "%s: invalid 'nand-bus-width'\n",
    				child->name);
    			ret = -EINVAL;
    			goto err;
    		}
    
    		/* disable write protect */
    		gpmc_configure(GPMC_CONFIG_WP, 0);
    		gpmc_s.device_nand = true;
    	} else {
    		ret = of_property_read_u32(child, "bank-width",
    					   &gpmc_s.device_width);
    		if (ret < 0)
    			goto err;
    	}
    
    	/* Reserve wait pin if it is required and valid */
    	if (gpmc_s.wait_on_read || gpmc_s.wait_on_write) {
    		unsigned int wait_pin = gpmc_s.wait_pin;
    
    		waitpin_desc = gpiochip_request_own_desc(&gpmc->gpio_chip,
    							 wait_pin, "WAITPIN");
    		if (IS_ERR(waitpin_desc)) {
    			dev_err(&pdev->dev, "invalid wait-pin: %d\n", wait_pin);
    			ret = PTR_ERR(waitpin_desc);
    			goto err;
    		}
    	}
    
    	gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
    
    	ret = gpmc_cs_program_settings(cs, &gpmc_s);
    	if (ret < 0)
    		goto err_cs;
    
    	ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s);
    	if (ret) {
    		dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n",
    			child->name);
    		goto err_cs;
    	}
    
    	/* Clear limited address i.e. enable A26-A11 */
    	val = gpmc_read_reg(GPMC_CONFIG);
    	val &= ~GPMC_CONFIG_LIMITEDADDRESS;
    	gpmc_write_reg(GPMC_CONFIG, val);
    
    	/* Enable CS region */
    	gpmc_cs_enable_mem(cs);
    
    no_timings:
    
    	/* create platform device, NULL on error or when disabled */
    	if (!of_platform_device_create(child, NULL, &pdev->dev))
    		goto err_child_fail;
    
    	/* is child a common bus? */
    	if (of_match_node(of_default_bus_match_table, child))
    		/* create children and other common bus children */
    		if (of_platform_default_populate(child, NULL, &pdev->dev))
    			goto err_child_fail;
    
    	return 0;
    
    err_child_fail:
    
    	dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
    	ret = -ENODEV;
    
    err_cs:
    	gpiochip_free_own_desc(waitpin_desc);
    err:
    	gpmc_cs_free(cs);
    
    	return ret;
    }

    When we delete the timing properties from the .dts file, this function jumps to the no_timings label and starts probing the omap2 nand driver. However, when trying to read a byte from the memory, the kernel panics. After some more studying, it seems that by moving the 'if (!gpmc_t.cs_rd_off)'  to after the gpmc_cs_remap() function call, the processor boots just fine. By dumping the GPMC registers, this is what I get:

    At the very beginning  of gpmc_probe_generic_child (these are the values as they were set by the bootloader):

    cs0 GPMC_CS_CONFIG1: 0x00000800
    cs0 GPMC_CS_CONFIG2: 0x00030300
    cs0 GPMC_CS_CONFIG3: 0x00030300
    cs0 GPMC_CS_CONFIG4: 0x02000200
    cs0 GPMC_CS_CONFIG5: 0x00020303
    cs0 GPMC_CS_CONFIG6: 0x00000000
    cs0 GPMC_CS_CONFIG7: 0x00000848

    Just before starting omap2_nand_probe (with the modification allowing for a cs_request and cs_remap before jumping to the label):

    cs0 GPMC_CS_CONFIG1: 0x00000800
    cs0 GPMC_CS_CONFIG2: 0x00030300
    cs0 GPMC_CS_CONFIG3: 0x00030300
    cs0 GPMC_CS_CONFIG4: 0x02000200
    cs0 GPMC_CS_CONFIG5: 0x00020303
    cs0 GPMC_CS_CONFIG6: 0x00000000
    cs0 GPMC_CS_CONFIG7: 0x00000f48

    From these dumps, we can see that the only difference is in the GPMC_CONFIG7 register, specifically in the MASKADDRESS bits. The bootloader sets these pins for a 128MB MASKADDRESS, and the kernel sets them for a 16 MB MASKADDRESS. The memory we are using is a 256MB memory, and both of these values seem strange to me... Shouldn't these values make the GPMC controller not be able to work properly with a 256 MB memory?

    Also, I'd like to know how the kernel decided on this MASKADDRESS value... It seems to me that this is related to the reg property of the nand child node. However, I haven't been able to properly map this value to the value in the MASKADDRESS bits... Currently, my reg property is this: reg = <0 0 8>; Is this value correct? The gpmc-nand DT documentation states that the fields are the "range id (CS number), base offset and length of the NAND I/O space". The first two are clear to me, but I've never heard of the NAND I/O space term. What's the meaning of this field?


    Lastly, if really there is a need for a cs_request and cs_remap before probing the child node, I believe this would be a bug, right?

    Regards,

    Guilherme

  • Hello,

    I mode two modifications that solved the problem:

    1. After some research, I came across some posts here in the E2E forums saying that, for NAND GPMC, the value of MASKADDRESS doesn't matter whe interfacing with NAND memories, so I decided to change my U-Boot code to use the  16 MB MASKADDRESS value, just like the kernel.
    2. I tweaked the omap-gpmc.c code to only do a gpmc_cs_request if the timing and gpmc settings properties are present in the .dts file. I did this to avoid inadvertely changing the GPMC_CONFIG7 register.

    Together with these modifications, I also inserted the "ti,no-reset-on-init" property in the gpmc node, as well as deleted the gpmc settings and timings properties in the .dts file, as Pavel suggested.

    Regards,

    Guilherme