video: tegra: host: Register devices in SoC files
[linux-2.6.git] / drivers / video / tegra / host / host1x / host1x_syncpt.c
1 /*
2  * drivers/video/tegra/host/host1x/host1x_syncpt.c
3  *
4  * Tegra Graphics Host Syncpoints for HOST1X
5  *
6  * Copyright (c) 2010-2012, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms and conditions of the GNU General Public License,
10  * version 2, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <linux/nvhost_ioctl.h>
22 #include <linux/io.h>
23 #include <trace/events/nvhost.h>
24 #include "nvhost_syncpt.h"
25 #include "nvhost_acm.h"
26 #include "host1x.h"
27 #include "host1x_syncpt.h"
28 #include "host1x_hardware.h"
29 #include "chip_support.h"
30
31 /**
32  * Write the current syncpoint value back to hw.
33  */
34 static void t20_syncpt_reset(struct nvhost_syncpt *sp, u32 id)
35 {
36         struct nvhost_master *dev = syncpt_to_dev(sp);
37         int min = nvhost_syncpt_read_min(sp, id);
38         writel(min, dev->sync_aperture + (HOST1X_SYNC_SYNCPT_0 + id * 4));
39 }
40
41 /**
42  * Write the current waitbase value back to hw.
43  */
44 static void t20_syncpt_reset_wait_base(struct nvhost_syncpt *sp, u32 id)
45 {
46         struct nvhost_master *dev = syncpt_to_dev(sp);
47         writel(sp->base_val[id],
48                 dev->sync_aperture + (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
49 }
50
51 /**
52  * Read waitbase value from hw.
53  */
54 static void t20_syncpt_read_wait_base(struct nvhost_syncpt *sp, u32 id)
55 {
56         struct nvhost_master *dev = syncpt_to_dev(sp);
57         sp->base_val[id] = readl(dev->sync_aperture +
58                                 (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
59 }
60
61 /**
62  * Updates the last value read from hardware.
63  * (was nvhost_syncpt_update_min)
64  */
65 static u32 t20_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
66 {
67         struct nvhost_master *dev = syncpt_to_dev(sp);
68         void __iomem *sync_regs = dev->sync_aperture;
69         u32 old, live;
70
71         do {
72                 old = nvhost_syncpt_read_min(sp, id);
73                 live = readl(sync_regs + (HOST1X_SYNC_SYNCPT_0 + id * 4));
74         } while ((u32)atomic_cmpxchg(&sp->min_val[id], old, live) != old);
75
76         if (!nvhost_syncpt_check_max(sp, id, live))
77                 dev_err(&syncpt_to_dev(sp)->dev->dev,
78                                 "%s failed: id=%u, min=%d, max=%d\n",
79                                 __func__,
80                                 nvhost_syncpt_read_min(sp, id),
81                                 nvhost_syncpt_read_max(sp, id),
82                                 id);
83
84         return live;
85 }
86
87 /**
88  * Write a cpu syncpoint increment to the hardware, without touching
89  * the cache. Caller is responsible for host being powered.
90  */
91 static void t20_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
92 {
93         struct nvhost_master *dev = syncpt_to_dev(sp);
94         BUG_ON(!nvhost_module_powered(dev->dev));
95         if (!client_managed(id) && nvhost_syncpt_min_eq_max(sp, id)) {
96                 dev_err(&syncpt_to_dev(sp)->dev->dev,
97                         "Trying to increment syncpoint id %d beyond max\n",
98                         id);
99                 nvhost_debug_dump(syncpt_to_dev(sp));
100                 return;
101         }
102         writel(BIT(id), dev->sync_aperture + HOST1X_SYNC_SYNCPT_CPU_INCR);
103         wmb();
104 }
105
106 /* remove a wait pointed to by patch_addr */
107 static int host1x_syncpt_patch_wait(struct nvhost_syncpt *sp,
108                 void *patch_addr)
109 {
110         u32 override = nvhost_class_host_wait_syncpt(
111                         NVSYNCPT_GRAPHICS_HOST, 0);
112         __raw_writel(override, patch_addr);
113         return 0;
114 }
115
116
117 static const char *s_syncpt_names[32] = {
118         "gfx_host",
119         "", "", "", "", "", "", "",
120         "disp0_a", "disp1_a", "avp_0",
121         "csi_vi_0", "csi_vi_1",
122         "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4",
123         "2d_0", "2d_1",
124         "disp0_b", "disp1_b",
125         "3d",
126         "mpe",
127         "disp0_c", "disp1_c",
128         "vblank0", "vblank1",
129         "mpe_ebm_eof", "mpe_wr_safe",
130         "2d_tinyblt",
131         "dsi"
132 };
133
134 static const char *t20_syncpt_name(struct nvhost_syncpt *s, u32 id)
135 {
136         BUG_ON(id >= ARRAY_SIZE(s_syncpt_names));
137         return s_syncpt_names[id];
138 }
139
140 static void t20_syncpt_debug(struct nvhost_syncpt *sp)
141 {
142         u32 i;
143         for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
144                 u32 max = nvhost_syncpt_read_max(sp, i);
145                 u32 min = nvhost_syncpt_update_min(sp, i);
146                 if (!max && !min)
147                         continue;
148                 dev_info(&syncpt_to_dev(sp)->dev->dev,
149                         "id %d (%s) min %d max %d\n",
150                         i, syncpt_op().name(sp, i),
151                         min, max);
152
153         }
154
155         for (i = 0; i < NV_HOST1X_SYNCPT_NB_BASES; i++) {
156                 u32 base_val;
157                 t20_syncpt_read_wait_base(sp, i);
158                 base_val = sp->base_val[i];
159                 if (base_val)
160                         dev_info(&syncpt_to_dev(sp)->dev->dev,
161                                         "waitbase id %d val %d\n",
162                                         i, base_val);
163
164         }
165 }
166
167 static int syncpt_mutex_try_lock(struct nvhost_syncpt *sp,
168                 unsigned int idx)
169 {
170         void __iomem *sync_regs = syncpt_to_dev(sp)->sync_aperture;
171         /* mlock registers returns 0 when the lock is aquired.
172          * writing 0 clears the lock. */
173         return !!readl(sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
174 }
175
176 static void syncpt_mutex_unlock(struct nvhost_syncpt *sp,
177                unsigned int idx)
178 {
179         void __iomem *sync_regs = syncpt_to_dev(sp)->sync_aperture;
180
181         writel(0, sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
182 }
183
184 int host1x_init_syncpt_support(struct nvhost_master *host,
185         struct nvhost_chip_support *op)
186 {
187         host->sync_aperture = host->aperture +
188                 (NV_HOST1X_CHANNEL0_BASE +
189                         HOST1X_CHANNEL_SYNC_REG_BASE);
190
191         op->syncpt.reset = t20_syncpt_reset;
192         op->syncpt.reset_wait_base = t20_syncpt_reset_wait_base;
193         op->syncpt.read_wait_base = t20_syncpt_read_wait_base;
194         op->syncpt.update_min = t20_syncpt_update_min;
195         op->syncpt.cpu_incr = t20_syncpt_cpu_incr;
196         op->syncpt.patch_wait = host1x_syncpt_patch_wait;
197         op->syncpt.debug = t20_syncpt_debug;
198         op->syncpt.name = t20_syncpt_name;
199         op->syncpt.mutex_try_lock = syncpt_mutex_try_lock;
200         op->syncpt.mutex_unlock = syncpt_mutex_unlock;
201
202         host->syncpt.nb_pts = NV_HOST1X_SYNCPT_NB_PTS;
203         host->syncpt.nb_bases = NV_HOST1X_SYNCPT_NB_BASES;
204         host->syncpt.client_managed = NVSYNCPTS_CLIENT_MANAGED;
205         host->syncpt.nb_mlocks =  NV_HOST1X_SYNC_MLOCK_NUM;
206
207         return 0;
208 }