Commit b57250fa authored by Tony Lindgren's avatar Tony Lindgren
Browse files

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 <paul@pwsan.com>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 6d63b12d
Loading
Loading
Loading
Loading
+78 −4
Original line number Diff line number Diff line
@@ -235,6 +235,7 @@ static struct omap_hwmod_soc_ops soc_ops;

/* omap_hwmod_list contains all registered struct omap_hwmods */
static LIST_HEAD(omap_hwmod_list);
static DEFINE_MUTEX(list_lock);

/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
static struct omap_hwmod *mpu_oh;
@@ -2624,7 +2625,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
 * that the copy process would be relatively complex due to the large number
 * of substructures.
 */
static int __init _register(struct omap_hwmod *oh)
static int _register(struct omap_hwmod *oh)
{
	if (!oh || !oh->name || !oh->class || !oh->class->name ||
	    (oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -2663,7 +2664,7 @@ static int __init _register(struct omap_hwmod *oh)
 * locking in this code.  Changes to this assumption will require
 * additional locking.  Returns 0.
 */
static int __init _add_link(struct omap_hwmod_ocp_if *oi)
static int _add_link(struct omap_hwmod_ocp_if *oi)
{
	pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
		 oi->slave->name);
@@ -3444,6 +3445,9 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
{
	struct omap_hwmod_class_sysconfig *sysc;
	struct omap_hwmod_class *class = NULL;
	struct omap_hwmod_ocp_if *oi = NULL;
	struct clockdomain *clkdm = NULL;
	struct clk *clk = NULL;
	void __iomem *regs = NULL;
	unsigned long flags;

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

	if (list_empty(&oh->slave_ports)) {
		oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
		if (!oi)
			return -ENOMEM;

		/*
		 * Note that we assume interconnect interface clocks will be
		 * managed by the interconnect driver for OCPIF_SWSUP_IDLE case
		 * on omap24xx and omap3.
		 */
		oi->slave = oh;
		oi->user = OCP_USER_MPU | OCP_USER_SDMA;
	}

	if (!oh->_clk) {
		struct clk_hw_omap *hwclk;

		clk = of_clk_get_by_name(dev->of_node, "fck");
		if (!IS_ERR(clk))
			clk_prepare(clk);
		else
			clk = NULL;

		/*
		 * Populate clockdomain based on dts clock. It is needed for
		 * clkdm_deny_idle() and clkdm_allow_idle() until we have have
		 * interconnect driver and reset driver capable of blocking
		 * clockdomain idle during reset, enable and idle.
		 */
		if (clk) {
			hwclk = to_clk_hw_omap(__clk_get_hw(clk));
			if (hwclk && hwclk->clkdm_name)
				clkdm = clkdm_lookup(hwclk->clkdm_name);
		}

		/*
		 * Note that we assume interconnect driver manages the clocks
		 * and do not need to populate oh->_clk for dynamically
		 * allocated modules.
		 */
		clk_unprepare(clk);
		clk_put(clk);
	}

	spin_lock_irqsave(&oh->_lock, flags);
	if (regs)
		oh->_mpu_rt_va = regs;
	if (class)
		oh->class = class;
	oh->class->sysc = sysc;
	if (oi)
		_add_link(oi);
	if (clkdm)
		oh->clkdm = clkdm;
	oh->_state = _HWMOD_STATE_INITIALIZED;
	oh->_postsetup_state = _HWMOD_STATE_DEFAULT;
	_setup(oh, NULL);
	spin_unlock_irqrestore(&oh->_lock, flags);

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

	oh = _lookup(data->name);
	if (!oh) {
		oh = kzalloc(sizeof(*oh), GFP_KERNEL);
		if (!oh)
		return -ENODEV;
			return -ENOMEM;

		oh->name = data->name;
		oh->_state = _HWMOD_STATE_UNKNOWN;
		lockdep_register_key(&oh->hwmod_key);

		/* Unused, can be handled by PRM driver handling resets */
		oh->prcm.omap4.flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT;

		oh->class = kzalloc(sizeof(*oh->class), GFP_KERNEL);
		if (!oh->class) {
			kfree(oh);
			return -ENOMEM;
		}

		oh->class->name = data->name;
		mutex_lock(&list_lock);
		error = _register(oh);
		mutex_unlock(&list_lock);
	}

	cookie->data = oh;