1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #ifndef DMAC_CORE_H
10 #define DMAC_CORE_H
11
12 #include "hdf_base.h"
13 #include "hdf_device.h"
14 #include "hdf_device_desc.h"
15 #include "hdf_object.h"
16 #include "los_event.h"
17 #include "osal_mutex.h"
18 #include "osal_spinlock.h"
19
20 #ifdef __cplusplus
21 #if __cplusplus
22 extern "C" {
23 #endif
24 #endif /* __cplusplus */
25
26 #define PERIPH_ADDR_INVALID 0xfff
27 #define DMAC_CHAN_NUM_MAX 100
28
29 #define DmaEventInit(event) LOS_EventInit(event)
30 #define DmaEventSignal(event, bit) LOS_EventWrite(event, bit)
31 #define DmaEventWait(event, bit, timeout) LOS_EventRead(event, bit, LOS_WAITMODE_OR + LOS_WAITMODE_CLR, timeout)
32
33 typedef void DmacCallback(void *callbackData, int status);
34 typedef EVENT_CB_S DmacEvent;
35
36 /* definition for the return value */
37 enum DmacErrorNumber {
38 DMAC_ERROR_BASE = 0x100,
39 DMAC_CHANNEL_INVALID = DMAC_ERROR_BASE + 1,
40 DMAC_TRXFERSIZE_INVALID = DMAC_ERROR_BASE + 2,
41 DMAC_SOURCE_ADDRESS_INVALID = DMAC_ERROR_BASE + 3,
42 DMAC_DESTINATION_ADDRESS_INVALID = DMAC_ERROR_BASE + 4,
43 DMAC_MEMORY_ADDRESS_INVALID = DMAC_ERROR_BASE + 5,
44 DMAC_PERIPHERAL_ID_INVALID = DMAC_ERROR_BASE + 6,
45 DMAC_DIRECTION_ERROR = DMAC_ERROR_BASE + 7,
46 DMAC_TRXFER_ERROR = DMAC_ERROR_BASE + 8,
47 DMAC_LLIHEAD_ERROR = DMAC_ERROR_BASE + 9,
48 DMAC_SWIDTH_ERROR = DMAC_ERROR_BASE + 0xa,
49 DMAC_LLI_ADDRESS_INVALID = DMAC_ERROR_BASE + 0xb,
50 DMAC_TRANS_CONTROL_INVALID = DMAC_ERROR_BASE + 0xc,
51 DMAC_MEMORY_ALLOCATE_ERROR = DMAC_ERROR_BASE + 0xd,
52 DMAC_NOT_FINISHED = DMAC_ERROR_BASE + 0xe,
53 DMAC_TIMEOUT = DMAC_ERROR_BASE + 0xf,
54 DMAC_CHN_SUCCESS = DMAC_ERROR_BASE + 0x10,
55 DMAC_CHN_ERROR = DMAC_ERROR_BASE + 0x11,
56 DMAC_CHN_TIMEOUT = DMAC_ERROR_BASE + 0x12,
57 DMAC_CHN_ALLOCAT = DMAC_ERROR_BASE + 0x13,
58 DMAC_CHN_VACANCY = DMAC_ERROR_BASE + 0x14,
59 };
60
61 enum DmacEvent {
62 DMAC_EVENT_DONE = 0x1,
63 DMAC_EVENT_ERROR = 0x2,
64 };
65 #define DMA_EVENT_WAIT_DEF_TIME ((LOSCFG_BASE_CORE_TICK_PER_SECOND) * 5)
66
67 enum DmacTransferType {
68 TRASFER_TYPE_M2M = 0x0,
69 TRASFER_TYPE_P2M = 0x1,
70 TRASFER_TYPE_M2P = 0x2,
71 };
72
73 struct DmacMsg {
74 uintptr_t srcAddr;
75 uintptr_t destAddr;
76 uint8_t srcWidth; // src data width in bytes
77 uint8_t destWidth; // dest data width in bytes
78 uint8_t transType; // 0: mem to mem; 1: periph to mem; 2:mem to periph
79 size_t transLen;
80 DmacCallback *cb;
81 void *para;
82 };
83
DmacMsgGetPeriphAddr(struct DmacMsg * msg)84 static inline uintptr_t DmacMsgGetPeriphAddr(struct DmacMsg *msg)
85 {
86 return (msg->transType == TRASFER_TYPE_M2P) ? msg->destAddr :
87 (msg->transType == TRASFER_TYPE_P2M) ? msg->srcAddr : PERIPH_ADDR_INVALID;
88 }
89
90 #define DMAC_LLI_HEAD \
91 uintptr_t nextLli; \
92 uintptr_t reserved0[6]; \
93 unsigned long count; \
94 uintptr_t srcAddr; \
95 uintptr_t reserved1; \
96 uintptr_t destAddr; \
97 uintptr_t reserved2; \
98 unsigned long config
99
100 struct DmacLliHead {
101 DMAC_LLI_HEAD;
102 };
103 #define DMAC_LLI_HEAD_SIZE (sizeof(struct DmacLliHead))
104
105 #define DMAC_LLI_SIZE 64 // must be 64 Bytes aligned
106 struct DmacLli {
107 DMAC_LLI_HEAD;
108 uint8_t pad[DMAC_LLI_SIZE - DMAC_LLI_HEAD_SIZE];
109 };
110
111 struct DmacChanInfo {
112 uint16_t channel;
113 int status;
114 int useStatus;
115 int transType;
116 uint8_t srcWidth; // src data width in bytes
117 uint8_t destWidth; // dest data width in bytes
118 unsigned long config; // cpu width expected
119 uintptr_t lliEnFlag;
120 DmacEvent waitEvent;
121 DmacCallback *callback;
122 void *callbackData;
123 uint16_t lliCnt;
124 struct DmacLli *lli;
125 void *dummyPage;
126 };
127
128 struct DmaCntlr {
129 struct IDeviceIoService service;
130 struct HdfDeviceObject *device;
131 uint16_t index;
132 uint32_t irq;
133 uintptr_t phyBase;
134 volatile unsigned char *remapBase;
135 size_t regSize;
136 size_t maxTransSize;
137 uint16_t channelNum;
138 OsalSpinlock lock;
139 struct DmacChanInfo *channelList;
140 int32_t (*getChanInfo)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, struct DmacMsg *msg);
141 int32_t (*dmaChanEnable)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo);
142 int32_t (*dmaM2mChanEnable)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo,
143 uintptr_t src, uintptr_t dest, size_t length);
144 void (*dmacChanDisable)(struct DmaCntlr *cntlr, uint16_t channel);
145 void (*dmacCacheInv)(uintptr_t vaddr, uintptr_t vend);
146 void (*dmacCacheFlush)(uintptr_t vaddr, uintptr_t vend);
147 void *(*dmacPaddrToVaddr)(uintptr_t paddr);
148 uintptr_t (*dmacVaddrToPaddr)(void *vaddr);
149 int (*dmacGetChanStatus)(struct DmaCntlr *cntlr, uint16_t chan);
150 uintptr_t (*dmacGetCurrDestAddr)(struct DmaCntlr *cntlr, uint16_t chan);
151 void *private;
152 };
153
154 #ifdef LOSCFG_DRIVERS_HDF_PLATFORM_DMAC
155 struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *dev);
156
157 void DmaCntlrDestroy(struct DmaCntlr *cntlr);
158
159 int32_t DmacCntlrAdd(struct DmaCntlr *cntlr);
160
161 void DmacCntlrRemove(struct DmaCntlr *cntlr);
162
163 int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg);
164
165 uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan);
166 #else
DmaCntlrCreate(struct HdfDeviceObject * dev)167 static inline struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *dev)
168 {
169 (void)dev;
170 return NULL;
171 }
172
DmaCntlrDestroy(struct DmaCntlr * cntlr)173 static inline void DmaCntlrDestroy(struct DmaCntlr *cntlr)
174 {
175 (void)cntlr;
176 return;
177 }
178
DmacCntlrAdd(struct DmaCntlr * cntlr)179 static inline int32_t DmacCntlrAdd(struct DmaCntlr *cntlr)
180 {
181 (void)cntlr;
182 return HDF_ERR_NOT_SUPPORT;
183 }
184
DmacCntlrRemove(struct DmaCntlr * cntlr)185 static inline void DmacCntlrRemove(struct DmaCntlr *cntlr)
186 {
187 (void)cntlr;
188 return;
189 }
190
DmaCntlrTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)191 static inline int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
192 {
193 (void)cntlr;
194 (void)msg;
195 return HDF_ERR_NOT_SUPPORT;
196 }
197
DmaGetCurrChanDestAddr(struct DmaCntlr * cntlr,uint16_t chan)198 static inline uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan)
199 {
200 (void)cntlr;
201 (void)chan;
202 return 0;
203 }
204 #endif
205
206 #ifdef __cplusplus
207 #if __cplusplus
208 }
209 #endif
210 #endif /* __cplusplus */
211
212 #endif /* DMAC_CORE_H */
213