Commit a0594cefb7682dc0c32084d088b3ac0a85ed7395
Committed by
Jagan Teki
1 parent
18c61e9571
Exists in
v2017.01-smarct4x
and in
30 other branches
dm: implement a DMA uclass
Implement a DMA uclass so that the devices like ethernet, spi, mmc etc can offload the data transfers from/to the device and memory. Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Jagan Teki <jteki@openedev.com>
Showing 5 changed files with 176 additions and 0 deletions Side-by-side Diff
drivers/dma/Kconfig
1 | +menu "DMA Support" | |
2 | + | |
3 | +config DMA | |
4 | + bool "Enable Driver Model for DMA drivers" | |
5 | + depends on DM | |
6 | + help | |
7 | + Enable driver model for DMA. DMA engines can do | |
8 | + asynchronous data transfers without involving the host | |
9 | + CPU. Currently, this framework can be used to offload | |
10 | + memory copies to and from devices like qspi, ethernet | |
11 | + etc Drivers provide methods to access the DMA devices | |
12 | + buses that is used to transfer data to and from memory. | |
13 | + The uclass interface is defined in include/dma.h. | |
14 | + | |
15 | +endmenu # menu "DMA Support" |
drivers/dma/Makefile
drivers/dma/dma-uclass.c
1 | +/* | |
2 | + * Direct Memory Access U-Class driver | |
3 | + * | |
4 | + * (C) Copyright 2015 | |
5 | + * Texas Instruments Incorporated, <www.ti.com> | |
6 | + * | |
7 | + * Author: Mugunthan V N <mugunthanvnm@ti.com> | |
8 | + * | |
9 | + * SPDX-License-Identifier: GPL-2.0+ | |
10 | + */ | |
11 | + | |
12 | +#include <common.h> | |
13 | +#include <dma.h> | |
14 | +#include <dm.h> | |
15 | +#include <dm/uclass-internal.h> | |
16 | +#include <dm/device-internal.h> | |
17 | +#include <errno.h> | |
18 | + | |
19 | +DECLARE_GLOBAL_DATA_PTR; | |
20 | + | |
21 | +int dma_get_device(u32 transfer_type, struct udevice **devp) | |
22 | +{ | |
23 | + struct udevice *dev; | |
24 | + int ret; | |
25 | + | |
26 | + for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret; | |
27 | + ret = uclass_next_device(&dev)) { | |
28 | + struct dma_dev_priv *uc_priv; | |
29 | + | |
30 | + uc_priv = dev_get_uclass_priv(dev); | |
31 | + if (uc_priv->supported & transfer_type) | |
32 | + break; | |
33 | + } | |
34 | + | |
35 | + if (!dev) { | |
36 | + error("No DMA device found that supports %x type\n", | |
37 | + transfer_type); | |
38 | + return -EPROTONOSUPPORT; | |
39 | + } | |
40 | + | |
41 | + *devp = dev; | |
42 | + | |
43 | + return ret; | |
44 | +} | |
45 | + | |
46 | +int dma_memcpy(void *dst, void *src, size_t len) | |
47 | +{ | |
48 | + struct udevice *dev; | |
49 | + const struct dma_ops *ops; | |
50 | + int ret; | |
51 | + | |
52 | + ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev); | |
53 | + if (ret < 0) | |
54 | + return ret; | |
55 | + | |
56 | + ops = device_get_ops(dev); | |
57 | + if (!ops->transfer) | |
58 | + return -ENOSYS; | |
59 | + | |
60 | + /* Invalidate the area, so no writeback into the RAM races with DMA */ | |
61 | + invalidate_dcache_range((unsigned long)dst, (unsigned long)dst + | |
62 | + roundup(len, ARCH_DMA_MINALIGN)); | |
63 | + | |
64 | + return ops->transfer(dev, DMA_MEM_TO_MEM, dst, src, len); | |
65 | +} | |
66 | + | |
67 | +UCLASS_DRIVER(dma) = { | |
68 | + .id = UCLASS_DMA, | |
69 | + .name = "dma", | |
70 | + .flags = DM_UC_FLAG_SEQ_ALIAS, | |
71 | + .per_device_auto_alloc_size = sizeof(struct dma_dev_priv), | |
72 | +}; |
include/dm/uclass-id.h
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | UCLASS_CROS_EC, /* Chrome OS EC */ |
32 | 32 | UCLASS_DISK, /* Disk controller, e.g. SATA */ |
33 | 33 | UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ |
34 | + UCLASS_DMA, /* Direct Memory Access */ | |
34 | 35 | UCLASS_RAM, /* RAM controller */ |
35 | 36 | UCLASS_ETH, /* Ethernet device */ |
36 | 37 | UCLASS_GPIO, /* Bank of general-purpose I/O pins */ |
include/dma.h
1 | +/* | |
2 | + * (C) Copyright 2015 | |
3 | + * Texas Instruments Incorporated, <www.ti.com> | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +#ifndef _DMA_H_ | |
9 | +#define _DMA_H_ | |
10 | + | |
11 | +/* | |
12 | + * enum dma_direction - dma transfer direction indicator | |
13 | + * @DMA_MEM_TO_MEM: Memcpy mode | |
14 | + * @DMA_MEM_TO_DEV: From Memory to Device | |
15 | + * @DMA_DEV_TO_MEM: From Device to Memory | |
16 | + * @DMA_DEV_TO_DEV: From Device to Device | |
17 | + */ | |
18 | +enum dma_direction { | |
19 | + DMA_MEM_TO_MEM, | |
20 | + DMA_MEM_TO_DEV, | |
21 | + DMA_DEV_TO_MEM, | |
22 | + DMA_DEV_TO_DEV, | |
23 | +}; | |
24 | + | |
25 | +#define DMA_SUPPORTS_MEM_TO_MEM BIT(0) | |
26 | +#define DMA_SUPPORTS_MEM_TO_DEV BIT(1) | |
27 | +#define DMA_SUPPORTS_DEV_TO_MEM BIT(2) | |
28 | +#define DMA_SUPPORTS_DEV_TO_DEV BIT(3) | |
29 | + | |
30 | +/* | |
31 | + * struct dma_ops - Driver model DMA operations | |
32 | + * | |
33 | + * The uclass interface is implemented by all DMA devices which use | |
34 | + * driver model. | |
35 | + */ | |
36 | +struct dma_ops { | |
37 | + /* | |
38 | + * Get the current timer count | |
39 | + * | |
40 | + * @dev: The DMA device | |
41 | + * @direction: direction of data transfer should be one from | |
42 | + enum dma_direction | |
43 | + * @dst: Destination pointer | |
44 | + * @src: Source pointer | |
45 | + * @len: Length of the data to be copied. | |
46 | + * @return: 0 if OK, -ve on error | |
47 | + */ | |
48 | + int (*transfer)(struct udevice *dev, int direction, void *dst, | |
49 | + void *src, size_t len); | |
50 | +}; | |
51 | + | |
52 | +/* | |
53 | + * struct dma_dev_priv - information about a device used by the uclass | |
54 | + * | |
55 | + * @supported: mode of transfers that DMA can support, should be | |
56 | + * one/multiple of DMA_SUPPORTS_* | |
57 | + */ | |
58 | +struct dma_dev_priv { | |
59 | + u32 supported; | |
60 | +}; | |
61 | + | |
62 | +/* | |
63 | + * dma_get_device - get a DMA device which supports transfer | |
64 | + * type of transfer_type | |
65 | + * | |
66 | + * @transfer_type - transfer type should be one/multiple of | |
67 | + * DMA_SUPPORTS_* | |
68 | + * @devp - udevice pointer to return the found device | |
69 | + * @return - will return on success and devp will hold the | |
70 | + * pointer to the device | |
71 | + */ | |
72 | +int dma_get_device(u32 transfer_type, struct udevice **devp); | |
73 | + | |
74 | +/* | |
75 | + * dma_memcpy - try to use DMA to do a mem copy which will be | |
76 | + * much faster than CPU mem copy | |
77 | + * | |
78 | + * @dst - destination pointer | |
79 | + * @src - souce pointer | |
80 | + * @len - data length to be copied | |
81 | + * @return - on successful transfer returns no of bytes | |
82 | + transferred and on failure return error code. | |
83 | + */ | |
84 | +int dma_memcpy(void *dst, void *src, size_t len); | |
85 | + | |
86 | +#endif /* _DMA_H_ */ |