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/DM388: How to enable the SPI interface from the device tree of kernel 4.4?

Part Number: DM388
Other Parts Discussed in Thread: SYSCONFIG

Tool/software: Linux

Hi,

I need to use the SPI interface to control the motor.

I try any possible method, but it still is unrecognized.

Can you give me a example to enable it ?

--------------------------------------------------------------------------

This is from ti81xx.dtsi

mcspi1: mcspi@30000 {
                compatible = "ti,omap4-mcspi";
                #address-cells = <1>;
                #size-cells = <0>;
                ti,hwmods = "mcspi1";
                ti,spi-num-cs = <4>;
                reg = <0x30000 0x1000>;
                interrupts = <65>;
                dmas = <&edma 16 &edma 17
                    &edma 18 &edma 19
                    &edma 20 &edma 21
                    &edma 22 &edma 23>;
                dma-names = "tx0", "rx0", "tx1", "rx1",
                    "tx2", "rx2", "tx3", "rx3";
                status = "disabled";
            };

            mcspi2: mcspi@1A0000 {
                compatible = "ti,omap4-mcspi";
                #address-cells = <1>;
                #size-cells = <0>;
                ti,hwmods = "mcspi2";
                ti,spi-num-cs = <2>;
                reg = <0x1A0000 0x1000>;
                interrupts = <125>;
                dmas = <&edma 42 &edma 43
                    &edma 44 &edma 45>;
                dma-names = "tx0", "rx0",
                    "tx1", "rx1";
                status = "disabled";    
            };

  • Hi Huang,

    You should change the status from disabled to enabled in your custom DTS file. For example see DM38x TI board DTS file dm38x-csk.dts, see for example how uart1 is enabled. You should do the same for mcspi1/2

    &uart1 {
    status = "okay";
    };

    Regards,
    Pavel
  • Hi Pavel,

    I have rewritten my spi device driver. 

    Now I can see the correct SPI interface .

    However, if I want to send 1 byte from  SPI controller of DM388 to my slave device, it always shows the error message " spidev spi1.0: TXS timed out".  

    (It runs the PIO mode and it's not successful for the DMA mode.)

    I trace the new driver(spi-omap2-mcspi.c)  of the spi controller. I don't see any function about enable/disable the clock(Ex. ick and fck from ipnc_rdk 3.8).

    Do you know how to enable  the SPI clock in the device tree ?

    Thanks.

    S.K.

  • S.K.

    When boot up (in user space), check the below registers with devmem2 tool:

    CM_ALWON_SPI_CLKCTRL - if clock is enabled, value in [1:0] MODULEMODE should be 0x2, [17:16] IDLEST should be 0x0
    MCSPI_SYSCONFIG - if you are able to read/write this register successful (or any McSPI register), than clock is enabled

    Regards,
    Pavel
  • Hi Pavel,

    1. CM_ALWON_SPI_CLKCTRL

    root@ti81xx:/dev# devmem2 0x48181590
    /dev/mem opened.
    Memory mapped at address 0xb6f86000.
    Read at address 0x48181590 (0xb6f86590): 0x00030000

    -------------------------------------------------------------------------------------

    2. MCSPI_SYSCONFIG

    root@ti81xx:/dev# devmem2 0x48030110
    /dev/mem opened.[14770.449131] Unhandled fault: external abort on non-linefetch (0x1018) at 0xb6f6f110
    [14770.458045] pgd = c26d8000
    [14770.460763] [b6f6f110] *pgd=81966831, *pte=48030303, *ppte=48030a33

    Memory mapped at address 0xb6f6f000.
    Bus error (core dumped)

    -------------------------------------------------------------------------------------

    3. CM_ALWON_I2C_0_CLKCTRL

    root@ti81xx:/dev# devmem2 0x48181564
    /dev/mem opened.
    Memory mapped at address 0xb6f72000.
    Read at address 0x48181564 (0xb6f72564): 0x00000002

    -------------------------------------------------------------------------------------

    4. For the TRM document, SPI and I2C use the same clock source.

        I can find out the clock file "ti81xx-clocks.dtsi" for the device tree.

        I2C and SPI use the same setting for the clock source.

       I2C clock is enabled, but SPI clock is not enabled.

       Do you have any idea?

     

    Thanks.

    S.K.

  • S.K.

    Do you update dm38x-csk.dts file to add SPI support in it? By default this file has support for I2C, but nothing for SPI. Please send me your DTS file (dm38x-csk.dts or your own custom DTS file) for review.

    SPI and I2C clocks are handled in ti81xx-clocks.dtsi file, you just need to enable SPI in your main DTS file.

    /* I2C02 Functional Clock(final) */
    i2c02_ck: i2c02_ck {
    #clock-cells = <0>;
    compatible = "ti,gate-clock";
    clocks = <&sysclk10_ck>;
    ti,bit-shift = <1>;
    reg = <0x1564>; /* CM_ALWON_I2C_0_CLKCTRL */

    /* I2C1 Functional Clock(final) */
    i2c1_fck: i2c1_fck {
    #clock-cells = <0>;
    compatible = "fixed-factor-clock";
    clocks = <&i2c02_ck>;
    clock-mult = <1>;
    clock-div = <1>;
    };

    /* SPI0 Functional Clock(final) */
    mcspi1_fck: mcspi1_fck {
    #clock-cells = <0>;
    compatible = "ti,gate-clock";
    clocks = <&sysclk10_ck>;
    ti,bit-shift = <1>;
    reg = <0x1590>; /* CM_ALWON_SPI_CLKCTRL */
    };

    Regards,
    Pavel
  • Hi ,

    I2C and SPI use the same setting for the clock source.

       I2C clock is enabled, but SPI clock is not enabled.

    Interface clock for SPI and I2C or same . But , functional clock for SPI is "mcspi1_fck".
    You can go through TRM for difference in functional clock and interface clock.

    Thanks & Regards,

    Vishwanath Patil

  • Hi Pavel,

    [dm38x-csk.dts]

    The setting for SPI_0 and my motor driver.

    spi0_pins: pinmux_spi0_pins{
            pinctrl-single,pins =<
                0x14C (PULL_UP | MUX_MODE0)
                0x148 (PULL_UP | MUX_MODE0)
                0x144 (PULL_UP | MUX_MODE0)
                0x140 (PULL_UP | MUX_MODE0)
            >;
        };

    &mcspi1 {
        pinctrl-names = "default";
        pinctrl-0 = <&spi0_pins>;
        
        status = "okay";

        motor: motor@0 {
            compatible = "miis,motor";
            reg = <0>;
            spi-max-frequency = <5000000>;
        };
    };

    dm38x-csk.dts.zip

  • S.K.

    Can you try these 3 methods:

    1. In ti81xx.dtsi file add this line of code:

    aliases {
    serial0 = &uart1;
    ethernet0 = &cpsw_emac0;
    i2c0 = &i2c1;
    i2c1 = &i2c2;
    usb0 = &usb0;
    phy0 = &usb0_phy;
    + mcspi0=&mcspi1;

    };

    2. In ti81xx.dtsi file update this line of code:

    mcspi1: mcspi@30000 {
    compatible = "ti,omap4-mcspi";
    #address-cells = <1>;
    #size-cells = <0>;
    ti,hwmods = "mcspi1";
    ti,spi-num-cs = <4>;
    reg = <0x30000 0x1000>;
    interrupts = <65>;
    dmas = <&edma 16 &edma 17
    &edma 18 &edma 19
    &edma 20 &edma 21
    &edma 22 &edma 23>;
    dma-names = "tx0", "rx0", "tx1", "rx1",
    "tx2", "rx2", "tx3", "rx3";
    -status = "disabled";
    +status = "okay";
    };

    3. Try both 1 and 2 at the same time

    Regards,
    Pavel

  • Hi Pavel,

    I have tried them. The result is the same.

    The SPI function clock is still not enabled.

    I think the issue is at  ti,hwmods = "mcspi1",  but i don't have much time to trace them.

    ( ti/ipnc_rdk-3.9.0/Source/ti_tools/ipnc_psp_arago/kernel/arch/arm/mach-omap2/omap_hwmod_81xx_data.c)

    I try to directly access the register CM_ALWON_SPI_CLKCTRL to enable  in the kernel mode, but they are not working.

    //method1

    //omap_writel(0x2,0x48181590);

    //method2

    {
    unsigned long *reg;
    reg = ioremap_nocache(0x48181590,4);
    *reg = 0x02;
    iounmap(reg);

    }

    Do you know how to do that?

  • S.K. Huang said:

    The SPI function clock is still not enabled.

    I think the issue is at  ti,hwmods = "mcspi1",  but i don't have much time to trace them.

    I am not sure why this do not work. From the link below you can see that this is the official way to enable a module (i.e. McSPI1):

    You can check if "__of_device_is_available()" function is called for McSPI1:

    kernel/drivers/of/base.c

    /**
     *  __of_device_is_available - check if a device is available for use
     *
     *  @device: Node to check for availability, with locks already held
     *
     *  Returns true if the status property is absent or set to "okay" or "ok",
     *  false otherwise
     */

    S.K. Huang said:

    I try to directly access the register CM_ALWON_SPI_CLKCTRL to enable  in the kernel mode, but they are not working.

    //method1

    //omap_writel(0x2,0x48181590);

    //method2

    {
    unsigned long *reg;
    reg = ioremap_nocache(0x48181590,4);
    *reg = 0x02;
    iounmap(reg);

    }

    Do you know how to do that?

    Refer to the below e2e posts:

    For writing in register you can use __raw_writel(value,addr);

  • Hi 

    I can read/write the register with ioremap method.

    I try to enable SPI function clock to avoid this issue. (CM_ALWON_SPI_CLKCTRL)

    Step 1: I read the register and get the value: 0x00030000. (correct)

    Step 2: I write the register with the value 0x2.

                I read it and get the value: 0x00030002.(error)

    17-16 IDLEST R 0h Module idle status.
    0x0(read) = Module is fully functional, including OCP
    0x1(read) = Module is performing transition: wakeup, or sleep, or
    sleep abortion
    0x2(read) = Module is in Idle mode (only OCP part). It is functional if
    using separate functional clock
    0x3(read) = Module is disabled and cannot be accessed

    Step 3:

    I go to the shell layer and read it. The value is  0x00030000.

    Do I need to setup others register in the kernel mode?

    Do you know how to setup the interface clock? (Do it call ick?)

    Thanks.

  • S.K. Huang said:
    I read it and get the value: 0x00030002.(error)

    You need to wait for a while, as the SPI module is making transition from disable to enable.

    You can also try to enable mcspi1_fck through the clock framework:

    S.K. Huang said:
    Do you know how to setup the interface clock? (Do it call ick?)

    It should be enabled by default. McSPI is attached to L4 Slow interconnect. Check the below registers values to verify sysclk6/mcspi_ick is ON:

    CM_ALWON_SYSCLK6_CLKSTCTRL

    CM_ALWON_L4LS_CLKCTRL

    Regards,
    Pavel

  • S.K. Huang said:
    Do I need to setup others register in the kernel mode?

    Check USB DPLL (USBPLL_x registers), it should be configured and locked. USB DPLL provide sysclk10, which provide mcspi1_fck.

  • Hi Huang,

    I would like to add few more details to you,

    Interface clock (ick) is already enabled for SPI1 .

    at console try this first,

    1) Read SPI functional clk control register.

    $devmem2 0x48181590

    2) Without enabling clock try reading spi control register

    $devmem2 0x48030000

    expected is crash page fault since functional clock is not enabled.

    3) Enable the clock now,

    $devmem2 0x48181590 w 0x00030002

    4) Now try reading the spi control registers

    $devmem2 0x48030000

    you should be able to read the register.

    Now coming to device node,

    &mcspi1 {
        pinctrl-names = "default";
        pinctrl-0 = <&spi0_pins>;
        
        status = "okay";

        motor: motor@0 {
            compatible = "miis,motor";
            reg = <0>;

            clocks = <&mcspi1_fck>;

            clock-names = "fck";
            spi-max-frequency = <5000000>;
        };
    };


    In your driver,

    clk = devm_clk_get(&pdev->dev, "fck");

    clk_prepare_enable(clk); or //clk_prepare(clk); and clk_enable(clk);

    Thanks & Regards,

    Vishwanath Patil