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/AM3354: Device tree issue

Part Number: AM3354
Other Parts Discussed in Thread: TMS320C6746,

Tool/software: Linux

Hi guys,

I'm currently working on a custom board with an ARM processor (AM3354) and a DSP (TMS320C6746) on it. The GPMC of AM3354 is connected to the UHPI interface of DSP (Chip select is 2). Also AM3354's GPIO3[20] pin is connected to the DSP's RESETn pin. My current goal is to reset the DSP automatically every time the board is powered on. This reset is a must in order to get ready for UHPI-boot.

Linux 3.8.13 is installed on ARM. I wrote the driver functions for UHPI, and things all worked just fine. (Device read, write and ioctl functions all worked well) until this morning as I modified the .dts file to set PINMUX for GPIO3[20]. Basically, I added the following code under the "am33xx_pinmux: pinmux@44e10800" node:

          pinctrl-0 = <... &dsp_ctrl_pins>;

......

dsp_ctrl_pins: dsp_ctrl_pins {
        pinctrl-single,pins = <0x1A8 0x17>;  /* Offset is 0x1A8, mode 7, output, internal pull-up */
};

Nothing else is done. The dtb file was generated and then I rebooted the board, but the UHPI device was gone (not listed under /dev folder). I traced back to my driver functions and Linux source code and found that gpmc_cs_request() failed. Seemed like the CS has been claimed by something else, and I found gpmc_probe() was not called to clear the gpmc_cs_map. This is really awkward because I did nothing else like modifiying driver source code or configuration files or Makefile, absolutely nothing except the device tree file.

I appreciate help from anybody who encountered similar problems or giving me suggestions/clues on how to configure the GPMC back to its proper manner.

NOTE: last Saturday I tried to reset the DSP by hand (i.e. using echo command under /sys/class/gpio and things worked fine), but I'd definitely like to reset the DSP automatically each time the board is powered on.

Thanks,

Charlie

  • The software team have been notified. Please note that Linux 3.8.13 is not a TI release and therefore is not supported by TI. Response will be limited to possible syntax errors in your configuration.
  • Thanks Biser.

    I confirmed that gpmc_probe() was not called at startup. Consequently, all CS spaces are in busy state, which is the reason why gpmc_cs_request() failed.

    I traced the following call chain in my version of Linux kernel source (version 3.8.13. I believe Beaglebone Black sourced this version as well): 

    1) gpmc_init() defined in /arch/arm/mach-omap2/gpmc.c

    2) platform_driver_register(drv) defined in /drivers/base/platform.c

    3) driver_register(drv) defined in /drivers/base/driver.c

    4) bus_add_driver(drv) defined in /drivers/base/bus.c

    5) driver_attach(drv) defined in /drivers/base/dd.c

    6) bus_for_each_dev(drv->bus, NULL, drv, __driver_attach) defined in /drivers/base/bus.c

    7) __driver_attach(dev, drv) defined in /drivers/base/dd.c

    8) driver_probe_device(drv, dev) defined in /drivers/base/dd.c

    9) really_probe(dev, drv) defined in /drivers/base/dd.c

    10) drv->probe(dev) which is the probe member function of the driver. I believe the probe function is assigned to the driver in platform_driver_register() in step 2), which is exactly

    11) platform_drv_probe(dev) defined in /drivers/platform.c

    12) platform_drv->probe(dev) which is the probe member function of the platform driver. I expected this probe() function should exactly be gpmc_probe(), while in fact it isn't. So this is the problem.

    Note:

    I guess two drivers are in concern throughout this call chain. One is the gpmc_driver (of struct platform_driver) defined in /arch/armgpmc.c, which I call platform_drv, while the other is the driver member of gpmc_driver, which I simply called drv. The dev are those attached to the GPMC bus. They are generated by bus_for_each_dev().