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 Jan 14, 2016
1 parent 0bfec99 commit 7f412be
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 9 deletions.
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/arm/omap/omap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ 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
24 changes: 22 additions & 2 deletions arch/arm/mach-omap2/omap_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,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 @@ -180,6 +180,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
4 changes: 2 additions & 2 deletions drivers/uio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ config UIO_FSL_ELBC_GPCM_NETX5152

config UIO_PRUSS
tristate "Texas Instruments PRUSS driver"
depends on ARCH_DAVINCI_DA850
depends on ARCH_DAVINCI_DA850 || SOC_AM33XX
select GENERIC_ALLOCATOR
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
105 changes: 100 additions & 5 deletions drivers/uio/uio_pruss.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@
#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>
#include <linux/clk.h>
#include <linux/dma-mapping.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 @@ -105,10 +111,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_put(gdev->pruss_clk);
kfree(gdev);
Expand All @@ -119,9 +127,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 @@ -132,7 +146,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 @@ -144,8 +158,25 @@ static int pruss_probe(struct platform_device *pdev)
} else {
clk_enable(gdev->pruss_clk);
}
#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 @@ -156,7 +187,47 @@ 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;
}

dev_err(&pdev->dev, "Child has %u gpios\n", count);
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 (pdata && pdata->sram_pool) {
gdev->sram_pool = pdata->sram_pool;
gdev->sram_vaddr =
(unsigned long)gen_pool_dma_alloc(gdev->sram_pool,
Expand All @@ -181,22 +252,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 @@ -226,11 +312,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 7f412be

Please sign in to comment.