From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- drivers/gpu/host1x/hw/syncpt_hw.c | 112 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 drivers/gpu/host1x/hw/syncpt_hw.c (limited to 'drivers/gpu/host1x/hw/syncpt_hw.c') diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c new file mode 100644 index 000000000..56e85395a --- /dev/null +++ b/drivers/gpu/host1x/hw/syncpt_hw.c @@ -0,0 +1,112 @@ +/* + * Tegra host1x Syncpoints + * + * 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 . + */ + +#include + +#include "../dev.h" +#include "../syncpt.h" + +/* + * Write the current syncpoint value back to hw. + */ +static void syncpt_restore(struct host1x_syncpt *sp) +{ + struct host1x *host = sp->host; + int min = host1x_syncpt_read_min(sp); + host1x_sync_writel(host, min, HOST1X_SYNC_SYNCPT(sp->id)); +} + +/* + * Write the current waitbase value back to hw. + */ +static void syncpt_restore_wait_base(struct host1x_syncpt *sp) +{ + struct host1x *host = sp->host; + host1x_sync_writel(host, sp->base_val, + HOST1X_SYNC_SYNCPT_BASE(sp->id)); +} + +/* + * Read waitbase value from hw. + */ +static void syncpt_read_wait_base(struct host1x_syncpt *sp) +{ + struct host1x *host = sp->host; + sp->base_val = + host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(sp->id)); +} + +/* + * Updates the last value read from hardware. + */ +static u32 syncpt_load(struct host1x_syncpt *sp) +{ + struct host1x *host = sp->host; + u32 old, live; + + /* Loop in case there's a race writing to min_val */ + do { + old = host1x_syncpt_read_min(sp); + live = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT(sp->id)); + } while ((u32)atomic_cmpxchg(&sp->min_val, old, live) != old); + + if (!host1x_syncpt_check_max(sp, live)) + dev_err(host->dev, "%s failed: id=%u, min=%d, max=%d\n", + __func__, sp->id, host1x_syncpt_read_min(sp), + host1x_syncpt_read_max(sp)); + + return live; +} + +/* + * Write a cpu syncpoint increment to the hardware, without touching + * the cache. + */ +static int syncpt_cpu_incr(struct host1x_syncpt *sp) +{ + struct host1x *host = sp->host; + u32 reg_offset = sp->id / 32; + + if (!host1x_syncpt_client_managed(sp) && + host1x_syncpt_idle(sp)) + return -EINVAL; + host1x_sync_writel(host, BIT_MASK(sp->id), + HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset)); + wmb(); + + return 0; +} + +/* remove a wait pointed to by patch_addr */ +static int syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr) +{ + u32 override = host1x_class_host_wait_syncpt( + HOST1X_SYNCPT_RESERVED, 0); + + *((u32 *)patch_addr) = override; + return 0; +} + +static const struct host1x_syncpt_ops host1x_syncpt_ops = { + .restore = syncpt_restore, + .restore_wait_base = syncpt_restore_wait_base, + .load_wait_base = syncpt_read_wait_base, + .load = syncpt_load, + .cpu_incr = syncpt_cpu_incr, + .patch_wait = syncpt_patch_wait, +}; -- cgit v1.2.3-54-g00ecf