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 */
dpbp_open(struct fsl_mc_io * mc_io,u32 cmd_flags,int dpbp_id,u16 * token)54 int 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 }
77 EXPORT_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 */
dpbp_close(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)90 int 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 }
103 EXPORT_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 */
dpbp_create(struct fsl_mc_io * mc_io,u32 cmd_flags,const struct dpbp_cfg * cfg,u16 * token)126 int 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 */
dpbp_destroy(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)159 int 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 */
dpbp_enable(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)181 int 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 }
194 EXPORT_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 */
dpbp_disable(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)204 int 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 }
217 EXPORT_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 */
dpbp_is_enabled(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,int * en)228 int 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 */
dpbp_reset(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)258 int 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 */
dpbp_set_irq(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,struct dpbp_irq_cfg * irq_cfg)282 int 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 */
dpbp_get_irq(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,int * type,struct dpbp_irq_cfg * irq_cfg)314 int 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 */
dpbp_set_irq_enable(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u8 en)357 int 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 */
dpbp_get_irq_enable(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u8 * en)385 int 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 */
dpbp_set_irq_mask(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 mask)425 int 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 */
dpbp_get_irq_mask(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 * mask)456 int 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 */
dpbp_get_irq_status(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 * status)493 int 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 */
dpbp_clear_irq_status(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 status)530 int 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 */
dpbp_get_attributes(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,struct dpbp_attr * attr)558 int 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 }
582 EXPORT_SYMBOL(dpbp_get_attributes);
583