0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/io.h>
0009
0010 #include "../dev.h"
0011 #include "../syncpt.h"
0012
0013
0014
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
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
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
0052
0053 static u32 syncpt_load(struct host1x_syncpt *sp)
0054 {
0055 struct host1x *host = sp->host;
0056 u32 old, live;
0057
0058
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
0074
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
0094
0095
0096
0097
0098
0099
0100
0101
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
0120
0121
0122
0123
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 };