diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index db971802378cc..63d410a0aece5 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -24,6 +24,8 @@ Optional properties: - ti,no-reset-on-init: When present, the module should not be reset at init - ti,no-idle-on-init: When present, the module should not be idled at init - ti,no-idle: When present, the module is never allowed to idle. +- ti,deassert-hard-reset: list of hwmod and hardware reset line name pairs + (ascii strings) to be deasserted upon device instantiation. Example: diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 17824aefc1da1..8e79bd9f0d6b0 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -584,6 +584,17 @@ ti,timer-pwm; }; + pruss: pruss@4a300000 { + compatible = "ti,pruss-v2"; + ti,hwmods = "pruss"; + ti,deassert-hard-reset = "pruss", "pruss"; + reg = <0x4a300000 0x080000>; + ti,pintc-offset = <0x20000>; + interrupt-parent = <&intc>; + status = "disabled"; + interrupts = <20 21 22 23 24 25 26 27>; + }; + rtc: rtc@44e3e000 { compatible = "ti,am3352-rtc", "ti,da830-rtc"; reg = <0x44e3e000 0x1000>; diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index bd9882d213fee..38444e5917a50 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -138,8 +138,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev) struct omap_device *od; struct omap_hwmod *oh; struct device_node *node = pdev->dev.of_node; - const char *oh_name; - int oh_cnt, i, ret = 0; + const char *oh_name, *rst_name; + int oh_cnt, dstr_cnt, i, ret = 0; bool device_active = false; oh_cnt = of_property_count_strings(node, "ti,hwmods"); @@ -190,6 +190,26 @@ static int omap_device_build_from_dt(struct platform_device *pdev) omap_device_enable(pdev); pm_runtime_set_active(&pdev->dev); } + dstr_cnt = + of_property_count_strings(node, "ti,deassert-hard-reset"); + if (dstr_cnt > 0) { + for (i = 0; i < dstr_cnt; i += 2) { + of_property_read_string_index( + node, "ti,deassert-hard-reset", i, + &oh_name); + of_property_read_string_index( + node, "ti,deassert-hard-reset", i+1, + &rst_name); + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + dev_warn(&pdev->dev, + "Cannot parse deassert property for '%s'\n", + oh_name); + break; + } + omap_hwmod_deassert_hardreset(oh, rst_name); + } + } odbfd_exit1: kfree(hwmods); diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 7e8dc78a97961..e0c68acc1d941 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -129,7 +129,7 @@ config UIO_PRUSS select GENERIC_ALLOCATOR depends on HAS_IOMEM && HAS_DMA help - PRUSS driver for OMAPL138/DA850/AM18XX devices + PRUSS driver for OMAPL138/DA850/AM18XX and AM33XX devices PRUSS driver requires user space components, examples and user space driver is available from below SVN repo - you may use anonymous login diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c index 31d5b1d3b5af6..dbe8ec8d2faff 100644 --- a/drivers/uio/uio_pruss.c +++ b/drivers/uio/uio_pruss.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,11 @@ #include #include #include +#include +#include +#include +#include +#include #define DRV_NAME "pruss_uio" #define DRV_VERSION "1.0" @@ -106,10 +112,12 @@ static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev) dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr, gdev->ddr_paddr); } +#ifdef CONFIG_ARCH_DAVINCI_DA850 if (gdev->sram_vaddr) gen_pool_free(gdev->sram_pool, gdev->sram_vaddr, sram_pool_sz); +#endif kfree(gdev->info); clk_disable(gdev->pruss_clk); clk_put(gdev->pruss_clk); @@ -121,9 +129,15 @@ static int pruss_probe(struct platform_device *pdev) struct uio_info *p; struct uio_pruss_dev *gdev; struct resource *regs_prussio; + struct resource res; struct device *dev = &pdev->dev; int ret = -ENODEV, cnt = 0, len; struct uio_pruss_pdata *pdata = dev_get_platdata(dev); + struct pinctrl *pinctrl; + + int count; + struct device_node *child; + const char *pin_name; gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL); if (!gdev) @@ -134,7 +148,7 @@ static int pruss_probe(struct platform_device *pdev) kfree(gdev); return -ENOMEM; } - +#ifdef CONFIG_ARCH_DAVINCI_DA850 /* Power on PRU in case its not done as part of boot-loader */ gdev->pruss_clk = clk_get(dev, "pruss"); if (IS_ERR(gdev->pruss_clk)) { @@ -153,8 +167,25 @@ static int pruss_probe(struct platform_device *pdev) return ret; } } +#endif + + if (pdev->dev.of_node) { + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (IS_ERR_VALUE(ret)) { + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); + return ret; + } - regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ret = of_address_to_resource(pdev->dev.of_node, 0, &res); + if (IS_ERR_VALUE(ret)) { + dev_err(&pdev->dev, "failed to parse DT reg\n"); + return ret; + } + regs_prussio = &res; + } + else + regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs_prussio) { dev_err(dev, "No PRUSS I/O resource specified\n"); goto out_free; @@ -165,7 +196,50 @@ static int pruss_probe(struct platform_device *pdev) goto out_free; } - if (pdata->sram_pool) { + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_warn(&pdev->dev, + "pins are not configured from the driver\n"); + else{ + count = of_get_child_count(pdev->dev.of_node); + if (!count){ + dev_info(&pdev->dev, "No children\n"); + return -ENODEV; + } + // Run through all children. They have lables for easy reference. + for_each_child_of_node(pdev->dev.of_node, child){ + enum of_gpio_flags flags; + unsigned gpio; + + count = of_gpio_count(child); + + ret = of_property_count_strings(child, "pin-names"); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get pin-names\n"); + continue; + } + if(count != ret){ + dev_err(&pdev->dev, "The number of gpios (%d) does not match"\ + " the number of pin names (%d)\n", count, ret); + continue; + } + + for(cnt=0; cntdev, "Error on pin-name #%d\n", cnt); + gpio = of_get_gpio_flags(child, cnt, &flags); + ret = devm_gpio_request_one(&pdev->dev, gpio, flags, pin_name); + if (ret < 0) { + dev_err(dev, "Failed to request GPIO %d (%s) flags: '%d', error %d\n", + gpio, pin_name, flags, ret); + } + } + } + } + if (pdata && pdata->sram_pool) { gdev->sram_pool = pdata->sram_pool; gdev->sram_vaddr = (unsigned long)gen_pool_dma_alloc(gdev->sram_pool, @@ -190,7 +264,17 @@ static int pruss_probe(struct platform_device *pdev) goto out_free; } - gdev->pintc_base = pdata->pintc_base; + if (pdev->dev.of_node) { + ret = of_property_read_u32(pdev->dev.of_node, + "ti,pintc-offset", + &gdev->pintc_base); + if (ret < 0) { + dev_err(&pdev->dev, + "Can't parse ti,pintc-offset property\n"); + goto out_free; + } + } else + gdev->pintc_base = pdata->pintc_base; gdev->hostirq_start = platform_get_irq(pdev, 0); for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) { @@ -198,6 +282,7 @@ static int pruss_probe(struct platform_device *pdev) p->mem[0].size = resource_size(regs_prussio); p->mem[0].memtype = UIO_MEM_PHYS; +#ifdef CONFIG_ARCH_DAVINCI_DA850 p->mem[1].addr = gdev->sram_paddr; p->mem[1].size = sram_pool_sz; p->mem[1].memtype = UIO_MEM_PHYS; @@ -205,7 +290,11 @@ static int pruss_probe(struct platform_device *pdev) p->mem[2].addr = gdev->ddr_paddr; p->mem[2].size = extram_pool_sz; p->mem[2].memtype = UIO_MEM_PHYS; - +#else + p->mem[1].addr = gdev->ddr_paddr; + p->mem[1].size = extram_pool_sz; + p->mem[1].memtype = UIO_MEM_PHYS; +#endif p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt); p->version = DRV_VERSION; @@ -235,11 +324,20 @@ static int pruss_remove(struct platform_device *dev) return 0; } +static const struct of_device_id pruss_dt_ids[] = { + { .compatible = "ti,pruss-v1", .data = NULL, }, + { .compatible = "ti,pruss-v2", .data = NULL, }, + {}, +}; +MODULE_DEVICE_TABLE(of, pruss_dt_ids); + + static struct platform_driver pruss_driver = { .probe = pruss_probe, .remove = pruss_remove, .driver = { .name = DRV_NAME, + .of_match_table = pruss_dt_ids, }, };