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