• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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