diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/crypto/ux500/cryp/cryp.h | 7 | ||||
-rw-r--r-- | drivers/crypto/ux500/cryp/cryp_core.c | 31 | ||||
-rw-r--r-- | drivers/crypto/ux500/hash/hash_alg.h | 5 | ||||
-rw-r--r-- | drivers/crypto/ux500/hash/hash_core.c | 24 | ||||
-rw-r--r-- | drivers/dma/ste_dma40.c | 366 | ||||
-rw-r--r-- | drivers/dma/ste_dma40_ll.c | 106 | ||||
-rw-r--r-- | drivers/dma/ste_dma40_ll.h | 3 |
7 files changed, 322 insertions, 220 deletions
diff --git a/drivers/crypto/ux500/cryp/cryp.h b/drivers/crypto/ux500/cryp/cryp.h index 14cfd05b777a..d1d6606fe56c 100644 --- a/drivers/crypto/ux500/cryp/cryp.h +++ b/drivers/crypto/ux500/cryp/cryp.h | |||
@@ -114,6 +114,9 @@ enum cryp_status_id { | |||
114 | }; | 114 | }; |
115 | 115 | ||
116 | /* Cryp DMA interface */ | 116 | /* Cryp DMA interface */ |
117 | #define CRYP_DMA_TX_FIFO 0x08 | ||
118 | #define CRYP_DMA_RX_FIFO 0x10 | ||
119 | |||
117 | enum cryp_dma_req_type { | 120 | enum cryp_dma_req_type { |
118 | CRYP_DMA_DISABLE_BOTH, | 121 | CRYP_DMA_DISABLE_BOTH, |
119 | CRYP_DMA_ENABLE_IN_DATA, | 122 | CRYP_DMA_ENABLE_IN_DATA, |
@@ -217,7 +220,8 @@ struct cryp_dma { | |||
217 | 220 | ||
218 | /** | 221 | /** |
219 | * struct cryp_device_data - structure for a cryp device. | 222 | * struct cryp_device_data - structure for a cryp device. |
220 | * @base: Pointer to the hardware base address. | 223 | * @base: Pointer to virtual base address of the cryp device. |
224 | * @phybase: Pointer to physical memory location of the cryp device. | ||
221 | * @dev: Pointer to the devices dev structure. | 225 | * @dev: Pointer to the devices dev structure. |
222 | * @clk: Pointer to the device's clock control. | 226 | * @clk: Pointer to the device's clock control. |
223 | * @pwr_regulator: Pointer to the device's power control. | 227 | * @pwr_regulator: Pointer to the device's power control. |
@@ -232,6 +236,7 @@ struct cryp_dma { | |||
232 | */ | 236 | */ |
233 | struct cryp_device_data { | 237 | struct cryp_device_data { |
234 | struct cryp_register __iomem *base; | 238 | struct cryp_register __iomem *base; |
239 | phys_addr_t phybase; | ||
235 | struct device *dev; | 240 | struct device *dev; |
236 | struct clk *clk; | 241 | struct clk *clk; |
237 | struct regulator *pwr_regulator; | 242 | struct regulator *pwr_regulator; |
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index 32f480622b97..4f8b11af29a6 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c | |||
@@ -475,6 +475,19 @@ static int cryp_get_device_data(struct cryp_ctx *ctx, | |||
475 | static void cryp_dma_setup_channel(struct cryp_device_data *device_data, | 475 | static void cryp_dma_setup_channel(struct cryp_device_data *device_data, |
476 | struct device *dev) | 476 | struct device *dev) |
477 | { | 477 | { |
478 | struct dma_slave_config mem2cryp = { | ||
479 | .direction = DMA_MEM_TO_DEV, | ||
480 | .dst_addr = device_data->phybase + CRYP_DMA_TX_FIFO, | ||
481 | .dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, | ||
482 | .dst_maxburst = 4, | ||
483 | }; | ||
484 | struct dma_slave_config cryp2mem = { | ||
485 | .direction = DMA_DEV_TO_MEM, | ||
486 | .src_addr = device_data->phybase + CRYP_DMA_RX_FIFO, | ||
487 | .src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, | ||
488 | .src_maxburst = 4, | ||
489 | }; | ||
490 | |||
478 | dma_cap_zero(device_data->dma.mask); | 491 | dma_cap_zero(device_data->dma.mask); |
479 | dma_cap_set(DMA_SLAVE, device_data->dma.mask); | 492 | dma_cap_set(DMA_SLAVE, device_data->dma.mask); |
480 | 493 | ||
@@ -490,6 +503,9 @@ static void cryp_dma_setup_channel(struct cryp_device_data *device_data, | |||
490 | stedma40_filter, | 503 | stedma40_filter, |
491 | device_data->dma.cfg_cryp2mem); | 504 | device_data->dma.cfg_cryp2mem); |
492 | 505 | ||
506 | dmaengine_slave_config(device_data->dma.chan_mem2cryp, &mem2cryp); | ||
507 | dmaengine_slave_config(device_data->dma.chan_cryp2mem, &cryp2mem); | ||
508 | |||
493 | init_completion(&device_data->dma.cryp_dma_complete); | 509 | init_completion(&device_data->dma.cryp_dma_complete); |
494 | } | 510 | } |
495 | 511 | ||
@@ -1431,6 +1447,7 @@ static int ux500_cryp_probe(struct platform_device *pdev) | |||
1431 | goto out_kfree; | 1447 | goto out_kfree; |
1432 | } | 1448 | } |
1433 | 1449 | ||
1450 | device_data->phybase = res->start; | ||
1434 | device_data->base = ioremap(res->start, resource_size(res)); | 1451 | device_data->base = ioremap(res->start, resource_size(res)); |
1435 | if (!device_data->base) { | 1452 | if (!device_data->base) { |
1436 | dev_err(dev, "[%s]: ioremap failed!", __func__); | 1453 | dev_err(dev, "[%s]: ioremap failed!", __func__); |
@@ -1458,11 +1475,17 @@ static int ux500_cryp_probe(struct platform_device *pdev) | |||
1458 | goto out_regulator; | 1475 | goto out_regulator; |
1459 | } | 1476 | } |
1460 | 1477 | ||
1478 | ret = clk_prepare(device_data->clk); | ||
1479 | if (ret) { | ||
1480 | dev_err(dev, "[%s]: clk_prepare() failed!", __func__); | ||
1481 | goto out_clk; | ||
1482 | } | ||
1483 | |||
1461 | /* Enable device power (and clock) */ | 1484 | /* Enable device power (and clock) */ |
1462 | ret = cryp_enable_power(device_data->dev, device_data, false); | 1485 | ret = cryp_enable_power(device_data->dev, device_data, false); |
1463 | if (ret) { | 1486 | if (ret) { |
1464 | dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__); | 1487 | dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__); |
1465 | goto out_clk; | 1488 | goto out_clk_unprepare; |
1466 | } | 1489 | } |
1467 | 1490 | ||
1468 | cryp_error = cryp_check(device_data); | 1491 | cryp_error = cryp_check(device_data); |
@@ -1518,11 +1541,16 @@ static int ux500_cryp_probe(struct platform_device *pdev) | |||
1518 | goto out_power; | 1541 | goto out_power; |
1519 | } | 1542 | } |
1520 | 1543 | ||
1544 | dev_info(dev, "successfully registered\n"); | ||
1545 | |||
1521 | return 0; | 1546 | return 0; |
1522 | 1547 | ||
1523 | out_power: | 1548 | out_power: |
1524 | cryp_disable_power(device_data->dev, device_data, false); | 1549 | cryp_disable_power(device_data->dev, device_data, false); |
1525 | 1550 | ||
1551 | out_clk_unprepare: | ||
1552 | clk_unprepare(device_data->clk); | ||
1553 | |||
1526 | out_clk: | 1554 | out_clk: |
1527 | clk_put(device_data->clk); | 1555 | clk_put(device_data->clk); |
1528 | 1556 | ||
@@ -1593,6 +1621,7 @@ static int ux500_cryp_remove(struct platform_device *pdev) | |||
1593 | dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed", | 1621 | dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed", |
1594 | __func__); | 1622 | __func__); |
1595 | 1623 | ||
1624 | clk_unprepare(device_data->clk); | ||
1596 | clk_put(device_data->clk); | 1625 | clk_put(device_data->clk); |
1597 | regulator_put(device_data->pwr_regulator); | 1626 | regulator_put(device_data->pwr_regulator); |
1598 | 1627 | ||
diff --git a/drivers/crypto/ux500/hash/hash_alg.h b/drivers/crypto/ux500/hash/hash_alg.h index cd9351cb24df..be6eb54da40f 100644 --- a/drivers/crypto/ux500/hash/hash_alg.h +++ b/drivers/crypto/ux500/hash/hash_alg.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | 12 | ||
13 | #define HASH_BLOCK_SIZE 64 | 13 | #define HASH_BLOCK_SIZE 64 |
14 | #define HASH_DMA_FIFO 4 | ||
14 | #define HASH_DMA_ALIGN_SIZE 4 | 15 | #define HASH_DMA_ALIGN_SIZE 4 |
15 | #define HASH_DMA_PERFORMANCE_MIN_SIZE 1024 | 16 | #define HASH_DMA_PERFORMANCE_MIN_SIZE 1024 |
16 | #define HASH_BYTES_PER_WORD 4 | 17 | #define HASH_BYTES_PER_WORD 4 |
@@ -347,7 +348,8 @@ struct hash_req_ctx { | |||
347 | 348 | ||
348 | /** | 349 | /** |
349 | * struct hash_device_data - structure for a hash device. | 350 | * struct hash_device_data - structure for a hash device. |
350 | * @base: Pointer to the hardware base address. | 351 | * @base: Pointer to virtual base address of the hash device. |
352 | * @phybase: Pointer to physical memory location of the hash device. | ||
351 | * @list_node: For inclusion in klist. | 353 | * @list_node: For inclusion in klist. |
352 | * @dev: Pointer to the device dev structure. | 354 | * @dev: Pointer to the device dev structure. |
353 | * @ctx_lock: Spinlock for current_ctx. | 355 | * @ctx_lock: Spinlock for current_ctx. |
@@ -361,6 +363,7 @@ struct hash_req_ctx { | |||
361 | */ | 363 | */ |
362 | struct hash_device_data { | 364 | struct hash_device_data { |
363 | struct hash_register __iomem *base; | 365 | struct hash_register __iomem *base; |
366 | phys_addr_t phybase; | ||
364 | struct klist_node list_node; | 367 | struct klist_node list_node; |
365 | struct device *dev; | 368 | struct device *dev; |
366 | struct spinlock ctx_lock; | 369 | struct spinlock ctx_lock; |
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c index cf5508967539..9ca6fbb5e30d 100644 --- a/drivers/crypto/ux500/hash/hash_core.c +++ b/drivers/crypto/ux500/hash/hash_core.c | |||
@@ -122,6 +122,13 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data, | |||
122 | struct device *dev) | 122 | struct device *dev) |
123 | { | 123 | { |
124 | struct hash_platform_data *platform_data = dev->platform_data; | 124 | struct hash_platform_data *platform_data = dev->platform_data; |
125 | struct dma_slave_config conf = { | ||
126 | .direction = DMA_MEM_TO_DEV, | ||
127 | .dst_addr = device_data->phybase + HASH_DMA_FIFO, | ||
128 | .dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, | ||
129 | .dst_maxburst = 16, | ||
130 | }; | ||
131 | |||
125 | dma_cap_zero(device_data->dma.mask); | 132 | dma_cap_zero(device_data->dma.mask); |
126 | dma_cap_set(DMA_SLAVE, device_data->dma.mask); | 133 | dma_cap_set(DMA_SLAVE, device_data->dma.mask); |
127 | 134 | ||
@@ -131,6 +138,8 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data, | |||
131 | platform_data->dma_filter, | 138 | platform_data->dma_filter, |
132 | device_data->dma.cfg_mem2hash); | 139 | device_data->dma.cfg_mem2hash); |
133 | 140 | ||
141 | dmaengine_slave_config(device_data->dma.chan_mem2hash, &conf); | ||
142 | |||
134 | init_completion(&device_data->dma.complete); | 143 | init_completion(&device_data->dma.complete); |
135 | } | 144 | } |
136 | 145 | ||
@@ -1699,6 +1708,7 @@ static int ux500_hash_probe(struct platform_device *pdev) | |||
1699 | goto out_kfree; | 1708 | goto out_kfree; |
1700 | } | 1709 | } |
1701 | 1710 | ||
1711 | device_data->phybase = res->start; | ||
1702 | device_data->base = ioremap(res->start, resource_size(res)); | 1712 | device_data->base = ioremap(res->start, resource_size(res)); |
1703 | if (!device_data->base) { | 1713 | if (!device_data->base) { |
1704 | dev_err(dev, "[%s] ioremap() failed!", | 1714 | dev_err(dev, "[%s] ioremap() failed!", |
@@ -1726,11 +1736,17 @@ static int ux500_hash_probe(struct platform_device *pdev) | |||
1726 | goto out_regulator; | 1736 | goto out_regulator; |
1727 | } | 1737 | } |
1728 | 1738 | ||
1739 | ret = clk_prepare(device_data->clk); | ||
1740 | if (ret) { | ||
1741 | dev_err(dev, "[%s] clk_prepare() failed!", __func__); | ||
1742 | goto out_clk; | ||
1743 | } | ||
1744 | |||
1729 | /* Enable device power (and clock) */ | 1745 | /* Enable device power (and clock) */ |
1730 | ret = hash_enable_power(device_data, false); | 1746 | ret = hash_enable_power(device_data, false); |
1731 | if (ret) { | 1747 | if (ret) { |
1732 | dev_err(dev, "[%s]: hash_enable_power() failed!", __func__); | 1748 | dev_err(dev, "[%s]: hash_enable_power() failed!", __func__); |
1733 | goto out_clk; | 1749 | goto out_clk_unprepare; |
1734 | } | 1750 | } |
1735 | 1751 | ||
1736 | ret = hash_check_hw(device_data); | 1752 | ret = hash_check_hw(device_data); |
@@ -1756,12 +1772,15 @@ static int ux500_hash_probe(struct platform_device *pdev) | |||
1756 | goto out_power; | 1772 | goto out_power; |
1757 | } | 1773 | } |
1758 | 1774 | ||
1759 | dev_info(dev, "[%s] successfully probed\n", __func__); | 1775 | dev_info(dev, "successfully registered\n"); |
1760 | return 0; | 1776 | return 0; |
1761 | 1777 | ||
1762 | out_power: | 1778 | out_power: |
1763 | hash_disable_power(device_data, false); | 1779 | hash_disable_power(device_data, false); |
1764 | 1780 | ||
1781 | out_clk_unprepare: | ||
1782 | clk_unprepare(device_data->clk); | ||
1783 | |||
1765 | out_clk: | 1784 | out_clk: |
1766 | clk_put(device_data->clk); | 1785 | clk_put(device_data->clk); |
1767 | 1786 | ||
@@ -1826,6 +1845,7 @@ static int ux500_hash_remove(struct platform_device *pdev) | |||
1826 | dev_err(dev, "[%s]: hash_disable_power() failed", | 1845 | dev_err(dev, "[%s]: hash_disable_power() failed", |
1827 | __func__); | 1846 | __func__); |
1828 | 1847 | ||
1848 | clk_unprepare(device_data->clk); | ||
1829 | clk_put(device_data->clk); | 1849 | clk_put(device_data->clk); |
1830 | regulator_put(device_data->regulator); | 1850 | regulator_put(device_data->regulator); |
1831 | 1851 | ||
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 1734feec47b1..6ed775736853 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/pm_runtime.h> | 18 | #include <linux/pm_runtime.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_dma.h> | ||
20 | #include <linux/amba/bus.h> | 22 | #include <linux/amba/bus.h> |
21 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
22 | #include <linux/platform_data/dma-ste-dma40.h> | 24 | #include <linux/platform_data/dma-ste-dma40.h> |
@@ -45,6 +47,9 @@ | |||
45 | #define D40_LCLA_LINK_PER_EVENT_GRP 128 | 47 | #define D40_LCLA_LINK_PER_EVENT_GRP 128 |
46 | #define D40_LCLA_END D40_LCLA_LINK_PER_EVENT_GRP | 48 | #define D40_LCLA_END D40_LCLA_LINK_PER_EVENT_GRP |
47 | 49 | ||
50 | /* Max number of logical channels per physical channel */ | ||
51 | #define D40_MAX_LOG_CHAN_PER_PHY 32 | ||
52 | |||
48 | /* Attempts before giving up to trying to get pages that are aligned */ | 53 | /* Attempts before giving up to trying to get pages that are aligned */ |
49 | #define MAX_LCLA_ALLOC_ATTEMPTS 256 | 54 | #define MAX_LCLA_ALLOC_ATTEMPTS 256 |
50 | 55 | ||
@@ -53,7 +58,50 @@ | |||
53 | #define D40_ALLOC_PHY (1 << 30) | 58 | #define D40_ALLOC_PHY (1 << 30) |
54 | #define D40_ALLOC_LOG_FREE 0 | 59 | #define D40_ALLOC_LOG_FREE 0 |
55 | 60 | ||
56 | #define MAX(a, b) (((a) < (b)) ? (b) : (a)) | 61 | /* Reserved event lines for memcpy only. */ |
62 | #define DB8500_DMA_MEMCPY_EV_0 51 | ||
63 | #define DB8500_DMA_MEMCPY_EV_1 56 | ||
64 | #define DB8500_DMA_MEMCPY_EV_2 57 | ||
65 | #define DB8500_DMA_MEMCPY_EV_3 58 | ||
66 | #define DB8500_DMA_MEMCPY_EV_4 59 | ||
67 | #define DB8500_DMA_MEMCPY_EV_5 60 | ||
68 | |||
69 | static int dma40_memcpy_channels[] = { | ||
70 | DB8500_DMA_MEMCPY_EV_0, | ||
71 | DB8500_DMA_MEMCPY_EV_1, | ||
72 | DB8500_DMA_MEMCPY_EV_2, | ||
73 | DB8500_DMA_MEMCPY_EV_3, | ||
74 | DB8500_DMA_MEMCPY_EV_4, | ||
75 | DB8500_DMA_MEMCPY_EV_5, | ||
76 | }; | ||
77 | |||
78 | /* Default configuration for physcial memcpy */ | ||
79 | struct stedma40_chan_cfg dma40_memcpy_conf_phy = { | ||
80 | .mode = STEDMA40_MODE_PHYSICAL, | ||
81 | .dir = STEDMA40_MEM_TO_MEM, | ||
82 | |||
83 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | ||
84 | .src_info.psize = STEDMA40_PSIZE_PHY_1, | ||
85 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
86 | |||
87 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | ||
88 | .dst_info.psize = STEDMA40_PSIZE_PHY_1, | ||
89 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
90 | }; | ||
91 | |||
92 | /* Default configuration for logical memcpy */ | ||
93 | struct stedma40_chan_cfg dma40_memcpy_conf_log = { | ||
94 | .mode = STEDMA40_MODE_LOGICAL, | ||
95 | .dir = STEDMA40_MEM_TO_MEM, | ||
96 | |||
97 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | ||
98 | .src_info.psize = STEDMA40_PSIZE_LOG_1, | ||
99 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
100 | |||
101 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | ||
102 | .dst_info.psize = STEDMA40_PSIZE_LOG_1, | ||
103 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
104 | }; | ||
57 | 105 | ||
58 | /** | 106 | /** |
59 | * enum 40_command - The different commands and/or statuses. | 107 | * enum 40_command - The different commands and/or statuses. |
@@ -171,6 +219,9 @@ static u32 d40_backup_regs_chan[] = { | |||
171 | D40_CHAN_REG_SDLNK, | 219 | D40_CHAN_REG_SDLNK, |
172 | }; | 220 | }; |
173 | 221 | ||
222 | #define BACKUP_REGS_SZ_MAX ((BACKUP_REGS_SZ_V4A > BACKUP_REGS_SZ_V4B) ? \ | ||
223 | BACKUP_REGS_SZ_V4A : BACKUP_REGS_SZ_V4B) | ||
224 | |||
174 | /** | 225 | /** |
175 | * struct d40_interrupt_lookup - lookup table for interrupt handler | 226 | * struct d40_interrupt_lookup - lookup table for interrupt handler |
176 | * | 227 | * |
@@ -534,7 +585,7 @@ struct d40_base { | |||
534 | resource_size_t lcpa_size; | 585 | resource_size_t lcpa_size; |
535 | struct kmem_cache *desc_slab; | 586 | struct kmem_cache *desc_slab; |
536 | u32 reg_val_backup[BACKUP_REGS_SZ]; | 587 | u32 reg_val_backup[BACKUP_REGS_SZ]; |
537 | u32 reg_val_backup_v4[MAX(BACKUP_REGS_SZ_V4A, BACKUP_REGS_SZ_V4B)]; | 588 | u32 reg_val_backup_v4[BACKUP_REGS_SZ_MAX]; |
538 | u32 *reg_val_backup_chan; | 589 | u32 *reg_val_backup_chan; |
539 | u16 gcc_pwr_off_mask; | 590 | u16 gcc_pwr_off_mask; |
540 | bool initialized; | 591 | bool initialized; |
@@ -1257,21 +1308,17 @@ static void __d40_config_set_event(struct d40_chan *d40c, | |||
1257 | static void d40_config_set_event(struct d40_chan *d40c, | 1308 | static void d40_config_set_event(struct d40_chan *d40c, |
1258 | enum d40_events event_type) | 1309 | enum d40_events event_type) |
1259 | { | 1310 | { |
1311 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); | ||
1312 | |||
1260 | /* Enable event line connected to device (or memcpy) */ | 1313 | /* Enable event line connected to device (or memcpy) */ |
1261 | if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || | 1314 | if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || |
1262 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) { | 1315 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) |
1263 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); | ||
1264 | |||
1265 | __d40_config_set_event(d40c, event_type, event, | 1316 | __d40_config_set_event(d40c, event_type, event, |
1266 | D40_CHAN_REG_SSLNK); | 1317 | D40_CHAN_REG_SSLNK); |
1267 | } | ||
1268 | |||
1269 | if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) { | ||
1270 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); | ||
1271 | 1318 | ||
1319 | if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) | ||
1272 | __d40_config_set_event(d40c, event_type, event, | 1320 | __d40_config_set_event(d40c, event_type, event, |
1273 | D40_CHAN_REG_SDLNK); | 1321 | D40_CHAN_REG_SDLNK); |
1274 | } | ||
1275 | } | 1322 | } |
1276 | 1323 | ||
1277 | static u32 d40_chan_has_events(struct d40_chan *d40c) | 1324 | static u32 d40_chan_has_events(struct d40_chan *d40c) |
@@ -1713,8 +1760,6 @@ static int d40_validate_conf(struct d40_chan *d40c, | |||
1713 | struct stedma40_chan_cfg *conf) | 1760 | struct stedma40_chan_cfg *conf) |
1714 | { | 1761 | { |
1715 | int res = 0; | 1762 | int res = 0; |
1716 | u32 dst_event_group = D40_TYPE_TO_GROUP(conf->dst_dev_type); | ||
1717 | u32 src_event_group = D40_TYPE_TO_GROUP(conf->src_dev_type); | ||
1718 | bool is_log = conf->mode == STEDMA40_MODE_LOGICAL; | 1763 | bool is_log = conf->mode == STEDMA40_MODE_LOGICAL; |
1719 | 1764 | ||
1720 | if (!conf->dir) { | 1765 | if (!conf->dir) { |
@@ -1722,44 +1767,10 @@ static int d40_validate_conf(struct d40_chan *d40c, | |||
1722 | res = -EINVAL; | 1767 | res = -EINVAL; |
1723 | } | 1768 | } |
1724 | 1769 | ||
1725 | if (conf->dst_dev_type != STEDMA40_DEV_DST_MEMORY && | 1770 | if ((is_log && conf->dev_type > d40c->base->num_log_chans) || |
1726 | d40c->base->plat_data->dev_tx[conf->dst_dev_type] == 0 && | 1771 | (!is_log && conf->dev_type > d40c->base->num_phy_chans) || |
1727 | d40c->runtime_addr == 0) { | 1772 | (conf->dev_type < 0)) { |
1728 | 1773 | chan_err(d40c, "Invalid device type (%d)\n", conf->dev_type); | |
1729 | chan_err(d40c, "Invalid TX channel address (%d)\n", | ||
1730 | conf->dst_dev_type); | ||
1731 | res = -EINVAL; | ||
1732 | } | ||
1733 | |||
1734 | if (conf->src_dev_type != STEDMA40_DEV_SRC_MEMORY && | ||
1735 | d40c->base->plat_data->dev_rx[conf->src_dev_type] == 0 && | ||
1736 | d40c->runtime_addr == 0) { | ||
1737 | chan_err(d40c, "Invalid RX channel address (%d)\n", | ||
1738 | conf->src_dev_type); | ||
1739 | res = -EINVAL; | ||
1740 | } | ||
1741 | |||
1742 | if (conf->dir == STEDMA40_MEM_TO_PERIPH && | ||
1743 | dst_event_group == STEDMA40_DEV_DST_MEMORY) { | ||
1744 | chan_err(d40c, "Invalid dst\n"); | ||
1745 | res = -EINVAL; | ||
1746 | } | ||
1747 | |||
1748 | if (conf->dir == STEDMA40_PERIPH_TO_MEM && | ||
1749 | src_event_group == STEDMA40_DEV_SRC_MEMORY) { | ||
1750 | chan_err(d40c, "Invalid src\n"); | ||
1751 | res = -EINVAL; | ||
1752 | } | ||
1753 | |||
1754 | if (src_event_group == STEDMA40_DEV_SRC_MEMORY && | ||
1755 | dst_event_group == STEDMA40_DEV_DST_MEMORY && is_log) { | ||
1756 | chan_err(d40c, "No event line\n"); | ||
1757 | res = -EINVAL; | ||
1758 | } | ||
1759 | |||
1760 | if (conf->dir == STEDMA40_PERIPH_TO_PERIPH && | ||
1761 | (src_event_group != dst_event_group)) { | ||
1762 | chan_err(d40c, "Invalid event group\n"); | ||
1763 | res = -EINVAL; | 1774 | res = -EINVAL; |
1764 | } | 1775 | } |
1765 | 1776 | ||
@@ -1880,7 +1891,7 @@ out: | |||
1880 | 1891 | ||
1881 | static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) | 1892 | static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) |
1882 | { | 1893 | { |
1883 | int dev_type; | 1894 | int dev_type = d40c->dma_cfg.dev_type; |
1884 | int event_group; | 1895 | int event_group; |
1885 | int event_line; | 1896 | int event_line; |
1886 | struct d40_phy_res *phys; | 1897 | struct d40_phy_res *phys; |
@@ -1895,13 +1906,11 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) | |||
1895 | num_phy_chans = d40c->base->num_phy_chans; | 1906 | num_phy_chans = d40c->base->num_phy_chans; |
1896 | 1907 | ||
1897 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 1908 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { |
1898 | dev_type = d40c->dma_cfg.src_dev_type; | ||
1899 | log_num = 2 * dev_type; | 1909 | log_num = 2 * dev_type; |
1900 | is_src = true; | 1910 | is_src = true; |
1901 | } else if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 1911 | } else if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || |
1902 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 1912 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { |
1903 | /* dst event lines are used for logical memcpy */ | 1913 | /* dst event lines are used for logical memcpy */ |
1904 | dev_type = d40c->dma_cfg.dst_dev_type; | ||
1905 | log_num = 2 * dev_type + 1; | 1914 | log_num = 2 * dev_type + 1; |
1906 | is_src = false; | 1915 | is_src = false; |
1907 | } else | 1916 | } else |
@@ -2012,14 +2021,23 @@ static int d40_config_memcpy(struct d40_chan *d40c) | |||
2012 | dma_cap_mask_t cap = d40c->chan.device->cap_mask; | 2021 | dma_cap_mask_t cap = d40c->chan.device->cap_mask; |
2013 | 2022 | ||
2014 | if (dma_has_cap(DMA_MEMCPY, cap) && !dma_has_cap(DMA_SLAVE, cap)) { | 2023 | if (dma_has_cap(DMA_MEMCPY, cap) && !dma_has_cap(DMA_SLAVE, cap)) { |
2015 | d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_log; | 2024 | d40c->dma_cfg = dma40_memcpy_conf_log; |
2016 | d40c->dma_cfg.src_dev_type = STEDMA40_DEV_SRC_MEMORY; | 2025 | d40c->dma_cfg.dev_type = dma40_memcpy_channels[d40c->chan.chan_id]; |
2017 | d40c->dma_cfg.dst_dev_type = d40c->base->plat_data-> | 2026 | |
2018 | memcpy[d40c->chan.chan_id]; | 2027 | d40_log_cfg(&d40c->dma_cfg, |
2028 | &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); | ||
2019 | 2029 | ||
2020 | } else if (dma_has_cap(DMA_MEMCPY, cap) && | 2030 | } else if (dma_has_cap(DMA_MEMCPY, cap) && |
2021 | dma_has_cap(DMA_SLAVE, cap)) { | 2031 | dma_has_cap(DMA_SLAVE, cap)) { |
2022 | d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_phy; | 2032 | d40c->dma_cfg = dma40_memcpy_conf_phy; |
2033 | |||
2034 | /* Generate interrrupt at end of transfer or relink. */ | ||
2035 | d40c->dst_def_cfg |= BIT(D40_SREG_CFG_TIM_POS); | ||
2036 | |||
2037 | /* Generate interrupt on error. */ | ||
2038 | d40c->src_def_cfg |= BIT(D40_SREG_CFG_EIM_POS); | ||
2039 | d40c->dst_def_cfg |= BIT(D40_SREG_CFG_EIM_POS); | ||
2040 | |||
2023 | } else { | 2041 | } else { |
2024 | chan_err(d40c, "No memcpy\n"); | 2042 | chan_err(d40c, "No memcpy\n"); |
2025 | return -EINVAL; | 2043 | return -EINVAL; |
@@ -2032,7 +2050,7 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
2032 | { | 2050 | { |
2033 | 2051 | ||
2034 | int res = 0; | 2052 | int res = 0; |
2035 | u32 event; | 2053 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); |
2036 | struct d40_phy_res *phy = d40c->phy_chan; | 2054 | struct d40_phy_res *phy = d40c->phy_chan; |
2037 | bool is_src; | 2055 | bool is_src; |
2038 | 2056 | ||
@@ -2051,13 +2069,11 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
2051 | } | 2069 | } |
2052 | 2070 | ||
2053 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 2071 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || |
2054 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 2072 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) |
2055 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); | ||
2056 | is_src = false; | 2073 | is_src = false; |
2057 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 2074 | else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) |
2058 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); | ||
2059 | is_src = true; | 2075 | is_src = true; |
2060 | } else { | 2076 | else { |
2061 | chan_err(d40c, "Unknown direction\n"); | 2077 | chan_err(d40c, "Unknown direction\n"); |
2062 | return -EINVAL; | 2078 | return -EINVAL; |
2063 | } | 2079 | } |
@@ -2098,7 +2114,7 @@ static bool d40_is_paused(struct d40_chan *d40c) | |||
2098 | unsigned long flags; | 2114 | unsigned long flags; |
2099 | void __iomem *active_reg; | 2115 | void __iomem *active_reg; |
2100 | u32 status; | 2116 | u32 status; |
2101 | u32 event; | 2117 | u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); |
2102 | 2118 | ||
2103 | spin_lock_irqsave(&d40c->lock, flags); | 2119 | spin_lock_irqsave(&d40c->lock, flags); |
2104 | 2120 | ||
@@ -2119,10 +2135,8 @@ static bool d40_is_paused(struct d40_chan *d40c) | |||
2119 | 2135 | ||
2120 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 2136 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || |
2121 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 2137 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { |
2122 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); | ||
2123 | status = readl(chanbase + D40_CHAN_REG_SDLNK); | 2138 | status = readl(chanbase + D40_CHAN_REG_SDLNK); |
2124 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 2139 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { |
2125 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); | ||
2126 | status = readl(chanbase + D40_CHAN_REG_SSLNK); | 2140 | status = readl(chanbase + D40_CHAN_REG_SSLNK); |
2127 | } else { | 2141 | } else { |
2128 | chan_err(d40c, "Unknown direction\n"); | 2142 | chan_err(d40c, "Unknown direction\n"); |
@@ -2253,24 +2267,6 @@ err: | |||
2253 | return NULL; | 2267 | return NULL; |
2254 | } | 2268 | } |
2255 | 2269 | ||
2256 | static dma_addr_t | ||
2257 | d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction) | ||
2258 | { | ||
2259 | struct stedma40_platform_data *plat = chan->base->plat_data; | ||
2260 | struct stedma40_chan_cfg *cfg = &chan->dma_cfg; | ||
2261 | dma_addr_t addr = 0; | ||
2262 | |||
2263 | if (chan->runtime_addr) | ||
2264 | return chan->runtime_addr; | ||
2265 | |||
2266 | if (direction == DMA_DEV_TO_MEM) | ||
2267 | addr = plat->dev_rx[cfg->src_dev_type]; | ||
2268 | else if (direction == DMA_MEM_TO_DEV) | ||
2269 | addr = plat->dev_tx[cfg->dst_dev_type]; | ||
2270 | |||
2271 | return addr; | ||
2272 | } | ||
2273 | |||
2274 | static struct dma_async_tx_descriptor * | 2270 | static struct dma_async_tx_descriptor * |
2275 | d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, | 2271 | d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, |
2276 | struct scatterlist *sg_dst, unsigned int sg_len, | 2272 | struct scatterlist *sg_dst, unsigned int sg_len, |
@@ -2297,14 +2293,10 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, | |||
2297 | if (sg_next(&sg_src[sg_len - 1]) == sg_src) | 2293 | if (sg_next(&sg_src[sg_len - 1]) == sg_src) |
2298 | desc->cyclic = true; | 2294 | desc->cyclic = true; |
2299 | 2295 | ||
2300 | if (direction != DMA_TRANS_NONE) { | 2296 | if (direction == DMA_DEV_TO_MEM) |
2301 | dma_addr_t dev_addr = d40_get_dev_addr(chan, direction); | 2297 | src_dev_addr = chan->runtime_addr; |
2302 | 2298 | else if (direction == DMA_MEM_TO_DEV) | |
2303 | if (direction == DMA_DEV_TO_MEM) | 2299 | dst_dev_addr = chan->runtime_addr; |
2304 | src_dev_addr = dev_addr; | ||
2305 | else if (direction == DMA_MEM_TO_DEV) | ||
2306 | dst_dev_addr = dev_addr; | ||
2307 | } | ||
2308 | 2300 | ||
2309 | if (chan_is_logical(chan)) | 2301 | if (chan_is_logical(chan)) |
2310 | ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst, | 2302 | ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst, |
@@ -2397,11 +2389,55 @@ static void d40_set_prio_realtime(struct d40_chan *d40c) | |||
2397 | 2389 | ||
2398 | if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || | 2390 | if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || |
2399 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) | 2391 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) |
2400 | __d40_set_prio_rt(d40c, d40c->dma_cfg.src_dev_type, true); | 2392 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, true); |
2401 | 2393 | ||
2402 | if ((d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH) || | 2394 | if ((d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH) || |
2403 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) | 2395 | (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) |
2404 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dst_dev_type, false); | 2396 | __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, false); |
2397 | } | ||
2398 | |||
2399 | #define D40_DT_FLAGS_MODE(flags) ((flags >> 0) & 0x1) | ||
2400 | #define D40_DT_FLAGS_DIR(flags) ((flags >> 1) & 0x1) | ||
2401 | #define D40_DT_FLAGS_BIG_ENDIAN(flags) ((flags >> 2) & 0x1) | ||
2402 | #define D40_DT_FLAGS_FIXED_CHAN(flags) ((flags >> 3) & 0x1) | ||
2403 | |||
2404 | static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec, | ||
2405 | struct of_dma *ofdma) | ||
2406 | { | ||
2407 | struct stedma40_chan_cfg cfg; | ||
2408 | dma_cap_mask_t cap; | ||
2409 | u32 flags; | ||
2410 | |||
2411 | memset(&cfg, 0, sizeof(struct stedma40_chan_cfg)); | ||
2412 | |||
2413 | dma_cap_zero(cap); | ||
2414 | dma_cap_set(DMA_SLAVE, cap); | ||
2415 | |||
2416 | cfg.dev_type = dma_spec->args[0]; | ||
2417 | flags = dma_spec->args[2]; | ||
2418 | |||
2419 | switch (D40_DT_FLAGS_MODE(flags)) { | ||
2420 | case 0: cfg.mode = STEDMA40_MODE_LOGICAL; break; | ||
2421 | case 1: cfg.mode = STEDMA40_MODE_PHYSICAL; break; | ||
2422 | } | ||
2423 | |||
2424 | switch (D40_DT_FLAGS_DIR(flags)) { | ||
2425 | case 0: | ||
2426 | cfg.dir = STEDMA40_MEM_TO_PERIPH; | ||
2427 | cfg.dst_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); | ||
2428 | break; | ||
2429 | case 1: | ||
2430 | cfg.dir = STEDMA40_PERIPH_TO_MEM; | ||
2431 | cfg.src_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); | ||
2432 | break; | ||
2433 | } | ||
2434 | |||
2435 | if (D40_DT_FLAGS_FIXED_CHAN(flags)) { | ||
2436 | cfg.phy_channel = dma_spec->args[1]; | ||
2437 | cfg.use_fixed_channel = true; | ||
2438 | } | ||
2439 | |||
2440 | return dma_request_channel(cap, stedma40_filter, &cfg); | ||
2405 | } | 2441 | } |
2406 | 2442 | ||
2407 | /* DMA ENGINE functions */ | 2443 | /* DMA ENGINE functions */ |
@@ -2433,23 +2469,21 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) | |||
2433 | } | 2469 | } |
2434 | 2470 | ||
2435 | pm_runtime_get_sync(d40c->base->dev); | 2471 | pm_runtime_get_sync(d40c->base->dev); |
2436 | /* Fill in basic CFG register values */ | ||
2437 | d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, | ||
2438 | &d40c->dst_def_cfg, chan_is_logical(d40c)); | ||
2439 | 2472 | ||
2440 | d40_set_prio_realtime(d40c); | 2473 | d40_set_prio_realtime(d40c); |
2441 | 2474 | ||
2442 | if (chan_is_logical(d40c)) { | 2475 | if (chan_is_logical(d40c)) { |
2443 | d40_log_cfg(&d40c->dma_cfg, | ||
2444 | &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); | ||
2445 | |||
2446 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) | 2476 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) |
2447 | d40c->lcpa = d40c->base->lcpa_base + | 2477 | d40c->lcpa = d40c->base->lcpa_base + |
2448 | d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE; | 2478 | d40c->dma_cfg.dev_type * D40_LCPA_CHAN_SIZE; |
2449 | else | 2479 | else |
2450 | d40c->lcpa = d40c->base->lcpa_base + | 2480 | d40c->lcpa = d40c->base->lcpa_base + |
2451 | d40c->dma_cfg.dst_dev_type * | 2481 | d40c->dma_cfg.dev_type * |
2452 | D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; | 2482 | D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; |
2483 | |||
2484 | /* Unmask the Global Interrupt Mask. */ | ||
2485 | d40c->src_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS); | ||
2486 | d40c->dst_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS); | ||
2453 | } | 2487 | } |
2454 | 2488 | ||
2455 | dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n", | 2489 | dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n", |
@@ -2710,15 +2744,8 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2710 | dst_maxburst = config->dst_maxburst; | 2744 | dst_maxburst = config->dst_maxburst; |
2711 | 2745 | ||
2712 | if (config->direction == DMA_DEV_TO_MEM) { | 2746 | if (config->direction == DMA_DEV_TO_MEM) { |
2713 | dma_addr_t dev_addr_rx = | ||
2714 | d40c->base->plat_data->dev_rx[cfg->src_dev_type]; | ||
2715 | |||
2716 | config_addr = config->src_addr; | 2747 | config_addr = config->src_addr; |
2717 | if (dev_addr_rx) | 2748 | |
2718 | dev_dbg(d40c->base->dev, | ||
2719 | "channel has a pre-wired RX address %08x " | ||
2720 | "overriding with %08x\n", | ||
2721 | dev_addr_rx, config_addr); | ||
2722 | if (cfg->dir != STEDMA40_PERIPH_TO_MEM) | 2749 | if (cfg->dir != STEDMA40_PERIPH_TO_MEM) |
2723 | dev_dbg(d40c->base->dev, | 2750 | dev_dbg(d40c->base->dev, |
2724 | "channel was not configured for peripheral " | 2751 | "channel was not configured for peripheral " |
@@ -2733,15 +2760,8 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2733 | dst_maxburst = src_maxburst; | 2760 | dst_maxburst = src_maxburst; |
2734 | 2761 | ||
2735 | } else if (config->direction == DMA_MEM_TO_DEV) { | 2762 | } else if (config->direction == DMA_MEM_TO_DEV) { |
2736 | dma_addr_t dev_addr_tx = | ||
2737 | d40c->base->plat_data->dev_tx[cfg->dst_dev_type]; | ||
2738 | |||
2739 | config_addr = config->dst_addr; | 2763 | config_addr = config->dst_addr; |
2740 | if (dev_addr_tx) | 2764 | |
2741 | dev_dbg(d40c->base->dev, | ||
2742 | "channel has a pre-wired TX address %08x " | ||
2743 | "overriding with %08x\n", | ||
2744 | dev_addr_tx, config_addr); | ||
2745 | if (cfg->dir != STEDMA40_MEM_TO_PERIPH) | 2765 | if (cfg->dir != STEDMA40_MEM_TO_PERIPH) |
2746 | dev_dbg(d40c->base->dev, | 2766 | dev_dbg(d40c->base->dev, |
2747 | "channel was not configured for memory " | 2767 | "channel was not configured for memory " |
@@ -2761,6 +2781,11 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2761 | return -EINVAL; | 2781 | return -EINVAL; |
2762 | } | 2782 | } |
2763 | 2783 | ||
2784 | if (config_addr <= 0) { | ||
2785 | dev_err(d40c->base->dev, "no address supplied\n"); | ||
2786 | return -EINVAL; | ||
2787 | } | ||
2788 | |||
2764 | if (src_maxburst * src_addr_width != dst_maxburst * dst_addr_width) { | 2789 | if (src_maxburst * src_addr_width != dst_maxburst * dst_addr_width) { |
2765 | dev_err(d40c->base->dev, | 2790 | dev_err(d40c->base->dev, |
2766 | "src/dst width/maxburst mismatch: %d*%d != %d*%d\n", | 2791 | "src/dst width/maxburst mismatch: %d*%d != %d*%d\n", |
@@ -2795,8 +2820,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, | |||
2795 | if (chan_is_logical(d40c)) | 2820 | if (chan_is_logical(d40c)) |
2796 | d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); | 2821 | d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); |
2797 | else | 2822 | else |
2798 | d40_phy_cfg(cfg, &d40c->src_def_cfg, | 2823 | d40_phy_cfg(cfg, &d40c->src_def_cfg, &d40c->dst_def_cfg); |
2799 | &d40c->dst_def_cfg, false); | ||
2800 | 2824 | ||
2801 | /* These settings will take precedence later */ | 2825 | /* These settings will take precedence later */ |
2802 | d40c->runtime_addr = config_addr; | 2826 | d40c->runtime_addr = config_addr; |
@@ -2927,7 +2951,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, | |||
2927 | } | 2951 | } |
2928 | 2952 | ||
2929 | d40_chan_init(base, &base->dma_memcpy, base->log_chans, | 2953 | d40_chan_init(base, &base->dma_memcpy, base->log_chans, |
2930 | base->num_log_chans, base->plat_data->memcpy_len); | 2954 | base->num_log_chans, ARRAY_SIZE(dma40_memcpy_channels)); |
2931 | 2955 | ||
2932 | dma_cap_zero(base->dma_memcpy.cap_mask); | 2956 | dma_cap_zero(base->dma_memcpy.cap_mask); |
2933 | dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask); | 2957 | dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask); |
@@ -3121,7 +3145,7 @@ static int __init d40_phy_res_init(struct d40_base *base) | |||
3121 | 3145 | ||
3122 | static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | 3146 | static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) |
3123 | { | 3147 | { |
3124 | struct stedma40_platform_data *plat_data; | 3148 | struct stedma40_platform_data *plat_data = pdev->dev.platform_data; |
3125 | struct clk *clk = NULL; | 3149 | struct clk *clk = NULL; |
3126 | void __iomem *virtbase = NULL; | 3150 | void __iomem *virtbase = NULL; |
3127 | struct resource *res = NULL; | 3151 | struct resource *res = NULL; |
@@ -3187,8 +3211,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3187 | * DB8540v1 has revision 4 | 3211 | * DB8540v1 has revision 4 |
3188 | */ | 3212 | */ |
3189 | rev = AMBA_REV_BITS(pid); | 3213 | rev = AMBA_REV_BITS(pid); |
3190 | 3214 | if (rev < 2) { | |
3191 | plat_data = pdev->dev.platform_data; | 3215 | d40_err(&pdev->dev, "hardware revision: %d is not supported", rev); |
3216 | goto failure; | ||
3217 | } | ||
3192 | 3218 | ||
3193 | /* The number of physical channels on this HW */ | 3219 | /* The number of physical channels on this HW */ |
3194 | if (plat_data->num_of_phy_chans) | 3220 | if (plat_data->num_of_phy_chans) |
@@ -3196,26 +3222,14 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3196 | else | 3222 | else |
3197 | num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; | 3223 | num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; |
3198 | 3224 | ||
3199 | dev_info(&pdev->dev, "hardware revision: %d @ 0x%x with %d physical channels\n", | 3225 | num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY; |
3200 | rev, res->start, num_phy_chans); | ||
3201 | |||
3202 | if (rev < 2) { | ||
3203 | d40_err(&pdev->dev, "hardware revision: %d is not supported", | ||
3204 | rev); | ||
3205 | goto failure; | ||
3206 | } | ||
3207 | 3226 | ||
3208 | /* Count the number of logical channels in use */ | 3227 | dev_info(&pdev->dev, |
3209 | for (i = 0; i < plat_data->dev_len; i++) | 3228 | "hardware rev: %d @ 0x%x with %d physical and %d logical channels\n", |
3210 | if (plat_data->dev_rx[i] != 0) | 3229 | rev, res->start, num_phy_chans, num_log_chans); |
3211 | num_log_chans++; | ||
3212 | |||
3213 | for (i = 0; i < plat_data->dev_len; i++) | ||
3214 | if (plat_data->dev_tx[i] != 0) | ||
3215 | num_log_chans++; | ||
3216 | 3230 | ||
3217 | base = kzalloc(ALIGN(sizeof(struct d40_base), 4) + | 3231 | base = kzalloc(ALIGN(sizeof(struct d40_base), 4) + |
3218 | (num_phy_chans + num_log_chans + plat_data->memcpy_len) * | 3232 | (num_phy_chans + num_log_chans + ARRAY_SIZE(dma40_memcpy_channels)) * |
3219 | sizeof(struct d40_chan), GFP_KERNEL); | 3233 | sizeof(struct d40_chan), GFP_KERNEL); |
3220 | 3234 | ||
3221 | if (base == NULL) { | 3235 | if (base == NULL) { |
@@ -3276,17 +3290,11 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3276 | if (!base->lookup_phy_chans) | 3290 | if (!base->lookup_phy_chans) |
3277 | goto failure; | 3291 | goto failure; |
3278 | 3292 | ||
3279 | if (num_log_chans + plat_data->memcpy_len) { | 3293 | base->lookup_log_chans = kzalloc(num_log_chans * |
3280 | /* | 3294 | sizeof(struct d40_chan *), |
3281 | * The max number of logical channels are event lines for all | 3295 | GFP_KERNEL); |
3282 | * src devices and dst devices | 3296 | if (!base->lookup_log_chans) |
3283 | */ | 3297 | goto failure; |
3284 | base->lookup_log_chans = kzalloc(plat_data->dev_len * 2 * | ||
3285 | sizeof(struct d40_chan *), | ||
3286 | GFP_KERNEL); | ||
3287 | if (!base->lookup_log_chans) | ||
3288 | goto failure; | ||
3289 | } | ||
3290 | 3298 | ||
3291 | base->reg_val_backup_chan = kmalloc(base->num_phy_chans * | 3299 | base->reg_val_backup_chan = kmalloc(base->num_phy_chans * |
3292 | sizeof(d40_backup_regs_chan), | 3300 | sizeof(d40_backup_regs_chan), |
@@ -3470,17 +3478,52 @@ failure: | |||
3470 | return ret; | 3478 | return ret; |
3471 | } | 3479 | } |
3472 | 3480 | ||
3481 | static int __init d40_of_probe(struct platform_device *pdev, | ||
3482 | struct device_node *np) | ||
3483 | { | ||
3484 | struct stedma40_platform_data *pdata; | ||
3485 | |||
3486 | /* | ||
3487 | * FIXME: Fill in this routine as more support is added. | ||
3488 | * First platform enabled (u8500) doens't need any extra | ||
3489 | * properties to run, so this is fairly sparce currently. | ||
3490 | */ | ||
3491 | |||
3492 | pdata = devm_kzalloc(&pdev->dev, | ||
3493 | sizeof(struct stedma40_platform_data), | ||
3494 | GFP_KERNEL); | ||
3495 | if (!pdata) | ||
3496 | return -ENOMEM; | ||
3497 | |||
3498 | pdev->dev.platform_data = pdata; | ||
3499 | |||
3500 | return 0; | ||
3501 | } | ||
3502 | |||
3473 | static int __init d40_probe(struct platform_device *pdev) | 3503 | static int __init d40_probe(struct platform_device *pdev) |
3474 | { | 3504 | { |
3505 | struct stedma40_platform_data *plat_data = pdev->dev.platform_data; | ||
3506 | struct device_node *np = pdev->dev.of_node; | ||
3475 | int err; | 3507 | int err; |
3476 | int ret = -ENOENT; | 3508 | int ret = -ENOENT; |
3477 | struct d40_base *base; | 3509 | struct d40_base *base = NULL; |
3478 | struct resource *res = NULL; | 3510 | struct resource *res = NULL; |
3479 | int num_reserved_chans; | 3511 | int num_reserved_chans; |
3480 | u32 val; | 3512 | u32 val; |
3481 | 3513 | ||
3482 | base = d40_hw_detect_init(pdev); | 3514 | if (!plat_data) { |
3515 | if (np) { | ||
3516 | if(d40_of_probe(pdev, np)) { | ||
3517 | ret = -ENOMEM; | ||
3518 | goto failure; | ||
3519 | } | ||
3520 | } else { | ||
3521 | d40_err(&pdev->dev, "No pdata or Device Tree provided\n"); | ||
3522 | goto failure; | ||
3523 | } | ||
3524 | } | ||
3483 | 3525 | ||
3526 | base = d40_hw_detect_init(pdev); | ||
3484 | if (!base) | 3527 | if (!base) |
3485 | goto failure; | 3528 | goto failure; |
3486 | 3529 | ||
@@ -3601,6 +3644,13 @@ static int __init d40_probe(struct platform_device *pdev) | |||
3601 | 3644 | ||
3602 | d40_hw_init(base); | 3645 | d40_hw_init(base); |
3603 | 3646 | ||
3647 | if (np) { | ||
3648 | err = of_dma_controller_register(np, d40_xlate, NULL); | ||
3649 | if (err && err != -ENODEV) | ||
3650 | dev_err(&pdev->dev, | ||
3651 | "could not register of_dma_controller\n"); | ||
3652 | } | ||
3653 | |||
3604 | dev_info(base->dev, "initialized\n"); | 3654 | dev_info(base->dev, "initialized\n"); |
3605 | return 0; | 3655 | return 0; |
3606 | 3656 | ||
@@ -3654,11 +3704,17 @@ failure: | |||
3654 | return ret; | 3704 | return ret; |
3655 | } | 3705 | } |
3656 | 3706 | ||
3707 | static const struct of_device_id d40_match[] = { | ||
3708 | { .compatible = "stericsson,dma40", }, | ||
3709 | {} | ||
3710 | }; | ||
3711 | |||
3657 | static struct platform_driver d40_driver = { | 3712 | static struct platform_driver d40_driver = { |
3658 | .driver = { | 3713 | .driver = { |
3659 | .owner = THIS_MODULE, | 3714 | .owner = THIS_MODULE, |
3660 | .name = D40_NAME, | 3715 | .name = D40_NAME, |
3661 | .pm = DMA40_PM_OPS, | 3716 | .pm = DMA40_PM_OPS, |
3717 | .of_match_table = d40_match, | ||
3662 | }, | 3718 | }, |
3663 | }; | 3719 | }; |
3664 | 3720 | ||
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 7180e0d41722..ab5a2a706f7a 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c | |||
@@ -50,68 +50,58 @@ void d40_log_cfg(struct stedma40_chan_cfg *cfg, | |||
50 | 50 | ||
51 | } | 51 | } |
52 | 52 | ||
53 | /* Sets up SRC and DST CFG register for both logical and physical channels */ | 53 | void d40_phy_cfg(struct stedma40_chan_cfg *cfg, u32 *src_cfg, u32 *dst_cfg) |
54 | void d40_phy_cfg(struct stedma40_chan_cfg *cfg, | ||
55 | u32 *src_cfg, u32 *dst_cfg, bool is_log) | ||
56 | { | 54 | { |
57 | u32 src = 0; | 55 | u32 src = 0; |
58 | u32 dst = 0; | 56 | u32 dst = 0; |
59 | 57 | ||
60 | if (!is_log) { | 58 | if ((cfg->dir == STEDMA40_PERIPH_TO_MEM) || |
61 | /* Physical channel */ | 59 | (cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) { |
62 | if ((cfg->dir == STEDMA40_PERIPH_TO_MEM) || | 60 | /* Set master port to 1 */ |
63 | (cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) { | 61 | src |= 1 << D40_SREG_CFG_MST_POS; |
64 | /* Set master port to 1 */ | 62 | src |= D40_TYPE_TO_EVENT(cfg->dev_type); |
65 | src |= 1 << D40_SREG_CFG_MST_POS; | 63 | |
66 | src |= D40_TYPE_TO_EVENT(cfg->src_dev_type); | 64 | if (cfg->src_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) |
67 | 65 | src |= 1 << D40_SREG_CFG_PHY_TM_POS; | |
68 | if (cfg->src_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) | 66 | else |
69 | src |= 1 << D40_SREG_CFG_PHY_TM_POS; | 67 | src |= 3 << D40_SREG_CFG_PHY_TM_POS; |
70 | else | 68 | } |
71 | src |= 3 << D40_SREG_CFG_PHY_TM_POS; | 69 | if ((cfg->dir == STEDMA40_MEM_TO_PERIPH) || |
72 | } | 70 | (cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) { |
73 | if ((cfg->dir == STEDMA40_MEM_TO_PERIPH) || | 71 | /* Set master port to 1 */ |
74 | (cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) { | 72 | dst |= 1 << D40_SREG_CFG_MST_POS; |
75 | /* Set master port to 1 */ | 73 | dst |= D40_TYPE_TO_EVENT(cfg->dev_type); |
76 | dst |= 1 << D40_SREG_CFG_MST_POS; | 74 | |
77 | dst |= D40_TYPE_TO_EVENT(cfg->dst_dev_type); | 75 | if (cfg->dst_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) |
78 | 76 | dst |= 1 << D40_SREG_CFG_PHY_TM_POS; | |
79 | if (cfg->dst_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) | 77 | else |
80 | dst |= 1 << D40_SREG_CFG_PHY_TM_POS; | 78 | dst |= 3 << D40_SREG_CFG_PHY_TM_POS; |
81 | else | 79 | } |
82 | dst |= 3 << D40_SREG_CFG_PHY_TM_POS; | 80 | /* Interrupt on end of transfer for destination */ |
83 | } | 81 | dst |= 1 << D40_SREG_CFG_TIM_POS; |
84 | /* Interrupt on end of transfer for destination */ | 82 | |
85 | dst |= 1 << D40_SREG_CFG_TIM_POS; | 83 | /* Generate interrupt on error */ |
86 | 84 | src |= 1 << D40_SREG_CFG_EIM_POS; | |
87 | /* Generate interrupt on error */ | 85 | dst |= 1 << D40_SREG_CFG_EIM_POS; |
88 | src |= 1 << D40_SREG_CFG_EIM_POS; | 86 | |
89 | dst |= 1 << D40_SREG_CFG_EIM_POS; | 87 | /* PSIZE */ |
90 | 88 | if (cfg->src_info.psize != STEDMA40_PSIZE_PHY_1) { | |
91 | /* PSIZE */ | 89 | src |= 1 << D40_SREG_CFG_PHY_PEN_POS; |
92 | if (cfg->src_info.psize != STEDMA40_PSIZE_PHY_1) { | 90 | src |= cfg->src_info.psize << D40_SREG_CFG_PSIZE_POS; |
93 | src |= 1 << D40_SREG_CFG_PHY_PEN_POS; | 91 | } |
94 | src |= cfg->src_info.psize << D40_SREG_CFG_PSIZE_POS; | 92 | if (cfg->dst_info.psize != STEDMA40_PSIZE_PHY_1) { |
95 | } | 93 | dst |= 1 << D40_SREG_CFG_PHY_PEN_POS; |
96 | if (cfg->dst_info.psize != STEDMA40_PSIZE_PHY_1) { | 94 | dst |= cfg->dst_info.psize << D40_SREG_CFG_PSIZE_POS; |
97 | dst |= 1 << D40_SREG_CFG_PHY_PEN_POS; | 95 | } |
98 | dst |= cfg->dst_info.psize << D40_SREG_CFG_PSIZE_POS; | 96 | |
99 | } | 97 | /* Element size */ |
100 | 98 | src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS; | |
101 | /* Element size */ | 99 | dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS; |
102 | src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS; | 100 | |
103 | dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS; | 101 | /* Set the priority bit to high for the physical channel */ |
104 | 102 | if (cfg->high_priority) { | |
105 | /* Set the priority bit to high for the physical channel */ | 103 | src |= 1 << D40_SREG_CFG_PRI_POS; |
106 | if (cfg->high_priority) { | 104 | dst |= 1 << D40_SREG_CFG_PRI_POS; |
107 | src |= 1 << D40_SREG_CFG_PRI_POS; | ||
108 | dst |= 1 << D40_SREG_CFG_PRI_POS; | ||
109 | } | ||
110 | |||
111 | } else { | ||
112 | /* Logical channel */ | ||
113 | dst |= 1 << D40_SREG_CFG_LOG_GIM_POS; | ||
114 | src |= 1 << D40_SREG_CFG_LOG_GIM_POS; | ||
115 | } | 105 | } |
116 | 106 | ||
117 | if (cfg->src_info.big_endian) | 107 | if (cfg->src_info.big_endian) |
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index fdde8ef77542..1b47312bc574 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h | |||
@@ -432,8 +432,7 @@ enum d40_lli_flags { | |||
432 | 432 | ||
433 | void d40_phy_cfg(struct stedma40_chan_cfg *cfg, | 433 | void d40_phy_cfg(struct stedma40_chan_cfg *cfg, |
434 | u32 *src_cfg, | 434 | u32 *src_cfg, |
435 | u32 *dst_cfg, | 435 | u32 *dst_cfg); |
436 | bool is_log); | ||
437 | 436 | ||
438 | void d40_log_cfg(struct stedma40_chan_cfg *cfg, | 437 | void d40_log_cfg(struct stedma40_chan_cfg *cfg, |
439 | u32 *lcsp1, | 438 | u32 *lcsp1, |