Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Tegra host1x Syncpoints
0004  *
0005  * Copyright (c) 2010-2013, NVIDIA Corporation.
0006  */
0007 
0008 #include <linux/io.h>
0009 
0010 #include "../dev.h"
0011 #include "../syncpt.h"
0012 
0013 /*
0014  * Write the current syncpoint value back to hw.
0015  */
0016 static void syncpt_restore(struct host1x_syncpt *sp)
0017 {
0018     u32 min = host1x_syncpt_read_min(sp);
0019     struct host1x *host = sp->host;
0020 
0021     host1x_sync_writel(host, min, HOST1X_SYNC_SYNCPT(sp->id));
0022 }
0023 
0024 /*
0025  * Write the current waitbase value back to hw.
0026  */
0027 static void syncpt_restore_wait_base(struct host1x_syncpt *sp)
0028 {
0029 #if HOST1X_HW < 7
0030     struct host1x *host = sp->host;
0031 
0032     host1x_sync_writel(host, sp->base_val,
0033                HOST1X_SYNC_SYNCPT_BASE(sp->id));
0034 #endif
0035 }
0036 
0037 /*
0038  * Read waitbase value from hw.
0039  */
0040 static void syncpt_read_wait_base(struct host1x_syncpt *sp)
0041 {
0042 #if HOST1X_HW < 7
0043     struct host1x *host = sp->host;
0044 
0045     sp->base_val =
0046         host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(sp->id));
0047 #endif
0048 }
0049 
0050 /*
0051  * Updates the last value read from hardware.
0052  */
0053 static u32 syncpt_load(struct host1x_syncpt *sp)
0054 {
0055     struct host1x *host = sp->host;
0056     u32 old, live;
0057 
0058     /* Loop in case there's a race writing to min_val */
0059     do {
0060         old = host1x_syncpt_read_min(sp);
0061         live = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT(sp->id));
0062     } while ((u32)atomic_cmpxchg(&sp->min_val, old, live) != old);
0063 
0064     if (!host1x_syncpt_check_max(sp, live))
0065         dev_err(host->dev, "%s failed: id=%u, min=%d, max=%d\n",
0066             __func__, sp->id, host1x_syncpt_read_min(sp),
0067             host1x_syncpt_read_max(sp));
0068 
0069     return live;
0070 }
0071 
0072 /*
0073  * Write a cpu syncpoint increment to the hardware, without touching
0074  * the cache.
0075  */
0076 static int syncpt_cpu_incr(struct host1x_syncpt *sp)
0077 {
0078     struct host1x *host = sp->host;
0079     u32 reg_offset = sp->id / 32;
0080 
0081     if (!host1x_syncpt_client_managed(sp) &&
0082         host1x_syncpt_idle(sp))
0083         return -EINVAL;
0084 
0085     host1x_sync_writel(host, BIT(sp->id % 32),
0086                HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
0087     wmb();
0088 
0089     return 0;
0090 }
0091 
0092 /**
0093  * syncpt_assign_to_channel() - Assign syncpoint to channel
0094  * @sp: syncpoint
0095  * @ch: channel
0096  *
0097  * On chips with the syncpoint protection feature (Tegra186+), assign @sp to
0098  * @ch, preventing other channels from incrementing the syncpoints. If @ch is
0099  * NULL, unassigns the syncpoint.
0100  *
0101  * On older chips, do nothing.
0102  */
0103 static void syncpt_assign_to_channel(struct host1x_syncpt *sp,
0104                   struct host1x_channel *ch)
0105 {
0106 #if HOST1X_HW >= 6
0107     struct host1x *host = sp->host;
0108 
0109     if (!host->hv_regs)
0110         return;
0111 
0112     host1x_sync_writel(host,
0113                HOST1X_SYNC_SYNCPT_CH_APP_CH(ch ? ch->id : 0xff),
0114                HOST1X_SYNC_SYNCPT_CH_APP(sp->id));
0115 #endif
0116 }
0117 
0118 /**
0119  * syncpt_enable_protection() - Enable syncpoint protection
0120  * @host: host1x instance
0121  *
0122  * On chips with the syncpoint protection feature (Tegra186+), enable this
0123  * feature. On older chips, do nothing.
0124  */
0125 static void syncpt_enable_protection(struct host1x *host)
0126 {
0127 #if HOST1X_HW >= 6
0128     if (!host->hv_regs)
0129         return;
0130 
0131     host1x_hypervisor_writel(host, HOST1X_HV_SYNCPT_PROT_EN_CH_EN,
0132                  HOST1X_HV_SYNCPT_PROT_EN);
0133 #endif
0134 }
0135 
0136 static const struct host1x_syncpt_ops host1x_syncpt_ops = {
0137     .restore = syncpt_restore,
0138     .restore_wait_base = syncpt_restore_wait_base,
0139     .load_wait_base = syncpt_read_wait_base,
0140     .load = syncpt_load,
0141     .cpu_incr = syncpt_cpu_incr,
0142     .assign_to_channel = syncpt_assign_to_channel,
0143     .enable_protection = syncpt_enable_protection,
0144 };