Skip to content

Commit

Permalink
Making the uio pruss driver work
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasbakken authored and RobertCNelson committed Oct 20, 2018
1 parent 46a8da6 commit a37c376
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 8 deletions.
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/arm/omap/omap.txt
Expand Up @@ -24,6 +24,8 @@ Optional properties:
- ti,no-reset-on-init: When present, the module should not be reset at init - 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-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,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: Example:


Expand Down
11 changes: 11 additions & 0 deletions arch/arm/boot/dts/am33xx.dtsi
Expand Up @@ -584,6 +584,17 @@
ti,timer-pwm; 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 { rtc: rtc@44e3e000 {
compatible = "ti,am3352-rtc", "ti,da830-rtc"; compatible = "ti,am3352-rtc", "ti,da830-rtc";
reg = <0x44e3e000 0x1000>; reg = <0x44e3e000 0x1000>;
Expand Down
24 changes: 22 additions & 2 deletions arch/arm/mach-omap2/omap_device.c
Expand Up @@ -138,8 +138,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
struct omap_device *od; struct omap_device *od;
struct omap_hwmod *oh; struct omap_hwmod *oh;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
const char *oh_name; const char *oh_name, *rst_name;
int oh_cnt, i, ret = 0; int oh_cnt, dstr_cnt, i, ret = 0;
bool device_active = false; bool device_active = false;


oh_cnt = of_property_count_strings(node, "ti,hwmods"); oh_cnt = of_property_count_strings(node, "ti,hwmods");
Expand Down Expand Up @@ -190,6 +190,26 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
omap_device_enable(pdev); omap_device_enable(pdev);
pm_runtime_set_active(&pdev->dev); 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: odbfd_exit1:
kfree(hwmods); kfree(hwmods);
Expand Down
2 changes: 1 addition & 1 deletion drivers/uio/Kconfig
Expand Up @@ -129,7 +129,7 @@ config UIO_PRUSS
select GENERIC_ALLOCATOR select GENERIC_ALLOCATOR
depends on HAS_IOMEM && HAS_DMA depends on HAS_IOMEM && HAS_DMA
help 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 PRUSS driver requires user space components, examples and user space
driver is available from below SVN repo - you may use anonymous login driver is available from below SVN repo - you may use anonymous login


Expand Down
108 changes: 103 additions & 5 deletions drivers/uio/uio_pruss.c
Expand Up @@ -19,6 +19,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/uio_driver.h> #include <linux/uio_driver.h>
#include <linux/platform_data/uio_pruss.h> #include <linux/platform_data/uio_pruss.h>
#include <linux/io.h> #include <linux/io.h>
Expand All @@ -27,6 +28,11 @@
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/genalloc.h> #include <linux/genalloc.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/err.h>
#include <linux/pm_runtime.h>


#define DRV_NAME "pruss_uio" #define DRV_NAME "pruss_uio"
#define DRV_VERSION "1.0" #define DRV_VERSION "1.0"
Expand Down Expand Up @@ -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, dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr,
gdev->ddr_paddr); gdev->ddr_paddr);
} }
#ifdef CONFIG_ARCH_DAVINCI_DA850
if (gdev->sram_vaddr) if (gdev->sram_vaddr)
gen_pool_free(gdev->sram_pool, gen_pool_free(gdev->sram_pool,
gdev->sram_vaddr, gdev->sram_vaddr,
sram_pool_sz); sram_pool_sz);
#endif
kfree(gdev->info); kfree(gdev->info);
clk_disable(gdev->pruss_clk); clk_disable(gdev->pruss_clk);
clk_put(gdev->pruss_clk); clk_put(gdev->pruss_clk);
Expand All @@ -121,9 +129,15 @@ static int pruss_probe(struct platform_device *pdev)
struct uio_info *p; struct uio_info *p;
struct uio_pruss_dev *gdev; struct uio_pruss_dev *gdev;
struct resource *regs_prussio; struct resource *regs_prussio;
struct resource res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret = -ENODEV, cnt = 0, len; int ret = -ENODEV, cnt = 0, len;
struct uio_pruss_pdata *pdata = dev_get_platdata(dev); 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); gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
if (!gdev) if (!gdev)
Expand All @@ -134,7 +148,7 @@ static int pruss_probe(struct platform_device *pdev)
kfree(gdev); kfree(gdev);
return -ENOMEM; return -ENOMEM;
} }

#ifdef CONFIG_ARCH_DAVINCI_DA850
/* Power on PRU in case its not done as part of boot-loader */ /* Power on PRU in case its not done as part of boot-loader */
gdev->pruss_clk = clk_get(dev, "pruss"); gdev->pruss_clk = clk_get(dev, "pruss");
if (IS_ERR(gdev->pruss_clk)) { if (IS_ERR(gdev->pruss_clk)) {
Expand All @@ -153,8 +167,25 @@ static int pruss_probe(struct platform_device *pdev)
return ret; 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) { if (!regs_prussio) {
dev_err(dev, "No PRUSS I/O resource specified\n"); dev_err(dev, "No PRUSS I/O resource specified\n");
goto out_free; goto out_free;
Expand All @@ -165,7 +196,50 @@ static int pruss_probe(struct platform_device *pdev)
goto out_free; 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; cnt<count; cnt++){
ret = of_property_read_string_index(child,
"pin-names", cnt, &pin_name);
if (ret != 0)
dev_err(&pdev->dev, "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_pool = pdata->sram_pool;
gdev->sram_vaddr = gdev->sram_vaddr =
(unsigned long)gen_pool_dma_alloc(gdev->sram_pool, (unsigned long)gen_pool_dma_alloc(gdev->sram_pool,
Expand All @@ -190,22 +264,37 @@ static int pruss_probe(struct platform_device *pdev)
goto out_free; 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); gdev->hostirq_start = platform_get_irq(pdev, 0);


for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) { for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
p->mem[0].addr = regs_prussio->start; p->mem[0].addr = regs_prussio->start;
p->mem[0].size = resource_size(regs_prussio); p->mem[0].size = resource_size(regs_prussio);
p->mem[0].memtype = UIO_MEM_PHYS; p->mem[0].memtype = UIO_MEM_PHYS;


#ifdef CONFIG_ARCH_DAVINCI_DA850
p->mem[1].addr = gdev->sram_paddr; p->mem[1].addr = gdev->sram_paddr;
p->mem[1].size = sram_pool_sz; p->mem[1].size = sram_pool_sz;
p->mem[1].memtype = UIO_MEM_PHYS; p->mem[1].memtype = UIO_MEM_PHYS;


p->mem[2].addr = gdev->ddr_paddr; p->mem[2].addr = gdev->ddr_paddr;
p->mem[2].size = extram_pool_sz; p->mem[2].size = extram_pool_sz;
p->mem[2].memtype = UIO_MEM_PHYS; 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->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
p->version = DRV_VERSION; p->version = DRV_VERSION;


Expand Down Expand Up @@ -235,11 +324,20 @@ static int pruss_remove(struct platform_device *dev)
return 0; 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 = { static struct platform_driver pruss_driver = {
.probe = pruss_probe, .probe = pruss_probe,
.remove = pruss_remove, .remove = pruss_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = pruss_dt_ids,
}, },
}; };


Expand Down

0 comments on commit a37c376

Please sign in to comment.