Linux-libre 4.9.88-gnu
[librecmc/linux-libre.git] / drivers / staging / fsl-mc / bus / dpmcp.c
1 /* Copyright 2013-2016 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
35 #include "dpmcp.h"
36 #include "dpmcp-cmd.h"
37
38 /**
39  * dpmcp_open() - Open a control session for the specified object.
40  * @mc_io:      Pointer to MC portal's I/O object
41  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
42  * @dpmcp_id:   DPMCP unique ID
43  * @token:      Returned token; use in subsequent API calls
44  *
45  * This function can be used to open a control session for an
46  * already created object; an object may have been declared in
47  * the DPL or by calling the dpmcp_create function.
48  * This function returns a unique authentication token,
49  * associated with the specific object ID and the specific MC
50  * portal; this token must be used in all subsequent commands for
51  * this specific object
52  *
53  * Return:      '0' on Success; Error code otherwise.
54  */
55 int dpmcp_open(struct fsl_mc_io *mc_io,
56                u32 cmd_flags,
57                int dpmcp_id,
58                u16 *token)
59 {
60         struct mc_command cmd = { 0 };
61         struct dpmcp_cmd_open *cmd_params;
62         int err;
63
64         /* prepare command */
65         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
66                                           cmd_flags, 0);
67         cmd_params = (struct dpmcp_cmd_open *)cmd.params;
68         cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id);
69
70         /* send command to mc*/
71         err = mc_send_command(mc_io, &cmd);
72         if (err)
73                 return err;
74
75         /* retrieve response parameters */
76         *token = mc_cmd_hdr_read_token(&cmd);
77
78         return err;
79 }
80
81 /**
82  * dpmcp_close() - Close the control session of the object
83  * @mc_io:      Pointer to MC portal's I/O object
84  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
85  * @token:      Token of DPMCP object
86  *
87  * After this function is called, no further operations are
88  * allowed on the object without opening a new control session.
89  *
90  * Return:      '0' on Success; Error code otherwise.
91  */
92 int dpmcp_close(struct fsl_mc_io *mc_io,
93                 u32 cmd_flags,
94                 u16 token)
95 {
96         struct mc_command cmd = { 0 };
97
98         /* prepare command */
99         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE,
100                                           cmd_flags, token);
101
102         /* send command to mc*/
103         return mc_send_command(mc_io, &cmd);
104 }
105
106 /**
107  * dpmcp_create() - Create the DPMCP object.
108  * @mc_io:      Pointer to MC portal's I/O object
109  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
110  * @cfg:        Configuration structure
111  * @token:      Returned token; use in subsequent API calls
112  *
113  * Create the DPMCP object, allocate required resources and
114  * perform required initialization.
115  *
116  * The object can be created either by declaring it in the
117  * DPL file, or by calling this function.
118  * This function returns a unique authentication token,
119  * associated with the specific object ID and the specific MC
120  * portal; this token must be used in all subsequent calls to
121  * this specific object. For objects that are created using the
122  * DPL file, call dpmcp_open function to get an authentication
123  * token first.
124  *
125  * Return:      '0' on Success; Error code otherwise.
126  */
127 int dpmcp_create(struct fsl_mc_io *mc_io,
128                  u32 cmd_flags,
129                  const struct dpmcp_cfg *cfg,
130                  u16 *token)
131 {
132         struct mc_command cmd = { 0 };
133         struct dpmcp_cmd_create *cmd_params;
134
135         int err;
136
137         /* prepare command */
138         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE,
139                                           cmd_flags, 0);
140         cmd_params = (struct dpmcp_cmd_create *)cmd.params;
141         cmd_params->portal_id = cpu_to_le32(cfg->portal_id);
142
143         /* send command to mc*/
144         err = mc_send_command(mc_io, &cmd);
145         if (err)
146                 return err;
147
148         /* retrieve response parameters */
149         *token = mc_cmd_hdr_read_token(&cmd);
150
151         return 0;
152 }
153
154 /**
155  * dpmcp_destroy() - Destroy the DPMCP object and release all its resources.
156  * @mc_io:      Pointer to MC portal's I/O object
157  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
158  * @token:      Token of DPMCP object
159  *
160  * Return:      '0' on Success; error code otherwise.
161  */
162 int dpmcp_destroy(struct fsl_mc_io *mc_io,
163                   u32 cmd_flags,
164                   u16 token)
165 {
166         struct mc_command cmd = { 0 };
167
168         /* prepare command */
169         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY,
170                                           cmd_flags, token);
171
172         /* send command to mc*/
173         return mc_send_command(mc_io, &cmd);
174 }
175
176 /**
177  * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
178  * @mc_io:      Pointer to MC portal's I/O object
179  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
180  * @token:      Token of DPMCP object
181  *
182  * Return:      '0' on Success; Error code otherwise.
183  */
184 int dpmcp_reset(struct fsl_mc_io *mc_io,
185                 u32 cmd_flags,
186                 u16 token)
187 {
188         struct mc_command cmd = { 0 };
189
190         /* prepare command */
191         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
192                                           cmd_flags, token);
193
194         /* send command to mc*/
195         return mc_send_command(mc_io, &cmd);
196 }
197
198 /**
199  * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt.
200  * @mc_io:      Pointer to MC portal's I/O object
201  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
202  * @token:      Token of DPMCP object
203  * @irq_index:  Identifies the interrupt index to configure
204  * @irq_cfg:    IRQ configuration
205  *
206  * Return:      '0' on Success; Error code otherwise.
207  */
208 int dpmcp_set_irq(struct fsl_mc_io *mc_io,
209                   u32 cmd_flags,
210                   u16 token,
211                   u8 irq_index,
212                   struct dpmcp_irq_cfg  *irq_cfg)
213 {
214         struct mc_command cmd = { 0 };
215         struct dpmcp_cmd_set_irq *cmd_params;
216
217         /* prepare command */
218         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ,
219                                           cmd_flags, token);
220         cmd_params = (struct dpmcp_cmd_set_irq *)cmd.params;
221         cmd_params->irq_index = irq_index;
222         cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
223         cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
224         cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
225
226         /* send command to mc*/
227         return mc_send_command(mc_io, &cmd);
228 }
229
230 /**
231  * dpmcp_get_irq() - Get IRQ information from the DPMCP.
232  * @mc_io:      Pointer to MC portal's I/O object
233  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
234  * @token:      Token of DPMCP object
235  * @irq_index:  The interrupt index to configure
236  * @type:       Interrupt type: 0 represents message interrupt
237  *              type (both irq_addr and irq_val are valid)
238  * @irq_cfg:    IRQ attributes
239  *
240  * Return:      '0' on Success; Error code otherwise.
241  */
242 int dpmcp_get_irq(struct fsl_mc_io *mc_io,
243                   u32 cmd_flags,
244                   u16 token,
245                   u8 irq_index,
246                   int *type,
247                   struct dpmcp_irq_cfg  *irq_cfg)
248 {
249         struct mc_command cmd = { 0 };
250         struct dpmcp_cmd_get_irq *cmd_params;
251         struct dpmcp_rsp_get_irq *rsp_params;
252         int err;
253
254         /* prepare command */
255         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ,
256                                           cmd_flags, token);
257         cmd_params = (struct dpmcp_cmd_get_irq *)cmd.params;
258         cmd_params->irq_index = irq_index;
259
260         /* send command to mc*/
261         err = mc_send_command(mc_io, &cmd);
262         if (err)
263                 return err;
264
265         /* retrieve response parameters */
266         rsp_params = (struct dpmcp_rsp_get_irq *)cmd.params;
267         irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
268         irq_cfg->paddr = le64_to_cpu(rsp_params->irq_paddr);
269         irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
270         *type = le32_to_cpu(rsp_params->type);
271         return 0;
272 }
273
274 /**
275  * dpmcp_set_irq_enable() - Set overall interrupt state.
276  * @mc_io:      Pointer to MC portal's I/O object
277  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
278  * @token:      Token of DPMCP object
279  * @irq_index:  The interrupt index to configure
280  * @en: Interrupt state - enable = 1, disable = 0
281  *
282  * Allows GPP software to control when interrupts are generated.
283  * Each interrupt can have up to 32 causes.  The enable/disable control's the
284  * overall interrupt state. if the interrupt is disabled no causes will cause
285  * an interrupt.
286  *
287  * Return:      '0' on Success; Error code otherwise.
288  */
289 int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io,
290                          u32 cmd_flags,
291                          u16 token,
292                          u8 irq_index,
293                          u8 en)
294 {
295         struct mc_command cmd = { 0 };
296         struct dpmcp_cmd_set_irq_enable *cmd_params;
297
298         /* prepare command */
299         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE,
300                                           cmd_flags, token);
301         cmd_params = (struct dpmcp_cmd_set_irq_enable *)cmd.params;
302         cmd_params->enable = en & DPMCP_ENABLE;
303         cmd_params->irq_index = irq_index;
304
305         /* send command to mc*/
306         return mc_send_command(mc_io, &cmd);
307 }
308
309 /**
310  * dpmcp_get_irq_enable() - Get overall interrupt state
311  * @mc_io:      Pointer to MC portal's I/O object
312  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
313  * @token:      Token of DPMCP object
314  * @irq_index:  The interrupt index to configure
315  * @en:         Returned interrupt state - enable = 1, disable = 0
316  *
317  * Return:      '0' on Success; Error code otherwise.
318  */
319 int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io,
320                          u32 cmd_flags,
321                          u16 token,
322                          u8 irq_index,
323                          u8 *en)
324 {
325         struct mc_command cmd = { 0 };
326         struct dpmcp_cmd_get_irq_enable *cmd_params;
327         struct dpmcp_rsp_get_irq_enable *rsp_params;
328         int err;
329
330         /* prepare command */
331         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE,
332                                           cmd_flags, token);
333         cmd_params = (struct dpmcp_cmd_get_irq_enable *)cmd.params;
334         cmd_params->irq_index = irq_index;
335
336         /* send command to mc*/
337         err = mc_send_command(mc_io, &cmd);
338         if (err)
339                 return err;
340
341         /* retrieve response parameters */
342         rsp_params = (struct dpmcp_rsp_get_irq_enable *)cmd.params;
343         *en = rsp_params->enabled & DPMCP_ENABLE;
344         return 0;
345 }
346
347 /**
348  * dpmcp_set_irq_mask() - Set interrupt mask.
349  * @mc_io:      Pointer to MC portal's I/O object
350  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
351  * @token:      Token of DPMCP object
352  * @irq_index:  The interrupt index to configure
353  * @mask:       Event mask to trigger interrupt;
354  *                      each bit:
355  *                              0 = ignore event
356  *                              1 = consider event for asserting IRQ
357  *
358  * Every interrupt can have up to 32 causes and the interrupt model supports
359  * masking/unmasking each cause independently
360  *
361  * Return:      '0' on Success; Error code otherwise.
362  */
363 int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io,
364                        u32 cmd_flags,
365                        u16 token,
366                        u8 irq_index,
367                        u32 mask)
368 {
369         struct mc_command cmd = { 0 };
370         struct dpmcp_cmd_set_irq_mask *cmd_params;
371
372         /* prepare command */
373         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK,
374                                           cmd_flags, token);
375         cmd_params = (struct dpmcp_cmd_set_irq_mask *)cmd.params;
376         cmd_params->mask = cpu_to_le32(mask);
377         cmd_params->irq_index = irq_index;
378
379         /* send command to mc*/
380         return mc_send_command(mc_io, &cmd);
381 }
382
383 /**
384  * dpmcp_get_irq_mask() - Get interrupt mask.
385  * @mc_io:      Pointer to MC portal's I/O object
386  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
387  * @token:      Token of DPMCP object
388  * @irq_index:  The interrupt index to configure
389  * @mask:       Returned event mask to trigger interrupt
390  *
391  * Every interrupt can have up to 32 causes and the interrupt model supports
392  * masking/unmasking each cause independently
393  *
394  * Return:      '0' on Success; Error code otherwise.
395  */
396 int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io,
397                        u32 cmd_flags,
398                        u16 token,
399                        u8 irq_index,
400                        u32 *mask)
401 {
402         struct mc_command cmd = { 0 };
403         struct dpmcp_cmd_get_irq_mask *cmd_params;
404         struct dpmcp_rsp_get_irq_mask *rsp_params;
405
406         int err;
407
408         /* prepare command */
409         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK,
410                                           cmd_flags, token);
411         cmd_params = (struct dpmcp_cmd_get_irq_mask *)cmd.params;
412         cmd_params->irq_index = irq_index;
413
414         /* send command to mc*/
415         err = mc_send_command(mc_io, &cmd);
416         if (err)
417                 return err;
418
419         /* retrieve response parameters */
420         rsp_params = (struct dpmcp_rsp_get_irq_mask *)cmd.params;
421         *mask = le32_to_cpu(rsp_params->mask);
422
423         return 0;
424 }
425
426 /**
427  * dpmcp_get_irq_status() - Get the current status of any pending interrupts.
428  *
429  * @mc_io:      Pointer to MC portal's I/O object
430  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
431  * @token:      Token of DPMCP object
432  * @irq_index:  The interrupt index to configure
433  * @status:     Returned interrupts status - one bit per cause:
434  *                      0 = no interrupt pending
435  *                      1 = interrupt pending
436  *
437  * Return:      '0' on Success; Error code otherwise.
438  */
439 int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
440                          u32 cmd_flags,
441                          u16 token,
442                          u8 irq_index,
443                          u32 *status)
444 {
445         struct mc_command cmd = { 0 };
446         struct dpmcp_cmd_get_irq_status *cmd_params;
447         struct dpmcp_rsp_get_irq_status *rsp_params;
448         int err;
449
450         /* prepare command */
451         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS,
452                                           cmd_flags, token);
453         cmd_params = (struct dpmcp_cmd_get_irq_status *)cmd.params;
454         cmd_params->status = cpu_to_le32(*status);
455         cmd_params->irq_index = irq_index;
456
457         /* send command to mc*/
458         err = mc_send_command(mc_io, &cmd);
459         if (err)
460                 return err;
461
462         /* retrieve response parameters */
463         rsp_params = (struct dpmcp_rsp_get_irq_status *)cmd.params;
464         *status = le32_to_cpu(rsp_params->status);
465
466         return 0;
467 }
468
469 /**
470  * dpmcp_get_attributes - Retrieve DPMCP attributes.
471  *
472  * @mc_io:      Pointer to MC portal's I/O object
473  * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
474  * @token:      Token of DPMCP object
475  * @attr:       Returned object's attributes
476  *
477  * Return:      '0' on Success; Error code otherwise.
478  */
479 int dpmcp_get_attributes(struct fsl_mc_io *mc_io,
480                          u32 cmd_flags,
481                          u16 token,
482                          struct dpmcp_attr *attr)
483 {
484         struct mc_command cmd = { 0 };
485         struct dpmcp_rsp_get_attributes *rsp_params;
486         int err;
487
488         /* prepare command */
489         cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR,
490                                           cmd_flags, token);
491
492         /* send command to mc*/
493         err = mc_send_command(mc_io, &cmd);
494         if (err)
495                 return err;
496
497         /* retrieve response parameters */
498         rsp_params = (struct dpmcp_rsp_get_attributes *)cmd.params;
499         attr->id = le32_to_cpu(rsp_params->id);
500         attr->version.major = le16_to_cpu(rsp_params->version_major);
501         attr->version.minor = le16_to_cpu(rsp_params->version_minor);
502
503         return 0;
504 }