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 Sep 13, 2018
1 parent eb2397a commit 22ab992
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-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:

Expand Down
11 changes: 11 additions & 0 deletions arch/arm/boot/dts/am33xx.dtsi
Expand Up @@ -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>;
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_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");
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/uio/Kconfig
Expand Up @@ -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

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/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/uio_driver.h>
#include <linux/platform_data/uio_pruss.h>
#include <linux/io.h>
Expand All @@ -27,6 +28,11 @@
#include <linux/sizes.h>
#include <linux/slab.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_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,
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);
Expand All @@ -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)
Expand All @@ -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)) {
Expand All @@ -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;
Expand All @@ -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; 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_vaddr =
(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;
}

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++) {
p->mem[0].addr = regs_prussio->start;
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;

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;

Expand Down Expand Up @@ -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,
},
};

Expand Down

0 comments on commit 22ab992

Please sign in to comment.