These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / fsl-mc / bus / dpmcp.c
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 }