From: Erik Gilling Date: Mon, 30 Aug 2010 22:17:04 +0000 (-0700) Subject: HACK: host1x mega commit X-Git-Tag: firefly_0821_release~9834^2~619 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=15fde475646a9e7ee47f3c25dae8f2b052812ae2;p=firefly-linux-kernel-4.4.55.git HACK: host1x mega commit Change-Id: Ibf5d4d58c24ca4db26450bb7a5c68154ba73d7c5 --- diff --git a/arch/arm/mach-tegra/board-olympus.c b/arch/arm/mach-tegra/board-olympus.c index 4e9143158143..d754e21c795b 100644 --- a/arch/arm/mach-tegra/board-olympus.c +++ b/arch/arm/mach-tegra/board-olympus.c @@ -222,8 +222,55 @@ static struct platform_device tegra_gart_dev = { .resource = tegra_gart_resources }; +static struct resource tegra_grhost_resources[] = { + { + .start = TEGRA_HOST1X_BASE, + .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_DISPLAY_BASE, + .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_DISPLAY2_BASE, + .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_VI_BASE, + .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_ISP_BASE, + .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_MPE_BASE, + .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SYNCPT_THRESH_BASE, + .end = INT_SYNCPT_THRESH_BASE + INT_SYNCPT_THRESH_NR - 1, + .flags = IORESOURCE_IRQ, + }, + { + .start = INT_HOST1X_MPCORE_GENERAL, + .end = INT_HOST1X_MPCORE_GENERAL, + .flags = IORESOURCE_IRQ, + }, +}; - +static struct platform_device tegra_grhost_dev = { + .name = "tegra_grhost", + .id = -1, + .resource = tegra_grhost_resources, + .num_resources = ARRAY_SIZE(tegra_grhost_resources), +}; static struct platform_device *olympus_devices[] __initdata = { &debug_uart, @@ -240,6 +287,7 @@ static struct platform_device *olympus_devices[] __initdata = { &tegra_spi_device3, &tegra_spi_device4, &tegra_gart_dev, + &tegra_grhost_dev, }; extern struct tegra_sdhci_platform_data olympus_wifi_data; /* sdhci1 */ diff --git a/arch/arm/mach-tegra/board-stingray.c b/arch/arm/mach-tegra/board-stingray.c index 4bcb64b45150..8c501fef2773 100644 --- a/arch/arm/mach-tegra/board-stingray.c +++ b/arch/arm/mach-tegra/board-stingray.c @@ -525,6 +525,56 @@ static struct platform_device tegra_gart_dev = { .resource = tegra_gart_resources }; +static struct resource tegra_grhost_resources[] = { + { + .start = TEGRA_HOST1X_BASE, + .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_DISPLAY_BASE, + .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_DISPLAY2_BASE, + .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_VI_BASE, + .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_ISP_BASE, + .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TEGRA_MPE_BASE, + .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SYNCPT_THRESH_BASE, + .end = INT_SYNCPT_THRESH_BASE + INT_SYNCPT_THRESH_NR - 1, + .flags = IORESOURCE_IRQ, + }, + { + .start = INT_HOST1X_MPCORE_GENERAL, + .end = INT_HOST1X_MPCORE_GENERAL, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tegra_grhost_dev = { + .name = "tegra_grhost", + .id = -1, + .resource = tegra_grhost_resources, + .num_resources = ARRAY_SIZE(tegra_grhost_resources), +}; + static struct platform_device bcm4329_rfkill = { .name = "bcm4329_rfkill", .id = -1, @@ -586,6 +636,7 @@ static struct platform_device *stingray_devices[] __initdata = { &tegra_spi_device3, &tegra_spi_device4, &tegra_gart_dev, + &tegra_grhost_dev, &ram_console_device, &tegra_camera, &tegra_i2s_device1, diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index 189f26896c81..ac9c8b4e0615 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -157,6 +157,8 @@ struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win); void tegra_dc_enable(struct tegra_dc *dc); void tegra_dc_disable(struct tegra_dc *dc); +u32 tegra_dc_get_syncpt_id(struct tegra_dc *dc); + /* tegra_dc_update_windows and tegra_dc_sync_windows do not support windows * with differenct dcs in one call */ diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h index d79c6c89d056..766b590a1be7 100644 --- a/arch/arm/mach-tegra/include/mach/iomap.h +++ b/arch/arm/mach-tegra/include/mach/iomap.h @@ -26,6 +26,9 @@ #define TEGRA_IRAM_BASE 0x40000000 #define TEGRA_IRAM_SIZE SZ_256K +#define TEGRA_HOST1X_BASE 0x50000000 +#define TEGRA_HOST1X_SIZE 0x24000 + #define TEGRA_ARM_PERIF_BASE 0x50040000 #define TEGRA_ARM_PERIF_SIZE SZ_8K @@ -35,13 +38,21 @@ #define TEGRA_ARM_INT_DIST_BASE 0x50041000 #define TEGRA_ARM_INT_DIST_SIZE SZ_4K +#define TEGRA_MPE_BASE 0x54040000 +#define TEGRA_MPE_SIZE SZ_256K + +#define TEGRA_VI_BASE 0x54080000 +#define TEGRA_VI_SIZE SZ_256K + +#define TEGRA_ISP_BASE 0x54100000 +#define TEGRA_ISP_SIZE SZ_256K + #define TEGRA_DISPLAY_BASE 0x54200000 #define TEGRA_DISPLAY_SIZE SZ_256K #define TEGRA_DISPLAY2_BASE 0x54240000 #define TEGRA_DISPLAY2_SIZE SZ_256K - #define TEGRA_HDMI_BASE 0x54280000 #define TEGRA_HDMI_SIZE SZ_256K diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h index 9c2da0ec7759..2352c2c77b61 100644 --- a/arch/arm/mach-tegra/include/mach/irqs.h +++ b/arch/arm/mach-tegra/include/mach/irqs.h @@ -168,8 +168,11 @@ #define INT_MAIN_NR (INT_QUAD_BASE + 32 - INT_PRI_BASE) -#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR) +#define INT_SYNCPT_THRESH_BASE (INT_QUAD_BASE + 32) +#define INT_SYNCPT_THRESH_NR 32 +#define INT_GPIO_BASE (INT_SYNCPT_THRESH_BASE + \ + INT_SYNCPT_THRESH_NR) #define INT_GPIO_NR (28 * 8) #define FIQ_START INT_GIC_BASE diff --git a/arch/arm/mach-tegra/include/mach/vmalloc.h b/arch/arm/mach-tegra/include/mach/vmalloc.h index db488e890b9e..af56a1cf3fac 100644 --- a/arch/arm/mach-tegra/include/mach/vmalloc.h +++ b/arch/arm/mach-tegra/include/mach/vmalloc.h @@ -1,3 +1,4 @@ + /* * arch/arm/mach-tegra/include/mach/vmalloc.h * diff --git a/arch/arm/mach-tegra/nv/nvmap.c b/arch/arm/mach-tegra/nv/nvmap.c index febd416942c3..4fae80a6ce40 100644 --- a/arch/arm/mach-tegra/nv/nvmap.c +++ b/arch/arm/mach-tegra/nv/nvmap.c @@ -3321,10 +3321,6 @@ static u32 nvmap_get_physaddr(struct nvmap_handle *h) { u32 addr; - if (unlikely(!atomic_add_return(0, &h->pin))) { - WARN_ON(1); - return ~0ul; - } if (h->heap_pgalloc && h->pgalloc.contig) { addr = page_to_phys(h->pgalloc.pages[0]); } else if (h->heap_pgalloc) { @@ -3418,10 +3414,12 @@ u32 nvmap_pin_single(struct nvmap_handle *h) return nvmap_get_physaddr(h); } -int nvmap_pin_array(struct nvmap_pinarray_elem *arr, int num_elems, +int nvmap_pin_array(struct file *filp, + struct nvmap_pinarray_elem *arr, int num_elems, struct nvmap_handle **unique_arr, int *num_unique, bool wait) { struct nvmap_pinarray_elem *elem; + struct nvmap_file_priv *priv = filp->private_data; int i, unique_idx = 0; unsigned long pfn = 0; void *pteaddr = NULL; @@ -3432,11 +3430,28 @@ int nvmap_pin_array(struct nvmap_pinarray_elem *arr, int num_elems, /* find unique handles, pin them and collect into unpin array */ for (elem = arr, i = num_elems; i && !ret; i--, elem++) { struct nvmap_handle *to_pin = elem->pin_mem; - if (!(to_pin->flags & NVMEM_HANDLE_VISITED)) { - if (wait) + if (to_pin->poison != NVDA_POISON) { + pr_err("%s: handle is poisoned\n", __func__); + ret = -EFAULT; + } + else if (!(to_pin->flags & NVMEM_HANDLE_VISITED)) { + if (!priv->su && !to_pin->global) { + struct nvmap_handle_ref *r; + spin_lock(&priv->ref_lock); + r = _nvmap_ref_lookup_locked(priv, + (unsigned long)to_pin); + spin_unlock(&priv->ref_lock); + if (!r) { + pr_err("%s: handle access failure\n", __func__); + ret = -EPERM; + break; + } + } + if (wait) { ret = wait_event_interruptible( nvmap_pin_wait, !_nvmap_handle_pin_locked(to_pin)); + } else ret = _nvmap_handle_pin_locked(to_pin); if (!ret) { @@ -3445,6 +3460,7 @@ int nvmap_pin_array(struct nvmap_pinarray_elem *arr, int num_elems, } } } + /* clear visited flags before releasing mutex */ i = unique_idx; while (i--) @@ -3462,7 +3478,7 @@ int nvmap_pin_array(struct nvmap_pinarray_elem *arr, int num_elems, do_wake |= _nvmap_handle_unpin(unique_arr[i]); if (do_wake) wake_up(&nvmap_pin_wait); - return -EINTR; + return ret; } for (elem = arr, i = num_elems; i; i--, elem++) { @@ -3519,3 +3535,8 @@ void nvmap_unpin(struct nvmap_handle **h, int num_handles) if (do_wake) wake_up(&nvmap_pin_wait); } + +int nvmap_validate_file(struct file *f) +{ + return (f->f_op==&knvmap_fops || f->f_op==&nvmap_fops) ? 0 : -EFAULT; +} diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index cceef8916487..cee8fe44dad6 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -1871,6 +1871,10 @@ struct clk_duplicate tegra_clk_duplicates[] = { CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL), CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL), CLK_DUPLICATE("usbd", "cpcap-otg", NULL), + CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"), + CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"), + CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"), + CLK_DUPLICATE("epp", "tegra_grhost", "epp"), }; #define CLK(dev, con, ck) \ diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index ef333f6474af..c70f7f848357 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -102,6 +102,8 @@ static void _dump_regs(struct tegra_dc *dc, void *data, int i; char buff[256]; + tegra_dc_io_start(dc); + DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0); DUMP_REG(DC_CMD_DISPLAY_COMMAND); DUMP_REG(DC_CMD_SIGNAL_RAISE); @@ -225,6 +227,8 @@ static void _dump_regs(struct tegra_dc *dc, void *data, DUMP_REG(DC_WINBUF_ADDR_H_OFFSET); DUMP_REG(DC_WINBUF_ADDR_V_OFFSET); } + + tegra_dc_io_end(dc); } #undef DUMP_REG @@ -285,7 +289,6 @@ static void tegra_dc_dbg_add(struct tegra_dc *dc) snprintf(name, sizeof(name), "tegra_dc%d_regs", dc->ndev->id); (void) debugfs_create_file(name, S_IRUGO, NULL, dc, &dbg_fops); - } #else static void tegra_dc_dbg_add(struct tegra_dc *dc) {} @@ -409,6 +412,12 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *bl } } +u32 tegra_dc_get_syncpt_id(struct tegra_dc *dc) +{ + return dc->syncpt_id; +} +EXPORT_SYMBOL(tegra_dc_get_syncpt_id); + /* does not support updating windows on multiple dcs in one call */ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) { @@ -520,9 +529,11 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); + dc->syncpt_max = nvhost_syncpt_incr_max(&dc->ndev->host->syncpt, dc->syncpt_id, 1); + mutex_unlock(&dc->lock); - return 0; + return dc->syncpt_max; } EXPORT_SYMBOL(tegra_dc_update_windows); @@ -701,6 +712,11 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); } + while (dc->syncpt_min < dc->syncpt_max) { + dc->syncpt_min++; + nvhost_syncpt_cpu_incr(&dc->ndev->host->syncpt, dc->syncpt_id); + } + if (completed) wake_up(&dc->wq); } @@ -755,11 +771,18 @@ static void tegra_dc_set_color_control(struct tegra_dc *dc) static void tegra_dc_init(struct tegra_dc *dc) { + u32 disp_syncpt; + u32 vblank_syncpt; + tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); - if (dc->ndev->id == 0) - tegra_dc_writel(dc, 0x0000011a, DC_CMD_CONT_SYNCPT_VSYNC); - else - tegra_dc_writel(dc, 0x0000011b, DC_CMD_CONT_SYNCPT_VSYNC); + if (dc->ndev->id == 0) { + disp_syncpt = NVSYNCPT_DISP0; + vblank_syncpt = NVSYNCPT_VBLANK0; + } else if (dc->ndev->id == 1) { + disp_syncpt = NVSYNCPT_DISP1; + vblank_syncpt = NVSYNCPT_VBLANK1; + } + tegra_dc_writel(dc, 0x00000100 | vblank_syncpt, DC_CMD_CONT_SYNCPT_VSYNC); tegra_dc_writel(dc, 0x00004700, DC_CMD_INT_TYPE); tegra_dc_writel(dc, 0x0001c700, DC_CMD_INT_POLARITY); tegra_dc_writel(dc, 0x00000020, DC_DISP_MEM_HIGH_PRIORITY); @@ -771,6 +794,10 @@ static void tegra_dc_init(struct tegra_dc *dc) tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR); tegra_dc_set_color_control(dc); + dc->syncpt_id = disp_syncpt; + + dc->syncpt_min = dc->syncpt_max = + nvhost_syncpt_read(&dc->ndev->host->syncpt, disp_syncpt); if (dc->mode.pclk) tegra_dc_program_mode(dc, &dc->mode); @@ -778,12 +805,13 @@ static void tegra_dc_init(struct tegra_dc *dc) static void _tegra_dc_enable(struct tegra_dc *dc) { + tegra_dc_io_start(dc); + if (dc->out && dc->out->enable) dc->out->enable(); tegra_dc_setup_clk(dc, dc->clk); - clk_enable(dc->host1x_clk); clk_enable(dc->clk); tegra_periph_reset_deassert(dc->clk); enable_irq(dc->irq); @@ -817,10 +845,11 @@ static void _tegra_dc_disable(struct tegra_dc *dc) disable_irq(dc->irq); tegra_periph_reset_assert(dc->clk); clk_disable(dc->clk); - clk_disable(dc->host1x_clk); if (dc->out && dc->out->disable) dc->out->disable(); + + tegra_dc_io_end(dc); } @@ -840,7 +869,6 @@ static int tegra_dc_probe(struct nvhost_device *ndev) { struct tegra_dc *dc; struct clk *clk; - struct clk *host1x_clk; struct resource *res; struct resource *base_res; struct resource *fb_mem = NULL; @@ -890,23 +918,14 @@ static int tegra_dc_probe(struct nvhost_device *ndev) fb_mem = nvhost_get_resource_byname(ndev, IORESOURCE_MEM, "fbmem"); - host1x_clk = clk_get(&ndev->dev, "host1x"); - if (IS_ERR_OR_NULL(host1x_clk)) { - dev_err(&ndev->dev, "can't get host1x clock\n"); - ret = -ENOENT; - goto err_iounmap_reg; - } - clk = clk_get(&ndev->dev, NULL); if (IS_ERR_OR_NULL(clk)) { dev_err(&ndev->dev, "can't get clock\n"); ret = -ENOENT; - - goto err_put_host1x_clk; + goto err_iounmap_reg; } dc->clk = clk; - dc->host1x_clk = host1x_clk; dc->base_res = base_res; dc->base = base; dc->irq = irq; @@ -970,8 +989,6 @@ err_free_irq: free_irq(irq, dc); err_put_clk: clk_put(clk); -err_put_host1x_clk: - clk_put(host1x_clk); err_iounmap_reg: iounmap(base); if (fb_mem) @@ -1000,7 +1017,6 @@ static int tegra_dc_remove(struct nvhost_device *ndev) free_irq(dc->irq, dc); clk_put(dc->clk); - clk_put(dc->host1x_clk); iounmap(dc->base); if (dc->fb_mem) release_resource(dc->base_res); diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 2297be40f030..39a03e8fb9c0 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -22,6 +22,7 @@ #include #include #include +#include "../host/dev.h" struct tegra_dc; @@ -54,7 +55,6 @@ struct tegra_dc { int irq; struct clk *clk; - struct clk *host1x_clk; bool enabled; @@ -74,17 +74,33 @@ struct tegra_dc { struct resource *fb_mem; struct tegra_fb_info *fb; + + u32 syncpt_id; + u32 syncpt_min; + u32 syncpt_max; }; +static inline void tegra_dc_io_start(struct tegra_dc *dc) +{ + nvhost_module_busy(&dc->ndev->host->mod); +} + +static inline void tegra_dc_io_end(struct tegra_dc *dc) +{ + nvhost_module_idle(&dc->ndev->host->mod); +} + static inline unsigned long tegra_dc_readl(struct tegra_dc *dc, unsigned long reg) { + BUG_ON(!nvhost_module_powered(&dc->ndev->host->mod)); return readl(dc->base + reg * 4); } static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long val, unsigned long reg) { + BUG_ON(!nvhost_module_powered(&dc->ndev->host->mod)); writel(val, dc->base + reg * 4); } diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 87bae6fb1f69..44550c1f283c 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -23,14 +23,21 @@ #include #include #include +#include #include +#include #include +#include #include +#include