.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Driver for the Atmel Extensible DMA Controller (aka XDMAC on AT91 systems) |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2014 Atmel Corporation |
---|
5 | 6 | * |
---|
6 | 7 | * Author: Ludovic Desroches <ludovic.desroches@atmel.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify it |
---|
9 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
10 | | - * the Free Software Foundation. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that 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 along with |
---|
18 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
---|
19 | 8 | */ |
---|
20 | 9 | |
---|
21 | 10 | #include <asm/barrier.h> |
---|
.. | .. |
---|
223 | 212 | int irq; |
---|
224 | 213 | struct clk *clk; |
---|
225 | 214 | u32 save_gim; |
---|
| 215 | + u32 save_gs; |
---|
226 | 216 | struct dma_pool *at_xdmac_desc_pool; |
---|
227 | | - struct at_xdmac_chan chan[0]; |
---|
| 217 | + struct at_xdmac_chan chan[]; |
---|
228 | 218 | }; |
---|
229 | 219 | |
---|
230 | 220 | |
---|
.. | .. |
---|
309 | 299 | return csize; |
---|
310 | 300 | }; |
---|
311 | 301 | |
---|
| 302 | +static inline bool at_xdmac_chan_is_peripheral_xfer(u32 cfg) |
---|
| 303 | +{ |
---|
| 304 | + return cfg & AT_XDMAC_CC_TYPE_PER_TRAN; |
---|
| 305 | +} |
---|
| 306 | + |
---|
312 | 307 | static inline u8 at_xdmac_get_dwidth(u32 cfg) |
---|
313 | 308 | { |
---|
314 | 309 | return (cfg & AT_XDMAC_CC_DWIDTH_MASK) >> AT_XDMAC_CC_DWIDTH_OFFSET; |
---|
.. | .. |
---|
388 | 383 | at_xdmac_chan_read(atchan, AT_XDMAC_CUBC)); |
---|
389 | 384 | |
---|
390 | 385 | at_xdmac_chan_write(atchan, AT_XDMAC_CID, 0xffffffff); |
---|
391 | | - reg = AT_XDMAC_CIE_RBEIE | AT_XDMAC_CIE_WBEIE | AT_XDMAC_CIE_ROIE; |
---|
| 386 | + reg = AT_XDMAC_CIE_RBEIE | AT_XDMAC_CIE_WBEIE; |
---|
| 387 | + /* |
---|
| 388 | + * Request Overflow Error is only for peripheral synchronized transfers |
---|
| 389 | + */ |
---|
| 390 | + if (at_xdmac_chan_is_peripheral_xfer(first->lld.mbr_cfg)) |
---|
| 391 | + reg |= AT_XDMAC_CIE_ROIE; |
---|
| 392 | + |
---|
392 | 393 | /* |
---|
393 | 394 | * There is no end of list when doing cyclic dma, we need to get |
---|
394 | 395 | * an interrupt after each periods. |
---|
.. | .. |
---|
677 | 678 | if (!desc) { |
---|
678 | 679 | dev_err(chan2dev(chan), "can't get descriptor\n"); |
---|
679 | 680 | if (first) |
---|
680 | | - list_splice_init(&first->descs_list, &atchan->free_descs_list); |
---|
| 681 | + list_splice_tail_init(&first->descs_list, |
---|
| 682 | + &atchan->free_descs_list); |
---|
681 | 683 | goto spin_unlock; |
---|
682 | 684 | } |
---|
683 | 685 | |
---|
.. | .. |
---|
765 | 767 | if (!desc) { |
---|
766 | 768 | dev_err(chan2dev(chan), "can't get descriptor\n"); |
---|
767 | 769 | if (first) |
---|
768 | | - list_splice_init(&first->descs_list, &atchan->free_descs_list); |
---|
| 770 | + list_splice_tail_init(&first->descs_list, |
---|
| 771 | + &atchan->free_descs_list); |
---|
769 | 772 | spin_unlock_irqrestore(&atchan->lock, irqflags); |
---|
770 | 773 | return NULL; |
---|
771 | 774 | } |
---|
.. | .. |
---|
967 | 970 | NULL, |
---|
968 | 971 | src_addr, dst_addr, |
---|
969 | 972 | xt, xt->sgl); |
---|
| 973 | + if (!first) |
---|
| 974 | + return NULL; |
---|
970 | 975 | |
---|
971 | 976 | /* Length of the block is (BLEN+1) microblocks. */ |
---|
972 | 977 | for (i = 0; i < xt->numf - 1; i++) |
---|
.. | .. |
---|
997 | 1002 | src_addr, dst_addr, |
---|
998 | 1003 | xt, chunk); |
---|
999 | 1004 | if (!desc) { |
---|
1000 | | - list_splice_init(&first->descs_list, |
---|
1001 | | - &atchan->free_descs_list); |
---|
| 1005 | + if (first) |
---|
| 1006 | + list_splice_tail_init(&first->descs_list, |
---|
| 1007 | + &atchan->free_descs_list); |
---|
1002 | 1008 | return NULL; |
---|
1003 | 1009 | } |
---|
1004 | 1010 | |
---|
.. | .. |
---|
1076 | 1082 | if (!desc) { |
---|
1077 | 1083 | dev_err(chan2dev(chan), "can't get descriptor\n"); |
---|
1078 | 1084 | if (first) |
---|
1079 | | - list_splice_init(&first->descs_list, &atchan->free_descs_list); |
---|
| 1085 | + list_splice_tail_init(&first->descs_list, |
---|
| 1086 | + &atchan->free_descs_list); |
---|
1080 | 1087 | return NULL; |
---|
1081 | 1088 | } |
---|
1082 | 1089 | |
---|
.. | .. |
---|
1250 | 1257 | sg_dma_len(sg), |
---|
1251 | 1258 | value); |
---|
1252 | 1259 | if (!desc && first) |
---|
1253 | | - list_splice_init(&first->descs_list, |
---|
1254 | | - &atchan->free_descs_list); |
---|
| 1260 | + list_splice_tail_init(&first->descs_list, |
---|
| 1261 | + &atchan->free_descs_list); |
---|
1255 | 1262 | |
---|
1256 | 1263 | if (!first) |
---|
1257 | 1264 | first = desc; |
---|
.. | .. |
---|
1390 | 1397 | { |
---|
1391 | 1398 | struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); |
---|
1392 | 1399 | struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); |
---|
1393 | | - struct at_xdmac_desc *desc, *_desc; |
---|
| 1400 | + struct at_xdmac_desc *desc, *_desc, *iter; |
---|
1394 | 1401 | struct list_head *descs_list; |
---|
1395 | 1402 | enum dma_status ret; |
---|
1396 | 1403 | int residue, retry; |
---|
.. | .. |
---|
1505 | 1512 | * microblock. |
---|
1506 | 1513 | */ |
---|
1507 | 1514 | descs_list = &desc->descs_list; |
---|
1508 | | - list_for_each_entry_safe(desc, _desc, descs_list, desc_node) { |
---|
1509 | | - dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg); |
---|
1510 | | - residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth; |
---|
1511 | | - if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda) |
---|
| 1515 | + list_for_each_entry_safe(iter, _desc, descs_list, desc_node) { |
---|
| 1516 | + dwidth = at_xdmac_get_dwidth(iter->lld.mbr_cfg); |
---|
| 1517 | + residue -= (iter->lld.mbr_ubc & 0xffffff) << dwidth; |
---|
| 1518 | + if ((iter->lld.mbr_nda & 0xfffffffc) == cur_nda) { |
---|
| 1519 | + desc = iter; |
---|
1512 | 1520 | break; |
---|
| 1521 | + } |
---|
1513 | 1522 | } |
---|
1514 | 1523 | residue += cur_ubc << dwidth; |
---|
1515 | 1524 | |
---|
.. | .. |
---|
1524 | 1533 | return ret; |
---|
1525 | 1534 | } |
---|
1526 | 1535 | |
---|
1527 | | -/* Call must be protected by lock. */ |
---|
1528 | | -static void at_xdmac_remove_xfer(struct at_xdmac_chan *atchan, |
---|
1529 | | - struct at_xdmac_desc *desc) |
---|
1530 | | -{ |
---|
1531 | | - dev_dbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); |
---|
1532 | | - |
---|
1533 | | - /* |
---|
1534 | | - * Remove the transfer from the transfer list then move the transfer |
---|
1535 | | - * descriptors into the free descriptors list. |
---|
1536 | | - */ |
---|
1537 | | - list_del(&desc->xfer_node); |
---|
1538 | | - list_splice_init(&desc->descs_list, &atchan->free_descs_list); |
---|
1539 | | -} |
---|
1540 | | - |
---|
1541 | 1536 | static void at_xdmac_advance_work(struct at_xdmac_chan *atchan) |
---|
1542 | 1537 | { |
---|
1543 | 1538 | struct at_xdmac_desc *desc; |
---|
1544 | | - unsigned long flags; |
---|
1545 | | - |
---|
1546 | | - spin_lock_irqsave(&atchan->lock, flags); |
---|
1547 | 1539 | |
---|
1548 | 1540 | /* |
---|
1549 | 1541 | * If channel is enabled, do nothing, advance_work will be triggered |
---|
.. | .. |
---|
1557 | 1549 | if (!desc->active_xfer) |
---|
1558 | 1550 | at_xdmac_start_xfer(atchan, desc); |
---|
1559 | 1551 | } |
---|
1560 | | - |
---|
1561 | | - spin_unlock_irqrestore(&atchan->lock, flags); |
---|
1562 | 1552 | } |
---|
1563 | 1553 | |
---|
1564 | 1554 | static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan) |
---|
.. | .. |
---|
1566 | 1556 | struct at_xdmac_desc *desc; |
---|
1567 | 1557 | struct dma_async_tx_descriptor *txd; |
---|
1568 | 1558 | |
---|
1569 | | - desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node); |
---|
| 1559 | + spin_lock_irq(&atchan->lock); |
---|
| 1560 | + if (list_empty(&atchan->xfers_list)) { |
---|
| 1561 | + spin_unlock_irq(&atchan->lock); |
---|
| 1562 | + return; |
---|
| 1563 | + } |
---|
| 1564 | + desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, |
---|
| 1565 | + xfer_node); |
---|
| 1566 | + spin_unlock_irq(&atchan->lock); |
---|
1570 | 1567 | txd = &desc->tx_dma_desc; |
---|
1571 | | - |
---|
1572 | 1568 | if (txd->flags & DMA_PREP_INTERRUPT) |
---|
1573 | 1569 | dmaengine_desc_get_callback_invoke(txd, NULL); |
---|
1574 | 1570 | } |
---|
1575 | 1571 | |
---|
1576 | | -static void at_xdmac_tasklet(unsigned long data) |
---|
| 1572 | +static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) |
---|
1577 | 1573 | { |
---|
1578 | | - struct at_xdmac_chan *atchan = (struct at_xdmac_chan *)data; |
---|
| 1574 | + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); |
---|
| 1575 | + struct at_xdmac_desc *bad_desc; |
---|
| 1576 | + |
---|
| 1577 | + /* |
---|
| 1578 | + * The descriptor currently at the head of the active list is |
---|
| 1579 | + * broken. Since we don't have any way to report errors, we'll |
---|
| 1580 | + * just have to scream loudly and try to continue with other |
---|
| 1581 | + * descriptors queued (if any). |
---|
| 1582 | + */ |
---|
| 1583 | + if (atchan->irq_status & AT_XDMAC_CIS_RBEIS) |
---|
| 1584 | + dev_err(chan2dev(&atchan->chan), "read bus error!!!"); |
---|
| 1585 | + if (atchan->irq_status & AT_XDMAC_CIS_WBEIS) |
---|
| 1586 | + dev_err(chan2dev(&atchan->chan), "write bus error!!!"); |
---|
| 1587 | + if (atchan->irq_status & AT_XDMAC_CIS_ROIS) |
---|
| 1588 | + dev_err(chan2dev(&atchan->chan), "request overflow error!!!"); |
---|
| 1589 | + |
---|
| 1590 | + spin_lock_irq(&atchan->lock); |
---|
| 1591 | + |
---|
| 1592 | + /* Channel must be disabled first as it's not done automatically */ |
---|
| 1593 | + at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); |
---|
| 1594 | + while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask) |
---|
| 1595 | + cpu_relax(); |
---|
| 1596 | + |
---|
| 1597 | + bad_desc = list_first_entry(&atchan->xfers_list, |
---|
| 1598 | + struct at_xdmac_desc, |
---|
| 1599 | + xfer_node); |
---|
| 1600 | + |
---|
| 1601 | + spin_unlock_irq(&atchan->lock); |
---|
| 1602 | + |
---|
| 1603 | + /* Print bad descriptor's details if needed */ |
---|
| 1604 | + dev_dbg(chan2dev(&atchan->chan), |
---|
| 1605 | + "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", |
---|
| 1606 | + __func__, &bad_desc->lld.mbr_sa, &bad_desc->lld.mbr_da, |
---|
| 1607 | + bad_desc->lld.mbr_ubc); |
---|
| 1608 | + |
---|
| 1609 | + /* Then continue with usual descriptor management */ |
---|
| 1610 | +} |
---|
| 1611 | + |
---|
| 1612 | +static void at_xdmac_tasklet(struct tasklet_struct *t) |
---|
| 1613 | +{ |
---|
| 1614 | + struct at_xdmac_chan *atchan = from_tasklet(atchan, t, tasklet); |
---|
1579 | 1615 | struct at_xdmac_desc *desc; |
---|
1580 | 1616 | u32 error_mask; |
---|
1581 | 1617 | |
---|
.. | .. |
---|
1592 | 1628 | || (atchan->irq_status & error_mask)) { |
---|
1593 | 1629 | struct dma_async_tx_descriptor *txd; |
---|
1594 | 1630 | |
---|
1595 | | - if (atchan->irq_status & AT_XDMAC_CIS_RBEIS) |
---|
1596 | | - dev_err(chan2dev(&atchan->chan), "read bus error!!!"); |
---|
1597 | | - if (atchan->irq_status & AT_XDMAC_CIS_WBEIS) |
---|
1598 | | - dev_err(chan2dev(&atchan->chan), "write bus error!!!"); |
---|
1599 | | - if (atchan->irq_status & AT_XDMAC_CIS_ROIS) |
---|
1600 | | - dev_err(chan2dev(&atchan->chan), "request overflow error!!!"); |
---|
| 1631 | + if (atchan->irq_status & error_mask) |
---|
| 1632 | + at_xdmac_handle_error(atchan); |
---|
1601 | 1633 | |
---|
1602 | | - spin_lock_bh(&atchan->lock); |
---|
| 1634 | + spin_lock_irq(&atchan->lock); |
---|
1603 | 1635 | desc = list_first_entry(&atchan->xfers_list, |
---|
1604 | 1636 | struct at_xdmac_desc, |
---|
1605 | 1637 | xfer_node); |
---|
1606 | 1638 | dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); |
---|
1607 | 1639 | if (!desc->active_xfer) { |
---|
1608 | 1640 | dev_err(chan2dev(&atchan->chan), "Xfer not active: exiting"); |
---|
1609 | | - spin_unlock(&atchan->lock); |
---|
| 1641 | + spin_unlock_irq(&atchan->lock); |
---|
1610 | 1642 | return; |
---|
1611 | 1643 | } |
---|
1612 | 1644 | |
---|
1613 | 1645 | txd = &desc->tx_dma_desc; |
---|
| 1646 | + dma_cookie_complete(txd); |
---|
| 1647 | + /* Remove the transfer from the transfer list. */ |
---|
| 1648 | + list_del(&desc->xfer_node); |
---|
| 1649 | + spin_unlock_irq(&atchan->lock); |
---|
1614 | 1650 | |
---|
1615 | | - at_xdmac_remove_xfer(atchan, desc); |
---|
1616 | | - spin_unlock_bh(&atchan->lock); |
---|
1617 | | - |
---|
1618 | | - if (!at_xdmac_chan_is_cyclic(atchan)) { |
---|
1619 | | - dma_cookie_complete(txd); |
---|
1620 | | - if (txd->flags & DMA_PREP_INTERRUPT) |
---|
1621 | | - dmaengine_desc_get_callback_invoke(txd, NULL); |
---|
1622 | | - } |
---|
| 1651 | + if (txd->flags & DMA_PREP_INTERRUPT) |
---|
| 1652 | + dmaengine_desc_get_callback_invoke(txd, NULL); |
---|
1623 | 1653 | |
---|
1624 | 1654 | dma_run_dependencies(txd); |
---|
1625 | 1655 | |
---|
| 1656 | + spin_lock_irq(&atchan->lock); |
---|
| 1657 | + /* Move the xfer descriptors into the free descriptors list. */ |
---|
| 1658 | + list_splice_tail_init(&desc->descs_list, |
---|
| 1659 | + &atchan->free_descs_list); |
---|
1626 | 1660 | at_xdmac_advance_work(atchan); |
---|
| 1661 | + spin_unlock_irq(&atchan->lock); |
---|
1627 | 1662 | } |
---|
1628 | 1663 | } |
---|
1629 | 1664 | |
---|
.. | .. |
---|
1684 | 1719 | static void at_xdmac_issue_pending(struct dma_chan *chan) |
---|
1685 | 1720 | { |
---|
1686 | 1721 | struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); |
---|
| 1722 | + unsigned long flags; |
---|
1687 | 1723 | |
---|
1688 | 1724 | dev_dbg(chan2dev(&atchan->chan), "%s\n", __func__); |
---|
1689 | 1725 | |
---|
1690 | | - if (!at_xdmac_chan_is_cyclic(atchan)) |
---|
1691 | | - at_xdmac_advance_work(atchan); |
---|
| 1726 | + spin_lock_irqsave(&atchan->lock, flags); |
---|
| 1727 | + at_xdmac_advance_work(atchan); |
---|
| 1728 | + spin_unlock_irqrestore(&atchan->lock, flags); |
---|
1692 | 1729 | |
---|
1693 | 1730 | return; |
---|
1694 | 1731 | } |
---|
.. | .. |
---|
1766 | 1803 | cpu_relax(); |
---|
1767 | 1804 | |
---|
1768 | 1805 | /* Cancel all pending transfers. */ |
---|
1769 | | - list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node) |
---|
1770 | | - at_xdmac_remove_xfer(atchan, desc); |
---|
| 1806 | + list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node) { |
---|
| 1807 | + list_del(&desc->xfer_node); |
---|
| 1808 | + list_splice_tail_init(&desc->descs_list, |
---|
| 1809 | + &atchan->free_descs_list); |
---|
| 1810 | + } |
---|
1771 | 1811 | |
---|
1772 | 1812 | clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); |
---|
1773 | 1813 | clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status); |
---|
.. | .. |
---|
1781 | 1821 | struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); |
---|
1782 | 1822 | struct at_xdmac_desc *desc; |
---|
1783 | 1823 | int i; |
---|
1784 | | - unsigned long flags; |
---|
1785 | | - |
---|
1786 | | - spin_lock_irqsave(&atchan->lock, flags); |
---|
1787 | 1824 | |
---|
1788 | 1825 | if (at_xdmac_chan_is_enabled(atchan)) { |
---|
1789 | 1826 | dev_err(chan2dev(chan), |
---|
1790 | 1827 | "can't allocate channel resources (channel enabled)\n"); |
---|
1791 | | - i = -EIO; |
---|
1792 | | - goto spin_unlock; |
---|
| 1828 | + return -EIO; |
---|
1793 | 1829 | } |
---|
1794 | 1830 | |
---|
1795 | 1831 | if (!list_empty(&atchan->free_descs_list)) { |
---|
1796 | 1832 | dev_err(chan2dev(chan), |
---|
1797 | 1833 | "can't allocate channel resources (channel not free from a previous use)\n"); |
---|
1798 | | - i = -EIO; |
---|
1799 | | - goto spin_unlock; |
---|
| 1834 | + return -EIO; |
---|
1800 | 1835 | } |
---|
1801 | 1836 | |
---|
1802 | 1837 | for (i = 0; i < init_nr_desc_per_channel; i++) { |
---|
1803 | | - desc = at_xdmac_alloc_desc(chan, GFP_ATOMIC); |
---|
| 1838 | + desc = at_xdmac_alloc_desc(chan, GFP_KERNEL); |
---|
1804 | 1839 | if (!desc) { |
---|
| 1840 | + if (i == 0) { |
---|
| 1841 | + dev_warn(chan2dev(chan), |
---|
| 1842 | + "can't allocate any descriptors\n"); |
---|
| 1843 | + return -EIO; |
---|
| 1844 | + } |
---|
1805 | 1845 | dev_warn(chan2dev(chan), |
---|
1806 | 1846 | "only %d descriptors have been allocated\n", i); |
---|
1807 | 1847 | break; |
---|
.. | .. |
---|
1813 | 1853 | |
---|
1814 | 1854 | dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i); |
---|
1815 | 1855 | |
---|
1816 | | -spin_unlock: |
---|
1817 | | - spin_unlock_irqrestore(&atchan->lock, flags); |
---|
1818 | 1856 | return i; |
---|
1819 | 1857 | } |
---|
1820 | 1858 | |
---|
.. | .. |
---|
1871 | 1909 | } |
---|
1872 | 1910 | } |
---|
1873 | 1911 | atxdmac->save_gim = at_xdmac_read(atxdmac, AT_XDMAC_GIM); |
---|
| 1912 | + atxdmac->save_gs = at_xdmac_read(atxdmac, AT_XDMAC_GS); |
---|
1874 | 1913 | |
---|
1875 | 1914 | at_xdmac_off(atxdmac); |
---|
1876 | 1915 | clk_disable_unprepare(atxdmac->clk); |
---|
.. | .. |
---|
1907 | 1946 | at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, atchan->save_cndc); |
---|
1908 | 1947 | at_xdmac_chan_write(atchan, AT_XDMAC_CIE, atchan->save_cim); |
---|
1909 | 1948 | wmb(); |
---|
1910 | | - at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask); |
---|
| 1949 | + if (atxdmac->save_gs & atchan->mask) |
---|
| 1950 | + at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask); |
---|
1911 | 1951 | } |
---|
1912 | 1952 | } |
---|
1913 | 1953 | return 0; |
---|
.. | .. |
---|
1916 | 1956 | |
---|
1917 | 1957 | static int at_xdmac_probe(struct platform_device *pdev) |
---|
1918 | 1958 | { |
---|
1919 | | - struct resource *res; |
---|
1920 | 1959 | struct at_xdmac *atxdmac; |
---|
1921 | 1960 | int irq, size, nr_channels, i, ret; |
---|
1922 | 1961 | void __iomem *base; |
---|
1923 | 1962 | u32 reg; |
---|
1924 | 1963 | |
---|
1925 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1926 | | - if (!res) |
---|
1927 | | - return -EINVAL; |
---|
1928 | | - |
---|
1929 | 1964 | irq = platform_get_irq(pdev, 0); |
---|
1930 | 1965 | if (irq < 0) |
---|
1931 | 1966 | return irq; |
---|
1932 | 1967 | |
---|
1933 | | - base = devm_ioremap_resource(&pdev->dev, res); |
---|
| 1968 | + base = devm_platform_ioremap_resource(pdev, 0); |
---|
1934 | 1969 | if (IS_ERR(base)) |
---|
1935 | 1970 | return PTR_ERR(base); |
---|
1936 | 1971 | |
---|
.. | .. |
---|
2035 | 2070 | spin_lock_init(&atchan->lock); |
---|
2036 | 2071 | INIT_LIST_HEAD(&atchan->xfers_list); |
---|
2037 | 2072 | INIT_LIST_HEAD(&atchan->free_descs_list); |
---|
2038 | | - tasklet_init(&atchan->tasklet, at_xdmac_tasklet, |
---|
2039 | | - (unsigned long)atchan); |
---|
| 2073 | + tasklet_setup(&atchan->tasklet, at_xdmac_tasklet); |
---|
2040 | 2074 | |
---|
2041 | 2075 | /* Clear pending interrupts. */ |
---|
2042 | 2076 | while (at_xdmac_chan_read(atchan, AT_XDMAC_CIS)) |
---|