1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2 /* 3 * Copyright 2013-2016 Freescale Semiconductor Inc. 4 * 5 */ 6 #include <linux/kernel.h> 7 #include <linux/fsl/mc.h> 8 9 #include "fsl-mc-private.h" 10 11 /** 12 * dprc_open() - Open DPRC object for use 13 * @mc_io: Pointer to MC portal's I/O object 14 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 15 * @container_id: Container ID to open 16 * @token: Returned token of DPRC object 17 * 18 * Return: '0' on Success; Error code otherwise. 19 * 20 * @warning Required before any operation on the object. 21 */ 22 int dprc_open(struct fsl_mc_io *mc_io, 23 u32 cmd_flags, 24 int container_id, 25 u16 *token) 26 { 27 struct fsl_mc_command cmd = { 0 }; 28 struct dprc_cmd_open *cmd_params; 29 int err; 30 31 /* prepare command */ 32 cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, 33 0); 34 cmd_params = (struct dprc_cmd_open *)cmd.params; 35 cmd_params->container_id = cpu_to_le32(container_id); 36 37 /* send command to mc*/ 38 err = mc_send_command(mc_io, &cmd); 39 if (err) 40 return err; 41 42 /* retrieve response parameters */ 43 *token = mc_cmd_hdr_read_token(&cmd); 44 45 return 0; 46 } 47 EXPORT_SYMBOL_GPL(dprc_open); 48 49 /** 50 * dprc_close() - Close the control session of the object 51 * @mc_io: Pointer to MC portal's I/O object 52 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 53 * @token: Token of DPRC object 54 * 55 * After this function is called, no further operations are 56 * allowed on the object without opening a new control session. 57 * 58 * Return: '0' on Success; Error code otherwise. 59 */ 60 int dprc_close(struct fsl_mc_io *mc_io, 61 u32 cmd_flags, 62 u16 token) 63 { 64 struct fsl_mc_command cmd = { 0 }; 65 66 /* prepare command */ 67 cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, 68 token); 69 70 /* send command to mc*/ 71 return mc_send_command(mc_io, &cmd); 72 } 73 EXPORT_SYMBOL_GPL(dprc_close); 74 75 /** 76 * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. 77 * @mc_io: Pointer to MC portal's I/O object 78 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 79 * @token: Token of DPRC object 80 * @irq_index: Identifies the interrupt index to configure 81 * @irq_cfg: IRQ configuration 82 * 83 * Return: '0' on Success; Error code otherwise. 84 */ 85 int dprc_set_irq(struct fsl_mc_io *mc_io, 86 u32 cmd_flags, 87 u16 token, 88 u8 irq_index, 89 struct dprc_irq_cfg *irq_cfg) 90 { 91 struct fsl_mc_command cmd = { 0 }; 92 struct dprc_cmd_set_irq *cmd_params; 93 94 /* prepare command */ 95 cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, 96 cmd_flags, 97 token); 98 cmd_params = (struct dprc_cmd_set_irq *)cmd.params; 99 cmd_params->irq_val = cpu_to_le32(irq_cfg->val); 100 cmd_params->irq_index = irq_index; 101 cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); 102 cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); 103 104 /* send command to mc*/ 105 return mc_send_command(mc_io, &cmd); 106 } 107 108 /** 109 * dprc_set_irq_enable() - Set overall interrupt state. 110 * @mc_io: Pointer to MC portal's I/O object 111 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 112 * @token: Token of DPRC object 113 * @irq_index: The interrupt index to configure 114 * @en: Interrupt state - enable = 1, disable = 0 115 * 116 * Allows GPP software to control when interrupts are generated. 117 * Each interrupt can have up to 32 causes. The enable/disable control's the 118 * overall interrupt state. if the interrupt is disabled no causes will cause 119 * an interrupt. 120 * 121 * Return: '0' on Success; Error code otherwise. 122 */ 123 int dprc_set_irq_enable(struct fsl_mc_io *mc_io, 124 u32 cmd_flags, 125 u16 token, 126 u8 irq_index, 127 u8 en) 128 { 129 struct fsl_mc_command cmd = { 0 }; 130 struct dprc_cmd_set_irq_enable *cmd_params; 131 132 /* prepare command */ 133 cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, 134 cmd_flags, token); 135 cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; 136 cmd_params->enable = en & DPRC_ENABLE; 137 cmd_params->irq_index = irq_index; 138 139 /* send command to mc*/ 140 return mc_send_command(mc_io, &cmd); 141 } 142 143 /** 144 * dprc_set_irq_mask() - Set interrupt mask. 145 * @mc_io: Pointer to MC portal's I/O object 146 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 147 * @token: Token of DPRC object 148 * @irq_index: The interrupt index to configure 149 * @mask: event mask to trigger interrupt; 150 * each bit: 151 * 0 = ignore event 152 * 1 = consider event for asserting irq 153 * 154 * Every interrupt can have up to 32 causes and the interrupt model supports 155 * masking/unmasking each cause independently 156 * 157 * Return: '0' on Success; Error code otherwise. 158 */ 159 int dprc_set_irq_mask(struct fsl_mc_io *mc_io, 160 u32 cmd_flags, 161 u16 token, 162 u8 irq_index, 163 u32 mask) 164 { 165 struct fsl_mc_command cmd = { 0 }; 166 struct dprc_cmd_set_irq_mask *cmd_params; 167 168 /* prepare command */ 169 cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, 170 cmd_flags, token); 171 cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; 172 cmd_params->mask = cpu_to_le32(mask); 173 cmd_params->irq_index = irq_index; 174 175 /* send command to mc*/ 176 return mc_send_command(mc_io, &cmd); 177 } 178 179 /** 180 * dprc_get_irq_status() - Get the current status of any pending interrupts. 181 * @mc_io: Pointer to MC portal's I/O object 182 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 183 * @token: Token of DPRC object 184 * @irq_index: The interrupt index to configure 185 * @status: Returned interrupts status - one bit per cause: 186 * 0 = no interrupt pending 187 * 1 = interrupt pending 188 * 189 * Return: '0' on Success; Error code otherwise. 190 */ 191 int dprc_get_irq_status(struct fsl_mc_io *mc_io, 192 u32 cmd_flags, 193 u16 token, 194 u8 irq_index, 195 u32 *status) 196 { 197 struct fsl_mc_command cmd = { 0 }; 198 struct dprc_cmd_get_irq_status *cmd_params; 199 struct dprc_rsp_get_irq_status *rsp_params; 200 int err; 201 202 /* prepare command */ 203 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, 204 cmd_flags, token); 205 cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; 206 cmd_params->status = cpu_to_le32(*status); 207 cmd_params->irq_index = irq_index; 208 209 /* send command to mc*/ 210 err = mc_send_command(mc_io, &cmd); 211 if (err) 212 return err; 213 214 /* retrieve response parameters */ 215 rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; 216 *status = le32_to_cpu(rsp_params->status); 217 218 return 0; 219 } 220 221 /** 222 * dprc_clear_irq_status() - Clear a pending interrupt's status 223 * @mc_io: Pointer to MC portal's I/O object 224 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 225 * @token: Token of DPRC object 226 * @irq_index: The interrupt index to configure 227 * @status: bits to clear (W1C) - one bit per cause: 228 * 0 = don't change 229 * 1 = clear status bit 230 * 231 * Return: '0' on Success; Error code otherwise. 232 */ 233 int dprc_clear_irq_status(struct fsl_mc_io *mc_io, 234 u32 cmd_flags, 235 u16 token, 236 u8 irq_index, 237 u32 status) 238 { 239 struct fsl_mc_command cmd = { 0 }; 240 struct dprc_cmd_clear_irq_status *cmd_params; 241 242 /* prepare command */ 243 cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, 244 cmd_flags, token); 245 cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; 246 cmd_params->status = cpu_to_le32(status); 247 cmd_params->irq_index = irq_index; 248 249 /* send command to mc*/ 250 return mc_send_command(mc_io, &cmd); 251 } 252 253 /** 254 * dprc_get_attributes() - Obtains container attributes 255 * @mc_io: Pointer to MC portal's I/O object 256 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 257 * @token: Token of DPRC object 258 * @attributes Returned container attributes 259 * 260 * Return: '0' on Success; Error code otherwise. 261 */ 262 int dprc_get_attributes(struct fsl_mc_io *mc_io, 263 u32 cmd_flags, 264 u16 token, 265 struct dprc_attributes *attr) 266 { 267 struct fsl_mc_command cmd = { 0 }; 268 struct dprc_rsp_get_attributes *rsp_params; 269 int err; 270 271 /* prepare command */ 272 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, 273 cmd_flags, 274 token); 275 276 /* send command to mc*/ 277 err = mc_send_command(mc_io, &cmd); 278 if (err) 279 return err; 280 281 /* retrieve response parameters */ 282 rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; 283 attr->container_id = le32_to_cpu(rsp_params->container_id); 284 attr->icid = le16_to_cpu(rsp_params->icid); 285 attr->options = le32_to_cpu(rsp_params->options); 286 attr->portal_id = le32_to_cpu(rsp_params->portal_id); 287 288 return 0; 289 } 290 291 /** 292 * dprc_get_obj_count() - Obtains the number of objects in the DPRC 293 * @mc_io: Pointer to MC portal's I/O object 294 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 295 * @token: Token of DPRC object 296 * @obj_count: Number of objects assigned to the DPRC 297 * 298 * Return: '0' on Success; Error code otherwise. 299 */ 300 int dprc_get_obj_count(struct fsl_mc_io *mc_io, 301 u32 cmd_flags, 302 u16 token, 303 int *obj_count) 304 { 305 struct fsl_mc_command cmd = { 0 }; 306 struct dprc_rsp_get_obj_count *rsp_params; 307 int err; 308 309 /* prepare command */ 310 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, 311 cmd_flags, token); 312 313 /* send command to mc*/ 314 err = mc_send_command(mc_io, &cmd); 315 if (err) 316 return err; 317 318 /* retrieve response parameters */ 319 rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; 320 *obj_count = le32_to_cpu(rsp_params->obj_count); 321 322 return 0; 323 } 324 EXPORT_SYMBOL_GPL(dprc_get_obj_count); 325 326 /** 327 * dprc_get_obj() - Get general information on an object 328 * @mc_io: Pointer to MC portal's I/O object 329 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 330 * @token: Token of DPRC object 331 * @obj_index: Index of the object to be queried (< obj_count) 332 * @obj_desc: Returns the requested object descriptor 333 * 334 * The object descriptors are retrieved one by one by incrementing 335 * obj_index up to (not including) the value of obj_count returned 336 * from dprc_get_obj_count(). dprc_get_obj_count() must 337 * be called prior to dprc_get_obj(). 338 * 339 * Return: '0' on Success; Error code otherwise. 340 */ 341 int dprc_get_obj(struct fsl_mc_io *mc_io, 342 u32 cmd_flags, 343 u16 token, 344 int obj_index, 345 struct fsl_mc_obj_desc *obj_desc) 346 { 347 struct fsl_mc_command cmd = { 0 }; 348 struct dprc_cmd_get_obj *cmd_params; 349 struct dprc_rsp_get_obj *rsp_params; 350 int err; 351 352 /* prepare command */ 353 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, 354 cmd_flags, 355 token); 356 cmd_params = (struct dprc_cmd_get_obj *)cmd.params; 357 cmd_params->obj_index = cpu_to_le32(obj_index); 358 359 /* send command to mc*/ 360 err = mc_send_command(mc_io, &cmd); 361 if (err) 362 return err; 363 364 /* retrieve response parameters */ 365 rsp_params = (struct dprc_rsp_get_obj *)cmd.params; 366 obj_desc->id = le32_to_cpu(rsp_params->id); 367 obj_desc->vendor = le16_to_cpu(rsp_params->vendor); 368 obj_desc->irq_count = rsp_params->irq_count; 369 obj_desc->region_count = rsp_params->region_count; 370 obj_desc->state = le32_to_cpu(rsp_params->state); 371 obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); 372 obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); 373 obj_desc->flags = le16_to_cpu(rsp_params->flags); 374 strncpy(obj_desc->type, rsp_params->type, 16); 375 obj_desc->type[15] = '\0'; 376 strncpy(obj_desc->label, rsp_params->label, 16); 377 obj_desc->label[15] = '\0'; 378 return 0; 379 } 380 EXPORT_SYMBOL_GPL(dprc_get_obj); 381 382 /** 383 * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. 384 * @mc_io: Pointer to MC portal's I/O object 385 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 386 * @token: Token of DPRC object 387 * @obj_type: Type of the object to set its IRQ 388 * @obj_id: ID of the object to set its IRQ 389 * @irq_index: The interrupt index to configure 390 * @irq_cfg: IRQ configuration 391 * 392 * Return: '0' on Success; Error code otherwise. 393 */ 394 int dprc_set_obj_irq(struct fsl_mc_io *mc_io, 395 u32 cmd_flags, 396 u16 token, 397 char *obj_type, 398 int obj_id, 399 u8 irq_index, 400 struct dprc_irq_cfg *irq_cfg) 401 { 402 struct fsl_mc_command cmd = { 0 }; 403 struct dprc_cmd_set_obj_irq *cmd_params; 404 405 /* prepare command */ 406 cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, 407 cmd_flags, 408 token); 409 cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; 410 cmd_params->irq_val = cpu_to_le32(irq_cfg->val); 411 cmd_params->irq_index = irq_index; 412 cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); 413 cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); 414 cmd_params->obj_id = cpu_to_le32(obj_id); 415 strncpy(cmd_params->obj_type, obj_type, 16); 416 cmd_params->obj_type[15] = '\0'; 417 418 /* send command to mc*/ 419 return mc_send_command(mc_io, &cmd); 420 } 421 EXPORT_SYMBOL_GPL(dprc_set_obj_irq); 422 423 /** 424 * dprc_get_obj_region() - Get region information for a specified object. 425 * @mc_io: Pointer to MC portal's I/O object 426 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 427 * @token: Token of DPRC object 428 * @obj_type; Object type as returned in dprc_get_obj() 429 * @obj_id: Unique object instance as returned in dprc_get_obj() 430 * @region_index: The specific region to query 431 * @region_desc: Returns the requested region descriptor 432 * 433 * Return: '0' on Success; Error code otherwise. 434 */ 435 int dprc_get_obj_region(struct fsl_mc_io *mc_io, 436 u32 cmd_flags, 437 u16 token, 438 char *obj_type, 439 int obj_id, 440 u8 region_index, 441 struct dprc_region_desc *region_desc) 442 { 443 struct fsl_mc_command cmd = { 0 }; 444 struct dprc_cmd_get_obj_region *cmd_params; 445 struct dprc_rsp_get_obj_region *rsp_params; 446 u16 major_ver, minor_ver; 447 int err; 448 449 /* prepare command */ 450 err = dprc_get_api_version(mc_io, 0, 451 &major_ver, 452 &minor_ver); 453 if (err) 454 return err; 455 456 /** 457 * MC API version 6.3 introduced a new field to the region 458 * descriptor: base_address. If the older API is in use then the base 459 * address is set to zero to indicate it needs to be obtained elsewhere 460 * (typically the device tree). 461 */ 462 if (major_ver > 6 || (major_ver == 6 && minor_ver >= 3)) 463 cmd.header = 464 mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG_V2, 465 cmd_flags, token); 466 else 467 cmd.header = 468 mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, 469 cmd_flags, token); 470 471 cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; 472 cmd_params->obj_id = cpu_to_le32(obj_id); 473 cmd_params->region_index = region_index; 474 strncpy(cmd_params->obj_type, obj_type, 16); 475 cmd_params->obj_type[15] = '\0'; 476 477 /* send command to mc*/ 478 err = mc_send_command(mc_io, &cmd); 479 if (err) 480 return err; 481 482 /* retrieve response parameters */ 483 rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; 484 region_desc->base_offset = le64_to_cpu(rsp_params->base_offset); 485 region_desc->size = le32_to_cpu(rsp_params->size); 486 if (major_ver > 6 || (major_ver == 6 && minor_ver >= 3)) 487 region_desc->base_address = le64_to_cpu(rsp_params->base_addr); 488 else 489 region_desc->base_address = 0; 490 491 return 0; 492 } 493 EXPORT_SYMBOL_GPL(dprc_get_obj_region); 494 495 /** 496 * dprc_get_api_version - Get Data Path Resource Container API version 497 * @mc_io: Pointer to Mc portal's I/O object 498 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 499 * @major_ver: Major version of Data Path Resource Container API 500 * @minor_ver: Minor version of Data Path Resource Container API 501 * 502 * Return: '0' on Success; Error code otherwise. 503 */ 504 int dprc_get_api_version(struct fsl_mc_io *mc_io, 505 u32 cmd_flags, 506 u16 *major_ver, 507 u16 *minor_ver) 508 { 509 struct fsl_mc_command cmd = { 0 }; 510 int err; 511 512 /* prepare command */ 513 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, 514 cmd_flags, 0); 515 516 /* send command to mc */ 517 err = mc_send_command(mc_io, &cmd); 518 if (err) 519 return err; 520 521 /* retrieve response parameters */ 522 mc_cmd_read_api_version(&cmd, major_ver, minor_ver); 523 524 return 0; 525 } 526 527 /** 528 * dprc_get_container_id - Get container ID associated with a given portal. 529 * @mc_io: Pointer to Mc portal's I/O object 530 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 531 * @container_id: Requested container id 532 * 533 * Return: '0' on Success; Error code otherwise. 534 */ 535 int dprc_get_container_id(struct fsl_mc_io *mc_io, 536 u32 cmd_flags, 537 int *container_id) 538 { 539 struct fsl_mc_command cmd = { 0 }; 540 int err; 541 542 /* prepare command */ 543 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, 544 cmd_flags, 545 0); 546 547 /* send command to mc*/ 548 err = mc_send_command(mc_io, &cmd); 549 if (err) 550 return err; 551 552 /* retrieve response parameters */ 553 *container_id = (int)mc_cmd_read_object_id(&cmd); 554 555 return 0; 556 } 557 558 /** 559 * dprc_get_connection() - Get connected endpoint and link status if connection 560 * exists. 561 * @mc_io: Pointer to MC portal's I/O object 562 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 563 * @token: Token of DPRC object 564 * @endpoint1: Endpoint 1 configuration parameters 565 * @endpoint2: Returned endpoint 2 configuration parameters 566 * @state: Returned link state: 567 * 1 - link is up; 568 * 0 - link is down; 569 * -1 - no connection (endpoint2 information is irrelevant) 570 * 571 * Return: '0' on Success; -ENOTCONN if connection does not exist. 572 */ 573 int dprc_get_connection(struct fsl_mc_io *mc_io, 574 u32 cmd_flags, 575 u16 token, 576 const struct dprc_endpoint *endpoint1, 577 struct dprc_endpoint *endpoint2, 578 int *state) 579 { 580 struct dprc_cmd_get_connection *cmd_params; 581 struct dprc_rsp_get_connection *rsp_params; 582 struct fsl_mc_command cmd = { 0 }; 583 int err, i; 584 585 /* prepare command */ 586 cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, 587 cmd_flags, 588 token); 589 cmd_params = (struct dprc_cmd_get_connection *)cmd.params; 590 cmd_params->ep1_id = cpu_to_le32(endpoint1->id); 591 cmd_params->ep1_interface_id = cpu_to_le16(endpoint1->if_id); 592 for (i = 0; i < 16; i++) 593 cmd_params->ep1_type[i] = endpoint1->type[i]; 594 595 /* send command to mc */ 596 err = mc_send_command(mc_io, &cmd); 597 if (err) 598 return -ENOTCONN; 599 600 /* retrieve response parameters */ 601 rsp_params = (struct dprc_rsp_get_connection *)cmd.params; 602 endpoint2->id = le32_to_cpu(rsp_params->ep2_id); 603 endpoint2->if_id = le16_to_cpu(rsp_params->ep2_interface_id); 604 *state = le32_to_cpu(rsp_params->state); 605 for (i = 0; i < 16; i++) 606 endpoint2->type[i] = rsp_params->ep2_type[i]; 607 608 return 0; 609 } 610