在driver/reset/hisilicon/Makefile
obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
可见要使用reset controller 必须定义CONFIG_COMMON_RESET_HI6220
在Hi6220_resetc中
static struct platform_driver hi6220_reset_driver = {
.probe = hi6220_reset_probe,
.driver = {
.name = "reset-hi6220",
.of_match_table = hi6220_reset_match,
},
};
static int __init hi6220_reset_init(void)
{
return platform_driver_register(&hi6220_reset_driver);
}
postcore_initcall(hi6220_reset_init);
定义了一个platform_driver,当其of_match_table 和dts中匹配时就调用hi6220_reset_probe
static const struct reset_control_ops hi6220_peripheral_reset_ops = {
.assert = hi6220_peripheral_assert,
.deassert = hi6220_peripheral_deassert,
};
static int hi6220_reset_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
enum hi6220_reset_ctrl_type type;
struct hi6220_reset_data *data;
struct regmap *regmap;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
type = (enum hi6220_reset_ctrl_type)of_device_get_match_data(dev);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap)) {
dev_err(dev, "failed to get reset controller regmap\n");
return PTR_ERR(regmap);
}
data->regmap = regmap;
data->rc_dev.of_node = np;
if (type == MEDIA) {
data->rc_dev.ops = &hi6220_media_reset_ops;
data->rc_dev.nr_resets = MEDIA_MAX_INDEX;
} else {
data->rc_dev.ops = &hi6220_peripheral_reset_ops;
data->rc_dev.nr_resets = PERIPH_MAX_INDEX;
}
return reset_controller_register(&data->rc_dev);
}
在hi6220_reset_probe 中通过reset_controller_register注册了一个reset controller,reset controller最重要的就是hi6220_peripheral_reset_ops的assert 和 deassert 函数。
这样在dw_mci_parse_dt函数中就会通过下面的code 找到这个reset controller
/* find reset controller when exist */
pdata->rstc = devm_reset_control_get_optional(dev, "reset");
if (IS_ERR(pdata->rstc)) {
if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
}
最终在dw_mci_probe中通过下面的code来调用reset controller,来reset mmc host
if (!IS_ERR(host->pdata->rstc)) {
reset_control_assert(host->pdata->rstc);
usleep_range(10, 50);
reset_control_deassert(host->pdata->rstc);
}
这里以reset_control_assert 为例,很容易看出最终调用ops->assert,而这样的ops就是我们在hi6220_reset.c 中定义的hi6220_peripheral_reset_ops
int reset_control_assert(struct reset_control *rstc)
{
if (WARN_ON(IS_ERR_OR_NULL(rstc)))
return -EINVAL;
if (!rstc->rcdev->ops->assert)
return -ENOTSUPP;
if (rstc->shared) {
if (WARN_ON(atomic_read(&rstc->deassert_count) == 0))
return -EINVAL;
if (atomic_dec_return(&rstc->deassert_count) != 0)
return 0;
}
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
可见要使用reset controller 必须定义CONFIG_COMMON_RESET_HI6220
在Hi6220_resetc中
static struct platform_driver hi6220_reset_driver = {
.probe = hi6220_reset_probe,
.driver = {
.name = "reset-hi6220",
.of_match_table = hi6220_reset_match,
},
};
static int __init hi6220_reset_init(void)
{
return platform_driver_register(&hi6220_reset_driver);
}
postcore_initcall(hi6220_reset_init);
定义了一个platform_driver,当其of_match_table 和dts中匹配时就调用hi6220_reset_probe
static const struct reset_control_ops hi6220_peripheral_reset_ops = {
.assert = hi6220_peripheral_assert,
.deassert = hi6220_peripheral_deassert,
};
static int hi6220_reset_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
enum hi6220_reset_ctrl_type type;
struct hi6220_reset_data *data;
struct regmap *regmap;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
type = (enum hi6220_reset_ctrl_type)of_device_get_match_data(dev);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap)) {
dev_err(dev, "failed to get reset controller regmap\n");
return PTR_ERR(regmap);
}
data->regmap = regmap;
data->rc_dev.of_node = np;
if (type == MEDIA) {
data->rc_dev.ops = &hi6220_media_reset_ops;
data->rc_dev.nr_resets = MEDIA_MAX_INDEX;
} else {
data->rc_dev.ops = &hi6220_peripheral_reset_ops;
data->rc_dev.nr_resets = PERIPH_MAX_INDEX;
}
return reset_controller_register(&data->rc_dev);
}
在hi6220_reset_probe 中通过reset_controller_register注册了一个reset controller,reset controller最重要的就是hi6220_peripheral_reset_ops的assert 和 deassert 函数。
这样在dw_mci_parse_dt函数中就会通过下面的code 找到这个reset controller
/* find reset controller when exist */
pdata->rstc = devm_reset_control_get_optional(dev, "reset");
if (IS_ERR(pdata->rstc)) {
if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
}
最终在dw_mci_probe中通过下面的code来调用reset controller,来reset mmc host
if (!IS_ERR(host->pdata->rstc)) {
reset_control_assert(host->pdata->rstc);
usleep_range(10, 50);
reset_control_deassert(host->pdata->rstc);
}
这里以reset_control_assert 为例,很容易看出最终调用ops->assert,而这样的ops就是我们在hi6220_reset.c 中定义的hi6220_peripheral_reset_ops
int reset_control_assert(struct reset_control *rstc)
{
if (WARN_ON(IS_ERR_OR_NULL(rstc)))
return -EINVAL;
if (!rstc->rcdev->ops->assert)
return -ENOTSUPP;
if (rstc->shared) {
if (WARN_ON(atomic_read(&rstc->deassert_count) == 0))
return -EINVAL;
if (atomic_dec_return(&rstc->deassert_count) != 0)
return 0;
}
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);