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