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  */
dpmcp_open(struct fsl_mc_io * mc_io,u32 cmd_flags,int dpmcp_id,u16 * token)54 int 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  */
dpmcp_close(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)89 int 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  */
dpmcp_create(struct fsl_mc_io * mc_io,u32 cmd_flags,const struct dpmcp_cfg * cfg,u16 * token)124 int 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  */
dpmcp_destroy(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)156 int 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  */
dpmcp_reset(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token)178 int 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  */
dpmcp_set_irq(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,struct dpmcp_irq_cfg * irq_cfg)202 int 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  */
dpmcp_get_irq(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,int * type,struct dpmcp_irq_cfg * irq_cfg)234 int 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  */
dpmcp_set_irq_enable(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u8 en)277 int 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  */
dpmcp_get_irq_enable(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u8 * en)305 int 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  */
dpmcp_set_irq_mask(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 mask)345 int 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  */
dpmcp_get_irq_mask(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 * mask)376 int 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  */
dpmcp_get_irq_status(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 * status)413 int 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  */
dpmcp_clear_irq_status(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,u8 irq_index,u32 status)450 int 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  */
dpmcp_get_attributes(struct fsl_mc_io * mc_io,u32 cmd_flags,u16 token,struct dpmcp_attr * attr)478 int 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