MediaTek-Labs / mt3620_m4_software

mt3620_m4_driver
Other
32 stars 29 forks source link

[Question] How to change SPI CS pin react timing (M4) #29

Closed Visit-Learn closed 4 years ago

Visit-Learn commented 4 years ago

Hi,

Currently, we implemented SPI feature and we found that the CS pin is automatically trigger before SPI data sending. That's very great and useful feature, but SPI sending is too quick after CS pin pull low, let make related chip cannot work properly. We use other pin to implement CS pin feature with 1 us delay to sending SPI data after CS pin pull low and related chip works properly, so any API could change this? And following picture is from logic analyzer with SDK automatically CS pull low, we could found that after CS pin pull low, the SPI data is sending with about 40 ns image image image

By the way, we use FreeRTOS version, thanks. Thank you so much.

kevinwh-chou commented 4 years ago

Hi,

Currently there's no API function for SPI to change the interval between CS and CLK, however, there's a SPI register "SPI_REG_CS_POLAR" existed for that purpose, bit [15:12] as "cmd_delay_sel" to set additional delays between CS and CLK. Based on that register, you would be able to implement such API function like the following example in hdl_spim.c, and call it say within mtk_mhal_spim_prepare_hw() for the moment.

void mtk_hdl_set_cs_clk_delay(void __iomem *base, u32 delay)
{
    int reg_val;
    /* cmd_delay_sel is 4 bits, at SPI_REG_CS_POLAR bit[15:12], each step (max 15) adds around 12.5ns delay */
    reg_val = osai_readl(SPI_REG_CS_POLAR(base));
    reg_val |= (delay << 12);
    osai_writel(reg_val, SPI_REG_CS_POLAR(base));
}

We will also have an internal discussion about adding such API function support in the next release.

Visit-Learn commented 4 years ago

Hi,

Currently there's no API function for SPI to change the interval between CS and CLK, however, there's a SPI register "SPI_REG_CS_POLAR" existed for that purpose, bit [15:12] as "cmd_delay_sel" to set additional delays between CS and CLK. Based on that register, you would be able to implement such API function like the following example in hdl_spim.c, and call it say within mtk_mhal_spim_prepare_hw() for the moment.

void mtk_hdl_set_cs_clk_delay(void __iomem *base, u32 delay)
{
  int reg_val;
  /* cmd_delay_sel is 4 bits, at SPI_REG_CS_POLAR bit[15:12], each step (max 15) adds around 12.5ns delay */
  reg_val = osai_readl(SPI_REG_CS_POLAR(base));
  reg_val |= (delay << 12);
  osai_writel(reg_val, SPI_REG_CS_POLAR(base));
}

We will also have an internal discussion about adding such API function support in the next release.

Hi,

We try your suggestion as following, but there still cannot make our SPI device work properly, we will check mtk_hdl_set_cs_clk_delay this function from logic analyzer for summarize it. If you have other good method, please let us know, thank you so much.

void mtk_hdl_set_cs_clk_delay(void __iomem *base, u32 delay)
{
    int reg_val;
    /* cmd_delay_sel is 4 bits, at SPI_REG_CS_POLAR bit[15:12], each step (max 15) adds around 12.5ns delay */
    reg_val = osai_readl(SPI_REG_CS_POLAR(base));
    reg_val |= (delay << 12);
    osai_writel(reg_val, SPI_REG_CS_POLAR(base));
}

int mtk_mhal_spim_prepare_hw(struct mtk_spi_controller *ctlr,
                  struct mtk_spi_config *config)
{
    ...
    mtk_hdl_spim_sw_reset(ctlr->cg_base);
    mtk_hdl_set_cs_clk_delay(ctlr->cg_base, 15);
    mtk_hdl_spim_prepare_hw(ctlr->base,
          config->cpol, config->cpha,
          config->tx_mlsb, config->rx_mlsb,
          config->slave_sel);

    return 0;
}
Visit-Learn commented 4 years ago

Hi,

By the way, could we modify CS to GPIO? Actually, we try to do it, but the compiler cannot accept it, thank you so much.

kevinwh-chou commented 4 years ago

Hi,

Please pass in ctlr->base instead of ctlr-> cg_base to the function mtk_hdl_set_cs_clk_delay() as the register SPI_REG_CS_POLAR's address is 0x380X0338 (X=7,8,9,a,b for ISU0~4).

mtk_hdl_set_cs_clk_delay(ctlr->base, 15);

could we modify CS to GPIO? Actually, we try to do it, but the compiler cannot accept it, thank you so much.

For the 2nd question, by Microsoft's configuration rule, if certain ISU group is already assigned to SPI, then its member pins can only be used as SPI functions. In other word, SPI pins and GPIO pins won't coexist in one group.

Visit-Learn commented 4 years ago

Hi,

Thanks your comment, we use LA to know that mtk_hdl_set_cs_clk_delay is work but still cannot make SPI device work properly. Any possible to make CS interval larger than 1 us? Thank you so much.

Visit-Learn commented 4 years ago

Hi,

We check SPI device data sheet again, as following, found that TCSS minimum interval is 50 ns, so we think that delay function could meet requirement, and also found that TCSH minimum interval is 210 ns image

And we use delay function for below configuration, and TCSS is 220 ns then TCSH is 20 ns, so could we know how to modify TCSH? Thank you so much. mtk_hdl_set_cs_clk_delay(ctlr->base, 15); image

kevinwh-chou commented 4 years ago

HI,

Regarding your questions:

Any possible to make CS interval larger than 1 us?

The hardware supports max 15 steps as the delay between CS and CLK by configuring the register "SPI_REG_CS_POLAR", for longer delay, it needs to be implemented by replacing the CS pin with a available GPIO pin (from a different group) like you've done.

Could we know how to modify TCSH?

Yes, also in the same register SPI_REG_CS_POLAR, bit[19:16] controls the delay between the last CLK and CS, like bit[15:12] controls the delay between CS and the first CLK.

So you can do like the following in the function mtk_hdl_set_cs_clk_delay().

// you can add another delay parameter to be passed in to the function if you want to control the delay separately. 
reg_val |= ((delay << 12) | (delay << 16)); 
Visit-Learn commented 4 years ago

Hi,

Thank you for your elaboration, now we know how to implement our design, thanks.