I2C clock设置的过程

一般在drivers/acpi/acpi_apd.c 中注册i2c的device。这次我们重点关注clock的情况
static const struct acpi_device_id acpi_apd_device_ids[] = {
    /* Generic apd devices */
、
#ifdef CONFIG_ARM64
    { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
#endif
    { }
};
这里以APMC0D0F为例的话
static const struct apd_device_desc xgene_i2c_desc = {
    .setup = acpi_apd_setup,
    .fixed_clk_rate = 100000000,
};
可以看到clock rate这里设置的100M
这样在acpi_apd_create_device 中会调用下面的code来执行xgene_i2c_desc 中定义的setup函数
    if (dev_desc->setup) {
        ret = dev_desc->setup(pdata);
        if (ret)
            goto err_out;
    }

static int acpi_apd_setup(struct apd_private_data *pdata)
{
    const struct apd_device_desc *dev_desc = pdata->dev_desc;
    struct clk *clk = ERR_PTR(-ENODEV);
//这里的fixed_clk_rate 显然不为null,因此调用
    if (dev_desc->fixed_clk_rate) {
        clk = clk_register_fixed_rate(&pdata->adev->dev,
                    dev_name(&pdata->adev->dev),
                    NULL, 0, dev_desc->fixed_clk_rate);
        clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev));
        pdata->clk = clk;
    }

    return 0;
}

这样当我们在i2c的driver probe的函数dw_i2c_plat_probe
static int dw_i2c_plat_probe(struct platform_device *pdev)
{

    struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
    struct dw_i2c_dev *dev;
    struct i2c_adapter *adap;
    struct resource *mem;
    int irq, r;
    u32 acpi_speed, ht = 0;

    irq = platform_get_irq(pdev, 0);
    if (irq < 0)
        return irq;

    dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;

    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    dev->base = devm_ioremap_resource(&pdev->dev, mem);
    if (IS_ERR(dev->base))
        return PTR_ERR(dev->base);

    dev->dev = &pdev->dev;
    dev->irq = irq;
    platform_set_drvdata(pdev, dev);

    dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
    if (IS_ERR(dev->rst)) {
        if (PTR_ERR(dev->rst) == -EPROBE_DEFER)
            return -EPROBE_DEFER;
    } else {
        reset_control_deassert(dev->rst);
    }
//得到dw_i2c_platform_data 显然不为null。如果在i2c的device中没有定义clock的话,会走else的case从bios中设定得到.
    if (pdata) {
        dev->clk_freq = pdata->i2c_scl_freq;
    } else {
        device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
                     &ht);
        device_property_read_u32(&pdev->dev, "i2c-sda-falling-time-ns",
                     &dev->sda_falling_time);
        device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
                     &dev->scl_falling_time);
        device_property_read_u32(&pdev->dev, "clock-frequency",
                     &dev->clk_freq);
    }
//再从另外一个apcpi node拿到一个speed
    acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
    /*
     * Find bus speed from the "clock-frequency" device property, ACPI
     * or by using fast mode if neither is set.
     */
//比较acpi_speed 和之前dev->clk_freq。我们这种情况下acpi_speed 为0,因此走else if的case得到dev->clk_freq, acpi_speed的最大值,由于acpi_speed 为0因此最大值也就是dev->clk_freq
    if (acpi_speed && dev->clk_freq)
        dev->clk_freq = min(dev->clk_freq, acpi_speed);
    else if (acpi_speed || dev->clk_freq)
        dev->clk_freq = max(dev->clk_freq, acpi_speed);
    else
        dev->clk_freq = 400000;

    if (has_acpi_companion(&pdev->dev))
        dw_i2c_acpi_configure(pdev);

    /*
     * Only standard mode at 100kHz, fast mode at 400kHz,
     * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
     */

    if (dev->clk_freq != 100000 && dev->clk_freq != 400000
        && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
        dev_err(&pdev->dev,
            "Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
        r = -EINVAL;
        goto exit_reset;
    }


}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值