memory: tegra: Add and use devm_tegra_memory_controller_get()
Multiple Tegra drivers need to retrieve Memory Controller and there is duplication of the retrieval code among the drivers. Add new devm_tegra_memory_controller_get() helper to remove the code's duplication and to fix put_device() which was missed in the duplicated code. Make EMC drivers to use the new helper. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Acked-by: Thierry Reding <treding@nvidia.com> Link: https://lore.kernel.org/r/20201104164923.21238-29-digetx@gmail.com Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
This commit is contained in:
Родитель
7f3cdaf795
Коммит
6c6bd2075f
|
@ -42,6 +42,54 @@ static const struct of_device_id tegra_mc_of_match[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
|
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
|
||||||
|
|
||||||
|
static void tegra_mc_devm_action_put_device(void *data)
|
||||||
|
{
|
||||||
|
struct tegra_mc *mc = data;
|
||||||
|
|
||||||
|
put_device(mc->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_tegra_memory_controller_get() - get Tegra Memory Controller handle
|
||||||
|
* @dev: device pointer for the consumer device
|
||||||
|
*
|
||||||
|
* This function will search for the Memory Controller node in a device-tree
|
||||||
|
* and retrieve the Memory Controller handle.
|
||||||
|
*
|
||||||
|
* Return: ERR_PTR() on error or a valid pointer to a struct tegra_mc.
|
||||||
|
*/
|
||||||
|
struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct device_node *np;
|
||||||
|
struct tegra_mc *mc;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
np = of_parse_phandle(dev->of_node, "nvidia,memory-controller", 0);
|
||||||
|
if (!np)
|
||||||
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
|
pdev = of_find_device_by_node(np);
|
||||||
|
of_node_put(np);
|
||||||
|
if (!pdev)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
mc = platform_get_drvdata(pdev);
|
||||||
|
if (!mc) {
|
||||||
|
put_device(&pdev->dev);
|
||||||
|
return ERR_PTR(-EPROBE_DEFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = devm_add_action(dev, tegra_mc_devm_action_put_device, mc);
|
||||||
|
if (err) {
|
||||||
|
put_device(mc->dev);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_tegra_memory_controller_get);
|
||||||
|
|
||||||
static int tegra_mc_block_dma_common(struct tegra_mc *mc,
|
static int tegra_mc_block_dma_common(struct tegra_mc *mc,
|
||||||
const struct tegra_mc_reset *rst)
|
const struct tegra_mc_reset *rst)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1177,7 +1177,6 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
|
||||||
|
|
||||||
static int tegra_emc_probe(struct platform_device *pdev)
|
static int tegra_emc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct platform_device *mc;
|
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
struct tegra_emc *emc;
|
struct tegra_emc *emc;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
@ -1195,20 +1194,9 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(emc->regs))
|
if (IS_ERR(emc->regs))
|
||||||
return PTR_ERR(emc->regs);
|
return PTR_ERR(emc->regs);
|
||||||
|
|
||||||
np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
|
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
|
||||||
if (!np) {
|
if (IS_ERR(emc->mc))
|
||||||
dev_err(&pdev->dev, "could not get memory controller\n");
|
return PTR_ERR(emc->mc);
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
mc = of_find_device_by_node(np);
|
|
||||||
of_node_put(np);
|
|
||||||
if (!mc)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
emc->mc = platform_get_drvdata(mc);
|
|
||||||
if (!emc->mc)
|
|
||||||
return -EPROBE_DEFER;
|
|
||||||
|
|
||||||
ram_code = tegra_read_ram_code();
|
ram_code = tegra_read_ram_code();
|
||||||
|
|
||||||
|
|
|
@ -1828,7 +1828,6 @@ static int tegra210_emc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct thermal_cooling_device *cd;
|
struct thermal_cooling_device *cd;
|
||||||
unsigned long current_rate;
|
unsigned long current_rate;
|
||||||
struct platform_device *mc;
|
|
||||||
struct tegra210_emc *emc;
|
struct tegra210_emc *emc;
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -1846,35 +1845,19 @@ static int tegra210_emc_probe(struct platform_device *pdev)
|
||||||
spin_lock_init(&emc->lock);
|
spin_lock_init(&emc->lock);
|
||||||
emc->dev = &pdev->dev;
|
emc->dev = &pdev->dev;
|
||||||
|
|
||||||
np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
|
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
|
||||||
if (!np) {
|
if (IS_ERR(emc->mc))
|
||||||
dev_err(&pdev->dev, "could not get memory controller\n");
|
return PTR_ERR(emc->mc);
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
mc = of_find_device_by_node(np);
|
|
||||||
of_node_put(np);
|
|
||||||
if (!mc)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
emc->mc = platform_get_drvdata(mc);
|
|
||||||
if (!emc->mc) {
|
|
||||||
put_device(&mc->dev);
|
|
||||||
return -EPROBE_DEFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
emc->regs = devm_platform_ioremap_resource(pdev, 0);
|
emc->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(emc->regs)) {
|
if (IS_ERR(emc->regs))
|
||||||
err = PTR_ERR(emc->regs);
|
return PTR_ERR(emc->regs);
|
||||||
goto put_mc;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
emc->channel[i] = devm_platform_ioremap_resource(pdev, 1 + i);
|
emc->channel[i] = devm_platform_ioremap_resource(pdev, 1 + i);
|
||||||
if (IS_ERR(emc->channel[i])) {
|
if (IS_ERR(emc->channel[i]))
|
||||||
err = PTR_ERR(emc->channel[i]);
|
return PTR_ERR(emc->channel[i]);
|
||||||
goto put_mc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra210_emc_detect(emc);
|
tegra210_emc_detect(emc);
|
||||||
|
@ -1884,7 +1867,7 @@ static int tegra210_emc_probe(struct platform_device *pdev)
|
||||||
err = of_reserved_mem_device_init_by_name(emc->dev, np, "nominal");
|
err = of_reserved_mem_device_init_by_name(emc->dev, np, "nominal");
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(emc->dev, "failed to get nominal EMC table: %d\n", err);
|
dev_err(emc->dev, "failed to get nominal EMC table: %d\n", err);
|
||||||
goto put_mc;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
|
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
|
||||||
|
@ -2015,8 +1998,7 @@ detach:
|
||||||
tegra210_clk_emc_detach(emc->clk);
|
tegra210_clk_emc_detach(emc->clk);
|
||||||
release:
|
release:
|
||||||
of_reserved_mem_device_release(emc->dev);
|
of_reserved_mem_device_release(emc->dev);
|
||||||
put_mc:
|
|
||||||
put_device(emc->mc->dev);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2027,7 +2009,6 @@ static int tegra210_emc_remove(struct platform_device *pdev)
|
||||||
debugfs_remove_recursive(emc->debugfs.root);
|
debugfs_remove_recursive(emc->debugfs.root);
|
||||||
tegra210_clk_emc_detach(emc->clk);
|
tegra210_clk_emc_detach(emc->clk);
|
||||||
of_reserved_mem_device_release(emc->dev);
|
of_reserved_mem_device_release(emc->dev);
|
||||||
put_device(emc->mc->dev);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1258,7 +1258,6 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc)
|
||||||
|
|
||||||
static int tegra_emc_probe(struct platform_device *pdev)
|
static int tegra_emc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct platform_device *mc;
|
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
struct tegra_emc *emc;
|
struct tegra_emc *emc;
|
||||||
int err;
|
int err;
|
||||||
|
@ -1269,17 +1268,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
|
|
||||||
if (!np) {
|
|
||||||
dev_err(&pdev->dev, "could not get memory controller node\n");
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
mc = of_find_device_by_node(np);
|
|
||||||
of_node_put(np);
|
|
||||||
if (!mc)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
np = emc_find_node_by_ram_code(&pdev->dev);
|
np = emc_find_node_by_ram_code(&pdev->dev);
|
||||||
if (!np)
|
if (!np)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1290,9 +1278,9 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
emc->mc = platform_get_drvdata(mc);
|
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
|
||||||
if (!emc->mc)
|
if (IS_ERR(emc->mc))
|
||||||
return -EPROBE_DEFER;
|
return PTR_ERR(emc->mc);
|
||||||
|
|
||||||
emc->clk_nb.notifier_call = emc_clk_change_notify;
|
emc->clk_nb.notifier_call = emc_clk_change_notify;
|
||||||
emc->dev = &pdev->dev;
|
emc->dev = &pdev->dev;
|
||||||
|
|
|
@ -184,4 +184,14 @@ struct tegra_mc {
|
||||||
int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
|
int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
|
||||||
unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
|
unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
|
||||||
|
|
||||||
|
#ifdef CONFIG_TEGRA_MC
|
||||||
|
struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev);
|
||||||
|
#else
|
||||||
|
static inline struct tegra_mc *
|
||||||
|
devm_tegra_memory_controller_get(struct device *dev)
|
||||||
|
{
|
||||||
|
ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __SOC_TEGRA_MC_H__ */
|
#endif /* __SOC_TEGRA_MC_H__ */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче