2 * drivers/video/tegra/host/t124/t124.c
4 * Tegra Graphics Init for T124 Architecture Chips
6 * Copyright (c) 2011-2012, NVIDIA Corporation.
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.
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
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/>.
20 #include <linux/slab.h>
23 #include "nvhost_job.h"
24 #include "class_ids.h"
27 #include "host1x/host1x.h"
29 #include "hardware_t124.h"
30 #include "syncpt_t124.h"
32 #include "gk20a/gk20a.h"
34 #include "vic03/vic03.h"
35 #include "msenc/msenc.h"
36 #include "tsec/tsec.h"
38 #include "nvhost_memmgr.h"
39 #include "chip_support.h"
41 static int t124_num_alloc_channels = 0;
43 #define HOST_EMC_FLOOR 300000000
45 #define BIT64(nr) (1ULL << (nr))
46 #define NVSYNCPTS_CLIENT_MANAGED_T124 ( \
47 BIT64(NVSYNCPT_DISP0_A) | BIT64(NVSYNCPT_DISP1_A) | \
48 BIT64(NVSYNCPT_DISP0_B) | BIT64(NVSYNCPT_DISP1_B) | \
49 BIT64(NVSYNCPT_DISP0_C) | BIT64(NVSYNCPT_DISP1_C) | \
50 BIT64(NVSYNCPT_DSI) | \
51 BIT64(NVSYNCPT_VBLANK0) | BIT64(NVSYNCPT_VBLANK1) | \
52 BIT64(NVSYNCPT_ISP_0_0) | BIT64(NVSYNCPT_ISP_0_1) | \
53 BIT64(NVSYNCPT_ISP_0_3) | \
54 BIT64(NVSYNCPT_ISP_1_0) | BIT64(NVSYNCPT_ISP_1_1) | \
55 BIT64(NVSYNCPT_ISP_1_3) | BIT64(NVSYNCPT_AVP_0))
57 static struct resource tegra_host1x04_resources[] = {
59 .start = TEGRA_HOST1X_BASE,
60 .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1,
61 .flags = IORESOURCE_MEM,
64 .start = INT_HOST1X_MPCORE_SYNCPT,
65 .end = INT_HOST1X_MPCORE_SYNCPT,
66 .flags = IORESOURCE_IRQ,
69 .start = INT_HOST1X_MPCORE_GENERAL,
70 .end = INT_HOST1X_MPCORE_GENERAL,
71 .flags = IORESOURCE_IRQ,
75 static const char *s_syncpt_names[NV_HOST1X_SYNCPT_NB_PTS] = {
76 [NVSYNCPT_CSI_VI_0] = "csi_vi_0",
77 [NVSYNCPT_CSI_VI_1] = "csi_vi_1",
78 [NVSYNCPT_VI_ISP_0] = "vi_isp_0",
79 [NVSYNCPT_VI_ISP_1] = "vi_isp_1",
80 [NVSYNCPT_VI_ISP_2] = "vi_isp_2",
81 [NVSYNCPT_VI_ISP_3] = "vi_isp_3",
82 [NVSYNCPT_VI_ISP_4] = "vi_isp_4",
84 [NVSYNCPT_MPE] = "mpe",
85 [NVSYNCPT_MPE_EBM_EOF] = "mpe_ebm_eof",
86 [NVSYNCPT_MPE_WR_SAFE] = "mpe_wr_safe",
87 [NVSYNCPT_VIC] = "vic",
88 [NVSYNCPT_TSEC] = "tsec",
89 [NVSYNCPT_DISP0_A] = "disp0",
90 [NVSYNCPT_DISP1_A] = "disp1",
91 [NVSYNCPT_AVP_0] = "avp",
92 [NVSYNCPT_DISP0_B] = "disp0b",
93 [NVSYNCPT_DISP1_B] = "disp1b",
94 [NVSYNCPT_DISP0_C] = "disp0c",
95 [NVSYNCPT_DISP1_C] = "disp0c",
96 [NVSYNCPT_VBLANK0] = "vblank0",
97 [NVSYNCPT_VBLANK1] = "vblank1",
98 [NVSYNCPT_DSI] = "dsi",
101 static struct host1x_device_info host1x04_info = {
102 .nb_channels = T124_NVHOST_NUMCHANNELS,
103 .nb_pts = NV_HOST1X_SYNCPT_NB_PTS,
104 .nb_mlocks = NV_HOST1X_NB_MLOCKS,
105 .nb_bases = NV_HOST1X_SYNCPT_NB_BASES,
106 .syncpt_names = s_syncpt_names,
107 .client_managed = NVSYNCPTS_CLIENT_MANAGED_T124,
110 static struct nvhost_device_data tegra_host1x04_info = {
111 .clocks = {{"host1x", UINT_MAX}, {} },
112 NVHOST_MODULE_NO_POWERGATE_IDS,
116 static struct platform_device tegra_host1x04_device = {
118 .resource = tegra_host1x04_resources,
119 .num_resources = ARRAY_SIZE(tegra_host1x04_resources),
121 .platform_data = &tegra_host1x04_info,
126 static struct resource isp_resources[] = {
129 .start = TEGRA_ISP_BASE,
130 .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1,
131 .flags = IORESOURCE_MEM,
135 static struct nvhost_device_data tegra_isp01_info = {
136 .syncpts = NV_ISP_0_SYNCPTS,
137 .modulemutexes = {NVMODMUTEX_ISP_0},
138 .clocks = {{"isp", UINT_MAX}, {} },
140 /* HACK: Mark as keepalive until 1188795 is fixed */
142 NVHOST_MODULE_NO_POWERGATE_IDS,
143 NVHOST_DEFAULT_CLOCKGATE_DELAY,
144 .moduleid = NVHOST_MODULE_ISP,
146 static struct platform_device tegra_isp01_device = {
148 .resource = isp_resources,
149 .num_resources = ARRAY_SIZE(isp_resources),
151 .platform_data = &tegra_isp01_info,
155 static struct resource ispb_resources[] = {
158 .start = TEGRA_ISPB_BASE,
159 .end = TEGRA_ISPB_BASE + TEGRA_ISPB_SIZE - 1,
160 .flags = IORESOURCE_MEM,
165 static struct nvhost_device_data tegra_isp01b_info = {
166 .syncpts = NV_ISP_1_SYNCPTS,
167 .modulemutexes = {NVMODMUTEX_ISP_1},
168 .clocks = {{"isp", UINT_MAX}, {} },
170 /* HACK: Mark as keepalive until 1188795 is fixed */
172 NVHOST_MODULE_NO_POWERGATE_IDS,
173 NVHOST_DEFAULT_CLOCKGATE_DELAY,
174 .moduleid = (1 << 16) | NVHOST_MODULE_ISP,
177 static struct platform_device tegra_isp01b_device = {
179 .id = 1, /* .1 on the dev node */
180 .resource = ispb_resources,
181 .num_resources = ARRAY_SIZE(ispb_resources),
183 .platform_data = &tegra_isp01b_info,
187 static struct resource vi_resources[] = {
190 .start = TEGRA_VI_BASE,
191 .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1,
192 .flags = IORESOURCE_MEM,
196 static struct nvhost_device_data tegra_vi01_info = {
197 .syncpts = NV_VI_0_SYNCPTS,
198 .modulemutexes = {NVMODMUTEX_VI_0},
200 /* HACK: Mark as keepalive until 1188795 is fixed */
202 .clocks = {{"vi", UINT_MAX}, {"csi", UINT_MAX}, {} },
203 NVHOST_MODULE_NO_POWERGATE_IDS,
204 NVHOST_DEFAULT_CLOCKGATE_DELAY,
205 .moduleid = NVHOST_MODULE_VI,
209 static struct platform_device tegra_vi01_device = {
211 .resource = vi_resources,
212 .num_resources = ARRAY_SIZE(vi_resources),
214 .platform_data = &tegra_vi01_info,
218 static struct nvhost_device_data tegra_vi01b_info = {
219 .syncpts = NV_VI_1_SYNCPTS,
220 .modulemutexes = {NVMODMUTEX_VI_1},
222 /* HACK: Mark as keepalive until 1188795 is fixed */
224 .clocks = {{"vi", UINT_MAX}, {"csi", UINT_MAX}, {} },
225 NVHOST_MODULE_NO_POWERGATE_IDS,
226 NVHOST_DEFAULT_CLOCKGATE_DELAY,
227 .moduleid = (1 << 16 | NVHOST_MODULE_VI),
230 static struct platform_device tegra_vi01b_device = {
232 .id = 1, /* .1 on the dev node */
234 .platform_data = &tegra_vi01b_info,
238 static struct resource msenc_resources[] = {
241 .start = TEGRA_MSENC_BASE,
242 .end = TEGRA_MSENC_BASE + TEGRA_MSENC_SIZE - 1,
243 .flags = IORESOURCE_MEM,
247 static struct nvhost_device_data tegra_msenc03_info = {
248 .version = NVHOST_ENCODE_MSENC_VER(3, 1),
249 .syncpts = {NVSYNCPT_MSENC, NVSYNCPT_MSENC_SLICE},
250 .waitbases = {NVWAITBASE_MSENC},
251 .class = NV_VIDEO_ENCODE_MSENC_CLASS_ID,
252 .clocks = {{"msenc", UINT_MAX}, {"emc", HOST_EMC_FLOOR} },
253 NVHOST_MODULE_NO_POWERGATE_IDS,
254 NVHOST_DEFAULT_CLOCKGATE_DELAY,
257 .moduleid = NVHOST_MODULE_MSENC,
260 struct platform_device tegra_msenc03_device = {
262 .resource = msenc_resources,
263 .num_resources = ARRAY_SIZE(msenc_resources),
265 .platform_data = &tegra_msenc03_info,
269 static struct resource tsec_resources[] = {
272 .start = TEGRA_TSEC_BASE,
273 .end = TEGRA_TSEC_BASE + TEGRA_TSEC_SIZE - 1,
274 .flags = IORESOURCE_MEM,
278 static struct nvhost_device_data tegra_tsec01_info = {
279 .version = NVHOST_ENCODE_TSEC_VER(1, 0),
280 .syncpts = {NVSYNCPT_TSEC},
281 .waitbases = {NVWAITBASE_TSEC},
282 .class = NV_TSEC_CLASS_ID,
284 .clocks = {{"tsec", UINT_MAX}, {"emc", HOST_EMC_FLOOR} },
285 NVHOST_MODULE_NO_POWERGATE_IDS,
286 NVHOST_DEFAULT_CLOCKGATE_DELAY,
287 .moduleid = NVHOST_MODULE_TSEC,
290 static struct platform_device tegra_tsec01_device = {
292 .resource = tsec_resources,
293 .num_resources = ARRAY_SIZE(tsec_resources),
295 .platform_data = &tegra_tsec01_info,
301 static struct platform_device *t12_devices[] = {
303 &tegra_isp01b_device,
306 &tegra_msenc03_device,
307 &tegra_tsec01_device,
308 #if defined(CONFIG_TEGRA_GK20A)
311 #if defined(CONFIG_ARCH_TEGRA_VIC)
317 struct platform_device *tegra12_register_host1x_devices(void)
320 struct platform_device *pdev;
322 struct nvhost_device_data *pdata =
323 (struct nvhost_device_data *)tegra_host1x04_device.dev.platform_data;
327 pdata->private_data = &host1x04_info;
329 /* register host1x device first */
330 platform_device_register(&tegra_host1x04_device);
331 tegra_host1x04_device.dev.parent = NULL;
333 /* register clients with host1x device as parent */
334 for (index = 0; index < ARRAY_SIZE(t12_devices); index++) {
335 pdev = t12_devices[index];
336 pdev->dev.parent = &tegra_host1x04_device.dev;
337 platform_device_register(pdev);
340 return &tegra_host1x04_device;
343 static inline void __iomem *t124_channel_aperture(void __iomem *p, int ndx)
345 return p + (ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES);
348 static int t124_channel_init(struct nvhost_channel *ch,
349 struct nvhost_master *dev, int index)
352 mutex_init(&ch->reflock);
353 mutex_init(&ch->submitlock);
355 ch->aperture = t124_channel_aperture(dev->aperture, index);
357 nvhost_dbg_fn("dev=%s chid=%d ap=%p",
358 dev_name(&ch->dev->dev),
362 return t124_nvhost_hwctx_handler_init(ch);
365 #include "host1x/host1x_channel.c"
366 static int t124_channel_submit(struct nvhost_job *job)
370 #if defined(CONFIG_TEGRA_GK20A)
371 if (job->ch->dev == &tegra_gk20a_device)
372 return gk20a_channel_submit(job);
375 return host1x_channel_submit(job);
378 #if defined(CONFIG_TEGRA_GK20A)
379 static int t124_channel_alloc_obj(struct nvhost_hwctx *hwctx,
380 struct nvhost_alloc_obj_ctx_args *args)
383 return gk20a_alloc_obj_ctx(hwctx->priv, args);
386 static int t124_channel_free_obj(struct nvhost_hwctx *hwctx,
387 struct nvhost_free_obj_ctx_args *args)
390 return gk20a_free_obj_ctx(hwctx->priv, args);
393 static int t124_channel_alloc_gpfifo(struct nvhost_hwctx *hwctx,
394 struct nvhost_alloc_gpfifo_args *args)
397 return gk20a_alloc_channel_gpfifo(hwctx->priv, args);
400 static int t124_channel_submit_gpfifo(struct nvhost_hwctx *hwctx,
401 struct nvhost_gpfifo *gpfifo, u32 num_entries,
402 struct nvhost_fence *fence, u32 flags)
404 struct nvhost_channel *ch = hwctx->channel;
405 void *completed_waiter = NULL;
410 completed_waiter = nvhost_intr_alloc_waiter();
411 if (!completed_waiter)
414 nvhost_module_busy(ch->dev);
416 ret = gk20a_submit_channel_gpfifo(hwctx->priv, gpfifo, num_entries,
419 err = nvhost_intr_add_action(&nvhost_get_host(ch->dev)->intr,
420 fence->syncpt_id, fence->value,
421 NVHOST_INTR_ACTION_SUBMIT_COMPLETE, ch,
424 WARN(err, "Failed to set submit complete interrupt");
429 static int t124_channel_wait(struct nvhost_hwctx *hwctx,
430 struct nvhost_wait_args *args)
433 return gk20a_channel_wait(hwctx->priv, args);
436 static int t124_channel_zcull_bind(struct nvhost_hwctx *hwctx,
437 struct nvhost_zcull_bind_args *args)
440 return gk20a_channel_zcull_bind(hwctx->priv, args);
442 #endif /* CONFIG_TEGRA_GK20A */
444 static void t124_free_nvhost_channel(struct nvhost_channel *ch)
447 nvhost_free_channel_internal(ch, &t124_num_alloc_channels);
450 static struct nvhost_channel *t124_alloc_nvhost_channel(
451 struct platform_device *dev)
453 struct nvhost_device_data *pdata = nvhost_get_devdata(dev);
455 return nvhost_alloc_channel_internal(pdata->index,
456 nvhost_get_host(dev)->info.nb_channels,
457 &t124_num_alloc_channels);
460 int nvhost_init_t124_channel_support(struct nvhost_master *host,
461 struct nvhost_chip_support *op)
464 nvhost_dbg_fn("max channels=%d devices=%zd",
466 ARRAY_SIZE(t12_devices));
467 BUILD_BUG_ON(T124_NVHOST_NUMCHANNELS < ARRAY_SIZE(t12_devices));
469 nb_channels = ARRAY_SIZE(t12_devices);
471 /* Set indices dynamically as we can have
472 * missing/non-static devices above (e.g.: vic, gk20a).
475 for (i = 0; i < nb_channels; i++ ) {
476 struct platform_device *dev = t12_devices[i];
477 struct nvhost_device_data *pdata =
478 (struct nvhost_device_data *)dev->dev.platform_data;
480 #if defined(CONFIG_ARCH_TEGRA_VIC)
481 if (dev == &tegra_vic03_device) {
482 pdata->modulemutexes[0] = NVMODMUTEX_VIC;
483 pdata->syncpts[0] = NVSYNCPT_VIC;
486 #if defined(CONFIG_TEGRA_GK20A)
487 if (dev == &tegra_gk20a_device) {
488 pdata->syncpts[0] = NVSYNCPT_3D;
489 pdata->waitbases[0] = NVWAITBASE_3D;
490 pdata->modulemutexes[0] = NVMODMUTEX_3D;
495 op->channel.init = t124_channel_init;
496 op->channel.submit = t124_channel_submit;
498 #if defined(CONFIG_TEGRA_GK20A)
499 op->channel.alloc_obj = t124_channel_alloc_obj;
500 op->channel.free_obj = t124_channel_free_obj;
501 op->channel.alloc_gpfifo = t124_channel_alloc_gpfifo;
502 op->channel.submit_gpfifo = t124_channel_submit_gpfifo;
503 op->channel.wait = t124_channel_wait;
504 op->channel.zcull.bind = t124_channel_zcull_bind;
506 op->nvhost_dev.alloc_nvhost_channel = t124_alloc_nvhost_channel;
507 op->nvhost_dev.free_nvhost_channel = t124_free_nvhost_channel;
512 int t124_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
515 struct nvhost_device_data *pdata = nvhost_get_devdata(ch->dev);
516 u32 syncpt = pdata->syncpts[0];
517 u32 waitbase = pdata->waitbases[0];
521 if (pdata->alloc_hwctx_handler) {
522 ch->ctxhandler = pdata->alloc_hwctx_handler(syncpt,
531 static void t124_remove_support(struct nvhost_chip_support *op)
537 #include "host1x/host1x_syncpt.c"
538 #include "host1x/host1x_intr.c"
540 int nvhost_init_t124_support(struct nvhost_master *host,
541 struct nvhost_chip_support *op)
544 struct t124 *t124 = 0;
546 /* don't worry about cleaning up on failure... "remove" does it. */
547 err = nvhost_init_t124_channel_support(host, op);
551 err = nvhost_init_t124_cdma_support(op);
555 err = nvhost_init_t124_debug_support(op);
559 host->sync_aperture = host->aperture + HOST1X_CHANNEL_SYNC_REG_BASE;
560 op->syncpt = host1x_syncpt_ops;
561 op->intr = host1x_intr_ops;
563 err = nvhost_memmgr_init(op);
567 err = nvhost_init_t124_as_support(op);
571 t124 = kzalloc(sizeof(struct t124), GFP_KERNEL);
579 op->remove_support = t124_remove_support;
580 op->nvhost_dev.alloc_nvhost_channel = t124_alloc_nvhost_channel;
581 op->nvhost_dev.free_nvhost_channel = t124_free_nvhost_channel;
589 op->remove_support = 0;