mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 20:32:22 +00:00
clk: renesas: cpg-mssr: Add early clock support
Add support for SoCs that need to register core and module clocks early in order to use OF drivers that exclusively use macros such as TIMER_OF_DECLARE. Signed-off-by: Chris Brandt <chris.brandt@renesas.com> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
parent
9ef5e0370d
commit
1f7db7bbf0
@ -130,6 +130,7 @@ struct cpg_mssr_priv {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
spinlock_t rmw_lock;
|
||||
struct device_node *np;
|
||||
|
||||
struct clk **clks;
|
||||
unsigned int num_core_clks;
|
||||
@ -144,6 +145,7 @@ struct cpg_mssr_priv {
|
||||
} smstpcr_saved[ARRAY_SIZE(smstpcr)];
|
||||
};
|
||||
|
||||
static struct cpg_mssr_priv *cpg_mssr_priv;
|
||||
|
||||
/**
|
||||
* struct mstp_clock - MSTP gating clock
|
||||
@ -319,7 +321,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
||||
|
||||
switch (core->type) {
|
||||
case CLK_TYPE_IN:
|
||||
clk = of_clk_get_by_name(priv->dev->of_node, core->name);
|
||||
clk = of_clk_get_by_name(priv->np, core->name);
|
||||
break;
|
||||
|
||||
case CLK_TYPE_FF:
|
||||
@ -891,42 +893,43 @@ static const struct dev_pm_ops cpg_mssr_pm = {
|
||||
#define DEV_PM_OPS NULL
|
||||
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
|
||||
|
||||
static int __init cpg_mssr_probe(struct platform_device *pdev)
|
||||
static int __init cpg_mssr_common_init(struct device *dev,
|
||||
struct device_node *np,
|
||||
const struct cpg_mssr_info *info)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
const struct cpg_mssr_info *info;
|
||||
struct cpg_mssr_priv *priv;
|
||||
struct clk **clks = NULL;
|
||||
unsigned int nclks, i;
|
||||
struct resource *res;
|
||||
struct clk **clks;
|
||||
int error;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
if (info->init) {
|
||||
error = info->init(dev);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->np = np;
|
||||
priv->dev = dev;
|
||||
spin_lock_init(&priv->rmw_lock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
priv->base = of_iomap(np, 0);
|
||||
if (!priv->base) {
|
||||
error = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
nclks = info->num_total_core_clks + info->num_hw_mod_clks;
|
||||
clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL);
|
||||
if (!clks)
|
||||
return -ENOMEM;
|
||||
clks = kmalloc_array(nclks, sizeof(*clks), GFP_KERNEL);
|
||||
if (!clks) {
|
||||
error = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
cpg_mssr_priv = priv;
|
||||
priv->clks = clks;
|
||||
priv->num_core_clks = info->num_total_core_clks;
|
||||
priv->num_mod_clks = info->num_hw_mod_clks;
|
||||
@ -937,16 +940,68 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < nclks; i++)
|
||||
clks[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
|
||||
if (error)
|
||||
goto out_err;
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
kfree(clks);
|
||||
if (priv->base)
|
||||
iounmap(priv->base);
|
||||
kfree(priv);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void __init cpg_mssr_early_init(struct device_node *np,
|
||||
const struct cpg_mssr_info *info)
|
||||
{
|
||||
int error;
|
||||
int i;
|
||||
|
||||
error = cpg_mssr_common_init(NULL, np, info);
|
||||
if (error)
|
||||
return;
|
||||
|
||||
for (i = 0; i < info->num_early_core_clks; i++)
|
||||
cpg_mssr_register_core_clk(&info->early_core_clks[i], info,
|
||||
cpg_mssr_priv);
|
||||
|
||||
for (i = 0; i < info->num_early_mod_clks; i++)
|
||||
cpg_mssr_register_mod_clk(&info->early_mod_clks[i], info,
|
||||
cpg_mssr_priv);
|
||||
|
||||
}
|
||||
|
||||
static int __init cpg_mssr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
const struct cpg_mssr_info *info;
|
||||
struct cpg_mssr_priv *priv;
|
||||
unsigned int i;
|
||||
int error;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
|
||||
if (!cpg_mssr_priv) {
|
||||
error = cpg_mssr_common_init(dev, dev->of_node, info);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
priv = cpg_mssr_priv;
|
||||
priv->dev = dev;
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
for (i = 0; i < info->num_core_clks; i++)
|
||||
cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
|
||||
|
||||
for (i = 0; i < info->num_mod_clks; i++)
|
||||
cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv);
|
||||
|
||||
error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = devm_add_action_or_reset(dev,
|
||||
cpg_mssr_del_clk_provider,
|
||||
np);
|
||||
|
@ -91,6 +91,11 @@ struct device_node;
|
||||
/**
|
||||
* SoC-specific CPG/MSSR Description
|
||||
*
|
||||
* @early_core_clks: Array of Early Core Clock definitions
|
||||
* @num_early_core_clks: Number of entries in early_core_clks[]
|
||||
* @early_mod_clks: Array of Early Module Clock definitions
|
||||
* @num_early_mod_clks: Number of entries in early_mod_clks[]
|
||||
*
|
||||
* @core_clks: Array of Core Clock definitions
|
||||
* @num_core_clks: Number of entries in core_clks[]
|
||||
* @last_dt_core_clk: ID of the last Core Clock exported to DT
|
||||
@ -117,6 +122,12 @@ struct device_node;
|
||||
*/
|
||||
|
||||
struct cpg_mssr_info {
|
||||
/* Early Clocks */
|
||||
const struct cpg_core_clk *early_core_clks;
|
||||
unsigned int num_early_core_clks;
|
||||
const struct mssr_mod_clk *early_mod_clks;
|
||||
unsigned int num_early_mod_clks;
|
||||
|
||||
/* Core Clocks */
|
||||
const struct cpg_core_clk *core_clks;
|
||||
unsigned int num_core_clks;
|
||||
@ -164,6 +175,8 @@ extern const struct cpg_mssr_info r8a77980_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a77990_cpg_mssr_info;
|
||||
extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
|
||||
|
||||
void __init cpg_mssr_early_init(struct device_node *np,
|
||||
const struct cpg_mssr_info *info);
|
||||
|
||||
/*
|
||||
* Helpers for fixing up clock tables depending on SoC revision
|
||||
|
Loading…
Reference in New Issue
Block a user