|
@@ -3598,3 +3598,201 @@ int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res)
|
|
|
* first array entry will be returned. Data order is not meaningful
|
|
|
* in hwmod data, so callers are strongly encouraged to use a non-null
|
|
|
* @name whenever possible to avoid unpredictable effects if hwmod
|
|
|
+ * data is later added that causes data ordering to change. This
|
|
|
+ * function is only intended for use by OMAP core code. Device
|
|
|
+ * drivers should not call this function - the appropriate bus-related
|
|
|
+ * data accessor functions should be used instead. Returns 0 upon
|
|
|
+ * success or a negative error code upon error.
|
|
|
+ */
|
|
|
+int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
|
|
|
+ const char *name, struct resource *rsrc)
|
|
|
+{
|
|
|
+ int r;
|
|
|
+ unsigned int irq, dma;
|
|
|
+ u32 pa_start, pa_end;
|
|
|
+
|
|
|
+ if (!oh || !rsrc)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (type == IORESOURCE_IRQ) {
|
|
|
+ r = _get_mpu_irq_by_name(oh, name, &irq);
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ rsrc->start = irq;
|
|
|
+ rsrc->end = irq;
|
|
|
+ } else if (type == IORESOURCE_DMA) {
|
|
|
+ r = _get_sdma_req_by_name(oh, name, &dma);
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ rsrc->start = dma;
|
|
|
+ rsrc->end = dma;
|
|
|
+ } else if (type == IORESOURCE_MEM) {
|
|
|
+ r = _get_addr_space_by_name(oh, name, &pa_start, &pa_end);
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ rsrc->start = pa_start;
|
|
|
+ rsrc->end = pa_end;
|
|
|
+ } else {
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ rsrc->flags = type;
|
|
|
+ rsrc->name = name;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_hwmod_get_pwrdm - return pointer to this module's main powerdomain
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Return the powerdomain pointer associated with the OMAP module
|
|
|
+ * @oh's main clock. If @oh does not have a main clk, return the
|
|
|
+ * powerdomain associated with the interface clock associated with the
|
|
|
+ * module's MPU port. (XXX Perhaps this should use the SDMA port
|
|
|
+ * instead?) Returns NULL on error, or a struct powerdomain * on
|
|
|
+ * success.
|
|
|
+ */
|
|
|
+struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ struct clk *c;
|
|
|
+ struct omap_hwmod_ocp_if *oi;
|
|
|
+ struct clockdomain *clkdm;
|
|
|
+ struct clk_hw_omap *clk;
|
|
|
+
|
|
|
+ if (!oh)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (oh->clkdm)
|
|
|
+ return oh->clkdm->pwrdm.ptr;
|
|
|
+
|
|
|
+ if (oh->_clk) {
|
|
|
+ c = oh->_clk;
|
|
|
+ } else {
|
|
|
+ oi = _find_mpu_rt_port(oh);
|
|
|
+ if (!oi)
|
|
|
+ return NULL;
|
|
|
+ c = oi->_clk;
|
|
|
+ }
|
|
|
+
|
|
|
+ clk = to_clk_hw_omap(__clk_get_hw(c));
|
|
|
+ clkdm = clk->clkdm;
|
|
|
+ if (!clkdm)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return clkdm->pwrdm.ptr;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_hwmod_get_mpu_rt_va - return the module's base address (for the MPU)
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Returns the virtual address corresponding to the beginning of the
|
|
|
+ * module's register target, in the address range that is intended to
|
|
|
+ * be used by the MPU. Returns the virtual address upon success or NULL
|
|
|
+ * upon error.
|
|
|
+ */
|
|
|
+void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ if (!oh)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (oh->_state == _HWMOD_STATE_UNKNOWN)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return oh->_mpu_rt_va;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_hwmod_add_initiator_dep - add sleepdep from @init_oh to @oh
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ * @init_oh: struct omap_hwmod * (initiator)
|
|
|
+ *
|
|
|
+ * Add a sleep dependency between the initiator @init_oh and @oh.
|
|
|
+ * Intended to be called by DSP/Bridge code via platform_data for the
|
|
|
+ * DSP case; and by the DMA code in the sDMA case. DMA code, *Bridge
|
|
|
+ * code needs to add/del initiator dependencies dynamically
|
|
|
+ * before/after accessing a device. Returns the return value from
|
|
|
+ * _add_initiator_dep().
|
|
|
+ *
|
|
|
+ * XXX Keep a usecount in the clockdomain code
|
|
|
+ */
|
|
|
+int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh,
|
|
|
+ struct omap_hwmod *init_oh)
|
|
|
+{
|
|
|
+ return _add_initiator_dep(oh, init_oh);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * XXX what about functions for drivers to save/restore ocp_sysconfig
|
|
|
+ * for context save/restore operations?
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_hwmod_del_initiator_dep - remove sleepdep from @init_oh to @oh
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ * @init_oh: struct omap_hwmod * (initiator)
|
|
|
+ *
|
|
|
+ * Remove a sleep dependency between the initiator @init_oh and @oh.
|
|
|
+ * Intended to be called by DSP/Bridge code via platform_data for the
|
|
|
+ * DSP case; and by the DMA code in the sDMA case. DMA code, *Bridge
|
|
|
+ * code needs to add/del initiator dependencies dynamically
|
|
|
+ * before/after accessing a device. Returns the return value from
|
|
|
+ * _del_initiator_dep().
|
|
|
+ *
|
|
|
+ * XXX Keep a usecount in the clockdomain code
|
|
|
+ */
|
|
|
+int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
|
|
|
+ struct omap_hwmod *init_oh)
|
|
|
+{
|
|
|
+ return _del_initiator_dep(oh, init_oh);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_hwmod_enable_wakeup - allow device to wake up the system
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Sets the module OCP socket ENAWAKEUP bit to allow the module to
|
|
|
+ * send wakeups to the PRCM, and enable I/O ring wakeup events for
|
|
|
+ * this IP block if it has dynamic mux entries. Eventually this
|
|
|
+ * should set PRCM wakeup registers to cause the PRCM to receive
|
|
|
+ * wakeup events from the module. Does not set any wakeup routing
|
|
|
+ * registers beyond this point - if the module is to wake up any other
|
|
|
+ * module or subsystem, that must be set separately. Called by
|
|
|
+ * omap_device code. Returns -EINVAL on error or 0 upon success.
|
|
|
+ */
|
|
|
+int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ u32 v;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&oh->_lock, flags);
|
|
|
+
|
|
|
+ if (oh->class->sysc &&
|
|
|
+ (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
|
|
|
+ v = oh->_sysc_cache;
|
|
|
+ _enable_wakeup(oh, &v);
|
|
|
+ _write_sysconfig(v, oh);
|
|
|
+ }
|
|
|
+
|
|
|
+ _set_idle_ioring_wakeup(oh, true);
|
|
|
+ spin_unlock_irqrestore(&oh->_lock, flags);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_hwmod_disable_wakeup - prevent device from waking the system
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Clears the module OCP socket ENAWAKEUP bit to prevent the module
|
|
|
+ * from sending wakeups to the PRCM, and disable I/O ring wakeup
|
|
|
+ * events for this IP block if it has dynamic mux entries. Eventually
|
|
|
+ * this should clear PRCM wakeup registers to cause the PRCM to ignore
|
|
|
+ * wakeup events from the module. Does not set any wakeup routing
|