1/* Copyright 2013-2015 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 "dpmcp.h" 35#include "dpmcp-cmd.h" 36 37/** 38 * dpmcp_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 * @dpmcp_id: DPMCP 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 dpmcp_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 dpmcp_open(struct fsl_mc_io *mc_io, 55 u32 cmd_flags, 56 int dpmcp_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(DPMCP_CMDID_OPEN, 64 cmd_flags, 0); 65 cmd.params[0] |= mc_enc(0, 32, dpmcp_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} 77 78/** 79 * dpmcp_close() - Close the control session of the object 80 * @mc_io: Pointer to MC portal's I/O object 81 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 82 * @token: Token of DPMCP object 83 * 84 * After this function is called, no further operations are 85 * allowed on the object without opening a new control session. 86 * 87 * Return: '0' on Success; Error code otherwise. 88 */ 89int dpmcp_close(struct fsl_mc_io *mc_io, 90 u32 cmd_flags, 91 u16 token) 92{ 93 struct mc_command cmd = { 0 }; 94 95 /* prepare command */ 96 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, 97 cmd_flags, token); 98 99 /* send command to mc*/ 100 return mc_send_command(mc_io, &cmd); 101} 102 103/** 104 * dpmcp_create() - Create the DPMCP object. 105 * @mc_io: Pointer to MC portal's I/O object 106 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 107 * @cfg: Configuration structure 108 * @token: Returned token; use in subsequent API calls 109 * 110 * Create the DPMCP object, allocate required resources and 111 * perform required initialization. 112 * 113 * The object can be created either by declaring it in the 114 * DPL file, or by calling this function. 115 * This function returns a unique authentication token, 116 * associated with the specific object ID and the specific MC 117 * portal; this token must be used in all subsequent calls to 118 * this specific object. For objects that are created using the 119 * DPL file, call dpmcp_open function to get an authentication 120 * token first. 121 * 122 * Return: '0' on Success; Error code otherwise. 123 */ 124int dpmcp_create(struct fsl_mc_io *mc_io, 125 u32 cmd_flags, 126 const struct dpmcp_cfg *cfg, 127 u16 *token) 128{ 129 struct mc_command cmd = { 0 }; 130 int err; 131 132 /* prepare command */ 133 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE, 134 cmd_flags, 0); 135 cmd.params[0] |= mc_enc(0, 32, cfg->portal_id); 136 137 /* send command to mc*/ 138 err = mc_send_command(mc_io, &cmd); 139 if (err) 140 return err; 141 142 /* retrieve response parameters */ 143 *token = MC_CMD_HDR_READ_TOKEN(cmd.header); 144 145 return 0; 146} 147 148/** 149 * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. 150 * @mc_io: Pointer to MC portal's I/O object 151 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 152 * @token: Token of DPMCP object 153 * 154 * Return: '0' on Success; error code otherwise. 155 */ 156int dpmcp_destroy(struct fsl_mc_io *mc_io, 157 u32 cmd_flags, 158 u16 token) 159{ 160 struct mc_command cmd = { 0 }; 161 162 /* prepare command */ 163 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY, 164 cmd_flags, token); 165 166 /* send command to mc*/ 167 return mc_send_command(mc_io, &cmd); 168} 169 170/** 171 * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. 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 DPMCP object 175 * 176 * Return: '0' on Success; Error code otherwise. 177 */ 178int dpmcp_reset(struct fsl_mc_io *mc_io, 179 u32 cmd_flags, 180 u16 token) 181{ 182 struct mc_command cmd = { 0 }; 183 184 /* prepare command */ 185 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, 186 cmd_flags, token); 187 188 /* send command to mc*/ 189 return mc_send_command(mc_io, &cmd); 190} 191 192/** 193 * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. 194 * @mc_io: Pointer to MC portal's I/O object 195 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 196 * @token: Token of DPMCP object 197 * @irq_index: Identifies the interrupt index to configure 198 * @irq_cfg: IRQ configuration 199 * 200 * Return: '0' on Success; Error code otherwise. 201 */ 202int dpmcp_set_irq(struct fsl_mc_io *mc_io, 203 u32 cmd_flags, 204 u16 token, 205 u8 irq_index, 206 struct dpmcp_irq_cfg *irq_cfg) 207{ 208 struct mc_command cmd = { 0 }; 209 210 /* prepare command */ 211 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ, 212 cmd_flags, token); 213 cmd.params[0] |= mc_enc(0, 8, irq_index); 214 cmd.params[0] |= mc_enc(32, 32, irq_cfg->val); 215 cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); 216 cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); 217 218 /* send command to mc*/ 219 return mc_send_command(mc_io, &cmd); 220} 221 222/** 223 * dpmcp_get_irq() - Get IRQ information from the DPMCP. 224 * @mc_io: Pointer to MC portal's I/O object 225 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 226 * @token: Token of DPMCP object 227 * @irq_index: The interrupt index to configure 228 * @type: Interrupt type: 0 represents message interrupt 229 * type (both irq_addr and irq_val are valid) 230 * @irq_cfg: IRQ attributes 231 * 232 * Return: '0' on Success; Error code otherwise. 233 */ 234int dpmcp_get_irq(struct fsl_mc_io *mc_io, 235 u32 cmd_flags, 236 u16 token, 237 u8 irq_index, 238 int *type, 239 struct dpmcp_irq_cfg *irq_cfg) 240{ 241 struct mc_command cmd = { 0 }; 242 int err; 243 244 /* prepare command */ 245 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ, 246 cmd_flags, token); 247 cmd.params[0] |= mc_enc(32, 8, irq_index); 248 249 /* send command to mc*/ 250 err = mc_send_command(mc_io, &cmd); 251 if (err) 252 return err; 253 254 /* retrieve response parameters */ 255 irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); 256 irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64); 257 irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); 258 *type = (int)mc_dec(cmd.params[2], 32, 32); 259 return 0; 260} 261 262/** 263 * dpmcp_set_irq_enable() - Set overall interrupt state. 264 * @mc_io: Pointer to MC portal's I/O object 265 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 266 * @token: Token of DPMCP object 267 * @irq_index: The interrupt index to configure 268 * @en: Interrupt state - enable = 1, disable = 0 269 * 270 * Allows GPP software to control when interrupts are generated. 271 * Each interrupt can have up to 32 causes. The enable/disable control's the 272 * overall interrupt state. if the interrupt is disabled no causes will cause 273 * an interrupt. 274 * 275 * Return: '0' on Success; Error code otherwise. 276 */ 277int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, 278 u32 cmd_flags, 279 u16 token, 280 u8 irq_index, 281 u8 en) 282{ 283 struct mc_command cmd = { 0 }; 284 285 /* prepare command */ 286 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE, 287 cmd_flags, token); 288 cmd.params[0] |= mc_enc(0, 8, en); 289 cmd.params[0] |= mc_enc(32, 8, irq_index); 290 291 /* send command to mc*/ 292 return mc_send_command(mc_io, &cmd); 293} 294 295/** 296 * dpmcp_get_irq_enable() - Get overall interrupt state 297 * @mc_io: Pointer to MC portal's I/O object 298 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 299 * @token: Token of DPMCP object 300 * @irq_index: The interrupt index to configure 301 * @en: Returned interrupt state - enable = 1, disable = 0 302 * 303 * Return: '0' on Success; Error code otherwise. 304 */ 305int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, 306 u32 cmd_flags, 307 u16 token, 308 u8 irq_index, 309 u8 *en) 310{ 311 struct mc_command cmd = { 0 }; 312 int err; 313 314 /* prepare command */ 315 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE, 316 cmd_flags, token); 317 cmd.params[0] |= mc_enc(32, 8, irq_index); 318 319 /* send command to mc*/ 320 err = mc_send_command(mc_io, &cmd); 321 if (err) 322 return err; 323 324 /* retrieve response parameters */ 325 *en = (u8)mc_dec(cmd.params[0], 0, 8); 326 return 0; 327} 328 329/** 330 * dpmcp_set_irq_mask() - Set interrupt mask. 331 * @mc_io: Pointer to MC portal's I/O object 332 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 333 * @token: Token of DPMCP object 334 * @irq_index: The interrupt index to configure 335 * @mask: Event mask to trigger interrupt; 336 * each bit: 337 * 0 = ignore event 338 * 1 = consider event for asserting IRQ 339 * 340 * Every interrupt can have up to 32 causes and the interrupt model supports 341 * masking/unmasking each cause independently 342 * 343 * Return: '0' on Success; Error code otherwise. 344 */ 345int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, 346 u32 cmd_flags, 347 u16 token, 348 u8 irq_index, 349 u32 mask) 350{ 351 struct mc_command cmd = { 0 }; 352 353 /* prepare command */ 354 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, 355 cmd_flags, token); 356 cmd.params[0] |= mc_enc(0, 32, mask); 357 cmd.params[0] |= mc_enc(32, 8, irq_index); 358 359 /* send command to mc*/ 360 return mc_send_command(mc_io, &cmd); 361} 362 363/** 364 * dpmcp_get_irq_mask() - Get interrupt mask. 365 * @mc_io: Pointer to MC portal's I/O object 366 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 367 * @token: Token of DPMCP object 368 * @irq_index: The interrupt index to configure 369 * @mask: Returned event mask to trigger interrupt 370 * 371 * Every interrupt can have up to 32 causes and the interrupt model supports 372 * masking/unmasking each cause independently 373 * 374 * Return: '0' on Success; Error code otherwise. 375 */ 376int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, 377 u32 cmd_flags, 378 u16 token, 379 u8 irq_index, 380 u32 *mask) 381{ 382 struct mc_command cmd = { 0 }; 383 int err; 384 385 /* prepare command */ 386 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK, 387 cmd_flags, token); 388 cmd.params[0] |= mc_enc(32, 8, irq_index); 389 390 /* send command to mc*/ 391 err = mc_send_command(mc_io, &cmd); 392 if (err) 393 return err; 394 395 /* retrieve response parameters */ 396 *mask = (u32)mc_dec(cmd.params[0], 0, 32); 397 return 0; 398} 399 400/** 401 * dpmcp_get_irq_status() - Get the current status of any pending interrupts. 402 * 403 * @mc_io: Pointer to MC portal's I/O object 404 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 405 * @token: Token of DPMCP object 406 * @irq_index: The interrupt index to configure 407 * @status: Returned interrupts status - one bit per cause: 408 * 0 = no interrupt pending 409 * 1 = interrupt pending 410 * 411 * Return: '0' on Success; Error code otherwise. 412 */ 413int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, 414 u32 cmd_flags, 415 u16 token, 416 u8 irq_index, 417 u32 *status) 418{ 419 struct mc_command cmd = { 0 }; 420 int err; 421 422 /* prepare command */ 423 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS, 424 cmd_flags, token); 425 cmd.params[0] |= mc_enc(32, 8, irq_index); 426 427 /* send command to mc*/ 428 err = mc_send_command(mc_io, &cmd); 429 if (err) 430 return err; 431 432 /* retrieve response parameters */ 433 *status = (u32)mc_dec(cmd.params[0], 0, 32); 434 return 0; 435} 436 437/** 438 * dpmcp_clear_irq_status() - Clear a pending interrupt's status 439 * 440 * @mc_io: Pointer to MC portal's I/O object 441 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 442 * @token: Token of DPMCP object 443 * @irq_index: The interrupt index to configure 444 * @status: Bits to clear (W1C) - one bit per cause: 445 * 0 = don't change 446 * 1 = clear status bit 447 * 448 * Return: '0' on Success; Error code otherwise. 449 */ 450int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io, 451 u32 cmd_flags, 452 u16 token, 453 u8 irq_index, 454 u32 status) 455{ 456 struct mc_command cmd = { 0 }; 457 458 /* prepare command */ 459 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLEAR_IRQ_STATUS, 460 cmd_flags, token); 461 cmd.params[0] |= mc_enc(0, 32, status); 462 cmd.params[0] |= mc_enc(32, 8, irq_index); 463 464 /* send command to mc*/ 465 return mc_send_command(mc_io, &cmd); 466} 467 468/** 469 * dpmcp_get_attributes - Retrieve DPMCP attributes. 470 * 471 * @mc_io: Pointer to MC portal's I/O object 472 * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' 473 * @token: Token of DPMCP object 474 * @attr: Returned object's attributes 475 * 476 * Return: '0' on Success; Error code otherwise. 477 */ 478int dpmcp_get_attributes(struct fsl_mc_io *mc_io, 479 u32 cmd_flags, 480 u16 token, 481 struct dpmcp_attr *attr) 482{ 483 struct mc_command cmd = { 0 }; 484 int err; 485 486 /* prepare command */ 487 cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR, 488 cmd_flags, token); 489 490 /* send command to mc*/ 491 err = mc_send_command(mc_io, &cmd); 492 if (err) 493 return err; 494 495 /* retrieve response parameters */ 496 attr->id = (int)mc_dec(cmd.params[0], 32, 32); 497 attr->version.major = (u16)mc_dec(cmd.params[1], 0, 16); 498 attr->version.minor = (u16)mc_dec(cmd.params[1], 16, 16); 499 return 0; 500} 501