zoukankan      html  css  js  c++  java
  • u-boot 设置qspi speed

    sf probe

    
    
    

      do_spi_flash (cmd/sf.c)

    
    
    

        do_spi_flash_probe (cmd/sf.c)

          /* Remove the old device, otherwise probe will just be a nop */

          spi_find_bus_and_cs (spi-uclass.c)

    
    
    

            uclass_find_device_by_seq   (drivers/core/uclasee.c)//寻找spi总线设备(SPI控制器) 没有probe

            //ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, false, &bus);

            spi_find_chip_select  (drivers/spi/spi-uclass.c)//在SPI总线设备下找到FLASH设备

    
    
    

          spi_flash_probe_bus_cs(driver/mtd/spi/sf-uclass.c)

    
    
    

            spi_get_bus_and_cs  (drivers/spi/spi-uclass.c)

            /*ret = spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode,
                      "spi_flash_std", str, &bus, &slave); 这里直接指定了driver name*/
    
    
    

              uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus); //UCLASS_SPI cadence_spi_probe

     //driver/core/device.c 的device_probe

    //ret = drv->ofdata_to_platdata(dev);

    //ret = drv->probe(dev); 会读到设备树里的spi-max-frequency=50MHz 

    //plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency",500000);

     

              spi_find_chip_select(bus, cs, &dev);

              if (ret == -ENODEV && drv_name) 

                ret = device_bind_driver(bus, drv_name, dev_name, &dev);

    
    
    

              device_probe (qspi flash颗粒 激活)

    plat = dev_get_parent_platdata(dev);
    if (!speed) {
    speed = plat->max_hz; //speed=50MHz
    mode = plat->mode;
    }

    ret = spi_set_speed_mode(bus, speed, mode); 传入50M

    if (ops->set_speed)
    ret = ops->set_speed(bus, speed);

    调用cadence_spi_set_speed 传入50MHz

    static int cadence_spi_set_speed(struct udevice *bus, uint hz)
    {
        struct cadence_spi_platdata *plat = bus->platdata;
        struct cadence_spi_priv *priv = dev_get_priv(bus);
        int err;
    
        if (hz > plat->max_hz)
            hz = plat->max_hz;
    
        /* Disable QSPI */
        cadence_qspi_apb_controller_disable(priv->regbase);
    
        /*
         * Calibration required for different current SCLK speed, requested
         * SCLK speed or chip select
         */
        if (priv->previous_hz != hz ||
            priv->qspi_calibrated_hz != hz ||
            priv->qspi_calibrated_cs != spi_chip_select(bus)) {
            err = spi_calibration(bus, hz);//50MHz
            if (err)
                return err;
    
            /* prevent calibration run when same as previous request */
            priv->previous_hz = hz;
        }
    /* Calibration sequence to determine the read data capture delay register */
    static int spi_calibration(struct udevice *bus, uint hz)
    {
        struct cadence_spi_priv *priv = dev_get_priv(bus);
        void *base = priv->regbase;
        u8 opcode_rdid = 0x9F;
        unsigned int idcode = 0, temp = 0;
        int err = 0, i, range_lo = -1, range_hi = -1;
    
        /* start with slowest clock (1 MHz) */
        cadence_spi_write_speed(bus, 1000000);
    
        /* configure the read data capture delay register to 0 */
        cadence_qspi_apb_readdata_capture(base, 1, 0);
    
        /* Enable QSPI */
        cadence_qspi_apb_controller_enable(base);
    
        /* read the ID which will be our golden value */
        err = cadence_qspi_apb_command_read(base, 1, &opcode_rdid,
            3, (u8 *)&idcode);
        if (err) {
            puts("SF: Calibration failed (read)
    ");
            return err;
        }
    
        /* use back the intended clock and find low range */
        cadence_spi_write_speed(bus, hz);//50MHz
        for (i = 0; i < CQSPI_READ_CAPTURE_MAX_DELAY; i++) {
            /* Disable QSPI */
            cadence_qspi_apb_controller_disable(base);
    
            /* reconfigure the read data capture delay register */
            cadence_qspi_apb_readdata_capture(base, 1, i);
    
            /* Enable back QSPI */
            cadence_qspi_apb_controller_enable(base);
    
            /* issue a RDID to get the ID value */
            err = cadence_qspi_apb_command_read(base, 1, &opcode_rdid,
                3, (u8 *)&temp);
            if (err) {
                puts("SF: Calibration failed (read)
    ");
                return err;
            }
    
            /* search for range lo */
            if (range_lo == -1 && temp == idcode) {
                range_lo = i;
                continue;
            }
    
            /* search for range hi */
            if (range_lo != -1 && temp != idcode) {
                range_hi = i - 1;
                break;
            }
            range_hi = i;
        }
    
        if (range_lo == -1) {
            puts("SF: Calibration failed (low range)
    ");
            return err;
        }
    
        /* Disable QSPI for subsequent initialization */
        cadence_qspi_apb_controller_disable(base);
    
        /* configure the final value for read data capture delay register */
        cadence_qspi_apb_readdata_capture(base, 1, (range_hi + range_lo) / 2);
        debug("SF: Read data capture delay calibrated to %i (%i - %i)
    ",
              (range_hi + range_lo) / 2, range_lo, range_hi);
    
        /* just to ensure we do once only when speed or chip select change */
        priv->qspi_calibrated_hz = hz;
        priv->qspi_calibrated_cs = spi_chip_select(bus);
    
        return 0;
    }
    static int cadence_spi_write_speed(struct udevice *bus, uint hz)
    {
        struct cadence_spi_platdata *plat = bus->platdata;
        struct cadence_spi_priv *priv = dev_get_priv(bus);
    
        cadence_qspi_apb_config_baudrate_div(priv->regbase,
                             CONFIG_CQSPI_REF_CLK, hz);//算分频系数
    
        /* Reconfigure delay timing if speed is changed. */
        cadence_qspi_apb_delay(priv->regbase, CONFIG_CQSPI_REF_CLK, hz,
                       plat->tshsl_ns, plat->tsd2d_ns,
                       plat->tchsh_ns, plat->tslch_ns);
    
        return 0;
    }
  • 相关阅读:
    赠与今年的大学毕业生(胡适先生30年代的文章,仍不过时)
    统一管理磁盘上的开源代码
    生成sqlite导入库的做法
    提高二维矢量绘图效率之一般做法
    boost库命名规则的优点
    如何把腾讯微博挂到CSDN博客上
    fatal error C1902 Program database manager mismatch; please check your installation问题的解决
    智能指针变量做函数参数的一个值得注意的地方
    PC会消亡吗?
    软件制造问题的微软答案
  • 原文地址:https://www.cnblogs.com/idyllcheung/p/14063639.html
Copyright © 2011-2022 走看看