0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/completion.h>
0011 #include <linux/delay.h>
0012 #include <linux/dma-mapping.h>
0013 #include <linux/dmaengine.h>
0014 #include <linux/errno.h>
0015 #include <linux/init.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/list.h>
0018 #include <linux/mm.h>
0019 #include <linux/module.h>
0020 #include <linux/of.h>
0021 #include <linux/platform_device.h> /* platform_device() */
0022 #include <linux/sched.h>
0023 #include <linux/seq_file.h>
0024 #include <linux/slab.h>
0025 #include <linux/time.h>
0026 #include <linux/vmalloc.h>
0027 #include <linux/wait.h>
0028
0029 #include "omap_dmm_tiler.h"
0030 #include "omap_dmm_priv.h"
0031
0032 #define DMM_DRIVER_NAME "dmm"
0033
0034
0035 static struct tcm *containers[TILFMT_NFORMATS];
0036 static struct dmm *omap_dmm;
0037
0038 #if defined(CONFIG_OF)
0039 static const struct of_device_id dmm_of_match[];
0040 #endif
0041
0042
0043 static DEFINE_SPINLOCK(list_lock);
0044
0045
0046 #define GEOM(xshift, yshift, bytes_per_pixel) { \
0047 .x_shft = (xshift), \
0048 .y_shft = (yshift), \
0049 .cpp = (bytes_per_pixel), \
0050 .slot_w = 1 << (SLOT_WIDTH_BITS - (xshift)), \
0051 .slot_h = 1 << (SLOT_HEIGHT_BITS - (yshift)), \
0052 }
0053
0054 static const struct {
0055 u32 x_shft;
0056 u32 y_shft;
0057 u32 cpp;
0058 u32 slot_w;
0059 u32 slot_h;
0060 } geom[TILFMT_NFORMATS] = {
0061 [TILFMT_8BIT] = GEOM(0, 0, 1),
0062 [TILFMT_16BIT] = GEOM(0, 1, 2),
0063 [TILFMT_32BIT] = GEOM(1, 1, 4),
0064 [TILFMT_PAGE] = GEOM(SLOT_WIDTH_BITS, SLOT_HEIGHT_BITS, 1),
0065 };
0066
0067
0068
0069 static const u32 reg[][4] = {
0070 [PAT_STATUS] = {DMM_PAT_STATUS__0, DMM_PAT_STATUS__1,
0071 DMM_PAT_STATUS__2, DMM_PAT_STATUS__3},
0072 [PAT_DESCR] = {DMM_PAT_DESCR__0, DMM_PAT_DESCR__1,
0073 DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
0074 };
0075
0076 static int dmm_dma_copy(struct dmm *dmm, dma_addr_t src, dma_addr_t dst)
0077 {
0078 struct dma_async_tx_descriptor *tx;
0079 enum dma_status status;
0080 dma_cookie_t cookie;
0081
0082 tx = dmaengine_prep_dma_memcpy(dmm->wa_dma_chan, dst, src, 4, 0);
0083 if (!tx) {
0084 dev_err(dmm->dev, "Failed to prepare DMA memcpy\n");
0085 return -EIO;
0086 }
0087
0088 cookie = tx->tx_submit(tx);
0089 if (dma_submit_error(cookie)) {
0090 dev_err(dmm->dev, "Failed to do DMA tx_submit\n");
0091 return -EIO;
0092 }
0093
0094 status = dma_sync_wait(dmm->wa_dma_chan, cookie);
0095 if (status != DMA_COMPLETE)
0096 dev_err(dmm->dev, "i878 wa DMA copy failure\n");
0097
0098 dmaengine_terminate_all(dmm->wa_dma_chan);
0099 return 0;
0100 }
0101
0102 static u32 dmm_read_wa(struct dmm *dmm, u32 reg)
0103 {
0104 dma_addr_t src, dst;
0105 int r;
0106
0107 src = dmm->phys_base + reg;
0108 dst = dmm->wa_dma_handle;
0109
0110 r = dmm_dma_copy(dmm, src, dst);
0111 if (r) {
0112 dev_err(dmm->dev, "sDMA read transfer timeout\n");
0113 return readl(dmm->base + reg);
0114 }
0115
0116
0117
0118
0119
0120
0121 rmb();
0122 return readl(dmm->wa_dma_data);
0123 }
0124
0125 static void dmm_write_wa(struct dmm *dmm, u32 val, u32 reg)
0126 {
0127 dma_addr_t src, dst;
0128 int r;
0129
0130 writel(val, dmm->wa_dma_data);
0131
0132
0133
0134
0135
0136
0137 wmb();
0138
0139 src = dmm->wa_dma_handle;
0140 dst = dmm->phys_base + reg;
0141
0142 r = dmm_dma_copy(dmm, src, dst);
0143 if (r) {
0144 dev_err(dmm->dev, "sDMA write transfer timeout\n");
0145 writel(val, dmm->base + reg);
0146 }
0147 }
0148
0149 static u32 dmm_read(struct dmm *dmm, u32 reg)
0150 {
0151 if (dmm->dmm_workaround) {
0152 u32 v;
0153 unsigned long flags;
0154
0155 spin_lock_irqsave(&dmm->wa_lock, flags);
0156 v = dmm_read_wa(dmm, reg);
0157 spin_unlock_irqrestore(&dmm->wa_lock, flags);
0158
0159 return v;
0160 } else {
0161 return readl(dmm->base + reg);
0162 }
0163 }
0164
0165 static void dmm_write(struct dmm *dmm, u32 val, u32 reg)
0166 {
0167 if (dmm->dmm_workaround) {
0168 unsigned long flags;
0169
0170 spin_lock_irqsave(&dmm->wa_lock, flags);
0171 dmm_write_wa(dmm, val, reg);
0172 spin_unlock_irqrestore(&dmm->wa_lock, flags);
0173 } else {
0174 writel(val, dmm->base + reg);
0175 }
0176 }
0177
0178 static int dmm_workaround_init(struct dmm *dmm)
0179 {
0180 dma_cap_mask_t mask;
0181
0182 spin_lock_init(&dmm->wa_lock);
0183
0184 dmm->wa_dma_data = dma_alloc_coherent(dmm->dev, sizeof(u32),
0185 &dmm->wa_dma_handle, GFP_KERNEL);
0186 if (!dmm->wa_dma_data)
0187 return -ENOMEM;
0188
0189 dma_cap_zero(mask);
0190 dma_cap_set(DMA_MEMCPY, mask);
0191
0192 dmm->wa_dma_chan = dma_request_channel(mask, NULL, NULL);
0193 if (!dmm->wa_dma_chan) {
0194 dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
0195 return -ENODEV;
0196 }
0197
0198 return 0;
0199 }
0200
0201 static void dmm_workaround_uninit(struct dmm *dmm)
0202 {
0203 dma_release_channel(dmm->wa_dma_chan);
0204
0205 dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
0206 }
0207
0208
0209 static void *alloc_dma(struct dmm_txn *txn, size_t sz, dma_addr_t *pa)
0210 {
0211 void *ptr;
0212 struct refill_engine *engine = txn->engine_handle;
0213
0214
0215 txn->current_pa = round_up(txn->current_pa, 16);
0216 txn->current_va = (void *)round_up((long)txn->current_va, 16);
0217
0218 ptr = txn->current_va;
0219 *pa = txn->current_pa;
0220
0221 txn->current_pa += sz;
0222 txn->current_va += sz;
0223
0224 BUG_ON((txn->current_va - engine->refill_va) > REFILL_BUFFER_SIZE);
0225
0226 return ptr;
0227 }
0228
0229
0230 static int wait_status(struct refill_engine *engine, u32 wait_mask)
0231 {
0232 struct dmm *dmm = engine->dmm;
0233 u32 r = 0, err, i;
0234
0235 i = DMM_FIXED_RETRY_COUNT;
0236 while (true) {
0237 r = dmm_read(dmm, reg[PAT_STATUS][engine->id]);
0238 err = r & DMM_PATSTATUS_ERR;
0239 if (err) {
0240 dev_err(dmm->dev,
0241 "%s: error (engine%d). PAT_STATUS: 0x%08x\n",
0242 __func__, engine->id, r);
0243 return -EFAULT;
0244 }
0245
0246 if ((r & wait_mask) == wait_mask)
0247 break;
0248
0249 if (--i == 0) {
0250 dev_err(dmm->dev,
0251 "%s: timeout (engine%d). PAT_STATUS: 0x%08x\n",
0252 __func__, engine->id, r);
0253 return -ETIMEDOUT;
0254 }
0255
0256 udelay(1);
0257 }
0258
0259 return 0;
0260 }
0261
0262 static void release_engine(struct refill_engine *engine)
0263 {
0264 unsigned long flags;
0265
0266 spin_lock_irqsave(&list_lock, flags);
0267 list_add(&engine->idle_node, &omap_dmm->idle_head);
0268 spin_unlock_irqrestore(&list_lock, flags);
0269
0270 atomic_inc(&omap_dmm->engine_counter);
0271 wake_up_interruptible(&omap_dmm->engine_queue);
0272 }
0273
0274 static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
0275 {
0276 struct dmm *dmm = arg;
0277 u32 status = dmm_read(dmm, DMM_PAT_IRQSTATUS);
0278 int i;
0279
0280
0281 dmm_write(dmm, status, DMM_PAT_IRQSTATUS);
0282
0283 for (i = 0; i < dmm->num_engines; i++) {
0284 if (status & DMM_IRQSTAT_ERR_MASK)
0285 dev_err(dmm->dev,
0286 "irq error(engine%d): IRQSTAT 0x%02x\n",
0287 i, status & 0xff);
0288
0289 if (status & DMM_IRQSTAT_LST) {
0290 if (dmm->engines[i].async)
0291 release_engine(&dmm->engines[i]);
0292
0293 complete(&dmm->engines[i].compl);
0294 }
0295
0296 status >>= 8;
0297 }
0298
0299 return IRQ_HANDLED;
0300 }
0301
0302
0303
0304
0305 static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
0306 {
0307 struct dmm_txn *txn = NULL;
0308 struct refill_engine *engine = NULL;
0309 int ret;
0310 unsigned long flags;
0311
0312
0313
0314 ret = wait_event_interruptible(omap_dmm->engine_queue,
0315 atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
0316 if (ret)
0317 return ERR_PTR(ret);
0318
0319
0320 spin_lock_irqsave(&list_lock, flags);
0321 if (!list_empty(&dmm->idle_head)) {
0322 engine = list_entry(dmm->idle_head.next, struct refill_engine,
0323 idle_node);
0324 list_del(&engine->idle_node);
0325 }
0326 spin_unlock_irqrestore(&list_lock, flags);
0327
0328 BUG_ON(!engine);
0329
0330 txn = &engine->txn;
0331 engine->tcm = tcm;
0332 txn->engine_handle = engine;
0333 txn->last_pat = NULL;
0334 txn->current_va = engine->refill_va;
0335 txn->current_pa = engine->refill_pa;
0336
0337 return txn;
0338 }
0339
0340
0341
0342
0343
0344 static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
0345 struct page **pages, u32 npages, u32 roll)
0346 {
0347 dma_addr_t pat_pa = 0, data_pa = 0;
0348 u32 *data;
0349 struct pat *pat;
0350 struct refill_engine *engine = txn->engine_handle;
0351 int columns = (1 + area->x1 - area->x0);
0352 int rows = (1 + area->y1 - area->y0);
0353 int i = columns*rows;
0354
0355 pat = alloc_dma(txn, sizeof(*pat), &pat_pa);
0356
0357 if (txn->last_pat)
0358 txn->last_pat->next_pa = (u32)pat_pa;
0359
0360 pat->area = *area;
0361
0362
0363 pat->area.y0 += engine->tcm->y_offset;
0364 pat->area.y1 += engine->tcm->y_offset;
0365
0366 pat->ctrl = (struct pat_ctrl){
0367 .start = 1,
0368 .lut_id = engine->tcm->lut_id,
0369 };
0370
0371 data = alloc_dma(txn, 4*i, &data_pa);
0372
0373 pat->data_pa = data_pa;
0374
0375 while (i--) {
0376 int n = i + roll;
0377 if (n >= npages)
0378 n -= npages;
0379 data[i] = (pages && pages[n]) ?
0380 page_to_phys(pages[n]) : engine->dmm->dummy_pa;
0381 }
0382
0383 txn->last_pat = pat;
0384
0385 return;
0386 }
0387
0388
0389
0390
0391 static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
0392 {
0393 int ret = 0;
0394 struct refill_engine *engine = txn->engine_handle;
0395 struct dmm *dmm = engine->dmm;
0396
0397 if (!txn->last_pat) {
0398 dev_err(engine->dmm->dev, "need at least one txn\n");
0399 ret = -EINVAL;
0400 goto cleanup;
0401 }
0402
0403 txn->last_pat->next_pa = 0;
0404
0405 wmb();
0406
0407
0408
0409
0410
0411
0412
0413
0414 readl(&txn->last_pat->next_pa);
0415
0416
0417 dmm_write(dmm, 0x0, reg[PAT_DESCR][engine->id]);
0418
0419
0420 ret = wait_status(engine, DMM_PATSTATUS_READY);
0421 if (ret) {
0422 ret = -EFAULT;
0423 goto cleanup;
0424 }
0425
0426
0427 engine->async = wait ? false : true;
0428 reinit_completion(&engine->compl);
0429
0430 smp_mb();
0431
0432
0433 dmm_write(dmm, engine->refill_pa, reg[PAT_DESCR][engine->id]);
0434
0435 if (wait) {
0436 if (!wait_for_completion_timeout(&engine->compl,
0437 msecs_to_jiffies(100))) {
0438 dev_err(dmm->dev, "timed out waiting for done\n");
0439 ret = -ETIMEDOUT;
0440 goto cleanup;
0441 }
0442
0443
0444 ret = wait_status(engine, DMM_PATSTATUS_READY |
0445 DMM_PATSTATUS_VALID | DMM_PATSTATUS_DONE);
0446 }
0447
0448 cleanup:
0449
0450 if (ret || wait)
0451 release_engine(engine);
0452
0453 return ret;
0454 }
0455
0456
0457
0458
0459 static int fill(struct tcm_area *area, struct page **pages,
0460 u32 npages, u32 roll, bool wait)
0461 {
0462 int ret = 0;
0463 struct tcm_area slice, area_s;
0464 struct dmm_txn *txn;
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 wait = true;
0480
0481 txn = dmm_txn_init(omap_dmm, area->tcm);
0482 if (IS_ERR_OR_NULL(txn))
0483 return -ENOMEM;
0484
0485 tcm_for_each_slice(slice, *area, area_s) {
0486 struct pat_area p_area = {
0487 .x0 = slice.p0.x, .y0 = slice.p0.y,
0488 .x1 = slice.p1.x, .y1 = slice.p1.y,
0489 };
0490
0491 dmm_txn_append(txn, &p_area, pages, npages, roll);
0492
0493 roll += tcm_sizeof(slice);
0494 }
0495
0496 ret = dmm_txn_commit(txn, wait);
0497
0498 return ret;
0499 }
0500
0501
0502
0503
0504
0505
0506
0507 int tiler_pin(struct tiler_block *block, struct page **pages,
0508 u32 npages, u32 roll, bool wait)
0509 {
0510 int ret;
0511
0512 ret = fill(&block->area, pages, npages, roll, wait);
0513
0514 if (ret)
0515 tiler_unpin(block);
0516
0517 return ret;
0518 }
0519
0520 int tiler_unpin(struct tiler_block *block)
0521 {
0522 return fill(&block->area, NULL, 0, 0, false);
0523 }
0524
0525
0526
0527
0528 struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, u16 w,
0529 u16 h, u16 align)
0530 {
0531 struct tiler_block *block;
0532 u32 min_align = 128;
0533 int ret;
0534 unsigned long flags;
0535 u32 slot_bytes;
0536
0537 block = kzalloc(sizeof(*block), GFP_KERNEL);
0538 if (!block)
0539 return ERR_PTR(-ENOMEM);
0540
0541 BUG_ON(!validfmt(fmt));
0542
0543
0544 w = DIV_ROUND_UP(w, geom[fmt].slot_w);
0545 h = DIV_ROUND_UP(h, geom[fmt].slot_h);
0546
0547
0548 slot_bytes = geom[fmt].slot_w * geom[fmt].cpp;
0549 min_align = max(min_align, slot_bytes);
0550 align = (align > min_align) ? ALIGN(align, min_align) : min_align;
0551 align /= slot_bytes;
0552
0553 block->fmt = fmt;
0554
0555 ret = tcm_reserve_2d(containers[fmt], w, h, align, -1, slot_bytes,
0556 &block->area);
0557 if (ret) {
0558 kfree(block);
0559 return ERR_PTR(-ENOMEM);
0560 }
0561
0562
0563 spin_lock_irqsave(&list_lock, flags);
0564 list_add(&block->alloc_node, &omap_dmm->alloc_head);
0565 spin_unlock_irqrestore(&list_lock, flags);
0566
0567 return block;
0568 }
0569
0570 struct tiler_block *tiler_reserve_1d(size_t size)
0571 {
0572 struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
0573 int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
0574 unsigned long flags;
0575
0576 if (!block)
0577 return ERR_PTR(-ENOMEM);
0578
0579 block->fmt = TILFMT_PAGE;
0580
0581 if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
0582 &block->area)) {
0583 kfree(block);
0584 return ERR_PTR(-ENOMEM);
0585 }
0586
0587 spin_lock_irqsave(&list_lock, flags);
0588 list_add(&block->alloc_node, &omap_dmm->alloc_head);
0589 spin_unlock_irqrestore(&list_lock, flags);
0590
0591 return block;
0592 }
0593
0594
0595 int tiler_release(struct tiler_block *block)
0596 {
0597 int ret = tcm_free(&block->area);
0598 unsigned long flags;
0599
0600 if (block->area.tcm)
0601 dev_err(omap_dmm->dev, "failed to release block\n");
0602
0603 spin_lock_irqsave(&list_lock, flags);
0604 list_del(&block->alloc_node);
0605 spin_unlock_irqrestore(&list_lock, flags);
0606
0607 kfree(block);
0608 return ret;
0609 }
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634 static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y)
0635 {
0636 u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
0637
0638 x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
0639 y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
0640 alignment = geom[fmt].x_shft + geom[fmt].y_shft;
0641
0642
0643 x_mask = MASK(x_bits);
0644 y_mask = MASK(y_bits);
0645
0646 if (x < 0 || x > x_mask || y < 0 || y > y_mask) {
0647 DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u",
0648 x, x, x_mask, y, y, y_mask);
0649 return 0;
0650 }
0651
0652
0653 if (orient & MASK_X_INVERT)
0654 x ^= x_mask;
0655 if (orient & MASK_Y_INVERT)
0656 y ^= y_mask;
0657
0658
0659 if (orient & MASK_XY_FLIP)
0660 tmp = ((x << y_bits) + y);
0661 else
0662 tmp = ((y << x_bits) + x);
0663
0664 return TIL_ADDR((tmp << alignment), orient, fmt);
0665 }
0666
0667 dma_addr_t tiler_ssptr(struct tiler_block *block)
0668 {
0669 BUG_ON(!validfmt(block->fmt));
0670
0671 return TILVIEW_8BIT + tiler_get_address(block->fmt, 0,
0672 block->area.p0.x * geom[block->fmt].slot_w,
0673 block->area.p0.y * geom[block->fmt].slot_h);
0674 }
0675
0676 dma_addr_t tiler_tsptr(struct tiler_block *block, u32 orient,
0677 u32 x, u32 y)
0678 {
0679 struct tcm_pt *p = &block->area.p0;
0680 BUG_ON(!validfmt(block->fmt));
0681
0682 return tiler_get_address(block->fmt, orient,
0683 (p->x * geom[block->fmt].slot_w) + x,
0684 (p->y * geom[block->fmt].slot_h) + y);
0685 }
0686
0687 void tiler_align(enum tiler_fmt fmt, u16 *w, u16 *h)
0688 {
0689 BUG_ON(!validfmt(fmt));
0690 *w = round_up(*w, geom[fmt].slot_w);
0691 *h = round_up(*h, geom[fmt].slot_h);
0692 }
0693
0694 u32 tiler_stride(enum tiler_fmt fmt, u32 orient)
0695 {
0696 BUG_ON(!validfmt(fmt));
0697
0698 if (orient & MASK_XY_FLIP)
0699 return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
0700 else
0701 return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
0702 }
0703
0704 size_t tiler_size(enum tiler_fmt fmt, u16 w, u16 h)
0705 {
0706 tiler_align(fmt, &w, &h);
0707 return geom[fmt].cpp * w * h;
0708 }
0709
0710 size_t tiler_vsize(enum tiler_fmt fmt, u16 w, u16 h)
0711 {
0712 BUG_ON(!validfmt(fmt));
0713 return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
0714 }
0715
0716 u32 tiler_get_cpu_cache_flags(void)
0717 {
0718 return omap_dmm->plat_data->cpu_cache_flags;
0719 }
0720
0721 bool dmm_is_available(void)
0722 {
0723 return omap_dmm ? true : false;
0724 }
0725
0726 static int omap_dmm_remove(struct platform_device *dev)
0727 {
0728 struct tiler_block *block, *_block;
0729 int i;
0730 unsigned long flags;
0731
0732 if (omap_dmm) {
0733
0734 dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_CLR);
0735 free_irq(omap_dmm->irq, omap_dmm);
0736
0737
0738 spin_lock_irqsave(&list_lock, flags);
0739 list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
0740 alloc_node) {
0741 list_del(&block->alloc_node);
0742 kfree(block);
0743 }
0744 spin_unlock_irqrestore(&list_lock, flags);
0745
0746 for (i = 0; i < omap_dmm->num_lut; i++)
0747 if (omap_dmm->tcm && omap_dmm->tcm[i])
0748 omap_dmm->tcm[i]->deinit(omap_dmm->tcm[i]);
0749 kfree(omap_dmm->tcm);
0750
0751 kfree(omap_dmm->engines);
0752 if (omap_dmm->refill_va)
0753 dma_free_wc(omap_dmm->dev,
0754 REFILL_BUFFER_SIZE * omap_dmm->num_engines,
0755 omap_dmm->refill_va, omap_dmm->refill_pa);
0756 if (omap_dmm->dummy_page)
0757 __free_page(omap_dmm->dummy_page);
0758
0759 if (omap_dmm->dmm_workaround)
0760 dmm_workaround_uninit(omap_dmm);
0761
0762 iounmap(omap_dmm->base);
0763 kfree(omap_dmm);
0764 omap_dmm = NULL;
0765 }
0766
0767 return 0;
0768 }
0769
0770 static int omap_dmm_probe(struct platform_device *dev)
0771 {
0772 int ret = -EFAULT, i;
0773 struct tcm_area area = {0};
0774 u32 hwinfo, pat_geom;
0775 struct resource *mem;
0776
0777 omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
0778 if (!omap_dmm)
0779 goto fail;
0780
0781
0782 INIT_LIST_HEAD(&omap_dmm->alloc_head);
0783 INIT_LIST_HEAD(&omap_dmm->idle_head);
0784
0785 init_waitqueue_head(&omap_dmm->engine_queue);
0786
0787 if (dev->dev.of_node) {
0788 const struct of_device_id *match;
0789
0790 match = of_match_node(dmm_of_match, dev->dev.of_node);
0791 if (!match) {
0792 dev_err(&dev->dev, "failed to find matching device node\n");
0793 ret = -ENODEV;
0794 goto fail;
0795 }
0796
0797 omap_dmm->plat_data = match->data;
0798 }
0799
0800
0801 mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
0802 if (!mem) {
0803 dev_err(&dev->dev, "failed to get base address resource\n");
0804 goto fail;
0805 }
0806
0807 omap_dmm->phys_base = mem->start;
0808 omap_dmm->base = ioremap(mem->start, SZ_2K);
0809
0810 if (!omap_dmm->base) {
0811 dev_err(&dev->dev, "failed to get dmm base address\n");
0812 goto fail;
0813 }
0814
0815 omap_dmm->irq = platform_get_irq(dev, 0);
0816 if (omap_dmm->irq < 0) {
0817 dev_err(&dev->dev, "failed to get IRQ resource\n");
0818 goto fail;
0819 }
0820
0821 omap_dmm->dev = &dev->dev;
0822
0823 if (of_machine_is_compatible("ti,dra7")) {
0824
0825
0826
0827
0828
0829 if (!dmm_workaround_init(omap_dmm)) {
0830 omap_dmm->dmm_workaround = true;
0831 dev_info(&dev->dev,
0832 "workaround for errata i878 in use\n");
0833 } else {
0834 dev_warn(&dev->dev,
0835 "failed to initialize work-around for i878\n");
0836 }
0837 }
0838
0839 hwinfo = dmm_read(omap_dmm, DMM_PAT_HWINFO);
0840 omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
0841 omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
0842 omap_dmm->container_width = 256;
0843 omap_dmm->container_height = 128;
0844
0845 atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
0846
0847
0848 pat_geom = dmm_read(omap_dmm, DMM_PAT_GEOMETRY);
0849 omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
0850 omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
0851
0852
0853
0854 if (omap_dmm->lut_height != omap_dmm->container_height)
0855 omap_dmm->num_lut++;
0856
0857
0858 dmm_write(omap_dmm, 0x88888888, DMM_PAT_VIEW__0);
0859 dmm_write(omap_dmm, 0x88888888, DMM_PAT_VIEW__1);
0860 dmm_write(omap_dmm, 0x80808080, DMM_PAT_VIEW_MAP__0);
0861 dmm_write(omap_dmm, 0x80000000, DMM_PAT_VIEW_MAP_BASE);
0862 dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__0);
0863 dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__1);
0864
0865 omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
0866 if (!omap_dmm->dummy_page) {
0867 dev_err(&dev->dev, "could not allocate dummy page\n");
0868 ret = -ENOMEM;
0869 goto fail;
0870 }
0871
0872
0873 ret = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
0874 if (ret)
0875 goto fail;
0876
0877 omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
0878
0879
0880 omap_dmm->refill_va = dma_alloc_wc(&dev->dev,
0881 REFILL_BUFFER_SIZE * omap_dmm->num_engines,
0882 &omap_dmm->refill_pa, GFP_KERNEL);
0883 if (!omap_dmm->refill_va) {
0884 dev_err(&dev->dev, "could not allocate refill memory\n");
0885 ret = -ENOMEM;
0886 goto fail;
0887 }
0888
0889
0890 omap_dmm->engines = kcalloc(omap_dmm->num_engines,
0891 sizeof(*omap_dmm->engines), GFP_KERNEL);
0892 if (!omap_dmm->engines) {
0893 ret = -ENOMEM;
0894 goto fail;
0895 }
0896
0897 for (i = 0; i < omap_dmm->num_engines; i++) {
0898 omap_dmm->engines[i].id = i;
0899 omap_dmm->engines[i].dmm = omap_dmm;
0900 omap_dmm->engines[i].refill_va = omap_dmm->refill_va +
0901 (REFILL_BUFFER_SIZE * i);
0902 omap_dmm->engines[i].refill_pa = omap_dmm->refill_pa +
0903 (REFILL_BUFFER_SIZE * i);
0904 init_completion(&omap_dmm->engines[i].compl);
0905
0906 list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head);
0907 }
0908
0909 omap_dmm->tcm = kcalloc(omap_dmm->num_lut, sizeof(*omap_dmm->tcm),
0910 GFP_KERNEL);
0911 if (!omap_dmm->tcm) {
0912 ret = -ENOMEM;
0913 goto fail;
0914 }
0915
0916
0917
0918
0919
0920 for (i = 0; i < omap_dmm->num_lut; i++) {
0921 omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
0922 omap_dmm->container_height);
0923
0924 if (!omap_dmm->tcm[i]) {
0925 dev_err(&dev->dev, "failed to allocate container\n");
0926 ret = -ENOMEM;
0927 goto fail;
0928 }
0929
0930 omap_dmm->tcm[i]->lut_id = i;
0931 }
0932
0933
0934
0935
0936 containers[TILFMT_8BIT] = omap_dmm->tcm[0];
0937 containers[TILFMT_16BIT] = omap_dmm->tcm[0];
0938 containers[TILFMT_32BIT] = omap_dmm->tcm[0];
0939
0940 if (omap_dmm->container_height != omap_dmm->lut_height) {
0941
0942
0943
0944 containers[TILFMT_PAGE] = omap_dmm->tcm[1];
0945 omap_dmm->tcm[1]->y_offset = OMAP5_LUT_OFFSET;
0946 omap_dmm->tcm[1]->lut_id = 0;
0947 } else {
0948 containers[TILFMT_PAGE] = omap_dmm->tcm[0];
0949 }
0950
0951 area = (struct tcm_area) {
0952 .tcm = NULL,
0953 .p1.x = omap_dmm->container_width - 1,
0954 .p1.y = omap_dmm->container_height - 1,
0955 };
0956
0957 ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
0958 "omap_dmm_irq_handler", omap_dmm);
0959
0960 if (ret) {
0961 dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
0962 omap_dmm->irq, ret);
0963 omap_dmm->irq = -1;
0964 goto fail;
0965 }
0966
0967
0968
0969
0970
0971
0972
0973 dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_SET);
0974
0975
0976 for (i = 0; i < omap_dmm->num_lut; i++) {
0977 area.tcm = omap_dmm->tcm[i];
0978 if (fill(&area, NULL, 0, 0, true))
0979 dev_err(omap_dmm->dev, "refill failed");
0980 }
0981
0982 dev_info(omap_dmm->dev, "initialized all PAT entries\n");
0983
0984 return 0;
0985
0986 fail:
0987 if (omap_dmm_remove(dev))
0988 dev_err(&dev->dev, "cleanup failed\n");
0989 return ret;
0990 }
0991
0992
0993
0994
0995
0996 #ifdef CONFIG_DEBUG_FS
0997
0998 static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
0999 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1000 static const char *special = ".,:;'\"`~!^-+";
1001
1002 static void fill_map(char **map, int xdiv, int ydiv, struct tcm_area *a,
1003 char c, bool ovw)
1004 {
1005 int x, y;
1006 for (y = a->p0.y / ydiv; y <= a->p1.y / ydiv; y++)
1007 for (x = a->p0.x / xdiv; x <= a->p1.x / xdiv; x++)
1008 if (map[y][x] == ' ' || ovw)
1009 map[y][x] = c;
1010 }
1011
1012 static void fill_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p,
1013 char c)
1014 {
1015 map[p->y / ydiv][p->x / xdiv] = c;
1016 }
1017
1018 static char read_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p)
1019 {
1020 return map[p->y / ydiv][p->x / xdiv];
1021 }
1022
1023 static int map_width(int xdiv, int x0, int x1)
1024 {
1025 return (x1 / xdiv) - (x0 / xdiv) + 1;
1026 }
1027
1028 static void text_map(char **map, int xdiv, char *nice, int yd, int x0, int x1)
1029 {
1030 char *p = map[yd] + (x0 / xdiv);
1031 int w = (map_width(xdiv, x0, x1) - strlen(nice)) / 2;
1032 if (w >= 0) {
1033 p += w;
1034 while (*nice)
1035 *p++ = *nice++;
1036 }
1037 }
1038
1039 static void map_1d_info(char **map, int xdiv, int ydiv, char *nice,
1040 struct tcm_area *a)
1041 {
1042 sprintf(nice, "%dK", tcm_sizeof(*a) * 4);
1043 if (a->p0.y + 1 < a->p1.y) {
1044 text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv, 0,
1045 256 - 1);
1046 } else if (a->p0.y < a->p1.y) {
1047 if (strlen(nice) < map_width(xdiv, a->p0.x, 256 - 1))
1048 text_map(map, xdiv, nice, a->p0.y / ydiv,
1049 a->p0.x + xdiv, 256 - 1);
1050 else if (strlen(nice) < map_width(xdiv, 0, a->p1.x))
1051 text_map(map, xdiv, nice, a->p1.y / ydiv,
1052 0, a->p1.y - xdiv);
1053 } else if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x)) {
1054 text_map(map, xdiv, nice, a->p0.y / ydiv, a->p0.x, a->p1.x);
1055 }
1056 }
1057
1058 static void map_2d_info(char **map, int xdiv, int ydiv, char *nice,
1059 struct tcm_area *a)
1060 {
1061 sprintf(nice, "(%d*%d)", tcm_awidth(*a), tcm_aheight(*a));
1062 if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x))
1063 text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv,
1064 a->p0.x, a->p1.x);
1065 }
1066
1067 int tiler_map_show(struct seq_file *s, void *arg)
1068 {
1069 int xdiv = 2, ydiv = 1;
1070 char **map = NULL, *global_map;
1071 struct tiler_block *block;
1072 struct tcm_area a, p;
1073 int i;
1074 const char *m2d = alphabet;
1075 const char *a2d = special;
1076 const char *m2dp = m2d, *a2dp = a2d;
1077 char nice[128];
1078 int h_adj;
1079 int w_adj;
1080 unsigned long flags;
1081 int lut_idx;
1082
1083
1084 if (!omap_dmm) {
1085
1086 return 0;
1087 }
1088
1089 h_adj = omap_dmm->container_height / ydiv;
1090 w_adj = omap_dmm->container_width / xdiv;
1091
1092 map = kmalloc_array(h_adj, sizeof(*map), GFP_KERNEL);
1093 global_map = kmalloc_array(w_adj + 1, h_adj, GFP_KERNEL);
1094
1095 if (!map || !global_map)
1096 goto error;
1097
1098 for (lut_idx = 0; lut_idx < omap_dmm->num_lut; lut_idx++) {
1099 memset(map, 0, h_adj * sizeof(*map));
1100 memset(global_map, ' ', (w_adj + 1) * h_adj);
1101
1102 for (i = 0; i < omap_dmm->container_height; i++) {
1103 map[i] = global_map + i * (w_adj + 1);
1104 map[i][w_adj] = 0;
1105 }
1106
1107 spin_lock_irqsave(&list_lock, flags);
1108
1109 list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
1110 if (block->area.tcm == omap_dmm->tcm[lut_idx]) {
1111 if (block->fmt != TILFMT_PAGE) {
1112 fill_map(map, xdiv, ydiv, &block->area,
1113 *m2dp, true);
1114 if (!*++a2dp)
1115 a2dp = a2d;
1116 if (!*++m2dp)
1117 m2dp = m2d;
1118 map_2d_info(map, xdiv, ydiv, nice,
1119 &block->area);
1120 } else {
1121 bool start = read_map_pt(map, xdiv,
1122 ydiv, &block->area.p0) == ' ';
1123 bool end = read_map_pt(map, xdiv, ydiv,
1124 &block->area.p1) == ' ';
1125
1126 tcm_for_each_slice(a, block->area, p)
1127 fill_map(map, xdiv, ydiv, &a,
1128 '=', true);
1129 fill_map_pt(map, xdiv, ydiv,
1130 &block->area.p0,
1131 start ? '<' : 'X');
1132 fill_map_pt(map, xdiv, ydiv,
1133 &block->area.p1,
1134 end ? '>' : 'X');
1135 map_1d_info(map, xdiv, ydiv, nice,
1136 &block->area);
1137 }
1138 }
1139 }
1140
1141 spin_unlock_irqrestore(&list_lock, flags);
1142
1143 if (s) {
1144 seq_printf(s, "CONTAINER %d DUMP BEGIN\n", lut_idx);
1145 for (i = 0; i < 128; i++)
1146 seq_printf(s, "%03d:%s\n", i, map[i]);
1147 seq_printf(s, "CONTAINER %d DUMP END\n", lut_idx);
1148 } else {
1149 dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP BEGIN\n",
1150 lut_idx);
1151 for (i = 0; i < 128; i++)
1152 dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
1153 dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP END\n",
1154 lut_idx);
1155 }
1156 }
1157
1158 error:
1159 kfree(map);
1160 kfree(global_map);
1161
1162 return 0;
1163 }
1164 #endif
1165
1166 #ifdef CONFIG_PM_SLEEP
1167 static int omap_dmm_resume(struct device *dev)
1168 {
1169 struct tcm_area area;
1170 int i;
1171
1172 if (!omap_dmm)
1173 return -ENODEV;
1174
1175 area = (struct tcm_area) {
1176 .tcm = NULL,
1177 .p1.x = omap_dmm->container_width - 1,
1178 .p1.y = omap_dmm->container_height - 1,
1179 };
1180
1181
1182 for (i = 0; i < omap_dmm->num_lut; i++) {
1183 area.tcm = omap_dmm->tcm[i];
1184 if (fill(&area, NULL, 0, 0, true))
1185 dev_err(dev, "refill failed");
1186 }
1187
1188 return 0;
1189 }
1190 #endif
1191
1192 static SIMPLE_DEV_PM_OPS(omap_dmm_pm_ops, NULL, omap_dmm_resume);
1193
1194 #if defined(CONFIG_OF)
1195 static const struct dmm_platform_data dmm_omap4_platform_data = {
1196 .cpu_cache_flags = OMAP_BO_WC,
1197 };
1198
1199 static const struct dmm_platform_data dmm_omap5_platform_data = {
1200 .cpu_cache_flags = OMAP_BO_UNCACHED,
1201 };
1202
1203 static const struct of_device_id dmm_of_match[] = {
1204 {
1205 .compatible = "ti,omap4-dmm",
1206 .data = &dmm_omap4_platform_data,
1207 },
1208 {
1209 .compatible = "ti,omap5-dmm",
1210 .data = &dmm_omap5_platform_data,
1211 },
1212 {},
1213 };
1214 #endif
1215
1216 struct platform_driver omap_dmm_driver = {
1217 .probe = omap_dmm_probe,
1218 .remove = omap_dmm_remove,
1219 .driver = {
1220 .owner = THIS_MODULE,
1221 .name = DMM_DRIVER_NAME,
1222 .of_match_table = of_match_ptr(dmm_of_match),
1223 .pm = &omap_dmm_pm_ops,
1224 },
1225 };
1226
1227 MODULE_LICENSE("GPL v2");
1228 MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
1229 MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");