1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Public header for the MPC52xx processor BestComm driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
6*4882a593Smuzhiyun * Copyright (C) 2005 Varma Electronics Oy,
7*4882a593Smuzhiyun * ( by Andrey Volkov <avolkov@varma-el.com> )
8*4882a593Smuzhiyun * Copyright (C) 2003-2004 MontaVista, Software, Inc.
9*4882a593Smuzhiyun * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public License
12*4882a593Smuzhiyun * version 2. This program is licensed "as is" without any warranty of any
13*4882a593Smuzhiyun * kind, whether express or implied.
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #ifndef __BESTCOMM_H__
17*4882a593Smuzhiyun #define __BESTCOMM_H__
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /**
20*4882a593Smuzhiyun * struct bcom_bd - Structure describing a generic BestComm buffer descriptor
21*4882a593Smuzhiyun * @status: The current status of this buffer. Exact meaning depends on the
22*4882a593Smuzhiyun * task type
23*4882a593Smuzhiyun * @data: An array of u32 extra data. Size of array is task dependent.
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * Note: Don't dereference a bcom_bd pointer as an array. The size of the
26*4882a593Smuzhiyun * bcom_bd is variable. Use bcom_get_bd() instead.
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun struct bcom_bd {
29*4882a593Smuzhiyun u32 status;
30*4882a593Smuzhiyun u32 data[]; /* variable payload size */
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* ======================================================================== */
34*4882a593Smuzhiyun /* Generic task management */
35*4882a593Smuzhiyun /* ======================================================================== */
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /**
38*4882a593Smuzhiyun * struct bcom_task - Structure describing a loaded BestComm task
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * This structure is never built by the driver it self. It's built and
41*4882a593Smuzhiyun * filled the intermediate layer of the BestComm API, the task dependent
42*4882a593Smuzhiyun * support code.
43*4882a593Smuzhiyun *
44*4882a593Smuzhiyun * Most likely you don't need to poke around inside this structure. The
45*4882a593Smuzhiyun * fields are exposed in the header just for the sake of inline functions
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun struct bcom_task {
48*4882a593Smuzhiyun unsigned int tasknum;
49*4882a593Smuzhiyun unsigned int flags;
50*4882a593Smuzhiyun int irq;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun struct bcom_bd *bd;
53*4882a593Smuzhiyun phys_addr_t bd_pa;
54*4882a593Smuzhiyun void **cookie;
55*4882a593Smuzhiyun unsigned short index;
56*4882a593Smuzhiyun unsigned short outdex;
57*4882a593Smuzhiyun unsigned int num_bd;
58*4882a593Smuzhiyun unsigned int bd_size;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun void* priv;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun #define BCOM_FLAGS_NONE 0x00000000ul
64*4882a593Smuzhiyun #define BCOM_FLAGS_ENABLE_TASK (1ul << 0)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /**
67*4882a593Smuzhiyun * bcom_enable - Enable a BestComm task
68*4882a593Smuzhiyun * @tsk: The BestComm task structure
69*4882a593Smuzhiyun *
70*4882a593Smuzhiyun * This function makes sure the given task is enabled and can be run
71*4882a593Smuzhiyun * by the BestComm engine as needed
72*4882a593Smuzhiyun */
73*4882a593Smuzhiyun extern void bcom_enable(struct bcom_task *tsk);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /**
76*4882a593Smuzhiyun * bcom_disable - Disable a BestComm task
77*4882a593Smuzhiyun * @tsk: The BestComm task structure
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun * This function disable a given task, making sure it's not executed
80*4882a593Smuzhiyun * by the BestComm engine.
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun extern void bcom_disable(struct bcom_task *tsk);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /**
86*4882a593Smuzhiyun * bcom_get_task_irq - Returns the irq number of a BestComm task
87*4882a593Smuzhiyun * @tsk: The BestComm task structure
88*4882a593Smuzhiyun */
89*4882a593Smuzhiyun static inline int
bcom_get_task_irq(struct bcom_task * tsk)90*4882a593Smuzhiyun bcom_get_task_irq(struct bcom_task *tsk) {
91*4882a593Smuzhiyun return tsk->irq;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /* ======================================================================== */
95*4882a593Smuzhiyun /* BD based tasks helpers */
96*4882a593Smuzhiyun /* ======================================================================== */
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun #define BCOM_BD_READY 0x40000000ul
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /** _bcom_next_index - Get next input index.
101*4882a593Smuzhiyun * @tsk: pointer to task structure
102*4882a593Smuzhiyun *
103*4882a593Smuzhiyun * Support function; Device drivers should not call this
104*4882a593Smuzhiyun */
105*4882a593Smuzhiyun static inline int
_bcom_next_index(struct bcom_task * tsk)106*4882a593Smuzhiyun _bcom_next_index(struct bcom_task *tsk)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /** _bcom_next_outdex - Get next output index.
112*4882a593Smuzhiyun * @tsk: pointer to task structure
113*4882a593Smuzhiyun *
114*4882a593Smuzhiyun * Support function; Device drivers should not call this
115*4882a593Smuzhiyun */
116*4882a593Smuzhiyun static inline int
_bcom_next_outdex(struct bcom_task * tsk)117*4882a593Smuzhiyun _bcom_next_outdex(struct bcom_task *tsk)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /**
123*4882a593Smuzhiyun * bcom_queue_empty - Checks if a BestComm task BD queue is empty
124*4882a593Smuzhiyun * @tsk: The BestComm task structure
125*4882a593Smuzhiyun */
126*4882a593Smuzhiyun static inline int
bcom_queue_empty(struct bcom_task * tsk)127*4882a593Smuzhiyun bcom_queue_empty(struct bcom_task *tsk)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun return tsk->index == tsk->outdex;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /**
133*4882a593Smuzhiyun * bcom_queue_full - Checks if a BestComm task BD queue is full
134*4882a593Smuzhiyun * @tsk: The BestComm task structure
135*4882a593Smuzhiyun */
136*4882a593Smuzhiyun static inline int
bcom_queue_full(struct bcom_task * tsk)137*4882a593Smuzhiyun bcom_queue_full(struct bcom_task *tsk)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun return tsk->outdex == _bcom_next_index(tsk);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /**
143*4882a593Smuzhiyun * bcom_get_bd - Get a BD from the queue
144*4882a593Smuzhiyun * @tsk: The BestComm task structure
145*4882a593Smuzhiyun * index: Index of the BD to fetch
146*4882a593Smuzhiyun */
147*4882a593Smuzhiyun static inline struct bcom_bd
bcom_get_bd(struct bcom_task * tsk,unsigned int index)148*4882a593Smuzhiyun *bcom_get_bd(struct bcom_task *tsk, unsigned int index)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun /* A cast to (void*) so the address can be incremented by the
151*4882a593Smuzhiyun * real size instead of by sizeof(struct bcom_bd) */
152*4882a593Smuzhiyun return ((void *)tsk->bd) + (index * tsk->bd_size);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /**
156*4882a593Smuzhiyun * bcom_buffer_done - Checks if a BestComm
157*4882a593Smuzhiyun * @tsk: The BestComm task structure
158*4882a593Smuzhiyun */
159*4882a593Smuzhiyun static inline int
bcom_buffer_done(struct bcom_task * tsk)160*4882a593Smuzhiyun bcom_buffer_done(struct bcom_task *tsk)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun struct bcom_bd *bd;
163*4882a593Smuzhiyun if (bcom_queue_empty(tsk))
164*4882a593Smuzhiyun return 0;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun bd = bcom_get_bd(tsk, tsk->outdex);
167*4882a593Smuzhiyun return !(bd->status & BCOM_BD_READY);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /**
171*4882a593Smuzhiyun * bcom_prepare_next_buffer - clear status of next available buffer.
172*4882a593Smuzhiyun * @tsk: The BestComm task structure
173*4882a593Smuzhiyun *
174*4882a593Smuzhiyun * Returns pointer to next buffer descriptor
175*4882a593Smuzhiyun */
176*4882a593Smuzhiyun static inline struct bcom_bd *
bcom_prepare_next_buffer(struct bcom_task * tsk)177*4882a593Smuzhiyun bcom_prepare_next_buffer(struct bcom_task *tsk)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun struct bcom_bd *bd;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun bd = bcom_get_bd(tsk, tsk->index);
182*4882a593Smuzhiyun bd->status = 0; /* cleanup last status */
183*4882a593Smuzhiyun return bd;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun static inline void
bcom_submit_next_buffer(struct bcom_task * tsk,void * cookie)187*4882a593Smuzhiyun bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct bcom_bd *bd = bcom_get_bd(tsk, tsk->index);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun tsk->cookie[tsk->index] = cookie;
192*4882a593Smuzhiyun mb(); /* ensure the bd is really up-to-date */
193*4882a593Smuzhiyun bd->status |= BCOM_BD_READY;
194*4882a593Smuzhiyun tsk->index = _bcom_next_index(tsk);
195*4882a593Smuzhiyun if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
196*4882a593Smuzhiyun bcom_enable(tsk);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun static inline void *
bcom_retrieve_buffer(struct bcom_task * tsk,u32 * p_status,struct bcom_bd ** p_bd)200*4882a593Smuzhiyun bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun void *cookie = tsk->cookie[tsk->outdex];
203*4882a593Smuzhiyun struct bcom_bd *bd = bcom_get_bd(tsk, tsk->outdex);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (p_status)
206*4882a593Smuzhiyun *p_status = bd->status;
207*4882a593Smuzhiyun if (p_bd)
208*4882a593Smuzhiyun *p_bd = bd;
209*4882a593Smuzhiyun tsk->outdex = _bcom_next_outdex(tsk);
210*4882a593Smuzhiyun return cookie;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun #endif /* __BESTCOMM_H__ */
214