1/* Copyright 2013-2014 Freescale Semiconductor Inc. 2* 3* Redistribution and use in source and binary forms, with or without 4* modification, are permitted provided that the following conditions are met: 5* * Redistributions of source code must retain the above copyright 6* notice, this list of conditions and the following disclaimer. 7* * Redistributions in binary form must reproduce the above copyright 8* notice, this list of conditions and the following disclaimer in the 9* documentation and/or other materials provided with the distribution. 10* * Neither the name of the above-listed copyright holders nor the 11* names of any contributors may be used to endorse or promote products 12* derived from this software without specific prior written permission. 13* 14* 15* ALTERNATIVELY, this software may be distributed under the terms of the 16* GNU General Public License ("GPL") as published by the Free Software 17* Foundation, either version 2 of that License or (at your option) any 18* later version. 19* 20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30* POSSIBILITY OF SUCH DAMAGE. 31*/ 32#include "../include/mc-sys.h" 33#include "../include/mc-cmd.h" 34#include "../include/dpbp.h" 35#include "../include/dpbp-cmd.h" 36 37/** 38 * dpbp_open() - Open a control session for the specified object. 39 * @mc_io: Pointer to MC portal's I/O object 40 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 41 * @dpbp_id: DPBP unique ID 42 * @token: Returned token; use in subsequent API calls 43 * 44 * This function can be used to open a control session for an 45 * already created object; an object may have been declared in 46 * the DPL or by calling the dpbp_create function. 47 * This function returns a unique authentication token, 48 * associated with the specific object ID and the specific MC 49 * portal; this token must be used in all subsequent commands for 50 * this specific object 51 * 52 * Return: '0' on Success; Error code otherwise. 53 */ 54int dpbp_open(struct fsl_mc_io *mc_io, 55 u32 cmd_flags, 56 int dpbp_id, 57 u16 *token) 58{ 59 struct mc_command cmd = { 0 }; 60 int err; 61 62 /* prepare command */ 63 cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, 64 cmd_flags, 0); 65 cmd.params[0] |= mc_enc(0, 32, dpbp_id); 66 67 /* send command to mc*/ 68 err = mc_send_command(mc_io, &cmd); 69 if (err) 70 return err; 71 72 /* retrieve response parameters */ 73 *token = MC_CMD_HDR_READ_TOKEN(cmd.header); 74 75 return err; 76} 77EXPORT_SYMBOL(dpbp_open); 78 79/** 80 * dpbp_close() - Close the control session of the object 81 * @mc_io: Pointer to MC portal's I/O object 82 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 83 * @token: Token of DPBP object 84 * 85 * After this function is called, no further operations are 86 * allowed on the object without opening a new control session. 87 * 88 * Return: '0' on Success; Error code otherwise. 89 */ 90int dpbp_close(struct fsl_mc_io *mc_io, 91 u32 cmd_flags, 92 u16 token) 93{ 94 struct mc_command cmd = { 0 }; 95 96 /* prepare command */ 97 cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, 98 token); 99 100 /* send command to mc*/ 101 return mc_send_command(mc_io, &cmd); 102} 103EXPORT_SYMBOL(dpbp_close); 104 105/** 106 * dpbp_create() - Create the DPBP object. 107 * @mc_io: Pointer to MC portal's I/O object 108 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 109 * @cfg: Configuration structure 110 * @token: Returned token; use in subsequent API calls 111 * 112 * Create the DPBP object, allocate required resources and 113 * perform required initialization. 114 * 115 * The object can be created either by declaring it in the 116 * DPL file, or by calling this function. 117 * This function returns a unique authentication token, 118 * associated with the specific object ID and the specific MC 119 * portal; this token must be used in all subsequent calls to 120 * this specific object. For objects that are created using the 121 * DPL file, call dpbp_open function to get an authentication 122 * token first. 123 * 124 * Return: '0' on Success; Error code otherwise. 125 */ 126int dpbp_create(struct fsl_mc_io *mc_io, 127 u32 cmd_flags, 128 const struct dpbp_cfg *cfg, 129 u16 *token) 130{ 131 struct mc_command cmd = { 0 }; 132 int err; 133 134 (void)(cfg); /* unused */ 135 136 /* prepare command */ 137 cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, 138 cmd_flags, 0); 139 140 /* send command to mc*/ 141 err = mc_send_command(mc_io, &cmd); 142 if (err) 143 return err; 144 145 /* retrieve response parameters */ 146 *token = MC_CMD_HDR_READ_TOKEN(cmd.header); 147 148 return 0; 149} 150 151/** 152 * dpbp_destroy() - Destroy the DPBP object and release all its resources. 153 * @mc_io: Pointer to MC portal's I/O object 154 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 155 * @token: Token of DPBP object 156 * 157 * Return: '0' on Success; error code otherwise. 158 */ 159int dpbp_destroy(struct fsl_mc_io *mc_io, 160 u32 cmd_flags, 161 u16 token) 162{ 163 struct mc_command cmd = { 0 }; 164 165 /* prepare command */ 166 cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, 167 cmd_flags, token); 168 169 /* send command to mc*/ 170 return mc_send_command(mc_io, &cmd); 171} 172 173/** 174 * dpbp_enable() - Enable the DPBP. 175 * @mc_io: Pointer to MC portal's I/O object 176 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 177 * @token: Token of DPBP object 178 * 179 * Return: '0' on Success; Error code otherwise. 180 */ 181int dpbp_enable(struct fsl_mc_io *mc_io, 182 u32 cmd_flags, 183 u16 token) 184{ 185 struct mc_command cmd = { 0 }; 186 187 /* prepare command */ 188 cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, 189 token); 190 191 /* send command to mc*/ 192 return mc_send_command(mc_io, &cmd); 193} 194EXPORT_SYMBOL(dpbp_enable); 195 196/** 197 * dpbp_disable() - Disable the DPBP. 198 * @mc_io: Pointer to MC portal's I/O object 199 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 200 * @token: Token of DPBP object 201 * 202 * Return: '0' on Success; Error code otherwise. 203 */ 204int dpbp_disable(struct fsl_mc_io *mc_io, 205 u32 cmd_flags, 206 u16 token) 207{ 208 struct mc_command cmd = { 0 }; 209 210 /* prepare command */ 211 cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, 212 cmd_flags, token); 213 214 /* send command to mc*/ 215 return mc_send_command(mc_io, &cmd); 216} 217EXPORT_SYMBOL(dpbp_disable); 218 219/** 220 * dpbp_is_enabled() - Check if the DPBP is enabled. 221 * @mc_io: Pointer to MC portal's I/O object 222 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 223 * @token: Token of DPBP object 224 * @en: Returns '1' if object is enabled; '0' otherwise 225 * 226 * Return: '0' on Success; Error code otherwise. 227 */ 228int dpbp_is_enabled(struct fsl_mc_io *mc_io, 229 u32 cmd_flags, 230 u16 token, 231 int *en) 232{ 233 struct mc_command cmd = { 0 }; 234 int err; 235 /* prepare command */ 236 cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, 237 token); 238 239 /* send command to mc*/ 240 err = mc_send_command(mc_io, &cmd); 241 if (err) 242 return err; 243 244 /* retrieve response parameters */ 245 *en = (int)mc_dec(cmd.params[0], 0, 1); 246 247 return 0; 248} 249 250/** 251 * dpbp_reset() - Reset the DPBP, returns the object to initial state. 252 * @mc_io: Pointer to MC portal's I/O object 253 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 254 * @token: Token of DPBP object 255 * 256 * Return: '0' on Success; Error code otherwise. 257 */ 258int dpbp_reset(struct fsl_mc_io *mc_io, 259 u32 cmd_flags, 260 u16 token) 261{ 262 struct mc_command cmd = { 0 }; 263 264 /* prepare command */ 265 cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, 266 cmd_flags, token); 267 268 /* send command to mc*/ 269 return mc_send_command(mc_io, &cmd); 270} 271 272/** 273 * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt. 274 * @mc_io: Pointer to MC portal's I/O object 275 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 276 * @token: Token of DPBP object 277 * @irq_index: Identifies the interrupt index to configure 278 * @irq_cfg: IRQ configuration 279 * 280 * Return: '0' on Success; Error code otherwise. 281 */ 282int dpbp_set_irq(struct fsl_mc_io *mc_io, 283 u32 cmd_flags, 284 u16 token, 285 u8 irq_index, 286 struct dpbp_irq_cfg *irq_cfg) 287{ 288 struct mc_command cmd = { 0 }; 289 290 /* prepare command */ 291 cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ, 292 cmd_flags, token); 293 cmd.params[0] |= mc_enc(0, 8, irq_index); 294 cmd.params[0] |= mc_enc(32, 32, irq_cfg->val); 295 cmd.params[1] |= mc_enc(0, 64, irq_cfg->addr); 296 cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); 297 298 /* send command to mc*/ 299 return mc_send_command(mc_io, &cmd); 300} 301 302/** 303 * dpbp_get_irq() - Get IRQ information from the DPBP. 304 * @mc_io: Pointer to MC portal's I/O object 305 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 306 * @token: Token of DPBP object 307 * @irq_index: The interrupt index to configure 308 * @type: Interrupt type: 0 represents message interrupt 309 * type (both irq_addr and irq_val are valid) 310 * @irq_cfg: IRQ attributes 311 * 312 * Return: '0' on Success; Error code otherwise. 313 */ 314int dpbp_get_irq(struct fsl_mc_io *mc_io, 315 u32 cmd_flags, 316 u16 token, 317 u8 irq_index, 318 int *type, 319 struct dpbp_irq_cfg *irq_cfg) 320{ 321 struct mc_command cmd = { 0 }; 322 int err; 323 324 /* prepare command */ 325 cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ, 326 cmd_flags, token); 327 cmd.params[0] |= mc_enc(32, 8, irq_index); 328 329 /* send command to mc*/ 330 err = mc_send_command(mc_io, &cmd); 331 if (err) 332 return err; 333 334 /* retrieve response parameters */ 335 irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); 336 irq_cfg->addr = (u64)mc_dec(cmd.params[1], 0, 64); 337 irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); 338 *type = (int)mc_dec(cmd.params[2], 32, 32); 339 return 0; 340} 341 342/** 343 * dpbp_set_irq_enable() - Set overall interrupt state. 344 * @mc_io: Pointer to MC portal's I/O object 345 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 346 * @token: Token of DPBP object 347 * @irq_index: The interrupt index to configure 348 * @en: Interrupt state - enable = 1, disable = 0 349 * 350 * Allows GPP software to control when interrupts are generated. 351 * Each interrupt can have up to 32 causes. The enable/disable control's the 352 * overall interrupt state. if the interrupt is disabled no causes will cause 353 * an interrupt. 354 * 355 * Return: '0' on Success; Error code otherwise. 356 */ 357int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, 358 u32 cmd_flags, 359 u16 token, 360 u8 irq_index, 361 u8 en) 362{ 363 struct mc_command cmd = { 0 }; 364 365 /* prepare command */ 366 cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE, 367 cmd_flags, token); 368 cmd.params[0] |= mc_enc(0, 8, en); 369 cmd.params[0] |= mc_enc(32, 8, irq_index); 370 371 /* send command to mc*/ 372 return mc_send_command(mc_io, &cmd); 373} 374 375/** 376 * dpbp_get_irq_enable() - Get overall interrupt state 377 * @mc_io: Pointer to MC portal's I/O object 378 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 379 * @token: Token of DPBP object 380 * @irq_index: The interrupt index to configure 381 * @en: Returned interrupt state - enable = 1, disable = 0 382 * 383 * Return: '0' on Success; Error code otherwise. 384 */ 385int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, 386 u32 cmd_flags, 387 u16 token, 388 u8 irq_index, 389 u8 *en) 390{ 391 struct mc_command cmd = { 0 }; 392 int err; 393 394 /* prepare command */ 395 cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE, 396 cmd_flags, token); 397 cmd.params[0] |= mc_enc(32, 8, irq_index); 398 399 /* send command to mc*/ 400 err = mc_send_command(mc_io, &cmd); 401 if (err) 402 return err; 403 404 /* retrieve response parameters */ 405 *en = (u8)mc_dec(cmd.params[0], 0, 8); 406 return 0; 407} 408 409/** 410 * dpbp_set_irq_mask() - Set interrupt mask. 411 * @mc_io: Pointer to MC portal's I/O object 412 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 413 * @token: Token of DPBP object 414 * @irq_index: The interrupt index to configure 415 * @mask: Event mask to trigger interrupt; 416 * each bit: 417 * 0 = ignore event 418 * 1 = consider event for asserting IRQ 419 * 420 * Every interrupt can have up to 32 causes and the interrupt model supports 421 * masking/unmasking each cause independently 422 * 423 * Return: '0' on Success; Error code otherwise. 424 */ 425int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, 426 u32 cmd_flags, 427 u16 token, 428 u8 irq_index, 429 u32 mask) 430{ 431 struct mc_command cmd = { 0 }; 432 433 /* prepare command */ 434 cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK, 435 cmd_flags, token); 436 cmd.params[0] |= mc_enc(0, 32, mask); 437 cmd.params[0] |= mc_enc(32, 8, irq_index); 438 439 /* send command to mc*/ 440 return mc_send_command(mc_io, &cmd); 441} 442 443/** 444 * dpbp_get_irq_mask() - Get interrupt mask. 445 * @mc_io: Pointer to MC portal's I/O object 446 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 447 * @token: Token of DPBP object 448 * @irq_index: The interrupt index to configure 449 * @mask: Returned event mask to trigger interrupt 450 * 451 * Every interrupt can have up to 32 causes and the interrupt model supports 452 * masking/unmasking each cause independently 453 * 454 * Return: '0' on Success; Error code otherwise. 455 */ 456int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, 457 u32 cmd_flags, 458 u16 token, 459 u8 irq_index, 460 u32 *mask) 461{ 462 struct mc_command cmd = { 0 }; 463 int err; 464 465 /* prepare command */ 466 cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK, 467 cmd_flags, token); 468 cmd.params[0] |= mc_enc(32, 8, irq_index); 469 470 /* send command to mc*/ 471 err = mc_send_command(mc_io, &cmd); 472 if (err) 473 return err; 474 475 /* retrieve response parameters */ 476 *mask = (u32)mc_dec(cmd.params[0], 0, 32); 477 return 0; 478} 479 480/** 481 * dpbp_get_irq_status() - Get the current status of any pending interrupts. 482 * 483 * @mc_io: Pointer to MC portal's I/O object 484 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 485 * @token: Token of DPBP object 486 * @irq_index: The interrupt index to configure 487 * @status: Returned interrupts status - one bit per cause: 488 * 0 = no interrupt pending 489 * 1 = interrupt pending 490 * 491 * Return: '0' on Success; Error code otherwise. 492 */ 493int dpbp_get_irq_status(struct fsl_mc_io *mc_io, 494 u32 cmd_flags, 495 u16 token, 496 u8 irq_index, 497 u32 *status) 498{ 499 struct mc_command cmd = { 0 }; 500 int err; 501 502 /* prepare command */ 503 cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS, 504 cmd_flags, token); 505 cmd.params[0] |= mc_enc(32, 8, irq_index); 506 507 /* send command to mc*/ 508 err = mc_send_command(mc_io, &cmd); 509 if (err) 510 return err; 511 512 /* retrieve response parameters */ 513 *status = (u32)mc_dec(cmd.params[0], 0, 32); 514 return 0; 515} 516 517/** 518 * dpbp_clear_irq_status() - Clear a pending interrupt's status 519 * 520 * @mc_io: Pointer to MC portal's I/O object 521 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 522 * @token: Token of DPBP object 523 * @irq_index: The interrupt index to configure 524 * @status: Bits to clear (W1C) - one bit per cause: 525 * 0 = don't change 526 * 1 = clear status bit 527 * 528 * Return: '0' on Success; Error code otherwise. 529 */ 530int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, 531 u32 cmd_flags, 532 u16 token, 533 u8 irq_index, 534 u32 status) 535{ 536 struct mc_command cmd = { 0 }; 537 538 /* prepare command */ 539 cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS, 540 cmd_flags, token); 541 cmd.params[0] |= mc_enc(0, 32, status); 542 cmd.params[0] |= mc_enc(32, 8, irq_index); 543 544 /* send command to mc*/ 545 return mc_send_command(mc_io, &cmd); 546} 547 548/** 549 * dpbp_get_attributes - Retrieve DPBP attributes. 550 * 551 * @mc_io: Pointer to MC portal's I/O object 552 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 553 * @token: Token of DPBP object 554 * @attr: Returned object's attributes 555 * 556 * Return: '0' on Success; Error code otherwise. 557 */ 558int dpbp_get_attributes(struct fsl_mc_io *mc_io, 559 u32 cmd_flags, 560 u16 token, 561 struct dpbp_attr *attr) 562{ 563 struct mc_command cmd = { 0 }; 564 int err; 565 566 /* prepare command */ 567 cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, 568 cmd_flags, token); 569 570 /* send command to mc*/ 571 err = mc_send_command(mc_io, &cmd); 572 if (err) 573 return err; 574 575 /* retrieve response parameters */ 576 attr->bpid = (u16)mc_dec(cmd.params[0], 16, 16); 577 attr->id = (int)mc_dec(cmd.params[0], 32, 32); 578 attr->version.major = (u16)mc_dec(cmd.params[1], 0, 16); 579 attr->version.minor = (u16)mc_dec(cmd.params[1], 16, 16); 580 return 0; 581} 582EXPORT_SYMBOL(dpbp_get_attributes); 583