|
@@ -3416,3 +3416,108 @@ int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
|
|
* XXX what about targets with multiple OCP threads?
|
|
* XXX what about targets with multiple OCP threads?
|
|
*/
|
|
*/
|
|
void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
|
|
void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
|
|
|
|
+{
|
|
|
|
+ BUG_ON(!oh);
|
|
|
|
+
|
|
|
|
+ if (!oh->class->sysc || !oh->class->sysc->sysc_flags) {
|
|
|
|
+ WARN(1, "omap_device: %s: OCP barrier impossible due to device configuration\n",
|
|
|
|
+ oh->name);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Forces posted writes to complete on the OCP thread handling
|
|
|
|
+ * register writes
|
|
|
|
+ */
|
|
|
|
+ omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap_hwmod_reset - reset the hwmod
|
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
|
+ *
|
|
|
|
+ * Under some conditions, a driver may wish to reset the entire device.
|
|
|
|
+ * Called from omap_device code. Returns -EINVAL on error or passes along
|
|
|
|
+ * the return value from _reset().
|
|
|
|
+ */
|
|
|
|
+int omap_hwmod_reset(struct omap_hwmod *oh)
|
|
|
|
+{
|
|
|
|
+ int r;
|
|
|
|
+ unsigned long flags;
|
|
|
|
+
|
|
|
|
+ if (!oh)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&oh->_lock, flags);
|
|
|
|
+ r = _reset(oh);
|
|
|
|
+ spin_unlock_irqrestore(&oh->_lock, flags);
|
|
|
|
+
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * IP block data retrieval functions
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap_hwmod_count_resources - count number of struct resources needed by hwmod
|
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
|
+ * @flags: Type of resources to include when counting (IRQ/DMA/MEM)
|
|
|
|
+ *
|
|
|
|
+ * Count the number of struct resource array elements necessary to
|
|
|
|
+ * contain omap_hwmod @oh resources. Intended to be called by code
|
|
|
|
+ * that registers omap_devices. Intended to be used to determine the
|
|
|
|
+ * size of a dynamically-allocated struct resource array, before
|
|
|
|
+ * calling omap_hwmod_fill_resources(). Returns the number of struct
|
|
|
|
+ * resource array elements needed.
|
|
|
|
+ *
|
|
|
|
+ * XXX This code is not optimized. It could attempt to merge adjacent
|
|
|
|
+ * resource IDs.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags)
|
|
|
|
+{
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ if (flags & IORESOURCE_IRQ)
|
|
|
|
+ ret += _count_mpu_irqs(oh);
|
|
|
|
+
|
|
|
|
+ if (flags & IORESOURCE_DMA)
|
|
|
|
+ ret += _count_sdma_reqs(oh);
|
|
|
|
+
|
|
|
|
+ if (flags & IORESOURCE_MEM) {
|
|
|
|
+ int i = 0;
|
|
|
|
+ struct omap_hwmod_ocp_if *os;
|
|
|
|
+ struct list_head *p = oh->slave_ports.next;
|
|
|
|
+
|
|
|
|
+ while (i < oh->slaves_cnt) {
|
|
|
|
+ os = _fetch_next_ocp_if(&p, &i);
|
|
|
|
+ ret += _count_ocp_if_addr_spaces(os);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * omap_hwmod_fill_resources - fill struct resource array with hwmod data
|
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
|
+ * @res: pointer to the first element of an array of struct resource to fill
|
|
|
|
+ *
|
|
|
|
+ * Fill the struct resource array @res with resource data from the
|
|
|
|
+ * omap_hwmod @oh. Intended to be called by code that registers
|
|
|
|
+ * omap_devices. See also omap_hwmod_count_resources(). Returns the
|
|
|
|
+ * number of array elements filled.
|
|
|
|
+ */
|
|
|
|
+int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
|
|
|
|
+{
|
|
|
|
+ struct omap_hwmod_ocp_if *os;
|
|
|
|
+ struct list_head *p;
|
|
|
|
+ int i, j, mpu_irqs_cnt, sdma_reqs_cnt, addr_cnt;
|
|
|
|
+ int r = 0;
|
|
|
|
+
|
|
|
|
+ /* For each IRQ, DMA, memory area, fill in array.*/
|
|
|
|
+
|
|
|
|
+ mpu_irqs_cnt = _count_mpu_irqs(oh);
|
|
|
|
+ for (i = 0; i < mpu_irqs_cnt; i++) {
|
|
|
|
+ (res + r)->name = (oh->mpu_irqs + i)->name;
|