Skip to content

Commit

Permalink
gpu: host1x: Add host1x driver
Browse files Browse the repository at this point in the history
Add host1x, the driver for host1x and its client unit 2D. The Tegra
host1x module is the DMA engine for register access to Tegra's
graphics- and multimedia-related modules. The modules served by
host1x are referred to as clients. host1x includes some other
functionality, such as synchronization.

Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Erik Faye-Lund <kusmabite@gmail.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
  • Loading branch information
Terje Bergstrom authored and Thierry Reding committed Apr 22, 2013
1 parent e1adc78 commit 7547168
Show file tree
Hide file tree
Showing 15 changed files with 957 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/Makefile
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
obj-y += drm/ vga/
obj-$(CONFIG_TEGRA_HOST1X) += host1x/
10 changes: 10 additions & 0 deletions drivers/gpu/host1x/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
config TEGRA_HOST1X
tristate "NVIDIA Tegra host1x driver"
depends on ARCH_TEGRA || ARCH_MULTIPLATFORM
help
Driver for the NVIDIA Tegra host1x hardware.

The Tegra host1x module is the DMA engine for register access to
Tegra's graphics- and multimedia-related modules. The modules served
by host1x are referred to as clients. host1x includes some other
functionality, such as synchronization.
8 changes: 8 additions & 0 deletions drivers/gpu/host1x/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ccflags-y = -Idrivers/gpu/host1x

host1x-y = \
syncpt.o \
dev.o \
hw/host1x01.o

obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
153 changes: 153 additions & 0 deletions drivers/gpu/host1x/dev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Tegra host1x driver
*
* Copyright (c) 2010-2013, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/io.h>

#define CREATE_TRACE_POINTS
#include <trace/events/host1x.h>

#include "dev.h"
#include "hw/host1x01.h"

void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
{
void __iomem *sync_regs = host1x->regs + host1x->info->sync_offset;

writel(v, sync_regs + r);
}

u32 host1x_sync_readl(struct host1x *host1x, u32 r)
{
void __iomem *sync_regs = host1x->regs + host1x->info->sync_offset;

return readl(sync_regs + r);
}

static const struct host1x_info host1x01_info = {
.nb_channels = 8,
.nb_pts = 32,
.nb_mlocks = 16,
.nb_bases = 8,
.init = host1x01_init,
.sync_offset = 0x3000,
};

static struct of_device_id host1x_of_match[] = {
{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
{ .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
{ },
};
MODULE_DEVICE_TABLE(of, host1x_of_match);

static int host1x_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
struct host1x *host;
struct resource *regs;
int syncpt_irq;
int err;

id = of_match_device(host1x_of_match, &pdev->dev);
if (!id)
return -EINVAL;

regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
dev_err(&pdev->dev, "failed to get registers\n");
return -ENXIO;
}

syncpt_irq = platform_get_irq(pdev, 0);
if (syncpt_irq < 0) {
dev_err(&pdev->dev, "failed to get IRQ\n");
return -ENXIO;
}

host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
if (!host)
return -ENOMEM;

host->dev = &pdev->dev;
host->info = id->data;

/* set common host1x device data */
platform_set_drvdata(pdev, host);

host->regs = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(host->regs))
return PTR_ERR(host->regs);

if (host->info->init) {
err = host->info->init(host);
if (err)
return err;
}

host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
err = PTR_ERR(host->clk);
return err;
}

err = clk_prepare_enable(host->clk);
if (err < 0) {
dev_err(&pdev->dev, "failed to enable clock\n");
return err;
}

err = host1x_syncpt_init(host);
if (err) {
dev_err(&pdev->dev, "failed to initialize syncpts\n");
return err;
}

return 0;
}

static int __exit host1x_remove(struct platform_device *pdev)
{
struct host1x *host = platform_get_drvdata(pdev);

host1x_syncpt_deinit(host);
clk_disable_unprepare(host->clk);

return 0;
}

static struct platform_driver platform_driver = {
.probe = host1x_probe,
.remove = __exit_p(host1x_remove),
.driver = {
.owner = THIS_MODULE,
.name = "tegra-host1x",
.of_match_table = host1x_of_match,
},
};

module_platform_driver(platform_driver);

MODULE_AUTHOR("Terje Bergstrom <tbergstrom@nvidia.com>");
MODULE_DESCRIPTION("Host1x driver for Tegra products");
MODULE_LICENSE("GPL");
96 changes: 96 additions & 0 deletions drivers/gpu/host1x/dev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2012-2013, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef HOST1X_DEV_H
#define HOST1X_DEV_H

#include <linux/platform_device.h>
#include <linux/device.h>

#include "syncpt.h"

struct host1x_syncpt;

struct host1x_syncpt_ops {
void (*restore)(struct host1x_syncpt *syncpt);
void (*restore_wait_base)(struct host1x_syncpt *syncpt);
void (*load_wait_base)(struct host1x_syncpt *syncpt);
u32 (*load)(struct host1x_syncpt *syncpt);
void (*cpu_incr)(struct host1x_syncpt *syncpt);
int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr);
};

struct host1x_info {
int nb_channels; /* host1x: num channels supported */
int nb_pts; /* host1x: num syncpoints supported */
int nb_bases; /* host1x: num syncpoints supported */
int nb_mlocks; /* host1x: number of mlocks */
int (*init)(struct host1x *); /* initialize per SoC ops */
int sync_offset;
};

struct host1x {
const struct host1x_info *info;

void __iomem *regs;
struct host1x_syncpt *syncpt;
struct device *dev;
struct clk *clk;

const struct host1x_syncpt_ops *syncpt_op;
};

void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v);
u32 host1x_sync_readl(struct host1x *host1x, u32 r);

static inline void host1x_hw_syncpt_restore(struct host1x *host,
struct host1x_syncpt *sp)
{
host->syncpt_op->restore(sp);
}

static inline void host1x_hw_syncpt_restore_wait_base(struct host1x *host,
struct host1x_syncpt *sp)
{
host->syncpt_op->restore_wait_base(sp);
}

static inline void host1x_hw_syncpt_load_wait_base(struct host1x *host,
struct host1x_syncpt *sp)
{
host->syncpt_op->load_wait_base(sp);
}

static inline u32 host1x_hw_syncpt_load(struct host1x *host,
struct host1x_syncpt *sp)
{
return host->syncpt_op->load(sp);
}

static inline void host1x_hw_syncpt_cpu_incr(struct host1x *host,
struct host1x_syncpt *sp)
{
host->syncpt_op->cpu_incr(sp);
}

static inline int host1x_hw_syncpt_patch_wait(struct host1x *host,
struct host1x_syncpt *sp,
void *patch_addr)
{
return host->syncpt_op->patch_wait(sp, patch_addr);
}

#endif
6 changes: 6 additions & 0 deletions drivers/gpu/host1x/hw/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ccflags-y = -Idrivers/gpu/host1x

host1x-hw-objs = \
host1x01.o

obj-$(CONFIG_TEGRA_HOST1X) += host1x-hw.o
33 changes: 33 additions & 0 deletions drivers/gpu/host1x/hw/host1x01.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Host1x init for T20 and T30 Architecture Chips
*
* Copyright (c) 2011-2013, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* include hw specification */
#include "hw/host1x01.h"
#include "hw/host1x01_hardware.h"

/* include code */
#include "hw/syncpt_hw.c"

#include "dev.h"

int host1x01_init(struct host1x *host)
{
host->syncpt_op = &host1x_syncpt_ops;

return 0;
}
25 changes: 25 additions & 0 deletions drivers/gpu/host1x/hw/host1x01.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Host1x init for T20 and T30 Architecture Chips
*
* Copyright (c) 2011-2013, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HOST1X_HOST1X01_H
#define HOST1X_HOST1X01_H

struct host1x;

int host1x01_init(struct host1x *host);

#endif /* HOST1X_HOST1X01_H_ */
27 changes: 27 additions & 0 deletions drivers/gpu/host1x/hw/host1x01_hardware.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Tegra host1x Register Offsets for Tegra20 and Tegra30
*
* Copyright (c) 2010-2013 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __HOST1X_HOST1X01_HARDWARE_H
#define __HOST1X_HOST1X01_HARDWARE_H

#include <linux/types.h>
#include <linux/bitops.h>

#include "hw_host1x01_sync.h"

#endif
Loading

0 comments on commit 7547168

Please sign in to comment.