|
@@ -1135,3 +1135,170 @@ static int _get_mpu_irq_by_name(struct omap_hwmod *oh, const char *name,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * _get_sdma_req_by_name - fetch SDMA request line ID by name
|
|
|
+ * @oh: struct omap_hwmod * to operate on
|
|
|
+ * @name: pointer to the name of the SDMA request line to fetch (optional)
|
|
|
+ * @dma: pointer to an unsigned int to store the request line ID to
|
|
|
+ *
|
|
|
+ * Retrieve an SDMA request line ID named by @name on the IP block
|
|
|
+ * pointed to by @oh. The ID will be filled into the address pointed
|
|
|
+ * to by @dma. When @name is non-null, the request line ID associated
|
|
|
+ * with the named entry will be returned. If @name is null, the first
|
|
|
+ * matching 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. Returns 0
|
|
|
+ * upon success or a negative error code upon error.
|
|
|
+ */
|
|
|
+static int _get_sdma_req_by_name(struct omap_hwmod *oh, const char *name,
|
|
|
+ unsigned int *dma)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ bool found = false;
|
|
|
+
|
|
|
+ if (!oh->sdma_reqs)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ i = 0;
|
|
|
+ while (oh->sdma_reqs[i].dma_req != -1) {
|
|
|
+ if (name == oh->sdma_reqs[i].name ||
|
|
|
+ !strcmp(name, oh->sdma_reqs[i].name)) {
|
|
|
+ found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ *dma = oh->sdma_reqs[i].dma_req;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _get_addr_space_by_name - fetch address space start & end by name
|
|
|
+ * @oh: struct omap_hwmod * to operate on
|
|
|
+ * @name: pointer to the name of the address space to fetch (optional)
|
|
|
+ * @pa_start: pointer to a u32 to store the starting address to
|
|
|
+ * @pa_end: pointer to a u32 to store the ending address to
|
|
|
+ *
|
|
|
+ * Retrieve address space start and end addresses for the IP block
|
|
|
+ * pointed to by @oh. The data will be filled into the addresses
|
|
|
+ * pointed to by @pa_start and @pa_end. When @name is non-null, the
|
|
|
+ * address space data associated with the named entry will be
|
|
|
+ * returned. If @name is null, the first matching 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. Returns 0 upon success or a
|
|
|
+ * negative error code upon error.
|
|
|
+ */
|
|
|
+static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name,
|
|
|
+ u32 *pa_start, u32 *pa_end)
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+ struct omap_hwmod_ocp_if *os;
|
|
|
+ struct list_head *p = NULL;
|
|
|
+ bool found = false;
|
|
|
+
|
|
|
+ p = oh->slave_ports.next;
|
|
|
+
|
|
|
+ i = 0;
|
|
|
+ while (i < oh->slaves_cnt) {
|
|
|
+ os = _fetch_next_ocp_if(&p, &i);
|
|
|
+
|
|
|
+ if (!os->addr)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ j = 0;
|
|
|
+ while (os->addr[j].pa_start != os->addr[j].pa_end) {
|
|
|
+ if (name == os->addr[j].name ||
|
|
|
+ !strcmp(name, os->addr[j].name)) {
|
|
|
+ found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (found)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ *pa_start = os->addr[j].pa_start;
|
|
|
+ *pa_end = os->addr[j].pa_end;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _save_mpu_port_index - find and save the index to @oh's MPU port
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Determines the array index of the OCP slave port that the MPU uses
|
|
|
+ * to address the device, and saves it into the struct omap_hwmod.
|
|
|
+ * Intended to be called during hwmod registration only. No return
|
|
|
+ * value.
|
|
|
+ */
|
|
|
+static void __init _save_mpu_port_index(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ struct omap_hwmod_ocp_if *os = NULL;
|
|
|
+ struct list_head *p;
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
+ if (!oh)
|
|
|
+ return;
|
|
|
+
|
|
|
+ oh->_int_flags |= _HWMOD_NO_MPU_PORT;
|
|
|
+
|
|
|
+ p = oh->slave_ports.next;
|
|
|
+
|
|
|
+ while (i < oh->slaves_cnt) {
|
|
|
+ os = _fetch_next_ocp_if(&p, &i);
|
|
|
+ if (os->user & OCP_USER_MPU) {
|
|
|
+ oh->_mpu_port = os;
|
|
|
+ oh->_int_flags &= ~_HWMOD_NO_MPU_PORT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _find_mpu_rt_port - return omap_hwmod_ocp_if accessible by the MPU
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Given a pointer to a struct omap_hwmod record @oh, return a pointer
|
|
|
+ * to the struct omap_hwmod_ocp_if record that is used by the MPU to
|
|
|
+ * communicate with the IP block. This interface need not be directly
|
|
|
+ * connected to the MPU (and almost certainly is not), but is directly
|
|
|
+ * connected to the IP block represented by @oh. Returns a pointer
|
|
|
+ * to the struct omap_hwmod_ocp_if * upon success, or returns NULL upon
|
|
|
+ * error or if there does not appear to be a path from the MPU to this
|
|
|
+ * IP block.
|
|
|
+ */
|
|
|
+static struct omap_hwmod_ocp_if *_find_mpu_rt_port(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ if (!oh || oh->_int_flags & _HWMOD_NO_MPU_PORT || oh->slaves_cnt == 0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return oh->_mpu_port;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * _find_mpu_rt_addr_space - return MPU register target address space for @oh
|
|
|
+ * @oh: struct omap_hwmod *
|
|
|
+ *
|
|
|
+ * Returns a pointer to the struct omap_hwmod_addr_space record representing
|
|
|
+ * the register target MPU address space; or returns NULL upon error.
|
|
|
+ */
|
|
|
+static struct omap_hwmod_addr_space * __init _find_mpu_rt_addr_space(struct omap_hwmod *oh)
|
|
|
+{
|
|
|
+ struct omap_hwmod_ocp_if *os;
|
|
|
+ struct omap_hwmod_addr_space *mem;
|