diff options
author | Arnd Bergmann <arnd@arndb.de> | 2017-10-20 00:43:31 +0200 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2017-10-20 00:43:31 +0200 |
commit | ab63d1efc5674c09e1c24a8bc9301daa172f5050 (patch) | |
tree | 0c2d8fc0239249c341c40d7c6aca7b71dbac081a /arch/arm/mach-omap2 | |
parent | e4191c53ae4627fe5bf32fd77abaa527f49b628b (diff) | |
parent | 684be5a48f4950cb8823b4c4b935515a75615498 (diff) |
Merge tag 'omap-for-v4.15/ti-sysc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc
Pull "more soc changes for omaps for v4.15 merge window" from Tony Lindgren:
Drop omap legacy platform data for IRQ, DMA and IO resources. With the
dts files fixed up to contain the necessary data for basic resources, we
can drop the related platform data.
Note that this branch depends on the "omap-for-v4.15/fixes-dt-signed"
branch and the patches with dependencies are based on a merge with that
branch.
These patches first ensure things keep working for the legacy "ti,hwmods"
property when we start making it optional, then adds a minimal TI sysc
interconnect target device driver to handle the new generic "ti,sysc"
compatible property. And then we can finally drop the legacy platform
data for IRQ, DMA and IO resources as seen in the diffstats.
* tag 'omap-for-v4.15/ti-sysc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (25 commits)
bus: ti-sysc: Fix unbalanced pm_runtime_enable by adding remove
bus: ti-sysc: mark PM functions as __maybe_unused
ARM: OMAP2+: omap_device: fix error return code in omap_device_copy_resources()
ARM: OMAP2+: Drop legacy struct omap_hwmod_addr_space
ARM: OMAP2+: Drop omap_hwmod_dma_info
ARM: OMAP2+: Drop omap_hwmod_irq_info
ARM: OMAP4: Remove legacy IRQ for PRM
ARM: OMAP3: Remove legacy IRQ for PRM
bus: ti-sysc: Add minimal TI sysc interconnect target driver
ARM: OMAP2+: Populate legacy resources for dma and smartreflex
ARM: OMAP2+: Parse module IO range from dts for legacy "ti,hwmods" support
ARM: dts: Configure SmartReflex only to idle the interconnect target module
ARM: dts: Add nodes for missing omap4 interconnect target modules
dt-bindings: bus: Minimal TI sysc interconnect target module binding
ARM: dts: Add missing hwmod related properties for dra7
ARM: dts: Add missing hwmod related nodes for am33xx
ARM: dts: Add missing dma hwmod property for omap5
ARM: dts: Add missing wdt3 node for omap4
ARM: dts: Add missing hsi node for omap4
ARM: dts: Add missing onewire node for omap4
...
Diffstat (limited to 'arch/arm/mach-omap2')
26 files changed, 215 insertions, 1693 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index e31a5a22e171..00b1f17f8d44 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -104,6 +104,7 @@ config ARCH_OMAP2PLUS select OMAP_GPMC select PINCTRL select SOC_BUS + select TI_SYSC select OMAP_IRQCHIP select CLKSRC_TI_32K help diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b3b3b3a19183..ca6dbbf73d76 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -198,15 +198,12 @@ obj-y += omap_hwmod_common_ipblock_data.o obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_ipblock_data.o obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_3xxx_ipblock_data.o obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_interconnect_data.o -obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_3xxx_interconnect_data.o obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2420_data.o obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2xxx_ipblock_data.o obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2xxx_3xxx_ipblock_data.o obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2xxx_interconnect_data.o -obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2xxx_3xxx_interconnect_data.o obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2430_data.o obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_2xxx_3xxx_ipblock_data.o -obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_2xxx_3xxx_interconnect_data.o obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_3xxx_data.o obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_data.o obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_43xx_interconnect_data.o diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index b5ad7fcb80ed..bc202835371b 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -225,7 +225,6 @@ extern struct device *omap2_get_iva_device(void); extern struct device *omap2_get_l3_device(void); extern struct device *omap4_get_dsp_device(void); -unsigned int omap4_xlate_irq(unsigned int hwirq); void omap_gic_of_init(void); #ifdef CONFIG_CACHE_L2X0 diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index cf65ab8bb004..b226c8aaf8b1 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -299,30 +299,6 @@ static const struct of_device_id intc_match[] = { static struct device_node *intc_node; -unsigned int omap4_xlate_irq(unsigned int hwirq) -{ - struct of_phandle_args irq_data; - unsigned int irq; - - if (!intc_node) - intc_node = of_find_matching_node(NULL, intc_match); - - if (WARN_ON(!intc_node)) - return hwirq; - - irq_data.np = intc_node; - irq_data.args_count = 3; - irq_data.args[0] = 0; - irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START; - irq_data.args[2] = IRQ_TYPE_LEVEL_HIGH; - - irq = irq_create_of_mapping(&irq_data); - if (WARN_ON(!irq)) - irq = hwirq; - - return irq; -} - void __init omap_gic_of_init(void) { struct device_node *np; diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index acbede082b5b..d45cbfdb4be6 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -35,6 +35,8 @@ #include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/notifier.h> #include "common.h" @@ -309,88 +311,6 @@ int omap_device_get_context_loss_count(struct platform_device *pdev) } /** - * omap_device_count_resources - count number of struct resource entries needed - * @od: struct omap_device * - * @flags: Type of resources to include when counting (IRQ/DMA/MEM) - * - * Count the number of struct resource entries needed for this - * omap_device @od. Used by omap_device_build_ss() to determine how - * much memory to allocate before calling - * omap_device_fill_resources(). Returns the count. - */ -static int omap_device_count_resources(struct omap_device *od, - unsigned long flags) -{ - int c = 0; - int i; - - for (i = 0; i < od->hwmods_cnt; i++) - c += omap_hwmod_count_resources(od->hwmods[i], flags); - - pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n", - od->pdev->name, c, od->hwmods_cnt); - - return c; -} - -/** - * omap_device_fill_resources - fill in array of struct resource - * @od: struct omap_device * - * @res: pointer to an array of struct resource to be filled in - * - * Populate one or more empty struct resource pointed to by @res with - * the resource data for this omap_device @od. Used by - * omap_device_build_ss() after calling omap_device_count_resources(). - * Ideally this function would not be needed at all. If omap_device - * replaces platform_device, then we can specify our own - * get_resource()/ get_irq()/etc functions that use the underlying - * omap_hwmod information. Or if platform_device is extended to use - * subarchitecture-specific function pointers, the various - * platform_device functions can simply call omap_device internal - * functions to get device resources. Hacking around the existing - * platform_device code wastes memory. Returns 0. - */ -static int omap_device_fill_resources(struct omap_device *od, - struct resource *res) -{ - int i, r; - - for (i = 0; i < od->hwmods_cnt; i++) { - r = omap_hwmod_fill_resources(od->hwmods[i], res); - res += r; - } - - return 0; -} - -/** - * _od_fill_dma_resources - fill in array of struct resource with dma resources - * @od: struct omap_device * - * @res: pointer to an array of struct resource to be filled in - * - * Populate one or more empty struct resource pointed to by @res with - * the dma resource data for this omap_device @od. Used by - * omap_device_alloc() after calling omap_device_count_resources(). - * - * Ideally this function would not be needed at all. If we have - * mechanism to get dma resources from DT. - * - * Returns 0. - */ -static int _od_fill_dma_resources(struct omap_device *od, - struct resource *res) -{ - int i, r; - - for (i = 0; i < od->hwmods_cnt; i++) { - r = omap_hwmod_fill_dma_resources(od->hwmods[i], res); - res += r; - } - - return 0; -} - -/** * omap_device_alloc - allocate an omap_device * @pdev: platform_device that will be included in this omap_device * @oh: ptr to the single omap_hwmod that backs this omap_device @@ -407,8 +327,7 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, { int ret = -ENOMEM; struct omap_device *od; - struct resource *res = NULL; - int i, res_count; + int i; struct omap_hwmod **hwmods; od = kzalloc(sizeof(struct omap_device), GFP_KERNEL); @@ -424,74 +343,6 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, od->hwmods = hwmods; od->pdev = pdev; - - /* - * Non-DT Boot: - * Here, pdev->num_resources = 0, and we should get all the - * resources from hwmod. - * - * DT Boot: - * OF framework will construct the resource structure (currently - * does for MEM & IRQ resource) and we should respect/use these - * resources, killing hwmod dependency. - * If pdev->num_resources > 0, we assume that MEM & IRQ resources - * have been allocated by OF layer already (through DTB). - * As preparation for the future we examine the OF provided resources - * to see if we have DMA resources provided already. In this case - * there is no need to update the resources for the device, we use the - * OF provided ones. - * - * TODO: Once DMA resource is available from OF layer, we should - * kill filling any resources from hwmod. - */ - if (!pdev->num_resources) { - /* Count all resources for the device */ - res_count = omap_device_count_resources(od, IORESOURCE_IRQ | - IORESOURCE_DMA | - IORESOURCE_MEM); - } else { - /* Take a look if we already have DMA resource via DT */ - for (i = 0; i < pdev->num_resources; i++) { - struct resource *r = &pdev->resource[i]; - - /* We have it, no need to touch the resources */ - if (r->flags == IORESOURCE_DMA) - goto have_everything; - } - /* Count only DMA resources for the device */ - res_count = omap_device_count_resources(od, IORESOURCE_DMA); - /* The device has no DMA resource, no need for update */ - if (!res_count) - goto have_everything; - - res_count += pdev->num_resources; - } - - /* Allocate resources memory to account for new resources */ - res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); - if (!res) - goto oda_exit3; - - if (!pdev->num_resources) { - dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n", - __func__, res_count); - omap_device_fill_resources(od, res); - } else { - dev_dbg(&pdev->dev, - "%s: appending %d DMA resources from hwmod\n", - __func__, res_count - pdev->num_resources); - memcpy(res, pdev->resource, - sizeof(struct resource) * pdev->num_resources); - _od_fill_dma_resources(od, &res[pdev->num_resources]); - } - - ret = platform_device_add_resources(pdev, res, res_count); - kfree(res); - - if (ret) - goto oda_exit3; - -have_everything: pdev->archdata.od = od; for (i = 0; i < oh_cnt; i++) { @@ -501,8 +352,6 @@ have_everything: return od; -oda_exit3: - kfree(hwmods); oda_exit2: kfree(od); oda_exit1: @@ -522,6 +371,93 @@ void omap_device_delete(struct omap_device *od) } /** + * omap_device_copy_resources - Add legacy IO and IRQ resources + * @oh: interconnect target module + * @pdev: platform device to copy resources to + * + * We still have legacy DMA and smartreflex needing resources. + * Let's populate what they need until we can eventually just + * remove this function. Note that there should be no need to + * call this from omap_device_build_from_dt(), nor should there + * be any need to call it for other devices. + */ +static int +omap_device_copy_resources(struct omap_hwmod *oh, + struct platform_device *pdev) +{ + struct device_node *np, *child; + struct property *prop; + struct resource *res; + const char *name; + int error, irq = 0; + + if (!oh || !oh->od || !oh->od->pdev) { + error = -EINVAL; + goto error; + } + + np = oh->od->pdev->dev.of_node; + if (!np) { + error = -ENODEV; + goto error; + } + + res = kzalloc(sizeof(*res) * 2, GFP_KERNEL); + if (!res) + return -ENOMEM; + + /* Do we have a dts range for the interconnect target module? */ + error = omap_hwmod_parse_module_range(oh, np, res); + + /* No ranges, rely on device reg entry */ + if (error) + error = of_address_to_resource(np, 0, res); + if (error) + goto free; + + /* SmartReflex needs first IO resource name to be "mpu" */ + res[0].name = "mpu"; + + /* + * We may have a configured "ti,sysc" interconnect target with a + * dts child with the interrupt. If so use the first child's + * first interrupt for "ti-hwmods" legacy support. + */ + of_property_for_each_string(np, "compatible", prop, name) + if (!strncmp("ti,sysc-", name, 8)) + break; + + child = of_get_next_available_child(np, NULL); + + if (name) + irq = irq_of_parse_and_map(child, 0); + if (!irq) + irq = irq_of_parse_and_map(np, 0); + if (!irq) { + error = -EINVAL; + goto free; + } + + /* Legacy DMA code needs interrupt name to be "0" */ + res[1].start = irq; + res[1].end = irq; + res[1].flags = IORESOURCE_IRQ; + res[1].name = "0"; + + error = platform_device_add_resources(pdev, res, 2); + +free: + kfree(res); + +error: + WARN(error, "%s: %s device %s failed: %i\n", + __func__, oh->name, dev_name(&pdev->dev), + error); + + return error; +} + +/** * omap_device_build - build and register an omap_device with one omap_hwmod * @pdev_name: name of the platform_device driver to use * @pdev_id: this platform_device's connection ID @@ -540,45 +476,24 @@ struct platform_device __init *omap_device_build(const char *pdev_name, struct omap_hwmod *oh, void *pdata, int pdata_len) { - struct omap_hwmod *ohs[] = { oh }; - - if (!oh) - return ERR_PTR(-EINVAL); - - return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata, - pdata_len); -} - -/** - * omap_device_build_ss - build and register an omap_device with multiple hwmods - * @pdev_name: name of the platform_device driver to use - * @pdev_id: this platform_device's connection ID - * @oh: ptr to the single omap_hwmod that backs this omap_device - * @pdata: platform_data ptr to associate with the platform_device - * @pdata_len: amount of memory pointed to by @pdata - * - * Convenience function for building and registering an omap_device - * subsystem record. Subsystem records consist of multiple - * omap_hwmods. This function in turn builds and registers a - * platform_device record. Returns an ERR_PTR() on error, or passes - * along the return value of omap_device_register(). - */ -struct platform_device __init *omap_device_build_ss(const char *pdev_name, - int pdev_id, - struct omap_hwmod **ohs, - int oh_cnt, void *pdata, - int pdata_len) -{ int ret = -ENOMEM; struct platform_device *pdev; struct omap_device *od; - if (!ohs || oh_cnt == 0 || !pdev_name) + if (!oh || !pdev_name) return ERR_PTR(-EINVAL); if (!pdata && pdata_len > 0) return ERR_PTR(-EINVAL); + if (strncmp(oh->name, "smartreflex", 11) && + strncmp(oh->name, "dma", 3)) { + pr_warn("%s need to update %s to probe with dt\na", + __func__, pdev_name); + ret = -ENODEV; + goto odbs_exit; + } + pdev = platform_device_alloc(pdev_name, pdev_id); if (!pdev) { ret = -ENOMEM; @@ -591,7 +506,16 @@ struct platform_device __init *omap_device_build_ss(const char *pdev_name, else dev_set_name(&pdev->dev, "%s", pdev->name); - od = omap_device_alloc(pdev, ohs, oh_cnt); + /* + * Must be called before omap_device_alloc() as oh->od + * only contains the currently registered omap_device + * and will get overwritten by omap_device_alloc(). + */ + ret = omap_device_copy_resources(oh, pdev); + if (ret) + goto odbs_exit1; + + od = omap_device_alloc(pdev, &oh, 1); if (IS_ERR(od)) goto odbs_exit1; diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h index 78c02b355179..786b9c00fdb9 100644 --- a/arch/arm/mach-omap2/omap_device.h +++ b/arch/arm/mach-omap2/omap_device.h @@ -75,10 +75,6 @@ struct platform_device *omap_device_build(const char *pdev_name, int pdev_id, struct omap_hwmod *oh, void *pdata, int pdata_len); -struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id, - struct omap_hwmod **oh, int oh_cnt, - void *pdata, int pdata_len); - struct omap_device *omap_device_alloc(struct platform_device *pdev, struct omap_hwmod **ohs, int oh_cnt); void omap_device_delete(struct omap_device *od); diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index d50101d44795..104256a5f0f7 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1102,215 +1102,6 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh) } /** - * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh - * @oh: struct omap_hwmod *oh - * - * Count and return the number of MPU IRQs associated with the hwmod - * @oh. Used to allocate struct resource data. Returns 0 if @oh is - * NULL. - */ -static int _count_mpu_irqs(struct omap_hwmod *oh) -{ - struct omap_hwmod_irq_info *ohii; - int i = 0; - - if (!oh || !oh->mpu_irqs) - return 0; - - do { - ohii = &oh->mpu_irqs[i++]; - } while (ohii->irq != -1); - - return i-1; -} - -/** - * _count_sdma_reqs - count the number of SDMA request lines associated with @oh - * @oh: struct omap_hwmod *oh - * - * Count and return the number of SDMA request lines associated with - * the hwmod @oh. Used to allocate struct resource data. Returns 0 - * if @oh is NULL. - */ -static int _count_sdma_reqs(struct omap_hwmod *oh) -{ - struct omap_hwmod_dma_info *ohdi; - int i = 0; - - if (!oh || !oh->sdma_reqs) - return 0; - - do { - ohdi = &oh->sdma_reqs[i++]; - } while (ohdi->dma_req != -1); - - return i-1; -} - -/** - * _count_ocp_if_addr_spaces - count the number of address space entries for @oh - * @oh: struct omap_hwmod *oh - * - * Count and return the number of address space ranges associated with - * the hwmod @oh. Used to allocate struct resource data. Returns 0 - * if @oh is NULL. - */ -static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os) -{ - struct omap_hwmod_addr_space *mem; - int i = 0; - - if (!os || !os->addr) - return 0; - - do { - mem = &os->addr[i++]; - } while (mem->pa_start != mem->pa_end); - - return i-1; -} - -/** - * _get_mpu_irq_by_name - fetch MPU interrupt line number by name - * @oh: struct omap_hwmod * to operate on - * @name: pointer to the name of the MPU interrupt number to fetch (optional) - * @irq: pointer to an unsigned int to store the MPU IRQ number to - * - * Retrieve a MPU hardware IRQ line number named by @name associated - * with the IP block pointed to by @oh. The IRQ number will be filled - * into the address pointed to by @dma. When @name is non-null, the - * IRQ line number 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_mpu_irq_by_name(struct omap_hwmod *oh, const char *name, - unsigned int *irq) -{ - int i; - bool found = false; - - if (!oh->mpu_irqs) - return -ENOENT; - - i = 0; - while (oh->mpu_irqs[i].irq != -1) { - if (name == oh->mpu_irqs[i].name || - !strcmp(name, oh->mpu_irqs[i].name)) { - found = true; - break; - } - i++; - } - - if (!found) - return -ENOENT; - - *irq = oh->mpu_irqs[i].irq; - - 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 j; - struct omap_hwmod_ocp_if *os; - bool found = false; - - list_for_each_entry(os, &oh->slave_ports, node) { - - 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 * * @@ -1361,32 +1152,6 @@ static struct omap_hwmod_ocp_if *_find_mpu_rt_port(struct omap_hwmod *oh) }; /** - * _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; - int found = 0, i = 0; - - os = _find_mpu_rt_port(oh); - if (!os || !os->addr) - return NULL; - - do { - mem = &os->addr[i++]; - if (mem->flags & ADDR_TYPE_RT) - found = 1; - } while (!found && mem->pa_start != mem->pa_end); - - return (found) ? mem : NULL; -} - -/** * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG * @oh: struct omap_hwmod * * @@ -2394,6 +2159,75 @@ static int of_dev_hwmod_lookup(struct device_node *np, } /** + * omap_hwmod_parse_module_range - map module IO range from device tree + * @oh: struct omap_hwmod * + * @np: struct device_node * + * + * Parse the device tree range an interconnect target module provides + * for it's child device IP blocks. This way we can support the old + * "ti,hwmods" property with just dts data without a need for platform + * data for IO resources. And we don't need all the child IP device + * nodes available in the dts. + */ +int omap_hwmod_parse_module_range(struct omap_hwmod *oh, + struct device_node *np, + struct resource *res) +{ + struct property *prop; + const __be32 *ranges; + const char *name; + u32 nr_addr, nr_size; + u64 base, size; + int len, error; + + if (!res) + return -EINVAL; + + ranges = of_get_property(np, "ranges", &len); + if (!ranges) + return -ENOENT; + + len /= sizeof(*ranges); + + if (len < 3) + return -EINVAL; + + of_property_for_each_string(np, "compatible", prop, name) + if (!strncmp("ti,sysc-", name, 8)) + break; + + if (!name) + return -ENOENT; + + error = of_property_read_u32(np, "#address-cells", &nr_addr); + if (error) + return -ENOENT; + + error = of_property_read_u32(np, "#size-cells", &nr_size); + if (error) + return -ENOENT; + + if (nr_addr != 1 || nr_size != 1) { + pr_err("%s: invalid range for %s->%s\n", __func__, + oh->name, np->name); + return -EINVAL; + } + + ranges++; + base = of_translate_address(np, ranges++); + size = be32_to_cpup(ranges); + + pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n", + oh->name, np->name, base, size); + + res->start = base; + res->end = base + size - 1; + res->flags = IORESOURCE_MEM; + + return 0; +} + +/** * _init_mpu_rt_base - populate the virtual address for a hwmod * @oh: struct omap_hwmod * to locate the virtual address * @data: (unused, caller should pass NULL) @@ -2413,8 +2247,9 @@ static int of_dev_hwmod_lookup(struct device_node *np, static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, int index, struct device_node *np) { - struct omap_hwmod_addr_space *mem; void __iomem *va_start = NULL; + struct resource res; + int error; if (!oh) return -EINVAL; @@ -2429,28 +2264,22 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, if (oh->_int_flags & _HWMOD_NO_MPU_PORT) return -ENXIO; - mem = _find_mpu_rt_addr_space(oh); - if (!mem) { - pr_debug("omap_hwmod: %s: no MPU register target found\n", - oh->name); + if (!np) { + pr_err("omap_hwmod: %s: no dt node\n", oh->name); + return -ENXIO; + } - /* Extract the IO space from device tree blob */ - if (!np) { - pr_err("omap_hwmod: %s: no dt node\n", oh->name); - return -ENXIO; - } + /* Do we have a dts range for the interconnect target module? */ + error = omap_hwmod_parse_module_range(oh, np, &res); + if (!error) + va_start = ioremap(res.start, resource_size(&res)); + /* No ranges, rely on device reg entry */ + if (!va_start) va_start = of_iomap(np, index + oh->mpu_rt_idx); - } else { - va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); - } - if (!va_start) { - if (mem) - pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name); - else - pr_err("omap_hwmod: %s: Missing dt reg%i for %pOF\n", - oh->name, index, np); + pr_err("omap_hwmod: %s: Missing dt reg%i for %pOF\n", + oh->name, index, np); return -ENXIO; } @@ -3355,189 +3184,6 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh) */ /** - * 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) - *< |