一般在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;
}
}
I2C clock设置的过程
最新推荐文章于 2024-04-14 09:44:28 发布