0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/export.h>
0010 #include <linux/pci.h>
0011 #include <linux/slab.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include <linux/of_irq.h>
0015 #include <linux/sched.h>
0016
0017 #include <asm/pasemi_dma.h>
0018
0019 #define MAX_TXCH 64
0020 #define MAX_RXCH 64
0021 #define MAX_FLAGS 64
0022 #define MAX_FUN 8
0023
0024 static struct pasdma_status *dma_status;
0025
0026 static void __iomem *iob_regs;
0027 static void __iomem *mac_regs[6];
0028 static void __iomem *dma_regs;
0029
0030 static int base_hw_irq;
0031
0032 static int num_txch, num_rxch;
0033
0034 static struct pci_dev *dma_pdev;
0035
0036
0037
0038 static DECLARE_BITMAP(txch_free, MAX_TXCH);
0039 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
0040 static DECLARE_BITMAP(flags_free, MAX_FLAGS);
0041 static DECLARE_BITMAP(fun_free, MAX_FUN);
0042
0043
0044
0045
0046 unsigned int pasemi_read_iob_reg(unsigned int reg)
0047 {
0048 return in_le32(iob_regs+reg);
0049 }
0050 EXPORT_SYMBOL(pasemi_read_iob_reg);
0051
0052
0053
0054
0055
0056 void pasemi_write_iob_reg(unsigned int reg, unsigned int val)
0057 {
0058 out_le32(iob_regs+reg, val);
0059 }
0060 EXPORT_SYMBOL(pasemi_write_iob_reg);
0061
0062
0063
0064
0065
0066 unsigned int pasemi_read_mac_reg(int intf, unsigned int reg)
0067 {
0068 return in_le32(mac_regs[intf]+reg);
0069 }
0070 EXPORT_SYMBOL(pasemi_read_mac_reg);
0071
0072
0073
0074
0075
0076
0077 void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val)
0078 {
0079 out_le32(mac_regs[intf]+reg, val);
0080 }
0081 EXPORT_SYMBOL(pasemi_write_mac_reg);
0082
0083
0084
0085
0086 unsigned int pasemi_read_dma_reg(unsigned int reg)
0087 {
0088 return in_le32(dma_regs+reg);
0089 }
0090 EXPORT_SYMBOL(pasemi_read_dma_reg);
0091
0092
0093
0094
0095
0096 void pasemi_write_dma_reg(unsigned int reg, unsigned int val)
0097 {
0098 out_le32(dma_regs+reg, val);
0099 }
0100 EXPORT_SYMBOL(pasemi_write_dma_reg);
0101
0102 static int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type)
0103 {
0104 int bit;
0105 int start, limit;
0106
0107 switch (type & (TXCHAN_EVT0|TXCHAN_EVT1)) {
0108 case TXCHAN_EVT0:
0109 start = 0;
0110 limit = 10;
0111 break;
0112 case TXCHAN_EVT1:
0113 start = 10;
0114 limit = MAX_TXCH;
0115 break;
0116 default:
0117 start = 0;
0118 limit = MAX_TXCH;
0119 break;
0120 }
0121 retry:
0122 bit = find_next_bit(txch_free, MAX_TXCH, start);
0123 if (bit >= limit)
0124 return -ENOSPC;
0125 if (!test_and_clear_bit(bit, txch_free))
0126 goto retry;
0127
0128 return bit;
0129 }
0130
0131 static void pasemi_free_tx_chan(int chan)
0132 {
0133 BUG_ON(test_bit(chan, txch_free));
0134 set_bit(chan, txch_free);
0135 }
0136
0137 static int pasemi_alloc_rx_chan(void)
0138 {
0139 int bit;
0140 retry:
0141 bit = find_first_bit(rxch_free, MAX_RXCH);
0142 if (bit >= MAX_TXCH)
0143 return -ENOSPC;
0144 if (!test_and_clear_bit(bit, rxch_free))
0145 goto retry;
0146
0147 return bit;
0148 }
0149
0150 static void pasemi_free_rx_chan(int chan)
0151 {
0152 BUG_ON(test_bit(chan, rxch_free));
0153 set_bit(chan, rxch_free);
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
0172 int total_size, int offset)
0173 {
0174 void *buf;
0175 struct pasemi_dmachan *chan;
0176 int chno;
0177
0178 BUG_ON(total_size < sizeof(struct pasemi_dmachan));
0179
0180 buf = kzalloc(total_size, GFP_KERNEL);
0181
0182 if (!buf)
0183 return NULL;
0184 chan = buf + offset;
0185
0186 chan->priv = buf;
0187
0188 switch (type & (TXCHAN|RXCHAN)) {
0189 case RXCHAN:
0190 chno = pasemi_alloc_rx_chan();
0191 chan->chno = chno;
0192 chan->irq = irq_create_mapping(NULL,
0193 base_hw_irq + num_txch + chno);
0194 chan->status = &dma_status->rx_sta[chno];
0195 break;
0196 case TXCHAN:
0197 chno = pasemi_alloc_tx_chan(type);
0198 chan->chno = chno;
0199 chan->irq = irq_create_mapping(NULL, base_hw_irq + chno);
0200 chan->status = &dma_status->tx_sta[chno];
0201 break;
0202 }
0203
0204 chan->chan_type = type;
0205
0206 return chan;
0207 }
0208 EXPORT_SYMBOL(pasemi_dma_alloc_chan);
0209
0210
0211
0212
0213
0214
0215
0216 void pasemi_dma_free_chan(struct pasemi_dmachan *chan)
0217 {
0218 if (chan->ring_virt)
0219 pasemi_dma_free_ring(chan);
0220
0221 switch (chan->chan_type & (RXCHAN|TXCHAN)) {
0222 case RXCHAN:
0223 pasemi_free_rx_chan(chan->chno);
0224 break;
0225 case TXCHAN:
0226 pasemi_free_tx_chan(chan->chno);
0227 break;
0228 }
0229
0230 kfree(chan->priv);
0231 }
0232 EXPORT_SYMBOL(pasemi_dma_free_chan);
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
0243 {
0244 BUG_ON(chan->ring_virt);
0245
0246 chan->ring_size = ring_size;
0247
0248 chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
0249 ring_size * sizeof(u64),
0250 &chan->ring_dma, GFP_KERNEL);
0251
0252 if (!chan->ring_virt)
0253 return -ENOMEM;
0254
0255 return 0;
0256 }
0257 EXPORT_SYMBOL(pasemi_dma_alloc_ring);
0258
0259
0260
0261
0262
0263
0264 void pasemi_dma_free_ring(struct pasemi_dmachan *chan)
0265 {
0266 BUG_ON(!chan->ring_virt);
0267
0268 dma_free_coherent(&dma_pdev->dev, chan->ring_size * sizeof(u64),
0269 chan->ring_virt, chan->ring_dma);
0270 chan->ring_virt = NULL;
0271 chan->ring_size = 0;
0272 chan->ring_dma = 0;
0273 }
0274 EXPORT_SYMBOL(pasemi_dma_free_ring);
0275
0276
0277
0278
0279
0280
0281
0282 void pasemi_dma_start_chan(const struct pasemi_dmachan *chan, const u32 cmdsta)
0283 {
0284 if (chan->chan_type == RXCHAN)
0285 pasemi_write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno),
0286 cmdsta | PAS_DMA_RXCHAN_CCMDSTA_EN);
0287 else
0288 pasemi_write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno),
0289 cmdsta | PAS_DMA_TXCHAN_TCMDSTA_EN);
0290 }
0291 EXPORT_SYMBOL(pasemi_dma_start_chan);
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 #define MAX_RETRIES 5000
0306 int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan)
0307 {
0308 int reg, retries;
0309 u32 sta;
0310
0311 if (chan->chan_type == RXCHAN) {
0312 reg = PAS_DMA_RXCHAN_CCMDSTA(chan->chno);
0313 pasemi_write_dma_reg(reg, PAS_DMA_RXCHAN_CCMDSTA_ST);
0314 for (retries = 0; retries < MAX_RETRIES; retries++) {
0315 sta = pasemi_read_dma_reg(reg);
0316 if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
0317 pasemi_write_dma_reg(reg, 0);
0318 return 1;
0319 }
0320 cond_resched();
0321 }
0322 } else {
0323 reg = PAS_DMA_TXCHAN_TCMDSTA(chan->chno);
0324 pasemi_write_dma_reg(reg, PAS_DMA_TXCHAN_TCMDSTA_ST);
0325 for (retries = 0; retries < MAX_RETRIES; retries++) {
0326 sta = pasemi_read_dma_reg(reg);
0327 if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
0328 pasemi_write_dma_reg(reg, 0);
0329 return 1;
0330 }
0331 cond_resched();
0332 }
0333 }
0334
0335 return 0;
0336 }
0337 EXPORT_SYMBOL(pasemi_dma_stop_chan);
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
0350 dma_addr_t *handle)
0351 {
0352 return dma_alloc_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
0353 }
0354 EXPORT_SYMBOL(pasemi_dma_alloc_buf);
0355
0356
0357
0358
0359
0360
0361
0362
0363 void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
0364 dma_addr_t *handle)
0365 {
0366 dma_free_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
0367 }
0368 EXPORT_SYMBOL(pasemi_dma_free_buf);
0369
0370
0371
0372
0373
0374
0375 int pasemi_dma_alloc_flag(void)
0376 {
0377 int bit;
0378
0379 retry:
0380 bit = find_first_bit(flags_free, MAX_FLAGS);
0381 if (bit >= MAX_FLAGS)
0382 return -ENOSPC;
0383 if (!test_and_clear_bit(bit, flags_free))
0384 goto retry;
0385
0386 return bit;
0387 }
0388 EXPORT_SYMBOL(pasemi_dma_alloc_flag);
0389
0390
0391
0392
0393
0394
0395
0396 void pasemi_dma_free_flag(int flag)
0397 {
0398 BUG_ON(test_bit(flag, flags_free));
0399 BUG_ON(flag >= MAX_FLAGS);
0400 set_bit(flag, flags_free);
0401 }
0402 EXPORT_SYMBOL(pasemi_dma_free_flag);
0403
0404
0405
0406
0407
0408
0409
0410 void pasemi_dma_set_flag(int flag)
0411 {
0412 BUG_ON(flag >= MAX_FLAGS);
0413 if (flag < 32)
0414 pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
0415 else
0416 pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
0417 }
0418 EXPORT_SYMBOL(pasemi_dma_set_flag);
0419
0420
0421
0422
0423
0424
0425 void pasemi_dma_clear_flag(int flag)
0426 {
0427 BUG_ON(flag >= MAX_FLAGS);
0428 if (flag < 32)
0429 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
0430 else
0431 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
0432 }
0433 EXPORT_SYMBOL(pasemi_dma_clear_flag);
0434
0435
0436
0437
0438
0439
0440 int pasemi_dma_alloc_fun(void)
0441 {
0442 int bit;
0443
0444 retry:
0445 bit = find_first_bit(fun_free, MAX_FLAGS);
0446 if (bit >= MAX_FLAGS)
0447 return -ENOSPC;
0448 if (!test_and_clear_bit(bit, fun_free))
0449 goto retry;
0450
0451 return bit;
0452 }
0453 EXPORT_SYMBOL(pasemi_dma_alloc_fun);
0454
0455
0456
0457
0458
0459
0460
0461 void pasemi_dma_free_fun(int fun)
0462 {
0463 BUG_ON(test_bit(fun, fun_free));
0464 BUG_ON(fun >= MAX_FLAGS);
0465 set_bit(fun, fun_free);
0466 }
0467 EXPORT_SYMBOL(pasemi_dma_free_fun);
0468
0469
0470 static void *map_onedev(struct pci_dev *p, int index)
0471 {
0472 struct device_node *dn;
0473 void __iomem *ret;
0474
0475 dn = pci_device_to_OF_node(p);
0476 if (!dn)
0477 goto fallback;
0478
0479 ret = of_iomap(dn, index);
0480 if (!ret)
0481 goto fallback;
0482
0483 return ret;
0484 fallback:
0485
0486
0487
0488
0489 return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499 int pasemi_dma_init(void)
0500 {
0501 static DEFINE_SPINLOCK(init_lock);
0502 struct pci_dev *iob_pdev;
0503 struct pci_dev *pdev;
0504 struct resource res;
0505 struct device_node *dn;
0506 int i, intf, err = 0;
0507 unsigned long timeout;
0508 u32 tmp;
0509
0510 if (!machine_is(pasemi))
0511 return -ENODEV;
0512
0513 spin_lock(&init_lock);
0514
0515
0516 if (dma_pdev)
0517 goto out;
0518
0519 iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
0520 if (!iob_pdev) {
0521 BUG();
0522 pr_warn("Can't find I/O Bridge\n");
0523 err = -ENODEV;
0524 goto out;
0525 }
0526 iob_regs = map_onedev(iob_pdev, 0);
0527
0528 dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
0529 if (!dma_pdev) {
0530 BUG();
0531 pr_warn("Can't find DMA controller\n");
0532 err = -ENODEV;
0533 goto out;
0534 }
0535 dma_regs = map_onedev(dma_pdev, 0);
0536 base_hw_irq = virq_to_hw(dma_pdev->irq);
0537
0538 pci_read_config_dword(dma_pdev, PAS_DMA_CAP_TXCH, &tmp);
0539 num_txch = (tmp & PAS_DMA_CAP_TXCH_TCHN_M) >> PAS_DMA_CAP_TXCH_TCHN_S;
0540
0541 pci_read_config_dword(dma_pdev, PAS_DMA_CAP_RXCH, &tmp);
0542 num_rxch = (tmp & PAS_DMA_CAP_RXCH_RCHN_M) >> PAS_DMA_CAP_RXCH_RCHN_S;
0543
0544 intf = 0;
0545 for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, NULL);
0546 pdev;
0547 pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, pdev))
0548 mac_regs[intf++] = map_onedev(pdev, 0);
0549
0550 pci_dev_put(pdev);
0551
0552 for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, NULL);
0553 pdev;
0554 pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, pdev))
0555 mac_regs[intf++] = map_onedev(pdev, 0);
0556
0557 pci_dev_put(pdev);
0558
0559 dn = pci_device_to_OF_node(iob_pdev);
0560 if (dn)
0561 err = of_address_to_resource(dn, 1, &res);
0562 if (!dn || err) {
0563
0564 res.start = 0xfd800000;
0565 res.end = res.start + 0x1000;
0566 }
0567 dma_status = ioremap_cache(res.start, resource_size(&res));
0568 pci_dev_put(iob_pdev);
0569
0570 for (i = 0; i < MAX_TXCH; i++)
0571 __set_bit(i, txch_free);
0572
0573 for (i = 0; i < MAX_RXCH; i++)
0574 __set_bit(i, rxch_free);
0575
0576 timeout = jiffies + HZ;
0577 pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
0578 while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) {
0579 if (time_after(jiffies, timeout)) {
0580 pr_warn("Warning: Could not disable RX section\n");
0581 break;
0582 }
0583 }
0584
0585 timeout = jiffies + HZ;
0586 pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
0587 while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) {
0588 if (time_after(jiffies, timeout)) {
0589 pr_warn("Warning: Could not disable TX section\n");
0590 break;
0591 }
0592 }
0593
0594
0595 tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
0596 pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
0597
0598
0599 pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
0600
0601
0602 pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
0603
0604 for (i = 0; i < MAX_FLAGS; i++)
0605 __set_bit(i, flags_free);
0606
0607 for (i = 0; i < MAX_FUN; i++)
0608 __set_bit(i, fun_free);
0609
0610
0611 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
0612 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
0613
0614 pr_info("PA Semi PWRficient DMA library initialized "
0615 "(%d tx, %d rx channels)\n", num_txch, num_rxch);
0616
0617 out:
0618 spin_unlock(&init_lock);
0619 return err;
0620 }
0621 EXPORT_SYMBOL(pasemi_dma_init);