Commit 0987862149575e557d50b2fc0cce21e2c04a257b

Authored by Hebbar, Gururaja
1 parent fb646cdbca
Exists in master

arm:omap:cpsw: fix module build support for Ethernet

export api used by cpsw driver so that the cpsw driver can be built as
module.

Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>

Showing 2 changed files with 27 additions and 0 deletions Inline Diff

drivers/net/cpsw_ale.c
1 /* 1 /*
2 * Texas Instruments 3-Port Ethernet Switch Address Lookup Engine 2 * Texas Instruments 3-Port Ethernet Switch Address Lookup Engine
3 * 3 *
4 * Copyright (C) 2010 Texas Instruments 4 * Copyright (C) 2010 Texas Instruments
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as 7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2. 8 * published by the Free Software Foundation version 2.
9 * 9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty 11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 */ 14 */
15 #include <linux/kernel.h> 15 #include <linux/kernel.h>
16 #include <linux/platform_device.h> 16 #include <linux/platform_device.h>
17 #include <linux/seq_file.h> 17 #include <linux/seq_file.h>
18 #include <linux/slab.h> 18 #include <linux/slab.h>
19 #include <linux/err.h> 19 #include <linux/err.h>
20 #include <linux/io.h> 20 #include <linux/io.h>
21 #include <linux/sysfs.h> 21 #include <linux/sysfs.h>
22 22
23 #include "cpsw_ale.h" 23 #include "cpsw_ale.h"
24 24
25 #define BITMASK(bits) (BIT(bits) - 1) 25 #define BITMASK(bits) (BIT(bits) - 1)
26 #define ADDR_FMT_STR "%02x:%02x:%02x:%02x:%02x:%02x" 26 #define ADDR_FMT_STR "%02x:%02x:%02x:%02x:%02x:%02x"
27 #define ADDR_FMT_ARGS(addr) (addr)[0], (addr)[1], (addr)[2], \ 27 #define ADDR_FMT_ARGS(addr) (addr)[0], (addr)[1], (addr)[2], \
28 (addr)[3], (addr)[4], (addr)[5] 28 (addr)[3], (addr)[4], (addr)[5]
29 #define ALE_ENTRY_BITS 68 29 #define ALE_ENTRY_BITS 68
30 #define ALE_ENTRY_WORDS DIV_ROUND_UP(ALE_ENTRY_BITS, 32) 30 #define ALE_ENTRY_WORDS DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
31 31
32 /* ALE Registers */ 32 /* ALE Registers */
33 #define ALE_IDVER 0x00 33 #define ALE_IDVER 0x00
34 #define ALE_CONTROL 0x08 34 #define ALE_CONTROL 0x08
35 #define ALE_PRESCALE 0x10 35 #define ALE_PRESCALE 0x10
36 #define ALE_UNKNOWNVLAN 0x18 36 #define ALE_UNKNOWNVLAN 0x18
37 #define ALE_TABLE_CONTROL 0x20 37 #define ALE_TABLE_CONTROL 0x20
38 #define ALE_TABLE 0x34 38 #define ALE_TABLE 0x34
39 #define ALE_PORTCTL 0x40 39 #define ALE_PORTCTL 0x40
40 40
41 #define ALE_TABLE_WRITE BIT(31) 41 #define ALE_TABLE_WRITE BIT(31)
42 42
43 #define ALE_TYPE_FREE 0 43 #define ALE_TYPE_FREE 0
44 #define ALE_TYPE_ADDR 1 44 #define ALE_TYPE_ADDR 1
45 #define ALE_TYPE_VLAN 2 45 #define ALE_TYPE_VLAN 2
46 #define ALE_TYPE_VLAN_ADDR 3 46 #define ALE_TYPE_VLAN_ADDR 3
47 47
48 #define ALE_UCAST_PERSISTANT 0 48 #define ALE_UCAST_PERSISTANT 0
49 #define ALE_UCAST_UNTOUCHED 1 49 #define ALE_UCAST_UNTOUCHED 1
50 #define ALE_UCAST_OUI 2 50 #define ALE_UCAST_OUI 2
51 #define ALE_UCAST_TOUCHED 3 51 #define ALE_UCAST_TOUCHED 3
52 52
53 #define ALE_MCAST_FWD 0 53 #define ALE_MCAST_FWD 0
54 #define ALE_MCAST_BLOCK_LEARN_FWD 1 54 #define ALE_MCAST_BLOCK_LEARN_FWD 1
55 #define ALE_MCAST_FWD_LEARN 2 55 #define ALE_MCAST_FWD_LEARN 2
56 #define ALE_MCAST_FWD_2 3 56 #define ALE_MCAST_FWD_2 3
57 57
58 /* the following remap params into members of cpsw_ale */ 58 /* the following remap params into members of cpsw_ale */
59 #define ale_regs params.ale_regs 59 #define ale_regs params.ale_regs
60 #define ale_entries params.ale_entries 60 #define ale_entries params.ale_entries
61 #define ale_ports params.ale_ports 61 #define ale_ports params.ale_ports
62 62
63 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) 63 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
64 { 64 {
65 int idx; 65 int idx;
66 66
67 idx = start / 32; 67 idx = start / 32;
68 start -= idx * 32; 68 start -= idx * 32;
69 idx = 2 - idx; /* flip */ 69 idx = 2 - idx; /* flip */
70 return (ale_entry[idx] >> start) & BITMASK(bits); 70 return (ale_entry[idx] >> start) & BITMASK(bits);
71 } 71 }
72 72
73 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, 73 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
74 u32 value) 74 u32 value)
75 { 75 {
76 int idx; 76 int idx;
77 77
78 value &= BITMASK(bits); 78 value &= BITMASK(bits);
79 idx = start / 32; 79 idx = start / 32;
80 start -= idx * 32; 80 start -= idx * 32;
81 idx = 2 - idx; /* flip */ 81 idx = 2 - idx; /* flip */
82 ale_entry[idx] &= ~(BITMASK(bits) << start); 82 ale_entry[idx] &= ~(BITMASK(bits) << start);
83 ale_entry[idx] |= (value << start); 83 ale_entry[idx] |= (value << start);
84 } 84 }
85 85
86 #define DEFINE_ALE_FIELD(name, start, bits) \ 86 #define DEFINE_ALE_FIELD(name, start, bits) \
87 static inline int cpsw_ale_get_##name(u32 *ale_entry) \ 87 static inline int cpsw_ale_get_##name(u32 *ale_entry) \
88 { \ 88 { \
89 return cpsw_ale_get_field(ale_entry, start, bits); \ 89 return cpsw_ale_get_field(ale_entry, start, bits); \
90 } \ 90 } \
91 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \ 91 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
92 { \ 92 { \
93 cpsw_ale_set_field(ale_entry, start, bits, value); \ 93 cpsw_ale_set_field(ale_entry, start, bits, value); \
94 } 94 }
95 95
96 DEFINE_ALE_FIELD(entry_type, 60, 2) 96 DEFINE_ALE_FIELD(entry_type, 60, 2)
97 DEFINE_ALE_FIELD(vlan_id, 48, 12) 97 DEFINE_ALE_FIELD(vlan_id, 48, 12)
98 DEFINE_ALE_FIELD(mcast_state, 62, 2) 98 DEFINE_ALE_FIELD(mcast_state, 62, 2)
99 DEFINE_ALE_FIELD(port_mask, 66, 3) 99 DEFINE_ALE_FIELD(port_mask, 66, 3)
100 DEFINE_ALE_FIELD(super, 65, 1) 100 DEFINE_ALE_FIELD(super, 65, 1)
101 DEFINE_ALE_FIELD(ucast_type, 62, 2) 101 DEFINE_ALE_FIELD(ucast_type, 62, 2)
102 DEFINE_ALE_FIELD(port_num, 66, 2) 102 DEFINE_ALE_FIELD(port_num, 66, 2)
103 DEFINE_ALE_FIELD(blocked, 65, 1) 103 DEFINE_ALE_FIELD(blocked, 65, 1)
104 DEFINE_ALE_FIELD(secure, 64, 1) 104 DEFINE_ALE_FIELD(secure, 64, 1)
105 DEFINE_ALE_FIELD(vlan_untag_force, 24, 3) 105 DEFINE_ALE_FIELD(vlan_untag_force, 24, 3)
106 DEFINE_ALE_FIELD(vlan_reg_mcast, 16, 3) 106 DEFINE_ALE_FIELD(vlan_reg_mcast, 16, 3)
107 DEFINE_ALE_FIELD(vlan_unreg_mcast, 8, 3) 107 DEFINE_ALE_FIELD(vlan_unreg_mcast, 8, 3)
108 DEFINE_ALE_FIELD(vlan_member_list, 0, 3) 108 DEFINE_ALE_FIELD(vlan_member_list, 0, 3)
109 DEFINE_ALE_FIELD(mcast, 40, 1) 109 DEFINE_ALE_FIELD(mcast, 40, 1)
110 110
111 /* The MAC address field in the ALE entry cannot be macroized as above */ 111 /* The MAC address field in the ALE entry cannot be macroized as above */
112 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr) 112 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
113 { 113 {
114 int i; 114 int i;
115 115
116 for (i = 0; i < 6; i++) 116 for (i = 0; i < 6; i++)
117 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8); 117 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
118 } 118 }
119 119
120 static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr) 120 static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr)
121 { 121 {
122 int i; 122 int i;
123 123
124 for (i = 0; i < 6; i++) 124 for (i = 0; i < 6; i++)
125 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]); 125 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
126 } 126 }
127 127
128 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry) 128 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
129 { 129 {
130 int i; 130 int i;
131 131
132 WARN_ON(idx > ale->ale_entries); 132 WARN_ON(idx > ale->ale_entries);
133 133
134 __raw_writel(idx, ale->ale_regs + ALE_TABLE_CONTROL); 134 __raw_writel(idx, ale->ale_regs + ALE_TABLE_CONTROL);
135 135
136 for (i = 0; i < ALE_ENTRY_WORDS; i++) 136 for (i = 0; i < ALE_ENTRY_WORDS; i++)
137 ale_entry[i] = __raw_readl(ale->ale_regs + ALE_TABLE + 4 * i); 137 ale_entry[i] = __raw_readl(ale->ale_regs + ALE_TABLE + 4 * i);
138 138
139 return idx; 139 return idx;
140 } 140 }
141 141
142 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry) 142 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
143 { 143 {
144 int i; 144 int i;
145 145
146 WARN_ON(idx > ale->ale_entries); 146 WARN_ON(idx > ale->ale_entries);
147 147
148 for (i = 0; i < ALE_ENTRY_WORDS; i++) 148 for (i = 0; i < ALE_ENTRY_WORDS; i++)
149 __raw_writel(ale_entry[i], ale->ale_regs + ALE_TABLE + 4 * i); 149 __raw_writel(ale_entry[i], ale->ale_regs + ALE_TABLE + 4 * i);
150 150
151 __raw_writel(idx | ALE_TABLE_WRITE, ale->ale_regs + ALE_TABLE_CONTROL); 151 __raw_writel(idx | ALE_TABLE_WRITE, ale->ale_regs + ALE_TABLE_CONTROL);
152 152
153 return idx; 153 return idx;
154 } 154 }
155 155
156 static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8* addr) 156 static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8* addr)
157 { 157 {
158 u32 ale_entry[ALE_ENTRY_WORDS]; 158 u32 ale_entry[ALE_ENTRY_WORDS];
159 int type, idx; 159 int type, idx;
160 160
161 for (idx = 0; idx < ale->ale_entries; idx++) { 161 for (idx = 0; idx < ale->ale_entries; idx++) {
162 u8 entry_addr[6]; 162 u8 entry_addr[6];
163 163
164 cpsw_ale_read(ale, idx, ale_entry); 164 cpsw_ale_read(ale, idx, ale_entry);
165 type = cpsw_ale_get_entry_type(ale_entry); 165 type = cpsw_ale_get_entry_type(ale_entry);
166 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) 166 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
167 continue; 167 continue;
168 cpsw_ale_get_addr(ale_entry, entry_addr); 168 cpsw_ale_get_addr(ale_entry, entry_addr);
169 if (memcmp(entry_addr, addr, 6) == 0) 169 if (memcmp(entry_addr, addr, 6) == 0)
170 return idx; 170 return idx;
171 } 171 }
172 return -ENOENT; 172 return -ENOENT;
173 } 173 }
174 174
175 static int cpsw_ale_match_free(struct cpsw_ale *ale) 175 static int cpsw_ale_match_free(struct cpsw_ale *ale)
176 { 176 {
177 u32 ale_entry[ALE_ENTRY_WORDS]; 177 u32 ale_entry[ALE_ENTRY_WORDS];
178 int type, idx; 178 int type, idx;
179 179
180 for (idx = 0; idx < ale->ale_entries; idx++) { 180 for (idx = 0; idx < ale->ale_entries; idx++) {
181 cpsw_ale_read(ale, idx, ale_entry); 181 cpsw_ale_read(ale, idx, ale_entry);
182 type = cpsw_ale_get_entry_type(ale_entry); 182 type = cpsw_ale_get_entry_type(ale_entry);
183 if (type == ALE_TYPE_FREE) 183 if (type == ALE_TYPE_FREE)
184 return idx; 184 return idx;
185 } 185 }
186 return -ENOENT; 186 return -ENOENT;
187 } 187 }
188 188
189 static int cpsw_ale_find_ageable(struct cpsw_ale *ale) 189 static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
190 { 190 {
191 u32 ale_entry[ALE_ENTRY_WORDS]; 191 u32 ale_entry[ALE_ENTRY_WORDS];
192 int type, idx; 192 int type, idx;
193 193
194 for (idx = 0; idx < ale->ale_entries; idx++) { 194 for (idx = 0; idx < ale->ale_entries; idx++) {
195 cpsw_ale_read(ale, idx, ale_entry); 195 cpsw_ale_read(ale, idx, ale_entry);
196 type = cpsw_ale_get_entry_type(ale_entry); 196 type = cpsw_ale_get_entry_type(ale_entry);
197 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) 197 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
198 continue; 198 continue;
199 if (cpsw_ale_get_mcast(ale_entry)) 199 if (cpsw_ale_get_mcast(ale_entry))
200 continue; 200 continue;
201 type = cpsw_ale_get_ucast_type(ale_entry); 201 type = cpsw_ale_get_ucast_type(ale_entry);
202 if (type != ALE_UCAST_PERSISTANT && 202 if (type != ALE_UCAST_PERSISTANT &&
203 type != ALE_UCAST_OUI) 203 type != ALE_UCAST_OUI)
204 return idx; 204 return idx;
205 } 205 }
206 return -ENOENT; 206 return -ENOENT;
207 } 207 }
208 208
209 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, 209 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
210 int port_mask) 210 int port_mask)
211 { 211 {
212 int mask; 212 int mask;
213 213
214 mask = cpsw_ale_get_port_mask(ale_entry); 214 mask = cpsw_ale_get_port_mask(ale_entry);
215 if ((mask & port_mask) == 0) 215 if ((mask & port_mask) == 0)
216 return; /* ports dont intersect, not interested */ 216 return; /* ports dont intersect, not interested */
217 mask &= ~port_mask; 217 mask &= ~port_mask;
218 218
219 /* free if only remaining port is host port */ 219 /* free if only remaining port is host port */
220 if (mask == BIT(ale->ale_ports)) 220 if (mask == BIT(ale->ale_ports))
221 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 221 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
222 else 222 else
223 cpsw_ale_set_port_mask(ale_entry, mask); 223 cpsw_ale_set_port_mask(ale_entry, mask);
224 } 224 }
225 225
226 static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry, 226 static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry,
227 int port_mask) 227 int port_mask)
228 { 228 {
229 int port; 229 int port;
230 230
231 port = cpsw_ale_get_port_num(ale_entry); 231 port = cpsw_ale_get_port_num(ale_entry);
232 if ((BIT(port) & port_mask) == 0) 232 if ((BIT(port) & port_mask) == 0)
233 return; /* ports dont intersect, not interested */ 233 return; /* ports dont intersect, not interested */
234 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 234 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
235 } 235 }
236 236
237 int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask) 237 int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
238 { 238 {
239 u32 ale_entry[ALE_ENTRY_WORDS]; 239 u32 ale_entry[ALE_ENTRY_WORDS];
240 int ret, idx; 240 int ret, idx;
241 241
242 for (idx = 0; idx < ale->ale_entries; idx++) { 242 for (idx = 0; idx < ale->ale_entries; idx++) {
243 cpsw_ale_read(ale, idx, ale_entry); 243 cpsw_ale_read(ale, idx, ale_entry);
244 ret = cpsw_ale_get_entry_type(ale_entry); 244 ret = cpsw_ale_get_entry_type(ale_entry);
245 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) 245 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
246 continue; 246 continue;
247 247
248 if (cpsw_ale_get_mcast(ale_entry)) 248 if (cpsw_ale_get_mcast(ale_entry))
249 cpsw_ale_flush_mcast(ale, ale_entry, port_mask); 249 cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
250 else 250 else
251 cpsw_ale_flush_ucast(ale, ale_entry, port_mask); 251 cpsw_ale_flush_ucast(ale, ale_entry, port_mask);
252 252
253 cpsw_ale_write(ale, idx, ale_entry); 253 cpsw_ale_write(ale, idx, ale_entry);
254 } 254 }
255 return 0; 255 return 0;
256 } 256 }
257 257
258 static int cpsw_ale_dump_mcast(u32 *ale_entry, char *buf, int len) 258 static int cpsw_ale_dump_mcast(u32 *ale_entry, char *buf, int len)
259 { 259 {
260 int outlen = 0; 260 int outlen = 0;
261 static const char *str_mcast_state[] = {"f", "blf", "lf", "f"}; 261 static const char *str_mcast_state[] = {"f", "blf", "lf", "f"};
262 int mcast_state = cpsw_ale_get_mcast_state(ale_entry); 262 int mcast_state = cpsw_ale_get_mcast_state(ale_entry);
263 int port_mask = cpsw_ale_get_port_mask(ale_entry); 263 int port_mask = cpsw_ale_get_port_mask(ale_entry);
264 int super = cpsw_ale_get_super(ale_entry); 264 int super = cpsw_ale_get_super(ale_entry);
265 265
266 outlen += snprintf(buf + outlen, len - outlen, 266 outlen += snprintf(buf + outlen, len - outlen,
267 "mcstate: %s(%d), ", str_mcast_state[mcast_state], 267 "mcstate: %s(%d), ", str_mcast_state[mcast_state],
268 mcast_state); 268 mcast_state);
269 outlen += snprintf(buf + outlen, len - outlen, 269 outlen += snprintf(buf + outlen, len - outlen,
270 "port mask: %x, %ssuper\n", port_mask, 270 "port mask: %x, %ssuper\n", port_mask,
271 super ? "" : "no "); 271 super ? "" : "no ");
272 return outlen; 272 return outlen;
273 } 273 }
274 274
275 static int cpsw_ale_dump_ucast(u32 *ale_entry, char *buf, int len) 275 static int cpsw_ale_dump_ucast(u32 *ale_entry, char *buf, int len)
276 { 276 {
277 int outlen = 0; 277 int outlen = 0;
278 static const char *str_ucast_type[] = {"persistant", "untouched", 278 static const char *str_ucast_type[] = {"persistant", "untouched",
279 "oui", "touched"}; 279 "oui", "touched"};
280 int ucast_type = cpsw_ale_get_ucast_type(ale_entry); 280 int ucast_type = cpsw_ale_get_ucast_type(ale_entry);
281 int port_num = cpsw_ale_get_port_num(ale_entry); 281 int port_num = cpsw_ale_get_port_num(ale_entry);
282 int secure = cpsw_ale_get_secure(ale_entry); 282 int secure = cpsw_ale_get_secure(ale_entry);
283 int blocked = cpsw_ale_get_blocked(ale_entry); 283 int blocked = cpsw_ale_get_blocked(ale_entry);
284 284
285 outlen += snprintf(buf + outlen, len - outlen, 285 outlen += snprintf(buf + outlen, len - outlen,
286 "uctype: %s(%d), ", str_ucast_type[ucast_type], 286 "uctype: %s(%d), ", str_ucast_type[ucast_type],
287 ucast_type); 287 ucast_type);
288 outlen += snprintf(buf + outlen, len - outlen, 288 outlen += snprintf(buf + outlen, len - outlen,
289 "port: %d%s%s\n", port_num, secure ? ", Secure" : "", 289 "port: %d%s%s\n", port_num, secure ? ", Secure" : "",
290 blocked ? ", Blocked" : ""); 290 blocked ? ", Blocked" : "");
291 return outlen; 291 return outlen;
292 } 292 }
293 293
294 static int cpsw_ale_dump_entry(int idx, u32 *ale_entry, char *buf, int len) 294 static int cpsw_ale_dump_entry(int idx, u32 *ale_entry, char *buf, int len)
295 { 295 {
296 int type, outlen = 0; 296 int type, outlen = 0;
297 u8 addr[6]; 297 u8 addr[6];
298 static const char *str_type[] = {"free", "addr", "vlan", "vlan+addr"}; 298 static const char *str_type[] = {"free", "addr", "vlan", "vlan+addr"};
299 299
300 type = cpsw_ale_get_entry_type(ale_entry); 300 type = cpsw_ale_get_entry_type(ale_entry);
301 if (type == ALE_TYPE_FREE) 301 if (type == ALE_TYPE_FREE)
302 return outlen; 302 return outlen;
303 303
304 if (idx >= 0) { 304 if (idx >= 0) {
305 outlen += snprintf(buf + outlen, len - outlen, 305 outlen += snprintf(buf + outlen, len - outlen,
306 "index %d, ", idx); 306 "index %d, ", idx);
307 } 307 }
308 308
309 outlen += snprintf(buf + outlen, len - outlen, "raw: %08x %08x %08x, ", 309 outlen += snprintf(buf + outlen, len - outlen, "raw: %08x %08x %08x, ",
310 ale_entry[0], ale_entry[1], ale_entry[2]); 310 ale_entry[0], ale_entry[1], ale_entry[2]);
311 311
312 outlen += snprintf(buf + outlen, len - outlen, 312 outlen += snprintf(buf + outlen, len - outlen,
313 "type: %s(%d), ", str_type[type], type); 313 "type: %s(%d), ", str_type[type], type);
314 314
315 cpsw_ale_get_addr(ale_entry, addr); 315 cpsw_ale_get_addr(ale_entry, addr);
316 outlen += snprintf(buf + outlen, len - outlen, 316 outlen += snprintf(buf + outlen, len - outlen,
317 "addr: " ADDR_FMT_STR ", ", ADDR_FMT_ARGS(addr)); 317 "addr: " ADDR_FMT_STR ", ", ADDR_FMT_ARGS(addr));
318 318
319 if (type == ALE_TYPE_VLAN || type == ALE_TYPE_VLAN_ADDR) { 319 if (type == ALE_TYPE_VLAN || type == ALE_TYPE_VLAN_ADDR) {
320 outlen += snprintf(buf + outlen, len - outlen, "vlan: %d, ", 320 outlen += snprintf(buf + outlen, len - outlen, "vlan: %d, ",
321 cpsw_ale_get_vlan_id(ale_entry)); 321 cpsw_ale_get_vlan_id(ale_entry));
322 } 322 }
323 323
324 outlen += cpsw_ale_get_mcast(ale_entry) ? 324 outlen += cpsw_ale_get_mcast(ale_entry) ?
325 cpsw_ale_dump_mcast(ale_entry, buf + outlen, len - outlen) : 325 cpsw_ale_dump_mcast(ale_entry, buf + outlen, len - outlen) :
326 cpsw_ale_dump_ucast(ale_entry, buf + outlen, len - outlen); 326 cpsw_ale_dump_ucast(ale_entry, buf + outlen, len - outlen);
327 327
328 return outlen; 328 return outlen;
329 } 329 }
330 330
331 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags) 331 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
332 { 332 {
333 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 333 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
334 int idx; 334 int idx;
335 335
336 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 336 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
337 cpsw_ale_set_addr(ale_entry, addr); 337 cpsw_ale_set_addr(ale_entry, addr);
338 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT); 338 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
339 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0); 339 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
340 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0); 340 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
341 cpsw_ale_set_port_num(ale_entry, port); 341 cpsw_ale_set_port_num(ale_entry, port);
342 342
343 idx = cpsw_ale_match_addr(ale, addr); 343 idx = cpsw_ale_match_addr(ale, addr);
344 if (idx < 0) 344 if (idx < 0)
345 idx = cpsw_ale_match_free(ale); 345 idx = cpsw_ale_match_free(ale);
346 if (idx < 0) 346 if (idx < 0)
347 idx = cpsw_ale_find_ageable(ale); 347 idx = cpsw_ale_find_ageable(ale);
348 if (idx < 0) 348 if (idx < 0)
349 return -ENOMEM; 349 return -ENOMEM;
350 350
351 cpsw_ale_write(ale, idx, ale_entry); 351 cpsw_ale_write(ale, idx, ale_entry);
352 return 0; 352 return 0;
353 } 353 }
354 EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast);
354 355
355 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port) 356 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
356 { 357 {
357 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 358 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
358 int idx; 359 int idx;
359 360
360 idx = cpsw_ale_match_addr(ale, addr); 361 idx = cpsw_ale_match_addr(ale, addr);
361 if (idx < 0) 362 if (idx < 0)
362 return -ENOENT; 363 return -ENOENT;
363 364
364 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 365 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
365 cpsw_ale_write(ale, idx, ale_entry); 366 cpsw_ale_write(ale, idx, ale_entry);
366 return 0; 367 return 0;
367 } 368 }
369 EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast);
368 370
369 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask) 371 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
370 { 372 {
371 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 373 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
372 int idx, mask; 374 int idx, mask;
373 375
374 idx = cpsw_ale_match_addr(ale, addr); 376 idx = cpsw_ale_match_addr(ale, addr);
375 if (idx >= 0) 377 if (idx >= 0)
376 cpsw_ale_read(ale, idx, ale_entry); 378 cpsw_ale_read(ale, idx, ale_entry);
377 379
378 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 380 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
379 cpsw_ale_set_addr(ale_entry, addr); 381 cpsw_ale_set_addr(ale_entry, addr);
380 cpsw_ale_set_mcast_state(ale_entry, ALE_MCAST_FWD_2); 382 cpsw_ale_set_mcast_state(ale_entry, ALE_MCAST_FWD_2);
381 383
382 mask = cpsw_ale_get_port_mask(ale_entry); 384 mask = cpsw_ale_get_port_mask(ale_entry);
383 port_mask |= mask; 385 port_mask |= mask;
384 cpsw_ale_set_port_mask(ale_entry, port_mask); 386 cpsw_ale_set_port_mask(ale_entry, port_mask);
385 387
386 if (idx < 0) 388 if (idx < 0)
387 idx = cpsw_ale_match_free(ale); 389 idx = cpsw_ale_match_free(ale);
388 if (idx < 0) 390 if (idx < 0)
389 idx = cpsw_ale_find_ageable(ale); 391 idx = cpsw_ale_find_ageable(ale);
390 if (idx < 0) 392 if (idx < 0)
391 return -ENOMEM; 393 return -ENOMEM;
392 394
393 cpsw_ale_write(ale, idx, ale_entry); 395 cpsw_ale_write(ale, idx, ale_entry);
394 return 0; 396 return 0;
395 } 397 }
398 EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast);
396 399
397 int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask) 400 int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
398 { 401 {
399 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 402 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
400 int idx, mask; 403 int idx, mask;
401 404
402 idx = cpsw_ale_match_addr(ale, addr); 405 idx = cpsw_ale_match_addr(ale, addr);
403 if (idx < 0) 406 if (idx < 0)
404 return -EINVAL; 407 return -EINVAL;
405 408
406 cpsw_ale_read(ale, idx, ale_entry); 409 cpsw_ale_read(ale, idx, ale_entry);
407 mask = cpsw_ale_get_port_mask(ale_entry); 410 mask = cpsw_ale_get_port_mask(ale_entry);
408 port_mask = mask & ~port_mask; 411 port_mask = mask & ~port_mask;
409 412
410 if (port_mask == BIT(ale->ale_ports)) 413 if (port_mask == BIT(ale->ale_ports))
411 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 414 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
412 else 415 else
413 cpsw_ale_set_port_mask(ale_entry, port_mask); 416 cpsw_ale_set_port_mask(ale_entry, port_mask);
414 417
415 cpsw_ale_write(ale, idx, ale_entry); 418 cpsw_ale_write(ale, idx, ale_entry);
416 return 0; 419 return 0;
417 } 420 }
418 421
419 struct ale_control_info { 422 struct ale_control_info {
420 const char *name; 423 const char *name;
421 int offset, port_offset; 424 int offset, port_offset;
422 int shift, port_shift; 425 int shift, port_shift;
423 int bits; 426 int bits;
424 }; 427 };
425 428
426 #define CTRL_GLOBAL(name, bit) {#name, ALE_CONTROL, 0, bit, 0, 1} 429 #define CTRL_GLOBAL(name, bit) {#name, ALE_CONTROL, 0, bit, 0, 1}
427 #define CTRL_UNK(name, bit) {#name, ALE_UNKNOWNVLAN, 0, bit, 1, 1} 430 #define CTRL_UNK(name, bit) {#name, ALE_UNKNOWNVLAN, 0, bit, 1, 1}
428 #define CTRL_PORTCTL(name, start, bits) {#name, ALE_PORTCTL, 4, start, 0, bits} 431 #define CTRL_PORTCTL(name, start, bits) {#name, ALE_PORTCTL, 4, start, 0, bits}
429 432
430 static struct ale_control_info ale_controls[] = { 433 static struct ale_control_info ale_controls[] = {
431 [ALE_ENABLE] = CTRL_GLOBAL(enable, 31), 434 [ALE_ENABLE] = CTRL_GLOBAL(enable, 31),
432 [ALE_CLEAR] = CTRL_GLOBAL(clear, 30), 435 [ALE_CLEAR] = CTRL_GLOBAL(clear, 30),
433 [ALE_AGEOUT] = CTRL_GLOBAL(ageout, 29), 436 [ALE_AGEOUT] = CTRL_GLOBAL(ageout, 29),
434 [ALE_VLAN_NOLEARN] = CTRL_GLOBAL(vlan_nolearn, 7), 437 [ALE_VLAN_NOLEARN] = CTRL_GLOBAL(vlan_nolearn, 7),
435 [ALE_NO_PORT_VLAN] = CTRL_GLOBAL(no_port_vlan, 6), 438 [ALE_NO_PORT_VLAN] = CTRL_GLOBAL(no_port_vlan, 6),
436 [ALE_OUI_DENY] = CTRL_GLOBAL(oui_deny, 5), 439 [ALE_OUI_DENY] = CTRL_GLOBAL(oui_deny, 5),
437 [ALE_BYPASS] = CTRL_GLOBAL(bypass, 4), 440 [ALE_BYPASS] = CTRL_GLOBAL(bypass, 4),
438 [ALE_RATE_LIMIT_TX] = CTRL_GLOBAL(rate_limit_tx, 3), 441 [ALE_RATE_LIMIT_TX] = CTRL_GLOBAL(rate_limit_tx, 3),
439 [ALE_VLAN_AWARE] = CTRL_GLOBAL(vlan_aware, 2), 442 [ALE_VLAN_AWARE] = CTRL_GLOBAL(vlan_aware, 2),
440 [ALE_AUTH_ENABLE] = CTRL_GLOBAL(auth_enable, 1), 443 [ALE_AUTH_ENABLE] = CTRL_GLOBAL(auth_enable, 1),
441 [ALE_RATE_LIMIT] = CTRL_GLOBAL(rate_limit, 0), 444 [ALE_RATE_LIMIT] = CTRL_GLOBAL(rate_limit, 0),
442 445
443 [ALE_PORT_STATE] = CTRL_PORTCTL(port_state, 0, 2), 446 [ALE_PORT_STATE] = CTRL_PORTCTL(port_state, 0, 2),
444 [ALE_PORT_DROP_UNTAGGED] = CTRL_PORTCTL(drop_untagged, 2, 1), 447 [ALE_PORT_DROP_UNTAGGED] = CTRL_PORTCTL(drop_untagged, 2, 1),
445 [ALE_PORT_DROP_UNKNOWN_VLAN] = CTRL_PORTCTL(drop_unknown, 3, 1), 448 [ALE_PORT_DROP_UNKNOWN_VLAN] = CTRL_PORTCTL(drop_unknown, 3, 1),
446 [ALE_PORT_NOLEARN] = CTRL_PORTCTL(nolearn, 4, 1), 449 [ALE_PORT_NOLEARN] = CTRL_PORTCTL(nolearn, 4, 1),
447 [ALE_PORT_MCAST_LIMIT] = CTRL_PORTCTL(mcast_limit, 16, 8), 450 [ALE_PORT_MCAST_LIMIT] = CTRL_PORTCTL(mcast_limit, 16, 8),
448 [ALE_PORT_BCAST_LIMIT] = CTRL_PORTCTL(bcast_limit, 24, 8), 451 [ALE_PORT_BCAST_LIMIT] = CTRL_PORTCTL(bcast_limit, 24, 8),
449 452
450 [ALE_PORT_UNKNOWN_VLAN_MEMBER] = CTRL_UNK(unknown_vlan_member, 0), 453 [ALE_PORT_UNKNOWN_VLAN_MEMBER] = CTRL_UNK(unknown_vlan_member, 0),
451 [ALE_PORT_UNKNOWN_MCAST_FLOOD] = CTRL_UNK(unknown_mcast_flood, 8), 454 [ALE_PORT_UNKNOWN_MCAST_FLOOD] = CTRL_UNK(unknown_mcast_flood, 8),
452 [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = CTRL_UNK(unknown_reg_flood, 16), 455 [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = CTRL_UNK(unknown_reg_flood, 16),
453 [ALE_PORT_UNTAGGED_EGRESS] = CTRL_UNK(untagged_egress, 24), 456 [ALE_PORT_UNTAGGED_EGRESS] = CTRL_UNK(untagged_egress, 24),
454 }; 457 };
455 458
456 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control, 459 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
457 int value) 460 int value)
458 { 461 {
459 struct ale_control_info *info = &ale_controls[control]; 462 struct ale_control_info *info = &ale_controls[control];
460 int offset, shift; 463 int offset, shift;
461 u32 tmp, mask; 464 u32 tmp, mask;
462 465
463 if (control < 0 || control >= ARRAY_SIZE(ale_controls)) 466 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
464 return -EINVAL; 467 return -EINVAL;
465 468
466 if (info->port_offset == 0 && info->port_shift == 0) 469 if (info->port_offset == 0 && info->port_shift == 0)
467 port = 0; /* global, port is a dont care */ 470 port = 0; /* global, port is a dont care */
468 471
469 if (port < 0 || port > ale->ale_ports) 472 if (port < 0 || port > ale->ale_ports)
470 return -EINVAL; 473 return -EINVAL;
471 474
472 mask = BITMASK(info->bits); 475 mask = BITMASK(info->bits);
473 if (value & ~mask) 476 if (value & ~mask)
474 return -EINVAL; 477 return -EINVAL;
475 478
476 offset = info->offset + (port * info->port_offset); 479 offset = info->offset + (port * info->port_offset);
477 shift = info->shift + (port * info->port_shift); 480 shift = info->shift + (port * info->port_shift);
478 481
479 tmp = __raw_readl(ale->ale_regs + offset); 482 tmp = __raw_readl(ale->ale_regs + offset);
480 tmp = (tmp & ~(mask << shift)) | (value << shift); 483 tmp = (tmp & ~(mask << shift)) | (value << shift);
481 __raw_writel(tmp, ale->ale_regs + offset); 484 __raw_writel(tmp, ale->ale_regs + offset);
482 485
483 { 486 {
484 volatile u32 dly = 10000; 487 volatile u32 dly = 10000;
485 while (dly--) 488 while (dly--)
486 ; 489 ;
487 } 490 }
488 return 0; 491 return 0;
489 } 492 }
493 EXPORT_SYMBOL_GPL(cpsw_ale_control_set);
490 494
491 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control) 495 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
492 { 496 {
493 struct ale_control_info *info = &ale_controls[control]; 497 struct ale_control_info *info = &ale_controls[control];
494 int offset, shift; 498 int offset, shift;
495 u32 tmp; 499 u32 tmp;
496 500
497 if (control < 0 || control >= ARRAY_SIZE(ale_controls)) 501 if (control < 0 || control >= ARRAY_SIZE(ale_controls))
498 return -EINVAL; 502 return -EINVAL;
499 503
500 if (info->port_offset == 0 && info->port_shift == 0) 504 if (info->port_offset == 0 && info->port_shift == 0)
501 port = 0; /* global, port is a dont care */ 505 port = 0; /* global, port is a dont care */
502 506
503 if (port < 0 || port > ale->ale_ports) 507 if (port < 0 || port > ale->ale_ports)
504 return -EINVAL; 508 return -EINVAL;
505 509
506 offset = info->offset + (port * info->port_offset); 510 offset = info->offset + (port * info->port_offset);
507 shift = info->shift + (port * info->port_shift); 511 shift = info->shift + (port * info->port_shift);
508 512
509 tmp = __raw_readl(ale->ale_regs + offset) >> shift; 513 tmp = __raw_readl(ale->ale_regs + offset) >> shift;
510 return tmp & BITMASK(info->bits); 514 return tmp & BITMASK(info->bits);
511 } 515 }
512 516
513 static ssize_t cpsw_ale_control_show(struct device *dev, 517 static ssize_t cpsw_ale_control_show(struct device *dev,
514 struct device_attribute *attr, 518 struct device_attribute *attr,
515 char *buf) 519 char *buf)
516 { 520 {
517 int i, port, len = 0; 521 int i, port, len = 0;
518 struct ale_control_info *info; 522 struct ale_control_info *info;
519 struct cpsw_ale *ale = control_attr_to_ale(attr); 523 struct cpsw_ale *ale = control_attr_to_ale(attr);
520 524
521 for (i = 0, info = ale_controls; i < ALE_NUM_CONTROLS; i++, info++) { 525 for (i = 0, info = ale_controls; i < ALE_NUM_CONTROLS; i++, info++) {
522 /* global controls */ 526 /* global controls */
523 if (info->port_shift == 0 && info->port_offset == 0) { 527 if (info->port_shift == 0 && info->port_offset == 0) {
524 len += snprintf(buf + len, SZ_4K - len, 528 len += snprintf(buf + len, SZ_4K - len,
525 "%s=%d\n", info->name, 529 "%s=%d\n", info->name,
526 cpsw_ale_control_get(ale, 0, i)); 530 cpsw_ale_control_get(ale, 0, i));
527 continue; 531 continue;
528 } 532 }
529 /* port specific controls */ 533 /* port specific controls */
530 for (port = 0; port < ale->ale_ports; port++) { 534 for (port = 0; port < ale->ale_ports; port++) {
531 len += snprintf(buf + len, SZ_4K - len, 535 len += snprintf(buf + len, SZ_4K - len,
532 "%s.%d=%d\n", info->name, port, 536 "%s.%d=%d\n", info->name, port,
533 cpsw_ale_control_get(ale, port, i)); 537 cpsw_ale_control_get(ale, port, i));
534 } 538 }
535 } 539 }
536 return len; 540 return len;
537 } 541 }
538 542
539 static ssize_t cpsw_ale_control_store(struct device *dev, 543 static ssize_t cpsw_ale_control_store(struct device *dev,
540 struct device_attribute *attr, 544 struct device_attribute *attr,
541 const char *buf, size_t count) 545 const char *buf, size_t count)
542 { 546 {
543 char ctrl_str[33], *end; 547 char ctrl_str[33], *end;
544 int port = 0, value, len, ret, control; 548 int port = 0, value, len, ret, control;
545 struct cpsw_ale *ale = control_attr_to_ale(attr); 549 struct cpsw_ale *ale = control_attr_to_ale(attr);
546 550
547 len = strcspn(buf, ".="); 551 len = strcspn(buf, ".=");
548 if (len >= 32) 552 if (len >= 32)
549 return -ENOMEM; 553 return -ENOMEM;
550 strncpy(ctrl_str, buf, len); 554 strncpy(ctrl_str, buf, len);
551 ctrl_str[len] = '\0'; 555 ctrl_str[len] = '\0';
552 buf += len; 556 buf += len;
553 557
554 if (*buf == '.') { 558 if (*buf == '.') {
555 port = simple_strtoul(buf + 1, &end, 0); 559 port = simple_strtoul(buf + 1, &end, 0);
556 buf = end; 560 buf = end;
557 } 561 }
558 562
559 if (*buf != '=') 563 if (*buf != '=')
560 return -EINVAL; 564 return -EINVAL;
561 565
562 value = simple_strtoul(buf + 1, NULL, 0); 566 value = simple_strtoul(buf + 1, NULL, 0);
563 567
564 for (control = 0; control < ALE_NUM_CONTROLS; control++) 568 for (control = 0; control < ALE_NUM_CONTROLS; control++)
565 if (strcmp(ctrl_str, ale_controls[control].name) == 0) 569 if (strcmp(ctrl_str, ale_controls[control].name) == 0)
566 break; 570 break;
567 571
568 if (control >= ALE_NUM_CONTROLS) 572 if (control >= ALE_NUM_CONTROLS)
569 return -ENOENT; 573 return -ENOENT;
570 574
571 dev_dbg(ale->params.dev, "processing command %s.%d=%d\n", 575 dev_dbg(ale->params.dev, "processing command %s.%d=%d\n",
572 ale_controls[control].name, port, value); 576 ale_controls[control].name, port, value);
573 577
574 ret = cpsw_ale_control_set(ale, port, control, value); 578 ret = cpsw_ale_control_set(ale, port, control, value);
575 if (ret < 0) 579 if (ret < 0)
576 return ret; 580 return ret;
577 return count; 581 return count;
578 } 582 }
579 583
580 DEVICE_ATTR(ale_control, S_IRUGO | S_IWUSR, cpsw_ale_control_show, 584 DEVICE_ATTR(ale_control, S_IRUGO | S_IWUSR, cpsw_ale_control_show,
581 cpsw_ale_control_store); 585 cpsw_ale_control_store);
582 586
583 static ssize_t cpsw_ale_table_show(struct device *dev, 587 static ssize_t cpsw_ale_table_show(struct device *dev,
584 struct device_attribute *attr, 588 struct device_attribute *attr,
585 char *buf) 589 char *buf)
586 { 590 {
587 int len = SZ_4K, outlen = 0, idx; 591 int len = SZ_4K, outlen = 0, idx;
588 u32 ale_entry[ALE_ENTRY_WORDS]; 592 u32 ale_entry[ALE_ENTRY_WORDS];
589 struct cpsw_ale *ale = table_attr_to_ale(attr); 593 struct cpsw_ale *ale = table_attr_to_ale(attr);
590 594
591 for (idx = 0; idx < ale->ale_entries; idx++) { 595 for (idx = 0; idx < ale->ale_entries; idx++) {
592 cpsw_ale_read(ale, idx, ale_entry); 596 cpsw_ale_read(ale, idx, ale_entry);
593 outlen += cpsw_ale_dump_entry(idx, ale_entry, buf + outlen, 597 outlen += cpsw_ale_dump_entry(idx, ale_entry, buf + outlen,
594 len - outlen); 598 len - outlen);
595 } 599 }
596 return outlen; 600 return outlen;
597 } 601 }
598 DEVICE_ATTR(ale_table, S_IRUGO, cpsw_ale_table_show, NULL); 602 DEVICE_ATTR(ale_table, S_IRUGO, cpsw_ale_table_show, NULL);
599 603
600 static void cpsw_ale_timer(unsigned long arg) 604 static void cpsw_ale_timer(unsigned long arg)
601 { 605 {
602 struct cpsw_ale *ale = (struct cpsw_ale *)arg; 606 struct cpsw_ale *ale = (struct cpsw_ale *)arg;
603 607
604 cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1); 608 cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
605 609
606 if (ale->ageout) { 610 if (ale->ageout) {
607 ale->timer.expires = jiffies + ale->ageout; 611 ale->timer.expires = jiffies + ale->ageout;
608 add_timer(&ale->timer); 612 add_timer(&ale->timer);
609 } 613 }
610 } 614 }
611 615
612 int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout) 616 int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout)
613 { 617 {
614 del_timer_sync(&ale->timer); 618 del_timer_sync(&ale->timer);
615 ale->ageout = ageout * HZ; 619 ale->ageout = ageout * HZ;
616 if (ale->ageout) { 620 if (ale->ageout) {
617 ale->timer.expires = jiffies + ale->ageout; 621 ale->timer.expires = jiffies + ale->ageout;
618 add_timer(&ale->timer); 622 add_timer(&ale->timer);
619 } 623 }
620 return 0; 624 return 0;
621 } 625 }
622 626
623 void cpsw_ale_start(struct cpsw_ale *ale) 627 void cpsw_ale_start(struct cpsw_ale *ale)
624 { 628 {
625 u32 rev; 629 u32 rev;
626 int ret; 630 int ret;
627 631
628 rev = __raw_readl(ale->ale_regs + ALE_IDVER); 632 rev = __raw_readl(ale->ale_regs + ALE_IDVER);
629 dev_dbg(ale->params.dev, "initialized cpsw ale revision %d.%d\n", 633 dev_dbg(ale->params.dev, "initialized cpsw ale revision %d.%d\n",
630 (rev >> 8) & 0xff, rev & 0xff); 634 (rev >> 8) & 0xff, rev & 0xff);
631 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1); 635 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
632 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1); 636 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
633 637
634 ale->ale_control_attr = dev_attr_ale_control; 638 ale->ale_control_attr = dev_attr_ale_control;
635 sysfs_attr_init(&ale->ale_control_attr.attr); 639 sysfs_attr_init(&ale->ale_control_attr.attr);
636 ret = device_create_file(ale->params.dev, &ale->ale_control_attr); 640 ret = device_create_file(ale->params.dev, &ale->ale_control_attr);
637 WARN_ON(ret < 0); 641 WARN_ON(ret < 0);
638 642
639 ale->ale_table_attr = dev_attr_ale_table; 643 ale->ale_table_attr = dev_attr_ale_table;
640 sysfs_attr_init(&ale->ale_table_attr.attr); 644 sysfs_attr_init(&ale->ale_table_attr.attr);
641 ret = device_create_file(ale->params.dev, &ale->ale_table_attr); 645 ret = device_create_file(ale->params.dev, &ale->ale_table_attr);
642 WARN_ON(ret < 0); 646 WARN_ON(ret < 0);
643 647
644 init_timer(&ale->timer); 648 init_timer(&ale->timer);
645 ale->timer.data = (unsigned long)ale; 649 ale->timer.data = (unsigned long)ale;
646 ale->timer.function = cpsw_ale_timer; 650 ale->timer.function = cpsw_ale_timer;
647 if (ale->ageout) { 651 if (ale->ageout) {
648 ale->timer.expires = jiffies + ale->ageout; 652 ale->timer.expires = jiffies + ale->ageout;
649 add_timer(&ale->timer); 653 add_timer(&ale->timer);
650 } 654 }
651 } 655 }
656 EXPORT_SYMBOL_GPL(cpsw_ale_start);
652 657
653 void cpsw_ale_stop(struct cpsw_ale *ale) 658 void cpsw_ale_stop(struct cpsw_ale *ale)
654 { 659 {
655 del_timer_sync(&ale->timer); 660 del_timer_sync(&ale->timer);
656 device_remove_file(ale->params.dev, &ale->ale_table_attr); 661 device_remove_file(ale->params.dev, &ale->ale_table_attr);
657 device_remove_file(ale->params.dev, &ale->ale_control_attr); 662 device_remove_file(ale->params.dev, &ale->ale_control_attr);
658 } 663 }
664 EXPORT_SYMBOL_GPL(cpsw_ale_stop);
659 665
660 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params) 666 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
661 { 667 {
662 struct cpsw_ale *ale; 668 struct cpsw_ale *ale;
663 int ret; 669 int ret;
664 670
665 ret = -ENOMEM; 671 ret = -ENOMEM;
666 ale = kzalloc(sizeof(*ale), GFP_KERNEL); 672 ale = kzalloc(sizeof(*ale), GFP_KERNEL);
667 if (WARN_ON(!ale)) 673 if (WARN_ON(!ale))
668 return NULL; 674 return NULL;
669 675
670 ale->params = *params; 676 ale->params = *params;
671 ale->ageout = ale->params.ale_ageout * HZ; 677 ale->ageout = ale->params.ale_ageout * HZ;
672 678
673 return ale; 679 return ale;
674 } 680 }
681 EXPORT_SYMBOL_GPL(cpsw_ale_create);
675 682
676 int cpsw_ale_destroy(struct cpsw_ale *ale) 683 int cpsw_ale_destroy(struct cpsw_ale *ale)
677 { 684 {
678 if (!ale) 685 if (!ale)
679 return -EINVAL; 686 return -EINVAL;
680 cpsw_ale_stop(ale); 687 cpsw_ale_stop(ale);
681 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0); 688 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
682 kfree(ale); 689 kfree(ale);
683 return 0; 690 return 0;
684 } 691 }
692 EXPORT_SYMBOL_GPL(cpsw_ale_destroy);
693
694 MODULE_DESCRIPTION("Ethernet Switch Address Lookup Engine driver");
695 MODULE_AUTHOR("Chandan Nath <chandan.nath@ti.com>");
696 MODULE_LICENSE("GPL");
685 697
698
drivers/net/davinci_cpdma.c
1 /* 1 /*
2 * Texas Instruments CPDMA Driver 2 * Texas Instruments CPDMA Driver
3 * 3 *
4 * Copyright (C) 2010 Texas Instruments 4 * Copyright (C) 2010 Texas Instruments
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as 7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2. 8 * published by the Free Software Foundation version 2.
9 * 9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty 11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 */ 14 */
15 #include <linux/kernel.h> 15 #include <linux/kernel.h>
16 #include <linux/spinlock.h> 16 #include <linux/spinlock.h>
17 #include <linux/device.h> 17 #include <linux/device.h>
18 #include <linux/slab.h> 18 #include <linux/slab.h>
19 #include <linux/err.h> 19 #include <linux/err.h>
20 #include <linux/dma-mapping.h> 20 #include <linux/dma-mapping.h>
21 #include <linux/io.h> 21 #include <linux/io.h>
22 22
23 #include "davinci_cpdma.h" 23 #include "davinci_cpdma.h"
24 24
25 /* DMA Registers */ 25 /* DMA Registers */
26 #define CPDMA_TXIDVER 0x00 26 #define CPDMA_TXIDVER 0x00
27 #define CPDMA_TXCONTROL 0x04 27 #define CPDMA_TXCONTROL 0x04
28 #define CPDMA_TXTEARDOWN 0x08 28 #define CPDMA_TXTEARDOWN 0x08
29 #define CPDMA_RXIDVER 0x10 29 #define CPDMA_RXIDVER 0x10
30 #define CPDMA_RXCONTROL 0x14 30 #define CPDMA_RXCONTROL 0x14
31 #define CPDMA_SOFTRESET 0x1c 31 #define CPDMA_SOFTRESET 0x1c
32 #define CPDMA_RXTEARDOWN 0x18 32 #define CPDMA_RXTEARDOWN 0x18
33 #define CPDMA_TXINTSTATRAW 0x80 33 #define CPDMA_TXINTSTATRAW 0x80
34 #define CPDMA_TXINTSTATMASKED 0x84 34 #define CPDMA_TXINTSTATMASKED 0x84
35 #define CPDMA_TXINTMASKSET 0x88 35 #define CPDMA_TXINTMASKSET 0x88
36 #define CPDMA_TXINTMASKCLEAR 0x8c 36 #define CPDMA_TXINTMASKCLEAR 0x8c
37 #define CPDMA_MACINVECTOR 0x90 37 #define CPDMA_MACINVECTOR 0x90
38 #define CPDMA_MACEOIVECTOR 0x94 38 #define CPDMA_MACEOIVECTOR 0x94
39 #define CPDMA_RXINTSTATRAW 0xa0 39 #define CPDMA_RXINTSTATRAW 0xa0
40 #define CPDMA_RXINTSTATMASKED 0xa4 40 #define CPDMA_RXINTSTATMASKED 0xa4
41 #define CPDMA_RXINTMASKSET 0xa8 41 #define CPDMA_RXINTMASKSET 0xa8
42 #define CPDMA_RXINTMASKCLEAR 0xac 42 #define CPDMA_RXINTMASKCLEAR 0xac
43 #define CPDMA_DMAINTSTATRAW 0xb0 43 #define CPDMA_DMAINTSTATRAW 0xb0
44 #define CPDMA_DMAINTSTATMASKED 0xb4 44 #define CPDMA_DMAINTSTATMASKED 0xb4
45 #define CPDMA_DMAINTMASKSET 0xb8 45 #define CPDMA_DMAINTMASKSET 0xb8
46 #define CPDMA_DMAINTMASKCLEAR 0xbc 46 #define CPDMA_DMAINTMASKCLEAR 0xbc
47 #define CPDMA_DMAINT_HOSTERR BIT(1) 47 #define CPDMA_DMAINT_HOSTERR BIT(1)
48 48
49 /* the following exist only if has_ext_regs is set */ 49 /* the following exist only if has_ext_regs is set */
50 #define CPDMA_DMACONTROL 0x20 50 #define CPDMA_DMACONTROL 0x20
51 #define CPDMA_DMASTATUS 0x24 51 #define CPDMA_DMASTATUS 0x24
52 #define CPDMA_RXBUFFOFS 0x28 52 #define CPDMA_RXBUFFOFS 0x28
53 #define CPDMA_EM_CONTROL 0x2c 53 #define CPDMA_EM_CONTROL 0x2c
54 54
55 /* Descriptor mode bits */ 55 /* Descriptor mode bits */
56 #define CPDMA_DESC_SOP BIT(31) 56 #define CPDMA_DESC_SOP BIT(31)
57 #define CPDMA_DESC_EOP BIT(30) 57 #define CPDMA_DESC_EOP BIT(30)
58 #define CPDMA_DESC_OWNER BIT(29) 58 #define CPDMA_DESC_OWNER BIT(29)
59 #define CPDMA_DESC_EOQ BIT(28) 59 #define CPDMA_DESC_EOQ BIT(28)
60 #define CPDMA_DESC_TD_COMPLETE BIT(27) 60 #define CPDMA_DESC_TD_COMPLETE BIT(27)
61 #define CPDMA_DESC_PASS_CRC BIT(26) 61 #define CPDMA_DESC_PASS_CRC BIT(26)
62 62
63 #define CPDMA_TEARDOWN_VALUE 0xfffffffc 63 #define CPDMA_TEARDOWN_VALUE 0xfffffffc
64 64
65 struct cpdma_desc { 65 struct cpdma_desc {
66 /* hardware fields */ 66 /* hardware fields */
67 u32 hw_next; 67 u32 hw_next;
68 u32 hw_buffer; 68 u32 hw_buffer;
69 u32 hw_len; 69 u32 hw_len;
70 u32 hw_mode; 70 u32 hw_mode;
71 /* software fields */ 71 /* software fields */
72 void *sw_token; 72 void *sw_token;
73 u32 sw_buffer; 73 u32 sw_buffer;
74 u32 sw_len; 74 u32 sw_len;
75 }; 75 };
76 76
77 struct cpdma_desc_pool { 77 struct cpdma_desc_pool {
78 u32 phys; 78 u32 phys;
79 u32 hw_addr; 79 u32 hw_addr;
80 void __iomem *iomap; /* ioremap map */ 80 void __iomem *iomap; /* ioremap map */
81 void *cpumap; /* dma_alloc map */ 81 void *cpumap; /* dma_alloc map */
82 int desc_size, mem_size; 82 int desc_size, mem_size;
83 int num_desc, used_desc; 83 int num_desc, used_desc;
84 unsigned long *bitmap; 84 unsigned long *bitmap;
85 struct device *dev; 85 struct device *dev;
86 spinlock_t lock; 86 spinlock_t lock;
87 }; 87 };
88 88
89 enum cpdma_state { 89 enum cpdma_state {
90 CPDMA_STATE_IDLE, 90 CPDMA_STATE_IDLE,
91 CPDMA_STATE_ACTIVE, 91 CPDMA_STATE_ACTIVE,
92 CPDMA_STATE_TEARDOWN, 92 CPDMA_STATE_TEARDOWN,
93 }; 93 };
94 94
95 const char *cpdma_state_str[] = { "idle", "active", "teardown" }; 95 const char *cpdma_state_str[] = { "idle", "active", "teardown" };
96 96
97 struct cpdma_ctlr { 97 struct cpdma_ctlr {
98 enum cpdma_state state; 98 enum cpdma_state state;
99 struct cpdma_params params; 99 struct cpdma_params params;
100 struct device *dev; 100 struct device *dev;
101 struct cpdma_desc_pool *pool; 101 struct cpdma_desc_pool *pool;
102 spinlock_t lock; 102 spinlock_t lock;
103 struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; 103 struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS];
104 }; 104 };
105 105
106 struct cpdma_chan { 106 struct cpdma_chan {
107 enum cpdma_state state; 107 enum cpdma_state state;
108 struct cpdma_ctlr *ctlr; 108 struct cpdma_ctlr *ctlr;
109 int chan_num; 109 int chan_num;
110 spinlock_t lock; 110 spinlock_t lock;
111 struct cpdma_desc __iomem *head, *tail; 111 struct cpdma_desc __iomem *head, *tail;
112 int count; 112 int count;
113 void __iomem *hdp, *cp, *rxfree; 113 void __iomem *hdp, *cp, *rxfree;
114 u32 mask; 114 u32 mask;
115 cpdma_handler_fn handler; 115 cpdma_handler_fn handler;
116 enum dma_data_direction dir; 116 enum dma_data_direction dir;
117 struct cpdma_chan_stats stats; 117 struct cpdma_chan_stats stats;
118 /* offsets into dmaregs */ 118 /* offsets into dmaregs */
119 int int_set, int_clear, td; 119 int int_set, int_clear, td;
120 }; 120 };
121 121
122 /* The following make access to common cpdma_ctlr params more readable */ 122 /* The following make access to common cpdma_ctlr params more readable */
123 #define dmaregs params.dmaregs 123 #define dmaregs params.dmaregs
124 #define num_chan params.num_chan 124 #define num_chan params.num_chan
125 125
126 /* various accessors */ 126 /* various accessors */
127 #define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) 127 #define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs))
128 #define chan_read(chan, fld) __raw_readl((chan)->fld) 128 #define chan_read(chan, fld) __raw_readl((chan)->fld)
129 #define desc_read(desc, fld) __raw_readl(&(desc)->fld) 129 #define desc_read(desc, fld) __raw_readl(&(desc)->fld)
130 #define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) 130 #define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs))
131 #define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) 131 #define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld)
132 #define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) 132 #define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld)
133 133
134 /* 134 /*
135 * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci 135 * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci
136 * emac) have dedicated on-chip memory for these descriptors. Some other 136 * emac) have dedicated on-chip memory for these descriptors. Some other
137 * devices (e.g. cpsw switches) use plain old memory. Descriptor pools 137 * devices (e.g. cpsw switches) use plain old memory. Descriptor pools
138 * abstract out these details 138 * abstract out these details
139 */ 139 */
140 static struct cpdma_desc_pool * 140 static struct cpdma_desc_pool *
141 cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr, 141 cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
142 int size, int align) 142 int size, int align)
143 { 143 {
144 int bitmap_size; 144 int bitmap_size;
145 struct cpdma_desc_pool *pool; 145 struct cpdma_desc_pool *pool;
146 146
147 pool = kzalloc(sizeof(*pool), GFP_KERNEL); 147 pool = kzalloc(sizeof(*pool), GFP_KERNEL);
148 if (!pool) 148 if (!pool)
149 return NULL; 149 return NULL;
150 150
151 spin_lock_init(&pool->lock); 151 spin_lock_init(&pool->lock);
152 152
153 pool->dev = dev; 153 pool->dev = dev;
154 pool->mem_size = size; 154 pool->mem_size = size;
155 pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); 155 pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align);
156 pool->num_desc = size / pool->desc_size; 156 pool->num_desc = size / pool->desc_size;
157 157
158 bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); 158 bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long);
159 pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); 159 pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
160 if (!pool->bitmap) 160 if (!pool->bitmap)
161 goto fail; 161 goto fail;
162 162
163 if (phys) { 163 if (phys) {
164 pool->phys = phys; 164 pool->phys = phys;
165 pool->iomap = ioremap(phys, size); 165 pool->iomap = ioremap(phys, size);
166 pool->hw_addr = hw_addr; 166 pool->hw_addr = hw_addr;
167 } else { 167 } else {
168 pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, 168 pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
169 GFP_KERNEL); 169 GFP_KERNEL);
170 pool->iomap = pool->cpumap; 170 pool->iomap = pool->cpumap;
171 pool->hw_addr = pool->phys; 171 pool->hw_addr = pool->phys;
172 } 172 }
173 173
174 if (pool->iomap) 174 if (pool->iomap)
175 return pool; 175 return pool;
176 176
177 fail: 177 fail:
178 kfree(pool->bitmap); 178 kfree(pool->bitmap);
179 kfree(pool); 179 kfree(pool);
180 return NULL; 180 return NULL;
181 } 181 }
182 182
183 static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) 183 static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
184 { 184 {
185 unsigned long flags; 185 unsigned long flags;
186 186
187 if (!pool) 187 if (!pool)
188 return; 188 return;
189 189
190 spin_lock_irqsave(&pool->lock, flags); 190 spin_lock_irqsave(&pool->lock, flags);
191 WARN_ON(pool->used_desc); 191 WARN_ON(pool->used_desc);
192 kfree(pool->bitmap); 192 kfree(pool->bitmap);
193 if (pool->cpumap) { 193 if (pool->cpumap) {
194 dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, 194 dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
195 pool->phys); 195 pool->phys);
196 } else { 196 } else {
197 iounmap(pool->iomap); 197 iounmap(pool->iomap);
198 } 198 }
199 spin_unlock_irqrestore(&pool->lock, flags); 199 spin_unlock_irqrestore(&pool->lock, flags);
200 kfree(pool); 200 kfree(pool);
201 } 201 }
202 202
203 static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, 203 static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
204 struct cpdma_desc __iomem *desc) 204 struct cpdma_desc __iomem *desc)
205 { 205 {
206 if (!desc) 206 if (!desc)
207 return 0; 207 return 0;
208 return pool->hw_addr + (__force dma_addr_t)desc - 208 return pool->hw_addr + (__force dma_addr_t)desc -
209 (__force dma_addr_t)pool->iomap; 209 (__force dma_addr_t)pool->iomap;
210 } 210 }
211 211
212 static inline struct cpdma_desc __iomem * 212 static inline struct cpdma_desc __iomem *
213 desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) 213 desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
214 { 214 {
215 return dma ? pool->iomap + dma - pool->hw_addr : NULL; 215 return dma ? pool->iomap + dma - pool->hw_addr : NULL;
216 } 216 }
217 217
218 static struct cpdma_desc __iomem * 218 static struct cpdma_desc __iomem *
219 cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) 219 cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
220 { 220 {
221 unsigned long flags; 221 unsigned long flags;
222 int index; 222 int index;
223 struct cpdma_desc __iomem *desc = NULL; 223 struct cpdma_desc __iomem *desc = NULL;
224 224
225 spin_lock_irqsave(&pool->lock, flags); 225 spin_lock_irqsave(&pool->lock, flags);
226 226
227 index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, 227 index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
228 num_desc, 0); 228 num_desc, 0);
229 if (index < pool->num_desc) { 229 if (index < pool->num_desc) {
230 bitmap_set(pool->bitmap, index, num_desc); 230 bitmap_set(pool->bitmap, index, num_desc);
231 desc = pool->iomap + pool->desc_size * index; 231 desc = pool->iomap + pool->desc_size * index;
232 pool->used_desc++; 232 pool->used_desc++;
233 } 233 }
234 234
235 spin_unlock_irqrestore(&pool->lock, flags); 235 spin_unlock_irqrestore(&pool->lock, flags);
236 return desc; 236 return desc;
237 } 237 }
238 238
239 static void cpdma_desc_free(struct cpdma_desc_pool *pool, 239 static void cpdma_desc_free(struct cpdma_desc_pool *pool,
240 struct cpdma_desc __iomem *desc, int num_desc) 240 struct cpdma_desc __iomem *desc, int num_desc)
241 { 241 {
242 unsigned long flags, index; 242 unsigned long flags, index;
243 243
244 index = ((unsigned long)desc - (unsigned long)pool->iomap) / 244 index = ((unsigned long)desc - (unsigned long)pool->iomap) /
245 pool->desc_size; 245 pool->desc_size;
246 spin_lock_irqsave(&pool->lock, flags); 246 spin_lock_irqsave(&pool->lock, flags);
247 bitmap_clear(pool->bitmap, index, num_desc); 247 bitmap_clear(pool->bitmap, index, num_desc);
248 pool->used_desc--; 248 pool->used_desc--;
249 spin_unlock_irqrestore(&pool->lock, flags); 249 spin_unlock_irqrestore(&pool->lock, flags);
250 } 250 }
251 251
252 struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) 252 struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
253 { 253 {
254 struct cpdma_ctlr *ctlr; 254 struct cpdma_ctlr *ctlr;
255 255
256 ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); 256 ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL);
257 if (!ctlr) 257 if (!ctlr)
258 return NULL; 258 return NULL;
259 259
260 ctlr->state = CPDMA_STATE_IDLE; 260 ctlr->state = CPDMA_STATE_IDLE;
261 ctlr->params = *params; 261 ctlr->params = *params;
262 ctlr->dev = params->dev; 262 ctlr->dev = params->dev;
263 spin_lock_init(&ctlr->lock); 263 spin_lock_init(&ctlr->lock);
264 264
265 ctlr->pool = cpdma_desc_pool_create(ctlr->dev, 265 ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
266 ctlr->params.desc_mem_phys, 266 ctlr->params.desc_mem_phys,
267 ctlr->params.desc_hw_addr, 267 ctlr->params.desc_hw_addr,
268 ctlr->params.desc_mem_size, 268 ctlr->params.desc_mem_size,
269 ctlr->params.desc_align); 269 ctlr->params.desc_align);
270 if (!ctlr->pool) { 270 if (!ctlr->pool) {
271 kfree(ctlr); 271 kfree(ctlr);
272 return NULL; 272 return NULL;
273 } 273 }
274 274
275 if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) 275 if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS))
276 ctlr->num_chan = CPDMA_MAX_CHANNELS; 276 ctlr->num_chan = CPDMA_MAX_CHANNELS;
277 return ctlr; 277 return ctlr;
278 } 278 }
279 EXPORT_SYMBOL_GPL(cpdma_ctlr_create);
279 280
280 int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) 281 int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
281 { 282 {
282 unsigned long flags; 283 unsigned long flags;
283 int i; 284 int i;
284 285
285 spin_lock_irqsave(&ctlr->lock, flags); 286 spin_lock_irqsave(&ctlr->lock, flags);
286 if (ctlr->state != CPDMA_STATE_IDLE) { 287 if (ctlr->state != CPDMA_STATE_IDLE) {
287 spin_unlock_irqrestore(&ctlr->lock, flags); 288 spin_unlock_irqrestore(&ctlr->lock, flags);
288 return -EBUSY; 289 return -EBUSY;
289 } 290 }
290 291
291 if (ctlr->params.has_soft_reset) { 292 if (ctlr->params.has_soft_reset) {
292 unsigned long timeout = jiffies + HZ/10; 293 unsigned long timeout = jiffies + HZ/10;
293 294
294 dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); 295 dma_reg_write(ctlr, CPDMA_SOFTRESET, 1);
295 while (time_before(jiffies, timeout)) { 296 while (time_before(jiffies, timeout)) {
296 if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) 297 if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0)
297 break; 298 break;
298 } 299 }
299 WARN_ON(!time_before(jiffies, timeout)); 300 WARN_ON(!time_before(jiffies, timeout));
300 } 301 }
301 302
302 for (i = 0; i < ctlr->num_chan; i++) { 303 for (i = 0; i < ctlr->num_chan; i++) {
303 __raw_writel(0, ctlr->params.txhdp + 4 * i); 304 __raw_writel(0, ctlr->params.txhdp + 4 * i);
304 __raw_writel(0, ctlr->params.rxhdp + 4 * i); 305 __raw_writel(0, ctlr->params.rxhdp + 4 * i);
305 __raw_writel(0, ctlr->params.txcp + 4 * i); 306 __raw_writel(0, ctlr->params.txcp + 4 * i);
306 __raw_writel(0, ctlr->params.rxcp + 4 * i); 307 __raw_writel(0, ctlr->params.rxcp + 4 * i);
307 } 308 }
308 309
309 dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); 310 dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
310 dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); 311 dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
311 312
312 dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); 313 dma_reg_write(ctlr, CPDMA_TXCONTROL, 1);
313 dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); 314 dma_reg_write(ctlr, CPDMA_RXCONTROL, 1);
314 315
315 ctlr->state = CPDMA_STATE_ACTIVE; 316 ctlr->state = CPDMA_STATE_ACTIVE;
316 317
317 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { 318 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
318 if (ctlr->channels[i]) 319 if (ctlr->channels[i])
319 cpdma_chan_start(ctlr->channels[i]); 320 cpdma_chan_start(ctlr->channels[i]);
320 } 321 }
321 spin_unlock_irqrestore(&ctlr->lock, flags); 322 spin_unlock_irqrestore(&ctlr->lock, flags);
322 return 0; 323 return 0;
323 } 324 }
325 EXPORT_SYMBOL_GPL(cpdma_ctlr_start);
324 326
325 int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) 327 int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
326 { 328 {
327 unsigned long flags; 329 unsigned long flags;
328 int i; 330 int i;
329 331
330 spin_lock_irqsave(&ctlr->lock, flags); 332 spin_lock_irqsave(&ctlr->lock, flags);
331 if (ctlr->state != CPDMA_STATE_ACTIVE) { 333 if (ctlr->state != CPDMA_STATE_ACTIVE) {
332 spin_unlock_irqrestore(&ctlr->lock, flags); 334 spin_unlock_irqrestore(&ctlr->lock, flags);
333 return -EINVAL; 335 return -EINVAL;
334 } 336 }
335 337
336 ctlr->state = CPDMA_STATE_TEARDOWN; 338 ctlr->state = CPDMA_STATE_TEARDOWN;
337 339
338 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { 340 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
339 if (ctlr->channels[i]) 341 if (ctlr->channels[i])
340 cpdma_chan_stop(ctlr->channels[i]); 342 cpdma_chan_stop(ctlr->channels[i]);
341 } 343 }
342 344
343 dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); 345 dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
344 dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); 346 dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
345 347
346 dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); 348 dma_reg_write(ctlr, CPDMA_TXCONTROL, 0);
347 dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); 349 dma_reg_write(ctlr, CPDMA_RXCONTROL, 0);
348 350
349 ctlr->state = CPDMA_STATE_IDLE; 351 ctlr->state = CPDMA_STATE_IDLE;
350 352
351 spin_unlock_irqrestore(&ctlr->lock, flags); 353 spin_unlock_irqrestore(&ctlr->lock, flags);
352 return 0; 354 return 0;
353 } 355 }
356 EXPORT_SYMBOL_GPL(cpdma_ctlr_stop);
354 357
355 int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr) 358 int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
356 { 359 {
357 struct device *dev = ctlr->dev; 360 struct device *dev = ctlr->dev;
358 unsigned long flags; 361 unsigned long flags;
359 int i; 362 int i;
360 363
361 spin_lock_irqsave(&ctlr->lock, flags); 364 spin_lock_irqsave(&ctlr->lock, flags);
362 365
363 dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]); 366 dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
364 367
365 dev_info(dev, "CPDMA: txidver: %x", 368 dev_info(dev, "CPDMA: txidver: %x",
366 dma_reg_read(ctlr, CPDMA_TXIDVER)); 369 dma_reg_read(ctlr, CPDMA_TXIDVER));
367 dev_info(dev, "CPDMA: txcontrol: %x", 370 dev_info(dev, "CPDMA: txcontrol: %x",
368 dma_reg_read(ctlr, CPDMA_TXCONTROL)); 371 dma_reg_read(ctlr, CPDMA_TXCONTROL));
369 dev_info(dev, "CPDMA: txteardown: %x", 372 dev_info(dev, "CPDMA: txteardown: %x",
370 dma_reg_read(ctlr, CPDMA_TXTEARDOWN)); 373 dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
371 dev_info(dev, "CPDMA: rxidver: %x", 374 dev_info(dev, "CPDMA: rxidver: %x",
372 dma_reg_read(ctlr, CPDMA_RXIDVER)); 375 dma_reg_read(ctlr, CPDMA_RXIDVER));
373 dev_info(dev, "CPDMA: rxcontrol: %x", 376 dev_info(dev, "CPDMA: rxcontrol: %x",
374 dma_reg_read(ctlr, CPDMA_RXCONTROL)); 377 dma_reg_read(ctlr, CPDMA_RXCONTROL));
375 dev_info(dev, "CPDMA: softreset: %x", 378 dev_info(dev, "CPDMA: softreset: %x",
376 dma_reg_read(ctlr, CPDMA_SOFTRESET)); 379 dma_reg_read(ctlr, CPDMA_SOFTRESET));
377 dev_info(dev, "CPDMA: rxteardown: %x", 380 dev_info(dev, "CPDMA: rxteardown: %x",
378 dma_reg_read(ctlr, CPDMA_RXTEARDOWN)); 381 dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
379 dev_info(dev, "CPDMA: txintstatraw: %x", 382 dev_info(dev, "CPDMA: txintstatraw: %x",
380 dma_reg_read(ctlr, CPDMA_TXINTSTATRAW)); 383 dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
381 dev_info(dev, "CPDMA: txintstatmasked: %x", 384 dev_info(dev, "CPDMA: txintstatmasked: %x",
382 dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED)); 385 dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
383 dev_info(dev, "CPDMA: txintmaskset: %x", 386 dev_info(dev, "CPDMA: txintmaskset: %x",
384 dma_reg_read(ctlr, CPDMA_TXINTMASKSET)); 387 dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
385 dev_info(dev, "CPDMA: txintmaskclear: %x", 388 dev_info(dev, "CPDMA: txintmaskclear: %x",
386 dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR)); 389 dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
387 dev_info(dev, "CPDMA: macinvector: %x", 390 dev_info(dev, "CPDMA: macinvector: %x",
388 dma_reg_read(ctlr, CPDMA_MACINVECTOR)); 391 dma_reg_read(ctlr, CPDMA_MACINVECTOR));
389 dev_info(dev, "CPDMA: maceoivector: %x", 392 dev_info(dev, "CPDMA: maceoivector: %x",
390 dma_reg_read(ctlr, CPDMA_MACEOIVECTOR)); 393 dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
391 dev_info(dev, "CPDMA: rxintstatraw: %x", 394 dev_info(dev, "CPDMA: rxintstatraw: %x",
392 dma_reg_read(ctlr, CPDMA_RXINTSTATRAW)); 395 dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
393 dev_info(dev, "CPDMA: rxintstatmasked: %x", 396 dev_info(dev, "CPDMA: rxintstatmasked: %x",
394 dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED)); 397 dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
395 dev_info(dev, "CPDMA: rxintmaskset: %x", 398 dev_info(dev, "CPDMA: rxintmaskset: %x",
396 dma_reg_read(ctlr, CPDMA_RXINTMASKSET)); 399 dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
397 dev_info(dev, "CPDMA: rxintmaskclear: %x", 400 dev_info(dev, "CPDMA: rxintmaskclear: %x",
398 dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR)); 401 dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
399 dev_info(dev, "CPDMA: dmaintstatraw: %x", 402 dev_info(dev, "CPDMA: dmaintstatraw: %x",
400 dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW)); 403 dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
401 dev_info(dev, "CPDMA: dmaintstatmasked: %x", 404 dev_info(dev, "CPDMA: dmaintstatmasked: %x",
402 dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED)); 405 dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
403 dev_info(dev, "CPDMA: dmaintmaskset: %x", 406 dev_info(dev, "CPDMA: dmaintmaskset: %x",
404 dma_reg_read(ctlr, CPDMA_DMAINTMASKSET)); 407 dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
405 dev_info(dev, "CPDMA: dmaintmaskclear: %x", 408 dev_info(dev, "CPDMA: dmaintmaskclear: %x",
406 dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR)); 409 dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
407 410
408 if (!ctlr->params.has_ext_regs) { 411 if (!ctlr->params.has_ext_regs) {
409 dev_info(dev, "CPDMA: dmacontrol: %x", 412 dev_info(dev, "CPDMA: dmacontrol: %x",
410 dma_reg_read(ctlr, CPDMA_DMACONTROL)); 413 dma_reg_read(ctlr, CPDMA_DMACONTROL));
411 dev_info(dev, "CPDMA: dmastatus: %x", 414 dev_info(dev, "CPDMA: dmastatus: %x",
412 dma_reg_read(ctlr, CPDMA_DMASTATUS)); 415 dma_reg_read(ctlr, CPDMA_DMASTATUS));
413 dev_info(dev, "CPDMA: rxbuffofs: %x", 416 dev_info(dev, "CPDMA: rxbuffofs: %x",
414 dma_reg_read(ctlr, CPDMA_RXBUFFOFS)); 417 dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
415 } 418 }
416 419
417 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) 420 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
418 if (ctlr->channels[i]) 421 if (ctlr->channels[i])
419 cpdma_chan_dump(ctlr->channels[i]); 422 cpdma_chan_dump(ctlr->channels[i]);
420 423
421 spin_unlock_irqrestore(&ctlr->lock, flags); 424 spin_unlock_irqrestore(&ctlr->lock, flags);
422 return 0; 425 return 0;
423 } 426 }
424 427
425 int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) 428 int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
426 { 429 {
427 unsigned long flags; 430 unsigned long flags;
428 int ret = 0, i; 431 int ret = 0, i;
429 432
430 if (!ctlr) 433 if (!ctlr)
431 return -EINVAL; 434 return -EINVAL;
432 435
433 spin_lock_irqsave(&ctlr->lock, flags); 436 spin_lock_irqsave(&ctlr->lock, flags);
434 if (ctlr->state != CPDMA_STATE_IDLE) 437 if (ctlr->state != CPDMA_STATE_IDLE)
435 cpdma_ctlr_stop(ctlr); 438 cpdma_ctlr_stop(ctlr);
436 439
437 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { 440 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
438 if (ctlr->channels[i]) 441 if (ctlr->channels[i])
439 cpdma_chan_destroy(ctlr->channels[i]); 442 cpdma_chan_destroy(ctlr->channels[i]);
440 } 443 }
441 444
442 cpdma_desc_pool_destroy(ctlr->pool); 445 cpdma_desc_pool_destroy(ctlr->pool);
443 spin_unlock_irqrestore(&ctlr->lock, flags); 446 spin_unlock_irqrestore(&ctlr->lock, flags);
444 kfree(ctlr); 447 kfree(ctlr);
445 return ret; 448 return ret;
446 } 449 }
450 EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
447 451
448 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) 452 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
449 { 453 {
450 unsigned long flags; 454 unsigned long flags;
451 int i, reg; 455 int i, reg;
452 456
453 spin_lock_irqsave(&ctlr->lock, flags); 457 spin_lock_irqsave(&ctlr->lock, flags);
454 if (ctlr->state != CPDMA_STATE_ACTIVE) { 458 if (ctlr->state != CPDMA_STATE_ACTIVE) {
455 spin_unlock_irqrestore(&ctlr->lock, flags); 459 spin_unlock_irqrestore(&ctlr->lock, flags);
456 return -EINVAL; 460 return -EINVAL;
457 } 461 }
458 462
459 reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; 463 reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
460 dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); 464 dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
461 465
462 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { 466 for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
463 if (ctlr->channels[i]) 467 if (ctlr->channels[i])
464 cpdma_chan_int_ctrl(ctlr->channels[i], enable); 468 cpdma_chan_int_ctrl(ctlr->channels[i], enable);
465 } 469 }
466 470
467 spin_unlock_irqrestore(&ctlr->lock, flags); 471 spin_unlock_irqrestore(&ctlr->lock, flags);
468 return 0; 472 return 0;
469 } 473 }
474 EXPORT_SYMBOL_GPL(cpdma_ctlr_int_ctrl);
470 475
471 void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) 476 void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
472 { 477 {
473 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); 478 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
474 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 1); 479 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 1);
475 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 2); 480 dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 2);
476 } 481 }
482 EXPORT_SYMBOL_GPL(cpdma_ctlr_eoi);
477 483
478 struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, 484 struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
479 cpdma_handler_fn handler) 485 cpdma_handler_fn handler)
480 { 486 {
481 struct cpdma_chan *chan; 487 struct cpdma_chan *chan;
482 int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; 488 int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4;
483 unsigned long flags; 489 unsigned long flags;
484 490
485 if (__chan_linear(chan_num) >= ctlr->num_chan) 491 if (__chan_linear(chan_num) >= ctlr->num_chan)
486 return NULL; 492 return NULL;
487 493
488 ret = -ENOMEM; 494 ret = -ENOMEM;
489 chan = kzalloc(sizeof(*chan), GFP_KERNEL); 495 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
490 if (!chan) 496 if (!chan)
491 goto err_chan_alloc; 497 goto err_chan_alloc;
492 498
493 spin_lock_irqsave(&ctlr->lock, flags); 499 spin_lock_irqsave(&ctlr->lock, flags);
494 ret = -EBUSY; 500 ret = -EBUSY;
495 if (ctlr->channels[chan_num]) 501 if (ctlr->channels[chan_num])
496 goto err_chan_busy; 502 goto err_chan_busy;
497 503
498 chan->ctlr = ctlr; 504 chan->ctlr = ctlr;
499 chan->state = CPDMA_STATE_IDLE; 505 chan->state = CPDMA_STATE_IDLE;
500 chan->chan_num = chan_num; 506 chan->chan_num = chan_num;
501 chan->handler = handler; 507 chan->handler = handler;
502 508
503 if (is_rx_chan(chan)) { 509 if (is_rx_chan(chan)) {
504 chan->hdp = ctlr->params.rxhdp + offset; 510 chan->hdp = ctlr->params.rxhdp + offset;
505 chan->cp = ctlr->params.rxcp + offset; 511 chan->cp = ctlr->params.rxcp + offset;
506 chan->rxfree = ctlr->params.rxfree + offset; 512 chan->rxfree = ctlr->params.rxfree + offset;
507 chan->int_set = CPDMA_RXINTMASKSET; 513 chan->int_set = CPDMA_RXINTMASKSET;
508 chan->int_clear = CPDMA_RXINTMASKCLEAR; 514 chan->int_clear = CPDMA_RXINTMASKCLEAR;
509 chan->td = CPDMA_RXTEARDOWN; 515 chan->td = CPDMA_RXTEARDOWN;
510 chan->dir = DMA_FROM_DEVICE; 516 chan->dir = DMA_FROM_DEVICE;
511 } else { 517 } else {
512 chan->hdp = ctlr->params.txhdp + offset; 518 chan->hdp = ctlr->params.txhdp + offset;
513 chan->cp = ctlr->params.txcp + offset; 519 chan->cp = ctlr->params.txcp + offset;
514 chan->int_set = CPDMA_TXINTMASKSET; 520 chan->int_set = CPDMA_TXINTMASKSET;
515 chan->int_clear = CPDMA_TXINTMASKCLEAR; 521 chan->int_clear = CPDMA_TXINTMASKCLEAR;
516 chan->td = CPDMA_TXTEARDOWN; 522 chan->td = CPDMA_TXTEARDOWN;
517 chan->dir = DMA_TO_DEVICE; 523 chan->dir = DMA_TO_DEVICE;
518 } 524 }
519 chan->mask = BIT(chan_linear(chan)); 525 chan->mask = BIT(chan_linear(chan));
520 526
521 spin_lock_init(&chan->lock); 527 spin_lock_init(&chan->lock);
522 528
523 ctlr->channels[chan_num] = chan; 529 ctlr->channels[chan_num] = chan;
524 spin_unlock_irqrestore(&ctlr->lock, flags); 530 spin_unlock_irqrestore(&ctlr->lock, flags);
525 return chan; 531 return chan;
526 532
527 err_chan_busy: 533 err_chan_busy:
528 spin_unlock_irqrestore(&ctlr->lock, flags); 534 spin_unlock_irqrestore(&ctlr->lock, flags);
529 kfree(chan); 535 kfree(chan);
530 err_chan_alloc: 536 err_chan_alloc:
531 return ERR_PTR(ret); 537 return ERR_PTR(ret);
532 } 538 }
539 EXPORT_SYMBOL_GPL(cpdma_chan_create);
533 540
534 int cpdma_chan_destroy(struct cpdma_chan *chan) 541 int cpdma_chan_destroy(struct cpdma_chan *chan)
535 { 542 {
536 struct cpdma_ctlr *ctlr = chan->ctlr; 543 struct cpdma_ctlr *ctlr = chan->ctlr;
537 unsigned long flags; 544 unsigned long flags;
538 545
539 if (!chan) 546 if (!chan)
540 return -EINVAL; 547 return -EINVAL;
541 548
542 spin_lock_irqsave(&ctlr->lock, flags); 549 spin_lock_irqsave(&ctlr->lock, flags);
543 if (chan->state != CPDMA_STATE_IDLE) 550 if (chan->state != CPDMA_STATE_IDLE)
544 cpdma_chan_stop(chan); 551 cpdma_chan_stop(chan);
545 ctlr->channels[chan->chan_num] = NULL; 552 ctlr->channels[chan->chan_num] = NULL;
546 spin_unlock_irqrestore(&ctlr->lock, flags); 553 spin_unlock_irqrestore(&ctlr->lock, flags);
547 kfree(chan); 554 kfree(chan);
548 return 0; 555 return 0;
549 } 556 }
557 EXPORT_SYMBOL_GPL(cpdma_chan_destroy);
550 558
551 int cpdma_chan_get_stats(struct cpdma_chan *chan, 559 int cpdma_chan_get_stats(struct cpdma_chan *chan,
552 struct cpdma_chan_stats *stats) 560 struct cpdma_chan_stats *stats)
553 { 561 {
554 unsigned long flags; 562 unsigned long flags;
555 if (!chan) 563 if (!chan)
556 return -EINVAL; 564 return -EINVAL;
557 spin_lock_irqsave(&chan->lock, flags); 565 spin_lock_irqsave(&chan->lock, flags);
558 memcpy(stats, &chan->stats, sizeof(*stats)); 566 memcpy(stats, &chan->stats, sizeof(*stats));
559 spin_unlock_irqrestore(&chan->lock, flags); 567 spin_unlock_irqrestore(&chan->lock, flags);
560 return 0; 568 return 0;
561 } 569 }
570 EXPORT_SYMBOL_GPL(cpdma_chan_get_stats);
562 571
563 int cpdma_chan_dump(struct cpdma_chan *chan) 572 int cpdma_chan_dump(struct cpdma_chan *chan)
564 { 573 {
565 unsigned long flags; 574 unsigned long flags;
566 struct device *dev = chan->ctlr->dev; 575 struct device *dev = chan->ctlr->dev;
567 576
568 spin_lock_irqsave(&chan->lock, flags); 577 spin_lock_irqsave(&chan->lock, flags);
569 578
570 dev_info(dev, "channel %d (%s %d) state %s", 579 dev_info(dev, "channel %d (%s %d) state %s",
571 chan->chan_num, is_rx_chan(chan) ? "rx" : "tx", 580 chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
572 chan_linear(chan), cpdma_state_str[chan->state]); 581 chan_linear(chan), cpdma_state_str[chan->state]);
573 dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp)); 582 dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
574 dev_info(dev, "\tcp: %x\n", chan_read(chan, cp)); 583 dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
575 if (chan->rxfree) { 584 if (chan->rxfree) {
576 dev_info(dev, "\trxfree: %x\n", 585 dev_info(dev, "\trxfree: %x\n",
577 chan_read(chan, rxfree)); 586 chan_read(chan, rxfree));
578 } 587 }
579 588
580 dev_info(dev, "\tstats head_enqueue: %d\n", 589 dev_info(dev, "\tstats head_enqueue: %d\n",
581 chan->stats.head_enqueue); 590 chan->stats.head_enqueue);
582 dev_info(dev, "\tstats tail_enqueue: %d\n", 591 dev_info(dev, "\tstats tail_enqueue: %d\n",
583 chan->stats.tail_enqueue); 592 chan->stats.tail_enqueue);
584 dev_info(dev, "\tstats pad_enqueue: %d\n", 593 dev_info(dev, "\tstats pad_enqueue: %d\n",
585 chan->stats.pad_enqueue); 594 chan->stats.pad_enqueue);
586 dev_info(dev, "\tstats misqueued: %d\n", 595 dev_info(dev, "\tstats misqueued: %d\n",
587 chan->stats.misqueued); 596 chan->stats.misqueued);
588 dev_info(dev, "\tstats desc_alloc_fail: %d\n", 597 dev_info(dev, "\tstats desc_alloc_fail: %d\n",
589 chan->stats.desc_alloc_fail); 598 chan->stats.desc_alloc_fail);
590 dev_info(dev, "\tstats pad_alloc_fail: %d\n", 599 dev_info(dev, "\tstats pad_alloc_fail: %d\n",
591 chan->stats.pad_alloc_fail); 600 chan->stats.pad_alloc_fail);
592 dev_info(dev, "\tstats runt_receive_buff: %d\n", 601 dev_info(dev, "\tstats runt_receive_buff: %d\n",
593 chan->stats.runt_receive_buff); 602 chan->stats.runt_receive_buff);
594 dev_info(dev, "\tstats runt_transmit_buff: %d\n", 603 dev_info(dev, "\tstats runt_transmit_buff: %d\n",
595 chan->stats.runt_transmit_buff); 604 chan->stats.runt_transmit_buff);
596 dev_info(dev, "\tstats empty_dequeue: %d\n", 605 dev_info(dev, "\tstats empty_dequeue: %d\n",
597 chan->stats.empty_dequeue); 606 chan->stats.empty_dequeue);
598 dev_info(dev, "\tstats busy_dequeue: %d\n", 607 dev_info(dev, "\tstats busy_dequeue: %d\n",
599 chan->stats.busy_dequeue); 608 chan->stats.busy_dequeue);
600 dev_info(dev, "\tstats good_dequeue: %d\n", 609 dev_info(dev, "\tstats good_dequeue: %d\n",
601 chan->stats.good_dequeue); 610 chan->stats.good_dequeue);
602 dev_info(dev, "\tstats requeue: %d\n", 611 dev_info(dev, "\tstats requeue: %d\n",
603 chan->stats.requeue); 612 chan->stats.requeue);
604 dev_info(dev, "\tstats teardown_dequeue: %d\n", 613 dev_info(dev, "\tstats teardown_dequeue: %d\n",
605 chan->stats.teardown_dequeue); 614 chan->stats.teardown_dequeue);
606 615
607 spin_unlock_irqrestore(&chan->lock, flags); 616 spin_unlock_irqrestore(&chan->lock, flags);
608 return 0; 617 return 0;
609 } 618 }
610 619
611 static void __cpdma_chan_submit(struct cpdma_chan *chan, 620 static void __cpdma_chan_submit(struct cpdma_chan *chan,
612 struct cpdma_desc __iomem *desc) 621 struct cpdma_desc __iomem *desc)
613 { 622 {
614 struct cpdma_ctlr *ctlr = chan->ctlr; 623 struct cpdma_ctlr *ctlr = chan->ctlr;
615 struct cpdma_desc __iomem *prev = chan->tail; 624 struct cpdma_desc __iomem *prev = chan->tail;
616 struct cpdma_desc_pool *pool = ctlr->pool; 625 struct cpdma_desc_pool *pool = ctlr->pool;
617 dma_addr_t desc_dma; 626 dma_addr_t desc_dma;
618 u32 mode; 627 u32 mode;
619 628
620 desc_dma = desc_phys(pool, desc); 629 desc_dma = desc_phys(pool, desc);
621 630
622 /* simple case - idle channel */ 631 /* simple case - idle channel */
623 if (!chan->head) { 632 if (!chan->head) {
624 chan->stats.head_enqueue++; 633 chan->stats.head_enqueue++;
625 chan->head = desc; 634 chan->head = desc;
626 chan->tail = desc; 635 chan->tail = desc;
627 if (chan->state == CPDMA_STATE_ACTIVE) 636 if (chan->state == CPDMA_STATE_ACTIVE)
628 chan_write(chan, hdp, desc_dma); 637 chan_write(chan, hdp, desc_dma);
629 return; 638 return;
630 } 639 }
631 640
632 /* first chain the descriptor at the tail of the list */ 641 /* first chain the descriptor at the tail of the list */
633 desc_write(prev, hw_next, desc_dma); 642 desc_write(prev, hw_next, desc_dma);
634 chan->tail = desc; 643 chan->tail = desc;
635 chan->stats.tail_enqueue++; 644 chan->stats.tail_enqueue++;
636 645
637 /* next check if EOQ has been triggered already */ 646 /* next check if EOQ has been triggered already */
638 mode = desc_read(prev, hw_mode); 647 mode = desc_read(prev, hw_mode);
639 if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) && 648 if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
640 (chan->state == CPDMA_STATE_ACTIVE)) { 649 (chan->state == CPDMA_STATE_ACTIVE)) {
641 desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ); 650 desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
642 chan_write(chan, hdp, desc_dma); 651 chan_write(chan, hdp, desc_dma);
643 chan->stats.misqueued++; 652 chan->stats.misqueued++;
644 } 653 }
645 } 654 }
646 655
647 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, 656 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
648 int len, gfp_t gfp_mask) 657 int len, gfp_t gfp_mask)
649 { 658 {
650 struct cpdma_ctlr *ctlr = chan->ctlr; 659 struct cpdma_ctlr *ctlr = chan->ctlr;
651 struct cpdma_desc __iomem *desc; 660 struct cpdma_desc __iomem *desc;
652 dma_addr_t buffer; 661 dma_addr_t buffer;
653 unsigned long flags; 662 unsigned long flags;
654 u32 mode; 663 u32 mode;
655 int ret = 0; 664 int ret = 0;
656 665
657 spin_lock_irqsave(&chan->lock, flags); 666 spin_lock_irqsave(&chan->lock, flags);
658 667
659 if (chan->state == CPDMA_STATE_TEARDOWN) { 668 if (chan->state == CPDMA_STATE_TEARDOWN) {
660 ret = -EINVAL; 669 ret = -EINVAL;
661 goto unlock_ret; 670 goto unlock_ret;
662 } 671 }
663 672
664 desc = cpdma_desc_alloc(ctlr->pool, 1); 673 desc = cpdma_desc_alloc(ctlr->pool, 1);
665 if (!desc) { 674 if (!desc) {
666 chan->stats.desc_alloc_fail++; 675 chan->stats.desc_alloc_fail++;
667 ret = -ENOMEM; 676 ret = -ENOMEM;
668 goto unlock_ret; 677 goto unlock_ret;
669 } 678 }
670 679
671 if (len < ctlr->params.min_packet_size) { 680 if (len < ctlr->params.min_packet_size) {
672 len = ctlr->params.min_packet_size; 681 len = ctlr->params.min_packet_size;
673 chan->stats.runt_transmit_buff++; 682 chan->stats.runt_transmit_buff++;
674 } 683 }
675 684
676 buffer = dma_map_single(ctlr->dev, data, len, chan->dir); 685 buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
677 mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; 686 mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
678 687
679 desc_write(desc, hw_next, 0); 688 desc_write(desc, hw_next, 0);
680 desc_write(desc, hw_buffer, buffer); 689 desc_write(desc, hw_buffer, buffer);
681 desc_write(desc, hw_len, len); 690 desc_write(desc, hw_len, len);
682 desc_write(desc, hw_mode, mode | len); 691 desc_write(desc, hw_mode, mode | len);
683 desc_write(desc, sw_token, token); 692 desc_write(desc, sw_token, token);
684 desc_write(desc, sw_buffer, buffer); 693 desc_write(desc, sw_buffer, buffer);
685 desc_write(desc, sw_len, len); 694 desc_write(desc, sw_len, len);
686 695
687 __cpdma_chan_submit(chan, desc); 696 __cpdma_chan_submit(chan, desc);
688 697
689 if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) 698 if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
690 chan_write(chan, rxfree, 1); 699 chan_write(chan, rxfree, 1);
691 700
692 chan->count++; 701 chan->count++;
693 702
694 unlock_ret: 703 unlock_ret:
695 spin_unlock_irqrestore(&chan->lock, flags); 704 spin_unlock_irqrestore(&chan->lock, flags);
696 return ret; 705 return ret;
697 } 706 }
707 EXPORT_SYMBOL_GPL(cpdma_chan_submit);
698 708
699 static void __cpdma_chan_free(struct cpdma_chan *chan, 709 static void __cpdma_chan_free(struct cpdma_chan *chan,
700 struct cpdma_desc __iomem *desc, 710 struct cpdma_desc __iomem *desc,
701 int outlen, int status) 711 int outlen, int status)
702 { 712 {
703 struct cpdma_ctlr *ctlr = chan->ctlr; 713 struct cpdma_ctlr *ctlr = chan->ctlr;
704 struct cpdma_desc_pool *pool = ctlr->pool; 714 struct cpdma_desc_pool *pool = ctlr->pool;
705 dma_addr_t buff_dma; 715 dma_addr_t buff_dma;
706 int origlen; 716 int origlen;
707 void *token; 717 void *token;
708 718
709 token = (void *)desc_read(desc, sw_token); 719 token = (void *)desc_read(desc, sw_token);
710 buff_dma = desc_read(desc, sw_buffer); 720 buff_dma = desc_read(desc, sw_buffer);
711 origlen = desc_read(desc, sw_len); 721 origlen = desc_read(desc, sw_len);
712 722
713 dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); 723 dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
714 cpdma_desc_free(pool, desc, 1); 724 cpdma_desc_free(pool, desc, 1);
715 (*chan->handler)(token, outlen, status); 725 (*chan->handler)(token, outlen, status);
716 } 726 }
717 727
718 static int __cpdma_chan_process(struct cpdma_chan *chan) 728 static int __cpdma_chan_process(struct cpdma_chan *chan)
719 { 729 {
720 struct cpdma_ctlr *ctlr = chan->ctlr; 730 struct cpdma_ctlr *ctlr = chan->ctlr;
721 struct cpdma_desc __iomem *desc; 731 struct cpdma_desc __iomem *desc;
722 int status, outlen; 732 int status, outlen;
723 struct cpdma_desc_pool *pool = ctlr->pool; 733 struct cpdma_desc_pool *pool = ctlr->pool;
724 dma_addr_t desc_dma; 734 dma_addr_t desc_dma;
725 735
726 desc = chan->head; 736 desc = chan->head;
727 if (!desc) { 737 if (!desc) {
728 chan->stats.empty_dequeue++; 738 chan->stats.empty_dequeue++;
729 status = -ENOENT; 739 status = -ENOENT;
730 goto unlock_ret; 740 goto unlock_ret;
731 } 741 }
732 desc_dma = desc_phys(pool, desc); 742 desc_dma = desc_phys(pool, desc);
733 743
734 status = __raw_readl(&desc->hw_mode); 744 status = __raw_readl(&desc->hw_mode);
735 outlen = status & 0x7ff; 745 outlen = status & 0x7ff;
736 if (status & CPDMA_DESC_OWNER) { 746 if (status & CPDMA_DESC_OWNER) {
737 chan->stats.busy_dequeue++; 747 chan->stats.busy_dequeue++;
738 status = -EBUSY; 748 status = -EBUSY;
739 goto unlock_ret; 749 goto unlock_ret;
740 } 750 }
741 status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); 751 status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
742 752
743 chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); 753 chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
744 chan_write(chan, cp, desc_dma); 754 chan_write(chan, cp, desc_dma);
745 chan->count--; 755 chan->count--;
746 chan->stats.good_dequeue++; 756 chan->stats.good_dequeue++;
747 757
748 if (status & CPDMA_DESC_EOQ) { 758 if (status & CPDMA_DESC_EOQ) {
749 chan->stats.requeue++; 759 chan->stats.requeue++;
750 chan_write(chan, hdp, desc_phys(pool, chan->head)); 760 chan_write(chan, hdp, desc_phys(pool, chan->head));
751 } 761 }
752 762
753 __cpdma_chan_free(chan, desc, outlen, status); 763 __cpdma_chan_free(chan, desc, outlen, status);
754 return status; 764 return status;
755 765
756 unlock_ret: 766 unlock_ret:
757 return status; 767 return status;
758 } 768 }
759 769
760 int cpdma_chan_process(struct cpdma_chan *chan, int quota) 770 int cpdma_chan_process(struct cpdma_chan *chan, int quota)
761 { 771 {
762 int used = 0, ret = 0; 772 int used = 0, ret = 0;
763 773
764 if (chan->state != CPDMA_STATE_ACTIVE) 774 if (chan->state != CPDMA_STATE_ACTIVE)
765 return -EINVAL; 775 return -EINVAL;
766 776
767 while (used < quota) { 777 while (used < quota) {
768 ret = __cpdma_chan_process(chan); 778 ret = __cpdma_chan_process(chan);
769 if (ret < 0) 779 if (ret < 0)
770 break; 780 break;
771 used++; 781 used++;
772 } 782 }
773 return used; 783 return used;
774 } 784 }
785 EXPORT_SYMBOL_GPL(cpdma_chan_process);
775 786
776 int cpdma_chan_start(struct cpdma_chan *chan) 787 int cpdma_chan_start(struct cpdma_chan *chan)
777 { 788 {
778 struct cpdma_ctlr *ctlr = chan->ctlr; 789 struct cpdma_ctlr *ctlr = chan->ctlr;
779 struct cpdma_desc_pool *pool = ctlr->pool; 790 struct cpdma_desc_pool *pool = ctlr->pool;
780 unsigned long flags; 791 unsigned long flags;
781 792
782 spin_lock_irqsave(&chan->lock, flags); 793 spin_lock_irqsave(&chan->lock, flags);
783 if (chan->state != CPDMA_STATE_IDLE) { 794 if (chan->state != CPDMA_STATE_IDLE) {
784 spin_unlock_irqrestore(&chan->lock, flags); 795 spin_unlock_irqrestore(&chan->lock, flags);
785 return -EBUSY; 796 return -EBUSY;
786 } 797 }
787 if (ctlr->state != CPDMA_STATE_ACTIVE) { 798 if (ctlr->state != CPDMA_STATE_ACTIVE) {
788 spin_unlock_irqrestore(&chan->lock, flags); 799 spin_unlock_irqrestore(&chan->lock, flags);
789 return -EINVAL; 800 return -EINVAL;
790 } 801 }
791 dma_reg_write(ctlr, chan->int_set, chan->mask); 802 dma_reg_write(ctlr, chan->int_set, chan->mask);
792 chan->state = CPDMA_STATE_ACTIVE; 803 chan->state = CPDMA_STATE_ACTIVE;
793 if (chan->head) { 804 if (chan->head) {
794 chan_write(chan, hdp, desc_phys(pool, chan->head)); 805 chan_write(chan, hdp, desc_phys(pool, chan->head));
795 if (chan->rxfree) 806 if (chan->rxfree)
796 chan_write(chan, rxfree, chan->count); 807 chan_write(chan, rxfree, chan->count);
797 } 808 }
798 809
799 spin_unlock_irqrestore(&chan->lock, flags); 810 spin_unlock_irqrestore(&chan->lock, flags);
800 return 0; 811 return 0;
801 } 812 }
813 EXPORT_SYMBOL_GPL(cpdma_chan_start);
802 814
803 int cpdma_chan_stop(struct cpdma_chan *chan) 815 int cpdma_chan_stop(struct cpdma_chan *chan)
804 { 816 {
805 struct cpdma_ctlr *ctlr = chan->ctlr; 817 struct cpdma_ctlr *ctlr = chan->ctlr;
806 struct cpdma_desc_pool *pool = ctlr->pool; 818 struct cpdma_desc_pool *pool = ctlr->pool;
807 unsigned long flags; 819 unsigned long flags;
808 int ret; 820 int ret;
809 unsigned long timeout; 821 unsigned long timeout;
810 822
811 spin_lock_irqsave(&chan->lock, flags); 823 spin_lock_irqsave(&chan->lock, flags);
812 if (chan->state != CPDMA_STATE_ACTIVE) { 824 if (chan->state != CPDMA_STATE_ACTIVE) {
813 spin_unlock_irqrestore(&chan->lock, flags); 825 spin_unlock_irqrestore(&chan->lock, flags);
814 return -EINVAL; 826 return -EINVAL;
815 } 827 }
816 828
817 chan->state = CPDMA_STATE_TEARDOWN; 829 chan->state = CPDMA_STATE_TEARDOWN;
818 dma_reg_write(ctlr, chan->int_clear, chan->mask); 830 dma_reg_write(ctlr, chan->int_clear, chan->mask);
819 831
820 /* trigger teardown */ 832 /* trigger teardown */
821 dma_reg_write(ctlr, chan->td, chan->chan_num); 833 dma_reg_write(ctlr, chan->td, chan->chan_num);
822 834
823 /* wait for teardown complete */ 835 /* wait for teardown complete */
824 timeout = jiffies + HZ/10; /* 100 msec */ 836 timeout = jiffies + HZ/10; /* 100 msec */
825 while (time_before(jiffies, timeout)) { 837 while (time_before(jiffies, timeout)) {
826 u32 cp = chan_read(chan, cp); 838 u32 cp = chan_read(chan, cp);
827 if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) 839 if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE)
828 break; 840 break;
829 cpu_relax(); 841 cpu_relax();
830 } 842 }
831 WARN_ON(!time_before(jiffies, timeout)); 843 WARN_ON(!time_before(jiffies, timeout));
832 chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); 844 chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
833 845
834 /* handle completed packets */ 846 /* handle completed packets */
835 do { 847 do {
836 ret = __cpdma_chan_process(chan); 848 ret = __cpdma_chan_process(chan);
837 if (ret < 0) 849 if (ret < 0)
838 break; 850 break;
839 } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); 851 } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0);
840 852
841 /* remaining packets haven't been tx/rx'ed, clean them up */ 853 /* remaining packets haven't been tx/rx'ed, clean them up */
842 while (chan->head) { 854 while (chan->head) {
843 struct cpdma_desc __iomem *desc = chan->head; 855 struct cpdma_desc __iomem *desc = chan->head;
844 dma_addr_t next_dma; 856 dma_addr_t next_dma;
845 857
846 next_dma = desc_read(desc, hw_next); 858 next_dma = desc_read(desc, hw_next);
847 chan->head = desc_from_phys(pool, next_dma); 859 chan->head = desc_from_phys(pool, next_dma);
848 chan->stats.teardown_dequeue++; 860 chan->stats.teardown_dequeue++;
849 861
850 /* issue callback without locks held */ 862 /* issue callback without locks held */
851 spin_unlock_irqrestore(&chan->lock, flags); 863 spin_unlock_irqrestore(&chan->lock, flags);
852 __cpdma_chan_free(chan, desc, 0, -ENOSYS); 864 __cpdma_chan_free(chan, desc, 0, -ENOSYS);
853 spin_lock_irqsave(&chan->lock, flags); 865 spin_lock_irqsave(&chan->lock, flags);
854 } 866 }
855 867
856 chan->state = CPDMA_STATE_IDLE; 868 chan->state = CPDMA_STATE_IDLE;
857 spin_unlock_irqrestore(&chan->lock, flags); 869 spin_unlock_irqrestore(&chan->lock, flags);
858 return 0; 870 return 0;
859 } 871 }
872 EXPORT_SYMBOL_GPL(cpdma_chan_stop);
860 873
861 int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) 874 int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
862 { 875 {
863 unsigned long flags; 876 unsigned long flags;
864 877
865 spin_lock_irqsave(&chan->lock, flags); 878 spin_lock_irqsave(&chan->lock, flags);
866 if (chan->state != CPDMA_STATE_ACTIVE) { 879 if (chan->state != CPDMA_STATE_ACTIVE) {
867 spin_unlock_irqrestore(&chan->lock, flags); 880 spin_unlock_irqrestore(&chan->lock, flags);
868 return -EINVAL; 881 return -EINVAL;
869 } 882 }
870 883
871 dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, 884 dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear,
872 chan->mask); 885 chan->mask);
873 spin_unlock_irqrestore(&chan->lock, flags); 886 spin_unlock_irqrestore(&chan->lock, flags);
874 887
875 return 0; 888 return 0;
876 } 889 }
877 890
878 struct cpdma_control_info { 891 struct cpdma_control_info {
879 u32 reg; 892 u32 reg;
880 u32 shift, mask; 893 u32 shift, mask;
881 int access; 894 int access;
882 #define ACCESS_RO BIT(0) 895 #define ACCESS_RO BIT(0)
883 #define ACCESS_WO BIT(1) 896 #define ACCESS_WO BIT(1)
884 #define ACCESS_RW (ACCESS_RO | ACCESS_WO) 897 #define ACCESS_RW (ACCESS_RO | ACCESS_WO)
885 }; 898 };
886 899
887 struct cpdma_control_info controls[] = { 900 struct cpdma_control_info controls[] = {
888 [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, 901 [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO},
889 [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, 902 [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW},
890 [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, 903 [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW},
891 [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, 904 [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW},
892 [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, 905 [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW},
893 [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, 906 [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO},
894 [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, 907 [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW},
895 [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, 908 [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW},
896 [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, 909 [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW},
897 [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, 910 [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW},
898 [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, 911 [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW},
899 }; 912 };
900 913
901 int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) 914 int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
902 { 915 {
903 unsigned long flags; 916 unsigned long flags;
904 struct cpdma_control_info *info = &controls[control]; 917 struct cpdma_control_info *info = &controls[control];
905 int ret; 918 int ret;
906 919
907 spin_lock_irqsave(&ctlr->lock, flags); 920 spin_lock_irqsave(&ctlr->lock, flags);
908 921
909 ret = -ENOTSUPP; 922 ret = -ENOTSUPP;
910 if (!ctlr->params.has_ext_regs) 923 if (!ctlr->params.has_ext_regs)
911 goto unlock_ret; 924 goto unlock_ret;
912 925
913 ret = -EINVAL; 926 ret = -EINVAL;
914 if (ctlr->state != CPDMA_STATE_ACTIVE) 927 if (ctlr->state != CPDMA_STATE_ACTIVE)
915 goto unlock_ret; 928 goto unlock_ret;
916 929
917 ret = -ENOENT; 930 ret = -ENOENT;
918 if (control < 0 || control >= ARRAY_SIZE(controls)) 931 if (control < 0 || control >= ARRAY_SIZE(controls))
919 goto unlock_ret; 932 goto unlock_ret;
920 933
921 ret = -EPERM; 934 ret = -EPERM;
922 if ((info->access & ACCESS_RO) != ACCESS_RO) 935 if ((info->access & ACCESS_RO) != ACCESS_RO)
923 goto unlock_ret; 936 goto unlock_ret;
924 937
925 ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; 938 ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
926 939
927 unlock_ret: 940 unlock_ret:
928 spin_unlock_irqrestore(&ctlr->lock, flags); 941 spin_unlock_irqrestore(&ctlr->lock, flags);
929 return ret; 942 return ret;
930 } 943 }
931 944
932 int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) 945 int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
933 { 946 {
934 unsigned long flags; 947 unsigned long flags;
935 struct cpdma_control_info *info = &controls[control]; 948 struct cpdma_control_info *info = &controls[control];
936 int ret; 949 int ret;
937 u32 val; 950 u32 val;
938 951
939 spin_lock_irqsave(&ctlr->lock, flags); 952 spin_lock_irqsave(&ctlr->lock, flags);
940 953
941 ret = -ENOTSUPP; 954 ret = -ENOTSUPP;
942 if (!ctlr->params.has_ext_regs) 955 if (!ctlr->params.has_ext_regs)
943 goto unlock_ret; 956 goto unlock_ret;
944 957
945 ret = -EINVAL; 958 ret = -EINVAL;
946 if (ctlr->state != CPDMA_STATE_ACTIVE) 959 if (ctlr->state != CPDMA_STATE_ACTIVE)
947 goto unlock_ret; 960 goto unlock_ret;
948 961
949 ret = -ENOENT; 962 ret = -ENOENT;
950 if (control < 0 || control >= ARRAY_SIZE(controls)) 963 if (control < 0 || control >= ARRAY_SIZE(controls))
951 goto unlock_ret; 964 goto unlock_ret;
952 965
953 ret = -EPERM; 966 ret = -EPERM;
954 if ((info->access & ACCESS_WO) != ACCESS_WO) 967 if ((info->access & ACCESS_WO) != ACCESS_WO)
955 goto unlock_ret; 968 goto unlock_ret;
956 969
957 val = dma_reg_read(ctlr, info->reg); 970 val = dma_reg_read(ctlr, info->reg);
958 val &= ~(info->mask << info->shift); 971 val &= ~(info->mask << info->shift);
959 val |= (value & info->mask) << info->shift; 972 val |= (value & info->mask) << info->shift;
960 dma_reg_write(ctlr, info->reg, val); 973 dma_reg_write(ctlr, info->reg, val);
961 ret = 0; 974 ret = 0;
962 975
963 unlock_ret: 976 unlock_ret:
964 spin_unlock_irqrestore(&ctlr->lock, flags); 977 spin_unlock_irqrestore(&ctlr->lock, flags);
965 return ret; 978 return ret;
966 } 979 }
980 EXPORT_SYMBOL_GPL(cpdma_control_set);
967 981