Skip to content

Commit b57250f

Browse files
committed
ARM: OMAP2+: Allocate struct omap_hwmod based on dts data
With ti-sysc interconnect target module, we can allocate struct omap_hwmod data based on the devicetree data. This allows dropping the static SoC specific data eventually so we will only boot with data we actually need. To allocate struct omap_hwmod dynamically, we need to add a mutex for modifying the list, and remove __init for few functions. Note that we are not initialized oh->_clk or the optional clocks and their related quirks. That can be directly handled by the interconnect target module driver. Cc: Paul Walmsley <[email protected]> Cc: Tero Kristo <[email protected]> Signed-off-by: Tony Lindgren <[email protected]>
1 parent 6d63b12 commit b57250f

File tree

1 file changed

+78
-4
lines changed

1 file changed

+78
-4
lines changed

arch/arm/mach-omap2/omap_hwmod.c

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ static struct omap_hwmod_soc_ops soc_ops;
235235

236236
/* omap_hwmod_list contains all registered struct omap_hwmods */
237237
static LIST_HEAD(omap_hwmod_list);
238+
static DEFINE_MUTEX(list_lock);
238239

239240
/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
240241
static struct omap_hwmod *mpu_oh;
@@ -2624,7 +2625,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
26242625
* that the copy process would be relatively complex due to the large number
26252626
* of substructures.
26262627
*/
2627-
static int __init _register(struct omap_hwmod *oh)
2628+
static int _register(struct omap_hwmod *oh)
26282629
{
26292630
if (!oh || !oh->name || !oh->class || !oh->class->name ||
26302631
(oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -2663,7 +2664,7 @@ static int __init _register(struct omap_hwmod *oh)
26632664
* locking in this code. Changes to this assumption will require
26642665
* additional locking. Returns 0.
26652666
*/
2666-
static int __init _add_link(struct omap_hwmod_ocp_if *oi)
2667+
static int _add_link(struct omap_hwmod_ocp_if *oi)
26672668
{
26682669
pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
26692670
oi->slave->name);
@@ -3444,6 +3445,9 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
34443445
{
34453446
struct omap_hwmod_class_sysconfig *sysc;
34463447
struct omap_hwmod_class *class = NULL;
3448+
struct omap_hwmod_ocp_if *oi = NULL;
3449+
struct clockdomain *clkdm = NULL;
3450+
struct clk *clk = NULL;
34473451
void __iomem *regs = NULL;
34483452
unsigned long flags;
34493453

@@ -3476,13 +3480,62 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
34763480
return -ENOMEM;
34773481
}
34783482

3483+
if (list_empty(&oh->slave_ports)) {
3484+
oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
3485+
if (!oi)
3486+
return -ENOMEM;
3487+
3488+
/*
3489+
* Note that we assume interconnect interface clocks will be
3490+
* managed by the interconnect driver for OCPIF_SWSUP_IDLE case
3491+
* on omap24xx and omap3.
3492+
*/
3493+
oi->slave = oh;
3494+
oi->user = OCP_USER_MPU | OCP_USER_SDMA;
3495+
}
3496+
3497+
if (!oh->_clk) {
3498+
struct clk_hw_omap *hwclk;
3499+
3500+
clk = of_clk_get_by_name(dev->of_node, "fck");
3501+
if (!IS_ERR(clk))
3502+
clk_prepare(clk);
3503+
else
3504+
clk = NULL;
3505+
3506+
/*
3507+
* Populate clockdomain based on dts clock. It is needed for
3508+
* clkdm_deny_idle() and clkdm_allow_idle() until we have have
3509+
* interconnect driver and reset driver capable of blocking
3510+
* clockdomain idle during reset, enable and idle.
3511+
*/
3512+
if (clk) {
3513+
hwclk = to_clk_hw_omap(__clk_get_hw(clk));
3514+
if (hwclk && hwclk->clkdm_name)
3515+
clkdm = clkdm_lookup(hwclk->clkdm_name);
3516+
}
3517+
3518+
/*
3519+
* Note that we assume interconnect driver manages the clocks
3520+
* and do not need to populate oh->_clk for dynamically
3521+
* allocated modules.
3522+
*/
3523+
clk_unprepare(clk);
3524+
clk_put(clk);
3525+
}
3526+
34793527
spin_lock_irqsave(&oh->_lock, flags);
34803528
if (regs)
34813529
oh->_mpu_rt_va = regs;
34823530
if (class)
34833531
oh->class = class;
34843532
oh->class->sysc = sysc;
3533+
if (oi)
3534+
_add_link(oi);
3535+
if (clkdm)
3536+
oh->clkdm = clkdm;
34853537
oh->_state = _HWMOD_STATE_INITIALIZED;
3538+
oh->_postsetup_state = _HWMOD_STATE_DEFAULT;
34863539
_setup(oh, NULL);
34873540
spin_unlock_irqrestore(&oh->_lock, flags);
34883541

@@ -3509,8 +3562,29 @@ int omap_hwmod_init_module(struct device *dev,
35093562
return -EINVAL;
35103563

35113564
oh = _lookup(data->name);
3512-
if (!oh)
3513-
return -ENODEV;
3565+
if (!oh) {
3566+
oh = kzalloc(sizeof(*oh), GFP_KERNEL);
3567+
if (!oh)
3568+
return -ENOMEM;
3569+
3570+
oh->name = data->name;
3571+
oh->_state = _HWMOD_STATE_UNKNOWN;
3572+
lockdep_register_key(&oh->hwmod_key);
3573+
3574+
/* Unused, can be handled by PRM driver handling resets */
3575+
oh->prcm.omap4.flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT;
3576+
3577+
oh->class = kzalloc(sizeof(*oh->class), GFP_KERNEL);
3578+
if (!oh->class) {
3579+
kfree(oh);
3580+
return -ENOMEM;
3581+
}
3582+
3583+
oh->class->name = data->name;
3584+
mutex_lock(&list_lock);
3585+
error = _register(oh);
3586+
mutex_unlock(&list_lock);
3587+
}
35143588

35153589
cookie->data = oh;
35163590

0 commit comments

Comments
 (0)