1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright 2019 NXP 3 4 #include <linux/bitfield.h> 5 #include <linux/module.h> 6 #include <linux/types.h> 7 #include <linux/io.h> 8 #include <linux/fsl/mc.h> 9 #include "dpdmai.h" 10 11 #define DEST_TYPE_MASK 0xF 12 13 struct dpdmai_rsp_get_attributes { 14 __le32 id; 15 u8 num_of_priorities; 16 u8 num_of_queues; 17 u8 pad0[2]; 18 __le16 major; 19 __le16 minor; 20 }; 21 22 struct dpdmai_cmd_queue { 23 __le32 dest_id; 24 u8 dest_priority; 25 union { 26 u8 queue; 27 u8 pri; 28 }; 29 u8 dest_type; 30 u8 queue_idx; 31 __le64 user_ctx; 32 union { 33 __le32 options; 34 __le32 fqid; 35 }; 36 } __packed; 37 38 struct dpdmai_rsp_get_tx_queue { 39 __le64 pad; 40 __le32 fqid; 41 }; 42 43 struct dpdmai_cmd_open { 44 __le32 dpdmai_id; 45 } __packed; 46 47 struct dpdmai_cmd_destroy { 48 __le32 dpdmai_id; 49 } __packed; 50 51 static inline u64 mc_enc(int lsoffset, int width, u64 val) 52 { 53 return (val & MAKE_UMASK64(width)) << lsoffset; 54 } 55 56 /** 57 * dpdmai_open() - Open a control session for the specified object 58 * @mc_io: Pointer to MC portal's I/O object 59 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 60 * @dpdmai_id: DPDMAI unique ID 61 * @token: Returned token; use in subsequent API calls 62 * 63 * This function can be used to open a control session for an 64 * already created object; an object may have been declared in 65 * the DPL or by calling the dpdmai_create() function. 66 * This function returns a unique authentication token, 67 * associated with the specific object ID and the specific MC 68 * portal; this token must be used in all subsequent commands for 69 * this specific object. 70 * 71 * Return: '0' on Success; Error code otherwise. 72 */ 73 int dpdmai_open(struct fsl_mc_io *mc_io, u32 cmd_flags, 74 int dpdmai_id, u16 *token) 75 { 76 struct dpdmai_cmd_open *cmd_params; 77 struct fsl_mc_command cmd = { 0 }; 78 int err; 79 80 /* prepare command */ 81 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_OPEN, 82 cmd_flags, 0); 83 84 cmd_params = (struct dpdmai_cmd_open *)&cmd.params; 85 cmd_params->dpdmai_id = cpu_to_le32(dpdmai_id); 86 87 /* send command to mc*/ 88 err = mc_send_command(mc_io, &cmd); 89 if (err) 90 return err; 91 92 /* retrieve response parameters */ 93 *token = mc_cmd_hdr_read_token(&cmd); 94 95 return 0; 96 } 97 EXPORT_SYMBOL_GPL(dpdmai_open); 98 99 /** 100 * dpdmai_close() - Close the control session of the object 101 * @mc_io: Pointer to MC portal's I/O object 102 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 103 * @token: Token of DPDMAI object 104 * 105 * After this function is called, no further operations are 106 * allowed on the object without opening a new control session. 107 * 108 * Return: '0' on Success; Error code otherwise. 109 */ 110 int dpdmai_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) 111 { 112 struct fsl_mc_command cmd = { 0 }; 113 114 /* prepare command */ 115 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLOSE, 116 cmd_flags, token); 117 118 /* send command to mc*/ 119 return mc_send_command(mc_io, &cmd); 120 } 121 EXPORT_SYMBOL_GPL(dpdmai_close); 122 123 /** 124 * dpdmai_destroy() - Destroy the DPDMAI object and release all its resources. 125 * @mc_io: Pointer to MC portal's I/O object 126 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 127 * @dpdmai_id: The object id; it must be a valid id within the container that created this object; 128 * @token: Token of DPDMAI object 129 * 130 * Return: '0' on Success; error code otherwise. 131 */ 132 int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u32 dpdmai_id, u16 token) 133 { 134 struct dpdmai_cmd_destroy *cmd_params; 135 struct fsl_mc_command cmd = { 0 }; 136 137 /* prepare command */ 138 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY, 139 cmd_flags, token); 140 141 cmd_params = (struct dpdmai_cmd_destroy *)&cmd.params; 142 cmd_params->dpdmai_id = cpu_to_le32(dpdmai_id); 143 144 /* send command to mc*/ 145 return mc_send_command(mc_io, &cmd); 146 } 147 EXPORT_SYMBOL_GPL(dpdmai_destroy); 148 149 /** 150 * dpdmai_enable() - Enable the DPDMAI, allow sending and receiving frames. 151 * @mc_io: Pointer to MC portal's I/O object 152 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 153 * @token: Token of DPDMAI object 154 * 155 * Return: '0' on Success; Error code otherwise. 156 */ 157 int dpdmai_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) 158 { 159 struct fsl_mc_command cmd = { 0 }; 160 161 /* prepare command */ 162 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_ENABLE, 163 cmd_flags, token); 164 165 /* send command to mc*/ 166 return mc_send_command(mc_io, &cmd); 167 } 168 EXPORT_SYMBOL_GPL(dpdmai_enable); 169 170 /** 171 * dpdmai_disable() - Disable the DPDMAI, stop sending and receiving frames. 172 * @mc_io: Pointer to MC portal's I/O object 173 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 174 * @token: Token of DPDMAI object 175 * 176 * Return: '0' on Success; Error code otherwise. 177 */ 178 int dpdmai_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) 179 { 180 struct fsl_mc_command cmd = { 0 }; 181 182 /* prepare command */ 183 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DISABLE, 184 cmd_flags, token); 185 186 /* send command to mc*/ 187 return mc_send_command(mc_io, &cmd); 188 } 189 EXPORT_SYMBOL_GPL(dpdmai_disable); 190 191 /** 192 * dpdmai_reset() - Reset the DPDMAI, returns the object to initial state. 193 * @mc_io: Pointer to MC portal's I/O object 194 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 195 * @token: Token of DPDMAI object 196 * 197 * Return: '0' on Success; Error code otherwise. 198 */ 199 int dpdmai_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) 200 { 201 struct fsl_mc_command cmd = { 0 }; 202 203 /* prepare command */ 204 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_RESET, 205 cmd_flags, token); 206 207 /* send command to mc*/ 208 return mc_send_command(mc_io, &cmd); 209 } 210 EXPORT_SYMBOL_GPL(dpdmai_reset); 211 212 /** 213 * dpdmai_get_attributes() - Retrieve DPDMAI attributes. 214 * @mc_io: Pointer to MC portal's I/O object 215 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 216 * @token: Token of DPDMAI object 217 * @attr: Returned object's attributes 218 * 219 * Return: '0' on Success; Error code otherwise. 220 */ 221 int dpdmai_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, 222 u16 token, struct dpdmai_attr *attr) 223 { 224 struct dpdmai_rsp_get_attributes *rsp_params; 225 struct fsl_mc_command cmd = { 0 }; 226 int err; 227 228 /* prepare command */ 229 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_ATTR, 230 cmd_flags, token); 231 232 /* send command to mc*/ 233 err = mc_send_command(mc_io, &cmd); 234 if (err) 235 return err; 236 237 /* retrieve response parameters */ 238 rsp_params = (struct dpdmai_rsp_get_attributes *)cmd.params; 239 attr->id = le32_to_cpu(rsp_params->id); 240 attr->version.major = le16_to_cpu(rsp_params->major); 241 attr->version.minor = le16_to_cpu(rsp_params->minor); 242 attr->num_of_priorities = rsp_params->num_of_priorities; 243 attr->num_of_queues = rsp_params->num_of_queues; 244 245 return 0; 246 } 247 EXPORT_SYMBOL_GPL(dpdmai_get_attributes); 248 249 /** 250 * dpdmai_set_rx_queue() - Set Rx queue configuration 251 * @mc_io: Pointer to MC portal's I/O object 252 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 253 * @token: Token of DPDMAI object 254 * @queue_idx: DMA queue index 255 * @priority: Select the queue relative to number of 256 * priorities configured at DPDMAI creation 257 * @cfg: Rx queue configuration 258 * 259 * Return: '0' on Success; Error code otherwise. 260 */ 261 int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 queue_idx, 262 u8 priority, const struct dpdmai_rx_queue_cfg *cfg) 263 { 264 struct dpdmai_cmd_queue *cmd_params; 265 struct fsl_mc_command cmd = { 0 }; 266 267 /* prepare command */ 268 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_RX_QUEUE, 269 cmd_flags, token); 270 271 cmd_params = (struct dpdmai_cmd_queue *)cmd.params; 272 cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id); 273 cmd_params->dest_priority = cfg->dest_cfg.priority; 274 cmd_params->pri = priority; 275 cmd_params->dest_type = cfg->dest_cfg.dest_type; 276 cmd_params->user_ctx = cpu_to_le64(cfg->user_ctx); 277 cmd_params->options = cpu_to_le32(cfg->options); 278 cmd_params->queue_idx = queue_idx; 279 280 /* send command to mc*/ 281 return mc_send_command(mc_io, &cmd); 282 } 283 EXPORT_SYMBOL_GPL(dpdmai_set_rx_queue); 284 285 /** 286 * dpdmai_get_rx_queue() - Retrieve Rx queue attributes. 287 * @mc_io: Pointer to MC portal's I/O object 288 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 289 * @token: Token of DPDMAI object 290 * @queue_idx: DMA Queue index 291 * @priority: Select the queue relative to number of 292 * priorities configured at DPDMAI creation 293 * @attr: Returned Rx queue attributes 294 * 295 * Return: '0' on Success; Error code otherwise. 296 */ 297 int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 queue_idx, 298 u8 priority, struct dpdmai_rx_queue_attr *attr) 299 { 300 struct dpdmai_cmd_queue *cmd_params; 301 struct fsl_mc_command cmd = { 0 }; 302 int err; 303 304 /* prepare command */ 305 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_RX_QUEUE, 306 cmd_flags, token); 307 308 cmd_params = (struct dpdmai_cmd_queue *)cmd.params; 309 cmd_params->queue = priority; 310 cmd_params->queue_idx = queue_idx; 311 312 /* send command to mc*/ 313 err = mc_send_command(mc_io, &cmd); 314 if (err) 315 return err; 316 317 /* retrieve response parameters */ 318 attr->dest_cfg.dest_id = le32_to_cpu(cmd_params->dest_id); 319 attr->dest_cfg.priority = cmd_params->dest_priority; 320 attr->dest_cfg.dest_type = FIELD_GET(DEST_TYPE_MASK, cmd_params->dest_type); 321 attr->user_ctx = le64_to_cpu(cmd_params->user_ctx); 322 attr->fqid = le32_to_cpu(cmd_params->fqid); 323 324 return 0; 325 } 326 EXPORT_SYMBOL_GPL(dpdmai_get_rx_queue); 327 328 /** 329 * dpdmai_get_tx_queue() - Retrieve Tx queue attributes. 330 * @mc_io: Pointer to MC portal's I/O object 331 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 332 * @token: Token of DPDMAI object 333 * @queue_idx: DMA queue index 334 * @priority: Select the queue relative to number of 335 * priorities configured at DPDMAI creation 336 * @attr: Returned DMA Tx queue attributes 337 * 338 * Return: '0' on Success; Error code otherwise. 339 */ 340 int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, 341 u16 token, u8 queue_idx, u8 priority, struct dpdmai_tx_queue_attr *attr) 342 { 343 struct dpdmai_rsp_get_tx_queue *rsp_params; 344 struct dpdmai_cmd_queue *cmd_params; 345 struct fsl_mc_command cmd = { 0 }; 346 int err; 347 348 /* prepare command */ 349 cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_TX_QUEUE, 350 cmd_flags, token); 351 352 cmd_params = (struct dpdmai_cmd_queue *)cmd.params; 353 cmd_params->queue = priority; 354 cmd_params->queue_idx = queue_idx; 355 356 /* send command to mc*/ 357 err = mc_send_command(mc_io, &cmd); 358 if (err) 359 return err; 360 361 /* retrieve response parameters */ 362 363 rsp_params = (struct dpdmai_rsp_get_tx_queue *)cmd.params; 364 attr->fqid = le32_to_cpu(rsp_params->fqid); 365 366 return 0; 367 } 368 EXPORT_SYMBOL_GPL(dpdmai_get_tx_queue); 369 370 MODULE_DESCRIPTION("NXP DPAA2 QDMA driver"); 371 MODULE_LICENSE("GPL v2"); 372