ramips_eth: pass sys_clk via platform_data
[oweals/openwrt.git] / target / linux / ubicom32 / patches-2.6.30 / 100-ubicom32_support.patch
1 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/aes_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/aes_ubicom32.c
2 --- linux-2.6.30.10/arch/ubicom32/crypto/aes_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
3 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/aes_ubicom32.c     2009-12-11 11:45:11.000000000 +0200
4 @@ -0,0 +1,458 @@
5 +/*
6 + * arch/ubicom32/crypto/aes_ubicom32.c
7 + *   Ubicom32 implementation of the AES Cipher Algorithm.
8 + *
9 + * (C) Copyright 2009, Ubicom, Inc.
10 + *
11 + * This file is part of the Ubicom32 Linux Kernel Port.
12 + *
13 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14 + * it and/or modify it under the terms of the GNU General Public License
15 + * as published by the Free Software Foundation, either version 2 of the
16 + * License, or (at your option) any later version.
17 + *
18 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21 + * the GNU General Public License for more details.
22 + *
23 + * You should have received a copy of the GNU General Public License
24 + * along with the Ubicom32 Linux Kernel Port.  If not,
25 + * see <http://www.gnu.org/licenses/>.
26 + *
27 + * Ubicom32 implementation derived from (with many thanks):
28 + *   arch/m68knommu
29 + *   arch/blackfin
30 + *   arch/parisc
31 + */
32 +#include <crypto/aes.h>
33 +#include <crypto/algapi.h>
34 +#include <linux/err.h>
35 +#include <linux/module.h>
36 +#include <linux/init.h>
37 +#include <linux/spinlock.h>
38 +#include "crypto_ubicom32.h"
39 +#include <asm/linkage.h>
40 +
41 +struct ubicom32_aes_ctx {
42 +       u8 key[AES_MAX_KEY_SIZE];
43 +       u32 ctrl;
44 +       int key_len;
45 +};
46 +
47 +static inline void aes_hw_set_key(const u8 *key, u8 key_len)
48 +{
49 +       /*
50 +        * switch case has more overhead than 4 move.4 instructions, so just copy 256 bits
51 +        */
52 +       SEC_SET_KEY_256(key);
53 +}
54 +
55 +static inline void aes_hw_set_iv(const u8 *iv)
56 +{
57 +       SEC_SET_IV_4W(iv);
58 +}
59 +
60 +static inline void aes_hw_cipher(u8 *out, const u8 *in)
61 +{
62 +       SEC_SET_INPUT_4W(in);
63 +
64 +       asm volatile (
65 +       "       ; start AES by writing 0x40(SECURITY_BASE)      \n\t"
66 +       "       move.4 0x40(%0), #0x01                          \n\t"
67 +       "       pipe_flush 0                                    \n\t"
68 +       "                                                       \n\t"
69 +       "       ; wait for the module to calculate the output   \n\t"
70 +       "       btst 0x04(%0), #0                               \n\t"
71 +       "       jmpne.f .-4                                     \n\t"
72 +               :
73 +               : "a" (SEC_BASE)
74 +               : "cc"
75 +       );
76 +
77 +       SEC_GET_OUTPUT_4W(out);
78 +}
79 +
80 +static int __ocm_text aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
81 +                      unsigned int key_len)
82 +{
83 +       struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
84 +
85 +       uctx->key_len = key_len;
86 +       memcpy(uctx->key, in_key, key_len);
87 +
88 +       /*
89 +        * leave out HASH_ALG (none = 0), CBC (no = 0), DIR (unknown) yet
90 +        */
91 +       switch (uctx->key_len) {
92 +       case 16:
93 +               uctx->ctrl = SEC_KEY_128_BITS | SEC_ALG_AES;
94 +               break;
95 +       case 24:
96 +               uctx->ctrl = SEC_KEY_192_BITS | SEC_ALG_AES;
97 +               break;
98 +       case 32:
99 +               uctx->ctrl = SEC_KEY_256_BITS | SEC_ALG_AES;
100 +               break;
101 +       }
102 +
103 +       return 0;
104 +}
105 +
106 +static inline void aes_cipher(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
107 +{
108 +       const struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
109 +
110 +       hw_crypto_lock();
111 +       hw_crypto_check();
112 +       hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
113 +
114 +       aes_hw_set_key(uctx->key, uctx->key_len);
115 +       aes_hw_cipher(out, in);
116 +
117 +       hw_crypto_unlock();
118 +}
119 +
120 +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
121 +{
122 +       aes_cipher(tfm, out, in, SEC_DIR_ENCRYPT);
123 +}
124 +
125 +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
126 +{
127 +       aes_cipher(tfm, out, in, SEC_DIR_DECRYPT);
128 +}
129 +
130 +static struct crypto_alg aes_alg = {
131 +       .cra_name               =       "aes",
132 +       .cra_driver_name        =       "aes-ubicom32",
133 +       .cra_priority           =       CRYPTO_UBICOM32_PRIORITY,
134 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
135 +       .cra_blocksize          =       AES_BLOCK_SIZE,
136 +       .cra_ctxsize            =       sizeof(struct ubicom32_aes_ctx),
137 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
138 +       .cra_module             =       THIS_MODULE,
139 +       .cra_list               =       LIST_HEAD_INIT(aes_alg.cra_list),
140 +       .cra_u                  =       {
141 +               .cipher = {
142 +                       .cia_min_keysize        =       AES_MIN_KEY_SIZE,
143 +                       .cia_max_keysize        =       AES_MAX_KEY_SIZE,
144 +                       .cia_setkey             =       aes_set_key,
145 +                       .cia_encrypt            =       aes_encrypt,
146 +                       .cia_decrypt            =       aes_decrypt,
147 +               }
148 +       }
149 +};
150 +
151 +static void __ocm_text ecb_aes_crypt_loop(u8 *out, u8 *in, unsigned int n)
152 +{
153 +       while (likely(n)) {
154 +               aes_hw_cipher(out, in);
155 +               out += AES_BLOCK_SIZE;
156 +               in += AES_BLOCK_SIZE;
157 +               n -= AES_BLOCK_SIZE;
158 +       }
159 +}
160 +
161 +static int __ocm_text ecb_aes_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
162 +                        struct scatterlist *src, unsigned int nbytes, u32 extra_flags)
163 +{
164 +       const struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
165 +       int ret;
166 +
167 +       struct blkcipher_walk walk;
168 +       blkcipher_walk_init(&walk, dst, src, nbytes);
169 +       ret = blkcipher_walk_virt(desc, &walk);
170 +        if (ret) {
171 +                return ret;
172 +        }
173 +
174 +       hw_crypto_lock();
175 +       hw_crypto_check();
176 +
177 +        hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
178 +        aes_hw_set_key(uctx->key, uctx->key_len);
179 +
180 +       while (likely((nbytes = walk.nbytes))) {
181 +               /* only use complete blocks */
182 +               unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
183 +               u8 *out = walk.dst.virt.addr;
184 +               u8 *in = walk.src.virt.addr;
185 +
186 +               /* finish n/16 blocks */
187 +               ecb_aes_crypt_loop(out, in, n);
188 +
189 +               nbytes &= AES_BLOCK_SIZE - 1;
190 +               ret = blkcipher_walk_done(desc, &walk, nbytes);
191 +       }
192 +
193 +       hw_crypto_unlock();
194 +       return ret;
195 +}
196 +
197 +static int ecb_aes_encrypt(struct blkcipher_desc *desc,
198 +                          struct scatterlist *dst, struct scatterlist *src,
199 +                          unsigned int nbytes)
200 +{
201 +       return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT);
202 +}
203 +
204 +static int ecb_aes_decrypt(struct blkcipher_desc *desc,
205 +                          struct scatterlist *dst, struct scatterlist *src,
206 +                          unsigned int nbytes)
207 +{
208 +       return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT);
209 +}
210 +
211 +static struct crypto_alg ecb_aes_alg = {
212 +       .cra_name               =       "ecb(aes)",
213 +       .cra_driver_name        =       "ecb-aes-ubicom32",
214 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
215 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
216 +       .cra_blocksize          =       AES_BLOCK_SIZE,
217 +       .cra_ctxsize            =       sizeof(struct ubicom32_aes_ctx),
218 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
219 +       .cra_type               =       &crypto_blkcipher_type,
220 +       .cra_module             =       THIS_MODULE,
221 +       .cra_list               =       LIST_HEAD_INIT(ecb_aes_alg.cra_list),
222 +       .cra_u                  =       {
223 +               .blkcipher = {
224 +                       .min_keysize            =       AES_MIN_KEY_SIZE,
225 +                       .max_keysize            =       AES_MAX_KEY_SIZE,
226 +                       .setkey                 =       aes_set_key,
227 +                       .encrypt                =       ecb_aes_encrypt,
228 +                       .decrypt                =       ecb_aes_decrypt,
229 +               }
230 +       }
231 +};
232 +
233 +#if CRYPTO_UBICOM32_LOOP_ASM
234 +void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
235 +{
236 +       asm volatile (
237 +       "; set init. iv 4w                      \n\t"
238 +       "       move.4 0x50(%0), 0x0(%3)        \n\t"
239 +       "       move.4 0x54(%0), 0x4(%3)        \n\t"
240 +       "       move.4 0x58(%0), 0x8(%3)        \n\t"
241 +       "       move.4 0x5c(%0), 0xc(%3)        \n\t"
242 +       "                                       \n\t"
243 +       "; we know n > 0, so we can always      \n\t"
244 +       "; load the first block                 \n\t"
245 +       "; set input 4w                         \n\t"
246 +       "       move.4 0x30(%0), 0x0(%2)        \n\t"
247 +       "       move.4 0x34(%0), 0x4(%2)        \n\t"
248 +       "       move.4 0x38(%0), 0x8(%2)        \n\t"
249 +       "       move.4 0x3c(%0), 0xc(%2)        \n\t"
250 +       "                                       \n\t"
251 +       "; kickoff hw                           \n\t"
252 +       "       move.4 0x40(%0), %2             \n\t"
253 +       "                                       \n\t"
254 +       "; update n & flush                     \n\t"
255 +       "       add.4 %4, #-16, %4              \n\t"
256 +       "       pipe_flush 0                    \n\t"
257 +       "                                       \n\t"
258 +       "; while (n):  work on 2nd block        \n\t"
259 +       " 1:    lsl.4 d15, %4, #0x0             \n\t"
260 +       "       jmpeq.f 5f                      \n\t"
261 +       "                                       \n\t"
262 +       "; set input 4w (2nd)                   \n\t"
263 +       "       move.4 0x30(%0), 0x10(%2)       \n\t"
264 +       "       move.4 0x34(%0), 0x14(%2)       \n\t"
265 +       "       move.4 0x38(%0), 0x18(%2)       \n\t"
266 +       "       move.4 0x3c(%0), 0x1c(%2)       \n\t"
267 +       "                                       \n\t"
268 +       "; update n/in asap while waiting       \n\t"
269 +       "       add.4 %4, #-16, %4              \n\t"
270 +       "       move.4 d15, 16(%2)++            \n\t"
271 +       "                                       \n\t"
272 +       "; wait for the previous output         \n\t"
273 +       "       btst 0x04(%0), #0               \n\t"
274 +       "       jmpne.f -4                      \n\t"
275 +       "                                       \n\t"
276 +       "; read previous output                 \n\t"
277 +       "       move.4 0x0(%1), 0x50(%0)        \n\t"
278 +       "       move.4 0x4(%1), 0x54(%0)        \n\t"
279 +       "       move.4 0x8(%1), 0x58(%0)        \n\t"
280 +       "       move.4 0xc(%1), 0x5c(%0)        \n\t"
281 +       "                                       \n\t"
282 +       "; kick off hw for 2nd input            \n\t"
283 +       "       move.4 0x40(%0), %2             \n\t"
284 +       "                                       \n\t"
285 +       "; update out asap                      \n\t"
286 +       "       move.4 d15, 16(%1)++            \n\t"
287 +       "                                       \n\t"
288 +       "; go back to loop                      \n\t"
289 +       "       jmpt 1b                         \n\t"
290 +       "                                       \n\t"
291 +       "; wait for last output                 \n\t"
292 +       " 5:    btst 0x04(%0), #0               \n\t"
293 +        "       jmpne.f -4                      \n\t"
294 +        "                                       \n\t"
295 +       "; read last output                     \n\t"
296 +       "       move.4 0x0(%1), 0x50(%0)        \n\t"
297 +       "       move.4 0x4(%1), 0x54(%0)        \n\t"
298 +       "       move.4 0x8(%1), 0x58(%0)        \n\t"
299 +       "       move.4 0xc(%1), 0x5c(%0)        \n\t"
300 +        "                                       \n\t"
301 +       "; copy out iv                          \n\t"
302 +       "       move.4 0x0(%3), 0x50(%0)        \n\t"
303 +       "       move.4 0x4(%3), 0x54(%0)        \n\t"
304 +       "       move.4 0x8(%3), 0x58(%0)        \n\t"
305 +       "       move.4 0xc(%3), 0x5c(%0)        \n\t"
306 +        "                                       \n\t"
307 +               :
308 +               : "a" (SEC_BASE), "a" (out), "a" (in), "a" (iv), "d" (n)
309 +               : "d15", "cc"
310 +       );
311 +}
312 +
313 +#else
314 +
315 +static void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
316 +{
317 +       aes_hw_set_iv(iv);
318 +       while (likely(n)) {
319 +               aes_hw_cipher(out, in);
320 +               out += AES_BLOCK_SIZE;
321 +               in += AES_BLOCK_SIZE;
322 +               n -= AES_BLOCK_SIZE;
323 +       }
324 +       SEC_COPY_4W(iv, out - AES_BLOCK_SIZE);
325 +}
326 +
327 +#endif
328 +
329 +static void __ocm_text cbc_aes_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
330 +{
331 +        while (likely(n)) {
332 +                aes_hw_set_iv(iv);
333 +               SEC_COPY_4W(iv, in);
334 +                aes_hw_cipher(out, in);
335 +                out += AES_BLOCK_SIZE;
336 +                in += AES_BLOCK_SIZE;
337 +                n -= AES_BLOCK_SIZE;
338 +        }
339 +}
340 +
341 +static int __ocm_text cbc_aes_crypt(struct blkcipher_desc *desc,
342 +                           struct scatterlist *dst, struct scatterlist *src,
343 +                           unsigned int nbytes, u32 extra_flags)
344 +{
345 +       struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
346 +       int ret;
347 +
348 +        struct blkcipher_walk walk;
349 +        blkcipher_walk_init(&walk, dst, src, nbytes);
350 +       ret = blkcipher_walk_virt(desc, &walk);
351 +       if (unlikely(ret)) {
352 +               return ret;
353 +       }
354 +
355 +        hw_crypto_lock();
356 +       hw_crypto_check();
357 +
358 +        hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
359 +        aes_hw_set_key(uctx->key, uctx->key_len);
360 +
361 +       while (likely((nbytes = walk.nbytes))) {
362 +                /* only use complete blocks */
363 +                unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
364 +               if (likely(n)) {
365 +                       u8 *out = walk.dst.virt.addr;
366 +                       u8 *in = walk.src.virt.addr;
367 +
368 +                       if (extra_flags & SEC_DIR_ENCRYPT) {
369 +                               cbc_aes_encrypt_loop(out, in, walk.iv, n);
370 +                       } else {
371 +                               cbc_aes_decrypt_loop(out, in, walk.iv, n);
372 +                       }
373 +               }
374 +
375 +               nbytes &= AES_BLOCK_SIZE - 1;
376 +                ret = blkcipher_walk_done(desc, &walk, nbytes);
377 +       }
378 +       hw_crypto_unlock();
379 +
380 +       return ret;
381 +}
382 +
383 +static int __ocm_text cbc_aes_encrypt(struct blkcipher_desc *desc,
384 +                          struct scatterlist *dst, struct scatterlist *src,
385 +                          unsigned int nbytes)
386 +{
387 +       return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT | SEC_CBC_SET);
388 +}
389 +
390 +static int __ocm_text cbc_aes_decrypt(struct blkcipher_desc *desc,
391 +                          struct scatterlist *dst, struct scatterlist *src,
392 +                          unsigned int nbytes)
393 +{
394 +       return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT | SEC_CBC_SET);
395 +}
396 +
397 +static struct crypto_alg cbc_aes_alg = {
398 +       .cra_name               =       "cbc(aes)",
399 +       .cra_driver_name        =       "cbc-aes-ubicom32",
400 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
401 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
402 +       .cra_blocksize          =       AES_BLOCK_SIZE,
403 +       .cra_ctxsize            =       sizeof(struct ubicom32_aes_ctx),
404 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
405 +       .cra_type               =       &crypto_blkcipher_type,
406 +       .cra_module             =       THIS_MODULE,
407 +       .cra_list               =       LIST_HEAD_INIT(cbc_aes_alg.cra_list),
408 +       .cra_u                  =       {
409 +               .blkcipher = {
410 +                       .min_keysize            =       AES_MIN_KEY_SIZE,
411 +                       .max_keysize            =       AES_MAX_KEY_SIZE,
412 +                       .ivsize                 =       AES_BLOCK_SIZE,
413 +                       .setkey                 =       aes_set_key,
414 +                       .encrypt                =       cbc_aes_encrypt,
415 +                       .decrypt                =       cbc_aes_decrypt,
416 +               }
417 +       }
418 +};
419 +
420 +static int __init aes_init(void)
421 +{
422 +       int ret;
423 +
424 +       hw_crypto_init();
425 +
426 +       ret = crypto_register_alg(&aes_alg);
427 +       if (ret)
428 +               goto aes_err;
429 +
430 +       ret = crypto_register_alg(&ecb_aes_alg);
431 +       if (ret)
432 +               goto ecb_aes_err;
433 +
434 +       ret = crypto_register_alg(&cbc_aes_alg);
435 +       if (ret)
436 +               goto cbc_aes_err;
437 +
438 +out:
439 +       return ret;
440 +
441 +cbc_aes_err:
442 +       crypto_unregister_alg(&ecb_aes_alg);
443 +ecb_aes_err:
444 +       crypto_unregister_alg(&aes_alg);
445 +aes_err:
446 +       goto out;
447 +}
448 +
449 +static void __exit aes_fini(void)
450 +{
451 +       crypto_unregister_alg(&cbc_aes_alg);
452 +       crypto_unregister_alg(&ecb_aes_alg);
453 +       crypto_unregister_alg(&aes_alg);
454 +}
455 +
456 +module_init(aes_init);
457 +module_exit(aes_fini);
458 +
459 +MODULE_ALIAS("aes");
460 +
461 +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
462 +MODULE_LICENSE("GPL");
463 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/crypto_des.h linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_des.h
464 --- linux-2.6.30.10/arch/ubicom32/crypto/crypto_des.h   1970-01-01 02:00:00.000000000 +0200
465 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_des.h       2009-12-11 11:45:11.000000000 +0200
466 @@ -0,0 +1,34 @@
467 +/*
468 + * arch/ubicom32/crypto/crypto_des.h
469 + *   Function for checking keys for the DES and Triple DES Encryption
470 + *   algorithms.
471 + *
472 + * (C) Copyright 2009, Ubicom, Inc.
473 + *
474 + * This file is part of the Ubicom32 Linux Kernel Port.
475 + *
476 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
477 + * it and/or modify it under the terms of the GNU General Public License
478 + * as published by the Free Software Foundation, either version 2 of the
479 + * License, or (at your option) any later version.
480 + *
481 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
482 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
483 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
484 + * the GNU General Public License for more details.
485 + *
486 + * You should have received a copy of the GNU General Public License
487 + * along with the Ubicom32 Linux Kernel Port.  If not,
488 + * see <http://www.gnu.org/licenses/>.
489 + *
490 + * Ubicom32 implementation derived from (with many thanks):
491 + *   arch/m68knommu
492 + *   arch/blackfin
493 + *   arch/parisc
494 + */
495 +#ifndef __CRYPTO_DES_H__
496 +#define __CRYPTO_DES_H__
497 +
498 +extern int crypto_des_check_key(const u8*, unsigned int, u32*);
499 +
500 +#endif /* __CRYPTO_DES_H__ */
501 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.c
502 --- linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.c      1970-01-01 02:00:00.000000000 +0200
503 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.c  2009-12-11 11:45:11.000000000 +0200
504 @@ -0,0 +1,50 @@
505 +/*
506 + * arch/ubicom32/crypto/crypto_ubicom32.c
507 + *   Generic code to support ubicom32 hardware crypto accelerator
508 + *
509 + * (C) Copyright 2009, Ubicom, Inc.
510 + *
511 + * This file is part of the Ubicom32 Linux Kernel Port.
512 + *
513 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
514 + * it and/or modify it under the terms of the GNU General Public License
515 + * as published by the Free Software Foundation, either version 2 of the
516 + * License, or (at your option) any later version.
517 + *
518 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
519 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
520 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
521 + * the GNU General Public License for more details.
522 + *
523 + * You should have received a copy of the GNU General Public License
524 + * along with the Ubicom32 Linux Kernel Port.  If not,
525 + * see <http://www.gnu.org/licenses/>.
526 + *
527 + * Ubicom32 implementation derived from (with many thanks):
528 + *   arch/m68knommu
529 + *   arch/blackfin
530 + *   arch/parisc
531 + */
532 +#include "crypto_ubicom32.h"
533 +
534 +spinlock_t crypto_ubicom32_lock;
535 +bool crypto_ubicom32_inited = false;
536 +volatile bool crypto_ubicom32_on = false;
537 +volatile unsigned long crypto_ubicom32_last_use;
538 +
539 +struct timer_list crypto_ubicom32_ps_timer;
540 +void crypto_ubicom32_ps_check(unsigned long data)
541 +{
542 +       unsigned long idle_time = msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS);
543 +
544 +       BUG_ON(!crypto_ubicom32_on);
545 +
546 +       if (((jiffies - crypto_ubicom32_last_use) > idle_time) && spin_trylock_bh(&crypto_ubicom32_lock)) {
547 +                hw_crypto_turn_off();
548 +                spin_unlock_bh(&crypto_ubicom32_lock);
549 +               return;
550 +       }
551 +
552 +       /* keep monitoring */
553 +       hw_crypto_ps_start();
554 +}
555 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.h linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.h
556 --- linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.h      1970-01-01 02:00:00.000000000 +0200
557 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.h  2009-12-11 11:45:11.000000000 +0200
558 @@ -0,0 +1,346 @@
559 +/*
560 + * arch/ubicom32/crypto/crypto_ubicom32.h
561 + *   Support for Ubicom32 cryptographic instructions.
562 + *
563 + * (C) Copyright 2009, Ubicom, Inc.
564 + *
565 + * This file is part of the Ubicom32 Linux Kernel Port.
566 + *
567 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
568 + * it and/or modify it under the terms of the GNU General Public License
569 + * as published by the Free Software Foundation, either version 2 of the
570 + * License, or (at your option) any later version.
571 + *
572 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
573 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
574 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
575 + * the GNU General Public License for more details.
576 + *
577 + * You should have received a copy of the GNU General Public License
578 + * along with the Ubicom32 Linux Kernel Port.  If not,
579 + * see <http://www.gnu.org/licenses/>.
580 + *
581 + * Ubicom32 implementation derived from (with many thanks):
582 + *   arch/m68knommu
583 + *   arch/blackfin
584 + *   arch/parisc
585 + */
586 +#ifndef _CRYPTO_ARCH_UBICOM32_CRYPT_H
587 +#define _CRYPTO_ARCH_UBICOM32_CRYPT_H
588 +
589 +#include <linux/module.h>
590 +#include <linux/kernel.h>
591 +#include <linux/jiffies.h>
592 +#include <linux/timer.h>
593 +#include <linux/spinlock.h>
594 +#include <asm/errno.h>
595 +#include <asm/io.h>
596 +#include <asm/ip5000.h>
597 +
598 +#define CRYPTO_UBICOM32_LOOP_ASM 1
599 +#define CRYPTO_UBICOM32_ALIGNMENT 4
600 +#define SEC_ALIGNED(p) (((u32)p & 3) == 0)
601 +
602 +#define SEC_BASE               SECURITY_BASE
603 +#define SEC_KEY_OFFSET         SECURITY_KEY_VALUE(0)
604 +#define SEC_INPUT_OFFSET       SECURITY_KEY_IN(0)
605 +#define SEC_OUTPUT_OFFSET      SECURITY_KEY_OUT(0)
606 +#define SEC_HASH_OFFSET                SECURITY_KEY_HASH(0)
607 +
608 +#define SEC_KEY_128_BITS       SECURITY_CTRL_KEY_SIZE(0)
609 +#define SEC_KEY_192_BITS       SECURITY_CTRL_KEY_SIZE(1)
610 +#define SEC_KEY_256_BITS       SECURITY_CTRL_KEY_SIZE(2)
611 +
612 +#define SEC_HASH_NONE          SECURITY_CTRL_HASH_ALG_NONE
613 +#define SEC_HASH_MD5           SECURITY_CTRL_HASH_ALG_MD5
614 +#define SEC_HASH_SHA1          SECURITY_CTRL_HASH_ALG_SHA1
615 +
616 +#define SEC_CBC_SET            SECURITY_CTRL_CBC
617 +#define SEC_CBC_NONE           0
618 +
619 +#define SEC_ALG_AES            SECURITY_CTRL_CIPHER_ALG_AES
620 +#define SEC_ALG_NONE           SECURITY_CTRL_CIPHER_ALG_NONE
621 +#define SEC_ALG_DES            SECURITY_CTRL_CIPHER_ALG_DES
622 +#define SEC_ALG_3DES           SECURITY_CTRL_CIPHER_ALG_3DES
623 +
624 +#define SEC_DIR_ENCRYPT                SECURITY_CTRL_ENCIPHER
625 +#define SEC_DIR_DECRYPT                0
626 +
627 +#define CRYPTO_UBICOM32_PRIORITY 300
628 +#define CRYPTO_UBICOM32_COMPOSITE_PRIORITY 400
629 +
630 +#define HW_CRYPTO_PS_MAX_IDLE_MS 100    /* idle time (ms) before shuting down sm */
631 +
632 +extern spinlock_t crypto_ubicom32_lock;
633 +extern bool crypto_ubicom32_inited;
634 +extern volatile bool crypto_ubicom32_on;
635 +extern volatile unsigned long crypto_ubicom32_last_use;
636 +extern struct timer_list crypto_ubicom32_ps_timer;
637 +extern void crypto_ubicom32_ps_check(unsigned long data);
638 +
639 +#define SEC_COPY_2W(t, s)                              \
640 +       asm volatile (                                  \
641 +       "       move.4 0(%0), 0(%1)             \n\t"   \
642 +       "       move.4 4(%0), 4(%1)             \n\t"   \
643 +                                                       \
644 +               :                                       \
645 +               : "a" (t), "a" (s)                      \
646 +       )
647 +
648 +#define SEC_COPY_4W(t, s)                              \
649 +       asm volatile (                                  \
650 +       "       move.4 0(%0), 0(%1)             \n\t"   \
651 +       "       move.4 4(%0), 4(%1)             \n\t"   \
652 +       "       move.4 8(%0), 8(%1)             \n\t"   \
653 +       "       move.4 12(%0), 12(%1)           \n\t"   \
654 +               :                                       \
655 +               : "a" (t), "a" (s)                      \
656 +       )
657 +
658 +#define SEC_COPY_5W(t, s)                              \
659 +       asm volatile (                                  \
660 +       "       move.4 0(%0), 0(%1)             \n\t"   \
661 +       "       move.4 4(%0), 4(%1)             \n\t"   \
662 +       "       move.4 8(%0), 8(%1)             \n\t"   \
663 +       "       move.4 12(%0), 12(%1)           \n\t"   \
664 +       "       move.4 16(%0), 16(%1)           \n\t"   \
665 +               :                                       \
666 +               : "a" (t), "a" (s)                      \
667 +       )
668 +
669 +#define SEC_SET_KEY_2W(x)                              \
670 +       asm volatile (                                  \
671 +       "       ; write key to Security Keyblock \n\t"  \
672 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
673 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
674 +               :                                       \
675 +               : "a" (SECURITY_BASE), "a" (x)          \
676 +       )
677 +
678 +#define SEC_SET_KEY_4W(x) \
679 +       asm volatile ( \
680 +       "       ; write key to Security Keyblock \n\t"  \
681 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
682 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
683 +       "       move.4 0x18(%0), 8(%1)          \n\t"   \
684 +       "       move.4 0x1c(%0), 12(%1)         \n\t"   \
685 +               :                                       \
686 +               : "a"(SECURITY_BASE), "a"(x)            \
687 +       )
688 +
689 +#define SEC_SET_KEY_6W(x)                              \
690 +       asm volatile (                                  \
691 +       "       ; write key to Security Keyblock \n\t"  \
692 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
693 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
694 +       "       move.4 0x18(%0), 8(%1)          \n\t"   \
695 +       "       move.4 0x1c(%0), 12(%1)         \n\t"   \
696 +       "       move.4 0x20(%0), 16(%1)         \n\t"   \
697 +       "       move.4 0x24(%0), 20(%1)         \n\t"   \
698 +               :                                       \
699 +               : "a" (SECURITY_BASE), "a" (x)          \
700 +       )
701 +
702 +#define SEC_SET_KEY_8W(x)                              \
703 +       asm volatile (                                  \
704 +       "       ; write key to Security Keyblock \n\t"  \
705 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
706 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
707 +       "       move.4 0x18(%0), 8(%1)          \n\t"   \
708 +       "       move.4 0x1c(%0), 12(%1)         \n\t"   \
709 +       "       move.4 0x20(%0), 16(%1)         \n\t"   \
710 +       "       move.4 0x24(%0), 20(%1)         \n\t"   \
711 +       "       move.4 0x28(%0), 24(%1)         \n\t"   \
712 +       "       move.4 0x2c(%0), 28(%1)         \n\t"   \
713 +               :                                       \
714 +               : "a" (SECURITY_BASE), "a" (x)          \
715 +       )
716 +
717 +#define SEC_SET_KEY_64(k)      SEC_SET_KEY_2W(k)
718 +#define SEC_SET_KEY_128(k)     SEC_SET_KEY_4W(k)
719 +#define SEC_SET_KEY_192(k)     SEC_SET_KEY_6W(k)
720 +#define SEC_SET_KEY_256(k)     SEC_SET_KEY_8W(k)
721 +
722 +#define DES_SET_KEY(x)                 SEC_SET_KEY_64(x)
723 +#define DES3_SET_KEY(x)        SEC_SET_KEY_192(x)
724 +
725 +#define SEC_SET_INPUT_2W(x)                            \
726 +       asm volatile (                                  \
727 +       "       ; write key to Security Keyblock \n\t"  \
728 +       "       move.4 0x30(%0), 0(%1)          \n\t"   \
729 +       "       move.4 0x34(%0), 4(%1)          \n\t"   \
730 +               :                                       \
731 +               : "a" (SECURITY_BASE), "a" (x)          \
732 +       )
733 +
734 +#define SEC_GET_OUTPUT_2W(x)                           \
735 +       asm volatile (                                  \
736 +       "       ; write key to Security Keyblock \n\t"  \
737 +       "       move.4 0(%1), 0x50(%0)          \n\t"   \
738 +       "       move.4 4(%1), 0x54(%0)          \n\t"   \
739 +               :                                       \
740 +               : "a" (SECURITY_BASE), "a" (x)          \
741 +       )
742 +
743 +#define SEC_SET_INPUT_4W(x) \
744 +       asm volatile ( \
745 +       "       ; write key to Security Keyblock \n\t"  \
746 +       "       move.4 0x30(%0), 0(%1)          \n\t"   \
747 +       "       move.4 0x34(%0), 4(%1)          \n\t"   \
748 +       "       move.4 0x38(%0), 8(%1)          \n\t"   \
749 +       "       move.4 0x3c(%0), 12(%1)         \n\t"   \
750 +               :                                       \
751 +               : "a" (SECURITY_BASE), "a" (x)          \
752 +       )
753 +
754 +#define SEC_GET_OUTPUT_4W(x)                           \
755 +       asm volatile (                                  \
756 +       "       ; read output from Security Keyblock \n\t" \
757 +       "       move.4 0(%1), 0x50(%0)          \n\t"   \
758 +       "       move.4 4(%1), 0x54(%0)          \n\t"   \
759 +       "       move.4 8(%1), 0x58(%0)          \n\t"   \
760 +       "       move.4 12(%1), 0x5c(%0)         \n\t"   \
761 +               :                                       \
762 +               : "a" (SECURITY_BASE), "a" (x)          \
763 +       )
764 +
765 +#define SEC_SET_IV_4W(x)                               \
766 +       asm volatile (                                  \
767 +       "       ; write IV to Security Keyblock  \n\t"  \
768 +       "       move.4 0x50(%0), 0(%1)          \n\t"   \
769 +       "       move.4 0x54(%0), 4(%1)          \n\t"   \
770 +       "       move.4 0x58(%0), 8(%1)          \n\t"   \
771 +       "       move.4 0x5c(%0), 12(%1)         \n\t"   \
772 +               :                                       \
773 +               : "a" (SECURITY_BASE), "a" (x)          \
774 +       )
775 +
776 +#define SEC_PIPE_FLUSH() asm volatile ( " pipe_flush 0 \n\t" )
777 +
778 +static inline void hw_crypto_set_ctrl(uint32_t c)
779 +{
780 +       asm volatile (
781 +       "       move.4  0(%0), %1               \n\t"
782 +               :
783 +               : "a" (SECURITY_BASE + SECURITY_CTRL), "d" (c)
784 +       );
785 +}
786 +
787 +static inline void hw_crypto_ps_start(void)
788 +{
789 +       crypto_ubicom32_ps_timer.expires = jiffies + msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS >> 1);
790 +       add_timer(&crypto_ubicom32_ps_timer);
791 +}
792 +
793 +static inline void hw_crypto_turn_on(void)
794 +{
795 +       asm volatile (
796 +       "       moveai  A4, %0                  \n\t"
797 +       "       bset    0x0(A4), 0x0(A4), %1    \n\t"
798 +       "       cycles 11                       \n\t"
799 +               :
800 +               : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
801 +               : "a4", "cc"
802 +       );
803 +       crypto_ubicom32_on = true;
804 +}
805 +
806 +static inline void hw_crypto_turn_off(void)
807 +{
808 +       asm volatile (
809 +       "       moveai  A4, %0                  \n\t"
810 +       "       bclr    0x0(A4), 0x0(A4), %1    \n\t"
811 +               :
812 +               : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
813 +               : "a4", "cc"
814 +       );
815 +       crypto_ubicom32_on = false;
816 +}
817 +
818 +/*
819 + * hw_crypto_check
820 + *     Most probably hw crypto is called in clusters and it makes no sense to turn it off
821 + *     and on and waster 13 cycles every time.
822 + */
823 +static inline void hw_crypto_check(void)
824 +{
825 +       if (likely(crypto_ubicom32_on)) {
826 +               return;
827 +       }
828 +       crypto_ubicom32_last_use = jiffies;
829 +       hw_crypto_turn_on();
830 +       hw_crypto_ps_start();
831 +}
832 +
833 +/*
834 + * hw_crypto_ps_init
835 + *     Init power save timer
836 + */
837 +static inline void hw_crypto_ps_init(void)
838 +{
839 +       init_timer_deferrable(&crypto_ubicom32_ps_timer);
840 +       crypto_ubicom32_ps_timer.function = crypto_ubicom32_ps_check;
841 +       crypto_ubicom32_ps_timer.data = 0;
842 +}
843 +
844 +/*
845 + * hw_crypto_init()
846 + *      Initialize OCP security module lock and disables its clock.
847 + */
848 +static inline void hw_crypto_init(void)
849 +{
850 +       if (!crypto_ubicom32_inited) {
851 +               crypto_ubicom32_inited = true;
852 +               spin_lock_init(&crypto_ubicom32_lock);
853 +               hw_crypto_ps_init();
854 +               hw_crypto_turn_off();
855 +       }
856 +}
857 +
858 +/*
859 + * hw_crypto_lock()
860 + *      Locks the OCP security module and enables its clock.
861 + */
862 +static inline void hw_crypto_lock(void)
863 +{
864 +       spin_lock_bh(&crypto_ubicom32_lock);
865 +}
866 +
867 +/*
868 + * hw_crypto_unlock()
869 + *      Unlocks the OCP security module and disables its clock.
870 + */
871 +static inline void hw_crypto_unlock(void)
872 +{
873 +       crypto_ubicom32_last_use = jiffies;
874 +       spin_unlock_bh(&crypto_ubicom32_lock);
875 +}
876 +
877 +#define CONFIG_CRYPTO_UBICOM32_DEBUG 1
878 +
879 +#ifdef CONFIG_CRYPTO_UBICOM32_DEBUG
880 +static inline void hex_dump(void *buf, int b_size, const char *msg)
881 +{
882 +       u8 *b = (u8 *)buf;
883 +       int i;
884 +       if (msg) {
885 +               printk("%s:\t", msg);
886 +       }
887 +
888 +       for (i=0; i < b_size; i++) {
889 +               printk("%02x ", b[i]);
890 +               if ((i & 3) == 3) {
891 +                       printk(" ");
892 +               }
893 +               if ((i & 31) == 31) {
894 +                       printk("\n");
895 +               }
896 +       }
897 +       printk("\n");
898 +}
899 +#define UBICOM32_SEC_DUMP(a, b, c) hex_dump(a, b, c)
900 +#else
901 +#define UBICOM32_SEC_DUMP(a, b, c)
902 +#endif
903 +
904 +#endif /* _CRYPTO_ARCH_UBICOM32_CRYPT_H */
905 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/des_check_key.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_check_key.c
906 --- linux-2.6.30.10/arch/ubicom32/crypto/des_check_key.c        1970-01-01 02:00:00.000000000 +0200
907 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_check_key.c    2009-12-11 11:45:11.000000000 +0200
908 @@ -0,0 +1,148 @@
909 +/*
910 + * arch/ubicom32/crypto/des_check_key.c
911 + *   Ubicom32 architecture function for checking keys for the DES and
912 + *   Tripple DES Encryption algorithms.
913 + *
914 + * (C) Copyright 2009, Ubicom, Inc.
915 + *
916 + * Originally released as descore by Dana L. How <how@isl.stanford.edu>.
917 + * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel.
918 + * Derived from Cryptoapi and Nettle implementations, adapted for in-place
919 + * scatterlist interface.  Changed LGPL to GPL per section 3 of the LGPL.
920 + *
921 + * s390 Version:
922 + *   Copyright IBM Corp. 2003
923 + *   Author(s): Thomas Spatzier
924 + *             Jan Glauber (jan.glauber@de.ibm.com)
925 + *
926 + * Derived from "crypto/des.c"
927 + *   Copyright (c) 1992 Dana L. How.
928 + *   Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de>
929 + *   Copyright (c) Gisle Sflensminde <gisle@ii.uib.no>
930 + *   Copyright (C) 2001 Niels Mvller.
931 + *   Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
932 + *
933 + * This file is part of the Ubicom32 Linux Kernel Port.
934 + *
935 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
936 + * it and/or modify it under the terms of the GNU General Public License
937 + * as published by the Free Software Foundation, either version 2 of the
938 + * License, or (at your option) any later version.
939 + *
940 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
941 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
942 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
943 + * the GNU General Public License for more details.
944 + *
945 + * You should have received a copy of the GNU General Public License
946 + * along with the Ubicom32 Linux Kernel Port.  If not,
947 + * see <http://www.gnu.org/licenses/>.
948 + *
949 + * Ubicom32 implementation derived from (with many thanks):
950 + *   arch/m68knommu
951 + *   arch/blackfin
952 + *   arch/parisc
953 + */
954 +#include <linux/init.h>
955 +#include <linux/module.h>
956 +#include <linux/errno.h>
957 +#include <linux/crypto.h>
958 +#include "crypto_des.h"
959 +
960 +#define ROR(d,c,o)     ((d) = (d) >> (c) | (d) << (o))
961 +
962 +static const u8 parity[] = {
963 +       8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3,
964 +       0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
965 +       0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
966 +       8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
967 +       0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
968 +       8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
969 +       8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
970 +       4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8,
971 +};
972 +
973 +/*
974 + * RFC2451: Weak key checks SHOULD be performed.
975 + */
976 +int
977 +crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags)
978 +{
979 +       u32 n, w;
980 +
981 +       n  = parity[key[0]]; n <<= 4;
982 +       n |= parity[key[1]]; n <<= 4;
983 +       n |= parity[key[2]]; n <<= 4;
984 +       n |= parity[key[3]]; n <<= 4;
985 +       n |= parity[key[4]]; n <<= 4;
986 +       n |= parity[key[5]]; n <<= 4;
987 +       n |= parity[key[6]]; n <<= 4;
988 +       n |= parity[key[7]];
989 +       w = 0x88888888L;
990 +
991 +       if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
992 +           && !((n - (w >> 3)) & w)) {  /* 1 in 10^10 keys passes this test */
993 +               if (n < 0x41415151) {
994 +                       if (n < 0x31312121) {
995 +                               if (n < 0x14141515) {
996 +                                       /* 01 01 01 01 01 01 01 01 */
997 +                                       if (n == 0x11111111) goto weak;
998 +                                       /* 01 1F 01 1F 01 0E 01 0E */
999 +                                       if (n == 0x13131212) goto weak;
1000 +                               } else {
1001 +                                       /* 01 E0 01 E0 01 F1 01 F1 */
1002 +                                       if (n == 0x14141515) goto weak;
1003 +                                       /* 01 FE 01 FE 01 FE 01 FE */
1004 +                                       if (n == 0x16161616) goto weak;
1005 +                               }
1006 +                       } else {
1007 +                               if (n < 0x34342525) {
1008 +                                       /* 1F 01 1F 01 0E 01 0E 01 */
1009 +                                       if (n == 0x31312121) goto weak;
1010 +                                       /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */
1011 +                                       if (n == 0x33332222) goto weak;
1012 +                               } else {
1013 +                                       /* 1F E0 1F E0 0E F1 0E F1 */
1014 +                                       if (n == 0x34342525) goto weak;
1015 +                                       /* 1F FE 1F FE 0E FE 0E FE */
1016 +                                       if (n == 0x36362626) goto weak;
1017 +                               }
1018 +                       }
1019 +               } else {
1020 +                       if (n < 0x61616161) {
1021 +                               if (n < 0x44445555) {
1022 +                                       /* E0 01 E0 01 F1 01 F1 01 */
1023 +                                       if (n == 0x41415151) goto weak;
1024 +                                       /* E0 1F E0 1F F1 0E F1 0E */
1025 +                                       if (n == 0x43435252) goto weak;
1026 +                               } else {
1027 +                                       /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */
1028 +                                       if (n == 0x44445555) goto weak;
1029 +                                       /* E0 FE E0 FE F1 FE F1 FE */
1030 +                                       if (n == 0x46465656) goto weak;
1031 +                               }
1032 +                       } else {
1033 +                               if (n < 0x64646565) {
1034 +                                       /* FE 01 FE 01 FE 01 FE 01 */
1035 +                                       if (n == 0x61616161) goto weak;
1036 +                                       /* FE 1F FE 1F FE 0E FE 0E */
1037 +                                       if (n == 0x63636262) goto weak;
1038 +                               } else {
1039 +                                       /* FE E0 FE E0 FE F1 FE F1 */
1040 +                                       if (n == 0x64646565) goto weak;
1041 +                                       /* FE FE FE FE FE FE FE FE */
1042 +                                       if (n == 0x66666666) goto weak;
1043 +                               }
1044 +                       }
1045 +               }
1046 +       }
1047 +       return 0;
1048 +weak:
1049 +       *flags |= CRYPTO_TFM_RES_WEAK_KEY;
1050 +       return -EINVAL;
1051 +}
1052 +
1053 +EXPORT_SYMBOL(crypto_des_check_key);
1054 +
1055 +MODULE_LICENSE("GPL");
1056 +MODULE_DESCRIPTION("Key Check function for DES &  DES3 Cipher Algorithms");
1057 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/des_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_ubicom32.c
1058 --- linux-2.6.30.10/arch/ubicom32/crypto/des_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
1059 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_ubicom32.c     2009-12-11 11:45:11.000000000 +0200
1060 @@ -0,0 +1,761 @@
1061 +/*
1062 + * arch/ubicom32/crypto/des_ubicom32.c
1063 + *   Ubicom32 implementation of the DES Cipher Algorithm.
1064 + *
1065 + * (C) Copyright 2009, Ubicom, Inc.
1066 + *
1067 + * This file is part of the Ubicom32 Linux Kernel Port.
1068 + *
1069 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1070 + * it and/or modify it under the terms of the GNU General Public License
1071 + * as published by the Free Software Foundation, either version 2 of the
1072 + * License, or (at your option) any later version.
1073 + *
1074 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1075 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1076 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1077 + * the GNU General Public License for more details.
1078 + *
1079 + * You should have received a copy of the GNU General Public License
1080 + * along with the Ubicom32 Linux Kernel Port.  If not,
1081 + * see <http://www.gnu.org/licenses/>.
1082 + *
1083 + * Ubicom32 implementation derived from (with many thanks):
1084 + *   arch/m68knommu
1085 + *   arch/blackfin
1086 + *   arch/parisc
1087 + */
1088 +#include <crypto/algapi.h>
1089 +#include <linux/init.h>
1090 +#include <linux/module.h>
1091 +
1092 +#include "crypto_ubicom32.h"
1093 +extern int crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags);
1094 +
1095 +#define DES_BLOCK_SIZE 8
1096 +#define DES_KEY_SIZE 8
1097 +
1098 +#define DES3_192_KEY_SIZE      (3 * DES_KEY_SIZE)
1099 +#define DES3_192_BLOCK_SIZE    DES_BLOCK_SIZE
1100 +
1101 +#define DES3_SUB_KEY(key, i)   (((u8 *)key) + (i * DES_KEY_SIZE))
1102 +
1103 +enum des_ops {
1104 +       DES_ENCRYPT,
1105 +       DES_DECRYPT,
1106 +
1107 +       DES3_EDE_ENCRYPT,
1108 +       DES3_EDE_DECRYPT,
1109 +
1110 +#ifdef DES3_EEE
1111 +       DES3_EEE_ENCRYPT,
1112 +       DES3_EEE_DECRYPT,
1113 +#endif
1114 +};
1115 +
1116 +struct ubicom32_des_ctx {
1117 +       u8 key[3 * DES_KEY_SIZE];
1118 +       u32 ctrl;
1119 +       int key_len;
1120 +};
1121 +
1122 +static inline void des_hw_set_key(const u8 *key, u8 key_len)
1123 +{
1124 +       /*
1125 +        * HW 3DES is not tested yet, use DES just as ipOS
1126 +        */
1127 +       DES_SET_KEY(key);
1128 +}
1129 +
1130 +static inline void des_hw_cipher(u8 *out, const u8 *in)
1131 +{
1132 +       SEC_SET_INPUT_2W(in);
1133 +
1134 +       asm volatile (
1135 +       "       ; start DES by writing 0x38(SECURITY_BASE)      \n\t"
1136 +       "       move.4 0x38(%0), #0x01                          \n\t"
1137 +       "       pipe_flush 0                                    \n\t"
1138 +       "                                                       \n\t"
1139 +       "       ; wait for the module to calculate the output   \n\t"
1140 +       "       btst 0x04(%0), #0                               \n\t"
1141 +       "       jmpne.f .-4                                     \n\t"
1142 +               :
1143 +               : "a" (SEC_BASE)
1144 +               : "cc"
1145 +       );
1146 +
1147 +       SEC_GET_OUTPUT_2W(out);
1148 +}
1149 +
1150 +
1151 +static void inline des3_hw_ede_encrypt(u8 *keys, u8 *out, const u8 *in)
1152 +{
1153 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1154 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1155 +       des_hw_cipher(out, in);
1156 +
1157 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1158 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1159 +       des_hw_cipher(out, out);
1160 +
1161 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1162 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1163 +       des_hw_cipher(out, out);
1164 +}
1165 +
1166 +static void inline des3_hw_ede_decrypt(u8 *keys, u8 *out, const u8 *in)
1167 +{
1168 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1169 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1170 +       des_hw_cipher(out, in);
1171 +
1172 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1173 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1174 +       des_hw_cipher(out, out);
1175 +
1176 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1177 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1178 +       des_hw_cipher(out, out);
1179 +}
1180 +
1181 +#ifdef DES3_EEE
1182 +static void inline des3_hw_eee_encrypt(u8 *keys, u8 *out, const u8 *in)
1183 +{
1184 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1185 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1186 +       des_hw_cipher(out, in);
1187 +
1188 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1189 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1190 +       des_hw_cipher(out, out);
1191 +
1192 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1193 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1194 +       des_hw_cipher(out, out);
1195 +}
1196 +
1197 +static void inline des3_hw_eee_decrypt(u8 *keys, u8 *out, const u8 *in)
1198 +{
1199 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1200 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1201 +       des_hw_cipher(out, in);
1202 +
1203 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1204 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1205 +       des_hw_cipher(out, out);
1206 +
1207 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1208 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1209 +       des_hw_cipher(out, out);
1210 +}
1211 +#endif
1212 +
1213 +static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
1214 +                     unsigned int keylen)
1215 +{
1216 +       struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1217 +       u32 *flags = &tfm->crt_flags;
1218 +       int ret;
1219 +
1220 +       /* test if key is valid (not a weak key) */
1221 +       ret = crypto_des_check_key(key, keylen, flags);
1222 +       if (ret == 0) {
1223 +               memcpy(dctx->key, key, keylen);
1224 +               dctx->key_len = keylen;
1225 +               //dctx->ctrl = (keylen == DES_KEY_SIZE) ? SEC_ALG_DES : SEC_ALG_3DES
1226 +               /* 2DES and 3DES are both implemented with DES hw function */
1227 +               dctx->ctrl = SEC_ALG_DES;
1228 +       }
1229 +       return ret;
1230 +}
1231 +
1232 +static inline void des_cipher_1b(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
1233 +{
1234 +       const struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1235 +
1236 +       hw_crypto_lock();
1237 +       hw_crypto_check();
1238 +       hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
1239 +
1240 +       des_hw_set_key(uctx->key, uctx->key_len);
1241 +       des_hw_cipher(out, in);
1242 +
1243 +       hw_crypto_unlock();
1244 +}
1245 +
1246 +static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1247 +{
1248 +       des_cipher_1b(tfm, out, in, SEC_DIR_ENCRYPT);
1249 +}
1250 +
1251 +static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1252 +{
1253 +       des_cipher_1b(tfm, out, in, SEC_DIR_DECRYPT);
1254 +}
1255 +
1256 +static struct crypto_alg des_alg = {
1257 +       .cra_name               =       "des",
1258 +       .cra_driver_name        =       "des-ubicom32",
1259 +       .cra_priority           =       CRYPTO_UBICOM32_PRIORITY,
1260 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
1261 +       .cra_blocksize          =       DES_BLOCK_SIZE,
1262 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1263 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1264 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1265 +       .cra_module             =       THIS_MODULE,
1266 +       .cra_list               =       LIST_HEAD_INIT(des_alg.cra_list),
1267 +       .cra_u                  = {
1268 +               .cipher = {
1269 +                       .cia_min_keysize        =       DES_KEY_SIZE,
1270 +                       .cia_max_keysize        =       DES_KEY_SIZE,
1271 +                       .cia_setkey             =       des_setkey,
1272 +                       .cia_encrypt            =       des_encrypt,
1273 +                       .cia_decrypt            =       des_decrypt,
1274 +               }
1275 +       }
1276 +};
1277 +
1278 +static void ecb_des_ciper_loop(u8 *out, u8 *in, unsigned int n)
1279 +{
1280 +       while (likely(n)) {
1281 +               des_hw_cipher(out, in);
1282 +               out += DES_BLOCK_SIZE;
1283 +               in += DES_BLOCK_SIZE;
1284 +               n -= DES_BLOCK_SIZE;
1285 +       }
1286 +}
1287 +
1288 +static void ecb_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1289 +{
1290 +       while (likely(n)) {
1291 +               des3_hw_ede_encrypt(keys, out, in);
1292 +
1293 +               out += DES_BLOCK_SIZE;
1294 +               in += DES_BLOCK_SIZE;
1295 +               n -= DES_BLOCK_SIZE;
1296 +       }
1297 +}
1298 +
1299 +static void ecb_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1300 +{
1301 +       while (likely(n)) {
1302 +               des3_hw_ede_decrypt(keys, out, in);
1303 +
1304 +               out += DES_BLOCK_SIZE;
1305 +               in += DES_BLOCK_SIZE;
1306 +               n -= DES_BLOCK_SIZE;
1307 +       }
1308 +}
1309 +
1310 +#ifdef DES3_EEE
1311 +static void ecb_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1312 +{
1313 +       while (likely(n)) {
1314 +               des3_hw_eee_encrypt(keys, out, in);
1315 +
1316 +               out += DES_BLOCK_SIZE;
1317 +               in += DES_BLOCK_SIZE;
1318 +               n -= DES_BLOCK_SIZE;
1319 +       }
1320 +}
1321 +
1322 +static void ecb_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1323 +{
1324 +       while (likely(n)) {
1325 +               des3_hw_eee_decrypt(keys, out, in);
1326 +
1327 +               out += DES_BLOCK_SIZE;
1328 +               in += DES_BLOCK_SIZE;
1329 +               n -= DES_BLOCK_SIZE;
1330 +       }
1331 +}
1332 +#endif
1333 +
1334 +static inline void ecb_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, unsigned int n)
1335 +{
1336 +       switch (op) {
1337 +       case DES_ENCRYPT:
1338 +       case DES_DECRYPT:
1339 +               /* set the right algo, direction and key once */
1340 +               hw_crypto_set_ctrl(SEC_ALG_DES | (op == DES_ENCRYPT ? SEC_DIR_ENCRYPT : 0));
1341 +               des_hw_set_key(uctx->key, uctx->key_len);
1342 +               ecb_des_ciper_loop(out, in, n);
1343 +               break;
1344 +
1345 +       case DES3_EDE_ENCRYPT:
1346 +               ecb_des3_ede_encrypt_loop(uctx->key, out, in, n);
1347 +               break;
1348 +
1349 +       case DES3_EDE_DECRYPT:
1350 +               ecb_des3_ede_decrypt_loop(uctx->key, out, in, n);
1351 +               break;
1352 +
1353 +#ifdef DES3_EEE
1354 +       case DES3_EEE_ENCRYPT:
1355 +               ecb_des3_eee_encrypt_loop(uctx->key, out, in, n);
1356 +               break;
1357 +
1358 +       case DES3_EEE_DECRYPT:
1359 +               ecb_des3_eee_decrypt_loop(uctx->key, out, in, n);
1360 +               break;
1361 +#endif
1362 +       }
1363 +}
1364 +
1365 +static inline void des_xor_2w(u32 *data, u32 *iv)
1366 +{
1367 +       data[0] ^= iv[0];
1368 +       data[1] ^= iv[1];
1369 +}
1370 +
1371 +static void cbc_des_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1372 +{
1373 +       while (likely(n)) {
1374 +               des_xor_2w((u32 *)in, (u32 *)iv);
1375 +               des_hw_cipher(out, in);
1376 +               SEC_COPY_2W(iv, out);
1377 +               out += DES_BLOCK_SIZE;
1378 +               in += DES_BLOCK_SIZE;
1379 +               n -= DES_BLOCK_SIZE;
1380 +       }
1381 +}
1382 +
1383 +static void cbc_des_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1384 +{
1385 +       u8 next_iv[DES_BLOCK_SIZE];
1386 +       while (likely(n)) {
1387 +               SEC_COPY_2W(next_iv, in);
1388 +               des_hw_cipher(out, in);
1389 +               des_xor_2w((u32 *)out, (u32 *)iv);
1390 +               SEC_COPY_2W(iv, next_iv);
1391 +
1392 +               out += DES_BLOCK_SIZE;
1393 +               in += DES_BLOCK_SIZE;
1394 +               n -= DES_BLOCK_SIZE;
1395 +       }
1396 +}
1397 +
1398 +static void cbc_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1399 +{
1400 +       while (likely(n)) {
1401 +               des_xor_2w((u32 *)in, (u32 *)iv);
1402 +               des3_hw_ede_encrypt(keys, out, in);
1403 +               SEC_COPY_2W(iv, out);
1404 +
1405 +               out += DES_BLOCK_SIZE;
1406 +               in += DES_BLOCK_SIZE;
1407 +               n -= DES_BLOCK_SIZE;
1408 +       }
1409 +}
1410 +
1411 +static void cbc_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1412 +{
1413 +       u8 next_iv[DES_BLOCK_SIZE];
1414 +       while (likely(n)) {
1415 +               SEC_COPY_2W(next_iv, in);
1416 +               des3_hw_ede_decrypt(keys, out, in);
1417 +               des_xor_2w((u32 *)out, (u32 *)iv);
1418 +               SEC_COPY_2W(iv, next_iv);
1419 +
1420 +               out += DES_BLOCK_SIZE;
1421 +               in += DES_BLOCK_SIZE;
1422 +               n -= DES_BLOCK_SIZE;
1423 +       }
1424 +}
1425 +
1426 +#ifdef DES3_EEE
1427 +static void cbc_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1428 +{
1429 +       while (likely(n)) {
1430 +               des_xor_2w((u32 *)in, (u32 *)iv);
1431 +               des3_hw_eee_encrypt(keys, out, in);
1432 +               SEC_COPY_2W(iv, out);
1433 +
1434 +               out += DES_BLOCK_SIZE;
1435 +               in += DES_BLOCK_SIZE;
1436 +               n -= DES_BLOCK_SIZE;
1437 +       }
1438 +}
1439 +
1440 +static void cbc_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1441 +{
1442 +       u8 next_iv[DES_BLOCK_SIZE];
1443 +       while (likely(n)) {
1444 +               SEC_COPY_2W(next_iv, in);
1445 +               des3_hw_eee_decrypt(keys, out, in);
1446 +               des_xor_2w((u32 *)out, (u32 *)iv);
1447 +               SEC_COPY_2W(iv, next_iv);
1448 +
1449 +               out += DES_BLOCK_SIZE;
1450 +               in += DES_BLOCK_SIZE;
1451 +               n -= DES_BLOCK_SIZE;
1452 +       }
1453 +}
1454 +#endif
1455 +
1456 +static inline void cbc_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, u8 *iv, unsigned int n)
1457 +{
1458 +       switch (op) {
1459 +       case DES_ENCRYPT:
1460 +               hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1461 +               des_hw_set_key(uctx->key, uctx->key_len);
1462 +               cbc_des_encrypt_loop(out, in, iv, n);
1463 +               break;
1464 +
1465 +       case DES_DECRYPT:
1466 +               /* set the right algo, direction and key once */
1467 +               hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1468 +               des_hw_set_key(uctx->key, uctx->key_len);
1469 +               cbc_des_decrypt_loop(out, in, iv, n);
1470 +               break;
1471 +
1472 +       case DES3_EDE_ENCRYPT:
1473 +               cbc_des3_ede_encrypt_loop(uctx->key, out, in, iv, n);
1474 +               break;
1475 +
1476 +       case DES3_EDE_DECRYPT:
1477 +               cbc_des3_ede_decrypt_loop(uctx->key, out, in, iv, n);
1478 +               break;
1479 +
1480 +#ifdef DES3_EEE
1481 +       case DES3_EEE_ENCRYPT:
1482 +               cbc_des3_eee_encrypt_loop(uctx->key, out, in, iv, n);
1483 +               break;
1484 +
1485 +       case DES3_EEE_DECRYPT:
1486 +               cbc_des3_eee_decrypt_loop(uctx->key, out, in, iv, n);
1487 +               break;
1488 +#endif
1489 +       }
1490 +}
1491 +
1492 +static int des_cipher(struct blkcipher_desc *desc, struct scatterlist *dst,
1493 +                     struct scatterlist *src, unsigned int nbytes, u32 extra_flags, enum des_ops op)
1494 +{
1495 +       struct ubicom32_des_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
1496 +       int ret;
1497 +
1498 +       struct blkcipher_walk walk;
1499 +       blkcipher_walk_init(&walk, dst, src, nbytes);
1500 +       ret = blkcipher_walk_virt(desc, &walk);
1501 +       if (ret) {
1502 +               return ret;
1503 +       }
1504 +
1505 +       hw_crypto_lock();
1506 +       hw_crypto_check();
1507 +
1508 +       while ((nbytes = walk.nbytes)) {
1509 +               /* only use complete blocks */
1510 +               unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
1511 +               u8 *out = walk.dst.virt.addr;
1512 +               u8 *in = walk.src.virt.addr;
1513 +
1514 +               /* finish n/16 blocks */
1515 +               if (extra_flags & SEC_CBC_SET) {
1516 +                       cbc_des_cipher_n(uctx, op, out, in, walk.iv, n);
1517 +               } else {
1518 +                       ecb_des_cipher_n(uctx, op, out, in, n);
1519 +               }
1520 +
1521 +               nbytes &= DES_BLOCK_SIZE - 1;
1522 +               ret = blkcipher_walk_done(desc, &walk, nbytes);
1523 +       }
1524 +
1525 +       hw_crypto_unlock();
1526 +       return ret;
1527 +}
1528 +
1529 +static int ecb_des_encrypt(struct blkcipher_desc *desc,
1530 +                          struct scatterlist *dst, struct scatterlist *src,
1531 +                          unsigned int nbytes)
1532 +{
1533 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_ENCRYPT);
1534 +}
1535 +
1536 +static int ecb_des_decrypt(struct blkcipher_desc *desc,
1537 +                          struct scatterlist *dst, struct scatterlist *src,
1538 +                          unsigned int nbytes)
1539 +{
1540 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_DECRYPT);
1541 +}
1542 +
1543 +static struct crypto_alg ecb_des_alg = {
1544 +       .cra_name               =       "ecb(des)",
1545 +       .cra_driver_name        =       "ecb-des-ubicom32",
1546 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1547 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1548 +       .cra_blocksize          =       DES_BLOCK_SIZE,
1549 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1550 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1551 +       .cra_type               =       &crypto_blkcipher_type,
1552 +       .cra_module             =       THIS_MODULE,
1553 +       .cra_list               =       LIST_HEAD_INIT(ecb_des_alg.cra_list),
1554 +       .cra_u                  = {
1555 +               .blkcipher = {
1556 +                       .min_keysize            =       DES_KEY_SIZE,
1557 +                       .max_keysize            =       DES_KEY_SIZE,
1558 +                       .setkey                 =       des_setkey,
1559 +                       .encrypt                =       ecb_des_encrypt,
1560 +                       .decrypt                =       ecb_des_decrypt,
1561 +               }
1562 +       }
1563 +};
1564 +
1565 +static int cbc_des_encrypt(struct blkcipher_desc *desc,
1566 +                          struct scatterlist *dst, struct scatterlist *src,
1567 +                          unsigned int nbytes)
1568 +{
1569 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_ENCRYPT);
1570 +}
1571 +
1572 +static int cbc_des_decrypt(struct blkcipher_desc *desc,
1573 +                          struct scatterlist *dst, struct scatterlist *src,
1574 +                          unsigned int nbytes)
1575 +{
1576 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_DECRYPT);
1577 +}
1578 +
1579 +static struct crypto_alg cbc_des_alg = {
1580 +       .cra_name               =       "cbc(des)",
1581 +       .cra_driver_name        =       "cbc-des-ubicom32",
1582 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1583 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1584 +       .cra_blocksize          =       DES_BLOCK_SIZE,
1585 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1586 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1587 +       .cra_type               =       &crypto_blkcipher_type,
1588 +       .cra_module             =       THIS_MODULE,
1589 +       .cra_list               =       LIST_HEAD_INIT(cbc_des_alg.cra_list),
1590 +       .cra_u                  = {
1591 +               .blkcipher = {
1592 +                       .min_keysize            =       DES_KEY_SIZE,
1593 +                       .max_keysize            =       DES_KEY_SIZE,
1594 +                       .ivsize                 =       DES_BLOCK_SIZE,
1595 +                       .setkey                 =       des_setkey,
1596 +                       .encrypt                =       cbc_des_encrypt,
1597 +                       .decrypt                =       cbc_des_decrypt,
1598 +               }
1599 +       }
1600 +};
1601 +
1602 +/*
1603 + * RFC2451:
1604 + *
1605 + *   For DES-EDE3, there is no known need to reject weak or
1606 + *   complementation keys.  Any weakness is obviated by the use of
1607 + *   multiple keys.
1608 + *
1609 + *   However, if the first two or last two independent 64-bit keys are
1610 + *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
1611 + *   same as DES.  Implementers MUST reject keys that exhibit this
1612 + *   property.
1613 + *
1614 + */
1615 +static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
1616 +                          unsigned int keylen)
1617 +{
1618 +       int i, ret;
1619 +       struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1620 +       const u8 *temp_key = key;
1621 +       u32 *flags = &tfm->crt_flags;
1622 +
1623 +       if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
1624 +           memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
1625 +                  DES_KEY_SIZE))) {
1626 +
1627 +               *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
1628 +               return -EINVAL;
1629 +       }
1630 +       for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
1631 +               ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
1632 +               if (ret < 0)
1633 +                       return ret;
1634 +       }
1635 +       memcpy(dctx->key, key, keylen);
1636 +       dctx->ctrl = SEC_ALG_DES;       //hw 3DES not working yet
1637 +       dctx->key_len = keylen;
1638 +       return 0;
1639 +}
1640 +
1641 +static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1642 +{
1643 +       struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1644 +
1645 +       hw_crypto_lock();
1646 +       hw_crypto_check();
1647 +
1648 +       des3_hw_ede_encrypt(uctx->key, dst, src);
1649 +
1650 +       hw_crypto_unlock();
1651 +}
1652 +
1653 +static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1654 +{
1655 +       struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1656 +
1657 +       hw_crypto_lock();
1658 +       hw_crypto_check();
1659 +
1660 +       des3_hw_ede_decrypt(uctx->key, dst, src);
1661 +
1662 +       hw_crypto_unlock();
1663 +}
1664 +
1665 +static struct crypto_alg des3_192_alg = {
1666 +       .cra_name               =       "des3_ede",
1667 +       .cra_driver_name        =       "des3_ede-ubicom32",
1668 +       .cra_priority           =       CRYPTO_UBICOM32_PRIORITY,
1669 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
1670 +       .cra_blocksize          =       DES3_192_BLOCK_SIZE,
1671 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1672 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1673 +       .cra_module             =       THIS_MODULE,
1674 +       .cra_list               =       LIST_HEAD_INIT(des3_192_alg.cra_list),
1675 +       .cra_u                  = {
1676 +               .cipher = {
1677 +                       .cia_min_keysize        =       DES3_192_KEY_SIZE,
1678 +                       .cia_max_keysize        =       DES3_192_KEY_SIZE,
1679 +                       .cia_setkey             =       des3_192_setkey,
1680 +                       .cia_encrypt            =       des3_192_encrypt,
1681 +                       .cia_decrypt            =       des3_192_decrypt,
1682 +               }
1683 +       }
1684 +};
1685 +
1686 +static int ecb_des3_192_encrypt(struct blkcipher_desc *desc,
1687 +                               struct scatterlist *dst,
1688 +                               struct scatterlist *src, unsigned int nbytes)
1689 +{
1690 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_ENCRYPT);
1691 +}
1692 +
1693 +static int ecb_des3_192_decrypt(struct blkcipher_desc *desc,
1694 +                               struct scatterlist *dst,
1695 +                               struct scatterlist *src, unsigned int nbytes)
1696 +{
1697 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_DECRYPT);
1698 +}
1699 +
1700 +static struct crypto_alg ecb_des3_192_alg = {
1701 +       .cra_name               =       "ecb(des3_ede)",
1702 +       .cra_driver_name        =       "ecb-des3_ede-ubicom32",
1703 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1704 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1705 +       .cra_blocksize          =       DES3_192_BLOCK_SIZE,
1706 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1707 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1708 +       .cra_type               =       &crypto_blkcipher_type,
1709 +       .cra_module             =       THIS_MODULE,
1710 +       .cra_list               =       LIST_HEAD_INIT(
1711 +                                               ecb_des3_192_alg.cra_list),
1712 +       .cra_u                  = {
1713 +               .blkcipher = {
1714 +                       .min_keysize            =       DES3_192_KEY_SIZE,
1715 +                       .max_keysize            =       DES3_192_KEY_SIZE,
1716 +                       .setkey                 =       des3_192_setkey,
1717 +                       .encrypt                =       ecb_des3_192_encrypt,
1718 +                       .decrypt                =       ecb_des3_192_decrypt,
1719 +               }
1720 +       }
1721 +};
1722 +
1723 +static int cbc_des3_192_encrypt(struct blkcipher_desc *desc,
1724 +                               struct scatterlist *dst,
1725 +                               struct scatterlist *src, unsigned int nbytes)
1726 +{
1727 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_ENCRYPT);
1728 +}
1729 +
1730 +static int cbc_des3_192_decrypt(struct blkcipher_desc *desc,
1731 +                               struct scatterlist *dst,
1732 +                               struct scatterlist *src, unsigned int nbytes)
1733 +{
1734 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_DECRYPT);
1735 +}
1736 +
1737 +static struct crypto_alg cbc_des3_192_alg = {
1738 +       .cra_name               =       "cbc(des3_ede)",
1739 +       .cra_driver_name        =       "cbc-des3_ede-ubicom32",
1740 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1741 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1742 +       .cra_blocksize          =       DES3_192_BLOCK_SIZE,
1743 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1744 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1745 +       .cra_type               =       &crypto_blkcipher_type,
1746 +       .cra_module             =       THIS_MODULE,
1747 +       .cra_list               =       LIST_HEAD_INIT(
1748 +                                               cbc_des3_192_alg.cra_list),
1749 +       .cra_u                  = {
1750 +               .blkcipher = {
1751 +                       .min_keysize            =       DES3_192_KEY_SIZE,
1752 +                       .max_keysize            =       DES3_192_KEY_SIZE,
1753 +                       .ivsize                 =       DES3_192_BLOCK_SIZE,
1754 +                       .setkey                 =       des3_192_setkey,
1755 +                       .encrypt                =       cbc_des3_192_encrypt,
1756 +                       .decrypt                =       cbc_des3_192_decrypt,
1757 +               }
1758 +       }
1759 +};
1760 +
1761 +static int init(void)
1762 +{
1763 +       int ret = 0;
1764 +
1765 +       hw_crypto_init();
1766 +
1767 +       ret = crypto_register_alg(&des_alg);
1768 +       if (ret)
1769 +               goto des_err;
1770 +       ret = crypto_register_alg(&ecb_des_alg);
1771 +       if (ret)
1772 +               goto ecb_des_err;
1773 +       ret = crypto_register_alg(&cbc_des_alg);
1774 +       if (ret)
1775 +               goto cbc_des_err;
1776 +
1777 +       ret = crypto_register_alg(&des3_192_alg);
1778 +       if (ret)
1779 +               goto des3_192_err;
1780 +       ret = crypto_register_alg(&ecb_des3_192_alg);
1781 +       if (ret)
1782 +               goto ecb_des3_192_err;
1783 +       ret = crypto_register_alg(&cbc_des3_192_alg);
1784 +       if (ret)
1785 +               goto cbc_des3_192_err;
1786 +
1787 +out:
1788 +       return ret;
1789 +
1790 +cbc_des3_192_err:
1791 +       crypto_unregister_alg(&ecb_des3_192_alg);
1792 +ecb_des3_192_err:
1793 +       crypto_unregister_alg(&des3_192_alg);
1794 +des3_192_err:
1795 +       crypto_unregister_alg(&cbc_des_alg);
1796 +cbc_des_err:
1797 +       crypto_unregister_alg(&ecb_des_alg);
1798 +ecb_des_err:
1799 +       crypto_unregister_alg(&des_alg);
1800 +des_err:
1801 +       goto out;
1802 +}
1803 +
1804 +static void __exit fini(void)
1805 +{
1806 +       crypto_unregister_alg(&cbc_des3_192_alg);
1807 +       crypto_unregister_alg(&ecb_des3_192_alg);
1808 +       crypto_unregister_alg(&des3_192_alg);
1809 +       crypto_unregister_alg(&cbc_des_alg);
1810 +       crypto_unregister_alg(&ecb_des_alg);
1811 +       crypto_unregister_alg(&des_alg);
1812 +}
1813 +
1814 +module_init(init);
1815 +module_exit(fini);
1816 +
1817 +MODULE_ALIAS("des");
1818 +MODULE_ALIAS("des3_ede");
1819 +
1820 +MODULE_LICENSE("GPL");
1821 +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1822 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/Makefile linux-2.6.30.10-ubi/arch/ubicom32/crypto/Makefile
1823 --- linux-2.6.30.10/arch/ubicom32/crypto/Makefile       1970-01-01 02:00:00.000000000 +0200
1824 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/Makefile   2009-12-11 11:45:11.000000000 +0200
1825 @@ -0,0 +1,36 @@
1826 +#
1827 +# arch/ubicom32/crypto/Makefile
1828 +#      <TODO: Replace with short file description>
1829 +#
1830 +# (C) Copyright 2009, Ubicom, Inc.
1831 +#
1832 +# This file is part of the Ubicom32 Linux Kernel Port.
1833 +#
1834 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
1835 +# it and/or modify it under the terms of the GNU General Public License
1836 +# as published by the Free Software Foundation, either version 2 of the
1837 +# License, or (at your option) any later version.
1838 +#
1839 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
1840 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
1841 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1842 +# the GNU General Public License for more details.
1843 +#
1844 +# You should have received a copy of the GNU General Public License
1845 +# along with the Ubicom32 Linux Kernel Port.  If not,
1846 +# see <http://www.gnu.org/licenses/>.
1847 +#
1848 +# Ubicom32 implementation derived from (with many thanks):
1849 +#   arch/m68knommu
1850 +#   arch/blackfin
1851 +#   arch/parisc
1852 +#
1853 +obj-$(CONFIG_CRYPTO_UBICOM32) += crypto_ubicom32.o
1854 +obj-$(CONFIG_CRYPTO_AES_UBICOM32) += aes_ubicom32.o
1855 +obj-$(CONFIG_CRYPTO_DES_UBICOM32) += des.o
1856 +obj-$(CONFIG_CRYPTO_MD5_UBICOM32) += md5.o
1857 +obj-$(CONFIG_CRYPTO_SHA1_UBICOM32) += sha1.o
1858 +
1859 +des-y := des_ubicom32.o des_check_key.o
1860 +md5-y := md5_ubicom32.o md5_ubicom32_asm.o
1861 +sha1-y := sha1_ubicom32.o
1862 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32_asm.S linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32_asm.S
1863 --- linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32_asm.S     1970-01-01 02:00:00.000000000 +0200
1864 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32_asm.S 2009-12-11 11:45:11.000000000 +0200
1865 @@ -0,0 +1,234 @@
1866 +/*
1867 + * arch/ubicom32/crypto/md5_ubicom32_asm.S
1868 + *     MD5 (Message Digest 5) support for Ubicom32 v3 architecture
1869 + *
1870 + * (C) Copyright 2009, Ubicom, Inc.
1871 + *
1872 + * This file is part of the Ubicom32 Linux Kernel Port.
1873 + *
1874 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1875 + * it and/or modify it under the terms of the GNU General Public License
1876 + * as published by the Free Software Foundation, either version 2 of the
1877 + * License, or (at your option) any later version.
1878 + *
1879 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1880 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1881 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1882 + * the GNU General Public License for more details.
1883 + *
1884 + * You should have received a copy of the GNU General Public License
1885 + * along with the Ubicom32 Linux Kernel Port.  If not,
1886 + * see <http://www.gnu.org/licenses/>.
1887 + *
1888 + * Ubicom32 implementation derived from (with many thanks):
1889 + *   arch/m68knommu
1890 + *   arch/blackfin
1891 + *   arch/parisc
1892 + */
1893 +
1894 +#define __ASM__
1895 +#include <asm/ip5000.h>
1896 +
1897 +#ifndef RP
1898 +#define RP A5
1899 +#endif
1900 +
1901 +;*****************************************************************************************
1902 +; The function prototypes
1903 +;*****************************************************************************************
1904 +; void md5_ip5k_init(void)
1905 +; void md5_ip5k_transform(u32_t *data_input)
1906 +; void md5_get_digest(u32_t *digest)
1907 +
1908 +;*****************************************************************************************
1909 +; Inputs
1910 +;*****************************************************************************************;
1911 +; data_input is the pointer to the block of data over which the digest will be calculated.
1912 +;      It should be word aligned.
1913 +;
1914 +; digest is the pointer to the block of data into which the digest (the output) will be written.
1915 +;      It should be word aligned.
1916 +;
1917 +
1918 +;*****************************************************************************************
1919 +; Outputs
1920 +;*****************************************************************************************
1921 +; None
1922 +
1923 +;*****************************************************************************************
1924 +; An: Address Registers
1925 +;*****************************************************************************************
1926 +#define an_digest A3
1927 +#define an_data_input A3
1928 +#define an_security_block A4
1929 +
1930 +;*****************************************************************************************
1931 +; Hash Constants
1932 +;*****************************************************************************************
1933 +#define HASH_MD5_IN0 0x01234567
1934 +#define HASH_MD5_IN1 0x89abcdef
1935 +#define HASH_MD5_IN2 0xfedcba98
1936 +#define HASH_MD5_IN3 0x76543210
1937 +
1938 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
1939 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_MD5 ((1 << 4) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
1940 +
1941 +;*****************************************************************************************
1942 +; Hash related defines
1943 +;*****************************************************************************************
1944 +#define hash_control 0x00(an_security_block)
1945 +#define hash_control_low 0x02(an_security_block)
1946 +#define hash_status 0x04(an_security_block)
1947 +
1948 +#define hash_input_0 0x30(an_security_block)
1949 +#define hash_input_1 0x34(an_security_block)
1950 +#define hash_input_2 0x38(an_security_block)
1951 +#define hash_input_3 0x3c(an_security_block)
1952 +#define hash_input_4 0x40(an_security_block)
1953 +
1954 +#define hash_output_0 0x70(an_security_block)
1955 +#define hash_output_0_low 0x72(an_security_block)
1956 +#define hash_output_1 0x74(an_security_block)
1957 +#define hash_output_1_low 0x76(an_security_block)
1958 +#define hash_output_2 0x78(an_security_block)
1959 +#define hash_output_2_low 0x7a(an_security_block)
1960 +#define hash_output_3 0x7c(an_security_block)
1961 +#define hash_output_3_low 0x7e(an_security_block)
1962 +
1963 +;*****************************************************************************************
1964 +; Assembly macros
1965 +;*****************************************************************************************
1966 +       ; C compiler reserves RP (A5) for return address during subroutine call.
1967 +       ; Use RP to return to caller
1968 +.macro call_return_macro
1969 +       calli   RP, 0(RP)
1970 +.endm
1971 +
1972 +#if 0
1973 +;*****************************************************************************************
1974 +;      void md5_ip5k_init(void)
1975 +;              initialize the output registers of the hash module
1976 +;
1977 +       ;.section .text.md5_ip5k_init,"ax",@progbits
1978 +       .section .text
1979 +       .global _md5_ip5k_init
1980 +       .func md5_ip5k_init, _md5_ip5k_init
1981 +
1982 +_md5_ip5k_init:
1983 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
1984 +
1985 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1986 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1987 +
1988 +       movei hash_output_0, #%hi(HASH_MD5_IN0)
1989 +       movei hash_output_0_low, #%lo(HASH_MD5_IN0)
1990 +
1991 +       movei hash_output_1, #%hi(HASH_MD5_IN1)
1992 +       movei hash_output_1_low, #%lo(HASH_MD5_IN1)
1993 +
1994 +       movei hash_output_2, #%hi(HASH_MD5_IN2)
1995 +       movei hash_output_2_low, #%lo(HASH_MD5_IN2)
1996 +
1997 +       movei hash_output_3, #%hi(HASH_MD5_IN3)
1998 +       movei hash_output_3_low, #%lo(HASH_MD5_IN3)
1999 +
2000 +       call_return_macro
2001 +       .endfunc
2002 +#endif
2003 +
2004 +;*****************************************************************************************
2005 +;      void md5_ip5k_init_digest(u32_t *hash_input)
2006 +;              initialize the output registers of the hash module
2007 +
2008 +       ;.section .text.md5_ip5k_init_digest,"ax",@progbits
2009 +       .section .text
2010 +       .global _md5_ip5k_init_digest
2011 +       .func md5_ip5k_init_digest, _md5_ip5k_init_digest
2012 +
2013 +_md5_ip5k_init_digest:
2014 +       movea an_data_input, D0
2015 +
2016 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2017 +
2018 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2019 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2020 +
2021 +       move.4 hash_output_0, (an_data_input)4++
2022 +       move.4 hash_output_1, (an_data_input)4++
2023 +       move.4 hash_output_2, (an_data_input)4++
2024 +       move.4 hash_output_3, (an_data_input)4++
2025 +
2026 +       call_return_macro
2027 +       .endfunc
2028 +
2029 +;*****************************************************************************************
2030 +;      void md5_ip5k_transform(u32_t *data_input)
2031 +;              performs intermediate transformation step for the hash calculation
2032 +;
2033 +       ;.sect .text.md5_ip5k_transform,"ax",@progbits
2034 +       .section .text
2035 +       .global _md5_ip5k_transform
2036 +       .func md5_ip5k_transform, _md5_ip5k_transform
2037 +
2038 +_md5_ip5k_transform:
2039 +       movea an_data_input, D0
2040 +
2041 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2042 +
2043 +       ; Write the first 128bits (16 bytes)
2044 +       move.4 hash_input_0, (an_data_input)4++
2045 +       move.4 hash_input_1, (an_data_input)4++
2046 +       move.4 hash_input_2, (an_data_input)4++
2047 +       move.4 hash_input_3, (an_data_input)4++
2048 +       move.4 hash_input_4, D0
2049 +
2050 +       move.4 hash_input_0, (an_data_input)4++
2051 +       move.4 hash_input_1, (an_data_input)4++
2052 +       move.4 hash_input_2, (an_data_input)4++
2053 +       move.4 hash_input_3, (an_data_input)4++
2054 +       move.4 hash_input_4, D0
2055 +
2056 +       move.4 hash_input_0, (an_data_input)4++
2057 +       move.4 hash_input_1, (an_data_input)4++
2058 +       move.4 hash_input_2, (an_data_input)4++
2059 +       move.4 hash_input_3, (an_data_input)4++
2060 +       move.4 hash_input_4, D0
2061 +
2062 +       move.4 hash_input_0, (an_data_input)4++
2063 +       move.4 hash_input_1, (an_data_input)4++
2064 +       move.4 hash_input_2, (an_data_input)4++
2065 +       move.4 hash_input_3, (an_data_input)4++
2066 +       move.4 hash_input_4, D0
2067 +
2068 +       pipe_flush 0
2069 +
2070 +md5_ip5k_transform_wait:
2071 +       ; wait for the module to calculate the output hash
2072 +       btst hash_status, #0
2073 +       jmpne.f md5_ip5k_transform_wait
2074 +
2075 +       call_return_macro
2076 +       .endfunc
2077 +
2078 +;*****************************************************************************************
2079 +;      void md5_ip5k_get_digest(u32_t *digest)
2080 +;              Return the hash of the input data
2081 +;
2082 +       ;.sect .text.md5_get_digest,"ax",@progbits
2083 +       .section .text
2084 +       .global _md5_ip5k_get_digest
2085 +       .func md5_ip5k_get_digest, _md5_ip5k_get_digest
2086 +
2087 +_md5_ip5k_get_digest:
2088 +       movea an_digest, D0
2089 +
2090 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2091 +
2092 +       ; we have finished
2093 +       move.4 0(an_digest), hash_output_0
2094 +       move.4 4(an_digest), hash_output_1
2095 +       move.4 8(an_digest), hash_output_2
2096 +       move.4 12(an_digest), hash_output_3
2097 +
2098 +       call_return_macro
2099 +       .endfunc
2100 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32.c
2101 --- linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
2102 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32.c     2009-12-11 11:45:11.000000000 +0200
2103 @@ -0,0 +1,200 @@
2104 +/*
2105 + * arch/ubicom32/crypto/md5_ubicom32.c
2106 + *   Ubicom32 implementation of the MD5 Secure Hash Algorithm
2107 + *
2108 + * (C) Copyright 2009, Ubicom, Inc.
2109 + *
2110 + * This file is part of the Ubicom32 Linux Kernel Port.
2111 + *
2112 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2113 + * it and/or modify it under the terms of the GNU General Public License
2114 + * as published by the Free Software Foundation, either version 2 of the
2115 + * License, or (at your option) any later version.
2116 + *
2117 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2118 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2119 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2120 + * the GNU General Public License for more details.
2121 + *
2122 + * You should have received a copy of the GNU General Public License
2123 + * along with the Ubicom32 Linux Kernel Port.  If not,
2124 + * see <http://www.gnu.org/licenses/>.
2125 + *
2126 + * Ubicom32 implementation derived from (with many thanks):
2127 + *   arch/m68knommu
2128 + *   arch/blackfin
2129 + *   arch/parisc
2130 + */
2131 +#include <linux/init.h>
2132 +#include <linux/module.h>
2133 +#include <linux/crypto.h>
2134 +
2135 +#include "crypto_ubicom32.h"
2136 +
2137 +#define MD5_DIGEST_SIZE        16
2138 +#define MD5_BLOCK_SIZE 64
2139 +#define MD5_HASH_WORDS 4
2140 +
2141 +extern void _md5_ip5k_init_digest(u32_t *digest);
2142 +extern void _md5_ip5k_transform(u32_t *data_input);
2143 +extern void _md5_ip5k_get_digest(u32_t *digest);
2144 +
2145 +struct ubicom32_md5_ctx {
2146 +       u64 count;              /* message length */
2147 +       u32 state[MD5_HASH_WORDS];
2148 +       u8 buf[2 * MD5_BLOCK_SIZE];
2149 +};
2150 +
2151 +static void md5_init(struct crypto_tfm *tfm)
2152 +{
2153 +       struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2154 +       mctx->state[0] = 0x01234567;
2155 +       mctx->state[1] = 0x89abcdef;
2156 +       mctx->state[2] = 0xfedcba98;
2157 +       mctx->state[3] = 0x76543210;
2158 +
2159 +       mctx->count = 0;
2160 +}
2161 +
2162 +static inline void _md5_process(u32 *digest, const u8 *data)
2163 +{
2164 +       _md5_ip5k_transform((u32 *)data);
2165 +}
2166 +
2167 +static void md5_update(struct crypto_tfm *tfm, const u8 *data,
2168 +                       unsigned int len)
2169 +{
2170 +       struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2171 +       int index, clen;
2172 +
2173 +       /* how much is already in the buffer? */
2174 +       index = mctx->count & 0x3f;
2175 +
2176 +       mctx->count += len;
2177 +
2178 +       if (index + len < MD5_BLOCK_SIZE) {
2179 +               goto store_only;
2180 +       }
2181 +
2182 +       hw_crypto_lock();
2183 +       hw_crypto_check();
2184 +
2185 +       /* init digest set ctrl register too */
2186 +       _md5_ip5k_init_digest(mctx->state);
2187 +
2188 +       if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2189 +fast_process:
2190 +               while (len >= MD5_BLOCK_SIZE) {
2191 +                       _md5_process(mctx->state, data);
2192 +                       data += MD5_BLOCK_SIZE;
2193 +                       len -= MD5_BLOCK_SIZE;
2194 +               }
2195 +               goto store;
2196 +       }
2197 +
2198 +       /* process one stored block */
2199 +       if (index) {
2200 +               clen = MD5_BLOCK_SIZE - index;
2201 +               memcpy(mctx->buf + index, data, clen);
2202 +               _md5_process(mctx->state, mctx->buf);
2203 +               data += clen;
2204 +               len -= clen;
2205 +               index = 0;
2206 +       }
2207 +
2208 +       if (likely(SEC_ALIGNED(data))) {
2209 +               goto fast_process;
2210 +       }
2211 +
2212 +       /* process as many blocks as possible */
2213 +       while (len >= MD5_BLOCK_SIZE) {
2214 +               memcpy(mctx->buf, data, MD5_BLOCK_SIZE);
2215 +               _md5_process(mctx->state, mctx->buf);
2216 +               data += MD5_BLOCK_SIZE;
2217 +               len -= MD5_BLOCK_SIZE;
2218 +       }
2219 +
2220 +store:
2221 +       _md5_ip5k_get_digest(mctx->state);
2222 +       hw_crypto_unlock();
2223 +
2224 +store_only:
2225 +       /* anything left? */
2226 +       if (len)
2227 +               memcpy(mctx->buf + index , data, len);
2228 +}
2229 +
2230 +/* Add padding and return the message digest. */
2231 +static void md5_final(struct crypto_tfm *tfm, u8 *out)
2232 +{
2233 +       struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2234 +       u32 bits[2];
2235 +       unsigned int index, end;
2236 +
2237 +       /* must perform manual padding */
2238 +       index = mctx->count & 0x3f;
2239 +       end =  (index < 56) ? MD5_BLOCK_SIZE : (2 * MD5_BLOCK_SIZE);
2240 +
2241 +       /* start pad with 1 */
2242 +       mctx->buf[index] = 0x80;
2243 +
2244 +       /* pad with zeros */
2245 +       index++;
2246 +       memset(mctx->buf + index, 0x00, end - index - 8);
2247 +
2248 +       /* append message length */
2249 +       bits[0] = mctx->count << 3;
2250 +       bits[1] = mctx->count >> 29;
2251 +       __cpu_to_le32s(bits);
2252 +       __cpu_to_le32s(bits + 1);
2253 +
2254 +       memcpy(mctx->buf + end - 8, &bits, sizeof(bits));
2255 +
2256 +       /* force to use the mctx->buf and ignore the partial buf */
2257 +       mctx->count = mctx->count & ~0x3f;
2258 +       md5_update(tfm, mctx->buf, end);
2259 +
2260 +       /* copy digest to out */
2261 +       memcpy(out, mctx->state, MD5_DIGEST_SIZE);
2262 +
2263 +       /* wipe context */
2264 +       memset(mctx, 0, sizeof *mctx);
2265 +}
2266 +
2267 +static struct crypto_alg alg = {
2268 +       .cra_name       =       "md5",
2269 +       .cra_driver_name=       "md5-ubicom32",
2270 +       .cra_priority   =       CRYPTO_UBICOM32_PRIORITY,
2271 +       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
2272 +       .cra_blocksize  =       MD5_BLOCK_SIZE,
2273 +       .cra_ctxsize    =       sizeof(struct ubicom32_md5_ctx),
2274 +       .cra_module     =       THIS_MODULE,
2275 +       .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
2276 +       .cra_u = {
2277 +               .digest = {
2278 +                       .dia_digestsize =       MD5_DIGEST_SIZE,
2279 +                       .dia_init       =       md5_init,
2280 +                       .dia_update     =       md5_update,
2281 +                       .dia_final      =       md5_final,
2282 +               }
2283 +       }
2284 +};
2285 +
2286 +static int __init init(void)
2287 +{
2288 +       hw_crypto_init();
2289 +       return crypto_register_alg(&alg);
2290 +}
2291 +
2292 +static void __exit fini(void)
2293 +{
2294 +       crypto_unregister_alg(&alg);
2295 +}
2296 +
2297 +module_init(init);
2298 +module_exit(fini);
2299 +
2300 +MODULE_ALIAS("md5");
2301 +
2302 +MODULE_LICENSE("GPL");
2303 +MODULE_DESCRIPTION("MD5 Secure Hash Algorithm");
2304 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32_asm.S linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32_asm.S
2305 --- linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32_asm.S    1970-01-01 02:00:00.000000000 +0200
2306 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32_asm.S        2009-12-11 11:45:11.000000000 +0200
2307 @@ -0,0 +1,244 @@
2308 +/*
2309 + * arch/ubicom32/crypto/sha1_ubicom32_asm.S
2310 + *     SHA1 hash support for Ubicom32 architecture V3.
2311 + *
2312 + * (C) Copyright 2009, Ubicom, Inc.
2313 + *
2314 + * This file is part of the Ubicom32 Linux Kernel Port.
2315 + *
2316 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2317 + * it and/or modify it under the terms of the GNU General Public License
2318 + * as published by the Free Software Foundation, either version 2 of the
2319 + * License, or (at your option) any later version.
2320 + *
2321 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2322 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2323 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2324 + * the GNU General Public License for more details.
2325 + *
2326 + * You should have received a copy of the GNU General Public License
2327 + * along with the Ubicom32 Linux Kernel Port.  If not,
2328 + * see <http://www.gnu.org/licenses/>.
2329 + *
2330 + * Ubicom32 implementation derived from (with many thanks):
2331 + *   arch/m68knommu
2332 + *   arch/blackfin
2333 + *   arch/parisc
2334 + */
2335 +
2336 +#define __ASM__
2337 +#include <asm/ip5000.h>
2338 +
2339 +#ifndef RP
2340 +#define RP A5
2341 +#endif
2342 +
2343 +;*****************************************************************************************
2344 +; The function prototype
2345 +;*****************************************************************************************
2346 +; void sha1_ip5k_init(void)
2347 +; void sha1_ip5k_transform(u32_t *data_input)
2348 +; void sha1_ip5k_output(u32_t *digest)
2349 +
2350 +;*****************************************************************************************
2351 +; Inputs
2352 +;*****************************************************************************************
2353 +; data_input is the pointer to the block of data over which the digest will be calculated.
2354 +;      It should be word aligned.
2355 +;
2356 +; digest is the pointer to the block of data into which the digest (the output) will be written.
2357 +;      It should be word aligned.
2358 +;
2359 +
2360 +;*****************************************************************************************
2361 +; Outputs
2362 +;*****************************************************************************************
2363 +; None
2364 +
2365 +;*****************************************************************************************
2366 +; Hash Constants
2367 +;*****************************************************************************************
2368 +#define HASH_SHA1_IN0 0x67452301
2369 +#define HASH_SHA1_IN1 0xefcdab89
2370 +#define HASH_SHA1_IN2 0x98badcfe
2371 +#define HASH_SHA1_IN3 0x10325476
2372 +#define HASH_SHA1_IN4 0xc3d2e1f0
2373 +
2374 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2375 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2376 +
2377 +;*****************************************************************************************
2378 +; An: Address Registers
2379 +;*****************************************************************************************
2380 +#define an_digest a4
2381 +#define an_data_input a4
2382 +#define an_security_block a3
2383 +
2384 +;*****************************************************************************************
2385 +; Hash related defines
2386 +;*****************************************************************************************
2387 +#define hash_control 0x00(an_security_block)
2388 +#define hash_control_low 0x02(an_security_block)
2389 +#define hash_status 0x04(an_security_block)
2390 +
2391 +#define hash_input_0 0x30(an_security_block)
2392 +#define hash_input_1 0x34(an_security_block)
2393 +#define hash_input_2 0x38(an_security_block)
2394 +#define hash_input_3 0x3c(an_security_block)
2395 +#define hash_input_4 0x40(an_security_block)
2396 +
2397 +#define hash_output_0 0x70(an_security_block)
2398 +#define hash_output_0_low 0x72(an_security_block)
2399 +#define hash_output_1 0x74(an_security_block)
2400 +#define hash_output_1_low 0x76(an_security_block)
2401 +#define hash_output_2 0x78(an_security_block)
2402 +#define hash_output_2_low 0x7a(an_security_block)
2403 +#define hash_output_3 0x7c(an_security_block)
2404 +#define hash_output_3_low 0x7e(an_security_block)
2405 +#define hash_output_4 0x80(an_security_block)
2406 +#define hash_output_4_low 0x82(an_security_block)
2407 +
2408 +;*****************************************************************************************
2409 +; Assembly macros
2410 +;*****************************************************************************************
2411 +       ; C compiler reserves RP (A5) for return address during subroutine call.
2412 +       ; Use RP to return to caller
2413 +.macro call_return_macro
2414 +       calli   RP, 0(RP)
2415 +.endm
2416 +
2417 +;*****************************************************************************************
2418 +;      void sha1_ip5k_init(void)
2419 +;              initialize the output registers of the hash module
2420 +
2421 +       ;.section .text.sha1_ip5k_init,"ax",@progbits
2422 +       .section .ocm_text,"ax",@progbits
2423 +       .global _sha1_ip5k_init
2424 +       .func sha1_ip5k_init, _sha1_ip5k_init
2425 +
2426 +_sha1_ip5k_init:
2427 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2428 +
2429 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2430 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2431 +
2432 +       movei hash_output_0, #%hi(HASH_SHA1_IN0)
2433 +       movei hash_output_0_low, #%lo(HASH_SHA1_IN0)
2434 +
2435 +       movei hash_output_1, #%hi(HASH_SHA1_IN1)
2436 +       movei hash_output_1_low, #%lo(HASH_SHA1_IN1)
2437 +
2438 +       movei hash_output_2, #%hi(HASH_SHA1_IN2)
2439 +       movei hash_output_2_low, #%lo(HASH_SHA1_IN2)
2440 +
2441 +       movei hash_output_3, #%hi(HASH_SHA1_IN3)
2442 +       movei hash_output_3_low, #%lo(HASH_SHA1_IN3)
2443 +
2444 +       movei hash_output_4, #%hi(HASH_SHA1_IN4)
2445 +       movei hash_output_4_low, #%lo(HASH_SHA1_IN4)
2446 +
2447 +       call_return_macro
2448 +       .endfunc
2449 +
2450 +;*****************************************************************************************
2451 +;      void sha1_ip5k_init_digest(u32_t *hash_input)
2452 +;              initialize the output registers of the hash module
2453 +
2454 +       ;.section .text.sha1_ip5k_init_digest,"ax",@progbits
2455 +       .section .ocm_text,"ax",@progbits
2456 +       .global _sha1_ip5k_init_digest
2457 +       .func sha1_ip5k_init_digest, _sha1_ip5k_init_digest
2458 +
2459 +_sha1_ip5k_init_digest:
2460 +       movea an_data_input, D0
2461 +
2462 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2463 +
2464 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2465 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2466 +
2467 +       move.4 hash_output_0, (an_data_input)4++
2468 +       move.4 hash_output_1, (an_data_input)4++
2469 +       move.4 hash_output_2, (an_data_input)4++
2470 +       move.4 hash_output_3, (an_data_input)4++
2471 +       move.4 hash_output_4, (an_data_input)4++
2472 +
2473 +       call_return_macro
2474 +       .endfunc
2475 +
2476 +;*****************************************************************************************
2477 +;      void sha1_ip5k_transform(u32_t *data_input)
2478 +;              performs intermediate transformation step for the hash calculation
2479 +
2480 +       ;.section .text.sha1_ip5k_transform,"ax",@progbits
2481 +       .section .ocm_text,"ax",@progbits
2482 +       .global _sha1_ip5k_transform
2483 +       .func sha1_ip5k_transform, _sha1_ip5k_transform
2484 +
2485 +_sha1_ip5k_transform:
2486 +       movea an_data_input, D0
2487 +
2488 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2489 +
2490 +       ; Write the first 128bits (16 bytes)
2491 +       move.4 hash_input_0, (an_data_input)4++
2492 +       move.4 hash_input_1, (an_data_input)4++
2493 +       move.4 hash_input_2, (an_data_input)4++
2494 +       move.4 hash_input_3, (an_data_input)4++
2495 +       move.4 hash_input_4, D0
2496 +
2497 +       move.4 hash_input_0, (an_data_input)4++
2498 +       move.4 hash_input_1, (an_data_input)4++
2499 +       move.4 hash_input_2, (an_data_input)4++
2500 +       move.4 hash_input_3, (an_data_input)4++
2501 +       move.4 hash_input_4, D0
2502 +
2503 +       move.4 hash_input_0, (an_data_input)4++
2504 +       move.4 hash_input_1, (an_data_input)4++
2505 +       move.4 hash_input_2, (an_data_input)4++
2506 +       move.4 hash_input_3, (an_data_input)4++
2507 +       move.4 hash_input_4, D0
2508 +
2509 +       move.4 hash_input_0, (an_data_input)4++
2510 +       move.4 hash_input_1, (an_data_input)4++
2511 +       move.4 hash_input_2, (an_data_input)4++
2512 +       move.4 hash_input_3, (an_data_input)4++
2513 +       move.4 hash_input_4, D0
2514 +
2515 +       pipe_flush 0
2516 +
2517 +sha1_ip5k_transform_wait:
2518 +       ; wait for the module to calculate the output hash
2519 +       btst hash_status, #0
2520 +       jmpne.f sha1_ip5k_transform_wait
2521 +
2522 +       call_return_macro
2523 +       .endfunc
2524 +
2525 +;*****************************************************************************************
2526 +;      void sha1_ip5k_output(u32_t *digest)
2527 +;              Return the hash of the input data
2528 +
2529 +       ;.section .text.sha1_ip5k_output,"ax",@progbits
2530 +       .section .ocm_text,"ax",@progbits
2531 +       .global _sha1_ip5k_output
2532 +       .func sha1_ip5k_output, _sha1_ip5k_output
2533 +
2534 +_sha1_ip5k_output:
2535 +       movea an_digest, D0
2536 +
2537 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2538 +
2539 +       ; we have finished
2540 +       move.4 0(an_digest), hash_output_0
2541 +       move.4 4(an_digest), hash_output_1
2542 +       move.4 8(an_digest), hash_output_2
2543 +       move.4 12(an_digest), hash_output_3
2544 +       move.4 16(an_digest), hash_output_4
2545 +
2546 +       call_return_macro
2547 +       .endfunc
2548 +
2549 +;*****************************************************************************************
2550 +;END                   ;End of program code
2551 +;*****************************************************************************************
2552 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32.c
2553 --- linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32.c        1970-01-01 02:00:00.000000000 +0200
2554 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32.c    2009-12-11 11:45:11.000000000 +0200
2555 @@ -0,0 +1,354 @@
2556 +/*
2557 + * arch/ubicom32/crypto/sha1_ubicom32.c
2558 + *   Ubicom32 implementation of the SHA1 Secure Hash Algorithm.
2559 + *
2560 + * (C) Copyright 2009, Ubicom, Inc.
2561 + *
2562 + * This file is part of the Ubicom32 Linux Kernel Port.
2563 + *
2564 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2565 + * it and/or modify it under the terms of the GNU General Public License
2566 + * as published by the Free Software Foundation, either version 2 of the
2567 + * License, or (at your option) any later version.
2568 + *
2569 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2570 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2571 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2572 + * the GNU General Public License for more details.
2573 + *
2574 + * You should have received a copy of the GNU General Public License
2575 + * along with the Ubicom32 Linux Kernel Port.  If not,
2576 + * see <http://www.gnu.org/licenses/>.
2577 + *
2578 + * Ubicom32 implementation derived from (with many thanks):
2579 + *   arch/m68knommu
2580 + *   arch/blackfin
2581 + *   arch/parisc
2582 + */
2583 +#include <linux/init.h>
2584 +#include <linux/module.h>
2585 +#include <linux/crypto.h>
2586 +#include <crypto/sha.h>
2587 +#include <asm/linkage.h>
2588 +
2589 +#include "crypto_ubicom32.h"
2590 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2591 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2592 +
2593 +struct ubicom32_sha1_ctx {
2594 +       u64 count;              /* message length */
2595 +       u32 state[5];
2596 +       u8 buf[2 * SHA1_BLOCK_SIZE];
2597 +};
2598 +
2599 +static inline void sha1_clear_2ws(u8 *buf, int wc)
2600 +{
2601 +       asm volatile (
2602 +       "1:     move.4  (%0)4++, #0             \n\t"
2603 +       "       move.4  (%0)4++, #0             \n\t"
2604 +       "       sub.4   %1, #2, %1              \n\t"
2605 +       "       jmple.f 1b                      \n\t"
2606 +               :
2607 +               : "a" (buf), "d" (wc)
2608 +               : "cc"
2609 +       );
2610 +}
2611 +
2612 +/* only wipe out count, state, and 1st half of buf - 9 bytes at most */
2613 +#define sha1_wipe_out(sctx) sha1_clear_2ws((u8 *)sctx, 2 + 5 + 16 - 2)
2614 +
2615 +static inline void sha1_init_digest(u32 *digest)
2616 +{
2617 +       hw_crypto_set_ctrl(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1);
2618 +       asm volatile (
2619 +       "       ; move digests to hash_output regs      \n\t"
2620 +       "       move.4  0x70(%0), 0x0(%1)               \n\t"
2621 +       "       move.4  0x74(%0), 0x4(%1)               \n\t"
2622 +       "       move.4  0x78(%0), 0x8(%1)               \n\t"
2623 +       "       move.4  0x7c(%0), 0xc(%1)               \n\t"
2624 +       "       move.4  0x80(%0), 0x10(%1)              \n\t"
2625 +               :
2626 +               : "a" (SEC_BASE), "a" (digest)
2627 +       );
2628 +}
2629 +
2630 +static inline void sha1_transform_feed(const u8 *in)
2631 +{
2632 +       asm volatile (
2633 +       "       ; write the 1st 16 bytes        \n\t"
2634 +       "       move.4  0x30(%0), 0x0(%1)       \n\t"
2635 +       "       move.4  0x34(%0), 0x4(%1)       \n\t"
2636 +       "       move.4  0x38(%0), 0x8(%1)       \n\t"
2637 +       "       move.4  0x3c(%0), 0xc(%1)       \n\t"
2638 +       "       move.4  0x40(%0), %1            \n\t"
2639 +       "       ; write the 2nd 16 bytes        \n\t"
2640 +       "       move.4  0x30(%0), 0x10(%1)      \n\t"
2641 +       "       move.4  0x34(%0), 0x14(%1)      \n\t"
2642 +       "       move.4  0x38(%0), 0x18(%1)      \n\t"
2643 +       "       move.4  0x3c(%0), 0x1c(%1)      \n\t"
2644 +       "       move.4  0x40(%0), %1            \n\t"
2645 +       "       ; write the 3rd 16 bytes        \n\t"
2646 +       "       move.4  0x30(%0), 0x20(%1)      \n\t"
2647 +       "       move.4  0x34(%0), 0x24(%1)      \n\t"
2648 +       "       move.4  0x38(%0), 0x28(%1)      \n\t"
2649 +       "       move.4  0x3c(%0), 0x2c(%1)      \n\t"
2650 +       "       move.4  0x40(%0), %1            \n\t"
2651 +       "       ; write the 4th 16 bytes        \n\t"
2652 +       "       move.4  0x30(%0), 0x30(%1)      \n\t"
2653 +       "       move.4  0x34(%0), 0x34(%1)      \n\t"
2654 +       "       move.4  0x38(%0), 0x38(%1)      \n\t"
2655 +       "       move.4  0x3c(%0), 0x3c(%1)      \n\t"
2656 +       "       move.4  0x40(%0), %1            \n\t"
2657 +       "       pipe_flush 0                    \n\t"
2658 +               :
2659 +               : "a"(SEC_BASE), "a"(in)
2660 +       );
2661 +}
2662 +
2663 +static inline void sha1_transform_wait(void)
2664 +{
2665 +       asm volatile (
2666 +       "       btst    0x04(%0), #0            \n\t"
2667 +       "       jmpne.f -4                      \n\t"
2668 +               :
2669 +               : "a"(SEC_BASE)
2670 +               : "cc"
2671 +       );
2672 +}
2673 +
2674 +static inline void sha1_output_digest(u32 *digest)
2675 +{
2676 +       asm volatile (
2677 +       "       move.4  0x0(%1), 0x70(%0)               \n\t"
2678 +       "       move.4  0x4(%1), 0x74(%0)               \n\t"
2679 +       "       move.4  0x8(%1), 0x78(%0)               \n\t"
2680 +       "       move.4  0xc(%1), 0x7c(%0)               \n\t"
2681 +       "       move.4  0x10(%1), 0x80(%0)              \n\t"
2682 +               :
2683 +               : "a" (SEC_BASE), "a" (digest)
2684 +       );
2685 +}
2686 +
2687 +static __ocm_text void sha1_init(struct crypto_tfm *tfm)
2688 +{
2689 +       struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2690 +
2691 +       sctx->state[0] = SHA1_H0;
2692 +       sctx->state[1] = SHA1_H1;
2693 +       sctx->state[2] = SHA1_H2;
2694 +       sctx->state[3] = SHA1_H3;
2695 +       sctx->state[4] = SHA1_H4;
2696 +       sctx->count = 0;
2697 +}
2698 +
2699 +static void __ocm_text sha1_update(struct crypto_tfm *tfm, const u8 *data,
2700 +                       unsigned int len)
2701 +{
2702 +       struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2703 +       int index, clen;
2704 +
2705 +       /* how much is already in the buffer? */
2706 +       index = sctx->count & 0x3f;
2707 +
2708 +       sctx->count += len;
2709 +
2710 +       if (index + len < SHA1_BLOCK_SIZE) {
2711 +               goto store_only;
2712 +       }
2713 +
2714 +       hw_crypto_lock();
2715 +       hw_crypto_check();
2716 +
2717 +       /* init digest set ctrl register too */
2718 +       sha1_init_digest(sctx->state);
2719 +
2720 +       if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2721 +fast_process:
2722 +#if CRYPTO_UBICOM32_LOOP_ASM
2723 +               if (likely(len >= SHA1_BLOCK_SIZE)) {
2724 +                       register unsigned int cnt = len >> 6;   // loop = len / 64;
2725 +                       sha1_transform_feed(data);
2726 +                       data += SHA1_BLOCK_SIZE;
2727 +
2728 +                       /* cnt is pre-decremented in the loop */
2729 +                       asm volatile (
2730 +                       "; while (--loop):  work on 2nd block   \n\t"
2731 +                       "1:     add.4   %2, #-1, %2             \n\t"
2732 +                       "       jmpeq.f 5f                      \n\t"
2733 +                       "                                       \n\t"
2734 +                       "       ; write the 1st 16 bytes        \n\t"
2735 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2736 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2737 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2738 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2739 +                       "       ; can not kick off hw before it \n\t"
2740 +                       "       ; is done with the prev block   \n\t"
2741 +                       "                                       \n\t"
2742 +                       "       btst    0x04(%1), #0            \n\t"
2743 +                       "       jmpne.f -4                      \n\t"
2744 +                       "                                       \n\t"
2745 +                       "       ; tell hw to load 1st 16 bytes  \n\t"
2746 +                       "       move.4  0x40(%1), %2            \n\t"
2747 +                       "                                       \n\t"
2748 +                       "       ; write the 2nd 16 bytes        \n\t"
2749 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2750 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2751 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2752 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2753 +                       "       move.4  0x40(%1), %2            \n\t"
2754 +                       "                                       \n\t"
2755 +                       "       ; write the 3rd 16 bytes        \n\t"
2756 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2757 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2758 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2759 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2760 +                       "       move.4  0x40(%1), %2            \n\t"
2761 +                       "                                       \n\t"
2762 +                       "       ; write the 4th 16 bytes        \n\t"
2763 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2764 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2765 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2766 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2767 +                       "       move.4  0x40(%1), %2            \n\t"
2768 +                       "                                       \n\t"
2769 +                       "; no need flush, enough insts          \n\t"
2770 +                       "; before next hw wait                  \n\t"
2771 +                       "                                       \n\t"
2772 +                       "; go back to loop                      \n\t"
2773 +                       "       jmpt 1b                         \n\t"
2774 +                       "                                       \n\t"
2775 +                       "; wait hw for last block               \n\t"
2776 +                       "5:     btst 0x04(%1), #0               \n\t"
2777 +                       "       jmpne.f -4                      \n\t"
2778 +                       "                                       \n\t"
2779 +                               : "+a" (data)
2780 +                               : "a"( SEC_BASE), "d" (cnt)
2781 +                               : "cc"
2782 +                       );
2783 +
2784 +                       len = len & (64 - 1);
2785 +               }
2786 +#else
2787 +               while (likely(len >= SHA1_BLOCK_SIZE)) {
2788 +                       sha1_transform_feed(data);
2789 +                       data += SHA1_BLOCK_SIZE;
2790 +                       len -= SHA1_BLOCK_SIZE;
2791 +                       sha1_transform_wait();
2792 +               }
2793 +#endif
2794 +               goto store;
2795 +       }
2796 +
2797 +       /* process one stored block */
2798 +       if (index) {
2799 +               clen = SHA1_BLOCK_SIZE - index;
2800 +               memcpy(sctx->buf + index, data, clen);
2801 +               sha1_transform_feed(sctx->buf);
2802 +               data += clen;
2803 +               len -= clen;
2804 +               index = 0;
2805 +               sha1_transform_wait();
2806 +       }
2807 +
2808 +       if (likely(SEC_ALIGNED(data))) {
2809 +               goto fast_process;
2810 +       }
2811 +
2812 +       /* process as many blocks as possible */
2813 +       if (likely(len >= SHA1_BLOCK_SIZE)) {
2814 +               memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2815 +               do {
2816 +                       sha1_transform_feed(sctx->buf);
2817 +                       data += SHA1_BLOCK_SIZE;
2818 +                       len -= SHA1_BLOCK_SIZE;
2819 +                       if (likely(len >= SHA1_BLOCK_SIZE)) {
2820 +                               memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2821 +                               sha1_transform_wait();
2822 +                               continue;
2823 +                       }
2824 +                       /* it is the last block */
2825 +                       sha1_transform_wait();
2826 +                       break;
2827 +               } while (1);
2828 +       }
2829 +
2830 +store:
2831 +       sha1_output_digest(sctx->state);
2832 +       hw_crypto_unlock();
2833 +
2834 +store_only:
2835 +       /* anything left? */
2836 +       if (len)
2837 +               memcpy(sctx->buf + index , data, len);
2838 +}
2839 +
2840 +/* Add padding and return the message digest. */
2841 +static void __ocm_text sha1_final(struct crypto_tfm *tfm, u8 *out)
2842 +{
2843 +       struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2844 +       u64 bits;
2845 +       unsigned int index, end;
2846 +
2847 +       /* must perform manual padding */
2848 +       index = sctx->count & 0x3f;
2849 +       end =  (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
2850 +
2851 +       /* start pad with 1 */
2852 +       sctx->buf[index] = 0x80;
2853 +
2854 +       /* pad with zeros */
2855 +       index++;
2856 +       memset(sctx->buf + index, 0x00, end - index - 8);
2857 +
2858 +       /* append message length */
2859 +       bits = sctx->count << 3 ;
2860 +       SEC_COPY_2W(sctx->buf + end - 8, &bits);
2861 +
2862 +       /* force to use the sctx->buf and ignore the partial buf */
2863 +       sctx->count = sctx->count & ~0x3f;
2864 +       sha1_update(tfm, sctx->buf, end);
2865 +
2866 +       /* copy digest to out */
2867 +       SEC_COPY_5W(out, sctx->state);
2868 +
2869 +       /* wipe context */
2870 +       sha1_wipe_out(sctx);
2871 +}
2872 +
2873 +static struct crypto_alg alg = {
2874 +       .cra_name       =       "sha1",
2875 +       .cra_driver_name=       "sha1-ubicom32",
2876 +       .cra_priority   =       CRYPTO_UBICOM32_PRIORITY,
2877 +       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
2878 +       .cra_blocksize  =       SHA1_BLOCK_SIZE,
2879 +       .cra_ctxsize    =       sizeof(struct ubicom32_sha1_ctx),
2880 +       .cra_module     =       THIS_MODULE,
2881 +       .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
2882 +       .cra_u    = {
2883 +               .digest = {
2884 +                       .dia_digestsize =       SHA1_DIGEST_SIZE,
2885 +                       .dia_init       =       sha1_init,
2886 +                       .dia_update     =       sha1_update,
2887 +                       .dia_final      =       sha1_final,
2888 +               }
2889 +       }
2890 +};
2891 +
2892 +static int __init init(void)
2893 +{
2894 +       hw_crypto_init();
2895 +       return crypto_register_alg(&alg);
2896 +}
2897 +
2898 +static void __exit fini(void)
2899 +{
2900 +       crypto_unregister_alg(&alg);
2901 +}
2902 +
2903 +module_init(init);
2904 +module_exit(fini);
2905 +
2906 +MODULE_ALIAS("sha1");
2907 +
2908 +MODULE_LICENSE("GPL");
2909 +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
2910 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/a.out.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/a.out.h
2911 --- linux-2.6.30.10/arch/ubicom32/include/asm/a.out.h   1970-01-01 02:00:00.000000000 +0200
2912 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/a.out.h       2009-12-11 11:45:11.000000000 +0200
2913 @@ -0,0 +1,47 @@
2914 +/*
2915 + * arch/ubicom32/include/asm/a.out.h
2916 + *   Definitions for Ubicom32 a.out executable format.
2917 + *
2918 + * (C) Copyright 2009, Ubicom, Inc.
2919 + *
2920 + * This file is part of the Ubicom32 Linux Kernel Port.
2921 + *
2922 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2923 + * it and/or modify it under the terms of the GNU General Public License
2924 + * as published by the Free Software Foundation, either version 2 of the
2925 + * License, or (at your option) any later version.
2926 + *
2927 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2928 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2929 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2930 + * the GNU General Public License for more details.
2931 + *
2932 + * You should have received a copy of the GNU General Public License
2933 + * along with the Ubicom32 Linux Kernel Port.  If not,
2934 + * see <http://www.gnu.org/licenses/>.
2935 + *
2936 + * Ubicom32 implementation derived from (with many thanks):
2937 + *   arch/m68knommu
2938 + *   arch/blackfin
2939 + *   arch/parisc
2940 + */
2941 +#ifndef _ASM_UBICOM32_A_OUT_H
2942 +#define _ASM_UBICOM32_A_OUT_H
2943 +
2944 +struct exec
2945 +{
2946 +  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
2947 +  unsigned a_text;             /* length of text, in bytes */
2948 +  unsigned a_data;             /* length of data, in bytes */
2949 +  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
2950 +  unsigned a_syms;             /* length of symbol table data in file, in bytes */
2951 +  unsigned a_entry;            /* start address */
2952 +  unsigned a_trsize;           /* length of relocation info for text, in bytes */
2953 +  unsigned a_drsize;           /* length of relocation info for data, in bytes */
2954 +};
2955 +
2956 +#define N_TRSIZE(a)    ((a).a_trsize)
2957 +#define N_DRSIZE(a)    ((a).a_drsize)
2958 +#define N_SYMSIZE(a)   ((a).a_syms)
2959 +
2960 +#endif /* _ASM_UBICOM32_A_OUT_H */
2961 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/atomic.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/atomic.h
2962 --- linux-2.6.30.10/arch/ubicom32/include/asm/atomic.h  1970-01-01 02:00:00.000000000 +0200
2963 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/atomic.h      2009-12-11 11:45:11.000000000 +0200
2964 @@ -0,0 +1,348 @@
2965 +/*
2966 + * arch/ubicom32/include/asm/atomic.h
2967 + *   Atomic operations definitions for Ubicom32 architecture.
2968 + *
2969 + * (C) Copyright 2009, Ubicom, Inc.
2970 + *
2971 + * This file is part of the Ubicom32 Linux Kernel Port.
2972 + *
2973 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2974 + * it and/or modify it under the terms of the GNU General Public License
2975 + * as published by the Free Software Foundation, either version 2 of the
2976 + * License, or (at your option) any later version.
2977 + *
2978 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2979 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2980 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2981 + * the GNU General Public License for more details.
2982 + *
2983 + * You should have received a copy of the GNU General Public License
2984 + * along with the Ubicom32 Linux Kernel Port.  If not,
2985 + * see <http://www.gnu.org/licenses/>.
2986 + *
2987 + * Ubicom32 implementation derived from (with many thanks):
2988 + *   arch/m68knommu
2989 + *   arch/blackfin
2990 + *   arch/parisc
2991 + */
2992 +#ifndef _ASM_UBICOM32_ATOMIC_H
2993 +#define _ASM_UBICOM32_ATOMIC_H
2994 +
2995 +#include <asm/system.h>
2996 +#include <asm/ubicom32-common.h>
2997 +#include <asm/types.h>
2998 +
2999 +/*
3000 + * Most instructions on the Ubicom32 processor are atomic in that they
3001 + * execute in one clock cycle.  However, Linux has several operations
3002 + * (e.g. compare and swap) which will require more than a single instruction
3003 + * to perform.   To achieve this, the Ubicom32 processor uses a single
3004 + * global bit in a scratchpad register as a critical section lock. All
3005 + * atomic operations acquire this lock.
3006 + *
3007 + * NOTE: To AVOID DEADLOCK(s), the atomic lock must only be used for atomic
3008 + * operations or by the ldsr to avoid disabling a thread performing an atomic
3009 + * operation.
3010 + *
3011 + * Do not attempt to disable interrupts while holding the atomic operations
3012 + * lock or you will DEADLOCK the system.
3013 + */
3014 +
3015 +#define ATOMIC_INIT(i) { (i) }
3016 +
3017 +/*
3018 + * __atomic_add()
3019 + *     Add i to v and return the result.
3020 + */
3021 +static inline void __atomic_add(int i, atomic_t *v)
3022 +{
3023 +       atomic_t *vt = v;
3024 +
3025 +       __atomic_lock_acquire();
3026 +       vt->counter += i;
3027 +       __atomic_lock_release();
3028 +}
3029 +
3030 +/*
3031 + * __atomic_sub()
3032 + *     Subtract i from v and return the result.
3033 + */
3034 +static inline void __atomic_sub(int i, atomic_t *v)
3035 +{
3036 +       atomic_t *vt = v;
3037 +
3038 +       __atomic_lock_acquire();
3039 +       vt->counter -= i;
3040 +       __atomic_lock_release();
3041 +}
3042 +
3043 +/*
3044 + * __atomic_add_return()
3045 + *     Add i to v and return the result.
3046 + *
3047 + * The implementation here looks rather odd because we appear to be doing
3048 + * the addition twice.  In fact that's exactly what we're doing but with
3049 + * the ubicom32 instruction set we can do the inner load and add with two
3050 + * instructions whereas generating both the atomic result and the "ret"
3051 + * result requires three instructions.  The second add is generally only as
3052 + * costly as a move instruction and in cases where we compare the result
3053 + * with a constant the compiler can fold two constant values and do a
3054 + * single instruction, thus saving an instruction overall!
3055 + *
3056 + * At the worst we save one instruction inside the atomic lock.
3057 + */
3058 +static inline int __atomic_add_return(int i, atomic_t *v)
3059 +{
3060 +       int ret;
3061 +       atomic_t *vt = v;
3062 +
3063 +       __atomic_lock_acquire();
3064 +       ret = vt->counter;
3065 +       vt->counter = ret + i;
3066 +       __atomic_lock_release();
3067 +
3068 +       return ret + i;
3069 +}
3070 +
3071 +/*
3072 + * __atomic_sub_return()
3073 + *     Subtract i from v and return the result.
3074 + *
3075 + * The implementation here looks rather odd because we appear to be doing
3076 + * the subtraction twice.  In fact that's exactly what we're doing but with
3077 + * the ubicom32 instruction set we can do the inner load and sub with two
3078 + * instructions whereas generating both the atomic result and the "ret"
3079 + * result requires three instructions.  The second sub is generally only as
3080 + * costly as a move instruction and in cases where we compare the result
3081 + * with a constant the compiler can fold two constant values and do a
3082 + * single instruction, thus saving an instruction overall!
3083 + *
3084 + * At the worst we save one instruction inside the atomic lock.
3085 + */
3086 +static inline int __atomic_sub_return(int i, atomic_t *v)
3087 +{
3088 +       int ret;
3089 +       atomic_t *vt = v;
3090 +
3091 +       __atomic_lock_acquire();
3092 +       ret = vt->counter;
3093 +       vt->counter = ret - i;
3094 +       __atomic_lock_release();
3095 +
3096 +       return ret - i;
3097 +}
3098 +
3099 +/*
3100 + * PUBLIC API FOR ATOMIC!
3101 + */
3102 +#define atomic_add(i,v)        (__atomic_add( ((int)i),(v)))
3103 +#define atomic_sub(i,v)        (__atomic_sub( ((int)i),(v)))
3104 +#define atomic_inc(v)  (__atomic_add(   1,(v)))
3105 +#define atomic_dec(v)  (__atomic_sub(   1,(v)))
3106 +#define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v)))
3107 +#define atomic_sub_return(i,v) (__atomic_sub_return( ((int)i),(v)))
3108 +#define atomic_inc_return(v)   (__atomic_add_return(   1,(v)))
3109 +#define atomic_dec_return(v)   (__atomic_sub_return(   1,(v)))
3110 +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
3111 +#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
3112 +#define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
3113 +#define atomic_sub_and_test(i,v)       (atomic_sub_return((i),(v)) == 0)
3114 +
3115 +/*
3116 + * atomic_read()
3117 + *     Acquire the atomic lock and read the variable.
3118 + */
3119 +static inline int atomic_read(const atomic_t *v)
3120 +{
3121 +       int ret;
3122 +       const atomic_t *vt = v;
3123 +
3124 +       __atomic_lock_acquire();
3125 +       ret = vt->counter;
3126 +       __atomic_lock_release();
3127 +
3128 +       return ret;
3129 +}
3130 +
3131 +/*
3132 + * atomic_set()
3133 + *     Acquire the atomic lock and set the variable.
3134 + */
3135 +static inline void atomic_set(atomic_t *v, int i)
3136 +{
3137 +       atomic_t *vt = v;
3138 +
3139 +       __atomic_lock_acquire();
3140 +       vt->counter = i;
3141 +       __atomic_lock_release();
3142 +}
3143 +
3144 +/*
3145 + * atomic_cmpxchg
3146 + *     Acquire the atomic lock and exchange if current == old.
3147 + */
3148 +static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
3149 +{
3150 +       int prev;
3151 +       atomic_t *vt = v;
3152 +
3153 +       __atomic_lock_acquire();
3154 +       prev = vt->counter;
3155 +       if (prev == old) {
3156 +               vt->counter = new;
3157 +       }
3158 +       __atomic_lock_release();
3159 +
3160 +       return prev;
3161 +}
3162 +
3163 +/*
3164 + * atomic_xchg()
3165 + *     Acquire the atomic lock and exchange values.
3166 + */
3167 +static inline int atomic_xchg(atomic_t *v, int new)
3168 +{
3169 +       int prev;
3170 +       atomic_t *vt = v;
3171 +
3172 +       __atomic_lock_acquire();
3173 +       prev = vt->counter;
3174 +       vt->counter = new;
3175 +       __atomic_lock_release();
3176 +
3177 +       return prev;
3178 +}
3179 +
3180 +/*
3181 + * atomic_add_unless()
3182 + *     Acquire the atomic lock and add a unless the value is u.
3183 + */
3184 +static inline int atomic_add_unless(atomic_t *v, int a, int u)
3185 +{
3186 +       int prev;
3187 +       atomic_t *vt = v;
3188 +
3189 +       __atomic_lock_acquire();
3190 +       prev = vt->counter;
3191 +       if (prev != u) {
3192 +               vt->counter += a;
3193 +               __atomic_lock_release();
3194 +               return 1;
3195 +       }
3196 +
3197 +       __atomic_lock_release();
3198 +       return 0;
3199 +}
3200 +
3201 +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
3202 +
3203 +#include <asm-generic/atomic.h>
3204 +
3205 +/*
3206 + * The following is not a real function.  The compiler should remove the function
3207 + * call as long as the user does not pass in a size that __xchg and __cmpxchg
3208 + * are not prepared for.  If the user does pass in an unknown size, the user
3209 + * will get a link time error.
3210 + *
3211 + * The no return is to prevent a compiler error that can occur when dealing with
3212 + * uninitialized variables. Given that the function doesn't exist there is no
3213 + * net effect (and if it did it would not return).
3214 + */
3215 +extern void __xchg_called_with_bad_pointer(void) __attribute__((noreturn));
3216 +
3217 +/*
3218 + * __xchg()
3219 + *     Xchange *ptr for x atomically.
3220 + *
3221 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3222 + * atomic exchange instruction so we use the global atomic_lock.
3223 + */
3224 +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
3225 +{
3226 +       unsigned long ret;
3227 +
3228 +       __atomic_lock_acquire();
3229 +
3230 +       switch (size) {
3231 +       case 1:
3232 +               ret = *(volatile unsigned char *)ptr;
3233 +               *(volatile unsigned char *)ptr = x;
3234 +               break;
3235 +
3236 +       case 2:
3237 +               ret = *(volatile unsigned short *)ptr;
3238 +               *(volatile unsigned short *)ptr = x;
3239 +               break;
3240 +
3241 +       case 4:
3242 +               ret = *(volatile unsigned int *)ptr;
3243 +               *(volatile unsigned int *)ptr = x;
3244 +               break;
3245 +
3246 +       default:
3247 +               __xchg_called_with_bad_pointer();
3248 +               break;
3249 +       }
3250 +       __atomic_lock_release();
3251 +       return ret;
3252 +}
3253 +
3254 +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
3255 +
3256 +/*
3257 + * __cmpxchg()
3258 + *     Compare and Xchange *ptr for x atomically.
3259 + *
3260 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3261 + * atomic exchange instruction so we use the global atomic_lock.
3262 + */
3263 +static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long next, int size)
3264 +{
3265 +       unsigned long prev;
3266 +
3267 +       __atomic_lock_acquire();
3268 +       switch (size) {
3269 +       case 1:
3270 +               prev = *(u8 *)ptr;
3271 +               if (prev == old) {
3272 +                       *(u8 *)ptr = (u8)next;
3273 +               }
3274 +               break;
3275 +
3276 +       case 2:
3277 +               prev = *(u16 *)ptr;
3278 +               if (prev == old) {
3279 +                       *(u16 *)ptr = (u16)next;
3280 +               }
3281 +               break;
3282 +
3283 +       case 4:
3284 +               prev = *(u32 *)ptr;
3285 +               if (prev == old) {
3286 +                       *(u32 *)ptr = (u32)next;
3287 +               }
3288 +               break;
3289 +
3290 +       default:
3291 +               __xchg_called_with_bad_pointer();
3292 +               break;
3293 +       }
3294 +       __atomic_lock_release();
3295 +       return prev;
3296 +}
3297 +
3298 +/*
3299 + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
3300 + * them available.
3301 + */
3302 +#define cmpxchg_local(ptr, o, n) \
3303 +       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
3304 +
3305 +#define cmpxchg(ptr, o, n) __cmpxchg((ptr), (o), (n), sizeof(*(ptr)))
3306 +
3307 +#define smp_mb__before_atomic_inc() asm volatile ("" : : : "memory")
3308 +#define smp_mb__after_atomic_inc() asm volatile ("" : : : "memory")
3309 +#define smp_mb__before_atomic_dec() asm volatile ("" : : : "memory")
3310 +#define smp_mb__after_atomic_dec() asm volatile ("" : : : "memory")
3311 +
3312 +#endif /* _ASM_UBICOM32_ATOMIC_H */
3313 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/audio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audio.h
3314 --- linux-2.6.30.10/arch/ubicom32/include/asm/audio.h   1970-01-01 02:00:00.000000000 +0200
3315 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audio.h       2009-12-11 11:45:11.000000000 +0200
3316 @@ -0,0 +1,40 @@
3317 +/*
3318 + * arch/ubicom32/include/asm/audio.h
3319 + *     Audio include file
3320 + *
3321 + * (C) Copyright 2009, Ubicom, Inc.
3322 + *
3323 + * This file is part of the Ubicom32 Linux Kernel Port.
3324 + *
3325 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3326 + * it and/or modify it under the terms of the GNU General Public License
3327 + * as published by the Free Software Foundation, either version 2 of the
3328 + * License, or (at your option) any later version.
3329 + *
3330 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3331 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3332 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3333 + * the GNU General Public License for more details.
3334 + *
3335 + * You should have received a copy of the GNU General Public License
3336 + * along with the Ubicom32 Linux Kernel Port.  If not,
3337 + * see <http://www.gnu.org/licenses/>.
3338 + */
3339 +
3340 +#ifndef _AUDIO_H
3341 +#define _AUDIO_H
3342 +
3343 +#include <asm/devtree.h>
3344 +#include <asm/audionode.h>
3345 +
3346 +/*
3347 + * Resource indices used to access IRQs via platform_get_resource
3348 + */
3349 +#define AUDIO_MEM_RESOURCE     0
3350 +#define AUDIO_TX_IRQ_RESOURCE  0
3351 +#define AUDIO_RX_IRQ_RESOURCE  1
3352 +
3353 +extern struct platform_device * __init audio_device_alloc(const char *driver_name, const char *node_name, const char *inst_name, int priv_size);
3354 +
3355 +#define audio_device_priv(pdev) (((struct ubi32pcm_platform_data *)(((struct platform_device *)(pdev))->dev.platform_data))->priv_data)
3356 +#endif
3357 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/audionode.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audionode.h
3358 --- linux-2.6.30.10/arch/ubicom32/include/asm/audionode.h       1970-01-01 02:00:00.000000000 +0200
3359 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audionode.h   2009-12-11 11:45:11.000000000 +0200
3360 @@ -0,0 +1,152 @@
3361 +/*
3362 + * audionode.h
3363 + *     audionode and DMA descriptors
3364 + *
3365 + * Copyright \81© 2009 Ubicom Inc. <www.ubicom.com>.  All rights reserved.
3366 + *
3367 + * This file contains confidential information of Ubicom, Inc. and your use of
3368 + * this file is subject to the Ubicom Software License Agreement distributed with
3369 + * this file. If you are uncertain whether you are an authorized user or to report
3370 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
3371 + * Unauthorized reproduction or distribution of this file is subject to civil and
3372 + * criminal penalties.
3373 + *
3374 + */
3375 +#ifndef _AUDIONODE_H_
3376 +#define _AUDIONODE_H_
3377 +
3378 +#define AUDIO_INT_FLAG_MORE_SAMPLES 0x00000001
3379 +#define AUDIO_INT_FLAG_COMMAND      0x00000002
3380 +
3381 +/*
3382 + * Commands the Primary OS sends to the audio device
3383 + */
3384 +enum audio_command {
3385 +       AUDIO_CMD_NONE,
3386 +       AUDIO_CMD_START,
3387 +       AUDIO_CMD_STOP,
3388 +       AUDIO_CMD_PAUSE,
3389 +       AUDIO_CMD_RESUME,
3390 +       AUDIO_CMD_MUTE,
3391 +       AUDIO_CMD_UNMUTE,
3392 +       AUDIO_CMD_SETUP,
3393 +       AUDIO_CMD_ENABLE,
3394 +       AUDIO_CMD_DISABLE,
3395 +};
3396 +
3397 +/*
3398 + * Flag bits passed in the registers
3399 + */
3400 +#define CMD_START_FLAG_LE              (1 << 0)        /* Use Little Endian Mode */
3401 +
3402 +/*
3403 + * Status bits that audio device can set to indicate reason
3404 + * for interrupting the Primary OS
3405 + */
3406 +#define AUDIO_STATUS_PLAY_DMA0_REQUEST (1 << 0) /* Audio device needs samples in DMA0 for playback */
3407 +#define AUDIO_STATUS_PLAY_DMA1_REQUEST (1 << 1) /* Audio device needs samples in DMA1 for playback */
3408 +
3409 +struct audio_dma {
3410 +       /*
3411 +        * NOTE: The active flag shall only be SET by the producer and CLEARED
3412 +        * by the consumer, NEVER the other way around.  For playback, the
3413 +        * Primary OS sets this flag and ipAudio clears it.
3414 +        *
3415 +        * The producer shall not modify the ptr or ctr fields when the transfer
3416 +        * is marked as active, as these are used by the consumer to do the
3417 +        * transfer.
3418 +        */
3419 +       volatile u32_t active;          /* Nonzero if data in ptr/ctr ready to be transferred */
3420 +       volatile void *ptr;             /* Pointer to data to be transferred */
3421 +       volatile u32_t ctr;             /* Counter: number of data units to transfer */
3422 +};
3423 +
3424 +#define AUDIONODE_CAP_BE       (1 << 0)
3425 +#define AUDIONODE_CAP_LE       (1 << 1)
3426 +
3427 +#define AUDIONODE_VERSION      7
3428 +struct audio_node {
3429 +       struct devtree_node dn;
3430 +
3431 +       /*
3432 +        * Version of this node
3433 +        */
3434 +       u32_t                   version;
3435 +
3436 +       /*
3437 +        * Pointer to the registers
3438 +        */
3439 +       struct audio_regs       *regs;
3440 +};
3441 +
3442 +/*
3443 + * [OCM] Audio registers
3444 + *     Registers exposed as part of our MMIO area
3445 + */
3446 +#define AUDIO_REGS_VERSION     7
3447 +struct audio_regs {
3448 +       /*
3449 +        * Version of this register set
3450 +        */
3451 +       u32_t version;
3452 +
3453 +       /*
3454 +        * Interrupt status
3455 +        */
3456 +       volatile u32_t int_status;
3457 +
3458 +       /*
3459 +        * Interrupt request
3460 +        */
3461 +       volatile u32_t int_req;
3462 +
3463 +       /*
3464 +        * Current IRQ being serviced
3465 +        */
3466 +       u32_t cur_irq;
3467 +
3468 +       /*
3469 +        * Maximum number of devices supported
3470 +        */
3471 +       u32_t max_devs;
3472 +
3473 +       /*
3474 +        * [DDR] Device registers for each of the devices
3475 +        */
3476 +       struct audio_dev_regs *adr;
3477 +};
3478 +
3479 +#define AUDIO_DEV_REGS_VERSION 2
3480 +struct audio_dev_regs {
3481 +       u32_t version;                                  /* Version of this register set */
3482 +
3483 +       u8_t name[32];                                  /* Name of this driver */
3484 +       u32_t caps;                                     /* Capabilities of this driver */
3485 +       const u32_t *sample_rates;                      /* Sample Rates supported by this driver */
3486 +       u32_t n_sample_rates;                           /* Number of sample rates supported by this driver */
3487 +       u32_t channel_mask;                             /* A bit set in a particular position means we support this channel configuration */
3488 +       volatile u32_t int_flags;                       /* Reason for interrupting audio device */
3489 +       volatile enum audio_command command;    /* Command from Primary OS */
3490 +       volatile u32_t flags;                           /* Flag bits for this command */
3491 +       volatile u32_t channels;                        /* Number of channels */
3492 +       volatile u32_t sample_rate;                     /* Sample rate */
3493 +       volatile u32_t status;                          /* Status bits sent from ipAudio to Primary OS */
3494 +       void *primary_os_buffer_ptr;                    /*
3495 +                                                        * Playback: Pointer to next sample to be removed from
3496 +                                                        *           Primary OS sample buffer
3497 +                                                        * Capture: Pointer to where next sample will be inserted
3498 +                                                        *          into Primary OS sample buffer
3499 +                                                        */
3500 +
3501 +       /*
3502 +        * These are the transfer requests.  They are used in alternating
3503 +        * order so that when ipAudio is processing one request, the
3504 +        * Primary OS can fill in the other one.
3505 +        *
3506 +        * NOTE: The active bit shall always be SET by the producer and
3507 +        * CLEARED by the consumer, NEVER the other way around.
3508 +        */
3509 +       struct audio_dma dma_xfer_requests[2];
3510 +};
3511 +
3512 +#endif
3513 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/auxvec.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/auxvec.h
3514 --- linux-2.6.30.10/arch/ubicom32/include/asm/auxvec.h  1970-01-01 02:00:00.000000000 +0200
3515 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/auxvec.h      2009-12-11 11:45:11.000000000 +0200
3516 @@ -0,0 +1,32 @@
3517 +/*
3518 + * arch/ubicom32/include/asm/auxvec.h
3519 + *   Symbolic values for the entries in the auxiliary table
3520 + *   put on the initial stack.
3521 + *
3522 + * (C) Copyright 2009, Ubicom, Inc.
3523 + *
3524 + * This file is part of the Ubicom32 Linux Kernel Port.
3525 + *
3526 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3527 + * it and/or modify it under the terms of the GNU General Public License
3528 + * as published by the Free Software Foundation, either version 2 of the
3529 + * License, or (at your option) any later version.
3530 + *
3531 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3532 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3533 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3534 + * the GNU General Public License for more details.
3535 + *
3536 + * You should have received a copy of the GNU General Public License
3537 + * along with the Ubicom32 Linux Kernel Port.  If not,
3538 + * see <http://www.gnu.org/licenses/>.
3539 + *
3540 + * Ubicom32 implementation derived from (with many thanks):
3541 + *   arch/m68knommu
3542 + *   arch/blackfin
3543 + *   arch/parisc
3544 + */
3545 +#ifndef _ASM_UBICOM32_AUXVEC_H
3546 +#define _ASM_UBICOM32_AUXVEC_H
3547 +
3548 +#endif /* _ASM_UBICOM32_AUXVEC_H */
3549 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bitops.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bitops.h
3550 --- linux-2.6.30.10/arch/ubicom32/include/asm/bitops.h  1970-01-01 02:00:00.000000000 +0200
3551 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bitops.h      2009-12-11 11:45:11.000000000 +0200
3552 @@ -0,0 +1,172 @@
3553 +/*
3554 + * arch/ubicom32/include/asm/bitops.h
3555 + *   Bit manipulation definitions for Ubicom32 architecture.
3556 + *
3557 + * (C) Copyright 2009, Ubicom, Inc.
3558 + *
3559 + * This file is part of the Ubicom32 Linux Kernel Port.
3560 + *
3561 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3562 + * it and/or modify it under the terms of the GNU General Public License
3563 + * as published by the Free Software Foundation, either version 2 of the
3564 + * License, or (at your option) any later version.
3565 + *
3566 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3567 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3568 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3569 + * the GNU General Public License for more details.
3570 + *
3571 + * You should have received a copy of the GNU General Public License
3572 + * along with the Ubicom32 Linux Kernel Port.  If not,
3573 + * see <http://www.gnu.org/licenses/>.
3574 + *
3575 + * Ubicom32 implementation derived from (with many thanks):
3576 + *   arch/m68knommu
3577 + *   arch/blackfin
3578 + *   arch/parisc
3579 + */
3580 +#ifndef _ASM_UBICOM32_BITOPS_H
3581 +#define _ASM_UBICOM32_BITOPS_H
3582 +
3583 +/*
3584 + * Copyright 1992, Linus Torvalds.
3585 + */
3586 +
3587 +#include <linux/compiler.h>
3588 +#include <asm/byteorder.h>     /* swab32 */
3589 +
3590 +#ifdef __KERNEL__
3591 +
3592 +#ifndef _LINUX_BITOPS_H
3593 +#error only <linux/bitops.h> can be included directly
3594 +#endif
3595 +
3596 +#include <asm-generic/bitops/ffs.h>
3597 +#include <asm-generic/bitops/__ffs.h>
3598 +
3599 +#include <asm-generic/bitops/sched.h>
3600 +#include <asm-generic/bitops/ffz.h>
3601 +
3602 +#include <asm/ubicom32-common.h>
3603 +
3604 +static inline void set_bit(int bit, volatile unsigned long *p)
3605 +{
3606 +       unsigned long mask = 1UL << (bit & 31);
3607 +
3608 +       p += bit >> 5;
3609 +
3610 +       __atomic_lock_acquire();
3611 +       *p |= mask;
3612 +       __atomic_lock_release();
3613 +}
3614 +
3615 +static inline void clear_bit(int bit, volatile unsigned long *p)
3616 +{
3617 +       unsigned long mask = 1UL << (bit & 31);
3618 +
3619 +       p += bit >> 5;
3620 +
3621 +       __atomic_lock_acquire();
3622 +       *p &= ~mask;
3623 +       __atomic_lock_release();
3624 +}
3625 +
3626 +/*
3627 + * clear_bit() doesn't provide any barrier for the compiler.
3628 + */
3629 +#define smp_mb__before_clear_bit()     barrier()
3630 +#define smp_mb__after_clear_bit()      barrier()
3631 +
3632 +static inline void change_bit(int bit, volatile unsigned long *p)
3633 +{
3634 +       unsigned long mask = 1UL << (bit & 31);
3635 +
3636 +       p += bit >> 5;
3637 +
3638 +       __atomic_lock_acquire();
3639 +       *p ^= mask;
3640 +       __atomic_lock_release();
3641 +}
3642 +
3643 +static inline int test_and_set_bit(int bit, volatile unsigned long *p)
3644 +{
3645 +       unsigned int res;
3646 +       unsigned long mask = 1UL << (bit & 31);
3647 +
3648 +       p += bit >> 5;
3649 +
3650 +       __atomic_lock_acquire();
3651 +       res = *p;
3652 +       *p = res | mask;
3653 +       __atomic_lock_release();
3654 +
3655 +       return res & mask;
3656 +}
3657 +
3658 +static inline int test_and_clear_bit(int bit, volatile unsigned long *p)
3659 +{
3660 +       unsigned int res;
3661 +       unsigned long mask = 1UL << (bit & 31);
3662 +
3663 +       p += bit >> 5;
3664 +
3665 +       __atomic_lock_acquire();
3666 +       res = *p;
3667 +       *p = res & ~mask;
3668 +       __atomic_lock_release();
3669 +
3670 +       return res & mask;
3671 +}
3672 +
3673 +static inline int test_and_change_bit(int bit, volatile unsigned long *p)
3674 +{
3675 +       unsigned int res;
3676 +       unsigned long mask = 1UL << (bit & 31);
3677 +
3678 +       p += bit >> 5;
3679 +
3680 +       __atomic_lock_acquire();
3681 +       res = *p;
3682 +       *p = res ^ mask;
3683 +       __atomic_lock_release();
3684 +
3685 +       return res & mask;
3686 +}
3687 +
3688 +#include <asm-generic/bitops/non-atomic.h>
3689 +
3690 +/*
3691 + * This routine doesn't need to be atomic.
3692 + */
3693 +static inline int __constant_test_bit(int nr, const volatile unsigned long *addr)
3694 +{
3695 +       return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
3696 +}
3697 +
3698 +static inline int __test_bit(int nr, const volatile unsigned long *addr)
3699 +{
3700 +       int     * a = (int *) addr;
3701 +       int     mask;
3702 +
3703 +       a += nr >> 5;
3704 +       mask = 1 << (nr & 0x1f);
3705 +       return ((mask & *a) != 0);
3706 +}
3707 +
3708 +#define test_bit(nr,addr) (__builtin_constant_p(nr) ?  __constant_test_bit((nr),(addr)) :  __test_bit((nr),(addr)))
3709 +
3710 +#include <asm-generic/bitops/find.h>
3711 +#include <asm-generic/bitops/hweight.h>
3712 +#include <asm-generic/bitops/lock.h>
3713 +
3714 +#include <asm-generic/bitops/ext2-non-atomic.h>
3715 +#include <asm-generic/bitops/ext2-atomic.h>
3716 +#include <asm-generic/bitops/minix.h>
3717 +
3718 +#endif /* __KERNEL__ */
3719 +
3720 +#include <asm-generic/bitops/fls.h>
3721 +#include <asm-generic/bitops/__fls.h>
3722 +#include <asm-generic/bitops/fls64.h>
3723 +
3724 +#endif /* _ASM_UBICOM32_BITOPS_H */
3725 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/board.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/board.h
3726 --- linux-2.6.30.10/arch/ubicom32/include/asm/board.h   1970-01-01 02:00:00.000000000 +0200
3727 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/board.h       2009-12-11 11:45:11.000000000 +0200
3728 @@ -0,0 +1,34 @@
3729 +/*
3730 + * arch/ubicom32/include/asm/board.h
3731 + *   Board init and revision definitions for Ubicom32 architecture.
3732 + *
3733 + * (C) Copyright 2009, Ubicom, Inc.
3734 + *
3735 + * This file is part of the Ubicom32 Linux Kernel Port.
3736 + *
3737 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3738 + * it and/or modify it under the terms of the GNU General Public License
3739 + * as published by the Free Software Foundation, either version 2 of the
3740 + * License, or (at your option) any later version.
3741 + *
3742 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3743 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3744 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3745 + * the GNU General Public License for more details.
3746 + *
3747 + * You should have received a copy of the GNU General Public License
3748 + * along with the Ubicom32 Linux Kernel Port.  If not,
3749 + * see <http://www.gnu.org/licenses/>.
3750 + *
3751 + * Ubicom32 implementation derived from (with many thanks):
3752 + *   arch/m68knommu
3753 + *   arch/blackfin
3754 + *   arch/parisc
3755 + */
3756 +#ifndef _ASM_UBICOM32_BOARD_H
3757 +#define _ASM_UBICOM32_BOARD_H
3758 +
3759 +extern const char *board_get_revision(void);
3760 +extern void __init board_init(void);
3761 +
3762 +#endif /* _ASM_UBICOM32_BOARD_H */
3763 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bootargs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootargs.h
3764 --- linux-2.6.30.10/arch/ubicom32/include/asm/bootargs.h        1970-01-01 02:00:00.000000000 +0200
3765 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootargs.h    2009-12-11 11:45:11.000000000 +0200
3766 @@ -0,0 +1,34 @@
3767 +/*
3768 + * arch/ubicom32/include/asm/bootargs.h
3769 + *   Kernel command line via the devtree API.
3770 + *
3771 + * (C) Copyright 2009, Ubicom, Inc.
3772 + *
3773 + * This file is part of the Ubicom32 Linux Kernel Port.
3774 + *
3775 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3776 + * it and/or modify it under the terms of the GNU General Public License
3777 + * as published by the Free Software Foundation, either version 2 of the
3778 + * License, or (at your option) any later version.
3779 + *
3780 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3781 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3782 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3783 + * the GNU General Public License for more details.
3784 + *
3785 + * You should have received a copy of the GNU General Public License
3786 + * along with the Ubicom32 Linux Kernel Port.  If not,
3787 + * see <http://www.gnu.org/licenses/>.
3788 + *
3789 + * Ubicom32 implementation derived from (with many thanks):
3790 + *   arch/m68knommu
3791 + *   arch/blackfin
3792 + *   arch/parisc
3793 + */
3794 +#ifndef _ASM_UBICOM32_BOOTARGS_H
3795 +#define _ASM_UBICOM32_BOOTARGS_H
3796 +
3797 +extern const char *bootargs_get_cmdline(void);
3798 +extern void __init bootargs_init(void);
3799 +
3800 +#endif /* _ASM_UBICOM32_BOOTARGS_H */
3801 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bootinfo.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootinfo.h
3802 --- linux-2.6.30.10/arch/ubicom32/include/asm/bootinfo.h        1970-01-01 02:00:00.000000000 +0200
3803 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootinfo.h    2009-12-11 11:45:11.000000000 +0200
3804 @@ -0,0 +1,34 @@
3805 +/*
3806 + * arch/ubicom32/include/asm/bootinfo.h
3807 + *   Definitions of firmware boot parameters passed to the kernel.
3808 + *
3809 + * (C) Copyright 2009, Ubicom, Inc.
3810 + *
3811 + * This file is part of the Ubicom32 Linux Kernel Port.
3812 + *
3813 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3814 + * it and/or modify it under the terms of the GNU General Public License
3815 + * as published by the Free Software Foundation, either version 2 of the
3816 + * License, or (at your option) any later version.
3817 + *
3818 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3819 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3820 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3821 + * the GNU General Public License for more details.
3822 + *
3823 + * You should have received a copy of the GNU General Public License
3824 + * along with the Ubicom32 Linux Kernel Port.  If not,
3825 + * see <http://www.gnu.org/licenses/>.
3826 + *
3827 + * Ubicom32 implementation derived from (with many thanks):
3828 + *   arch/m68knommu
3829 + *   arch/blackfin
3830 + *   arch/parisc
3831 + */
3832 +
3833 +#ifndef _ASM_UBICOM32_BOOTINFO_H
3834 +#define _ASM_UBICOM32_BOOTINFO_H
3835 +
3836 +/* Nothing for ubicom32 */
3837 +
3838 +#endif /* _ASM_UBICOM32_BOOTINFO_H */
3839 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bug.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bug.h
3840 --- linux-2.6.30.10/arch/ubicom32/include/asm/bug.h     1970-01-01 02:00:00.000000000 +0200
3841 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bug.h 2009-12-11 11:45:11.000000000 +0200
3842 @@ -0,0 +1,95 @@
3843 +/*
3844 + * arch/ubicom32/include/asm/bug.h
3845 + *   Generic bug.h for Ubicom32 architecture.
3846 + *
3847 + * (C) Copyright 2009, Ubicom, Inc.
3848 + *
3849 + * This file is part of the Ubicom32 Linux Kernel Port.
3850 + *
3851 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3852 + * it and/or modify it under the terms of the GNU General Public License
3853 + * as published by the Free Software Foundation, either version 2 of the
3854 + * License, or (at your option) any later version.
3855 + *
3856 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3857 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3858 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3859 + * the GNU General Public License for more details.
3860 + *
3861 + * You should have received a copy of the GNU General Public License
3862 + * along with the Ubicom32 Linux Kernel Port.  If not,
3863 + * see <http://www.gnu.org/licenses/>.
3864 + *
3865 + * Ubicom32 implementation derived from (with many thanks):
3866 + *   arch/m68knommu
3867 + *   arch/blackfin
3868 + *   arch/parisc
3869 + */
3870 +#ifndef _ASM_UBICOM32_BUG_H
3871 +#define _ASM_UBICOM32_BUG_H
3872 +
3873 +#include <linux/kernel.h>
3874 +#include <asm/thread.h>
3875 +
3876 +#if defined(CONFIG_BUG) && defined(CONFIG_STOP_ON_BUG)
3877 +
3878 +/*
3879 + * BUG()
3880 + *     Ubicom specific version of the BUG() macro.
3881 + *
3882 + * This implementation performs a THREAD_STALL stopping all threads before
3883 + * calling panic.  This enables a developer to see the "real" state of the
3884 + * machine (since panic alters the system state).  We do the printf first
3885 + * because while it is slow, it does not alter system state (like
3886 + * interrupts).
3887 + *
3888 + * TODO: Implement the trap sequence used by other architectures.
3889 + */
3890 +#define BUG() do { \
3891 +       printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3892 +       THREAD_STALL; \
3893 +       panic("BUG!"); \
3894 +} while (0)
3895 +
3896 +
3897 +/*
3898 + * __WARN()
3899 + *     WARN() using printk() for now.
3900 + *
3901 + * TODO: Implement the trap sequence used by other architectures.
3902 + */
3903 +#define __WARN()                                                       \
3904 +       do {                                                            \
3905 +               printk("WARN: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3906 +       } while(0)
3907 +
3908 +/*
3909 + * WARN_ON()
3910 + *     Ubicom specific version of the WARN_ON macro.
3911 + *
3912 + * This implementation performs a printk for the WARN_ON() instead
3913 + * of faulting into the kernel and using report_bug().
3914 + *
3915 + * TODO: Implement the trap sequence used by other architectures.
3916 + */
3917 +#define WARN_ON(x) ({                                          \
3918 +       int __ret_warn_on = !!(x);                              \
3919 +       if (__builtin_constant_p(__ret_warn_on)) {              \
3920 +               if (__ret_warn_on)                              \
3921 +                       __WARN();                               \
3922 +       } else {                                                \
3923 +               if (unlikely(__ret_warn_on))                    \
3924 +                       __WARN();                               \
3925 +       }                                                       \
3926 +       unlikely(__ret_warn_on);                                \
3927 +})
3928 +
3929 +
3930 +#define HAVE_ARCH_BUG
3931 +#define HAVE_ARCH_WARN_ON
3932 +
3933 +#endif
3934 +
3935 +#include <asm-generic/bug.h>
3936 +
3937 +#endif /* _ASM_UBICOM32_BUG_H */
3938 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bugs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bugs.h
3939 --- linux-2.6.30.10/arch/ubicom32/include/asm/bugs.h    1970-01-01 02:00:00.000000000 +0200
3940 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bugs.h        2009-12-11 11:45:11.000000000 +0200
3941 @@ -0,0 +1,44 @@
3942 +/*
3943 + * arch/ubicom32/include/asm/bugs.h
3944 + *   Definition of check_bugs() for Ubicom32 architecture.
3945 + *
3946 + * (C) Copyright 2009, Ubicom, Inc.
3947 + * Copyright (C) 1994  Linus Torvalds
3948 + *
3949 + * This file is part of the Ubicom32 Linux Kernel Port.
3950 + *
3951 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3952 + * it and/or modify it under the terms of the GNU General Public License
3953 + * as published by the Free Software Foundation, either version 2 of the
3954 + * License, or (at your option) any later version.
3955 + *
3956 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3957 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3958 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3959 + * the GNU General Public License for more details.
3960 + *
3961 + * You should have received a copy of the GNU General Public License
3962 + * along with the Ubicom32 Linux Kernel Port.  If not,
3963 + * see <http://www.gnu.org/licenses/>.
3964 + *
3965 + * Ubicom32 implementation derived from (with many thanks):
3966 + *   arch/m68knommu
3967 + *   arch/blackfin
3968 + *   arch/parisc
3969 + */
3970 +
3971 +/*
3972 + * This is included by init/main.c to check for architecture-dependent bugs.
3973 + *
3974 + * Needs:
3975 + *     void check_bugs(void);
3976 + */
3977 +
3978 +#ifndef _ASM_UBICOM32_BUGS_H
3979 +#define _ASM_UBICOM32_BUGS_H
3980 +
3981 +static void check_bugs(void)
3982 +{
3983 +}
3984 +
3985 +#endif /* _ASM_UBICOM32_BUGS_H */
3986 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/byteorder.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/byteorder.h
3987 --- linux-2.6.30.10/arch/ubicom32/include/asm/byteorder.h       1970-01-01 02:00:00.000000000 +0200
3988 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/byteorder.h   2009-12-11 11:45:11.000000000 +0200
3989 @@ -0,0 +1,33 @@
3990 +/*
3991 + * arch/ubicom32/include/asm/byteorder.h
3992 + *   Byte order swapping utility routines.
3993 + *
3994 + * (C) Copyright 2009, Ubicom, Inc.
3995 + *
3996 + * This file is part of the Ubicom32 Linux Kernel Port.
3997 + *
3998 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3999 + * it and/or modify it under the terms of the GNU General Public License
4000 + * as published by the Free Software Foundation, either version 2 of the
4001 + * License, or (at your option) any later version.
4002 + *
4003 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4004 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4005 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4006 + * the GNU General Public License for more details.
4007 + *
4008 + * You should have received a copy of the GNU General Public License
4009 + * along with the Ubicom32 Linux Kernel Port.  If not,
4010 + * see <http://www.gnu.org/licenses/>.
4011 + *
4012 + * Ubicom32 implementation derived from (with many thanks):
4013 + *   arch/m68knommu
4014 + *   arch/blackfin
4015 + *   arch/parisc
4016 + */
4017 +#ifndef _ASM_UBICOM32_BYTEORDER_H
4018 +#define _ASM_UBICOM32_BYTEORDER_H
4019 +
4020 +#include <linux/byteorder/big_endian.h>
4021 +
4022 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
4023 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cachectl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cachectl.h
4024 --- linux-2.6.30.10/arch/ubicom32/include/asm/cachectl.h        1970-01-01 02:00:00.000000000 +0200
4025 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cachectl.h    2009-12-11 11:45:11.000000000 +0200
4026 @@ -0,0 +1,39 @@
4027 +/*
4028 + * arch/ubicom32/include/asm/cachectl.h
4029 + *   Ubicom32 cache control definitions.
4030 + *
4031 + * (C) Copyright 2009, Ubicom, Inc.
4032 + *
4033 + * This file is part of the Ubicom32 Linux Kernel Port.
4034 + *
4035 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4036 + * it and/or modify it under the terms of the GNU General Public License
4037 + * as published by the Free Software Foundation, either version 2 of the
4038 + * License, or (at your option) any later version.
4039 + *
4040 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4041 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4042 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4043 + * the GNU General Public License for more details.
4044 + *
4045 + * You should have received a copy of the GNU General Public License
4046 + * along with the Ubicom32 Linux Kernel Port.  If not,
4047 + * see <http://www.gnu.org/licenses/>.
4048 + *
4049 + * Ubicom32 implementation derived from (with many thanks):
4050 + *   arch/m68knommu
4051 + *   arch/blackfin
4052 + *   arch/parisc
4053 + */
4054 +#ifndef _ASM_UBICOM32_CACHECTL_H
4055 +#define _ASM_UBICOM32_CACHECTL_H
4056 +
4057 +#include <asm/ip5000.h>
4058 +
4059 +/*
4060 + * mem_cache_control()
4061 + *     Special cache control operation
4062 + */
4063 +extern void mem_cache_control(unsigned long cc, unsigned long begin_addr, unsigned long end_addr, unsigned long op);
4064 +
4065 +#endif /* _ASM_UBICOM32_CACHECTL_H */
4066 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cacheflush.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cacheflush.h
4067 --- linux-2.6.30.10/arch/ubicom32/include/asm/cacheflush.h      1970-01-01 02:00:00.000000000 +0200
4068 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cacheflush.h  2009-12-11 11:45:11.000000000 +0200
4069 @@ -0,0 +1,111 @@
4070 +/*
4071 + * arch/ubicom32/include/asm/cacheflush.h
4072 + *   Cache flushing definitions for Ubicom32 architecture.
4073 + *
4074 + * (C) Copyright 2009, Ubicom, Inc.
4075 + *
4076 + * This file is part of the Ubicom32 Linux Kernel Port.
4077 + *
4078 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4079 + * it and/or modify it under the terms of the GNU General Public License
4080 + * as published by the Free Software Foundation, either version 2 of the
4081 + * License, or (at your option) any later version.
4082 + *
4083 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4084 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4085 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4086 + * the GNU General Public License for more details.
4087 + *
4088 + * You should have received a copy of the GNU General Public License
4089 + * along with the Ubicom32 Linux Kernel Port.  If not,
4090 + * see <http://www.gnu.org/licenses/>.
4091 + *
4092 + * Ubicom32 implementation derived from (with many thanks):
4093 + *   arch/m68knommu
4094 + *   arch/blackfin
4095 + *   arch/parisc
4096 + */
4097 +#ifndef _ASM_UBICOM32_CACHEFLUSH_H
4098 +#define _ASM_UBICOM32_CACHEFLUSH_H
4099 +
4100 +/*
4101 + * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
4102 + */
4103 +#include <linux/mm.h>
4104 +#include <asm/cachectl.h>
4105 +#include <asm/ip5000.h>
4106 +
4107 +#define flush_cache_all()                      __flush_cache_all()
4108 +#define flush_cache_mm(mm)                     do { } while (0)
4109 +#define flush_cache_dup_mm(mm)                 do { } while (0)
4110 +#define flush_cache_range(vma, start, end)     __flush_cache_all()
4111 +#define flush_cache_page(vma, vmaddr)          do { } while (0)
4112 +#define flush_dcache_page(page)                        do { } while (0)
4113 +#define flush_dcache_mmap_lock(mapping)                do { } while (0)
4114 +#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
4115 +
4116 +#define flush_dcache_range(start, end)                                 \
4117 +do {                                                                   \
4118 +       /* Flush the data cache and invalidate the I cache. */          \
4119 +       mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR);  \
4120 +       mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR);    \
4121 +} while (0)
4122 +
4123 +#define flush_icache_range(start, end)                                 \
4124 +do {                                                                   \
4125 +       /* Flush the data cache and invalidate the I cache. */          \
4126 +       mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR);  \
4127 +       mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR);    \
4128 +} while (0)
4129 +
4130 +#define flush_icache_page(vma,pg)              do { } while (0)
4131 +#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
4132 +#define flush_cache_vmap(start, end)           do { } while (0)
4133 +#define flush_cache_vunmap(start, end)         do { } while (0)
4134 +
4135 +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
4136 +       memcpy(dst, src, len)
4137 +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
4138 +       memcpy(dst, src, len)
4139 +
4140 +/*
4141 + * Cache handling for IP5000
4142 + */
4143 +extern inline void mem_cache_invalidate_all(unsigned long cc)
4144 +{
4145 +       if (cc == DCCR_BASE)
4146 +               UBICOM32_LOCK(DCCR_LOCK_BIT);
4147 +       else
4148 +               UBICOM32_LOCK(ICCR_LOCK_BIT);
4149 +
4150 +       asm volatile (
4151 +       "       bset    "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)"      \n\t"
4152 +       "       nop                                                                     \n\t"
4153 +       "       bclr    "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)"      \n\t"
4154 +       "       pipe_flush 0                                                            \n\t"
4155 +               :
4156 +               : "a"(cc)
4157 +               : "cc"
4158 +       );
4159 +
4160 +       if (cc == DCCR_BASE)
4161 +               UBICOM32_UNLOCK(DCCR_LOCK_BIT);
4162 +       else
4163 +               UBICOM32_UNLOCK(ICCR_LOCK_BIT);
4164 +
4165 +}
4166 +
4167 +static inline void __flush_cache_all(void)
4168 +{
4169 +       /*
4170 +        * Flush Icache
4171 +        */
4172 +       mem_cache_invalidate_all(ICCR_BASE);
4173 +
4174 +       /*
4175 +        * Flush Dcache
4176 +        */
4177 +       mem_cache_invalidate_all(DCCR_BASE);
4178 +}
4179 +
4180 +#endif /* _ASM_UBICOM32_CACHEFLUSH_H */
4181 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cache.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cache.h
4182 --- linux-2.6.30.10/arch/ubicom32/include/asm/cache.h   1970-01-01 02:00:00.000000000 +0200
4183 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cache.h       2009-12-11 11:45:11.000000000 +0200
4184 @@ -0,0 +1,40 @@
4185 +/*
4186 + * arch/ubicom32/include/asm/cache.h
4187 + *   Cache line definitions for Ubicom32 architecture.
4188 + *
4189 + * (C) Copyright 2009, Ubicom, Inc.
4190 + *
4191 + * This file is part of the Ubicom32 Linux Kernel Port.
4192 + *
4193 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4194 + * it and/or modify it under the terms of the GNU General Public License
4195 + * as published by the Free Software Foundation, either version 2 of the
4196 + * License, or (at your option) any later version.
4197 + *
4198 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4199 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4200 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4201 + * the GNU General Public License for more details.
4202 + *
4203 + * You should have received a copy of the GNU General Public License
4204 + * along with the Ubicom32 Linux Kernel Port.  If not,
4205 + * see <http://www.gnu.org/licenses/>.
4206 + *
4207 + * Ubicom32 implementation derived from (with many thanks):
4208 + *   arch/m68knommu
4209 + *   arch/blackfin
4210 + *   arch/parisc
4211 + */
4212 +#ifndef _ASM_UBICOM32_CACHE_H
4213 +#define _ASM_UBICOM32_CACHE_H
4214 +
4215 +/*
4216 + * bytes per L1 cache line
4217 + */
4218 +#define L1_CACHE_SHIFT  5
4219 +#define L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)
4220 +
4221 +#define __cacheline_aligned
4222 +#define ____cacheline_aligned
4223 +
4224 +#endif /* _ASM_UBICOM32_CACHE_H */
4225 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/checksum.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/checksum.h
4226 --- linux-2.6.30.10/arch/ubicom32/include/asm/checksum.h        1970-01-01 02:00:00.000000000 +0200
4227 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/checksum.h    2009-12-11 11:45:11.000000000 +0200
4228 @@ -0,0 +1,149 @@
4229 +/*
4230 + * arch/ubicom32/include/asm/checksum.h
4231 + *   Checksum utilities for Ubicom32 architecture.
4232 + *
4233 + * (C) Copyright 2009, Ubicom, Inc.
4234 + *
4235 + * This file is part of the Ubicom32 Linux Kernel Port.
4236 + *
4237 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4238 + * it and/or modify it under the terms of the GNU General Public License
4239 + * as published by the Free Software Foundation, either version 2 of the
4240 + * License, or (at your option) any later version.
4241 + *
4242 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4243 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4244 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4245 + * the GNU General Public License for more details.
4246 + *
4247 + * You should have received a copy of the GNU General Public License
4248 + * along with the Ubicom32 Linux Kernel Port.  If not,
4249 + * see <http://www.gnu.org/licenses/>.
4250 + *
4251 + * Ubicom32 implementation derived from (with many thanks):
4252 + *   arch/m68knommu
4253 + *   arch/blackfin
4254 + *   arch/parisc
4255 + */
4256 +#ifndef _ASM_UBICOM32_CHECKSUM_H
4257 +#define _ASM_UBICOM32_CHECKSUM_H
4258 +
4259 +#include <linux/in6.h>
4260 +
4261 +/*
4262 + * computes the checksum of a memory block at buff, length len,
4263 + * and adds in "sum" (32-bit)
4264 + *
4265 + * returns a 32-bit number suitable for feeding into itself
4266 + * or csum_tcpudp_magic
4267 + *
4268 + * this function must be called with even lengths, except
4269 + * for the last fragment, which may be odd
4270 + *
4271 + * it's best to have buff aligned on a 32-bit boundary
4272 + */
4273 +__wsum csum_partial(const void *buff, int len, __wsum sum);
4274 +
4275 +/*
4276 + * the same as csum_partial, but copies from src while it
4277 + * checksums
4278 + *
4279 + * here even more important to align src and dst on a 32-bit (or even
4280 + * better 64-bit) boundary
4281 + */
4282 +
4283 +__wsum csum_partial_copy_nocheck(const void *src, void *dst,
4284 +       int len, __wsum sum);
4285 +
4286 +
4287 +/*
4288 + * the same as csum_partial_copy, but copies from user space.
4289 + *
4290 + * here even more important to align src and dst on a 32-bit (or even
4291 + * better 64-bit) boundary
4292 + */
4293 +
4294 +extern __wsum csum_partial_copy_from_user(const void __user *src,
4295 +       void *dst, int len, __wsum sum, int *csum_err);
4296 +
4297 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
4298 +
4299 +/*
4300 + *     Fold a partial checksum
4301 + */
4302 +
4303 +static inline __sum16 csum_fold(__wsum sum)
4304 +{
4305 +       asm volatile (
4306 +       "       lsr.4   d15, %0, #16    \n\t"
4307 +       "       bfextu  %0, %0, #16     \n\t"
4308 +       "       add.4   %0, d15, %0     \n\t"
4309 +       "       lsr.4   d15, %0, #16    \n\t"
4310 +       "       bfextu  %0, %0, #16     \n\t"
4311 +       "       add.4   %0, d15, %0     \n\t"
4312 +               : "=&d" (sum)
4313 +               : "0"(sum)
4314 +               : "d15"
4315 +       );
4316 +       return (__force __sum16)~sum;
4317 +}
4318 +
4319 +
4320 +/*
4321 + * computes the checksum of the TCP/UDP pseudo-header
4322 + * returns a 16-bit checksum, already complemented
4323 + */
4324 +
4325 +static inline __wsum
4326 +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
4327 +                 unsigned short proto, __wsum sum)
4328 +{
4329 +       asm volatile (
4330 +       "       add.4   %0, %2, %0      \n\t"
4331 +       "       addc    %0, %3, %0      \n\t"
4332 +       "       addc    %0, %4, %0      \n\t"
4333 +       "       addc    %0, %5, %0      \n\t"
4334 +       "       addc    %0, #0, %0      \n\t"
4335 +               : "=&d" (sum)
4336 +               : "0"(sum), "r" (saddr), "r" (daddr), "r" (len), "r"(proto)
4337 +       );
4338 +       return sum;
4339 +}
4340 +
4341 +static inline __sum16
4342 +csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
4343 +                 unsigned short proto, __wsum sum)
4344 +{
4345 +       return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
4346 +}
4347 +
4348 +/*
4349 + * this routine is used for miscellaneous IP-like checksums, mainly
4350 + * in icmp.c
4351 + */
4352 +extern __sum16 ip_compute_csum(const void *buff, int len);
4353 +
4354 +#define _HAVE_ARCH_IPV6_CSUM
4355 +
4356 +static __inline__ __sum16
4357 +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
4358 +               __u32 len, unsigned short proto, __wsum sum)
4359 +{
4360 +       asm volatile (
4361 +       "       add.4   %0, 0(%2), %0   \n\t"
4362 +       "       addc    %0, 4(%2), %0   \n\t"
4363 +       "       addc    %0, 8(%2), %0   \n\t"
4364 +       "       addc    %0, 12(%2), %0  \n\t"
4365 +       "       addc    %0, 0(%3), %0   \n\t"
4366 +       "       addc    %0, 4(%3), %0   \n\t"
4367 +       "       addc    %0, 8(%3), %0   \n\t"
4368 +       "       addc    %0, 12(%3), %0  \n\t"
4369 +       "       addc    %0, %4, %0      \n\t"
4370 +       "       addc    %0, #0, %0      \n\t"
4371 +               : "=&d" (sum)
4372 +               : "0" (sum), "a" (saddr), "a" (daddr), "d" (len + proto)
4373 +       );
4374 +       return csum_fold(sum);
4375 +}
4376 +
4377 +#endif /* _ASM_UBICOM32_CHECKSUM_H */
4378 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cpu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cpu.h
4379 --- linux-2.6.30.10/arch/ubicom32/include/asm/cpu.h     1970-01-01 02:00:00.000000000 +0200
4380 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cpu.h 2009-12-11 11:45:11.000000000 +0200
4381 @@ -0,0 +1,45 @@
4382 +/*
4383 + * arch/ubicom32/include/asm/cpu.h
4384 + *   CPU definitions for Ubicom32 architecture.
4385 + *
4386 + * (C) Copyright 2009, Ubicom, Inc.
4387 + * Copyright (C) 2004-2005 ARM Ltd.
4388 + *
4389 + * This file is part of the Ubicom32 Linux Kernel Port.
4390 + *
4391 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4392 + * it and/or modify it under the terms of the GNU General Public License
4393 + * as published by the Free Software Foundation, either version 2 of the
4394 + * License, or (at your option) any later version.
4395 + *
4396 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4397 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4398 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4399 + * the GNU General Public License for more details.
4400 + *
4401 + * You should have received a copy of the GNU General Public License
4402 + * along with the Ubicom32 Linux Kernel Port.  If not,
4403 + * see <http://www.gnu.org/licenses/>.
4404 + *
4405 + * Ubicom32 implementation derived from (with many thanks):
4406 + *   arch/m68knommu
4407 + *   arch/blackfin
4408 + *   arch/parisc
4409 + */
4410 +#ifndef _ASM_UBICOM32_CPU_H
4411 +#define _ASM_UBICOM32_CPU_H
4412 +
4413 +#include <linux/percpu.h>
4414 +
4415 +struct cpuinfo_ubicom32 {
4416 +       unsigned long tid;                      /* Hardware thread number */
4417 +
4418 +#ifdef CONFIG_SMP
4419 +       volatile unsigned long ipi_pending;     /* Bit map of operations to execute */
4420 +       unsigned long ipi_count;                /* Number of IPI(s) taken on this cpu */
4421 +#endif
4422 +};
4423 +
4424 +DECLARE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
4425 +
4426 +#endif /* _ASM_UBICOM32_CPU_H */
4427 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cputime.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cputime.h
4428 --- linux-2.6.30.10/arch/ubicom32/include/asm/cputime.h 1970-01-01 02:00:00.000000000 +0200
4429 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cputime.h     2009-12-11 11:45:11.000000000 +0200
4430 @@ -0,0 +1,33 @@
4431 +/*
4432 + * arch/ubicom32/include/asm/cputime.h
4433 + *   Generic cputime.h for Ubicom32 architecture.
4434 + *
4435 + * (C) Copyright 2009, Ubicom, Inc.
4436 + *
4437 + * This file is part of the Ubicom32 Linux Kernel Port.
4438 + *
4439 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4440 + * it and/or modify it under the terms of the GNU General Public License
4441 + * as published by the Free Software Foundation, either version 2 of the
4442 + * License, or (at your option) any later version.
4443 + *
4444 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4445 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4446 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4447 + * the GNU General Public License for more details.
4448 + *
4449 + * You should have received a copy of the GNU General Public License
4450 + * along with the Ubicom32 Linux Kernel Port.  If not,
4451 + * see <http://www.gnu.org/licenses/>.
4452 + *
4453 + * Ubicom32 implementation derived from (with many thanks):
4454 + *   arch/m68knommu
4455 + *   arch/blackfin
4456 + *   arch/parisc
4457 + */
4458 +#ifndef _ASM_UBICOM32_CPUTIME_H
4459 +#define _ASM_UBICOM32_CPUTIME_H
4460 +
4461 +#include <asm-generic/cputime.h>
4462 +
4463 +#endif /* _ASM_UBICOM32_CPUTIME_H */
4464 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/current.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/current.h
4465 --- linux-2.6.30.10/arch/ubicom32/include/asm/current.h 1970-01-01 02:00:00.000000000 +0200
4466 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/current.h     2009-12-11 11:45:11.000000000 +0200
4467 @@ -0,0 +1,44 @@
4468 +/*
4469 + * arch/ubicom32/include/asm/current.h
4470 + *   Definition of get_current() for Ubicom32 architecture.
4471 + *
4472 + * (C) Copyright 2009, Ubicom, Inc.
4473 + * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
4474 + * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
4475 + *
4476 + * This file is part of the Ubicom32 Linux Kernel Port.
4477 + *
4478 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4479 + * it and/or modify it under the terms of the GNU General Public License
4480 + * as published by the Free Software Foundation, either version 2 of the
4481 + * License, or (at your option) any later version.
4482 + *
4483 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4484 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4485 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4486 + * the GNU General Public License for more details.
4487 + *
4488 + * You should have received a copy of the GNU General Public License
4489 + * along with the Ubicom32 Linux Kernel Port.  If not,
4490 + * see <http://www.gnu.org/licenses/>.
4491 + *
4492 + * Ubicom32 implementation derived from (with many thanks):
4493 + *   arch/m68knommu
4494 + *   arch/blackfin
4495 + *   arch/parisc
4496 + */
4497 +#ifndef _ASM_UBICOM32_CURRENT_H
4498 +#define _ASM_UBICOM32_CURRENT_H
4499 +
4500 +#include <linux/thread_info.h>
4501 +
4502 +struct task_struct;
4503 +
4504 +static inline struct task_struct *get_current(void)
4505 +{
4506 +       return(current_thread_info()->task);
4507 +}
4508 +
4509 +#define        current get_current()
4510 +
4511 +#endif /* _ASM_UBICOM32_CURRENT_H */
4512 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/delay.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/delay.h
4513 --- linux-2.6.30.10/arch/ubicom32/include/asm/delay.h   1970-01-01 02:00:00.000000000 +0200
4514 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/delay.h       2009-12-11 11:45:11.000000000 +0200
4515 @@ -0,0 +1,75 @@
4516 +/*
4517 + * arch/ubicom32/include/asm/delay.h
4518 + *   Definition of delay routines for Ubicom32 architecture.
4519 + *
4520 + * (C) Copyright 2009, Ubicom, Inc.
4521 + *
4522 + * This file is part of the Ubicom32 Linux Kernel Port.
4523 + *
4524 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4525 + * it and/or modify it under the terms of the GNU General Public License
4526 + * as published by the Free Software Foundation, either version 2 of the
4527 + * License, or (at your option) any later version.
4528 + *
4529 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4530 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4531 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4532 + * the GNU General Public License for more details.
4533 + *
4534 + * You should have received a copy of the GNU General Public License
4535 + * along with the Ubicom32 Linux Kernel Port.  If not,
4536 + * see <http://www.gnu.org/licenses/>.
4537 + *
4538 + * Ubicom32 implementation derived from (with many thanks):
4539 + *   arch/m68knommu
4540 + *   arch/blackfin
4541 + *   arch/parisc
4542 + */
4543 +#ifndef _ASM_UBICOM32_DELAY_H
4544 +#define _ASM_UBICOM32_DELAY_H
4545 +
4546 +#include <asm/param.h>
4547 +#include <asm/ip5000.h>
4548 +
4549 +static inline void __delay(unsigned long loops)
4550 +{
4551 +       if (loops == 0) {
4552 +               return;
4553 +       }
4554 +
4555 +       asm volatile (
4556 +       "1:     add.4   %0, #-1, %0             \n\t"
4557 +       "       jmpne.t 1b                      \n\t"
4558 +       : "+d" (loops)
4559 +       );
4560 +}
4561 +
4562 +/*
4563 + *     Ubicom32 processor uses fixed 12MHz external OSC.
4564 + *     So we use that as reference to count 12 cycles/us
4565 + */
4566 +
4567 +extern unsigned long loops_per_jiffy;
4568 +
4569 +static inline void _udelay(unsigned long usecs)
4570 +{
4571 +#if defined(CONFIG_UBICOM32_V4) || defined(CONFIG_UBICOM32_V3)
4572 +       asm volatile (
4573 +               "       add.4           d15, 0(%0), %1                  \n\t"
4574 +               "       sub.4           #0, 0(%0), d15                  \n\t"
4575 +               "       jmpmi.w.f       .-4                             \n\t"
4576 +               :
4577 +               : "a"(TIMER_BASE + TIMER_MPTVAL), "d"(usecs * (12000000/1000000))
4578 +               : "d15"
4579 +       );
4580 +#else
4581 +       BUG();
4582 +#endif
4583 +}
4584 +
4585 +/*
4586 + *     Moved the udelay() function into library code, no longer inlined.
4587 + */
4588 +extern void udelay(unsigned long usecs);
4589 +
4590 +#endif /* _ASM_UBICOM32_DELAY_H */
4591 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/device.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/device.h
4592 --- linux-2.6.30.10/arch/ubicom32/include/asm/device.h  1970-01-01 02:00:00.000000000 +0200
4593 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/device.h      2009-12-11 11:45:11.000000000 +0200
4594 @@ -0,0 +1,35 @@
4595 +/*
4596 + * arch/ubicom32/include/asm/device.h
4597 + *   Generic device.h for Ubicom32 architecture.
4598 + *
4599 + *   Used for arch specific extensions to struct device
4600 + *
4601 + * (C) Copyright 2009, Ubicom, Inc.
4602 + *
4603 + * This file is part of the Ubicom32 Linux Kernel Port.
4604 + *
4605 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4606 + * it and/or modify it under the terms of the GNU General Public License
4607 + * as published by the Free Software Foundation, either version 2 of the
4608 + * License, or (at your option) any later version.
4609 + *
4610 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4611 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4612 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4613 + * the GNU General Public License for more details.
4614 + *
4615 + * You should have received a copy of the GNU General Public License
4616 + * along with the Ubicom32 Linux Kernel Port.  If not,
4617 + * see <http://www.gnu.org/licenses/>.
4618 + *
4619 + * Ubicom32 implementation derived from (with many thanks):
4620 + *   arch/m68knommu
4621 + *   arch/blackfin
4622 + *   arch/parisc
4623 + */
4624 +#ifndef _ASM_UBICOM32_DEVICE_H
4625 +#define _ASM_UBICOM32_DEVICE_H
4626 +
4627 +#include <asm-generic/device.h>
4628 +
4629 +#endif /* _ASM_UBICOM32_DEVICE_H */
4630 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/devtree.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/devtree.h
4631 --- linux-2.6.30.10/arch/ubicom32/include/asm/devtree.h 1970-01-01 02:00:00.000000000 +0200
4632 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/devtree.h     2009-12-11 11:45:11.000000000 +0200
4633 @@ -0,0 +1,52 @@
4634 +/*
4635 + * arch/ubicom32/include/asm/devtree.h
4636 + *   Device Tree Header File (Shared between ultra and the Host OS)
4637 + *
4638 + * (C) Copyright 2009, Ubicom, Inc.
4639 + *
4640 + * This file is part of the Ubicom32 Linux Kernel Port.
4641 + *
4642 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4643 + * it and/or modify it under the terms of the GNU General Public License
4644 + * as published by the Free Software Foundation, either version 2 of the
4645 + * License, or (at your option) any later version.
4646 + *
4647 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4648 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4649 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4650 + * the GNU General Public License for more details.
4651 + *
4652 + * You should have received a copy of the GNU General Public License
4653 + * along with the Ubicom32 Linux Kernel Port.  If not,
4654 + * see <http://www.gnu.org/licenses/>.
4655 + *
4656 + * Ubicom32 implementation derived from (with many thanks):
4657 + *   arch/m68knommu
4658 + *   arch/blackfin
4659 + *   arch/parisc
4660 + */
4661 +
4662 +#ifndef _ASM_UBICOM32_DEVTREE_H
4663 +#define _ASM_UBICOM32_DEVTREE_H
4664 +
4665 +#define DEVTREE_MAX_NAME 32
4666 +#define DEVTREE_IRQ_NONE 0xff
4667 +#define DEVTREE_IRQ_DONTCARE 0xff
4668 +#define DEVTREE_NODE_MAGIC 0x10203040
4669 +
4670 +struct devtree_node {
4671 +       struct devtree_node *next;
4672 +       unsigned char sendirq;
4673 +       unsigned char recvirq;
4674 +       char name[DEVTREE_MAX_NAME];
4675 +       unsigned int magic;
4676 +};
4677 +
4678 +extern struct devtree_node *devtree;
4679 +extern struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq);
4680 +extern struct devtree_node *devtree_find_node(const char *str);
4681 +extern struct devtree_node *devtree_find_next(struct devtree_node **cur);
4682 +extern int devtree_irq(struct devtree_node *dn, unsigned char *sendirq, unsigned char *recvirq);
4683 +extern void devtree_print(void);
4684 +
4685 +#endif /* _ASM_UBICOM32_DEVTREE_H */
4686 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/div64.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/div64.h
4687 --- linux-2.6.30.10/arch/ubicom32/include/asm/div64.h   1970-01-01 02:00:00.000000000 +0200
4688 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/div64.h       2009-12-11 11:45:11.000000000 +0200
4689 @@ -0,0 +1,33 @@
4690 +/*
4691 + * arch/ubicom32/include/asm/div64.h
4692 + *   Generic div64.h for Ubicom32 architecture.
4693 + *
4694 + * (C) Copyright 2009, Ubicom, Inc.
4695 + *
4696 + * This file is part of the Ubicom32 Linux Kernel Port.
4697 + *
4698 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4699 + * it and/or modify it under the terms of the GNU General Public License
4700 + * as published by the Free Software Foundation, either version 2 of the
4701 + * License, or (at your option) any later version.
4702 + *
4703 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4704 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4705 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4706 + * the GNU General Public License for more details.
4707 + *
4708 + * You should have received a copy of the GNU General Public License
4709 + * along with the Ubicom32 Linux Kernel Port.  If not,
4710 + * see <http://www.gnu.org/licenses/>.
4711 + *
4712 + * Ubicom32 implementation derived from (with many thanks):
4713 + *   arch/m68knommu
4714 + *   arch/blackfin
4715 + *   arch/parisc
4716 + */
4717 +#ifndef _ASM_UBICOM32_DIV64_H
4718 +#define _ASM_UBICOM32_DIV64_H
4719 +
4720 +#include <asm-generic/div64.h>
4721 +
4722 +#endif /* _ASM_UBICOM32_DIV64_H */
4723 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/dma.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma.h
4724 --- linux-2.6.30.10/arch/ubicom32/include/asm/dma.h     1970-01-01 02:00:00.000000000 +0200
4725 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma.h 2009-12-11 11:45:11.000000000 +0200
4726 @@ -0,0 +1,34 @@
4727 +/*
4728 + * arch/ubicom32/include/asm/dma.h
4729 + *   DMA definitions for Ubicom32 architecture.
4730 + *
4731 + * (C) Copyright 2009, Ubicom, Inc.
4732 + *
4733 + * This file is part of the Ubicom32 Linux Kernel Port.
4734 + *
4735 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4736 + * it and/or modify it under the terms of the GNU General Public License
4737 + * as published by the Free Software Foundation, either version 2 of the
4738 + * License, or (at your option) any later version.
4739 + *
4740 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4741 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4742 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4743 + * the GNU General Public License for more details.
4744 + *
4745 + * You should have received a copy of the GNU General Public License
4746 + * along with the Ubicom32 Linux Kernel Port.  If not,
4747 + * see <http://www.gnu.org/licenses/>.
4748 + *
4749 + * Ubicom32 implementation derived from (with many thanks):
4750 + *   arch/m68knommu
4751 + *   arch/blackfin
4752 + *   arch/parisc
4753 + */
4754 +#ifndef _ASM_UBICOM32_DMA_H
4755 +#define _ASM_UBICOM32_DMA_H
4756 +
4757 +/* Nothing so far */
4758 +#define MAX_DMA_ADDRESS 0x00   /* This is quite suspicious */
4759 +
4760 +#endif /* _ASM_UBICOM32_DMA_H */
4761 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/dma-mapping.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma-mapping.h
4762 --- linux-2.6.30.10/arch/ubicom32/include/asm/dma-mapping.h     1970-01-01 02:00:00.000000000 +0200
4763 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma-mapping.h 2009-12-11 11:45:11.000000000 +0200
4764 @@ -0,0 +1,328 @@
4765 +/*
4766 + * arch/ubicom32/include/asm/dma-mapping.h
4767 + *   Generic dma-mapping.h for Ubicom32 architecture.
4768 + *
4769 + * (C) Copyright 2009, Ubicom, Inc.
4770 + *
4771 + * This file is part of the Ubicom32 Linux Kernel Port.
4772 + *
4773 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4774 + * it and/or modify it under the terms of the GNU General Public License
4775 + * as published by the Free Software Foundation, either version 2 of the
4776 + * License, or (at your option) any later version.
4777 + *
4778 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4779 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4780 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4781 + * the GNU General Public License for more details.
4782 + *
4783 + * You should have received a copy of the GNU General Public License
4784 + * along with the Ubicom32 Linux Kernel Port.  If not,
4785 + * see <http://www.gnu.org/licenses/>.
4786 + *
4787 + * Ubicom32 implementation derived from (with many thanks):
4788 + *   arch/m68knommu
4789 + *   arch/blackfin
4790 + *   arch/parisc
4791 + */
4792 +#ifndef _ASM_UBICOM32_DMA_MAPPING_H
4793 +#define _ASM_UBICOM32_DMA_MAPPING_H
4794 +
4795 +#include <linux/scatterlist.h>
4796 +#ifdef CONFIG_PCI
4797 +
4798 +/* we implement the API below in terms of the existing PCI one,
4799 + * so include it */
4800 +#include <linux/pci.h>
4801 +/* need struct page definitions */
4802 +#include <linux/mm.h>
4803 +
4804 +static inline int
4805 +dma_supported(struct device *dev, u64 mask)
4806 +{
4807 +       BUG_ON(dev->bus != &pci_bus_type);
4808 +
4809 +       return pci_dma_supported(to_pci_dev(dev), mask);
4810 +}
4811 +
4812 +static inline int
4813 +dma_set_mask(struct device *dev, u64 dma_mask)
4814 +{
4815 +       BUG_ON(dev->bus != &pci_bus_type);
4816 +
4817 +       return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
4818 +}
4819 +
4820 +static inline void *
4821 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4822 +                  gfp_t flag)
4823 +{
4824 +       BUG_ON(dev->bus != &pci_bus_type);
4825 +
4826 +       return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
4827 +}
4828 +
4829 +static inline void
4830 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4831 +                   dma_addr_t dma_handle)
4832 +{
4833 +       BUG_ON(dev->bus != &pci_bus_type);
4834 +
4835 +       pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
4836 +}
4837 +
4838 +static inline dma_addr_t
4839 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4840 +              enum dma_data_direction direction)
4841 +{
4842 +       BUG_ON(dev->bus != &pci_bus_type);
4843 +
4844 +       return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
4845 +}
4846 +
4847 +static inline void
4848 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4849 +                enum dma_data_direction direction)
4850 +{
4851 +       BUG_ON(dev->bus != &pci_bus_type);
4852 +
4853 +       pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
4854 +}
4855 +
4856 +static inline dma_addr_t
4857 +dma_map_page(struct device *dev, struct page *page,
4858 +            unsigned long offset, size_t size,
4859 +            enum dma_data_direction direction)
4860 +{
4861 +       BUG_ON(dev->bus != &pci_bus_type);
4862 +
4863 +       return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
4864 +}
4865 +
4866 +static inline void
4867 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4868 +              enum dma_data_direction direction)
4869 +{
4870 +       BUG_ON(dev->bus != &pci_bus_type);
4871 +
4872 +       pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
4873 +}
4874 +
4875 +static inline int
4876 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
4877 +          enum dma_data_direction direction)
4878 +{
4879 +       BUG_ON(dev->bus != &pci_bus_type);
4880 +
4881 +       return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
4882 +}
4883 +
4884 +static inline void
4885 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
4886 +            enum dma_data_direction direction)
4887 +{
4888 +       BUG_ON(dev->bus != &pci_bus_type);
4889 +
4890 +       pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
4891 +}
4892 +
4893 +static inline void
4894 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
4895 +                       enum dma_data_direction direction)
4896 +{
4897 +       BUG_ON(dev->bus != &pci_bus_type);
4898 +
4899 +       pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
4900 +                                   size, (int)direction);
4901 +}
4902 +
4903 +static inline void
4904 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
4905 +                          enum dma_data_direction direction)
4906 +{
4907 +       BUG_ON(dev->bus != &pci_bus_type);
4908 +
4909 +       pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
4910 +                                      size, (int)direction);
4911 +}
4912 +
4913 +static inline void
4914 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
4915 +                   enum dma_data_direction direction)
4916 +{
4917 +       BUG_ON(dev->bus != &pci_bus_type);
4918 +
4919 +       pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
4920 +}
4921 +
4922 +static inline void
4923 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
4924 +                      enum dma_data_direction direction)
4925 +{
4926 +       BUG_ON(dev->bus != &pci_bus_type);
4927 +
4928 +       pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
4929 +}
4930 +
4931 +static inline int
4932 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
4933 +{
4934 +       return pci_dma_mapping_error(to_pci_dev(dev), dma_addr);
4935 +}
4936 +
4937 +
4938 +#else
4939 +
4940 +static inline int
4941 +dma_supported(struct device *dev, u64 mask)
4942 +{
4943 +       return 0;
4944 +}
4945 +
4946 +static inline int
4947 +dma_set_mask(struct device *dev, u64 dma_mask)
4948 +{
4949 +       BUG();
4950 +       return 0;
4951 +}
4952 +
4953 +static inline void *
4954 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4955 +                  gfp_t flag)
4956 +{
4957 +       BUG();
4958 +       return NULL;
4959 +}
4960 +
4961 +static inline void
4962 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4963 +                   dma_addr_t dma_handle)
4964 +{
4965 +       BUG();
4966 +}
4967 +
4968 +static inline dma_addr_t
4969 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4970 +              enum dma_data_direction direction)
4971 +{
4972 +       BUG();
4973 +       return 0;
4974 +}
4975 +
4976 +static inline void
4977 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4978 +                enum dma_data_direction direction)
4979 +{
4980 +       BUG();
4981 +}
4982 +
4983 +static inline dma_addr_t
4984 +dma_map_page(struct device *dev, struct page *page,
4985 +            unsigned long offset, size_t size,
4986 +            enum dma_data_direction direction)
4987 +{
4988 +       BUG();
4989 +       return 0;
4990 +}
4991 +
4992 +static inline void
4993 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4994 +              enum dma_data_direction direction)
4995 +{
4996 +       BUG();
4997 +}
4998 +
4999 +static inline int
5000 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
5001 +          enum dma_data_direction direction)
5002 +{
5003 +       BUG();
5004 +       return 0;
5005 +}
5006 +
5007 +static inline void
5008 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
5009 +            enum dma_data_direction direction)
5010 +{
5011 +       BUG();
5012 +}
5013 +
5014 +static inline void
5015 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
5016 +                       enum dma_data_direction direction)
5017 +{
5018 +       BUG();
5019 +}
5020 +
5021 +static inline void
5022 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
5023 +                          enum dma_data_direction direction)
5024 +{
5025 +       BUG();
5026 +}
5027 +
5028 +static inline void
5029 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
5030 +                   enum dma_data_direction direction)
5031 +{
5032 +       BUG();
5033 +}
5034 +
5035 +static inline void
5036 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
5037 +                      enum dma_data_direction direction)
5038 +{
5039 +       BUG();
5040 +}
5041 +
5042 +static inline int
5043 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
5044 +{
5045 +       return 0;
5046 +}
5047 +
5048 +#endif
5049 +
5050 +/* Now for the API extensions over the pci_ one */
5051 +
5052 +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
5053 +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
5054 +#define dma_is_consistent(d, h)        (1)
5055 +
5056 +static inline int
5057 +dma_get_cache_alignment(void)
5058 +{
5059 +       /* no easy way to get cache size on all processors, so return
5060 +        * the maximum possible, to be safe */
5061 +       return (1 << INTERNODE_CACHE_SHIFT);
5062 +}
5063 +
5064 +static inline void
5065 +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
5066 +                             unsigned long offset, size_t size,
5067 +                             enum dma_data_direction direction)
5068 +{
5069 +       /* just sync everything, that's all the pci API can do */
5070 +       dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
5071 +}
5072 +
5073 +static inline void
5074 +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
5075 +                                unsigned long offset, size_t size,
5076 +                                enum dma_data_direction direction)
5077 +{
5078 +       /* just sync everything, that's all the pci API can do */
5079 +       dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
5080 +}
5081 +
5082 +static inline void
5083 +dma_cache_sync(struct device *dev, void *vaddr, size_t size,
5084 +              enum dma_data_direction direction)
5085 +{
5086 +       /* could define this in terms of the dma_cache ... operations,
5087 +        * but if you get this on a platform, you should convert the platform
5088 +        * to using the generic device DMA API */
5089 +       BUG();
5090 +}
5091 +
5092 +#endif /* _ASM_UBICOM32_DMA_MAPPING_H */
5093 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/elf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/elf.h
5094 --- linux-2.6.30.10/arch/ubicom32/include/asm/elf.h     1970-01-01 02:00:00.000000000 +0200
5095 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/elf.h 2009-12-11 11:45:11.000000000 +0200
5096 @@ -0,0 +1,173 @@
5097 +/*
5098 + * arch/ubicom32/include/asm/elf.h
5099 + *   Definitions for elf executable format for Ubicom32 architecture.
5100 + *
5101 + * (C) Copyright 2009, Ubicom, Inc.
5102 + *
5103 + * This file is part of the Ubicom32 Linux Kernel Port.
5104 + *
5105 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5106 + * it and/or modify it under the terms of the GNU General Public License
5107 + * as published by the Free Software Foundation, either version 2 of the
5108 + * License, or (at your option) any later version.
5109 + *
5110 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5111 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5112 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5113 + * the GNU General Public License for more details.
5114 + *
5115 + * You should have received a copy of the GNU General Public License
5116 + * along with the Ubicom32 Linux Kernel Port.  If not,
5117 + * see <http://www.gnu.org/licenses/>.
5118 + *
5119 + * Ubicom32 implementation derived from (with many thanks):
5120 + *   arch/m68knommu
5121 + *   arch/blackfin
5122 + *   arch/parisc
5123 + */
5124 +#ifndef _ASM_UBICOM32_ELF_H
5125 +#define _ASM_UBICOM32_ELF_H
5126 +
5127 +/*
5128 + * ELF register definitions..
5129 + */
5130 +
5131 +#include <asm/ptrace.h>
5132 +#include <asm/user.h>
5133 +
5134 +/*
5135 + * Processor specific flags for the ELF header e_flags field.
5136 + */
5137 +#define EF_UBICOM32_V3         0x00000001      /* -fmarch=ubicom32v3 */
5138 +#define EF_UBICOM32_V4         0x00000002      /* -fmarch=ubicom32v4 */
5139 +#define EF_UBICOM32_PIC                0x80000000      /* -fpic */
5140 +#define EF_UBICOM32_FDPIC      0x40000000      /* -mfdpic */
5141 +
5142 +/*
5143 + * Ubicom32 ELF relocation types
5144 + */
5145 +#define R_UBICOM32_NONE                        0
5146 +#define R_UBICOM32_16                  1
5147 +#define R_UBICOM32_32                  2
5148 +#define R_UBICOM32_LO16                        3
5149 +#define R_UBICOM32_HI16                        4
5150 +#define R_UBICOM32_21_PCREL            5
5151 +#define R_UBICOM32_24_PCREL            6
5152 +#define R_UBICOM32_HI24                        7
5153 +#define R_UBICOM32_LO7_S               8
5154 +#define R_UBICOM32_LO7_2_S             9
5155 +#define R_UBICOM32_LO7_4_S             10
5156 +#define R_UBICOM32_LO7_D               11
5157 +#define R_UBICOM32_LO7_2_D             12
5158 +#define R_UBICOM32_LO7_4_D             13
5159 +#define R_UBICOM32_32_HARVARD          14
5160 +#define R_UBICOM32_LO7_CALLI           15
5161 +#define R_UBICOM32_LO16_CALLI          16
5162 +#define R_UBICOM32_GOT_HI24            17
5163 +#define R_UBICOM32_GOT_LO7_S           18
5164 +#define R_UBICOM32_GOT_LO7_2_S         19
5165 +#define R_UBICOM32_GOT_LO7_4_S         20
5166 +#define R_UBICOM32_GOT_LO7_D           21
5167 +#define R_UBICOM32_GOT_LO7_2_D         22
5168 +#define R_UBICOM32_GOT_LO7_4_D         23
5169 +#define R_UBICOM32_FUNCDESC_GOT_HI24    24
5170 +#define R_UBICOM32_FUNCDESC_GOT_LO7_S   25
5171 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_S 26
5172 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_S 27
5173 +#define R_UBICOM32_FUNCDESC_GOT_LO7_D   28
5174 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_D 29
5175 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_D 30
5176 +#define R_UBICOM32_GOT_LO7_CALLI        31
5177 +#define R_UBICOM32_FUNCDESC_GOT_LO7_CALLI 32
5178 +#define R_UBICOM32_FUNCDESC_VALUE       33
5179 +#define R_UBICOM32_FUNCDESC             34
5180 +#define R_UBICOM32_GOTOFFSET_LO         35
5181 +#define R_UBICOM32_GOTOFFSET_HI         36
5182 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_LO 37
5183 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_HI 38
5184 +#define R_UBICOM32_GNU_VTINHERIT        200
5185 +#define R_UBICOM32_GNU_VTENTRY          201
5186 +
5187 +typedef unsigned long elf_greg_t;
5188 +
5189 +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
5190 +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
5191 +
5192 +typedef struct user_ubicom32fp_struct elf_fpregset_t;
5193 +
5194 +/*
5195 + * This is used to ensure we don't load something for the wrong architecture.
5196 + */
5197 +#define elf_check_arch(x) ((x)->e_machine == EM_UBICOM32)
5198 +
5199 +#define elf_check_fdpic(x) ((x)->e_flags & EF_UBICOM32_FDPIC)
5200 +
5201 +#define elf_check_const_displacement(x) ((x)->e_flags & EF_UBICOM32_PIC)
5202 +
5203 +/*
5204 + * These are used to set parameters in the core dumps.
5205 + */
5206 +#define ELF_CLASS      ELFCLASS32
5207 +#define ELF_DATA       ELFDATA2MSB
5208 +#define ELF_ARCH       EM_UBICOM32
5209 +
5210 +/* For SVR4/m68k the function pointer to be registered with `atexit' is
5211 +   passed in %a1.  Although my copy of the ABI has no such statement, it
5212 +   is actually used on ASV.  */
5213 +#define ELF_PLAT_INIT(_r, load_addr)   _r->a1 = 0
5214 +
5215 +#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map_addr, _interp_map_addr,   \
5216 +                           _dynamic_addr)                              \
5217 +       do {                                                            \
5218 +               _regs->dn[1]    = _exec_map_addr;                       \
5219 +               _regs->dn[2]    = _interp_map_addr;                     \
5220 +               _regs->dn[3]    = _dynamic_addr;                        \
5221 +               _regs->an[1]    = 0; /* dl_fini will be set by ldso */  \
5222 +       } while (0)
5223 +
5224 +#define USE_ELF_CORE_DUMP
5225 +#define ELF_EXEC_PAGESIZE      4096
5226 +
5227 +#ifdef __KERNEL__
5228 +#ifdef CONFIG_UBICOM32_V4
5229 +#define ELF_FDPIC_CORE_EFLAGS  (EF_UBICOM32_FDPIC | EF_UBICOM32_V4)
5230 +#elif defined CONFIG_UBICOM32_V3
5231 +#define ELF_FDPIC_CORE_EFLAGS  (EF_UBICOM32_FDPIC | EF_UBICOM32_V3)
5232 +#else
5233 +#error Unknown/Unsupported ubicom32 architecture.
5234 +#endif
5235 +#endif
5236 +
5237 +/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
5238 +   use of this is to invoke "./ld.so someprog" to test out a new version of
5239 +   the loader.  We need to make sure that it is out of the way of the program
5240 +   that it will "exec", and that there is sufficient room for the brk.  */
5241 +
5242 +#define ELF_ET_DYN_BASE         0xD0000000UL
5243 +
5244 +/*
5245 + * For Ubicom32, the elf_gregset_t and struct pt_regs are the same size
5246 + * data structure so a copy is performed instead of providing the
5247 + * ELF_CORE_COPY_REGS macro.
5248 + */
5249 +
5250 +/*
5251 + * ELF_CORE_COPY_TASK_REGS is needed to dump register state from multi threaded user projects.
5252 + */
5253 +extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
5254 +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
5255 +
5256 +/* This yields a mask that user programs can use to figure out what
5257 +   instruction set this cpu supports.  */
5258 +
5259 +#define ELF_HWCAP      (0)
5260 +
5261 +/* This yields a string that ld.so will use to load implementation
5262 +   specific libraries for optimization.  This is more specific in
5263 +   intent than poking at uname or /proc/cpuinfo.  */
5264 +
5265 +#define ELF_PLATFORM  (NULL)
5266 +
5267 +#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
5268 +
5269 +#endif /* _ASM_UBICOM32_ELF_H */
5270 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/emergency-restart.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/emergency-restart.h
5271 --- linux-2.6.30.10/arch/ubicom32/include/asm/emergency-restart.h       1970-01-01 02:00:00.000000000 +0200
5272 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/emergency-restart.h   2009-12-11 11:45:11.000000000 +0200
5273 @@ -0,0 +1,33 @@
5274 +/*
5275 + * arch/ubicom32/include/asm/emergency-restart.h
5276 + *   Generic emergency-restart.h for Ubicom32 architecture.
5277 + *
5278 + * (C) Copyright 2009, Ubicom, Inc.
5279 + *
5280 + * This file is part of the Ubicom32 Linux Kernel Port.
5281 + *
5282 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5283 + * it and/or modify it under the terms of the GNU General Public License
5284 + * as published by the Free Software Foundation, either version 2 of the
5285 + * License, or (at your option) any later version.
5286 + *
5287 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5288 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5289 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5290 + * the GNU General Public License for more details.
5291 + *
5292 + * You should have received a copy of the GNU General Public License
5293 + * along with the Ubicom32 Linux Kernel Port.  If not,
5294 + * see <http://www.gnu.org/licenses/>.
5295 + *
5296 + * Ubicom32 implementation derived from (with many thanks):
5297 + *   arch/m68knommu
5298 + *   arch/blackfin
5299 + *   arch/parisc
5300 + */
5301 +#ifndef _ASM_UBICOM32_EMERGENCY_RESTART_H
5302 +#define _ASM_UBICOM32_EMERGENCY_RESTART_H
5303 +
5304 +#include <asm-generic/emergency-restart.h>
5305 +
5306 +#endif /* _ASM_UBICOM32_EMERGENCY_RESTART_H */
5307 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/entry.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/entry.h
5308 --- linux-2.6.30.10/arch/ubicom32/include/asm/entry.h   1970-01-01 02:00:00.000000000 +0200
5309 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/entry.h       2009-12-11 11:45:11.000000000 +0200
5310 @@ -0,0 +1,34 @@
5311 +/*
5312 + * arch/ubicom32/include/asm/entry.h
5313 + *   Entry register/stack definitions for Ubicom32 architecture.
5314 + *
5315 + * (C) Copyright 2009, Ubicom, Inc.
5316 + *
5317 + * This file is part of the Ubicom32 Linux Kernel Port.
5318 + *
5319 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5320 + * it and/or modify it under the terms of the GNU General Public License
5321 + * as published by the Free Software Foundation, either version 2 of the
5322 + * License, or (at your option) any later version.
5323 + *
5324 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5325 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5326 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5327 + * the GNU General Public License for more details.
5328 + *
5329 + * You should have received a copy of the GNU General Public License
5330 + * along with the Ubicom32 Linux Kernel Port.  If not,
5331 + * see <http://www.gnu.org/licenses/>.
5332 + *
5333 + * Ubicom32 implementation derived from (with many thanks):
5334 + *   arch/m68knommu
5335 + *   arch/blackfin
5336 + *   arch/parisc
5337 + */
5338 +#ifndef _ASM_UBICOM32_ENTRY_H
5339 +#define _ASM_UBICOM32_ENTRY_H
5340 +
5341 +#include <asm/setup.h>
5342 +#include <asm/page.h>
5343 +
5344 +#endif /* _ASM_UBICOM32_ENTRY_H */
5345 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/errno.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/errno.h
5346 --- linux-2.6.30.10/arch/ubicom32/include/asm/errno.h   1970-01-01 02:00:00.000000000 +0200
5347 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/errno.h       2009-12-11 11:45:11.000000000 +0200
5348 @@ -0,0 +1,33 @@
5349 +/*
5350 + * arch/ubicom32/include/asm/errno.h
5351 + *   Generic errno.h for Ubicom32 architecture.
5352 + *
5353 + * (C) Copyright 2009, Ubicom, Inc.
5354 + *
5355 + * This file is part of the Ubicom32 Linux Kernel Port.
5356 + *
5357 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5358 + * it and/or modify it under the terms of the GNU General Public License
5359 + * as published by the Free Software Foundation, either version 2 of the
5360 + * License, or (at your option) any later version.
5361 + *
5362 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5363 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5364 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5365 + * the GNU General Public License for more details.
5366 + *
5367 + * You should have received a copy of the GNU General Public License
5368 + * along with the Ubicom32 Linux Kernel Port.  If not,
5369 + * see <http://www.gnu.org/licenses/>.
5370 + *
5371 + * Ubicom32 implementation derived from (with many thanks):
5372 + *   arch/m68knommu
5373 + *   arch/blackfin
5374 + *   arch/parisc
5375 + */
5376 +#ifndef _ASM_UBICOM32_ERRNO_H
5377 +#define _ASM_UBICOM32_ERRNO_H
5378 +
5379 +#include <asm-generic/errno.h>
5380 +
5381 +#endif /* _ASM_UBICOM32_ERRNO_H */
5382 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/fb.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fb.h
5383 --- linux-2.6.30.10/arch/ubicom32/include/asm/fb.h      1970-01-01 02:00:00.000000000 +0200
5384 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fb.h  2009-12-11 11:45:11.000000000 +0200
5385 @@ -0,0 +1,39 @@
5386 +/*
5387 + * arch/ubicom32/include/asm/fb.h
5388 + *   Definition of fb_is_primary_device() for Ubicom32 architecture.
5389 + *
5390 + * (C) Copyright 2009, Ubicom, Inc.
5391 + *
5392 + * This file is part of the Ubicom32 Linux Kernel Port.
5393 + *
5394 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5395 + * it and/or modify it under the terms of the GNU General Public License
5396 + * as published by the Free Software Foundation, either version 2 of the
5397 + * License, or (at your option) any later version.
5398 + *
5399 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5400 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5401 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5402 + * the GNU General Public License for more details.
5403 + *
5404 + * You should have received a copy of the GNU General Public License
5405 + * along with the Ubicom32 Linux Kernel Port.  If not,
5406 + * see <http://www.gnu.org/licenses/>.
5407 + *
5408 + * Ubicom32 implementation derived from (with many thanks):
5409 + *   arch/m68knommu
5410 + *   arch/blackfin
5411 + *   arch/parisc
5412 + */
5413 +#ifndef _ASM_UBICOM32_FB_H
5414 +#define _ASM_UBICOM32_FB_H
5415 +#include <linux/fb.h>
5416 +
5417 +#define fb_pgprotect(...) do {} while (0)
5418 +
5419 +static inline int fb_is_primary_device(struct fb_info *info)
5420 +{
5421 +       return 0;
5422 +}
5423 +
5424 +#endif /* _ASM_UBICOM32_FB_H */
5425 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/fcntl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fcntl.h
5426 --- linux-2.6.30.10/arch/ubicom32/include/asm/fcntl.h   1970-01-01 02:00:00.000000000 +0200
5427 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fcntl.h       2009-12-11 11:45:11.000000000 +0200
5428 @@ -0,0 +1,38 @@
5429 +/*
5430 + * arch/ubicom32/include/asm/fcntl.h
5431 + *   File control bit definitions for Ubicom32 architecture.
5432 + *
5433 + * (C) Copyright 2009, Ubicom, Inc.
5434 + *
5435 + * This file is part of the Ubicom32 Linux Kernel Port.
5436 + *
5437 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5438 + * it and/or modify it under the terms of the GNU General Public License
5439 + * as published by the Free Software Foundation, either version 2 of the
5440 + * License, or (at your option) any later version.
5441 + *
5442 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5443 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5444 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5445 + * the GNU General Public License for more details.
5446 + *
5447 + * You should have received a copy of the GNU General Public License
5448 + * along with the Ubicom32 Linux Kernel Port.  If not,
5449 + * see <http://www.gnu.org/licenses/>.
5450 + *
5451 + * Ubicom32 implementation derived from (with many thanks):
5452 + *   arch/m68knommu
5453 + *   arch/blackfin
5454 + *   arch/parisc
5455 + */
5456 +#ifndef _ASM_UBICOM32_FCNTL_H
5457 +#define _ASM_UBICOM32_FCNTL_H
5458 +
5459 +#define O_DIRECTORY    040000  /* must be a directory */
5460 +#define O_NOFOLLOW     0100000 /* don't follow links */
5461 +#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
5462 +#define O_LARGEFILE    0400000
5463 +
5464 +#include <asm-generic/fcntl.h>
5465 +
5466 +#endif /* _ASM_UBICOM32_FCNTL_H */
5467 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/flat.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/flat.h
5468 --- linux-2.6.30.10/arch/ubicom32/include/asm/flat.h    1970-01-01 02:00:00.000000000 +0200
5469 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/flat.h        2009-12-11 11:45:11.000000000 +0200
5470 @@ -0,0 +1,73 @@
5471 +/*
5472 + * arch/ubicom32/include/asm/flat.h
5473 + *   Definitions to support flat-format executables.
5474 + *
5475 + * (C) Copyright 2009, Ubicom, Inc.
5476 + *
5477 + * This file is part of the Ubicom32 Linux Kernel Port.
5478 + *
5479 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5480 + * it and/or modify it under the terms of the GNU General Public License
5481 + * as published by the Free Software Foundation, either version 2 of the
5482 + * License, or (at your option) any later version.
5483 + *
5484 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5485 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5486 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5487 + * the GNU General Public License for more details.
5488 + *
5489 + * You should have received a copy of the GNU General Public License
5490 + * along with the Ubicom32 Linux Kernel Port.  If not,
5491 + * see <http://www.gnu.org/licenses/>.
5492 + *
5493 + * Ubicom32 implementation derived from (with many thanks):
5494 + *   arch/m68knommu
5495 + *   arch/blackfin
5496 + *   arch/parisc
5497 + */
5498 +
5499 +#ifndef _ASM_UBICOM32_FLAT_H
5500 +#define _ASM_UBICOM32_FLAT_H
5501 +
5502 +#define ARCH_FLAT_ALIGN 0x80
5503 +#define ARCH_FLAT_ALIGN_TEXT 1
5504 +
5505 +#define  R_UBICOM32_32         2
5506 +#define  R_UBICOM32_HI24       7
5507 +#define  R_UBICOM32_LO7_S      8
5508 +#define  R_UBICOM32_LO7_2_S    9
5509 +#define  R_UBICOM32_LO7_4_S    10
5510 +#define  R_UBICOM32_LO7_D      11
5511 +#define  R_UBICOM32_LO7_2_D    12
5512 +#define  R_UBICOM32_LO7_4_D    13
5513 +#define  R_UBICOM32_LO7_CALLI  15
5514 +#define  R_UBICOM32_LO16_CALLI 16
5515 +
5516 +extern void ubicom32_flat_put_addr_at_rp(unsigned long *rp, u32_t val, u32_t rval, unsigned long  *p);
5517 +extern unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp, u32_t relval, u32_t flags, unsigned long *p);
5518 +
5519 +#define        flat_stack_align(sp)                    /* nothing needed */
5520 +#define        flat_argvp_envp_on_stack()              1
5521 +#define        flat_old_ram_flag(flags)                (flags)
5522 +#define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
5523 +#define        flat_get_addr_from_rp(rp, relval, flags, p)     (ubicom32_flat_get_addr_from_rp(rp, relval,flags, p))
5524 +#define        flat_put_addr_at_rp(rp, val, relval)    do {ubicom32_flat_put_addr_at_rp(rp, val, relval, &persistent);} while(0)
5525 +#define        flat_get_relocate_addr(rel)             ((persistent) ? (persistent & 0x07ffffff) : (rel & 0x07ffffff))
5526 +
5527 +static inline int flat_set_persistent(unsigned int relval, unsigned long *p)
5528 +{
5529 +       if (*p) {
5530 +               return 0;
5531 +       } else {
5532 +               if ((relval >> 27) != R_UBICOM32_32) {
5533 +                       /*
5534 +                        * Something other than UBICOM32_32. The next entry has the relocation.
5535 +                        */
5536 +                       *p = relval;
5537 +                       return 1;
5538 +               }
5539 +       }
5540 +       return 0;
5541 +}
5542 +
5543 +#endif /* _ASM_UBICOM32_FLAT_H */
5544 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/fpu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fpu.h
5545 --- linux-2.6.30.10/arch/ubicom32/include/asm/fpu.h     1970-01-01 02:00:00.000000000 +0200
5546 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fpu.h 2009-12-11 11:45:11.000000000 +0200
5547 @@ -0,0 +1,37 @@
5548 +/*
5549 + * arch/ubicom32/include/asm/fpu.h
5550 + *   Floating point state definitions for Ubicom32 architecture.
5551 + *
5552 + * (C) Copyright 2009, Ubicom, Inc.
5553 + *
5554 + * This file is part of the Ubicom32 Linux Kernel Port.
5555 + *
5556 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5557 + * it and/or modify it under the terms of the GNU General Public License
5558 + * as published by the Free Software Foundation, either version 2 of the
5559 + * License, or (at your option) any later version.
5560 + *
5561 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5562 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5563 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5564 + * the GNU General Public License for more details.
5565 + *
5566 + * You should have received a copy of the GNU General Public License
5567 + * along with the Ubicom32 Linux Kernel Port.  If not,
5568 + * see <http://www.gnu.org/licenses/>.
5569 + *
5570 + * Ubicom32 implementation derived from (with many thanks):
5571 + *   arch/m68knommu
5572 + *   arch/blackfin
5573 + *   arch/parisc
5574 + */
5575 +#ifndef _ASM_UBICOM32_FPU_H
5576 +#define _ASM_UBICOM32_FPU_H
5577 +
5578 +/*
5579 + * MAX floating point unit state size (FSAVE/FRESTORE)
5580 + */
5581 +/* No FP unit present then... */
5582 +#define FPSTATESIZE (2) /* dummy size */
5583 +
5584 +#endif /* _ASM_UBICOM32_FPU_H */
5585 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ftrace.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ftrace.h
5586 --- linux-2.6.30.10/arch/ubicom32/include/asm/ftrace.h  1970-01-01 02:00:00.000000000 +0200
5587 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ftrace.h      2009-12-11 11:45:11.000000000 +0200
5588 @@ -0,0 +1 @@
5589 +/* empty */
5590 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/futex.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/futex.h
5591 --- linux-2.6.30.10/arch/ubicom32/include/asm/futex.h   1970-01-01 02:00:00.000000000 +0200
5592 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/futex.h       2009-12-11 11:45:11.000000000 +0200
5593 @@ -0,0 +1,33 @@
5594 +/*
5595 + * arch/ubicom32/include/asm/futex.h
5596 + *   Generic futex.h for Ubicom32 architecture.
5597 + *
5598 + * (C) Copyright 2009, Ubicom, Inc.
5599 + *
5600 + * This file is part of the Ubicom32 Linux Kernel Port.
5601 + *
5602 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5603 + * it and/or modify it under the terms of the GNU General Public License
5604 + * as published by the Free Software Foundation, either version 2 of the
5605 + * License, or (at your option) any later version.
5606 + *
5607 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5608 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5609 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5610 + * the GNU General Public License for more details.
5611 + *
5612 + * You should have received a copy of the GNU General Public License
5613 + * along with the Ubicom32 Linux Kernel Port.  If not,
5614 + * see <http://www.gnu.org/licenses/>.
5615 + *
5616 + * Ubicom32 implementation derived from (with many thanks):
5617 + *   arch/m68knommu
5618 + *   arch/blackfin
5619 + *   arch/parisc
5620 + */
5621 +#ifndef _ASM_UBICOM32_FUTEX_H
5622 +#define _ASM_UBICOM32_FUTEX_H
5623 +
5624 +#include <asm-generic/futex.h>
5625 +
5626 +#endif /* _ASM_UBICOM32_FUTEX_H */
5627 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/.gitignore linux-2.6.30.10-ubi/arch/ubicom32/include/asm/.gitignore
5628 --- linux-2.6.30.10/arch/ubicom32/include/asm/.gitignore        1970-01-01 02:00:00.000000000 +0200
5629 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/.gitignore    2009-12-11 11:45:11.000000000 +0200
5630 @@ -0,0 +1 @@
5631 +/ocm_size.h
5632 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/gpio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/gpio.h
5633 --- linux-2.6.30.10/arch/ubicom32/include/asm/gpio.h    1970-01-01 02:00:00.000000000 +0200
5634 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/gpio.h        2009-12-11 11:45:11.000000000 +0200
5635 @@ -0,0 +1,453 @@
5636 +/*
5637 + * arch/ubicom32/include/asm/gpio.h
5638 + *   Definitions for GPIO operations on Ubicom32 architecture.
5639 + *
5640 + * (C) Copyright 2009, Ubicom, Inc.
5641 + *
5642 + * This file is part of the Ubicom32 Linux Kernel Port.
5643 + *
5644 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5645 + * it and/or modify it under the terms of the GNU General Public License
5646 + * as published by the Free Software Foundation, either version 2 of the
5647 + * License, or (at your option) any later version.
5648 + *
5649 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5650 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5651 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5652 + * the GNU General Public License for more details.
5653 + *
5654 + * You should have received a copy of the GNU General Public License
5655 + * along with the Ubicom32 Linux Kernel Port.  If not,
5656 + * see <http://www.gnu.org/licenses/>.
5657 + *
5658 + * Ubicom32 implementation derived from (with many thanks):
5659 + *   arch/m68knommu
5660 + *   arch/blackfin
5661 + *   arch/parisc
5662 + */
5663 +#ifndef _ASM_UBICOM32_GPIO_H
5664 +#define _ASM_UBICOM32_GPIO_H
5665 +
5666 +#include <linux/compiler.h>
5667 +#include <asm/irq.h>
5668 +
5669 +#include <asm/ip5000.h>
5670 +
5671 +#define ARCH_NR_GPIOS           512
5672 +#define MAX_UBICOM_ONCHIP_GPIO   (9 * 32)
5673 +
5674 +/*
5675 + * Macros for manipulating GPIO numbers
5676 + */
5677 +#define gpio_bit(gn)                   (1 << (gn & 0x1f))
5678 +#define gpio_bank(gn)                  (gn >> 5)
5679 +
5680 +#define gpio_pin_index(gn)             (gn & 0x1f)
5681 +#define gpio_port_index(gn)            (gn >> 5)
5682 +
5683 +#define GPIO_RA_0    ((32 * 0) + 0)
5684 +#define GPIO_RA_1    ((32 * 0) + 1)
5685 +#define GPIO_RA_2    ((32 * 0) + 2)
5686 +#define GPIO_RA_3    ((32 * 0) + 3)
5687 +#define GPIO_RA_4    ((32 * 0) + 4)
5688 +#define GPIO_RA_5    ((32 * 0) + 5)
5689 +#define GPIO_RA_6    ((32 * 0) + 6)
5690 +#define GPIO_RA_7    ((32 * 0) + 7)
5691 +
5692 +#define GPIO_RB_0    ((32 * 1) + 0)
5693 +#define GPIO_RB_1    ((32 * 1) + 1)
5694 +#define GPIO_RB_2    ((32 * 1) + 2)
5695 +#define GPIO_RB_3    ((32 * 1) + 3)
5696 +#define GPIO_RB_4    ((32 * 1) + 4)
5697 +#define GPIO_RB_5    ((32 * 1) + 5)
5698 +#define GPIO_RB_6    ((32 * 1) + 6)
5699 +#define GPIO_RB_7    ((32 * 1) + 7)
5700 +#define GPIO_RB_8    ((32 * 1) + 8)
5701 +#define GPIO_RB_9    ((32 * 1) + 9)
5702 +#define GPIO_RB_10   ((32 * 1) + 10)
5703 +#define GPIO_RB_11   ((32 * 1) + 11)
5704 +#define GPIO_RB_12   ((32 * 1) + 12)
5705 +#define GPIO_RB_13   ((32 * 1) + 13)
5706 +#define GPIO_RB_14   ((32 * 1) + 14)
5707 +#define GPIO_RB_15   ((32 * 1) + 15)
5708 +#define GPIO_RB_16   ((32 * 1) + 16)
5709 +#define GPIO_RB_17   ((32 * 1) + 17)
5710 +#define GPIO_RB_18   ((32 * 1) + 18)
5711 +#define GPIO_RB_19   ((32 * 1) + 19)
5712 +
5713 +#define GPIO_RC_0    ((32 * 2) + 0)
5714 +#define GPIO_RC_1    ((32 * 2) + 1)
5715 +#define GPIO_RC_2    ((32 * 2) + 2)
5716 +#define GPIO_RC_3    ((32 * 2) + 3)
5717 +#define GPIO_RC_4    ((32 * 2) + 4)
5718 +#define GPIO_RC_5    ((32 * 2) + 5)
5719 +#define GPIO_RC_6    ((32 * 2) + 6)
5720 +#define GPIO_RC_7    ((32 * 2) + 7)
5721 +#define GPIO_RC_8    ((32 * 2) + 8)
5722 +#define GPIO_RC_9    ((32 * 2) + 9)
5723 +#define GPIO_RC_10   ((32 * 2) + 10)
5724 +#define GPIO_RC_11   ((32 * 2) + 11)
5725 +#define GPIO_RC_12   ((32 * 2) + 12)
5726 +#define GPIO_RC_13   ((32 * 2) + 13)
5727 +#define GPIO_RC_14   ((32 * 2) + 14)
5728 +#define GPIO_RC_15   ((32 * 2) + 15)
5729 +#define GPIO_RC_16   ((32 * 2) + 16)
5730 +#define GPIO_RC_17   ((32 * 2) + 17)
5731 +#define GPIO_RC_18   ((32 * 2) + 18)
5732 +#define GPIO_RC_19   ((32 * 2) + 19)
5733 +#define GPIO_RC_20   ((32 * 2) + 20)
5734 +#define GPIO_RC_21   ((32 * 2) + 21)
5735 +#define GPIO_RC_22   ((32 * 2) + 22)
5736 +#define GPIO_RC_23   ((32 * 2) + 23)
5737 +#define GPIO_RC_24   ((32 * 2) + 24)
5738 +#define GPIO_RC_25   ((32 * 2) + 25)
5739 +#define GPIO_RC_26   ((32 * 2) + 26)
5740 +#define GPIO_RC_27   ((32 * 2) + 27)
5741 +#define GPIO_RC_28   ((32 * 2) + 28)
5742 +#define GPIO_RC_29   ((32 * 2) + 29)
5743 +#define GPIO_RC_30   ((32 * 2) + 30)
5744 +#define GPIO_RC_31   ((32 * 2) + 31)
5745 +
5746 +#define GPIO_RD_0    ((32 * 3) + 0)
5747 +#define GPIO_RD_1    ((32 * 3) + 1)
5748 +#define GPIO_RD_2    ((32 * 3) + 2)
5749 +#define GPIO_RD_3    ((32 * 3) + 3)
5750 +#define GPIO_RD_4    ((32 * 3) + 4)
5751 +#define GPIO_RD_5    ((32 * 3) + 5)
5752 +#define GPIO_RD_6    ((32 * 3) + 6)
5753 +#define GPIO_RD_7    ((32 * 3) + 7)
5754 +#define GPIO_RD_8    ((32 * 3) + 8)
5755 +#define GPIO_RD_9    ((32 * 3) + 9)
5756 +#define GPIO_RD_10   ((32 * 3) + 10)
5757 +#define GPIO_RD_11   ((32 * 3) + 11)
5758 +
5759 +#define GPIO_RE_0    ((32 * 4) + 0)
5760 +#define GPIO_RE_1    ((32 * 4) + 1)
5761 +#define GPIO_RE_2    ((32 * 4) + 2)
5762 +#define GPIO_RE_3    ((32 * 4) + 3)
5763 +#define GPIO_RE_4    ((32 * 4) + 4)
5764 +#define GPIO_RE_5    ((32 * 4) + 5)
5765 +#define GPIO_RE_6    ((32 * 4) + 6)
5766 +#define GPIO_RE_7    ((32 * 4) + 7)
5767 +
5768 +#define GPIO_RF_0    ((32 * 5) + 0)
5769 +#define GPIO_RF_1    ((32 * 5) + 1)
5770 +#define GPIO_RF_2    ((32 * 5) + 2)
5771 +#define GPIO_RF_3    ((32 * 5) + 3)
5772 +#define GPIO_RF_4    ((32 * 5) + 4)
5773 +#define GPIO_RF_5    ((32 * 5) + 5)
5774 +#define GPIO_RF_6    ((32 * 5) + 6)
5775 +#define GPIO_RF_7    ((32 * 5) + 7)
5776 +#define GPIO_RF_8    ((32 * 5) + 8)
5777 +#define GPIO_RF_9    ((32 * 5) + 9)
5778 +#define GPIO_RF_10   ((32 * 5) + 10)
5779 +#define GPIO_RF_11   ((32 * 5) + 11)
5780 +#define GPIO_RF_12   ((32 * 5) + 12)
5781 +#define GPIO_RF_13   ((32 * 5) + 13)
5782 +#define GPIO_RF_14   ((32 * 5) + 14)
5783 +#define GPIO_RF_15   ((32 * 5) + 15)
5784 +
5785 +#define GPIO_RG_0    ((32 * 6) + 0)
5786 +#define GPIO_RG_1    ((32 * 6) + 1)
5787 +#define GPIO_RG_2    ((32 * 6) + 2)
5788 +#define GPIO_RG_3    ((32 * 6) + 3)
5789 +#define GPIO_RG_4    ((32 * 6) + 4)
5790 +#define GPIO_RG_5    ((32 * 6) + 5)
5791 +#define GPIO_RG_6    ((32 * 6) + 6)
5792 +#define GPIO_RG_7    ((32 * 6) + 7)
5793 +#define GPIO_RG_8    ((32 * 6) + 8)
5794 +#define GPIO_RG_9    ((32 * 6) + 9)
5795 +#define GPIO_RG_10   ((32 * 6) + 10)
5796 +#define GPIO_RG_11   ((32 * 6) + 11)
5797 +#define GPIO_RG_12   ((32 * 6) + 12)
5798 +#define GPIO_RG_13   ((32 * 6) + 13)
5799 +#define GPIO_RG_14   ((32 * 6) + 14)
5800 +#define GPIO_RG_15   ((32 * 6) + 15)
5801 +#define GPIO_RG_16   ((32 * 6) + 16)
5802 +#define GPIO_RG_17   ((32 * 6) + 17)
5803 +#define GPIO_RG_18   ((32 * 6) + 18)
5804 +#define GPIO_RG_19   ((32 * 6) + 19)
5805 +#define GPIO_RG_20   ((32 * 6) + 20)
5806 +#define GPIO_RG_21   ((32 * 6) + 21)
5807 +#define GPIO_RG_22   ((32 * 6) + 22)
5808 +#define GPIO_RG_23   ((32 * 6) + 23)
5809 +#define GPIO_RG_24   ((32 * 6) + 24)
5810 +#define GPIO_RG_25   ((32 * 6) + 25)
5811 +#define GPIO_RG_26   ((32 * 6) + 26)
5812 +#define GPIO_RG_27   ((32 * 6) + 27)
5813 +#define GPIO_RG_28   ((32 * 6) + 28)
5814 +#define GPIO_RG_29   ((32 * 6) + 29)
5815 +#define GPIO_RG_30   ((32 * 6) + 30)
5816 +#define GPIO_RG_31   ((32 * 6) + 31)
5817 +
5818 +#define GPIO_RH_0    ((32 * 7) + 0)
5819 +#define GPIO_RH_1    ((32 * 7) + 1)
5820 +#define GPIO_RH_2    ((32 * 7) + 2)
5821 +#define GPIO_RH_3    ((32 * 7) + 3)
5822 +#define GPIO_RH_4    ((32 * 7) + 4)
5823 +#define GPIO_RH_5    ((32 * 7) + 5)
5824 +#define GPIO_RH_6    ((32 * 7) + 6)
5825 +#define GPIO_RH_7    ((32 * 7) + 7)
5826 +#define GPIO_RH_8    ((32 * 7) + 8)
5827 +#define GPIO_RH_9    ((32 * 7) + 9)
5828 +
5829 +#define GPIO_RI_0    ((32 * 8) + 0)
5830 +#define GPIO_RI_1    ((32 * 8) + 1)
5831 +#define GPIO_RI_2    ((32 * 8) + 2)
5832 +#define GPIO_RI_3    ((32 * 8) + 3)
5833 +#define GPIO_RI_4    ((32 * 8) + 4)
5834 +#define GPIO_RI_5    ((32 * 8) + 5)
5835 +#define GPIO_RI_6    ((32 * 8) + 6)
5836 +#define GPIO_RI_7    ((32 * 8) + 7)
5837 +#define GPIO_RI_8    ((32 * 8) + 8)
5838 +#define GPIO_RI_9    ((32 * 8) + 9)
5839 +#define GPIO_RI_10   ((32 * 8) + 10)
5840 +#define GPIO_RI_11   ((32 * 8) + 11)
5841 +#define GPIO_RI_12   ((32 * 8) + 12)
5842 +#define GPIO_RI_13   ((32 * 8) + 13)
5843 +#define GPIO_RI_14   ((32 * 8) + 14)
5844 +#define GPIO_RI_15   ((32 * 8) + 15)
5845 +
5846 +/*
5847 + * The following section defines extra GPIO available to some boards.
5848 + * These GPIO are generally external to the processor (i.e. SPI/I2C
5849 + * expander chips).
5850 + *
5851 + * Note that these defines show all possible GPIO available, however,
5852 + * depending on the actual board configuration, some GPIO are not
5853 + * available for use.
5854 + */
5855 +#ifdef CONFIG_IP7500MEDIA
5856 +/*
5857 + * U15
5858 + */
5859 +#define IP7500MEDIA_U15_BASE   (32 * 10)
5860 +#define IP7500MEDIA_IO0                (IP7500MEDIA_U15_BASE + 0)
5861 +#define IP7500MEDIA_IO1                (IP7500MEDIA_U15_BASE + 1)
5862 +#define IP7500MEDIA_IO2                (IP7500MEDIA_U15_BASE + 2)
5863 +#define IP7500MEDIA_IO3                (IP7500MEDIA_U15_BASE + 3)
5864 +#define IP7500MEDIA_IO4                (IP7500MEDIA_U15_BASE + 4)
5865 +#define IP7500MEDIA_IO5                (IP7500MEDIA_U15_BASE + 5)
5866 +#define IP7500MEDIA_IO6                (IP7500MEDIA_U15_BASE + 6)
5867 +#define IP7500MEDIA_IO7                (IP7500MEDIA_U15_BASE + 7)
5868 +
5869 +/*
5870 + * U16
5871 + */
5872 +#define IP7500MEDIA_U16_BASE   (32 * 11)
5873 +#define IP7500MEDIA_IO8                (IP7500MEDIA_U16_BASE + 0)
5874 +#define IP7500MEDIA_IO9                (IP7500MEDIA_U16_BASE + 1)
5875 +#define IP7500MEDIA_IO10       (IP7500MEDIA_U16_BASE + 2)
5876 +#define IP7500MEDIA_IO11       (IP7500MEDIA_U16_BASE + 3)
5877 +#define IP7500MEDIA_IO12       (IP7500MEDIA_U16_BASE + 4)
5878 +#define IP7500MEDIA_IO13       (IP7500MEDIA_U16_BASE + 5)
5879 +#define IP7500MEDIA_IO14       (IP7500MEDIA_U16_BASE + 6)
5880 +#define IP7500MEDIA_IO15       (IP7500MEDIA_U16_BASE + 7)
5881 +
5882 +/*
5883 + * U17
5884 + */
5885 +#define IP7500MEDIA_U17_BASE   (32 * 12)
5886 +#define IP7500MEDIA_IO16       (IP7500MEDIA_U17_BASE + 0)
5887 +#define IP7500MEDIA_IO17       (IP7500MEDIA_U17_BASE + 1)
5888 +#define IP7500MEDIA_IO18       (IP7500MEDIA_U17_BASE + 2)
5889 +#define IP7500MEDIA_IO19       (IP7500MEDIA_U17_BASE + 3)
5890 +#define IP7500MEDIA_IO20       (IP7500MEDIA_U17_BASE + 4)
5891 +#define IP7500MEDIA_IO21       (IP7500MEDIA_U17_BASE + 5)
5892 +#define IP7500MEDIA_IO22       (IP7500MEDIA_U17_BASE + 6)
5893 +#define IP7500MEDIA_IO23       (IP7500MEDIA_U17_BASE + 7)
5894 +
5895 +/*
5896 + * U18
5897 + */
5898 +#define IP7500MEDIA_U18_BASE   (32 * 13)
5899 +#define IP7500MEDIA_IO24       (IP7500MEDIA_U18_BASE + 0)
5900 +#define IP7500MEDIA_IO25       (IP7500MEDIA_U18_BASE + 1)
5901 +#define IP7500MEDIA_IO26       (IP7500MEDIA_U18_BASE + 2)
5902 +#define IP7500MEDIA_IO27       (IP7500MEDIA_U18_BASE + 3)
5903 +#define IP7500MEDIA_IO28       (IP7500MEDIA_U18_BASE + 4)
5904 +#define IP7500MEDIA_IO29       (IP7500MEDIA_U18_BASE + 5)
5905 +#define IP7500MEDIA_IO30       (IP7500MEDIA_U18_BASE + 6)
5906 +#define IP7500MEDIA_IO31       (IP7500MEDIA_U18_BASE + 7)
5907 +#endif
5908 +
5909 +#ifdef CONFIG_IP7145DPF
5910 +/*
5911 + * U48
5912 + */
5913 +#define IP7145DPF_U48_BASE     (32 * 10)
5914 +#define IP7145DPF_IO0          (IP7145DPF_U48_BASE + 0)
5915 +#define IP7145DPF_IO1          (IP7145DPF_U48_BASE + 1)
5916 +#define IP7145DPF_IO2          (IP7145DPF_U48_BASE + 2)
5917 +#define IP7145DPF_IO3          (IP7145DPF_U48_BASE + 3)
5918 +#define IP7145DPF_IO4          (IP7145DPF_U48_BASE + 4)
5919 +#define IP7145DPF_IO5          (IP7145DPF_U48_BASE + 5)
5920 +#define IP7145DPF_IO6          (IP7145DPF_U48_BASE + 6)
5921 +#define IP7145DPF_IO7          (IP7145DPF_U48_BASE + 7)
5922 +
5923 +/*
5924 + * U72
5925 + */
5926 +#define IP7145DPF_U72_BASE     (32 * 11)
5927 +#define IP7145DPF_IOB0         (IP7145DPF_U72_BASE + 0)
5928 +#define IP7145DPF_IOB1         (IP7145DPF_U72_BASE + 1)
5929 +#define IP7145DPF_IOB2         (IP7145DPF_U72_BASE + 2)
5930 +#define IP7145DPF_IOB3         (IP7145DPF_U72_BASE + 3)
5931 +#define IP7145DPF_IOB4         (IP7145DPF_U72_BASE + 4)
5932 +#define IP7145DPF_IOB5         (IP7145DPF_U72_BASE + 5)
5933 +#define IP7145DPF_IOB6         (IP7145DPF_U72_BASE + 6)
5934 +#define IP7145DPF_IOB7         (IP7145DPF_U72_BASE + 7)
5935 +#endif
5936 +
5937 +#include <asm-generic/gpio.h>
5938 +
5939 +/*
5940 + * The following macros bypass gpiolib to generate direct references
5941 + * to the port registers.  These assume, minimally, that either
5942 + * gpio_direction_input() or gpio_direction_output() have already been
5943 + * called to setup the pin direction and to enable the pin function to
5944 + * be gpio.  These macros generate the hardware port address based on
5945 + * the assumption that all ports are 32 bits wide (even though we know
5946 + * they are not).  This is so we can efficiently turn pin numbers into
5947 + * port addresses without a lookup.
5948 + *
5949 + * These operations must be done in one instruction to prevent clobbering
5950 + * other thread's accesses to the same port.
5951 + */
5952 +#define UBICOM32_GPIO_ENABLE(pin)                              \
5953 +       do {                                                    \
5954 +               asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t"                                          \
5955 +                               :                                                                               \
5956 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask),  \
5957 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5958 +                               : "cc", "memory"                                                                \
5959 +               );                                                                                              \
5960 +       } while (0);
5961 +
5962 +#define UBICOM32_GPIO_DISABLE(pin)                             \
5963 +       do {                                                    \
5964 +               asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5965 +                               :                                                                               \
5966 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask),  \
5967 +                                 [mask] "d" (~gpio_bit(pin))                                                   \
5968 +                               : "cc", "memory"                                                                \
5969 +               );                                                                                              \
5970 +       } while (0);
5971 +
5972 +#define UBICOM32_GPIO_SET_PIN_INPUT(pin)                       \
5973 +       do {                                                    \
5974 +               asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5975 +                               :                                                                               \
5976 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl),   \
5977 +                                 [mask] "d" (~gpio_bit(pin))                                                   \
5978 +                               : "cc", "memory"                                                                \
5979 +               );                                                                                              \
5980 +       } while (0);
5981 +
5982 +#define UBICOM32_GPIO_SET_PIN_OUTPUT(pin)                      \
5983 +       do {                                                    \
5984 +               asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t"                                          \
5985 +                               :                                                                               \
5986 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl),   \
5987 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5988 +                               : "cc", "memory"                                                                \
5989 +               );                                                                                              \
5990 +       } while (0);
5991 +
5992 +#define UBICOM32_GPIO_SET_PIN_TOGGLE(pin)                      \
5993 +       do {                                                    \
5994 +               asm volatile ("xor.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5995 +                               :                                                                               \
5996 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out),   \
5997 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5998 +                               : "cc", "memory"                                                                \
5999 +               );                                                                                              \
6000 +       } while (0);
6001 +
6002 +#define UBICOM32_GPIO_SET_PIN_HIGH(pin)                                \
6003 +       do {                                                    \
6004 +               asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t"                                          \
6005 +                               :                                                                               \
6006 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out),   \
6007 +                                 [mask] "d" (gpio_bit(pin))                                                    \
6008 +                               : "cc", "memory"                                                                \
6009 +               );                                                                                              \
6010 +       } while (0);
6011 +
6012 +#define UBICOM32_GPIO_SET_PIN_LOW(pin)                         \
6013 +       do {                                                    \
6014 +               asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
6015 +                               :                                                                               \
6016 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out),   \
6017 +                                 [mask] "d" (~gpio_bit(pin))                                                   \
6018 +                               : "cc", "memory"                                                                \
6019 +               );                                                                                              \
6020 +       } while (0);
6021 +
6022 +#define UBICOM32_GPIO_SET_PIN(pin, val) \
6023 +  if ( val ) {                          \
6024 +    UBICOM32_GPIO_SET_PIN_HIGH(pin);    \
6025 +  } else {                              \
6026 +    UBICOM32_GPIO_SET_PIN_LOW(pin);    \
6027 +  }
6028 +
6029 +#define UBICOM32_GPIO_GET_PIN(pin)                                    \
6030 +  (0 != (UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_in  \
6031 +        & gpio_bit(pin)))
6032 +
6033 +
6034 +static inline int gpio_get_value(unsigned gpio)
6035 +{
6036 +  if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
6037 +    return UBICOM32_GPIO_GET_PIN(gpio);
6038 +  else
6039 +    return __gpio_get_value(gpio);
6040 +}
6041 +
6042 +static inline void gpio_set_value(unsigned gpio, int value)
6043 +{
6044 +  if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
6045 +    {
6046 +      UBICOM32_GPIO_SET_PIN(gpio, value);
6047 +    }
6048 +  else
6049 +    {
6050 +      __gpio_set_value(gpio, value);
6051 +    }
6052 +}
6053 +
6054 +static inline int gpio_cansleep(unsigned gpio)
6055 +{
6056 +  return __gpio_cansleep(gpio);
6057 +}
6058 +
6059 +static inline int gpio_to_irq(unsigned gpio)
6060 +{
6061 +#if defined(IP5000) || defined(IP5000_REV2)
6062 +  if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6063 +    return 25;
6064 +  else
6065 +    return -ENXIO;
6066 +
6067 +#elif defined(IP7000) || defined(IP7000_REV2)
6068 +  if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6069 +    return 44 + (gpio - GPIO_RA_4);
6070 +  else
6071 +    return -ENXIO;
6072 +
6073 +#else
6074 +    return -ENXIO;
6075 +
6076 +#endif
6077 +}
6078 +
6079 +static inline int irq_to_gpio(unsigned gpio)
6080 +{
6081 +       return -ENXIO;
6082 +}
6083 +
6084 +extern struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio);
6085 +
6086 +extern int __init ubi_gpio_init(void);
6087 +
6088 +#endif /* _ASM_UBICOM32_GPIO_H */
6089 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/hardirq.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hardirq.h
6090 --- linux-2.6.30.10/arch/ubicom32/include/asm/hardirq.h 1970-01-01 02:00:00.000000000 +0200
6091 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hardirq.h     2009-12-11 11:45:11.000000000 +0200
6092 @@ -0,0 +1,55 @@
6093 +/*
6094 + * arch/ubicom32/include/asm/hardirq.h
6095 + *   Definition of ack_bad_irq() for Ubicom32 architecture.
6096 + *
6097 + * (C) Copyright 2009, Ubicom, Inc.
6098 + * Copyright (C) 1997, 98, 99, 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
6099 + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
6100 + * Copyright (C) 2001 MIPS Technologies, Inc.
6101 + *
6102 + * This file is part of the Ubicom32 Linux Kernel Port.
6103 + *
6104 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6105 + * it and/or modify it under the terms of the GNU General Public License
6106 + * as published by the Free Software Foundation, either version 2 of the
6107 + * License, or (at your option) any later version.
6108 + *
6109 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6110 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6111 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6112 + * the GNU General Public License for more details.
6113 + *
6114 + * You should have received a copy of the GNU General Public License
6115 + * along with the Ubicom32 Linux Kernel Port.  If not,
6116 + * see <http://www.gnu.org/licenses/>.
6117 + *
6118 + * Ubicom32 implementation derived from (with many thanks):
6119 + *   arch/m68knommu
6120 + *   arch/blackfin
6121 + *   arch/parisc
6122 + */
6123 +#ifndef _ASM_UBICOM32_HARDIRQ_H
6124 +#define _ASM_UBICOM32_HARDIRQ_H
6125 +
6126 +#include <linux/threads.h>
6127 +#include <linux/irq.h>
6128 +
6129 +/*
6130 + * The hardirq mask has to be large enough to have space
6131 + * for potentially all IRQ sources in the system nesting
6132 + * on a single CPU.  For Ubicom32, we have 64 IRQ sources.
6133 + */
6134 +#define HARDIRQ_BITS   6
6135 +#if (1 << HARDIRQ_BITS) < NR_IRQS
6136 +# error HARDIRQ_BITS is too low!
6137 +#endif
6138 +
6139 +typedef struct {
6140 +       unsigned int __softirq_pending;
6141 +} ____cacheline_aligned irq_cpustat_t;
6142 +
6143 +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
6144 +
6145 +extern void ack_bad_irq(unsigned int irq);
6146 +
6147 +#endif /* _ASM_UBICOM32_HARDIRQ_H */
6148 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/hw_irq.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hw_irq.h
6149 --- linux-2.6.30.10/arch/ubicom32/include/asm/hw_irq.h  1970-01-01 02:00:00.000000000 +0200
6150 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hw_irq.h      2009-12-11 11:45:11.000000000 +0200
6151 @@ -0,0 +1,31 @@
6152 +/*
6153 + * arch/ubicom32/include/asm/hw_irq.h
6154 + *   Ubicom32 architecture APIC support.
6155 + *
6156 + * (C) Copyright 2009, Ubicom, Inc.
6157 + *
6158 + * This file is part of the Ubicom32 Linux Kernel Port.
6159 + *
6160 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6161 + * it and/or modify it under the terms of the GNU General Public License
6162 + * as published by the Free Software Foundation, either version 2 of the
6163 + * License, or (at your option) any later version.
6164 + *
6165 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6166 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6167 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6168 + * the GNU General Public License for more details.
6169 + *
6170 + * You should have received a copy of the GNU General Public License
6171 + * along with the Ubicom32 Linux Kernel Port.  If not,
6172 + * see <http://www.gnu.org/licenses/>.
6173 + *
6174 + * Ubicom32 implementation derived from (with many thanks):
6175 + *   arch/m68knommu
6176 + *   arch/blackfin
6177 + *   arch/parisc
6178 + */
6179 +#ifndef _ASM_UBICOM32_HW_IRQ_H
6180 +#define _ASM_UBICOM32_HW_IRQ_H
6181 +
6182 +#endif /* _ASM_UBICOM32_HW_IRQ_H */
6183 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ioctl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctl.h
6184 --- linux-2.6.30.10/arch/ubicom32/include/asm/ioctl.h   1970-01-01 02:00:00.000000000 +0200
6185 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctl.h       2009-12-11 11:45:11.000000000 +0200
6186 @@ -0,0 +1,33 @@
6187 +/*
6188 + * arch/ubicom32/include/asm/ioctl.h
6189 + *   Generic ioctl.h for Ubicom32 architecture.
6190 + *
6191 + * (C) Copyright 2009, Ubicom, Inc.
6192 + *
6193 + * This file is part of the Ubicom32 Linux Kernel Port.
6194 + *
6195 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6196 + * it and/or modify it under the terms of the GNU General Public License
6197 + * as published by the Free Software Foundation, either version 2 of the
6198 + * License, or (at your option) any later version.
6199 + *
6200 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6201 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6202 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6203 + * the GNU General Public License for more details.
6204 + *
6205 + * You should have received a copy of the GNU General Public License
6206 + * along with the Ubicom32 Linux Kernel Port.  If not,
6207 + * see <http://www.gnu.org/licenses/>.
6208 + *
6209 + * Ubicom32 implementation derived from (with many thanks):
6210 + *   arch/m68knommu
6211 + *   arch/blackfin
6212 + *   arch/parisc
6213 + */
6214 +#ifndef _ASM_UBICOM32_IOCTL_H
6215 +#define _ASM_UBICOM32_IOCTL_H
6216 +
6217 +#include <asm-generic/ioctl.h>
6218 +
6219 +#endif /* _ASM_UBICOM32_IOCTL_H */
6220 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ioctls.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctls.h
6221 --- linux-2.6.30.10/arch/ubicom32/include/asm/ioctls.h  1970-01-01 02:00:00.000000000 +0200
6222 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctls.h      2009-12-11 11:45:11.000000000 +0200
6223 @@ -0,0 +1,111 @@
6224 +/*
6225 + * arch/ubicom32/include/asm/ioctls.h
6226 + *   Definitions of ioctls for Ubicom32 architecture.
6227 + *
6228 + * (C) Copyright 2009, Ubicom, Inc.
6229 + *
6230 + * This file is part of the Ubicom32 Linux Kernel Port.
6231 + *
6232 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6233 + * it and/or modify it under the terms of the GNU General Public License
6234 + * as published by the Free Software Foundation, either version 2 of the
6235 + * License, or (at your option) any later version.
6236 + *
6237 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6238 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6239 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6240 + * the GNU General Public License for more details.
6241 + *
6242 + * You should have received a copy of the GNU General Public License
6243 + * along with the Ubicom32 Linux Kernel Port.  If not,
6244 + * see <http://www.gnu.org/licenses/>.
6245 + *
6246 + * Ubicom32 implementation derived from (with many thanks):
6247 + *   arch/m68knommu
6248 + *   arch/blackfin
6249 + *   arch/parisc
6250 + */
6251 +#ifndef _ASM_UBICOM32_IOCTLS_H
6252 +#define _ASM_UBICOM32_IOCTLS_H
6253 +
6254 +#include <asm/ioctl.h>
6255 +
6256 +/* 0x54 is just a magic number to make these relatively unique ('T') */
6257 +
6258 +#define TCGETS         0x5401
6259 +#define TCSETS         0x5402
6260 +#define TCSETSW                0x5403
6261 +#define TCSETSF                0x5404
6262 +#define TCGETA         0x5405
6263 +#define TCSETA         0x5406
6264 +#define TCSETAW                0x5407
6265 +#define TCSETAF                0x5408
6266 +#define TCSBRK         0x5409
6267 +#define TCXONC         0x540A
6268 +#define TCFLSH         0x540B
6269 +#define TIOCEXCL       0x540C
6270 +#define TIOCNXCL       0x540D
6271 +#define TIOCSCTTY      0x540E
6272 +#define TIOCGPGRP      0x540F
6273 +#define TIOCSPGRP      0x5410
6274 +#define TIOCOUTQ       0x5411
6275 +#define TIOCSTI                0x5412
6276 +#define TIOCGWINSZ     0x5413
6277 +#define TIOCSWINSZ     0x5414
6278 +#define TIOCMGET       0x5415
6279 +#define TIOCMBIS       0x5416
6280 +#define TIOCMBIC       0x5417
6281 +#define TIOCMSET       0x5418
6282 +#define TIOCGSOFTCAR   0x5419
6283 +#define TIOCSSOFTCAR   0x541A
6284 +#define FIONREAD       0x541B
6285 +#define TIOCINQ                FIONREAD
6286 +#define TIOCLINUX      0x541C
6287 +#define TIOCCONS       0x541D
6288 +#define TIOCGSERIAL    0x541E
6289 +#define TIOCSSERIAL    0x541F
6290 +#define TIOCPKT                0x5420
6291 +#define FIONBIO                0x5421
6292 +#define TIOCNOTTY      0x5422
6293 +#define TIOCSETD       0x5423
6294 +#define TIOCGETD       0x5424
6295 +#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
6296 +#define TIOCSBRK       0x5427  /* BSD compatibility */
6297 +#define TIOCCBRK       0x5428  /* BSD compatibility */
6298 +#define TIOCGSID       0x5429  /* Return the session ID of FD */
6299 +#define TCGETS2                _IOR('T',0x2A, struct termios2)
6300 +#define TCSETS2                _IOW('T',0x2B, struct termios2)
6301 +#define TCSETSW2       _IOW('T',0x2C, struct termios2)
6302 +#define TCSETSF2       _IOW('T',0x2D, struct termios2)
6303 +#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
6304 +#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
6305 +
6306 +#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
6307 +#define FIOCLEX                0x5451
6308 +#define FIOASYNC       0x5452
6309 +#define TIOCSERCONFIG  0x5453
6310 +#define TIOCSERGWILD   0x5454
6311 +#define TIOCSERSWILD   0x5455
6312 +#define TIOCGLCKTRMIOS 0x5456
6313 +#define TIOCSLCKTRMIOS 0x5457
6314 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
6315 +#define TIOCSERGETLSR   0x5459 /* Get line status register */
6316 +#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
6317 +#define TIOCSERSETMULTI 0x545B /* Set multiport config */
6318 +
6319 +#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
6320 +#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
6321 +#define FIOQSIZE       0x545E
6322 +
6323 +/* Used for packet mode */
6324 +#define TIOCPKT_DATA            0
6325 +#define TIOCPKT_FLUSHREAD       1
6326 +#define TIOCPKT_FLUSHWRITE      2
6327 +#define TIOCPKT_STOP            4
6328 +#define TIOCPKT_START           8
6329 +#define TIOCPKT_NOSTOP         16
6330 +#define TIOCPKT_DOSTOP         32
6331 +
6332 +#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
6333 +
6334 +#endif /* _ASM_UBICOM32_IOCTLS_H */
6335 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/io.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/io.h
6336 --- linux-2.6.30.10/arch/ubicom32/include/asm/io.h      1970-01-01 02:00:00.000000000 +0200
6337 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/io.h  2009-12-11 11:45:11.000000000 +0200
6338 @@ -0,0 +1,313 @@
6339 +/*
6340 + * arch/ubicom32/include/asm/io.h
6341 + *   I/O memory accessor functions for Ubicom32 architecture.
6342 + *
6343 + * (C) Copyright 2009, Ubicom, Inc.
6344 + *
6345 + * This file is part of the Ubicom32 Linux Kernel Port.
6346 + *
6347 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6348 + * it and/or modify it under the terms of the GNU General Public License
6349 + * as published by the Free Software Foundation, either version 2 of the
6350 + * License, or (at your option) any later version.
6351 + *
6352 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6353 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6354 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6355 + * the GNU General Public License for more details.
6356 + *
6357 + * You should have received a copy of the GNU General Public License
6358 + * along with the Ubicom32 Linux Kernel Port.  If not,
6359 + * see <http://www.gnu.org/licenses/>.
6360 + *
6361 + * Ubicom32 implementation derived from (with many thanks):
6362 + *   arch/m68knommu
6363 + *   arch/blackfin
6364 + *   arch/parisc
6365 + */
6366 +#ifndef _ASM_UBICOM32_IO_H
6367 +#define _ASM_UBICOM32_IO_H
6368 +
6369 +#ifdef __KERNEL__
6370 +#include <linux/string.h>
6371 +#include <linux/compiler.h>
6372 +
6373 +static inline unsigned short _swapw(volatile unsigned short v)
6374 +{
6375 +    return ((v << 8) | (v >> 8));
6376 +}
6377 +
6378 +static inline unsigned int _swapl(volatile unsigned long v)
6379 +{
6380 +    return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
6381 +}
6382 +
6383 +#ifndef CONFIG_PCI
6384 +#define readb(addr) \
6385 +    ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
6386 +#define readw(addr) \
6387 +    ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
6388 +#define readl(addr) \
6389 +    ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
6390 +
6391 +#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
6392 +#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
6393 +#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
6394 +#else /*CONFIG_PCI */
6395 +
6396 +#define PCI_CPU_REG_BASE (0x00000000UL)   /* taking lower 2GB space */
6397 +#define PCI_DEV_REG_BASE (0x80000000UL)
6398 +
6399 +#if PCI_CPU_REG_BASE > PCI_DEV_REG_BASE
6400 +#define IS_PCI_ADDRESS(x) (((unsigned int)(x)&(PCI_CPU_REG_BASE)) == 0)
6401 +#else
6402 +#define IS_PCI_ADDRESS(x) ((unsigned int)(x)&(PCI_DEV_REG_BASE))
6403 +#endif
6404 +
6405 +extern unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr);
6406 +extern unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr);
6407 +extern unsigned char ubi32_pci_read_u8(const volatile void __iomem *addr);
6408 +extern  void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr);
6409 +extern  void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr);
6410 +extern  void ubi32_pci_write_u8(unsigned char val, const volatile void __iomem *addr);
6411 +
6412 +static  inline unsigned char readb(const volatile void __iomem *addr)
6413 +{
6414 +       if (IS_PCI_ADDRESS(addr))
6415 +               return ubi32_pci_read_u8(addr);
6416 +       else
6417 +               return (unsigned char)(*(volatile unsigned char *)addr);
6418 +}
6419 +static inline unsigned short readw(const volatile void __iomem *addr)
6420 +{
6421 +       if (IS_PCI_ADDRESS(addr))
6422 +               return ubi32_pci_read_u16(addr);
6423 +       else
6424 +               return (unsigned short)(*(volatile unsigned short *)addr);
6425 +}
6426 +
6427 +static  inline unsigned int  readl(const volatile void __iomem *addr)
6428 +{
6429 +       if (IS_PCI_ADDRESS(addr))
6430 +               return ubi32_pci_read_u32(addr);
6431 +       else
6432 +               return (unsigned int)(*(volatile unsigned int *)addr);
6433 +}
6434 +
6435 +static inline void writel(unsigned int val, volatile void __iomem *addr)
6436 +{
6437 +       if (IS_PCI_ADDRESS(addr))
6438 +                ubi32_pci_write_u32(val, addr);
6439 +        else
6440 +               *(volatile unsigned int *)addr = val;
6441 +}
6442 +
6443 +static inline void writew(unsigned short val, volatile void __iomem *addr)
6444 +{
6445 +       if (IS_PCI_ADDRESS(addr))
6446 +                ubi32_pci_write_u16(val, addr);
6447 +        else
6448 +               *(volatile unsigned short *)addr = val;
6449 +}
6450 +
6451 +static inline void writeb(unsigned char val, volatile void __iomem *addr)
6452 +{
6453 +       if (IS_PCI_ADDRESS(addr))
6454 +                ubi32_pci_write_u8(val, addr);
6455 +        else
6456 +               *(volatile unsigned char *)addr = val;
6457 +}
6458 +#endif
6459 +
6460 +#define readb_relaxed(addr) readb(addr)
6461 +#define readw_relaxed(addr) readw(addr)
6462 +#define readl_relaxed(addr) readl(addr)
6463 +
6464 +
6465 +#define __raw_readb readb
6466 +#define __raw_readw readw
6467 +#define __raw_readl readl
6468 +#define __raw_writeb writeb
6469 +#define __raw_writew writew
6470 +#define __raw_writel writel
6471 +
6472 +static inline void io_outsb(unsigned int addr, const void *buf, int len)
6473 +{
6474 +       volatile unsigned char *ap = (volatile unsigned char *) addr;
6475 +       unsigned char *bp = (unsigned char *) buf;
6476 +       while (len--)
6477 +               *ap = *bp++;
6478 +}
6479 +
6480 +static inline void io_outsw(unsigned int addr, const void *buf, int len)
6481 +{
6482 +       volatile unsigned short *ap = (volatile unsigned short *) addr;
6483 +       unsigned short *bp = (unsigned short *) buf;
6484 +       while (len--)
6485 +               *ap = _swapw(*bp++);
6486 +}
6487 +
6488 +static inline void io_outsl(unsigned int addr, const void *buf, int len)
6489 +{
6490 +       volatile unsigned int *ap = (volatile unsigned int *) addr;
6491 +       unsigned int *bp = (unsigned int *) buf;
6492 +       while (len--)
6493 +               *ap = _swapl(*bp++);
6494 +}
6495 +
6496 +static inline void io_insb(unsigned int addr, void *buf, int len)
6497 +{
6498 +       volatile unsigned char *ap = (volatile unsigned char *) addr;
6499 +       unsigned char *bp = (unsigned char *) buf;
6500 +       while (len--)
6501 +               *bp++ = *ap;
6502 +}
6503 +
6504 +static inline void io_insw(unsigned int addr, void *buf, int len)
6505 +{
6506 +       volatile unsigned short *ap = (volatile unsigned short *) addr;
6507 +       unsigned short *bp = (unsigned short *) buf;
6508 +       while (len--)
6509 +               *bp++ = _swapw(*ap);
6510 +}
6511 +
6512 +static inline void io_insl(unsigned int addr, void *buf, int len)
6513 +{
6514 +       volatile unsigned int *ap = (volatile unsigned int *) addr;
6515 +       unsigned int *bp = (unsigned int *) buf;
6516 +       while (len--)
6517 +               *bp++ = _swapl(*ap);
6518 +}
6519 +
6520 +#define mmiowb()
6521 +
6522 +/*
6523 + *     make the short names macros so specific devices
6524 + *     can override them as required
6525 + */
6526 +#ifndef CONFIG_PCI
6527 +#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
6528 +#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
6529 +#define memcpy_toio(a,b,c)     memcpy((void *)(a),(b),(c))
6530 +#else
6531 +extern void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len);
6532 +extern void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len);
6533 +extern void memset_io(volatile void __iomem *addr, int val, size_t count);
6534 +#endif
6535 +
6536 +#define inb(addr)    readb(addr)
6537 +#define inw(addr)    readw(addr)
6538 +#define inl(addr)    readl(addr)
6539 +#define outb(x,addr) ((void) writeb(x,addr))
6540 +#define outw(x,addr) ((void) writew(x,addr))
6541 +#define outl(x,addr) ((void) writel(x,addr))
6542 +
6543 +#define inb_p(addr)    inb(addr)
6544 +#define inw_p(addr)    inw(addr)
6545 +#define inl_p(addr)    inl(addr)
6546 +#define outb_p(x,addr) outb(x,addr)
6547 +#define outw_p(x,addr) outw(x,addr)
6548 +#define outl_p(x,addr) outl(x,addr)
6549 +
6550 +#define outsb(a,b,l) io_outsb(a,b,l)
6551 +#define outsw(a,b,l) io_outsw(a,b,l)
6552 +#define outsl(a,b,l) io_outsl(a,b,l)
6553 +
6554 +#define insb(a,b,l) io_insb(a,b,l)
6555 +#define insw(a,b,l) io_insw(a,b,l)
6556 +#define insl(a,b,l) io_insl(a,b,l)
6557 +
6558 +#ifndef CONFIG_PCI
6559 +#define ioread8_rep(a,d,c)     insb(a,d,c)
6560 +#define ioread16_rep(a,d,c)    insw(a,d,c)
6561 +#define ioread32_rep(a,d,c)    insl(a,d,c)
6562 +#define iowrite8_rep(a,s,c)    outsb(a,s,c)
6563 +#define iowrite16_rep(a,s,c)   outsw(a,s,c)
6564 +#define iowrite32_rep(a,s,c)   outsl(a,s,c)
6565 +#else
6566 +extern void  ioread8_rep(void __iomem *port, void *buf, unsigned long count);
6567 +extern void  ioread16_rep(void __iomem *port, void *buf, unsigned long count);
6568 +extern void  ioread32_rep(void __iomem *port, void *buf, unsigned long count);
6569 +extern void  iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
6570 +extern void  iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
6571 +extern void  iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
6572 +#endif
6573 +
6574 +
6575 +#ifndef CONFIG_PCI
6576 +#define ioread8(X)                     readb(X)
6577 +#define ioread16(X)                    readw(X)
6578 +#define ioread32(X)                    readl(X)
6579 +#define iowrite8(val,X)                        writeb(val,X)
6580 +#define iowrite16(val,X)               writew(val,X)
6581 +#define iowrite32(val,X)               writel(val,X)
6582 +#else /*CONFIG_PCI */
6583 +extern  unsigned char  ioread8(void __iomem *addr);
6584 +extern  unsigned short ioread16(void __iomem *addr);
6585 +extern  unsigned int  ioread32(void __iomem *addr);
6586 +extern  void iowrite8(unsigned char val, void __iomem *addr);
6587 +extern  void iowrite16(unsigned short val, void __iomem *addr);
6588 +extern  void iowrite32(unsigned int val, void __iomem *addr);
6589 +#endif /* CONFIG_PCI */
6590 +
6591 +#define IO_SPACE_LIMIT 0xffff
6592 +
6593 +/* Values for nocacheflag and cmode */
6594 +#define IOMAP_FULL_CACHING             0
6595 +#define IOMAP_NOCACHE_SER              1
6596 +#define IOMAP_NOCACHE_NONSER           2
6597 +#define IOMAP_WRITETHROUGH             3
6598 +
6599 +extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
6600 +extern void __iounmap(void *addr, unsigned long size);
6601 +
6602 +static inline void *ioremap(unsigned long physaddr, unsigned long size)
6603 +{
6604 +       return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6605 +}
6606 +static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
6607 +{
6608 +       return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6609 +}
6610 +static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
6611 +{
6612 +       return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
6613 +}
6614 +static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
6615 +{
6616 +       return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
6617 +}
6618 +
6619 +extern void iounmap(void *addr);
6620 +
6621 +#define ioport_map(port, nr)            ((void __iomem*)(port))
6622 +#define ioport_unmap(addr)
6623 +
6624 +
6625 +/* Pages to physical address... */
6626 +#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
6627 +#define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
6628 +
6629 +/*
6630 + * Macros used for converting between virtual and physical mappings.
6631 + */
6632 +#define phys_to_virt(vaddr)    ((void *) (vaddr))
6633 +#define virt_to_phys(vaddr)    ((unsigned long) (vaddr))
6634 +
6635 +#define virt_to_bus virt_to_phys
6636 +#define bus_to_virt phys_to_virt
6637 +
6638 +/*
6639 + * Convert a physical pointer to a virtual kernel pointer for /dev/mem
6640 + * access
6641 + */
6642 +#define xlate_dev_mem_ptr(p)   __va(p)
6643 +
6644 +/*
6645 + * Convert a virtual cached pointer to an uncached pointer
6646 + */
6647 +#define xlate_dev_kmem_ptr(p)  p
6648 +
6649 +#endif /* __KERNEL__ */
6650 +
6651 +#endif /* _ASM_UBICOM32_IO_H */
6652 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ip5000-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000-asm.h
6653 --- linux-2.6.30.10/arch/ubicom32/include/asm/ip5000-asm.h      1970-01-01 02:00:00.000000000 +0200
6654 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000-asm.h  2009-12-11 11:45:11.000000000 +0200
6655 @@ -0,0 +1,156 @@
6656 +/*
6657 + * arch/ubicom32/include/asm/ip5000-asm.h
6658 + *     Instruction macros for the IP5000.
6659 + *
6660 + * (C) Copyright 2009, Ubicom, Inc.
6661 + *
6662 + * This file is part of the Ubicom32 Linux Kernel Port.
6663 + *
6664 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6665 + * it and/or modify it under the terms of the GNU General Public License
6666 + * as published by the Free Software Foundation, either version 2 of the
6667 + * License, or (at your option) any later version.
6668 + *
6669 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6670 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6671 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6672 + * the GNU General Public License for more details.
6673 + *
6674 + * You should have received a copy of the GNU General Public License
6675 + * along with the Ubicom32 Linux Kernel Port.  If not,
6676 + * see <http://www.gnu.org/licenses/>.
6677 + *
6678 + * Ubicom32 implementation derived from (with many thanks):
6679 + *   arch/m68knommu
6680 + *   arch/blackfin
6681 + *   arch/parisc
6682 + */
6683 +
6684 +#ifndef _ASM_UBICOM32_IP5000_ASM_H
6685 +#define _ASM_UBICOM32_IP5000_ASM_H
6686 +
6687 +#if !defined(__LINKER__)
6688 +
6689 +#if defined(__ASSEMBLY__)
6690 +.macro cycles  quant
6691 +.if    (\quant) == 1
6692 +       nop
6693 +.else
6694 +.if    (((\quant) + 3) / 8) > 0
6695 +.rept  (((\quant) + 3) / 8)
6696 +       jmpt.f          .+4
6697 +.endr
6698 +.endif
6699 +.if    ((((\quant) + 3) % 8) / 4) > 0
6700 +       jmpt.t          .+4
6701 +.endif
6702 +.endif
6703 +.endm
6704 +#else
6705 +/*
6706 + * Same macro as above just in C inline asm
6707 + */
6708 +asm ("                                 \n\
6709 +.macro cycles  quant                   \n\
6710 +.if    (\\quant) == 1                  \n\
6711 +       nop                             \n\
6712 +.else                                  \n\
6713 +.if    (((\\quant) + 3) / 8) > 0       \n\
6714 +.rept  (((\\quant) + 3) / 8)           \n\
6715 +       jmpt.f          .+4             \n\
6716 +.endr                                  \n\
6717 +.endif                                 \n\
6718 +.if    ((((\\quant) + 3) % 8) / 4) > 0 \n\
6719 +       jmpt.t          .+4             \n\
6720 +.endif                                 \n\
6721 +.endif                                 \n\
6722 +.endm                                  \n\
6723 +");
6724 +#endif
6725 +
6726 +
6727 +#if defined(__ASSEMBLY__)
6728 +.macro pipe_flush      cyc
6729 +       cycles          11 - (\cyc)
6730 +.endm
6731 +#else
6732 +/*
6733 + * Same macro as above just in C inline asm
6734 + */
6735 +asm ("                                 \n\
6736 +.macro pipe_flush      cyc             \n\
6737 +       cycles          11 - (\\cyc)    \n\
6738 +.endm                                  \n\
6739 +");
6740 +
6741 +#endif
6742 +
6743 +#if defined(__ASSEMBLY__)
6744 +.macro setcsr_flush    cyc
6745 +       cycles          5 - (\cyc)
6746 +.endm
6747 +#else
6748 +/*
6749 + * Same macro as above just in C inline asm
6750 + */
6751 +asm ("                                 \n\
6752 +.macro setcsr_flush    cyc             \n\
6753 +       cycles          5 - (\\cyc)     \n\
6754 +.endm                                  \n\
6755 +");
6756 +#endif
6757 +
6758 +/*
6759 + * Macros for prefetch (using miss-aligned memory write)
6760 + */
6761 +#if defined(__ASSEMBLY__)
6762 +
6763 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length
6764 +       bclr            MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6765 +       bset            \Ascratch, \Aaddress, #0        ; force a miss-aligned address
6766 +       jmpt.t          .+4                             ; delay for both address setup and trap disable
6767 +       move.4          (\Ascratch), #0
6768 +       .if             (\length > 32)
6769 +       move.4          32(\Ascratch), #0
6770 +       .endif
6771 +       .if             (\length > 64)
6772 +       move.4          64(\Ascratch), #0
6773 +       .endif
6774 +       .if             (\length > 96)
6775 +       move.4          96(\Ascratch), #0
6776 +       .endif
6777 +       .if             (\length > 128)
6778 +       invalid_instruction                             ; maximum pre-fetch size is 4 cache lines
6779 +       .endif
6780 +       bset            MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6781 +.endm
6782 +
6783 +#else
6784 +/*
6785 + * Same macro as above just in C inline asm
6786 + */
6787 +asm ("                                                         \n\
6788 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length   \n\
6789 +       bclr            MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)  \n\
6790 +       bset            \\Ascratch, \\Aaddress, #0      ; force a miss-aligned address \n\
6791 +       jmpt.t          .+4                             ; delay for both address setup and trap disable \n\
6792 +       move.4          (\\Ascratch), #0                        \n\
6793 +       .if             (\\length > 32)                         \n\
6794 +       move.4          32(\\Ascratch), #0                      \n\
6795 +       .endif                                                  \n\
6796 +       .if             (\\length > 64)                         \n\
6797 +       move.4          64(\\Ascratch), #0                      \n\
6798 +       .endif                                                  \n\
6799 +       .if             (\\length > 96)                         \n\
6800 +       move.4          96(\\Ascratch), #0                      \n\
6801 +       .endif                                                  \n\
6802 +       .if             (\\length > 128)                        \n\
6803 +       invalid_instruction                             ; maximum pre-fetch size is 4 cache lines \n\
6804 +       .endif                                                  \n\
6805 +       bset            MT_TRAP_EN, MT_TRAP_EN, #(\\thread_num) \n\
6806 +.endm                                                          \n\
6807 +");
6808 +#endif
6809 +
6810 +#endif /* !defined(__LINKER__) */
6811 +#endif /* defined _ASM_UBICOM32_IP5000_ASM_H */
6812 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ip5000.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000.h
6813 --- linux-2.6.30.10/arch/ubicom32/include/asm/ip5000.h  1970-01-01 02:00:00.000000000 +0200
6814 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000.h      2009-12-11 11:45:11.000000000 +0200
6815 @@ -0,0 +1,845 @@
6816 +/*
6817 + * arch/ubicom32/include/asm/ip5000.h
6818 + *   Specific details for the Ubicom IP5000 processor.
6819 + *
6820 + * (C) Copyright 2009, Ubicom, Inc.
6821 + *
6822 + * This file is part of the Ubicom32 Linux Kernel Port.
6823 + *
6824 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6825 + * it and/or modify it under the terms of the GNU General Public License
6826 + * as published by the Free Software Foundation, either version 2 of the
6827 + * License, or (at your option) any later version.
6828 + *
6829 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6830 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6831 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6832 + * the GNU General Public License for more details.
6833 + *
6834 + * You should have received a copy of the GNU General Public License
6835 + * along with the Ubicom32 Linux Kernel Port.  If not,
6836 + * see <http://www.gnu.org/licenses/>.
6837 + *
6838 + * Ubicom32 implementation derived from (with many thanks):
6839 + *   arch/m68knommu
6840 + *   arch/blackfin
6841 + *   arch/parisc
6842 + */
6843 +
6844 +#ifndef _ASM_UBICOM32_IP5000_H
6845 +#define _ASM_UBICOM32_IP5000_H
6846 +
6847 +#include <asm/memory_map.h>
6848 +
6849 +/*
6850 + * Inline assembly define
6851 + */
6852 +#define S(arg) #arg
6853 +#define D(arg) S(arg)
6854 +
6855 +/*
6856 + * Assembler include file
6857 + */
6858 +#include <asm/ip5000-asm.h>
6859 +
6860 +/*
6861 + * Timing
6862 + */
6863 +#define JMPT_PENALTY 3
6864 +#define JMPF_PENALTY 7
6865 +#define RET_PENALTY 7
6866 +
6867 +/*
6868 + * Threads
6869 + */
6870 +#if defined(IP5000) || defined(IP5000_REV2)
6871 +#define THREAD_COUNT 10
6872 +#elif defined(IP7000) || defined(IP7000_REV2)
6873 +#define THREAD_COUNT 12
6874 +#else
6875 +#error "Unknown IP5K silicon"
6876 +#endif
6877 +
6878 +/*
6879 + * Arch
6880 + */
6881 +#if defined(IP5000) || defined(IP5000_REV2)
6882 +#define UBICOM32_ARCH_VERSION 3
6883 +#elif defined(IP7000) || defined(IP7000_REV2)
6884 +#define UBICOM32_ARCH_VERSION 4
6885 +#else
6886 +#error "Unknown IP5K silicon"
6887 +#endif
6888 +
6889 +
6890 +/*
6891 + * Registers
6892 + */
6893 +#define ROSR_INT (1 << 0)
6894 +
6895 +/* Interrupts */
6896 +#define INT_CHIP(reg, bit) (((reg) << 5) | (bit))
6897 +#define INT_REG(interrupt) (((interrupt) >> 5) * 4)
6898 +#define INT_SET(interrupt) 0x0114 + INT_REG(interrupt)
6899 +#define INT_CLR(interrupt) 0x0124 + INT_REG(interrupt)
6900 +#define INT_STAT(interrupt) 0x0104 + INT_REG(interrupt)
6901 +#define INT_MASK(interrupt) 0x00C0 + INT_REG(interrupt)
6902 +#define INT_BIT(interrupt) ((interrupt) & 0x1F)
6903 +#define INT_BIT_MASK(interrupt) (1 << INT_BIT(interrupt))
6904 +
6905 +/*
6906 + * The LOCK_INT and THREAD_INT are used to wake up corresponding thread. They are sharing
6907 + * the same set of SW interrupt resource.
6908 + *
6909 + * LOCK_INT(n): One SW INT per NRT thread that can participate lock operation.
6910 + *     The threads that can participate lock are application threads and DSR thread.
6911 + *     (Lock locks - numbers are hard-coded in lock.h)
6912 + * THREAD_INT(n):   One SW INT per HRT thread for wake up trigger.
6913 + */
6914 +#define LOCK_INT(thread)       INT_CHIP(0, (thread))
6915 +#define THREAD_INT(thread)     INT_CHIP(0, (thread))
6916 +
6917 +/*
6918 + * The SYSTEM_INT and DSR_INT are sharing the same set of SW interrupt resource.
6919 + *
6920 + * SYSTEM_INT(n): One SW INT per NRT threads (application threads) as system queue interrupt,
6921 + *     and for DSR as self-trigger interrupt.
6922 + *     (The application threads include at least thread 0)
6923 + * DSR_INT(n):    One SW INT per HRT thread to request DSR service.
6924 + */
6925 +#define SYSTEM_INT(thread)     INT_CHIP(0, THREAD_COUNT + (thread))
6926 +#define DSR_INT(thread)                INT_CHIP(0, THREAD_COUNT + (thread))
6927 +
6928 +/* GLOBAL_CTRL */
6929 +#define GLOBAL_CTRL_TRAP_RST_EN (1 << 9)
6930 +#define GLOBAL_CTRL_AERROR_RST_EN (1 << 8)
6931 +#define GLOBAL_CTRL_MT_MIN_DELAY(x) ((x) << 3)
6932 +#define GLOBAL_CTRL_HRT_BANK_SELECT (1 << 2)
6933 +#define GLOBAL_CTRL_INT_EN (1 << 0)
6934 +
6935 +/*
6936 + * HRT Tables
6937 + */
6938 +#define HRT_TABLE0_BASE 0x0800
6939 +#define HRT_TABLE1_BASE 0x0900
6940 +#define HRT_TABLE_SIZE 64
6941 +
6942 +/*
6943 + * Break Point Trap Register
6944 + */
6945 +#define ASYNCERROR_INT INT_CHIP(0, 31)
6946 +#define BREAKPOINT_INT INT_CHIP(1, 31)
6947 +
6948 +/*
6949 + * Port interrupts
6950 + *     The non-existing FIFO INTs are mapped to INT2 for the ports.
6951 + */
6952 +#define IO_PORT_PTR_TO_NUM(port) (((port) & 0x0000ffff) >> 12)
6953 +#define RX_FIFO_INT(port) \
6954 +       ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6955 +       ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 26) : \
6956 +       ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6957 +       ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 24) : \
6958 +       ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 27) : \
6959 +       ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 16) : \
6960 +       ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6961 +       ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6962 +       ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 21) : \
6963 +       INT_CHIP(1, 15))))))))))
6964 +#define TX_FIFO_INT(port) \
6965 +       ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 24) : \
6966 +       ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 27) : \
6967 +       ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6968 +       ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 25) : \
6969 +       ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 28) : \
6970 +       ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 17) : \
6971 +       ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6972 +       ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6973 +       ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 22) : \
6974 +       INT_CHIP(1, 15))))))))))
6975 +#define PORT_OTHER_INT(port) \
6976 +       ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6977 +       ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 28) : \
6978 +       ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6979 +       ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 26) : \
6980 +       ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 29) : \
6981 +       ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 18) : \
6982 +       ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6983 +       ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6984 +       ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 23) : \
6985 +       INT_CHIP(1, 15))))))))))
6986 +
6987 +/*
6988 + * On Chip Peripherals Base.
6989 + */
6990 +#define OCP_BASE       0x01000000
6991 +#define OCP_GENERAL    0x000
6992 +#define OCP_TIMERS     0x100
6993 +#define OCP_TRNG       0x200   /* True Random Number Generator Control Reigsters */
6994 +#define OCP_DEBUG      0x300
6995 +#define OCP_SECURITY   0x400
6996 +#define OCP_ICCR       0x500   /* I-Cache Control Registers */
6997 +#define OCP_DCCR       0x600   /* D-Cache Control Registers */
6998 +#define OCP_OCMC       0x700   /* On Chip Memory Control Registers */
6999 +#define OCP_STATISTICS 0x800   /* Statistics Counters */
7000 +#define OCP_MTEST      0x900   /* Memory Test Registers */
7001 +#define OCP_MCFG       0xa00   /* Memory Configuration Registers -- IP7000 only */
7002 +#define OCP_DEBUG_INST 0x000   /* Up to 16M */
7003 +
7004 +/*
7005 + * General Configuration Registers (PLL)
7006 + */
7007 +#define GENERAL_CFG_BASE (OCP_BASE + OCP_GENERAL)
7008 +#define GEN_CLK_CORE_CFG 0x00
7009 +#define GEN_CLK_IO_CFG 0x04
7010 +#define GEN_CLK_DDR_CFG 0x08
7011 +#define GEN_CLK_DDRDS_CFG 0x0c
7012 +#define GEN_CLK_SLIP_CLR 0x10
7013 +#define GEN_CLK_SLIP_START 0x14
7014 +#define GEN_CLK_SERDES_SEL 0x18        /* IP7000 only */
7015 +#define GEN_CLK_DDR_CFG2 0x1c  /* IP7000 only */
7016 +#define GEN_DDR_CAL_CTRL 0x30  /* IP5000 only */
7017 +#define GEN_DDR_CAL_STAT 0x34  /* IP5000 only */
7018 +#define GEN_USB_DFT_CTRL 0x38  /* IP5000 only */
7019 +#define GEN_USB_DFT_STAT 0x3c  /* IP5000 only */
7020 +#define GEN_USB_PHY_CFG 0x40   /* IP7000 only */
7021 +#define GEN_USB_PHY_TEST 0x44  /* IP7000 only */
7022 +#define GEN_USB_PHY_STAT 0x48  /* IP7000 only */
7023 +#define GEN_SW_RESET 0x80
7024 +#define GEN_RESET_REASON 0x84
7025 +#define GEN_BOND_CFG 0x88
7026 +#define GEN_IO_PU_CFG 0x8c
7027 +#define GEN_MEM_RM_CFG 0x90
7028 +#define GEN_IO_CONFIG 0x94
7029 +
7030 +#define GEN_CLK_PLL_SECURITY_BIT_NO 31
7031 +#define GEN_CLK_PLL_SECURITY (1 << GEN_CLK_PLL_SECURITY_BIT_NO)
7032 +#define GEN_CLK_PLL_ENSAT (1 << 30)
7033 +#define GEN_CLK_PLL_FASTEN (1 << 29)
7034 +#define GEN_CLK_PLL_NR(v) (((v) - 1) << 23)
7035 +#define GEN_CLK_PLL_NF(v) (((v) - 1) << 11)
7036 +#define GEN_CLK_PLL_OD(v) (((v) - 1) << 8)
7037 +#define GEN_CLK_PLL_RESET (1 << 7)
7038 +#define GEN_CLK_PLL_BYPASS (1 << 6)
7039 +#define GEN_CLK_PLL_POWERDOWN (1 << 5)
7040 +#define GEN_CLK_PLL_SELECT (1 << 4)
7041 +
7042 +#define GEN_GET_CLK_PLL_NR(v) ((((v) >> 23) & 0x003f) + 1)
7043 +#define GEN_GET_CLK_PLL_NF(v) ((((v) >> 11) & 0x0fff) + 1)
7044 +#define GEN_GET_CLK_PLL_OD(v) ((((v) >> 8) & 0x7) + 1)
7045 +
7046 +
7047 +#define RESET_FLAG_DST_MEM_ERROR (1 << 18)
7048 +#define RESET_FLAG_SRC1_MEM_ERROR (1 << 17)
7049 +#define RESET_FLAG_WRITE_ADDR (1 << 16)
7050 +#define RESET_FLAG_DST_SYNC_ERROR (1 << 15)
7051 +#define RESET_FLAG_SRC1_SYNC_ERROR (1 << 14)
7052 +#define RESET_FLAG_DST_ALGN_ERROR (1 << 13)
7053 +#define RESET_FLAG_SRC1_ALGN_ERROR (1 << 12)
7054 +#define RESET_FLAG_DST_ADDR_ERROR (1 << 11)
7055 +#define RESET_FLAG_SRC1_ADDR_ERROR (1 << 10)
7056 +#define RESET_FLAG_ILLEGAL_INST (1 << 9)
7057 +#define RESET_FLAG_INST_SYNC_ERROR (1 << 8)
7058 +#define RESET_FLAG_INST_ADDR_ERROR (1 << 7)
7059 +#define RESET_FLAG_DATA_PORT_ERROR (1 << 6)
7060 +#define RESET_FLAG_INST_PORT_ERROR (1 << 5)
7061 +#define RESET_FLAG_SW_RESET (1 << 4)
7062 +#define RESET_FLAG_DEBUG (1 << 3)
7063 +#define RESET_FLAG_WATCHDOG (1 << 2)
7064 +#define RESET_FLAG_POWER_ON (1 << 1)
7065 +#define RESET_FLAG_EXTERNAL (1 << 0)
7066 +
7067 +/*
7068 + * Timer block
7069 + */
7070 +#define TIMER_BASE (OCP_BASE + OCP_TIMERS)
7071 +#define TIMER_MPTVAL 0x00
7072 +#define TIMER_RTCOM 0x04
7073 +#define TIMER_TKEY 0x08
7074 +#define TIMER_WDCOM 0x0c
7075 +#define TIMER_WDCFG 0x10
7076 +#define TIMER_SYSVAL 0x14
7077 +#define TIMER_SYSCOM(tmr) (0x18 + (tmr) * 4)
7078 +#define TIMER_TRN_CFG 0x100
7079 +#define TIMER_TRN 0x104
7080 +
7081 +#define TIMER_COUNT 10
7082 +#define TIMER_INT(tmr) INT_CHIP(1, (tmr))
7083 +#define TIMER_TKEYVAL 0xa1b2c3d4
7084 +#define TIMER_WATCHDOG_DISABLE 0x4d3c2b1a
7085 +#define TIMER_TRN_CFG_ENABLE_OSC 0x00000007
7086 +
7087 +#ifndef __ASSEMBLY__
7088 +/*
7089 + * ubicom32_io_timer
7090 + */
7091 +struct ubicom32_io_timer {
7092 +       volatile u32_t mptval;
7093 +       volatile u32_t rtcom;
7094 +       volatile u32_t tkey;
7095 +       volatile u32_t wdcom;
7096 +       volatile u32_t wdcfg;
7097 +       volatile u32_t sysval;
7098 +       volatile u32_t syscom[TIMER_COUNT];
7099 +       volatile u32_t reserved[64 - 6 - TIMER_COUNT];  // skip all the way to OCP-TRNG section
7100 +       volatile u32_t rsgcfg;
7101 +       volatile u32_t trn;
7102 +};
7103 +
7104 +#define UBICOM32_IO_TIMER ((struct ubicom32_io_timer *)TIMER_BASE)
7105 +#endif
7106 +
7107 +#define UBICOM32_VECTOR_TO_TIMER_INDEX(vector) (vector - TIMER_INT(0))
7108 +
7109 +/*
7110 + * OCP-Debug Module (Mailbox)
7111 + */
7112 +#define ISD_MAILBOX_BASE (OCP_BASE + OCP_DEBUG)
7113 +#define ISD_MAILBOX_IN 0x00
7114 +#define ISD_MAILBOX_OUT 0x04
7115 +#define ISD_MAILBOX_STATUS 0x08
7116 +
7117 +#define ISD_MAILBOX_INT INT_CHIP(1, 30)
7118 +
7119 +#define ISD_MAILBOX_STATUS_IN_FULL (1 << 31)
7120 +#define ISD_MAILBOX_STATUS_IN_EMPTY (1 << 30)
7121 +#define ISD_MAILBOX_STATUS_OUT_FULL (1 << 29)
7122 +#define ISD_MAILBOX_STATUS_OUT_EMPTY (1 << 28)
7123 +
7124 +/*
7125 + * OCP-Security
7126 + */
7127 +#define SECURITY_BASE (OCP_BASE + OCP_SECURITY)
7128 +#define SECURITY_BASE_EFFECTIVE_ADDRESS (SECURITY_BASE >> 7) // To load the base address in a single instruction
7129 +#define SECURITY_CTRL 0x00
7130 +#define SECURITY_CTRL_BYTE_OFFSET(x) ((x) << 16)
7131 +#define SECURITY_CTRL_KEY_SIZE(x) ((x) << 8)
7132 +#define SECURITY_CTRL_HASH_ALG_NONE (0 << 4)
7133 +#define SECURITY_CTRL_HASH_ALG_MD5 (1 << 4)
7134 +#define SECURITY_CTRL_HASH_ALG_SHA1 (2 << 4)
7135 +#define SECURITY_CTRL_CBC (1 << 3)
7136 +#define SECURITY_CTRL_CIPHER_ALG_AES (0 << 1)
7137 +#define SECURITY_CTRL_CIPHER_ALG_NONE (1 << 1)
7138 +#define SECURITY_CTRL_CIPHER_ALG_DES (2 << 1)
7139 +#define SECURITY_CTRL_CIPHER_ALG_3DES (3 << 1)
7140 +#define SECURITY_CTRL_ENCIPHER (1 << 0)
7141 +#define SECURITY_CTRL_DECIPHER (0 << 0)
7142 +#define SECURITY_STAT 0x04
7143 +#define SECURITY_STAT_BUSY (1 << 0)
7144 +#define SECURITY_KEY_VALUE(x) (0x10 + (x) * 4)
7145 +#define SECURITY_KEY_IN(x) (0x30 + (x) * 4)
7146 +#define SECURITY_KEY_OUT(x) (0x50 + (x) * 4)
7147 +#define SECURITY_KEY_HASH(x) (0x70 + (x) * 4)
7148 +
7149 +/*
7150 + * OCP-ICCR
7151 + */
7152 +#define ICCR_BASE (OCP_BASE + OCP_ICCR)
7153 +#define ICACHE_TOTAL_SIZE 16384                        /* in bytes */
7154 +
7155 +/*
7156 + * OCP-DCCR
7157 + */
7158 +#define DCCR_BASE (OCP_BASE + OCP_DCCR)
7159 +#if defined(IP5000) || defined(IP5000_REV2)
7160 +#define DCACHE_TOTAL_SIZE 8192                 /* in bytes */
7161 +#elif defined(IP7000) || defined(IP7000_REV2)
7162 +#define DCACHE_TOTAL_SIZE 16384                        /* in bytes */
7163 +#endif
7164 +
7165 +#if defined(IP5000) || defined(IP5000_REV2) || defined(IP7000) || defined(IP7000_REV2)
7166 +#define DCACHE_WRITE_QUEUE_LENGTH 6
7167 +#else
7168 +#error "Unknown IP5K silicon"
7169 +#endif
7170 +
7171 +#define CACHE_LINE_SIZE 32                     /* in bytes */
7172 +
7173 +#define CCR_ADDR 0x00
7174 +#define CCR_RDD 0x04
7175 +#define CCR_WRD 0x08
7176 +#define CCR_STAT 0x0c
7177 +#define CCR_CTRL 0x10
7178 +
7179 +#define CCR_STAT_MCBE 0
7180 +#define CCR_STAT_WIDEL 1                       /* D-cache only */
7181 +
7182 +#define CCR_CTRL_DONE 0
7183 +#define CCR_CTRL_RESET 2
7184 +#define CCR_CTRL_VALID 3
7185 +#define CCR_CTRL_RD_DATA (1 << 4)
7186 +#define CCR_CTRL_RD_TAG (2 << 4)
7187 +#define CCR_CTRL_WR_DATA (3 << 4)
7188 +#define CCR_CTRL_WR_TAG (4 << 4)
7189 +#define CCR_CTRL_INV_INDEX (5 << 4)
7190 +#define CCR_CTRL_INV_ADDR (6 << 4)
7191 +#define CCR_CTRL_FLUSH_INDEX (7 << 4)          /* D-cache only */
7192 +#define CCR_CTRL_FLUSH_INV_INDEX (8 << 4)      /* D-cache only */
7193 +#define CCR_CTRL_FLUSH_ADDR (9 << 4)           /* D-cache only */
7194 +#define CCR_CTRL_FLUSH_INV_ADDR (10 << 4)      /* D-cache only */
7195 +
7196 +/*
7197 + * OCP-OCMC
7198 + */
7199 +#define OCMC_BASE (OCP_BASE + OCP_OCMC)
7200 +#define OCMC_BANK_MASK 0x00
7201 +#define OCMC_BIST_CNTL 0x04    /* IP5000 only */
7202 +#define OCMC_BIST_STAT 0x08    /* IP5000 only */
7203 +
7204 +#define OCMC_BANK_PROG(n) ((1<<(n))-1)
7205 +
7206 +#define OCMC_BIST_WRCK (1 << 7)
7207 +#define OCMC_BIST_RESET (1 << 5)
7208 +#define OCMC_BIST_SMART (1 << 4)
7209 +#define OCMC_BIST_RUN (1 << 3)
7210 +#define OCMC_BIST_REPAIR (1 << 2)
7211 +
7212 +#define OCMC_BIST_READY (1 << 3)
7213 +#define OCMC_BIST_FAIL (1 << 2)
7214 +
7215 +/*
7216 + * OCP-STATISTICS
7217 + */
7218 +#define STATISTICS_BASE (OCP_BASE + OCP_STATISTICS)
7219 +#define STAT_COUNTER_CTRL(n) ((n)*8)
7220 +#define STAT_COUNTER(n) ((n)*8 + 4)
7221 +
7222 +#define STAT_EVENT_MP_INST 0
7223 +#define STAT_EVENT_OCM_ACCESS 4
7224 +#define STAT_EVENT_OCM_REQ 5
7225 +#define STAT_EVENT_IC_REQ_INVAL 13
7226 +#define STAT_EVENT_IC_MISS_INVAL 14
7227 +#define STAT_EVENT_IC_REQ_INVAL_NACK 15
7228 +#define STAT_EVENT_IC_REQ_VAL 16
7229 +#define STAT_EVENT_IC_MISS_VAL 17
7230 +#define STAT_EVENT_IC_REQ_VAL_NACK 18
7231 +#define STAT_EVENT_IC_MISS_Q 19
7232 +#define STAT_EVENT_DC_RD_REQ 20
7233 +#define STAT_EVENT_DC_RD_MISS 21
7234 +#define STAT_EVENT_DC_WR_REQ 22
7235 +#define STAT_EVENT_DC_WR_MISS 23
7236 +#define STAT_EVENT_DC_MISS_Q 24
7237 +#define STAT_EVENT_DC_WB_FULL 25
7238 +#define STAT_EVENT_DC_REQ_NACK 26
7239 +#define STAT_EVENT_DC_CORE_REQ 27
7240 +#define STAT_EVENT_DC_MISS 28
7241 +#define STAT_EVENT_DC_EVICT 29
7242 +#define STAT_EVENT_TRUE 30
7243 +#define STAT_EVENT_FALSE 31
7244 +
7245 +/*
7246 + * OCP_MTEST
7247 + */
7248 +#define MTEST_BASE (OCP_BASE + OCP_MTEST)
7249 +#define MTEST_ADDR 0x00
7250 +#define MTEST_WR 0x04
7251 +#define MTEST_RD 0x08
7252 +#define MTEST_CTRL 0x0c
7253 +
7254 +/*
7255 + * OCP_MCFG (IP7000 only)
7256 + */
7257 +#define MCFG_BASE (OCP_BASE + OCP_MCFG)
7258 +#define MCFG_CTRL 0x00
7259 +#define MCFG_WCFG 0x04
7260 +#define MCFG_RCFG 0x08
7261 +
7262 +/*
7263 + * Port registers
7264 + */
7265 +#define IO_BASE 0x02000000
7266 +#define RA (IO_BASE + 0x00000000)
7267 +#define RB (IO_BASE + 0x00001000)
7268 +#define RC (IO_BASE + 0x00002000)
7269 +#define RD (IO_BASE + 0x00003000)
7270 +#define RE (IO_BASE + 0x00004000)
7271 +#define RF (IO_BASE + 0x00005000)
7272 +#define RG (IO_BASE + 0x00006000)
7273 +#define RH (IO_BASE + 0x00007000)
7274 +#define RI (IO_BASE + 0x00008000)
7275 +#define RJ (IO_BASE + 0x00009000)
7276 +#define RLATCH (IO_BASE + 0x00ff0000)  // For latched output only
7277 +#define IO_PORT_BR_OFFSET 0x00000800
7278 +
7279 +/*
7280 + * General I/O Register Map (per port)
7281 + */
7282 +#define IO_FUNC 0x00
7283 +#define IO_GPIO_CTL 0x04
7284 +#define IO_GPIO_OUT 0x08
7285 +#define IO_GPIO_IN 0x0C
7286 +#define IO_INT_STATUS 0x10
7287 +#define IO_INT_MASK 0x14
7288 +#define IO_INT_SET 0x18
7289 +#define IO_INT_CLR 0x1C
7290 +#define IO_TX_FIFO 0x20
7291 +#define IO_TX_FIFO_HI 0x24
7292 +#define IO_RX_FIFO 0x28
7293 +#define IO_RX_FIFO_HI 0x2c
7294 +#define IO_CTL0 0x30
7295 +#define IO_CTL1 0x34
7296 +#define IO_CTL2 0x38
7297 +#define IO_STATUS0 0x3c
7298 +#define IO_STATUS1 0x40
7299 +#define IO_STATUS2 0x44
7300 +#define IO_FIFO_WATER 0x48
7301 +#define IO_FIFO_LEVEL 0x4c
7302 +#define IO_GPIO_MASK 0x50
7303 +
7304 +#define IO_FUNC_FUNCTION_RESET(func) ((1 << ((func) - 1)) << 4)        /* Function 0 doesn't need reset */
7305 +#define IO_FUNC_RX_FIFO (1 << 3)
7306 +#define IO_FUNC_SELECT(func) ((func) << 0)
7307 +
7308 +/*
7309 + * External interrupt pins.
7310 + */
7311 +#define EXT_INT_IO_BIT(pin) ((pin) + 5)        // Interrupt pin number -> I/O INT bit
7312 +#define EXT_INT_RISING_EDGE(pin) (0x2 << (2*(pin) + 7))
7313 +#define EXT_INT_FALLING_EDGE(pin) (0x1 << (2*(pin) + 7))
7314 +
7315 +/*
7316 + * Flash
7317 + */
7318 +#define IO_XFL_BASE RA
7319 +
7320 +#define IO_XFL_INT_START (1 << 16)
7321 +#define IO_XFL_INT_ERR (1 << 8)
7322 +#define IO_XFL_INT_DONE (1 << 0)
7323 +
7324 +#define IO_XFL_CTL0_MASK (0xffe07fff)
7325 +#define IO_XFL_CTL0_RD_CMD(cmd) (((cmd) & 0xff) << 24)
7326 +#define IO_XFL_CTL0_RD_DUMMY(n) (((n) & 0x7) << 21)
7327 +#define IO_XFL_CTL0_CLK_WIDTH(core_cycles) ((((core_cycles) + 1) & 0x7e) << 8) /* must be even number */
7328 +#define IO_XFL_CTL0_CE_WAIT(spi_cycles) (((spi_cycles) & 0x3f) << 2)
7329 +#define IO_XFL_CTL0_MCB_LOCK (1 << 1)
7330 +#define IO_XFL_CTL0_ENABLE (1 << 0)
7331 +#define IO_XFL_CTL0_FAST_VALUE(div, wait) (IO_XFL_CTL0_RD_CMD(0xb) | IO_XFL_CTL0_RD_DUMMY(1) | IO_XFL_CTL0_CLK_WIDTH(div) | IO_XFL_CTL0_CE_WAIT(wait) | IO_XFL_CTL0_ENABLE)
7332 +#define IO_XFL_CTL0_VALUE(div, wait) (IO_XFL_CTL0_RD_CMD(3) | IO_XFL_CTL0_CLK_WIDTH(div) | IO_XFL_CTL0_CE_WAIT(wait) | IO_XFL_CTL0_ENABLE)
7333 +
7334 +#define IO_XFL_CTL1_MASK (0xc0003fff)
7335 +#define IO_XFL_CTL1_FC_INST(inst) (((inst) & 0x3) << 30)
7336 +#define IO_XFL_CTL1_FC_DATA(n) (((n) & 0x3ff) << 4)
7337 +#define IO_XFL_CTL1_FC_DUMMY(n) (((n) & 0x7) << 1)
7338 +#define IO_XFL_CTL1_FC_ADDR (1 << 0)
7339 +
7340 +#define IO_XFL_CTL2_FC_CMD(cmd) (((cmd) & 0xff) << 24)
7341 +#define IO_XFL_CTL2_FC_ADDR(addr) ((addr) & 0x00ffffff)        /* Only up to 24 bits */
7342 +
7343 +#define IO_XFL_STATUS0_MCB_ACTIVE (1 << 0)
7344 +#define IO_XFL_STATUS0_IOPCS_ACTIVE (1 << 1)
7345 +
7346 +/*
7347 + * SDRAM
7348 + */
7349 +#define IO_SDRAM_DATA_BASE RG
7350 +#define IO_SDRAM_CNTL_BASE RH
7351 +
7352 +#define IO_SDRAM_CTRL0_EN_REF (1 << 0)
7353 +
7354 +/*
7355 + * Port function code (common fucntion codes for all I/O ports)
7356 + */
7357 +#define IO_PORTX_FUNC_GPIO 0x00
7358 +#define IO_PORTX_FUNC_XFL 0x01
7359 +#define IO_PORTX_FUNC_PCI 0x01
7360 +#define IO_PORTX_FUNC_SERDES 0x01
7361 +#define IO_PORTX_FUNC_GMII 0x01
7362 +#define IO_PORTX_FUNC_DDR 0x01
7363 +#define IO_PORTX_FUNC_PCIX 0x01
7364 +#define IO_PORTX_FUNC_USB2_0 0x01
7365 +#define IO_PORTX_FUNC_GPIO_INT_CLK 0x02
7366 +#define IO_PORTX_FUNC_PLIO 0x02
7367 +#define IO_PORTX_FUNC_GPIO_INT 0x03
7368 +#define IO_PORTX_FUNC_MII 0x03
7369 +
7370 +/*
7371 + * Port 0
7372 + */
7373 +#define IO_PORT0_FUNC_GPIO IO_PORTX_FUNC_GPIO
7374 +#define IO_PORT0_FUNC_XFL_INT_CLK IO_PORTX_FUNC_XFL    // Default mode after reset
7375 +#define IO_PORT0_FUNC_GPIO_INT_CLK IO_PORTX_FUNC_GPIO_INT_CLK
7376 +#define IO_PORT0_FUNC_GPIO_INT IO_PORTX_FUNC_GPIO_INT
7377 +
7378 +/*
7379 + * Port 1
7380 + */
7381 +#define IO_PORT1_FUNC_GPIO IO_PORTX_FUNC_GPIO
7382 +#define IO_PORT1_FUNC_PCI IO_PORTX_FUNC_PCI            // PCI control
7383 +#define IO_PORT1_FUNC_MII IO_PORTX_FUNC_MII            // port 4 MII extension
7384 +
7385 +/*
7386 + * Port 2
7387 + */
7388 +#define IO_PORT2_FUNC_GPIO IO_PORTX_FUNC_GPIO
7389 +#define IO_PORT2_FUNC_PCI IO_PORTX_FUNC_PCI            // PCI data I/O
7390 +#define IO_PORT2_FUNC_PLIO IO_PORTX_FUNC_PLIO          // Extended LM
7391 +
7392 +/*
7393 + * Port 3
7394 + */
7395 +#define IO_PORT3_FUNC_GPIO IO_PORTX_FUNC_GPIO
7396 +#define IO_PORT3_FUNC_SERDES IO_PORTX_FUNC_SERDES
7397 +#define IO_PORT3_FUNC_PLIO IO_PORTX_FUNC_PLIO
7398 +
7399 +/*
7400 + * Port 4
7401 + */
7402 +#define IO_PORT4_FUNC_GPIO IO_PORTX_FUNC_GPIO
7403 +#define IO_PORT4_FUNC_SERDES IO_PORTX_FUNC_SERDES
7404 +#define IO_PORT4_FUNC_PLIO IO_PORTX_FUNC_PLIO          // Extended LM
7405 +#define IO_PORT4_FUNC_MII IO_PORTX_FUNC_MII
7406 +
7407 +/*
7408 + * Port 5
7409 + */
7410 +#define IO_PORT5_FUNC_GPIO IO_PORTX_FUNC_GPIO
7411 +#define IO_PORT5_FUNC_GMII IO_PORTX_FUNC_GMII
7412 +
7413 +/*
7414 + * Port 6
7415 + */
7416 +#define IO_PORT6_FUNC_GPIO IO_PORTX_FUNC_GPIO
7417 +#define IO_PORT6_FUNC_DDR IO_PORTX_FUNC_DDR
7418 +
7419 +/*
7420 + * Port 7
7421 + */
7422 +#define IO_PORT7_FUNC_GPIO IO_PORTX_FUNC_GPIO
7423 +#define IO_PORT7_FUNC_DDR IO_PORTX_FUNC_DDR
7424 +
7425 +/*
7426 + * Port 8
7427 + */
7428 +#define IO_PORT8_FUNC_GPIO IO_PORTX_FUNC_GPIO
7429 +#define IO_PORT8_FUNC_PCIX IO_PORTX_FUNC_PCIX
7430 +#define IO_PORT8_FUNC_PLIO IO_PORTX_FUNC_PLIO          // Extended LM
7431 +#define IO_PORT8_FUNC_MII IO_PORTX_FUNC_MII            // port 4 MII extension
7432 +
7433 +/*
7434 + * Port 9
7435 + */
7436 +#define IO_PORT9_FUNC_USB2_0 IO_PORTX_FUNC_USB2_0
7437 +
7438 +/*
7439 + * FIFO
7440 + */
7441 +#define IO_PORTX_INT_FIFO_TX_RESET (1 << 31)
7442 +#define IO_PORTX_INT_FIFO_RX_RESET (1 << 30)
7443 +#define IO_PORTX_INT_FIFO_TX_UF (1 << 15)
7444 +#define IO_PORTX_INT_FIFO_TX_WM (1 << 14)
7445 +#define IO_PORTX_INT_FIFO_RX_OF (1 << 13)
7446 +#define IO_PORTX_INT_FIFO_RX_WM (1 << 12)
7447 +
7448 +#define IO_PORTX_FUNC_FIFO_TX_WM(n) ((n) << 16)
7449 +#define IO_PORTX_FUNC_FIFO_RX_WM(n) ((n) << 0)
7450 +
7451 +/*
7452 + * MII
7453 + */
7454 +#define IO_PORTX_INT_MII_TX_ERR_SEND (1 << 18)
7455 +#define IO_PORTX_INT_MII_TX_HALT (1 << 17)
7456 +#define IO_PORTX_INT_MII_TX_START (1 << 16)
7457 +#define IO_PORTX_INT_MII_THRESHOLD (1 << 8)
7458 +#define IO_PORTX_INT_MII_RX_EOP (1 << 7)
7459 +#define IO_PORTX_INT_MII_RX_SFD (1 << 6)
7460 +#define IO_PORTX_INT_MII_RX_ERR (1 << 5)
7461 +#define IO_PORTX_INT_MII_TX_EOP (1 << 4)
7462 +#define IO_PORTX_INT_MII_COL (1 << 3)
7463 +#define IO_PORTX_INT_MII_CRS (1 << 2)
7464 +#define IO_PORTX_INT_MII_ODD_NIB_ERR (1 << 1)
7465 +#define IO_PORTX_INT_MII_FALSE_CARRIER (1 << 0)
7466 +
7467 +/*
7468 + * SerDes
7469 + */
7470 +#define IO_PORTX_INT_SERDES_TXBUF_VALID (1 << 16)
7471 +#define IO_PORTX_INT_SERDES_RXERR (1 << 7)
7472 +#define IO_PORTX_INT_SERDES_RXEOP (1 << 6)
7473 +#define IO_PORTX_INT_SERDES_SYND (1 << 5)
7474 +#define IO_PORTX_INT_SERDES_TXBE (1 << 4)
7475 +#define IO_PORTX_INT_SERDES_TXEOP (1 << 3)
7476 +#define IO_PORTX_INT_SERDES_SXLP (1 << 2)
7477 +#define IO_PORTX_INT_SERDES_RXBF (1 << 1)
7478 +#define IO_PORTX_INT_SERDES_RXCRS (1 << 0)
7479 +
7480 +#ifndef __ASSEMBLY__
7481 +struct ubicom32_io_port {
7482 +       volatile u32_t function;
7483 +       volatile u32_t gpio_ctl;
7484 +       volatile u32_t gpio_out;
7485 +       volatile u32_t gpio_in;
7486 +       volatile u32_t int_status;
7487 +       volatile u32_t int_mask;
7488 +       volatile u32_t int_set;
7489 +       volatile u32_t int_clr;
7490 +       volatile u32_t tx_fifo;
7491 +       volatile u32_t tx_fifo_hi;
7492 +       volatile u32_t rx_fifo;
7493 +       volatile u32_t rx_fifo_hi;
7494 +       volatile u32_t ctl0;
7495 +       volatile u32_t ctl1;
7496 +       volatile u32_t ctl2;
7497 +       volatile u32_t status0;
7498 +       volatile u32_t status1;
7499 +       volatile u32_t status2;
7500 +       volatile u32_t fifo_watermark;
7501 +       volatile u32_t fifo_level;
7502 +       volatile u32_t gpio_mask;
7503 +};
7504 +
7505 +#define UBICOM32_IO_PORT(port) ((struct ubicom32_io_port *)((port)))
7506 +#endif
7507 +
7508 +#ifndef __ASSEMBLY__
7509 +/*
7510 + * ubicom32_set_interrupt()
7511 + */
7512 +extern inline void ubicom32_set_interrupt(u8_t interrupt)
7513 +{
7514 +       u32_t ibit = INT_BIT_MASK(interrupt);
7515 +
7516 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7517 +               asm volatile (
7518 +                       "move.4         "D(INT_SET(INT_CHIP(0, 0)))", %0\n\t"
7519 +                       :
7520 +                       : "r" (ibit)
7521 +               );
7522 +
7523 +               return;
7524 +       }
7525 +
7526 +       asm volatile (
7527 +               "move.4         "D(INT_SET(INT_CHIP(1, 0)))", %0\n\t"
7528 +               :
7529 +               : "r" (ibit)
7530 +       );
7531 +}
7532 +
7533 +/*
7534 + * ubicom32_clear_interrupt()
7535 + */
7536 +extern inline void ubicom32_clear_interrupt(u8_t interrupt)
7537 +{
7538 +       u32_t ibit = INT_BIT_MASK(interrupt);
7539 +
7540 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7541 +               asm volatile (
7542 +                       "move.4         "D(INT_CLR(INT_CHIP(0, 0)))", %0\n\t"
7543 +                       :
7544 +                       : "r" (ibit)
7545 +               );
7546 +
7547 +               return;
7548 +       }
7549 +
7550 +       asm volatile (
7551 +               "move.4         "D(INT_CLR(INT_CHIP(1, 0)))", %0\n\t"
7552 +               :
7553 +               : "r" (ibit)
7554 +       );
7555 +}
7556 +
7557 +/*
7558 + * ubicom32_enable_interrupt()
7559 + */
7560 +extern inline void ubicom32_enable_interrupt(u8_t interrupt)
7561 +{
7562 +       u32_t ibit = INT_BIT_MASK(interrupt);
7563 +
7564 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7565 +               asm volatile (
7566 +                       "or.4           "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7567 +                       :
7568 +                       : "d" (ibit)
7569 +               );
7570 +
7571 +               return;
7572 +       }
7573 +
7574 +       asm volatile (
7575 +               "or.4           "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7576 +               :
7577 +               : "d" (ibit)
7578 +       );
7579 +}
7580 +
7581 +/*
7582 + * ubicom32_disable_interrupt()
7583 + */
7584 +extern inline void ubicom32_disable_interrupt(u8_t interrupt)
7585 +{
7586 +       u32_t ibit = ~INT_BIT_MASK(interrupt);
7587 +
7588 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7589 +               asm volatile (
7590 +                       "and.4          "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7591 +                       :
7592 +                       : "d" (ibit)
7593 +               );
7594 +
7595 +               return;
7596 +       }
7597 +
7598 +       asm volatile (
7599 +               "and.4          "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7600 +               :
7601 +               : "d" (ibit)
7602 +       );
7603 +}
7604 +
7605 +/*
7606 + * ubicom32_enable_global_interrupts()
7607 + */
7608 +extern inline void ubicom32_enable_global_interrupts(void)
7609 +{
7610 +       asm volatile(
7611 +               "bset           GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7612 +       );
7613 +}
7614 +
7615 +/*
7616 + * ubicom32_disable_global_interrupts()
7617 + */
7618 +extern inline void ubicom32_disable_global_interrupts(void)
7619 +{
7620 +       asm volatile(
7621 +               "bclr           GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7622 +       );
7623 +}
7624 +
7625 +/*
7626 + * ubicom32_get_reset_reason()
7627 + */
7628 +extern inline u32_t ubicom32_get_reset_reason(void)
7629 +{
7630 +       return *(u32_t *)(GENERAL_CFG_BASE + GEN_RESET_REASON);
7631 +}
7632 +
7633 +/*
7634 + * ubicom32_read_reg()
7635 + */
7636 +extern inline u32_t ubicom32_read_reg(volatile void *reg)
7637 +{
7638 +       u32_t v;
7639 +       asm volatile (
7640 +               "move.4         %[dest], %[src] \n\t"
7641 +               : [dest] "=r" (v)
7642 +               : [src] "m" (*(u32_t *)reg)
7643 +       );
7644 +       return v;
7645 +}
7646 +
7647 +/*
7648 + * ubicom32_write_reg()
7649 + */
7650 +extern inline void ubicom32_write_reg(volatile void *reg, u32_t v)
7651 +{
7652 +       asm volatile (
7653 +               "move.4         %[dest], %[src] \n\t"
7654 +               :
7655 +               : [src] "r" (v), [dest] "m" (*(u32_t *)reg)
7656 +       );
7657 +}
7658 +
7659 +#endif /* __ASSEMBLY__ */
7660 +#endif /* _ASM_UBICOM32_IP5000_H */
7661 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ipcbuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ipcbuf.h
7662 --- linux-2.6.30.10/arch/ubicom32/include/asm/ipcbuf.h  1970-01-01 02:00:00.000000000 +0200
7663 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ipcbuf.h      2009-12-11 11:45:11.000000000 +0200
7664 @@ -0,0 +1,55 @@
7665 +/*
7666 + * arch/ubicom32/include/asm/ipcbuf.h
7667 + *   Definition of ipc64_perm struct for Ubicom32 architecture.
7668 + *
7669 + * (C) Copyright 2009, Ubicom, Inc.
7670 + *
7671 + * This file is part of the Ubicom32 Linux Kernel Port.
7672 + *
7673 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7674 + * it and/or modify it under the terms of the GNU General Public License
7675 + * as published by the Free Software Foundation, either version 2 of the
7676 + * License, or (at your option) any later version.
7677 + *
7678 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7679 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7680 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7681 + * the GNU General Public License for more details.
7682 + *
7683 + * You should have received a copy of the GNU General Public License
7684 + * along with the Ubicom32 Linux Kernel Port.  If not,
7685 + * see <http://www.gnu.org/licenses/>.
7686 + *
7687 + * Ubicom32 implementation derived from (with many thanks):
7688 + *   arch/m68knommu
7689 + *   arch/blackfin
7690 + *   arch/parisc
7691 + */
7692 +#ifndef _ASM_UBICOM32_IPCBUF_H
7693 +#define _ASM_UBICOM32_IPCBUF_H
7694 +
7695 +/*
7696 + * The user_ipc_perm structure for m68k architecture.
7697 + * Note extra padding because this structure is passed back and forth
7698 + * between kernel and user space.
7699 + *
7700 + * Pad space is left for:
7701 + * - 32-bit mode_t and seq
7702 + * - 2 miscellaneous 32-bit values
7703 + */
7704 +struct ipc64_perm
7705 +{
7706 +       __kernel_key_t          key;
7707 +       __kernel_uid32_t        uid;
7708 +       __kernel_gid32_t        gid;
7709 +       __kernel_uid32_t        cuid;
7710 +       __kernel_gid32_t        cgid;
7711 +       __kernel_mode_t         mode;
7712 +       unsigned short          __pad1;
7713 +       unsigned short          seq;
7714 +       unsigned short          __pad2;
7715 +       unsigned long           __unused1;
7716 +       unsigned long           __unused2;
7717 +};
7718 +
7719 +#endif /* _ASM_UBICOM32_IPCBUF_H */
7720 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/irqflags.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irqflags.h
7721 --- linux-2.6.30.10/arch/ubicom32/include/asm/irqflags.h        1970-01-01 02:00:00.000000000 +0200
7722 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irqflags.h    2009-12-11 11:45:11.000000000 +0200
7723 @@ -0,0 +1,96 @@
7724 +/*
7725 + * arch/ubicom32/include/asm/irqflags.h
7726 + *   Raw implementation of local IRQ functions.
7727 + *
7728 + * (C) Copyright 2009, Ubicom, Inc.
7729 + *
7730 + * This file is part of the Ubicom32 Linux Kernel Port.
7731 + *
7732 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7733 + * it and/or modify it under the terms of the GNU General Public License
7734 + * as published by the Free Software Foundation, either version 2 of the
7735 + * License, or (at your option) any later version.
7736 + *
7737 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7738 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7739 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7740 + * the GNU General Public License for more details.
7741 + *
7742 + * You should have received a copy of the GNU General Public License
7743 + * along with the Ubicom32 Linux Kernel Port.  If not,
7744 + * see <http://www.gnu.org/licenses/>.
7745 + *
7746 + * Ubicom32 implementation derived from (with many thanks):
7747 + *   arch/m68knommu
7748 + *   arch/blackfin
7749 + *   arch/parisc
7750 + */
7751 +#ifndef _ASM_UBICOM32_IRQFLAGS_H
7752 +#define _ASM_UBICOM32_IRQFLAGS_H
7753 +
7754 +#include <linux/thread_info.h>
7755 +#include <asm/ubicom32-common.h>
7756 +#if defined(CONFIG_SMP)
7757 +#include <asm/smp.h>
7758 +#endif
7759 +#include <asm/ldsr.h>
7760 +
7761 +#if defined(CONFIG_PREEMPT)
7762 +#error Not supported by Ubicom32 irq handling, yet!
7763 +#endif
7764 +
7765 +/*
7766 + * raw_local_irq_enable()
7767 + *     Enable interrupts for this thread.
7768 + */
7769 +static inline void raw_local_irq_enable(void)
7770 +{
7771 +       ldsr_local_irq_enable();
7772 +}
7773 +
7774 +/*
7775 + * raw_local_irq_disable()
7776 + *     Disable interrupts for this thread.
7777 + */
7778 +static inline void raw_local_irq_disable(void)
7779 +{
7780 +       ldsr_local_irq_disable();
7781 +}
7782 +
7783 +/*
7784 + * raw_local_save_flags()
7785 + *     Get the current IRQ state.
7786 + */
7787 +#define raw_local_save_flags(flags)            \
7788 +do {                                           \
7789 +       (flags) = ldsr_local_irq_is_disabled(); \
7790 +} while (0)
7791 +
7792 +/*
7793 + * raw_local_irq_save()
7794 + *     Save the current interrupt state and disable interrupts.
7795 + */
7796 +#define raw_local_irq_save(flags)              \
7797 +do {                                           \
7798 +       (flags) = ldsr_local_irq_save();        \
7799 +} while (0)
7800 +
7801 +/*
7802 + * raw_local_irq_restore()
7803 + *     Restore the IRQ state back to flags.
7804 + */
7805 +static inline void raw_local_irq_restore(unsigned long flags)
7806 +{
7807 +       ldsr_local_irq_restore(flags);
7808 +}
7809 +
7810 +/*
7811 + * raw_irqs_disabled_flags()
7812 + *     Return true if the flags indicate that IRQ(s) are disabled.
7813 + */
7814 +static inline int raw_irqs_disabled_flags(unsigned long flags)
7815 +{
7816 +       return (flags);
7817 +}
7818 +
7819 +#endif /* _ASM_UBICOM32_IRQFLAGS_H */
7820 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/irq.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq.h
7821 --- linux-2.6.30.10/arch/ubicom32/include/asm/irq.h     1970-01-01 02:00:00.000000000 +0200
7822 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq.h 2009-12-11 11:45:11.000000000 +0200
7823 @@ -0,0 +1,45 @@
7824 +/*
7825 + * arch/ubicom32/include/asm/irq.h
7826 + *   IRQ definitions for Ubicom32 architecture.
7827 + *
7828 + * (C) Copyright 2009, Ubicom, Inc.
7829 + *
7830 + * This file is part of the Ubicom32 Linux Kernel Port.
7831 + *
7832 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7833 + * it and/or modify it under the terms of the GNU General Public License
7834 + * as published by the Free Software Foundation, either version 2 of the
7835 + * License, or (at your option) any later version.
7836 + *
7837 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7838 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7839 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7840 + * the GNU General Public License for more details.
7841 + *
7842 + * You should have received a copy of the GNU General Public License
7843 + * along with the Ubicom32 Linux Kernel Port.  If not,
7844 + * see <http://www.gnu.org/licenses/>.
7845 + *
7846 + * Ubicom32 implementation derived from (with many thanks):
7847 + *   arch/m68knommu
7848 + *   arch/blackfin
7849 + *   arch/parisc
7850 + */
7851 +#ifndef _ASM_UBICOM32_IRQ_H
7852 +#define _ASM_UBICOM32_IRQ_H
7853 +
7854 +#include <asm/irqflags.h>
7855 +
7856 +/*
7857 + * We setup the IRQS to cover the full range of interrupt registers in
7858 + * processor.
7859 + */
7860 +#define NR_IRQS                64
7861 +
7862 +#define irq_canonicalize(irq) (irq)
7863 +
7864 +extern int irq_soft_alloc(unsigned int *soft);
7865 +extern void ack_bad_irq(unsigned int irq);
7866 +extern void do_IRQ(int irq, struct pt_regs *fp);
7867 +
7868 +#endif /* _ASM_UBICOM32_IRQ_H */
7869 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/irq_regs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq_regs.h
7870 --- linux-2.6.30.10/arch/ubicom32/include/asm/irq_regs.h        1970-01-01 02:00:00.000000000 +0200
7871 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq_regs.h    2009-12-11 11:45:11.000000000 +0200
7872 @@ -0,0 +1,33 @@
7873 +/*
7874 + * arch/ubicom32/include/asm/irq_regs.h
7875 + *   Generic irq_regs.h for Ubicom32 architecture.
7876 + *
7877 + * (C) Copyright 2009, Ubicom, Inc.
7878 + *
7879 + * This file is part of the Ubicom32 Linux Kernel Port.
7880 + *
7881 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7882 + * it and/or modify it under the terms of the GNU General Public License
7883 + * as published by the Free Software Foundation, either version 2 of the
7884 + * License, or (at your option) any later version.
7885 + *
7886 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7887 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7888 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7889 + * the GNU General Public License for more details.
7890 + *
7891 + * You should have received a copy of the GNU General Public License
7892 + * along with the Ubicom32 Linux Kernel Port.  If not,
7893 + * see <http://www.gnu.org/licenses/>.
7894 + *
7895 + * Ubicom32 implementation derived from (with many thanks):
7896 + *   arch/m68knommu
7897 + *   arch/blackfin
7898 + *   arch/parisc
7899 + */
7900 +#ifndef _ASM_UBICOM32_IRQ_REGS_H
7901 +#define _ASM_UBICOM32_IRQ_REGS_H
7902 +
7903 +#include <asm-generic/irq_regs.h>
7904 +
7905 +#endif /* _ASM_UBICOM32_IRQ_REGS_H */
7906 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/Kbuild linux-2.6.30.10-ubi/arch/ubicom32/include/asm/Kbuild
7907 --- linux-2.6.30.10/arch/ubicom32/include/asm/Kbuild    1970-01-01 02:00:00.000000000 +0200
7908 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/Kbuild        2009-12-11 11:45:11.000000000 +0200
7909 @@ -0,0 +1 @@
7910 +include include/asm-generic/Kbuild.asm
7911 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/kdebug.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kdebug.h
7912 --- linux-2.6.30.10/arch/ubicom32/include/asm/kdebug.h  1970-01-01 02:00:00.000000000 +0200
7913 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kdebug.h      2009-12-11 11:45:11.000000000 +0200
7914 @@ -0,0 +1,33 @@
7915 +/*
7916 + * arch/ubicom32/include/asm/kdebug.h
7917 + *   Generic kdebug.h for Ubicom32 architecture.
7918 + *
7919 + * (C) Copyright 2009, Ubicom, Inc.
7920 + *
7921 + * This file is part of the Ubicom32 Linux Kernel Port.
7922 + *
7923 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7924 + * it and/or modify it under the terms of the GNU General Public License
7925 + * as published by the Free Software Foundation, either version 2 of the
7926 + * License, or (at your option) any later version.
7927 + *
7928 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7929 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7930 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7931 + * the GNU General Public License for more details.
7932 + *
7933 + * You should have received a copy of the GNU General Public License
7934 + * along with the Ubicom32 Linux Kernel Port.  If not,
7935 + * see <http://www.gnu.org/licenses/>.
7936 + *
7937 + * Ubicom32 implementation derived from (with many thanks):
7938 + *   arch/m68knommu
7939 + *   arch/blackfin
7940 + *   arch/parisc
7941 + */
7942 +#ifndef _ASM_UBICOM32_KDEBUG_H
7943 +#define _ASM_UBICOM32_KDEBUG_H
7944 +
7945 +#include <asm-generic/kdebug.h>
7946 +
7947 +#endif /* _ASM_UBICOM32_KDEBUG_H */
7948 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/kmap_types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kmap_types.h
7949 --- linux-2.6.30.10/arch/ubicom32/include/asm/kmap_types.h      1970-01-01 02:00:00.000000000 +0200
7950 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kmap_types.h  2009-12-11 11:45:11.000000000 +0200
7951 @@ -0,0 +1,48 @@
7952 +/*
7953 + * arch/ubicom32/include/asm/kmap_types.h
7954 + *   Definition of km_type's for Ubicom32 architecture.
7955 + *
7956 + * (C) Copyright 2009, Ubicom, Inc.
7957 + *
7958 + * This file is part of the Ubicom32 Linux Kernel Port.
7959 + *
7960 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7961 + * it and/or modify it under the terms of the GNU General Public License
7962 + * as published by the Free Software Foundation, either version 2 of the
7963 + * License, or (at your option) any later version.
7964 + *
7965 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7966 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7967 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7968 + * the GNU General Public License for more details.
7969 + *
7970 + * You should have received a copy of the GNU General Public License
7971 + * along with the Ubicom32 Linux Kernel Port.  If not,
7972 + * see <http://www.gnu.org/licenses/>.
7973 + *
7974 + * Ubicom32 implementation derived from (with many thanks):
7975 + *   arch/m68knommu
7976 + *   arch/blackfin
7977 + *   arch/parisc
7978 + */
7979 +#ifndef _ASM_UBICOM32_KMAP_TYPES_H
7980 +#define _ASM_UBICOM32_KMAP_TYPES_H
7981 +
7982 +enum km_type {
7983 +       KM_BOUNCE_READ,
7984 +       KM_SKB_SUNRPC_DATA,
7985 +       KM_SKB_DATA_SOFTIRQ,
7986 +       KM_USER0,
7987 +       KM_USER1,
7988 +       KM_BIO_SRC_IRQ,
7989 +       KM_BIO_DST_IRQ,
7990 +       KM_PTE0,
7991 +       KM_PTE1,
7992 +       KM_IRQ0,
7993 +       KM_IRQ1,
7994 +       KM_SOFTIRQ0,
7995 +       KM_SOFTIRQ1,
7996 +       KM_TYPE_NR
7997 +};
7998 +
7999 +#endif /* _ASM_UBICOM32_KMAP_TYPES_H */
8000 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ldsr.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ldsr.h
8001 --- linux-2.6.30.10/arch/ubicom32/include/asm/ldsr.h    1970-01-01 02:00:00.000000000 +0200
8002 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ldsr.h        2009-12-11 11:45:11.000000000 +0200
8003 @@ -0,0 +1,186 @@
8004 +/*
8005 + * arch/ubicom32/include/asm/ldsr.h
8006 + *   Ubicom32 LDSR interface definitions.
8007 + *
8008 + * (C) Copyright 2009, Ubicom, Inc.
8009 + *
8010 + * This file is part of the Ubicom32 Linux Kernel Port.
8011 + *
8012 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8013 + * it and/or modify it under the terms of the GNU General Public License
8014 + * as published by the Free Software Foundation, either version 2 of the
8015 + * License, or (at your option) any later version.
8016 + *
8017 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8018 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8019 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8020 + * the GNU General Public License for more details.
8021 + *
8022 + * You should have received a copy of the GNU General Public License
8023 + * along with the Ubicom32 Linux Kernel Port.  If not,
8024 + * see <http://www.gnu.org/licenses/>.
8025 + *
8026 + * Ubicom32 implementation derived from (with many thanks):
8027 + *   arch/m68knommu
8028 + *   arch/blackfin
8029 + *   arch/parisc
8030 + */
8031 +#ifndef _ASM_UBICOM32_LDSR_H
8032 +#define _ASM_UBICOM32_LDSR_H
8033 +
8034 +#include <asm/ubicom32-common.h>
8035 +#include <asm/types.h>
8036 +#include <asm/thread.h>
8037 +
8038 +extern unsigned int ldsr_soft_irq_mask;
8039 +
8040 +/*
8041 + * ldsr_local_irq_is_disabled()
8042 + *     Test if interrupts are disabled for this thread?
8043 + */
8044 +static inline int ldsr_local_irq_is_disabled(void)
8045 +{
8046 +       int ret;
8047 +       thread_t self = thread_get_self();
8048 +       unsigned int mask = (1 << self);
8049 +
8050 +       asm volatile (
8051 +       "       and.4   %0, scratchpad1, %1     \n\t"
8052 +               : "=r" (ret)
8053 +               : "d" (mask)
8054 +               : "cc"
8055 +       );
8056 +
8057 +       /*
8058 +        *  We return a simple 1 == disabled, 0 == enabled
8059 +        *  losing which tid this is for, because Linux
8060 +        *  can restore interrupts on a different thread.
8061 +        */
8062 +       return ret >> self;
8063 +}
8064 +
8065 +/*
8066 + * ldsr_local_irq_save()
8067 + *     Get the current interrupt state and disable interrupts.
8068 + */
8069 +static inline unsigned int ldsr_local_irq_save(void)
8070 +{
8071 +       int ret;
8072 +       thread_t self = thread_get_self();
8073 +       unsigned int mask = (1 << self);
8074 +
8075 +       /*
8076 +        * Ensure the compiler can not optimize out the code
8077 +        * (volatile) and that it does not "cache" values around
8078 +        * the interrupt state change (memory).  This ensures
8079 +        * that interrupt changes are treated as a critical
8080 +        * section.
8081 +        */
8082 +       asm volatile (
8083 +       "       and.4   %0, scratchpad1, %1             \n\t"
8084 +       "       or.4    scratchpad1, scratchpad1, %1    \n\t"
8085 +               : "=&r" (ret)
8086 +               : "d" (mask)
8087 +               : "cc", "memory"
8088 +       );
8089 +
8090 +       /*
8091 +        *  We return a simple 1 == disabled, 0 == enabled
8092 +        *  losing which tid this is for, because Linux
8093 +        *  can restore interrupts on a different thread.
8094 +        */
8095 +       return ret >> self;
8096 +}
8097 +
8098 +/*
8099 + * ldsr_local_irq_restore()
8100 + *     Restore this cpu's interrupt enable/disable state.
8101 + *
8102 + * Note: flags is either 0 or 1.
8103 + */
8104 +static inline void ldsr_local_irq_restore(unsigned int flags)
8105 +{
8106 +       unsigned int temp;
8107 +       thread_t self = thread_get_self();
8108 +       unsigned int mask = (1 << self);
8109 +       flags = (flags << self);
8110 +
8111 +       /*
8112 +        * Ensure the compiler can not optimize out the code
8113 +        * (volatile) and that it does not "cache" values around
8114 +        * the interrupt state change (memory).  This ensures
8115 +        * that interrupt changes are treated as a critical
8116 +        * section.
8117 +        *
8118 +        * Atomic change to our bit in scratchpad1 without
8119 +        * causing any temporary glitch in the value and
8120 +        * without effecting other values.  Also this uses
8121 +        * no branches so no penalties.
8122 +        */
8123 +       asm volatile (
8124 +       "       xor.4   %0, scratchpad1, %1             \n\t"
8125 +       "       and.4   %0, %2, %0                      \n\t"
8126 +       "       xor.4   scratchpad1, scratchpad1, %0    \n\t"
8127 +       "       move.4  int_set0, %3                    \n\t"
8128 +               : "=&d"(temp)
8129 +               : "d"(flags), "r"(mask), "r"(ldsr_soft_irq_mask)
8130 +               : "cc", "memory"
8131 +       );
8132 +}
8133 +
8134 +/*
8135 + * ldsr_local_irq_disable_interrupt()
8136 + *     Disable ints for this thread.
8137 + */
8138 +static inline void ldsr_local_irq_disable(void)
8139 +{
8140 +       unsigned int mask = (1 << thread_get_self());
8141 +
8142 +       /*
8143 +        * Ensure the compiler can not optimize out the code
8144 +        * (volatile) and that it does not "cache" values around
8145 +        * the interrupt state change (memory).  This ensures
8146 +        * that interrupt changes are treated as a critical
8147 +        * section.
8148 +        */
8149 +       asm  volatile (
8150 +       "       or.4    scratchpad1, scratchpad1, %0    \n\t"
8151 +               :
8152 +               : "d" (mask)
8153 +               : "cc", "memory"
8154 +       );
8155 +}
8156 +
8157 +/*
8158 + * ldsr_local_irq_enable_interrupt
8159 + *     Enable ints for this thread.
8160 + */
8161 +static inline void ldsr_local_irq_enable(void)
8162 +{
8163 +       unsigned int mask = (1 << thread_get_self());
8164 +
8165 +       /*
8166 +        * Ensure the compiler can not optimize out the code
8167 +        * (volatile) and that it does not "cache" values around
8168 +        * the interrupt state change (memory).  This ensures
8169 +        * that interrupt changes are treated as a critical
8170 +        * section.
8171 +        */
8172 +       asm volatile (
8173 +       "       and.4   scratchpad1, scratchpad1, %0    \n\t"
8174 +       "       move.4  int_set0, %1                    \n\t"
8175 +               :
8176 +               : "d" (~mask), "r" (ldsr_soft_irq_mask)
8177 +               : "cc", "memory"
8178 +       );
8179 +}
8180 +
8181 +extern void ldsr_init(void);
8182 +extern void ldsr_set_trap_irq(unsigned int irq);
8183 +extern void ldsr_mask_vector(unsigned int vector);
8184 +extern void ldsr_unmask_vector(unsigned int vector);
8185 +extern void ldsr_enable_vector(unsigned int vector);
8186 +extern void ldsr_disable_vector(unsigned int vector);
8187 +extern thread_t ldsr_get_threadid(void);
8188 +
8189 +#endif /* _ASM_UBICOM32_LDSR_H */
8190 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/linkage.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/linkage.h
8191 --- linux-2.6.30.10/arch/ubicom32/include/asm/linkage.h 1970-01-01 02:00:00.000000000 +0200
8192 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/linkage.h     2009-12-11 11:45:11.000000000 +0200
8193 @@ -0,0 +1,34 @@
8194 +/*
8195 + * arch/ubicom32/include/asm/linkage.h
8196 + *   Definition of Ubicom32 architecture specific linkage types.
8197 + *
8198 + * (C) Copyright 2009, Ubicom, Inc.
8199 + *
8200 + * This file is part of the Ubicom32 Linux Kernel Port.
8201 + *
8202 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8203 + * it and/or modify it under the terms of the GNU General Public License
8204 + * as published by the Free Software Foundation, either version 2 of the
8205 + * License, or (at your option) any later version.
8206 + *
8207 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8208 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8209 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8210 + * the GNU General Public License for more details.
8211 + *
8212 + * You should have received a copy of the GNU General Public License
8213 + * along with the Ubicom32 Linux Kernel Port.  If not,
8214 + * see <http://www.gnu.org/licenses/>.
8215 + *
8216 + * Ubicom32 implementation derived from (with many thanks):
8217 + *   arch/m68knommu
8218 + *   arch/blackfin
8219 + *   arch/parisc
8220 + */
8221 +#ifndef _ASM_UBICOM32_LINKAGE_H
8222 +#define _ASM_UBICOM32_LINKAGE_H
8223 +
8224 +#define __ocm_text __section(.ocm_text)
8225 +#define __ocm_data __section(.ocm_data)
8226 +
8227 +#endif /* _ASM_UBICOM32_LINKAGE_H */
8228 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/local.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/local.h
8229 --- linux-2.6.30.10/arch/ubicom32/include/asm/local.h   1970-01-01 02:00:00.000000000 +0200
8230 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/local.h       2009-12-11 11:45:11.000000000 +0200
8231 @@ -0,0 +1,33 @@
8232 +/*
8233 + * arch/ubicom32/include/asm/local.h
8234 + *   Generic local.h for Ubicom32 architecture.
8235 + *
8236 + * (C) Copyright 2009, Ubicom, Inc.
8237 + *
8238 + * This file is part of the Ubicom32 Linux Kernel Port.
8239 + *
8240 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8241 + * it and/or modify it under the terms of the GNU General Public License
8242 + * as published by the Free Software Foundation, either version 2 of the
8243 + * License, or (at your option) any later version.
8244 + *
8245 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8246 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8247 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8248 + * the GNU General Public License for more details.
8249 + *
8250 + * You should have received a copy of the GNU General Public License
8251 + * along with the Ubicom32 Linux Kernel Port.  If not,
8252 + * see <http://www.gnu.org/licenses/>.
8253 + *
8254 + * Ubicom32 implementation derived from (with many thanks):
8255 + *   arch/m68knommu
8256 + *   arch/blackfin
8257 + *   arch/parisc
8258 + */
8259 +#ifndef _ASM_UBICOM32_LOCAL_H
8260 +#define _ASM_UBICOM32_LOCAL_H
8261 +
8262 +#include <asm-generic/local.h>
8263 +
8264 +#endif /* _ASM_UBICOM32_LOCAL_H */
8265 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/machdep.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/machdep.h
8266 --- linux-2.6.30.10/arch/ubicom32/include/asm/machdep.h 1970-01-01 02:00:00.000000000 +0200
8267 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/machdep.h     2009-12-11 11:45:11.000000000 +0200
8268 @@ -0,0 +1,43 @@
8269 +/*
8270 + * arch/ubicom32/include/asm/machdep.h
8271 + *   Machine dependent utility routines.
8272 + *
8273 + * (C) Copyright 2009, Ubicom, Inc.
8274 + *
8275 + * This file is part of the Ubicom32 Linux Kernel Port.
8276 + *
8277 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8278 + * it and/or modify it under the terms of the GNU General Public License
8279 + * as published by the Free Software Foundation, either version 2 of the
8280 + * License, or (at your option) any later version.
8281 + *
8282 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8283 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8284 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8285 + * the GNU General Public License for more details.
8286 + *
8287 + * You should have received a copy of the GNU General Public License
8288 + * along with the Ubicom32 Linux Kernel Port.  If not,
8289 + * see <http://www.gnu.org/licenses/>.
8290 + *
8291 + * Ubicom32 implementation derived from (with many thanks):
8292 + *   arch/m68knommu
8293 + *   arch/blackfin
8294 + *   arch/parisc
8295 + */
8296 +#ifndef _ASM_UBICOM32_MACHDEP_H
8297 +#define _ASM_UBICOM32_MACHDEP_H
8298 +
8299 +#include <linux/interrupt.h>
8300 +
8301 +/* Hardware clock functions */
8302 +extern unsigned long hw_timer_offset(void);
8303 +
8304 +/* machine dependent power off functions */
8305 +extern void (*mach_reset)(void);
8306 +extern void (*mach_halt)(void);
8307 +extern void (*mach_power_off)(void);
8308 +
8309 +extern void config_BSP(char *command, int len);
8310 +
8311 +#endif /* _ASM_UBICOM32_MACHDEP_H */
8312 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mc146818rtc.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mc146818rtc.h
8313 --- linux-2.6.30.10/arch/ubicom32/include/asm/mc146818rtc.h     1970-01-01 02:00:00.000000000 +0200
8314 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mc146818rtc.h 2009-12-11 11:45:11.000000000 +0200
8315 @@ -0,0 +1,36 @@
8316 +/*
8317 + * arch/ubicom32/include/asm/mc146818rtc.h
8318 + *   Generic mc146818rtc.h for Ubicom32 architecture.
8319 + *
8320 + * (C) Copyright 2009, Ubicom, Inc.
8321 + *
8322 + * This file is part of the Ubicom32 Linux Kernel Port.
8323 + *
8324 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8325 + * it and/or modify it under the terms of the GNU General Public License
8326 + * as published by the Free Software Foundation, either version 2 of the
8327 + * License, or (at your option) any later version.
8328 + *
8329 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8330 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8331 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8332 + * the GNU General Public License for more details.
8333 + *
8334 + * You should have received a copy of the GNU General Public License
8335 + * along with the Ubicom32 Linux Kernel Port.  If not,
8336 + * see <http://www.gnu.org/licenses/>.
8337 + *
8338 + * Ubicom32 implementation derived from (with many thanks):
8339 + *   arch/m68knommu
8340 + *   arch/blackfin
8341 + *   arch/parisc
8342 + */
8343 +/*
8344 + * Machine dependent access functions for RTC registers.
8345 + */
8346 +#ifndef _ASM_UBICOM32_MC146818RTC_H
8347 +#define _ASM_UBICOM32_MC146818RTC_H
8348 +
8349 +/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
8350 +
8351 +#endif /* _ASM_UBICOM32_MC146818RTC_H */
8352 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/memory_map.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/memory_map.h
8353 --- linux-2.6.30.10/arch/ubicom32/include/asm/memory_map.h      1970-01-01 02:00:00.000000000 +0200
8354 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/memory_map.h  2009-12-11 11:45:11.000000000 +0200
8355 @@ -0,0 +1,66 @@
8356 +/*
8357 + * arch/ubicom32/include/asm/memory_map.h
8358 + *   Machine memory maps/
8359 + *
8360 + * (C) Copyright 2009, Ubicom, Inc.
8361 + *
8362 + * This file is part of the Ubicom32 Linux Kernel Port.
8363 + *
8364 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8365 + * it and/or modify it under the terms of the GNU General Public License
8366 + * as published by the Free Software Foundation, either version 2 of the
8367 + * License, or (at your option) any later version.
8368 + *
8369 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8370 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8371 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8372 + * the GNU General Public License for more details.
8373 + *
8374 + * You should have received a copy of the GNU General Public License
8375 + * along with the Ubicom32 Linux Kernel Port.  If not,
8376 + * see <http://www.gnu.org/licenses/>.
8377 + *
8378 + * Ubicom32 implementation derived from (with many thanks):
8379 + *   arch/m68knommu
8380 + *   arch/blackfin
8381 + *   arch/parisc
8382 + */
8383 +#ifndef _ASM_UBICOM32_MEMORY_MAP_H
8384 +#define _ASM_UBICOM32_MEMORY_MAP_H
8385 +
8386 +/*
8387 + * Memory Size
8388 + */
8389 +#define OCM_SECTOR_SIZE        0x00008000              /* 32K */
8390 +
8391 +#if defined(CONFIG_UBICOM32_V3)
8392 +#define OCMSIZE        0x00030000      /* 192K on-chip RAM for both program and data */
8393 +#elif defined(CONFIG_UBICOM32_V4)
8394 +#define OCMSIZE        0x0003C000      /* 240K on-chip RAM for both program and data */
8395 +#else
8396 +#error "Unknown IP5K silicon"
8397 +#endif
8398 +
8399 +#define OCMSTART       0x3ffc0000 /* alias from 0x03000000 for easy
8400 +                                   * jump to/from SDRAM */
8401 +#define OCMEND         (OCMSTART + OCMSIZE)
8402 +
8403 +#define SDRAMSTART     0x40000000
8404 +
8405 +#define KERNELSTART    (SDRAMSTART + 0x00400000)
8406 +
8407 +#define FLASHSTART     0x60000000
8408 +
8409 +/*
8410 + * CODELOADER / OS_SYSCALL OCM Reservations
8411 + * Don't change these unless you know what you are doing.
8412 + */
8413 +#define CODELOADER_SIZE  0x30
8414 +#define CODELOADER_BEGIN OCMSTART /* Must be OCM start for gdb to work. */
8415 +#define CODELOADER_END  (CODELOADER_BEGIN + CODELOADER_SIZE)
8416 +
8417 +#define OS_SYSCALL_BEGIN CODELOADER_END        /* system_call at this address */
8418 +#define OS_SYSCALL_SIZE  (512 - CODELOADER_SIZE)
8419 +#define OS_SYSCALL_END  (OS_SYSCALL_BEGIN + OS_SYSCALL_SIZE)
8420 +
8421 +#endif /* _ASM_UBICOM32_MEMORY_MAP_H */
8422 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mman.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mman.h
8423 --- linux-2.6.30.10/arch/ubicom32/include/asm/mman.h    1970-01-01 02:00:00.000000000 +0200
8424 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mman.h        2009-12-11 11:45:11.000000000 +0200
8425 @@ -0,0 +1,44 @@
8426 +/*
8427 + * arch/ubicom32/include/asm/mman.h
8428 + *   Memory mapping definitions for Ubicom32 architecture.
8429 + *
8430 + * (C) Copyright 2009, Ubicom, Inc.
8431 + *
8432 + * This file is part of the Ubicom32 Linux Kernel Port.
8433 + *
8434 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8435 + * it and/or modify it under the terms of the GNU General Public License
8436 + * as published by the Free Software Foundation, either version 2 of the
8437 + * License, or (at your option) any later version.
8438 + *
8439 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8440 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8441 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8442 + * the GNU General Public License for more details.
8443 + *
8444 + * You should have received a copy of the GNU General Public License
8445 + * along with the Ubicom32 Linux Kernel Port.  If not,
8446 + * see <http://www.gnu.org/licenses/>.
8447 + *
8448 + * Ubicom32 implementation derived from (with many thanks):
8449 + *   arch/m68knommu
8450 + *   arch/blackfin
8451 + *   arch/parisc
8452 + */
8453 +#ifndef _ASM_UBICOM32_MMAN_H
8454 +#define _ASM_UBICOM32_MMAN_H
8455 +
8456 +#include <asm-generic/mman.h>
8457 +
8458 +#define MAP_GROWSDOWN  0x0100          /* stack-like segment */
8459 +#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
8460 +#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
8461 +#define MAP_LOCKED     0x2000          /* pages are locked */
8462 +#define MAP_NORESERVE  0x4000          /* don't check for reservations */
8463 +#define MAP_POPULATE   0x8000          /* populate (prefault) pagetables */
8464 +#define MAP_NONBLOCK   0x10000         /* do not block on IO */
8465 +
8466 +#define MCL_CURRENT    1               /* lock all current mappings */
8467 +#define MCL_FUTURE     2               /* lock all future mappings */
8468 +
8469 +#endif /* _ASM_UBICOM32_MMAN_H */
8470 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mmu_context.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu_context.h
8471 --- linux-2.6.30.10/arch/ubicom32/include/asm/mmu_context.h     1970-01-01 02:00:00.000000000 +0200
8472 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu_context.h 2009-12-11 11:45:11.000000000 +0200
8473 @@ -0,0 +1,60 @@
8474 +/*
8475 + * arch/ubicom32/include/asm/mmu_context.h
8476 + *   MMU context definitions for Ubicom32 architecture.
8477 + *
8478 + * (C) Copyright 2009, Ubicom, Inc.
8479 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
8480 + *
8481 + * This file is part of the Ubicom32 Linux Kernel Port.
8482 + *
8483 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8484 + * it and/or modify it under the terms of the GNU General Public License
8485 + * as published by the Free Software Foundation, either version 2 of the
8486 + * License, or (at your option) any later version.
8487 + *
8488 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8489 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8490 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8491 + * the GNU General Public License for more details.
8492 + *
8493 + * You should have received a copy of the GNU General Public License
8494 + * along with the Ubicom32 Linux Kernel Port.  If not,
8495 + * see <http://www.gnu.org/licenses/>.
8496 + *
8497 + * Ubicom32 implementation derived from (with many thanks):
8498 + *   arch/m68knommu
8499 + *   arch/blackfin
8500 + *   arch/parisc
8501 + */
8502 +
8503 +#ifndef _ASM_UBICOM32_MMU_CONTEXT_H
8504 +#define _ASM_UBICOM32_MMU_CONTEXT_H
8505 +
8506 +#include <asm/setup.h>
8507 +#include <asm/page.h>
8508 +#include <asm/pgalloc.h>
8509 +
8510 +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
8511 +{
8512 +}
8513 +
8514 +extern inline int
8515 +init_new_context(struct task_struct *tsk, struct mm_struct *mm)
8516 +{
8517 +       // mm->context = virt_to_phys(mm->pgd);
8518 +       return(0);
8519 +}
8520 +
8521 +#define destroy_context(mm)            do { } while(0)
8522 +
8523 +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
8524 +{
8525 +}
8526 +
8527 +#define deactivate_mm(tsk,mm)  do { } while (0)
8528 +
8529 +extern inline void activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm)
8530 +{
8531 +}
8532 +
8533 +#endif /* _ASM_UBICOM32_MMU_CONTEXT_H */
8534 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mmu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu.h
8535 --- linux-2.6.30.10/arch/ubicom32/include/asm/mmu.h     1970-01-01 02:00:00.000000000 +0200
8536 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu.h 2009-12-11 11:45:11.000000000 +0200
8537 @@ -0,0 +1,41 @@
8538 +/*
8539 + * arch/ubicom32/include/asm/mmu.h
8540 + *   Definition of mm_context_t struct for Ubicom32 architecture.
8541 + *
8542 + * (C) Copyright 2009, Ubicom, Inc.
8543 + * Copyright (C) 2002, David McCullough <davidm@snapgear.com>
8544 + *
8545 + * This file is part of the Ubicom32 Linux Kernel Port.
8546 + *
8547 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8548 + * it and/or modify it under the terms of the GNU General Public License
8549 + * as published by the Free Software Foundation, either version 2 of the
8550 + * License, or (at your option) any later version.
8551 + *
8552 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8553 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8554 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8555 + * the GNU General Public License for more details.
8556 + *
8557 + * You should have received a copy of the GNU General Public License
8558 + * along with the Ubicom32 Linux Kernel Port.  If not,
8559 + * see <http://www.gnu.org/licenses/>.
8560 + *
8561 + * Ubicom32 implementation derived from (with many thanks):
8562 + *   arch/m68knommu
8563 + *   arch/blackfin
8564 + *   arch/parisc
8565 + */
8566 +#ifndef _ASM_UBICOM32_MMU_H
8567 +#define _ASM_UBICOM32_MMU_H
8568 +
8569 +typedef struct {
8570 +       struct vm_list_struct   *vmlist;
8571 +       unsigned long           end_brk;
8572 +#ifdef CONFIG_BINFMT_ELF_FDPIC
8573 +       unsigned long   exec_fdpic_loadmap;
8574 +       unsigned long   interp_fdpic_loadmap;
8575 +#endif
8576 +} mm_context_t;
8577 +
8578 +#endif /* _ASM_UBICOM32_MMU_H */
8579 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/module.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/module.h
8580 --- linux-2.6.30.10/arch/ubicom32/include/asm/module.h  1970-01-01 02:00:00.000000000 +0200
8581 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/module.h      2009-12-11 11:45:11.000000000 +0200
8582 @@ -0,0 +1,48 @@
8583 +/*
8584 + * arch/ubicom32/include/asm/module.h
8585 + *   Ubicom32 architecture specific module definitions.
8586 + *
8587 + * (C) Copyright 2009, Ubicom, Inc.
8588 + *
8589 + * This file is part of the Ubicom32 Linux Kernel Port.
8590 + *
8591 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8592 + * it and/or modify it under the terms of the GNU General Public License
8593 + * as published by the Free Software Foundation, either version 2 of the
8594 + * License, or (at your option) any later version.
8595 + *
8596 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8597 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8598 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8599 + * the GNU General Public License for more details.
8600 + *
8601 + * You should have received a copy of the GNU General Public License
8602 + * along with the Ubicom32 Linux Kernel Port.  If not,
8603 + * see <http://www.gnu.org/licenses/>.
8604 + *
8605 + * Ubicom32 implementation derived from (with many thanks):
8606 + *   arch/m68knommu
8607 + *   arch/blackfin
8608 + *   arch/parisc
8609 + */
8610 +#ifndef _ASM_UBICOM32_MODULE_H
8611 +#define _ASM_UBICOM32_MODULE_H
8612 +
8613 +struct mod_arch_specific {
8614 +       void *ocm_inst;
8615 +       int ocm_inst_size;
8616 +};
8617 +
8618 +#define Elf_Shdr Elf32_Shdr
8619 +#define Elf_Sym Elf32_Sym
8620 +#define Elf_Ehdr Elf32_Ehdr
8621 +
8622 +#define ARCH_PROC_MODULES_EXTRA(m,mod) \
8623 +       seq_printf(m, " OCM(%d bytes @ 0x%p)", \
8624 +                  (mod)->arch.ocm_inst_size, (mod)->arch.ocm_inst)
8625 +
8626 +#define ARCH_OOPS_MODULE_EXTRA(mod) \
8627 +       printk(KERN_INFO "%p %u OCM(%p %u)\n", \
8628 +               (mod)->module_core, (mod)->core_size, \
8629 +               (mod)->arch.ocm_inst, (mod)->arch.ocm_inst_size)
8630 +#endif /* _ASM_UBICOM32_MODULE_H */
8631 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/msgbuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/msgbuf.h
8632 --- linux-2.6.30.10/arch/ubicom32/include/asm/msgbuf.h  1970-01-01 02:00:00.000000000 +0200
8633 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/msgbuf.h      2009-12-11 11:45:11.000000000 +0200
8634 @@ -0,0 +1,58 @@
8635 +/*
8636 + * arch/ubicom32/include/asm/msgbuf.h
8637 + *   Definition of msqid64_ds struct for Ubicom32 architecture.
8638 + *
8639 + * (C) Copyright 2009, Ubicom, Inc.
8640 + *
8641 + * This file is part of the Ubicom32 Linux Kernel Port.
8642 + *
8643 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8644 + * it and/or modify it under the terms of the GNU General Public License
8645 + * as published by the Free Software Foundation, either version 2 of the
8646 + * License, or (at your option) any later version.
8647 + *
8648 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8649 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8650 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8651 + * the GNU General Public License for more details.
8652 + *
8653 + * You should have received a copy of the GNU General Public License
8654 + * along with the Ubicom32 Linux Kernel Port.  If not,
8655 + * see <http://www.gnu.org/licenses/>.
8656 + *
8657 + * Ubicom32 implementation derived from (with many thanks):
8658 + *   arch/m68knommu
8659 + *   arch/blackfin
8660 + *   arch/parisc
8661 + */
8662 +#ifndef _ASM_UBICOM32_MSGBUF_H
8663 +#define _ASM_UBICOM32_MSGBUF_H
8664 +
8665 +/*
8666 + * The msqid64_ds structure for ubicom32 architecture.
8667 + * Note extra padding because this structure is passed back and forth
8668 + * between kernel and user space.
8669 + *
8670 + * Pad space is left for:
8671 + * - 64-bit time_t to solve y2038 problem
8672 + * - 2 miscellaneous 32-bit values
8673 + */
8674 +
8675 +struct msqid64_ds {
8676 +       struct ipc64_perm msg_perm;
8677 +       __kernel_time_t msg_stime;      /* last msgsnd time */
8678 +       unsigned long   __unused1;
8679 +       __kernel_time_t msg_rtime;      /* last msgrcv time */
8680 +       unsigned long   __unused2;
8681 +       __kernel_time_t msg_ctime;      /* last change time */
8682 +       unsigned long   __unused3;
8683 +       unsigned long  msg_cbytes;      /* current number of bytes on queue */
8684 +       unsigned long  msg_qnum;        /* number of messages in queue */
8685 +       unsigned long  msg_qbytes;      /* max number of bytes on queue */
8686 +       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
8687 +       __kernel_pid_t msg_lrpid;       /* last receive pid */
8688 +       unsigned long  __unused4;
8689 +       unsigned long  __unused5;
8690 +};
8691 +
8692 +#endif /* _ASM_UBICOM32_MSGBUF_H */
8693 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mutex.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mutex.h
8694 --- linux-2.6.30.10/arch/ubicom32/include/asm/mutex.h   1970-01-01 02:00:00.000000000 +0200
8695 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mutex.h       2009-12-11 11:45:11.000000000 +0200
8696 @@ -0,0 +1,41 @@
8697 +/*
8698 + * arch/ubicom32/include/asm/mutex.h
8699 + *   Generic mutex.h for Ubicom32 architecture.
8700 + *
8701 + * (C) Copyright 2009, Ubicom, Inc.
8702 + *
8703 + * This file is part of the Ubicom32 Linux Kernel Port.
8704 + *
8705 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8706 + * it and/or modify it under the terms of the GNU General Public License
8707 + * as published by the Free Software Foundation, either version 2 of the
8708 + * License, or (at your option) any later version.
8709 + *
8710 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8711 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8712 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8713 + * the GNU General Public License for more details.
8714 + *
8715 + * You should have received a copy of the GNU General Public License
8716 + * along with the Ubicom32 Linux Kernel Port.  If not,
8717 + * see <http://www.gnu.org/licenses/>.
8718 + *
8719 + * Ubicom32 implementation derived from (with many thanks):
8720 + *   arch/m68knommu
8721 + *   arch/blackfin
8722 + *   arch/parisc
8723 + */
8724 +/*
8725 + * Pull in the generic implementation for the mutex fastpath.
8726 + *
8727 + * TODO: implement optimized primitives instead, or leave the generic
8728 + * implementation in place, or pick the atomic_xchg() based generic
8729 + * implementation. (see asm-generic/mutex-xchg.h for details)
8730 + */
8731 +
8732 +#ifndef _ASM_UBICOM32_MUTEX_H
8733 +#define _ASM_UBICOM32_MUTEX_H
8734 +
8735 +#include <asm-generic/mutex-dec.h>
8736 +
8737 +#endif /* _ASM_UBICOM32_MUTEX_H */
8738 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/namei.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/namei.h
8739 --- linux-2.6.30.10/arch/ubicom32/include/asm/namei.h   1970-01-01 02:00:00.000000000 +0200
8740 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/namei.h       2009-12-11 11:45:11.000000000 +0200
8741 @@ -0,0 +1,38 @@
8742 +/*
8743 + * arch/ubicom32/include/asm/namei.h
8744 + *   Definition of __emul_prefix() for Ubicom32 architecture.
8745 + *
8746 + * (C) Copyright 2009, Ubicom, Inc.
8747 + *
8748 + * This file is part of the Ubicom32 Linux Kernel Port.
8749 + *
8750 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8751 + * it and/or modify it under the terms of the GNU General Public License
8752 + * as published by the Free Software Foundation, either version 2 of the
8753 + * License, or (at your option) any later version.
8754 + *
8755 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8756 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8757 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8758 + * the GNU General Public License for more details.
8759 + *
8760 + * You should have received a copy of the GNU General Public License
8761 + * along with the Ubicom32 Linux Kernel Port.  If not,
8762 + * see <http://www.gnu.org/licenses/>.
8763 + *
8764 + * Ubicom32 implementation derived from (with many thanks):
8765 + *   arch/m68knommu
8766 + *   arch/blackfin
8767 + *   arch/parisc
8768 + */
8769 +#ifndef _ASM_UBICOM32_NAMEI_H
8770 +#define _ASM_UBICOM32_NAMEI_H
8771 +
8772 +/* This dummy routine maybe changed to something useful
8773 + * for /usr/gnemul/ emulation stuff.
8774 + * Look at asm-sparc/namei.h for details.
8775 + */
8776 +
8777 +#define __emul_prefix() NULL
8778 +
8779 +#endif /* _ASM_UBICOM32_NAMEI_H */
8780 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ocm-alloc.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm-alloc.h
8781 --- linux-2.6.30.10/arch/ubicom32/include/asm/ocm-alloc.h       1970-01-01 02:00:00.000000000 +0200
8782 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm-alloc.h   2009-12-11 11:45:11.000000000 +0200
8783 @@ -0,0 +1,36 @@
8784 +/*
8785 + * arch/ubicom32/include/asm/ocm-alloc.h
8786 + *   Ubicom32 architecture specific ocm definitions.
8787 + *
8788 + * (C) Copyright 2009, Ubicom, Inc.
8789 + *
8790 + * This file is part of the Ubicom32 Linux Kernel Port.
8791 + *
8792 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8793 + * it and/or modify it under the terms of the GNU General Public License
8794 + * as published by the Free Software Foundation, either version 2 of the
8795 + * License, or (at your option) any later version.
8796 + *
8797 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8798 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8799 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8800 + * the GNU General Public License for more details.
8801 + *
8802 + * You should have received a copy of the GNU General Public License
8803 + * along with the Ubicom32 Linux Kernel Port.  If not,
8804 + * see <http://www.gnu.org/licenses/>.
8805 + *
8806 + * Ubicom32 implementation derived from (with many thanks):
8807 + *   arch/m68knommu
8808 + *   arch/blackfin
8809 + *   arch/parisc
8810 + */
8811 +#ifndef _ASM_UBICOM32_OCM_ALLOC_H
8812 +#define _ASM_UBICOM32_OCM_ALLOC_H
8813 +
8814 +
8815 +extern void *ocm_inst_alloc(size_t size, pid_t pid);
8816 +extern int ocm_free(const void *ptr);
8817 +extern int ocm_inst_free(const void *ptr);
8818 +
8819 +#endif /* _ASM_UBICOM32_OCM_ALLOC_H */
8820 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ocm_size.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_size.h
8821 --- linux-2.6.30.10/arch/ubicom32/include/asm/ocm_size.h        1970-01-01 02:00:00.000000000 +0200
8822 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_size.h    2009-12-14 14:30:27.000000000 +0200
8823 @@ -0,0 +1,3 @@
8824 +#define APP_OCM_CODE_SIZE (0x3ffc2e00-0x3ffc0000)
8825 +#define APP_OCM_DATA_SIZE (0x3ffd3500-0x3ffc8000)
8826 +
8827 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ocm_text.lds.inc linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_text.lds.inc
8828 --- linux-2.6.30.10/arch/ubicom32/include/asm/ocm_text.lds.inc  1970-01-01 02:00:00.000000000 +0200
8829 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_text.lds.inc      2009-12-11 11:45:11.000000000 +0200
8830 @@ -0,0 +1,175 @@
8831 +/*
8832 + * arch/ubicom32/include/asm/ocm_text.lds.inc
8833 + *     <TODO: Replace with short file description>
8834 + *
8835 + * (C) Copyright 2009, Ubicom, Inc.
8836 + *
8837 + * This file is part of the Ubicom32 Linux Kernel Port.
8838 + *
8839 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8840 + * it and/or modify it under the terms of the GNU General Public License
8841 + * as published by the Free Software Foundation, either version 2 of the
8842 + * License, or (at your option) any later version.
8843 + *
8844 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8845 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8846 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8847 + * the GNU General Public License for more details.
8848 + *
8849 + * You should have received a copy of the GNU General Public License
8850 + * along with the Ubicom32 Linux Kernel Port.  If not,
8851 + * see <http://www.gnu.org/licenses/>.
8852 + *
8853 + * Ubicom32 implementation derived from (with many thanks):
8854 + *   arch/m68knommu
8855 + *   arch/blackfin
8856 + *   arch/parisc
8857 + */
8858 +*(.text.do_csum)
8859 +*(.text.tcp_packet)
8860 +*(.text.ipt_do_table)
8861 +*(.text.nf_conntrack_in)
8862 +*(.text.ip_forward)
8863 +*(.text.dev_queue_xmit)
8864 +*(.text.netif_receive_skb)
8865 +*(.text.ip_route_input)
8866 +*(.text.ip_finish_output)
8867 +*(.text.nf_iterate)
8868 +*(.text.__hash_conntrack)
8869 +*(.text.memset)
8870 +*(.text.memcpy)
8871 +*(.text.ip_rcv)
8872 +*(.text.__nf_conntrack_find)
8873 +*(.text.dev_hard_start_xmit)
8874 +*(.text.vlan_dev_hard_start_xmit)
8875 +*(.text.vlan_dev_hard_header)
8876 +*(.text.__nf_ct_refresh_acct)
8877 +*(.text.tcp_error)
8878 +*(.text.pfifo_fast_enqueue)
8879 +*(.text.ipv4_confirm)
8880 +*(.text.ip_output)
8881 +*(.text.neigh_connected_output)
8882 +*(.text.nf_hook_slow)
8883 +*(.text.nf_nat_packet)
8884 +*(.text.local_bh_enable)
8885 +*(.text.pfifo_fast_dequeue)
8886 +*(.text.ubi32_eth_receive)
8887 +*(.text.nf_nat_fn)
8888 +*(.text.skb_checksum)
8889 +*(.text.memmove)
8890 +*(.text.ubi32_eth_tx_done)
8891 +*(.text.eth_header)
8892 +*(.text.skb_release_data)
8893 +*(.text.nf_conntrack_find_get)
8894 +*(.text.process_backlog)
8895 +*(.text.vlan_skb_recv)
8896 +*(.text.ip_rcv_finish)
8897 +*(.text.__qdisc_run)
8898 +*(.text.skb_push)
8899 +*(.text.eth_type_trans)
8900 +*(.text.__alloc_skb)
8901 +*(.text.netif_rx)
8902 +*(.text.nf_ip_checksum)
8903 +*(.text.__skb_checksum_complete_head)
8904 +*(.text.ipv4_conntrack_defrag)
8905 +*(.text.tcp_pkt_to_tuple)
8906 +*(.text.kfree)
8907 +*(.text.tcp_manip_pkt)
8908 +*(.text.skb_put)
8909 +*(.text.nf_ct_get_tuple)
8910 +*(.text.__kmalloc)
8911 +*(.text.ubi32_eth_start_xmit)
8912 +*(.text.free_block)
8913 +*(.text.ipt_hook)
8914 +*(.text.kmem_cache_free)
8915 +*(.text.skb_pull_rcsum)
8916 +*(.text.cache_alloc_refill)
8917 +*(.text.skb_release_head_state)
8918 +*(.text.manip_pkt)
8919 +*(.text.ip_sabotage_in)
8920 +*(.text.ip_forward_finish)
8921 +*(.text.kmem_cache_alloc)
8922 +*(.text.local_bh_disable)
8923 +*(.text.ipv4_pkt_to_tuple)
8924 +*(.text.inet_proto_csum_replace4)
8925 +*(.text.__nf_ct_l4proto_find)
8926 +*(.text.csum_partial)
8927 +*(.text.neigh_resolve_output)
8928 +*(.text.__kfree_skb)
8929 +*(.text.kfree_skb)
8930 +*(.text.__find_vlan_dev)
8931 +*(.text.ldsr_ctxsw_thread)
8932 +*(.text.__do_IRQ)
8933 +*(.text.skb_pull)
8934 +*(.text.ipv4_invert_tuple)
8935 +*(.text.nf_ct_invert_tuplepr)
8936 +*(.text.skb_make_writable)
8937 +*(.text.ipv4_get_l4proto)
8938 +*(.text.handle_IRQ_event)
8939 +*(.text.net_rx_action)
8940 +*(.text.__do_softirq)
8941 +*(.text.nf_nat_in)
8942 +*(.text.note_interrupt)
8943 +*(.text.ipv4_conntrack_in)
8944 +*(.text.dst_release)
8945 +*(.text.tasklet_action)
8946 +*(.text.nf_nat_out)
8947 +*(.text.nf_ct_invert_tuple)
8948 +*(.text.do_IRQ)
8949 +*(.text.__tasklet_schedule)
8950 +*(.text.__skb_checksum_complete)
8951 +*(.text.ubi32_eth_interrupt)
8952 +*(.text.dev_kfree_skb_any)
8953 +*(.text.ret_from_interrupt_to_kernel)
8954 +*(.text.preemptive_context_save)
8955 +*(.text.irq_ack_vector)
8956 +*(.text.update_wall_time)
8957 +*(.text.ldsr_thread)
8958 +*(.text.irq_exit)
8959 +*(.text.ubi32_eth_do_tasklet)
8960 +*(.text.__napi_schedule)
8961 +*(.text.idle_cpu)
8962 +*(.text.run_timer_softirq)
8963 +*(.text.ldsr_mask_vector)
8964 +*(.text.irq_enter)
8965 +*(.text.ldsr_get_lsb)
8966 +*(.text.ldsr_unmask_vector)
8967 +*(.text.ip_fast_csum)
8968 +*(.text.hrtimer_run_queues)
8969 +*(.text.tcp_invert_tuple)
8970 +*(.text.T___705)
8971 +*(.text.run_posix_cpu_timers)
8972 +*(.text.free_hot_cold_page)
8973 +*(.text.lock_timer_base)
8974 +*(.text.calc_delta_mine)
8975 +*(.text.slab_destroy)
8976 +*(.text.rcu_pending)
8977 +*(.text.scheduler_tick)
8978 +*(.text.hrtimer_run_pending)
8979 +*(.text.do_softirq)
8980 +*(.text.del_timer)
8981 +*(.text.irq_end_vector)
8982 +*(.text.pci_read_u32)
8983 +*(.text.udivmodsi4)
8984 +*(.text.memcmp)
8985 +*(.text.memset)
8986 +*(.text.__slab_alloc)
8987 +*(.text.br_handle_frame)
8988 +*(.text.br_fdb_update)
8989 +*(.text.__br_fdb_get)
8990 +*(.text.br_forward)
8991 +*(.text.br_handle_frame_finish)
8992 +*(.text.pci_write_u32)
8993 +*(.text.kmem_freepages)
8994 +*(.text.br_dev_queue_push_xmit)
8995 +*(.text.ioread32)
8996 +*(.text.next_zones_zonelist)
8997 +*(.text.ubi32_pci_read_u32)
8998 +*(.text.zone_watermark_ok)
8999 +*(.text.__rmqueue_smallest)
9000 +*(.text.ubi32_eth_napi_poll)
9001 +*(.text.ubi32_pci_write_u32)
9002 +*(.text.ubi32_pci_read_u32)
9003 +*(.text._local_bh_enable)
9004 +*(.text._local_bh_disable)
9005 +*(.text.get_slab)
9006 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/page.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page.h
9007 --- linux-2.6.30.10/arch/ubicom32/include/asm/page.h    1970-01-01 02:00:00.000000000 +0200
9008 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page.h        2009-12-11 11:45:11.000000000 +0200
9009 @@ -0,0 +1,106 @@
9010 +/*
9011 + * arch/ubicom32/include/asm/page.h
9012 + *   Memory page related operations and definitions.
9013 + *
9014 + * (C) Copyright 2009, Ubicom, Inc.
9015 + *
9016 + * This file is part of the Ubicom32 Linux Kernel Port.
9017 + *
9018 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9019 + * it and/or modify it under the terms of the GNU General Public License
9020 + * as published by the Free Software Foundation, either version 2 of the
9021 + * License, or (at your option) any later version.
9022 + *
9023 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9024 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9025 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9026 + * the GNU General Public License for more details.
9027 + *
9028 + * You should have received a copy of the GNU General Public License
9029 + * along with the Ubicom32 Linux Kernel Port.  If not,
9030 + * see <http://www.gnu.org/licenses/>.
9031 + *
9032 + * Ubicom32 implementation derived from (with many thanks):
9033 + *   arch/m68knommu
9034 + *   arch/blackfin
9035 + *   arch/parisc
9036 + */
9037 +#ifndef _ASM_UBICOM32_PAGE_H
9038 +#define _ASM_UBICOM32_PAGE_H
9039 +
9040 +/* PAGE_SHIFT determines the page size */
9041 +
9042 +#define PAGE_SHIFT     12
9043 +#define PAGE_SIZE      (1 << PAGE_SHIFT)
9044 +#define PAGE_MASK      (~(PAGE_SIZE-1))
9045 +
9046 +#include <asm/setup.h>
9047 +
9048 +#ifndef __ASSEMBLY__
9049 +
9050 +#define get_user_page(vaddr)           __get_free_page(GFP_KERNEL)
9051 +#define free_user_page(page, addr)     free_page(addr)
9052 +
9053 +#define clear_page(page)       memset((page), 0, PAGE_SIZE)
9054 +#define copy_page(to,from)     memcpy((to), (from), PAGE_SIZE)
9055 +
9056 +#define clear_user_page(page, vaddr, pg)       clear_page(page)
9057 +#define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
9058 +
9059 +#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
9060 +       alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
9061 +#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
9062 +
9063 +/*
9064 + * These are used to make use of C type-checking..
9065 + */
9066 +typedef struct { unsigned long pte; } pte_t;
9067 +typedef struct { unsigned long pmd[16]; } pmd_t;
9068 +typedef struct { unsigned long pgd; } pgd_t;
9069 +typedef struct { unsigned long pgprot; } pgprot_t;
9070 +typedef struct page *pgtable_t;
9071 +
9072 +#define pte_val(x)     ((x).pte)
9073 +#define pmd_val(x)     ((&x)->pmd[0])
9074 +#define pgd_val(x)     ((x).pgd)
9075 +#define pgprot_val(x)  ((x).pgprot)
9076 +
9077 +#define __pte(x)       ((pte_t) { (x) } )
9078 +#define __pmd(x)       ((pmd_t) { (x) } )
9079 +#define __pgd(x)       ((pgd_t) { (x) } )
9080 +#define __pgprot(x)    ((pgprot_t) { (x) } )
9081 +
9082 +extern unsigned long memory_start;
9083 +extern unsigned long memory_end;
9084 +
9085 +#endif /* !__ASSEMBLY__ */
9086 +
9087 +#include <asm/page_offset.h>
9088 +
9089 +#define PAGE_OFFSET            (PAGE_OFFSET_RAW)
9090 +
9091 +#ifndef __ASSEMBLY__
9092 +
9093 +#define __pa(vaddr)            virt_to_phys((void *)(vaddr))
9094 +#define __va(paddr)            phys_to_virt((unsigned long)(paddr))
9095 +
9096 +#define virt_to_pfn(kaddr)     (__pa(kaddr) >> PAGE_SHIFT)
9097 +#define pfn_to_virt(pfn)       __va((pfn) << PAGE_SHIFT)
9098 +
9099 +#define virt_to_page(addr)     (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
9100 +#define page_to_virt(page)     ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
9101 +
9102 +#define pfn_to_page(pfn)       virt_to_page(pfn_to_virt(pfn))
9103 +#define page_to_pfn(page)      virt_to_pfn(page_to_virt(page))
9104 +#define pfn_valid(pfn)         ((pfn) < max_mapnr)
9105 +
9106 +#define        virt_addr_valid(kaddr)  (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
9107 +                               ((void *)(kaddr) < (void *)memory_end))
9108 +
9109 +#endif /* __ASSEMBLY__ */
9110 +
9111 +#ifdef __KERNEL__
9112 +#include <asm-generic/page.h>
9113 +#endif
9114 +
9115 +#endif /* _ASM_UBICOM32_PAGE_H */
9116 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/page_offset.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page_offset.h
9117 --- linux-2.6.30.10/arch/ubicom32/include/asm/page_offset.h     1970-01-01 02:00:00.000000000 +0200
9118 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page_offset.h 2009-12-11 11:45:11.000000000 +0200
9119 @@ -0,0 +1,35 @@
9120 +/*
9121 + * arch/ubicom32/include/asm/page_offset.h
9122 + *   Definition of PAGE_OFFSET_RAW for Ubicom32 architecture.
9123 + *
9124 + * (C) Copyright 2009, Ubicom, Inc.
9125 + *
9126 + * This file is part of the Ubicom32 Linux Kernel Port.
9127 + *
9128 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9129 + * it and/or modify it under the terms of the GNU General Public License
9130 + * as published by the Free Software Foundation, either version 2 of the
9131 + * License, or (at your option) any later version.
9132 + *
9133 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9134 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9135 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9136 + * the GNU General Public License for more details.
9137 + *
9138 + * You should have received a copy of the GNU General Public License
9139 + * along with the Ubicom32 Linux Kernel Port.  If not,
9140 + * see <http://www.gnu.org/licenses/>.
9141 + *
9142 + * Ubicom32 implementation derived from (with many thanks):
9143 + *   arch/m68knommu
9144 + *   arch/blackfin
9145 + *   arch/parisc
9146 + */
9147 +
9148 +#ifndef _ASM_UBICOM32_PAGE_OFFSET_H
9149 +#define _ASM_UBICOM32_PAGE_OFFSET_H
9150 +
9151 +/* This handles the memory map.. */
9152 +#define        PAGE_OFFSET_RAW         0x3ffc0000
9153 +
9154 +#endif /* _ASM_UBICOM32_PAGE_OFFSET_H */
9155 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/param.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/param.h
9156 --- linux-2.6.30.10/arch/ubicom32/include/asm/param.h   1970-01-01 02:00:00.000000000 +0200
9157 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/param.h       2009-12-11 11:45:11.000000000 +0200
9158 @@ -0,0 +1,49 @@
9159 +/*
9160 + * arch/ubicom32/include/asm/param.h
9161 + *   Definition of miscellaneous constants, including HZ.
9162 + *
9163 + * (C) Copyright 2009, Ubicom, Inc.
9164 + *
9165 + * This file is part of the Ubicom32 Linux Kernel Port.
9166 + *
9167 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9168 + * it and/or modify it under the terms of the GNU General Public License
9169 + * as published by the Free Software Foundation, either version 2 of the
9170 + * License, or (at your option) any later version.
9171 + *
9172 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9173 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9174 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9175 + * the GNU General Public License for more details.
9176 + *
9177 + * You should have received a copy of the GNU General Public License
9178 + * along with the Ubicom32 Linux Kernel Port.  If not,
9179 + * see <http://www.gnu.org/licenses/>.
9180 + *
9181 + * Ubicom32 implementation derived from (with many thanks):
9182 + *   arch/m68knommu
9183 + *   arch/blackfin
9184 + *   arch/parisc
9185 + */
9186 +#ifndef _ASM_UBICOM32_PARAM_H
9187 +#define _ASM_UBICOM32_PARAM_H
9188 +
9189 +#ifdef __KERNEL__
9190 +#define HZ CONFIG_HZ
9191 +#define        USER_HZ         HZ
9192 +#define        CLOCKS_PER_SEC  (USER_HZ)
9193 +#endif
9194 +
9195 +#ifndef HZ
9196 +#define HZ     100
9197 +#endif
9198 +
9199 +#define EXEC_PAGESIZE  4096
9200 +
9201 +#ifndef NOGROUP
9202 +#define NOGROUP                (-1)
9203 +#endif
9204 +
9205 +#define MAXHOSTNAMELEN 64      /* max length of hostname */
9206 +
9207 +#endif /* _ASM_UBICOM32_PARAM_H */
9208 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pci.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pci.h
9209 --- linux-2.6.30.10/arch/ubicom32/include/asm/pci.h     1970-01-01 02:00:00.000000000 +0200
9210 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pci.h 2009-12-11 11:45:11.000000000 +0200
9211 @@ -0,0 +1,210 @@
9212 +/*
9213 + * arch/ubicom32/include/asm/pci.h
9214 + *   Definitions of PCI operations for Ubicom32 architecture.
9215 + *
9216 + * (C) Copyright 2009, Ubicom, Inc.
9217 + *
9218 + * This file is part of the Ubicom32 Linux Kernel Port.
9219 + *
9220 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9221 + * it and/or modify it under the terms of the GNU General Public License
9222 + * as published by the Free Software Foundation, either version 2 of the
9223 + * License, or (at your option) any later version.
9224 + *
9225 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9226 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9227 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9228 + * the GNU General Public License for more details.
9229 + *
9230 + * You should have received a copy of the GNU General Public License
9231 + * along with the Ubicom32 Linux Kernel Port.  If not,
9232 + * see <http://www.gnu.org/licenses/>.
9233 + *
9234 + * Ubicom32 implementation derived from (with many thanks):
9235 + *   arch/m68knommu
9236 + *   arch/blackfin
9237 + *   arch/parisc
9238 + */
9239 +#ifndef _ASM_UBICOM32_PCI_H
9240 +#define _ASM_UBICOM32_PCI_H
9241 +
9242 +#include <asm/io.h>
9243 +
9244 +/* The PCI address space does equal the physical memory
9245 + * address space.  The networking and block device layers use
9246 + * this boolean for bounce buffer decisions.
9247 + */
9248 +#define PCI_DMA_BUS_IS_PHYS    (1)
9249 +
9250 +
9251 +
9252 +/*
9253 + * Perform a master read/write to the PCI bus.
9254 + * These functions return a PCI_RESP_xxx code.
9255 + */
9256 +extern u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data);
9257 +extern u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data);
9258 +extern u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data);
9259 +extern u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data);
9260 +extern u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data);
9261 +extern u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data);
9262 +
9263 +
9264 +#define PCIBIOS_MIN_IO          0x100
9265 +#define PCIBIOS_MIN_MEM         0x10000000
9266 +
9267 +#define pcibios_assign_all_busses()    0
9268 +#define pcibios_scan_all_fns(a, b)     0
9269 +extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
9270 +       struct resource *res);
9271 +
9272 +extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
9273 +       struct pci_bus_region *region);
9274 +
9275 +struct pci_sys_data;
9276 +struct pci_bus;
9277 +
9278 +struct hw_pci {
9279 +        struct list_head buses;
9280 +        int             nr_controllers;
9281 +        int             (*setup)(int nr, struct pci_sys_data *);
9282 +        struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
9283 +        void            (*preinit)(void);
9284 +        void            (*postinit)(void);
9285 +        u8              (*swizzle)(struct pci_dev *dev, u8 *pin);
9286 +        int             (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
9287 +};
9288 +
9289 +/*
9290 + * Per-controller structure
9291 + */
9292 +struct pci_sys_data {
9293 +        struct list_head node;
9294 +        int             busnr;          /* primary bus number                   */
9295 +        u64             mem_offset;     /* bus->cpu memory mapping offset       */
9296 +        unsigned long   io_offset;      /* bus->cpu IO mapping offset           */
9297 +        struct pci_bus  *bus;           /* PCI bus                              */
9298 +        struct resource *resource[3];   /* Primary PCI bus resources            */
9299 +                                        /* Bridge swizzling                     */
9300 +        u8              (*swizzle)(struct pci_dev *, u8 *);
9301 +                                        /* IRQ mapping                          */
9302 +        int             (*map_irq)(struct pci_dev *, u8, u8);
9303 +        struct hw_pci   *hw;
9304 +};
9305 +
9306 +static  inline struct resource *
9307 +pcibios_select_root(struct pci_dev *pdev, struct resource *res)
9308 +{
9309 +        struct resource *root = NULL;
9310 +
9311 +        if (res->flags & IORESOURCE_IO)
9312 +                root = &ioport_resource;
9313 +        if (res->flags & IORESOURCE_MEM)
9314 +                root = &iomem_resource;
9315 +
9316 +        return root;
9317 +}
9318 +
9319 +static inline void pcibios_set_master(struct pci_dev *dev)
9320 +{
9321 +        /* No special bus mastering setup handling */
9322 +}
9323 +#define HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE 1
9324 +#define HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY 1
9325 +
9326 +#ifdef CONFIG_PCI
9327 +static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
9328 +                     dma_addr_t *dma_handle)
9329 +{
9330 +    void *vaddr = kmalloc(size, GFP_KERNEL);
9331 +    if(vaddr != NULL) {
9332 +        *dma_handle = virt_to_phys(vaddr);
9333 +    }
9334 +    return vaddr;
9335 +}
9336 +
9337 +static  inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
9338 +{
9339 +       return 1;
9340 +}
9341 +
9342 +static  inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
9343 +       void *cpu_addr, dma_addr_t dma_handle)
9344 +{
9345 +       kfree(cpu_addr);
9346 +       return;
9347 +}
9348 +
9349 +static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
9350 +       size_t size, int direction)
9351 +{
9352 +        return virt_to_phys(ptr);
9353 +}
9354 +
9355 +static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
9356 +       size_t size, int direction)
9357 +{
9358 +        return;
9359 +}
9360 +
9361 +static inline dma_addr_t
9362 +pci_map_page(struct pci_dev *hwdev, struct page *page,
9363 +             unsigned long offset, size_t size, int direction)
9364 +{
9365 +        return pci_map_single(hwdev, page_address(page) + offset, size, (int)direction);
9366 +}
9367 +
9368 +static inline void
9369 +pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
9370 +               size_t size, int direction)
9371 +{
9372 +       pci_unmap_single(hwdev, dma_address, size, direction);
9373 +}
9374 +
9375 +static inline int
9376 +pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9377 +           int nents, int direction)
9378 +{
9379 +        return nents;
9380 +}
9381 +
9382 +static inline void
9383 +pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9384 +             int nents, int direction)
9385 +{
9386 +}
9387 +
9388 +static inline void
9389 +pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
9390 +                int nelems, int direction)
9391 +{
9392 +}
9393 +
9394 +static inline void
9395 +pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
9396 +                int nelems, int direction)
9397 +{
9398 +}
9399 +
9400 +static inline void
9401 +pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
9402 +                    size_t size, int direction)
9403 +{
9404 +}
9405 +
9406 +static inline void
9407 +pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
9408 +                    size_t size, int direction)
9409 +{
9410 +}
9411 +
9412 +static inline int
9413 +pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
9414 +{
9415 +        return dma_addr == 0;
9416 +}
9417 +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
9418 +extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
9419 +#endif
9420 +
9421 +#endif /* _ASM_UBICOM32_PCI_H */
9422 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pcm_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pcm_tio.h
9423 --- linux-2.6.30.10/arch/ubicom32/include/asm/pcm_tio.h 1970-01-01 02:00:00.000000000 +0200
9424 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pcm_tio.h     2009-12-11 11:45:11.000000000 +0200
9425 @@ -0,0 +1,84 @@
9426 +/*
9427 + * arch/ubicom32/include/asm/pcm_tio.h
9428 + *   Ubicom32 architecture PCM TIO definitions.
9429 + *
9430 + * (C) Copyright 2009, Ubicom, Inc.
9431 + *
9432 + * This file is part of the Ubicom32 Linux Kernel Port.
9433 + *
9434 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9435 + * it and/or modify it under the terms of the GNU General Public License
9436 + * as published by the Free Software Foundation, either version 2 of the
9437 + * License, or (at your option) any later version.
9438 + *
9439 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9440 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9441 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9442 + * the GNU General Public License for more details.
9443 + *
9444 + * You should have received a copy of the GNU General Public License
9445 + * along with the Ubicom32 Linux Kernel Port.  If not,
9446 + * see <http://www.gnu.org/licenses/>.
9447 + */
9448 +#ifndef _ASM_UBICOM32_PCM_TIO_H
9449 +#define _ASM_UBICOM32_PCM_TIO_H
9450 +
9451 +#include <asm/devtree.h>
9452 +
9453 +#define PCM_TIO_REGS_VERSION   2
9454 +struct pcm_tio_regs {
9455 +       /*
9456 +        * set this value to 1 to reload the parameters and restart the HRT
9457 +        */
9458 +       u32_t           reload;
9459 +
9460 +       /*
9461 +        * Pointers to the input and output buffers
9462 +        */
9463 +       void            *input_buf;
9464 +       void            *output_buf;
9465 +
9466 +       /*
9467 +        * Buffer size (see pcm_hrt.S for constraints)
9468 +        */
9469 +       u32_t           buffer_size;
9470 +
9471 +       /*
9472 +        * Current cycle.  This variable increases every time half the buffer
9473 +        * is consumed.
9474 +        */
9475 +       u32_t           cycle;
9476 +
9477 +       /*
9478 +        * Fields below this line are not accessed by the HRT.  They are purely
9479 +        * informational for the user of this TIO.
9480 +        */
9481 +
9482 +       /*
9483 +        * Version of this structure
9484 +        */
9485 +       u32_t           version;
9486 +
9487 +       /*
9488 +        * Number of channels supported
9489 +        */
9490 +       u32_t           channels;
9491 +
9492 +       /*
9493 +        * Maximum buffer size
9494 +        */
9495 +       u32_t           max_buffer_size;
9496 +};
9497 +
9498 +/*
9499 + * Our device node
9500 + */
9501 +#define PCM_TIO_NODE_VERSION   1
9502 +struct pcm_tio_node {
9503 +       struct devtree_node     dn;
9504 +       u32_t                   version;
9505 +       struct pcm_tio_regs     *regs;
9506 +};
9507 +
9508 +#endif
9509 +
9510 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/percpu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/percpu.h
9511 --- linux-2.6.30.10/arch/ubicom32/include/asm/percpu.h  1970-01-01 02:00:00.000000000 +0200
9512 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/percpu.h      2009-12-11 11:45:11.000000000 +0200
9513 @@ -0,0 +1,33 @@
9514 +/*
9515 + * arch/ubicom32/include/asm/percpu.h
9516 + *   Generic percpu.h for the Ubicom32 architecture.
9517 + *
9518 + * (C) Copyright 2009, Ubicom, Inc.
9519 + *
9520 + * This file is part of the Ubicom32 Linux Kernel Port.
9521 + *
9522 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9523 + * it and/or modify it under the terms of the GNU General Public License
9524 + * as published by the Free Software Foundation, either version 2 of the
9525 + * License, or (at your option) any later version.
9526 + *
9527 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9528 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9529 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9530 + * the GNU General Public License for more details.
9531 + *
9532 + * You should have received a copy of the GNU General Public License
9533 + * along with the Ubicom32 Linux Kernel Port.  If not,
9534 + * see <http://www.gnu.org/licenses/>.
9535 + *
9536 + * Ubicom32 implementation derived from (with many thanks):
9537 + *   arch/m68knommu
9538 + *   arch/blackfin
9539 + *   arch/parisc
9540 + */
9541 +#ifndef _ASM_UBICOM32_PERCPU_H
9542 +#define _ASM_UBICOM32_PERCPU_H
9543 +
9544 +#include <asm-generic/percpu.h>
9545 +
9546 +#endif /* _ASM_UBICOM32_PERCPU_H */
9547 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pgalloc.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgalloc.h
9548 --- linux-2.6.30.10/arch/ubicom32/include/asm/pgalloc.h 1970-01-01 02:00:00.000000000 +0200
9549 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgalloc.h     2009-12-11 11:45:11.000000000 +0200
9550 @@ -0,0 +1,36 @@
9551 +/*
9552 + * arch/ubicom32/include/asm/pgalloc.h
9553 + *   Page table allocation definitions.
9554 + *
9555 + * (C) Copyright 2009, Ubicom, Inc.
9556 + *
9557 + * This file is part of the Ubicom32 Linux Kernel Port.
9558 + *
9559 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9560 + * it and/or modify it under the terms of the GNU General Public License
9561 + * as published by the Free Software Foundation, either version 2 of the
9562 + * License, or (at your option) any later version.
9563 + *
9564 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9565 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9566 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9567 + * the GNU General Public License for more details.
9568 + *
9569 + * You should have received a copy of the GNU General Public License
9570 + * along with the Ubicom32 Linux Kernel Port.  If not,
9571 + * see <http://www.gnu.org/licenses/>.
9572 + *
9573 + * Ubicom32 implementation derived from (with many thanks):
9574 + *   arch/m68knommu
9575 + *   arch/blackfin
9576 + *   arch/parisc
9577 + */
9578 +#ifndef _ASM_UBICOM32_PGALLOC_H
9579 +#define _ASM_UBICOM32_PGALLOC_H
9580 +
9581 +#include <linux/mm.h>
9582 +#include <asm/setup.h>
9583 +
9584 +#define check_pgt_cache()      do { } while (0)
9585 +
9586 +#endif /* _ASM_UBICOM32_PGALLOC_H */
9587 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pgtable.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgtable.h
9588 --- linux-2.6.30.10/arch/ubicom32/include/asm/pgtable.h 1970-01-01 02:00:00.000000000 +0200
9589 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgtable.h     2009-12-11 11:45:11.000000000 +0200
9590 @@ -0,0 +1,124 @@
9591 +/*
9592 + * arch/ubicom32/include/asm/pgtable.h
9593 + *   Ubicom32 pseudo page table definitions and operations.
9594 + *
9595 + * (C) Copyright 2009, Ubicom, Inc.
9596 + * Copyright (C) 2004   Microtronix Datacom Ltd
9597 + *
9598 + * This file is part of the Ubicom32 Linux Kernel Port.
9599 + *
9600 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9601 + * it and/or modify it under the terms of the GNU General Public License
9602 + * as published by the Free Software Foundation, either version 2 of the
9603 + * License, or (at your option) any later version.
9604 + *
9605 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9606 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9607 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9608 + * the GNU General Public License for more details.
9609 + *
9610 + * You should have received a copy of the GNU General Public License
9611 + * along with the Ubicom32 Linux Kernel Port.  If not,
9612 + * see <http://www.gnu.org/licenses/>.
9613 + *
9614 + * Ubicom32 implementation derived from (with many thanks):
9615 + *   arch/m68knommu
9616 + *   arch/blackfin
9617 + *   arch/parisc
9618 + *   and various works, Alpha, ix86, M68K, Sparc, ...et al
9619 + */
9620 +#ifndef _ASM_UBICOM32_PGTABLE_H
9621 +#define _ASM_UBICOM32_PGTABLE_H
9622 +
9623 +#include <asm-generic/4level-fixup.h>
9624 +
9625 +//vic - this bit copied from m68knommu version
9626 +#include <asm/setup.h>
9627 +#include <asm/io.h>
9628 +#include <linux/sched.h>
9629 +
9630 +typedef pte_t *pte_addr_t;
9631 +
9632 +#define pgd_present(pgd)       (1)       /* pages are always present on NO_MM */
9633 +#define pgd_none(pgd)          (0)
9634 +#define pgd_bad(pgd)           (0)
9635 +#define pgd_clear(pgdp)
9636 +#define kern_addr_valid(addr)  (1)
9637 +#define        pmd_offset(a, b)        ((void *)0)
9638 +
9639 +#define PAGE_NONE              __pgprot(0)    /* these mean nothing to NO_MM */
9640 +#define PAGE_SHARED            __pgprot(0)    /* these mean nothing to NO_MM */
9641 +#define PAGE_COPY              __pgprot(0)    /* these mean nothing to NO_MM */
9642 +#define PAGE_READONLY          __pgprot(0)    /* these mean nothing to NO_MM */
9643 +#define PAGE_KERNEL            __pgprot(0)    /* these mean nothing to NO_MM */
9644 +//vic - this bit copied from m68knommu version
9645 +
9646 +extern void paging_init(void);
9647 +#define swapper_pg_dir ((pgd_t *) 0)
9648 +
9649 +#define __swp_type(x)          (0)
9650 +#define __swp_offset(x)                (0)
9651 +#define __swp_entry(typ,off)   ((swp_entry_t) { ((typ) | ((off) << 7)) })
9652 +#define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
9653 +#define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
9654 +
9655 +/*
9656 + * pgprot_noncached() is only for infiniband pci support, and a real
9657 + * implementation for RAM would be more complicated.
9658 + */
9659 +#define pgprot_noncached(prot) (prot)
9660 +
9661 +static inline int pte_file(pte_t pte) { return 0; }
9662 +
9663 +/*
9664 + * ZERO_PAGE is a global shared page that is always zero: used
9665 + * for zero-mapped memory areas etc..
9666 + */
9667 +#define ZERO_PAGE(vaddr)       (virt_to_page(0))
9668 +
9669 +extern unsigned int kobjsize(const void *objp);
9670 +extern int is_in_rom(unsigned long);
9671 +
9672 +/*
9673 + * No page table caches to initialise
9674 + */
9675 +#define pgtable_cache_init()   do { } while (0)
9676 +
9677 +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
9678 +               remap_pfn_range(vma, vaddr, pfn, size, prot)
9679 +
9680 +extern inline void flush_cache_mm(struct mm_struct *mm)
9681 +{
9682 +}
9683 +
9684 +extern inline void flush_cache_range(struct mm_struct *mm,
9685 +                                    unsigned long start,
9686 +                                    unsigned long end)
9687 +{
9688 +}
9689 +
9690 +/* Push the page at kernel virtual address and clear the icache */
9691 +extern inline void flush_page_to_ram (unsigned long address)
9692 +{
9693 +}
9694 +
9695 +/* Push n pages at kernel virtual address and clear the icache */
9696 +extern inline void flush_pages_to_ram (unsigned long address, int n)
9697 +{
9698 +}
9699 +
9700 +/*
9701 + * All 32bit addresses are effectively valid for vmalloc...
9702 + * Sort of meaningless for non-VM targets.
9703 + */
9704 +#define        VMALLOC_START   0
9705 +#define        VMALLOC_END     0xffffffff
9706 +
9707 +#define arch_enter_lazy_mmu_mode()     do {} while (0)
9708 +#define arch_leave_lazy_mmu_mode()     do {} while (0)
9709 +#define arch_flush_lazy_mmu_mode()     do {} while (0)
9710 +#define arch_enter_lazy_cpu_mode()     do {} while (0)
9711 +#define arch_leave_lazy_cpu_mode()     do {} while (0)
9712 +#define arch_flush_lazy_cpu_mode()     do {} while (0)
9713 +
9714 +#endif /* _ASM_UBICOM32_PGTABLE_H */
9715 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/plio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/plio.h
9716 --- linux-2.6.30.10/arch/ubicom32/include/asm/plio.h    1970-01-01 02:00:00.000000000 +0200
9717 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/plio.h        2009-12-11 11:45:11.000000000 +0200
9718 @@ -0,0 +1,313 @@
9719 +/*
9720 + * plio.h
9721 + *     PLIO defines.
9722 + *
9723 + * Copyright Â© 2009 Ubicom Inc. <www.ubicom.com>.  All Rights Reserved.
9724 + *
9725 + * This file is part of the Ubicom32 Linux Kernel Port.
9726 + *
9727 + * The Ubicom32 Linux Kernel Port is free software: you can
9728 + * redistribute it and/or modify it under the terms of the GNU General
9729 + * Public License as published by the Free Software Foundation, either
9730 + * version 2 of the License, or (at your option) any later version.
9731 + *
9732 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9733 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9734 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9735 + * See the GNU General Public License for more details.
9736 + *
9737 + * You should have received a copy of the GNU General Public License
9738 + * along with the Ubicom32 Linux Kernel Port.  If not,
9739 + * see <http://www.gnu.org/licenses/>.
9740 + * This file contains confidential information of Ubicom, Inc. and your use of
9741 + * this file is subject to the Ubicom Software License Agreement distributed with
9742 + * this file. If you are uncertain whether you are an authorized user or to report
9743 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
9744 + * Unauthorized reproduction or distribution of this file is subject to civil and
9745 + * criminal penalties.
9746 + */
9747 +
9748 +#ifndef __PLIO__H__
9749 +#define __PLIO__H__
9750 +
9751 +#include <asm/ip5000.h>
9752 +#include <asm/thread.h>
9753 +
9754 +#define PLIO_PORT              RD
9755 +#define PLIO_EXT_PORT          RI
9756 +
9757 +#define TRANSMIT_FIFO_WATERMARK 8
9758 +
9759 +/*
9760 + * PLIO non-blocking register definitions
9761 + */
9762 +#define PLIO_FN                2
9763 +
9764 +typedef struct {
9765 +       unsigned        : 10;
9766 +       unsigned        rxfifo_thread_enable: 1;   /* allowed rxfifo thread enable */
9767 +       unsigned        : 1;
9768 +       unsigned        rxfifo_thread: 4;          /* allowed rxfifo thread access */
9769 +       unsigned        : 4;
9770 +       unsigned        br_thread: 4;              /* allowed blocking region thread access */
9771 +       unsigned        fn_reset: 4;               /* function reset bit vector */
9772 +       unsigned        rxfifo_sel: 1;             /* select between RXFIFO 0 and 1 */
9773 +       unsigned        fn_sel: 3;                 /* select port function */
9774 +} plio_io_function_t;
9775 +
9776 +typedef struct {
9777 +       unsigned        : 24;
9778 +       unsigned        pin:8;
9779 +} plio_gpio_t;
9780 +
9781 +typedef struct {
9782 +       unsigned        : 16;
9783 +       unsigned        txfifo_uf: 1;              /* TXFIFO underflow */
9784 +       unsigned        txfifo_wm: 1;              /* TXFIFO watermark */
9785 +       unsigned        rxfifo_of: 1;              /* RXFIFO overflow */
9786 +       unsigned        rxfifo_wm: 1;              /* RXFIFO watermark */
9787 +       unsigned        : 5;
9788 +       unsigned        lreg_int_addr_rd: 1;       /* read from specified LREG address */
9789 +       unsigned        lreg_int_addr_wr: 1;       /* write to specified LREG address */
9790 +       unsigned        extctl_int: 4;             /* synchronized external interrupts */
9791 +       unsigned        pfsm_int: 1;               /* state machine */
9792 +} plio_intstat_t;
9793 +
9794 +typedef struct {
9795 +       unsigned        txfifo_reset: 1;           /* TXFIFO reset for int_set only */
9796 +       unsigned        rxfifo_reset: 1;           /* RXFIFO reset for int_set only */
9797 +       unsigned        : 11;
9798 +       unsigned        idif_txfifo_flush: 1;      /* flush TXFIFO and idif_txfifo */
9799 +       unsigned        idif_rxfifo_flush: 1;      /* flush RXFIFO and idif_rxfifo */
9800 +       unsigned        pfsm_start: 1;             /* input to fsm */
9801 +       unsigned        txfifo_uf: 1;              /* TXFIFO underflow */
9802 +       unsigned        txfifo_wm: 1;              /* TXFIFO watermark */
9803 +       unsigned        rxfifo_of: 1;              /* RXFIFO overflow */
9804 +       unsigned        rxfifo_wm: 1;              /* RXFIFO watermark */
9805 +       unsigned        : 5;
9806 +       unsigned        lreg_int_addr_rd: 1;       /* read from specified LREG address */
9807 +       unsigned        lreg_int_addr_wr: 1;       /* write to specified LREG address */
9808 +       unsigned        extctl_int: 4;             /* synchronized external interrupts */
9809 +       unsigned        pfsm_int: 1;               /* state machine */
9810 +} plio_intset_t;
9811 +
9812 +typedef enum {
9813 +       PLIO_PORT_MODE_D,
9814 +       PLIO_PORT_MODE_DE,
9815 +       PLIO_PORT_MODE_DI,
9816 +       PLIO_PORT_MODE_DEI,
9817 +       PLIO_PORT_MODE_DC,
9818 +} plio_port_mode_t;
9819 +
9820 +typedef enum {
9821 +       PLIO_CLK_CORE,  /* CORE CLK */
9822 +       PLIO_CLK_IO,    /* IO CLK */
9823 +       PLIO_CLK_EXT,   /* EXT CLK */
9824 +} plio_clk_src_t;
9825 +typedef struct {
9826 +       unsigned                : 4;
9827 +       unsigned                edif_iaena_sel: 1;         /* Input Address Enable Select */
9828 +       unsigned                edif_iaclk_sel: 1;         /* Input Address Clock Select */
9829 +       unsigned                edif_iald_inv: 1;          /* Input Address Strobe Invert */
9830 +       unsigned                edif_idclk_sel: 1;         /* Input Data Clock Select */
9831 +       unsigned                edif_idld_inv: 1;          /* Input Data Strobe Invert */
9832 +       unsigned                edif_ds: 3;                /* specify IDR and ODR data shift */
9833 +       unsigned                edif_cmp_mode: 1;          /* configure IDR comparator output */
9834 +       unsigned                edif_idena_sel: 1;         /* Input Data Enable Select */
9835 +       unsigned                ecif_extclk_ena: 1;        /* plio_extctl output select */
9836 +       unsigned                idif_tx_fifo_cmd_sel: 1;   /* select pfsm_cmd data word position */
9837 +       unsigned                ptif_porti_cfg: 2;         /* select port I pin configuration */
9838 +       unsigned                ptif_portd_cfg: 3;         /* select port D pin configuration */
9839 +       plio_port_mode_t        ptif_port_mode: 3;      /* select other plio ports  */
9840 +       unsigned                icif_clk_plio_ext_inv: 1;  /* invert external plio clock when set */
9841 +       unsigned                icif_rst_plio: 1;          /* reset plio function and io fifos */
9842 +       plio_clk_src_t          icif_clk_src_sel: 2;      /* select plio clock source */
9843 +       unsigned                pfsm_prog: 1;              /* enable pfsm programming */
9844 +       unsigned                pfsm_cmd: 3;               /* software input to pfsm */
9845 +} plio_fctl0_t;
9846 +
9847 +typedef struct {
9848 +       unsigned        : 2;
9849 +       unsigned        idif_byteswap_tx: 3;       /* swap TXFIFO byte order */
9850 +       unsigned        idif_byteswap_rx: 3;       /* swap RXFIFO byte order */
9851 +       unsigned        : 1;
9852 +       unsigned        lreg_ena: 1;               /* enable local register map */
9853 +       unsigned        lreg_addr_fifo_cmp_ena: 1; /* enable a specific LREG address from/to TX/RX fifos */
9854 +       unsigned        lreg_addr_fifo_cmp: 5;     /* LREG address routed from/to TX/RX fifos */
9855 +       unsigned        : 1;
9856 +       unsigned        dcod_iald_idld_sel: 2;     /* select address/data strobes */
9857 +       unsigned        dcod_rw_src_sel: 1;        /* select LREG strobe source */
9858 +       unsigned        dcod_rd_sel: 5;            /* select read strobe source */
9859 +       unsigned        dcod_wr_sel: 5;            /* select write strobe source */
9860 +       unsigned        dcod_rd_lvl: 1;            /* select active level of read strobe */
9861 +       unsigned        dcod_wr_lvl: 1;            /* select active level of read strobe */
9862 +} plio_fctl1_t;
9863 +
9864 +typedef struct {
9865 +       unsigned        icif_eclk_div: 16;         /* external plio clock divider */
9866 +       unsigned        icif_iclk_div: 16;         /* internal plio clock divider */
9867 +} plio_fctl2_t;
9868 +
9869 +typedef struct {
9870 +       unsigned        : 27;
9871 +       unsigned        pfsm_state: 5;             /* current pfsm state */
9872 +} plio_stat_0_t;
9873 +
9874 +typedef struct {
9875 +       unsigned        : 3;
9876 +       unsigned        lreg_r_int_addr: 5;
9877 +       unsigned        : 11;
9878 +       unsigned        lreg_w_int_addr: 5;
9879 +       unsigned        lreg_w_int_data: 8;
9880 +} plio_stat_1_t;
9881 +
9882 +typedef struct {
9883 +       unsigned        : 32;
9884 +} plio_stat_2_t;
9885 +
9886 +typedef struct {
9887 +       unsigned        tx: 16;
9888 +       unsigned        rx: 16;
9889 +} plio_io_fifo_wm_t, plio_io_fifo_lvl_t;
9890 +
9891 +
9892 +/* plio blocking region register definitions
9893 + */
9894 +typedef struct {
9895 +       unsigned         ns1: 5;
9896 +       unsigned         ic1: 7;
9897 +       unsigned         ec1: 4;
9898 +       unsigned         ns0: 5;
9899 +       unsigned         ic0: 7;
9900 +       unsigned         ec0: 4;
9901 +} plio_sram_t;
9902 +
9903 +typedef struct {
9904 +       unsigned         : 2;
9905 +       unsigned         s9: 3;
9906 +       unsigned         s8: 3;
9907 +       unsigned         s7: 3;
9908 +       unsigned         s6: 3;
9909 +       unsigned         s5: 3;
9910 +       unsigned         s4: 3;
9911 +       unsigned         s3: 3;
9912 +       unsigned         s2: 3;
9913 +       unsigned         s1: 3;
9914 +       unsigned         s0: 3;
9915 +} plio_grpsel_t;
9916 +
9917 +typedef struct {
9918 +       unsigned        s7: 4;
9919 +       unsigned        s6: 4;
9920 +       unsigned        s5: 4;
9921 +       unsigned        s4: 4;
9922 +       unsigned        s3: 4;
9923 +       unsigned        s2: 4;
9924 +       unsigned        s1: 4;
9925 +       unsigned        s0: 4;
9926 +} plio_cs_lut_t;
9927 +
9928 +typedef struct {
9929 +       unsigned        lut3: 8;
9930 +       unsigned        lut2: 8;
9931 +       unsigned        lut1: 8;
9932 +       unsigned        lut0: 8;
9933 +} plio_extctl_t;
9934 +
9935 +typedef struct {
9936 +       plio_grpsel_t   grpsel[4];
9937 +       u16_t           cv[16];
9938 +       plio_cs_lut_t   cs_lut[4];
9939 +       plio_extctl_t   extctl_o_lut[8];
9940 +} plio_pfsm_t;
9941 +
9942 +typedef struct {
9943 +       u32_t           odr_oe_sel;
9944 +       u32_t           odr_oe;
9945 +       u32_t           cmp;
9946 +       u32_t           ncmp;
9947 +       u32_t           cmp_mask;
9948 +} plio_edif_t;
9949 +
9950 +typedef enum {
9951 +       PLIO_ECIF_CLK_OUT       = 9,
9952 +       PLIO_ECIF_IALD          = 9,
9953 +       PLIO_ECIF_CLK_IN        = 8,
9954 +       PLIO_ECIF_IDLD          = 8,
9955 +       PLIO_ECIF_INT           = 2,
9956 +} plio_ecif_output_t;
9957 +
9958 +typedef struct {
9959 +       u32_t           bypass_sync;
9960 +       u32_t           ift;
9961 +       u32_t           output_type;
9962 +       u32_t           output_ena;
9963 +       u32_t           output_lvl;
9964 +} plio_ecif_t;
9965 +
9966 +typedef struct {
9967 +       u32_t           idr_addr_pos_mask;
9968 +       u32_t           reserved;
9969 +       u32_t           lreg_bar;
9970 +} plio_dcod_t;
9971 +
9972 +typedef struct {
9973 +       u32_t           addr_rd_ena;
9974 +       u32_t           addr_wr_ena;
9975 +       u32_t           addr_rd_int_ena;
9976 +       u32_t           addr_wr_int_ena;
9977 +} plio_lcfg_t;
9978 +
9979 +
9980 +/*
9981 + * PLIO configuration
9982 + */
9983 +typedef struct {
9984 +       plio_fctl0_t    fctl0;
9985 +       plio_fctl1_t    fctl1;
9986 +       plio_fctl2_t    fctl2;
9987 +} plio_fctl_t;
9988 +
9989 +typedef struct {
9990 +       plio_pfsm_t     pfsm;
9991 +       plio_edif_t     edif;
9992 +       plio_ecif_t     ecif;
9993 +       plio_dcod_t     dcod;
9994 +       plio_lcfg_t     lcfg;
9995 +} plio_config_t;
9996 +
9997 +typedef struct {
9998 +       plio_io_function_t      function;
9999 +       plio_gpio_t             gpio_ctl;
10000 +       plio_gpio_t             gpio_out;
10001 +       plio_gpio_t             gpio_in;
10002 +       plio_intstat_t          intstat;
10003 +       plio_intstat_t          intmask;
10004 +       plio_intset_t           intset;
10005 +       plio_intstat_t          intclr;
10006 +       unsigned                tx_lo;
10007 +       unsigned                tx_hi;
10008 +       unsigned                rx_lo;
10009 +       unsigned                rx_hi;
10010 +       plio_fctl0_t            fctl0;
10011 +       plio_fctl1_t            fctl1;
10012 +       plio_fctl2_t            fctl2;
10013 +       plio_stat_0_t           stat0;
10014 +       plio_stat_1_t           stat1;
10015 +       plio_stat_2_t           stat2;
10016 +       plio_io_fifo_wm_t       fifo_wm;
10017 +       plio_io_fifo_lvl_t      fifo_lvl;
10018 +} plio_nbr_t;
10019 +
10020 +typedef struct {
10021 +       u32_t                   pfsm_sram[256];
10022 +       plio_config_t           config;
10023 +} plio_br_t;
10024 +
10025 +#define PLIO_NBR       ((plio_nbr_t *)(PLIO_PORT))
10026 +#define PLIO_BR                ((plio_br_t *)((PLIO_PORT + IO_PORT_BR_OFFSET)))
10027 +#define PEXT_NBR       ((plio_nbr_t *)(PLIO_EXT_PORT))
10028 +
10029 +extern void plio_init(const plio_fctl_t *plio_fctl, const plio_config_t *plio_config, const plio_sram_t plio_sram_cfg[], int sram_cfg_size);
10030 +
10031 +#endif // __PLIO__H__
10032 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/poll.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/poll.h
10033 --- linux-2.6.30.10/arch/ubicom32/include/asm/poll.h    1970-01-01 02:00:00.000000000 +0200
10034 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/poll.h        2009-12-11 11:45:11.000000000 +0200
10035 @@ -0,0 +1,36 @@
10036 +/*
10037 + * arch/ubicom32/include/asm/poll.h
10038 + *   Ubicom32 specific poll() related flags definitions.
10039 + *
10040 + * (C) Copyright 2009, Ubicom, Inc.
10041 + *
10042 + * This file is part of the Ubicom32 Linux Kernel Port.
10043 + *
10044 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10045 + * it and/or modify it under the terms of the GNU General Public License
10046 + * as published by the Free Software Foundation, either version 2 of the
10047 + * License, or (at your option) any later version.
10048 + *
10049 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10050 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10051 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10052 + * the GNU General Public License for more details.
10053 + *
10054 + * You should have received a copy of the GNU General Public License
10055 + * along with the Ubicom32 Linux Kernel Port.  If not,
10056 + * see <http://www.gnu.org/licenses/>.
10057 + *
10058 + * Ubicom32 implementation derived from (with many thanks):
10059 + *   arch/m68knommu
10060 + *   arch/blackfin
10061 + *   arch/parisc
10062 + */
10063 +#ifndef _ASM_UBICOM32_POLL_H
10064 +#define _ASM_UBICOM32_POLL_H
10065 +
10066 +#define POLLWRNORM     POLLOUT
10067 +#define POLLWRBAND     0x0100
10068 +
10069 +#include <asm-generic/poll.h>
10070 +
10071 +#endif /* _ASM_UBICOM32_POLL_H */
10072 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/posix_types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/posix_types.h
10073 --- linux-2.6.30.10/arch/ubicom32/include/asm/posix_types.h     1970-01-01 02:00:00.000000000 +0200
10074 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/posix_types.h 2009-12-11 11:45:11.000000000 +0200
10075 @@ -0,0 +1,93 @@
10076 +/*
10077 + * arch/ubicom32/include/asm/posix_types.h
10078 + *   Ubicom32 architecture posix types.
10079 + *
10080 + * (C) Copyright 2009, Ubicom, Inc.
10081 + * Copyright (C) 2004   Microtronix Datacom Ltd
10082 + *
10083 + * This file is part of the Ubicom32 Linux Kernel Port.
10084 + *
10085 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10086 + * it and/or modify it under the terms of the GNU General Public License
10087 + * as published by the Free Software Foundation, either version 2 of the
10088 + * License, or (at your option) any later version.
10089 + *
10090 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10091 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10092 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10093 + * the GNU General Public License for more details.
10094 + *
10095 + * You should have received a copy of the GNU General Public License
10096 + * along with the Ubicom32 Linux Kernel Port.  If not,
10097 + * see <http://www.gnu.org/licenses/>.
10098 + *
10099 + * Ubicom32 implementation derived from (with many thanks):
10100 + *   arch/m68knommu
10101 + *   arch/blackfin
10102 + *   arch/parisc
10103 + */
10104 +#ifndef __ARCH_UBICOM32_POSIX_TYPES_H
10105 +#define __ARCH_UBICOM32_POSIX_TYPES_H
10106 +
10107 +/*
10108 + * This file is generally used by user-level software, so you need to
10109 + * be a little careful about namespace pollution etc.  Also, we cannot
10110 + * assume GCC is being used.
10111 + */
10112 +
10113 +typedef unsigned long  __kernel_ino_t;
10114 +typedef unsigned short __kernel_mode_t;
10115 +typedef unsigned short __kernel_nlink_t;
10116 +typedef long           __kernel_off_t;
10117 +typedef int            __kernel_pid_t;
10118 +typedef unsigned short __kernel_ipc_pid_t;
10119 +typedef unsigned short __kernel_uid_t;
10120 +typedef unsigned short __kernel_gid_t;
10121 +typedef unsigned int   __kernel_size_t;
10122 +typedef int            __kernel_ssize_t;
10123 +typedef int            __kernel_ptrdiff_t;
10124 +typedef long           __kernel_time_t;
10125 +typedef long           __kernel_suseconds_t;
10126 +typedef long           __kernel_clock_t;
10127 +typedef int            __kernel_timer_t;
10128 +typedef int            __kernel_clockid_t;
10129 +typedef int            __kernel_daddr_t;
10130 +typedef char *         __kernel_caddr_t;
10131 +typedef unsigned short __kernel_uid16_t;
10132 +typedef unsigned short __kernel_gid16_t;
10133 +typedef unsigned int   __kernel_uid32_t;
10134 +typedef unsigned int   __kernel_gid32_t;
10135 +
10136 +typedef unsigned short __kernel_old_uid_t;
10137 +typedef unsigned short __kernel_old_gid_t;
10138 +typedef unsigned short __kernel_old_dev_t;
10139 +
10140 +#ifdef __GNUC__
10141 +typedef long long      __kernel_loff_t;
10142 +#endif
10143 +
10144 +typedef struct {
10145 +#if defined(__KERNEL__) || defined(__USE_ALL)
10146 +       int     val[2];
10147 +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10148 +       int     __val[2];
10149 +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10150 +} __kernel_fsid_t;
10151 +
10152 +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
10153 +
10154 +#undef __FD_SET
10155 +#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
10156 +
10157 +#undef __FD_CLR
10158 +#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
10159 +
10160 +#undef __FD_ISSET
10161 +#define        __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
10162 +
10163 +#undef __FD_ZERO
10164 +#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
10165 +
10166 +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
10167 +
10168 +#endif
10169 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/processor.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/processor.h
10170 --- linux-2.6.30.10/arch/ubicom32/include/asm/processor.h       1970-01-01 02:00:00.000000000 +0200
10171 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/processor.h   2009-12-11 11:45:11.000000000 +0200
10172 @@ -0,0 +1,163 @@
10173 +/*
10174 + * arch/ubicom32/include/asm/processor.h
10175 + *   Thread related definitions for Ubicom32 architecture.
10176 + *
10177 + * (C) Copyright 2009, Ubicom, Inc.
10178 + * Copyright (C) 1995 Hamish Macdonald
10179 + *
10180 + * This file is part of the Ubicom32 Linux Kernel Port.
10181 + *
10182 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10183 + * it and/or modify it under the terms of the GNU General Public License
10184 + * as published by the Free Software Foundation, either version 2 of the
10185 + * License, or (at your option) any later version.
10186 + *
10187 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10188 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10189 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10190 + * the GNU General Public License for more details.
10191 + *
10192 + * You should have received a copy of the GNU General Public License
10193 + * along with the Ubicom32 Linux Kernel Port.  If not,
10194 + * see <http://www.gnu.org/licenses/>.
10195 + *
10196 + * Ubicom32 implementation derived from (with many thanks):
10197 + *   arch/m68knommu
10198 + *   arch/blackfin
10199 + *   arch/parisc
10200 + */
10201 +
10202 +#ifndef _ASM_UBICOM32_PROCESSOR_H
10203 +#define _ASM_UBICOM32_PROCESSOR_H
10204 +
10205 +/*
10206 + * Default implementation of macro that returns current
10207 + * instruction pointer ("program counter").
10208 + */
10209 +#define current_text_addr() ({ __label__ _l; _l: &&_l;})
10210 +
10211 +#include <linux/compiler.h>
10212 +#include <linux/threads.h>
10213 +#include <asm/types.h>
10214 +#include <asm/segment.h>
10215 +#include <asm/fpu.h>
10216 +#include <asm/ptrace.h>
10217 +#include <asm/current.h>
10218 +#include <asm/thread_info.h>
10219 +
10220 +#if defined(CONFIG_UBICOM32_V3)
10221 +       #define CPU "IP5K"
10222 +#endif
10223 +#if defined(CONFIG_UBICOM32_V4)
10224 +       #define CPU "IP7K"
10225 +#endif
10226 +#ifndef CPU
10227 +       #define CPU "UNKNOWN"
10228 +#endif
10229 +
10230 +/*
10231 + * User space process size: 1st byte beyond user address space.
10232 + */
10233 +extern unsigned long memory_end;
10234 +#define TASK_SIZE      (memory_end)
10235 +
10236 +/*
10237 + * This decides where the kernel will search for a free chunk of vm
10238 + * space during mmap's. We won't be using it
10239 + */
10240 +#define TASK_UNMAPPED_BASE     0
10241 +
10242 +/*
10243 + * This is the structure where we are going to save callee-saved registers.
10244 + * A5 is the return address, A7 is the stack pointer, A6 is the frame
10245 + * pointer.  This is the frame that is created because of switch_to. This
10246 + * is not the frame due to interrupt preemption or because of syscall entry.
10247 + */
10248 +
10249 +struct thread_struct {
10250 +       unsigned long  d10;             /* D10  */
10251 +       unsigned long  d11;             /* D11  */
10252 +       unsigned long  d12;             /* D12  */
10253 +       unsigned long  d13;             /* D13  */
10254 +       unsigned long  a1;              /* A1  */
10255 +       unsigned long  a2;              /* A2  */
10256 +       unsigned long  a5;              /* A5 return address. */
10257 +       unsigned long  a6;              /* A6 */
10258 +       unsigned long  sp;              /* A7 kernel stack pointer. */
10259 +};
10260 +
10261 +#define INIT_THREAD  { \
10262 +       0, 0, 0, 0, 0, 0, 0, 0, \
10263 +       sizeof(init_stack) + (unsigned long) init_stack - 8, \
10264 +}
10265 +
10266 +/*
10267 + * Do necessary setup to start up a newly executed thread.
10268 + *
10269 + * pass the data segment into user programs if it exists,
10270 + * it can't hurt anything as far as I can tell
10271 + */
10272 +/*
10273 + * Do necessary setup to start up a newly executed thread.
10274 + */
10275 +#define start_thread(regs, new_pc, new_sp)      \
10276 +       do {                                     \
10277 +               regs->pc = new_pc & ~3;          \
10278 +               regs->an[5] = new_pc & ~3;       \
10279 +               regs->an[7] = new_sp;            \
10280 +               regs->nesting_level = -1;        \
10281 +               regs->frame_type = UBICOM32_FRAME_TYPE_NEW_THREAD; \
10282 +               regs->thread_type = NORMAL_THREAD; \
10283 +       } while(0)
10284 +
10285 +/* Forward declaration, a strange C thing */
10286 +struct task_struct;
10287 +
10288 +/* Free all resources held by a thread. */
10289 +static inline void release_thread(struct task_struct *dead_task)
10290 +{
10291 +}
10292 +
10293 +/* Prepare to copy thread state - unlazy all lazy status */
10294 +#define prepare_to_copy(tsk)   do { } while (0)
10295 +
10296 +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
10297 +
10298 +/*
10299 + * Free current thread data structures etc..
10300 + */
10301 +static inline void exit_thread(void)
10302 +{
10303 +}
10304 +
10305 +unsigned long thread_saved_pc(struct task_struct *tsk);
10306 +unsigned long get_wchan(struct task_struct *p);
10307 +
10308 +#define        KSTK_EIP(tsk)   (tsk->thread.a5)
10309 +#define        KSTK_ESP(tsk)   (tsk->thread.sp)
10310 +
10311 +#define cpu_relax()    barrier()
10312 +
10313 +extern void processor_init(void);
10314 +extern unsigned int processor_timers(void);
10315 +extern unsigned int processor_threads(void);
10316 +extern unsigned int processor_frequency(void);
10317 +extern int processor_interrupts(unsigned int *int0, unsigned int *int1);
10318 +extern void processor_ocm(unsigned long *socm, unsigned long *eocm);
10319 +extern void processor_dram(unsigned long *sdram, unsigned long *edram);
10320 +
10321 +#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
10322 +#define KSTK_TOP(info)                                                 \
10323 +({                                                                     \
10324 +       unsigned long *__ptr = (unsigned long *)(info);                 \
10325 +       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
10326 +})
10327 +
10328 +#define task_pt_regs(task)                                             \
10329 +({                                                                     \
10330 +       struct pt_regs *__regs__;                                       \
10331 +       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
10332 +       __regs__ - 1;                                                   \
10333 +})
10334 +
10335 +#endif /* _ASM_UBICOM32_PROCESSOR_H */
10336 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/profilesample.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/profilesample.h
10337 --- linux-2.6.30.10/arch/ubicom32/include/asm/profilesample.h   1970-01-01 02:00:00.000000000 +0200
10338 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/profilesample.h       2009-12-11 11:45:11.000000000 +0200
10339 @@ -0,0 +1,44 @@
10340 +/*
10341 + * arch/ubicom32/mach-common/profile.h
10342 + *   Private data for the profile module
10343 + *
10344 + * (C) Copyright 2009, Ubicom, Inc.
10345 + *
10346 + * This file is part of the Ubicom32 Linux Kernel Port.
10347 + *
10348 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10349 + * it and/or modify it under the terms of the GNU General Public License
10350 + * as published by the Free Software Foundation, either version 2 of the
10351 + * License, or (at your option) any later version.
10352 + *
10353 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10354 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10355 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10356 + * the GNU General Public License for more details.
10357 + *
10358 + * You should have received a copy of the GNU General Public License
10359 + * along with the Ubicom32 Linux Kernel Port.  If not,
10360 + * see <http://www.gnu.org/licenses/>.
10361 + *
10362 + */
10363 +
10364 +
10365 +#ifndef _PROFILESAMPLE_H_
10366 +#define _PROFILESAMPLE_H_
10367 +
10368 +/*
10369 + * a sample taken by the ipProfile package for sending to the profilertool
10370 + */
10371 +struct profile_sample {
10372 +       unsigned int pc;                        /* PC value */
10373 +       unsigned int a5;                        /* a5 contents for parent of leaf function */
10374 +       unsigned int parent;                    /* return address from stack, to find the caller */
10375 +       unsigned int latency;                   /* CPU clocks since the last message dispatch in this thread (thread 0 ony for now) */
10376 +       unsigned short active;                  /* which threads are active - for accurate counting */
10377 +       unsigned short d_blocked;               /* which threads are blocked due to D cache misses */
10378 +       unsigned short i_blocked;               /* which threads are blocked due to I cache misses */
10379 +       unsigned char cond_codes;               /* for branch prediction */
10380 +       unsigned char thread;                   /* I-blocked, D-blocked, 4-bit thread number */
10381 +};
10382 +
10383 +#endif
10384 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ptrace.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ptrace.h
10385 --- linux-2.6.30.10/arch/ubicom32/include/asm/ptrace.h  1970-01-01 02:00:00.000000000 +0200
10386 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ptrace.h      2009-12-11 11:45:11.000000000 +0200
10387 @@ -0,0 +1,177 @@
10388 +/*
10389 + * arch/ubicom32/include/asm/ptrace.h
10390 + *   Ubicom32 architecture ptrace support.
10391 + *
10392 + * (C) Copyright 2009, Ubicom, Inc.
10393 + *
10394 + * This file is part of the Ubicom32 Linux Kernel Port.
10395 + *
10396 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10397 + * it and/or modify it under the terms of the GNU General Public License
10398 + * as published by the Free Software Foundation, either version 2 of the
10399 + * License, or (at your option) any later version.
10400 + *
10401 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10402 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10403 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10404 + * the GNU General Public License for more details.
10405 + *
10406 + * You should have received a copy of the GNU General Public License
10407 + * along with the Ubicom32 Linux Kernel Port.  If not,
10408 + * see <http://www.gnu.org/licenses/>.
10409 + *
10410 + * Ubicom32 implementation derived from (with many thanks):
10411 + *   arch/m68knommu
10412 + *   arch/blackfin
10413 + *   arch/parisc
10414 + */
10415 +#ifndef _ASM_UBICOM32_PTRACE_H
10416 +#define _ASM_UBICOM32_PTRACE_H
10417 +
10418 +#ifndef __ASSEMBLY__
10419 +
10420 +/*
10421 + * We use hard coded constants because this is shared with user
10422 + * space and the values are NOT allowed to change.  Only fields
10423 + * that are intended to be exposed get values.
10424 + */
10425 +#define PT_D0           0
10426 +#define PT_D1           4
10427 +#define PT_D2           8
10428 +#define PT_D3           12
10429 +#define PT_D4           16
10430 +#define PT_D5           20
10431 +#define PT_D6           24
10432 +#define PT_D7           28
10433 +#define PT_D8           32
10434 +#define PT_D9           36
10435 +#define PT_D10          40
10436 +#define PT_D11          44
10437 +#define PT_D12          48
10438 +#define PT_D13          52
10439 +#define PT_D14          56
10440 +#define PT_D15          60
10441 +#define PT_A0           64
10442 +#define PT_A1           68
10443 +#define PT_A2           72
10444 +#define PT_A3           76
10445 +#define PT_A4           80
10446 +#define PT_A5           84
10447 +#define PT_A6           88
10448 +#define PT_A7           92
10449 +#define PT_SP           92
10450 +#define PT_ACC0HI       96
10451 +#define PT_ACC0LO       100
10452 +#define PT_MAC_RC16     104
10453 +#define PT_ACC1HI       108
10454 +#define PT_ACC1LO       112
10455 +#define PT_SOURCE3      116
10456 +#define PT_INST_CNT     120
10457 +#define PT_CSR          124
10458 +#define PT_DUMMY_UNUSED 128
10459 +#define PT_INT_MASK0    132
10460 +#define PT_INT_MASK1    136
10461 +#define PT_TRAP_CAUSE   140
10462 +#define PT_PC           144
10463 +#define PT_ORIGINAL_D0  148
10464 +#define PT_FRAME_TYPE   152
10465 +
10466 +/*
10467 + * The following 'registers' are not registers at all but are used
10468 + * locate the relocated sections.
10469 + */
10470 +#define PT_TEXT_ADDR           200
10471 +#define PT_TEXT_END_ADDR       204
10472 +#define PT_DATA_ADDR           208
10473 +#define PT_EXEC_FDPIC_LOADMAP  212
10474 +#define PT_INTERP_FDPIC_LOADMAP        216
10475 +
10476 +/*
10477 + * This struct defines the way the registers are stored on the
10478 + * stack during a system call.
10479 + */
10480 +enum thread_type {
10481 +       NORMAL_THREAD,
10482 +       KERNEL_THREAD,
10483 +};
10484 +
10485 +#define UBICOM32_FRAME_TYPE_SYSCALL    -1 /* System call frame */
10486 +#define UBICOM32_FRAME_TYPE_INVALID    0 /* Invalid frame, no longer in use */
10487 +#define UBICOM32_FRAME_TYPE_INTERRUPT  1 /* Interrupt frame */
10488 +#define UBICOM32_FRAME_TYPE_TRAP       2 /* Trap frame */
10489 +#define UBICOM32_FRAME_TYPE_SIGTRAMP   3 /* Signal trampoline frame. */
10490 +#define UBICOM32_FRAME_TYPE_NEW_THREAD 4 /* New Thread. */
10491 +
10492 +struct pt_regs {
10493 +       /*
10494 +        * Data Registers
10495 +        */
10496 +       unsigned long dn[16];
10497 +
10498 +       /*
10499 +        * Address Registers
10500 +        */
10501 +       unsigned long an[8];
10502 +
10503 +       /*
10504 +        * Per thread misc registers.
10505 +        */
10506 +       unsigned long acc0[2];
10507 +       unsigned long mac_rc16;
10508 +       unsigned long acc1[2];
10509 +       unsigned long source3;
10510 +       unsigned long inst_cnt;
10511 +       unsigned long csr;
10512 +       unsigned long dummy_unused;
10513 +       unsigned long int_mask0;
10514 +       unsigned long int_mask1;
10515 +       unsigned long trap_cause;
10516 +       unsigned long pc;
10517 +       unsigned long original_dn_0;
10518 +
10519 +       /*
10520 +        * Frame type. Syscall frames are -1. For other types look above.
10521 +        */
10522 +       unsigned long frame_type;
10523 +
10524 +       /*
10525 +        * These fields are not exposed to ptrace.
10526 +        */
10527 +       unsigned long previous_pc;
10528 +       long nesting_level;             /* When the kernel in in user space this
10529 +                                        * will be -1. */
10530 +       unsigned long thread_type;      /* This indicates if this is a kernel
10531 +                                        * thread. */
10532 +};
10533 +
10534 +/*
10535 + * This is the extended stack used by signal handlers and the context
10536 + * switcher: it's pushed after the normal "struct pt_regs".
10537 + */
10538 +struct switch_stack {
10539 +       unsigned long  dummy;
10540 +};
10541 +
10542 +#ifdef __KERNEL__
10543 +
10544 +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
10545 +#define PTRACE_GETREGS         12
10546 +#define PTRACE_SETREGS         13
10547 +
10548 +#ifndef PS_S
10549 +#define PS_S  (0x2000)
10550 +#define PS_M  (0x1000)
10551 +#endif
10552 +
10553 +extern  int __user_mode(unsigned long sp);
10554 +
10555 +#define user_mode(regs) (__user_mode((regs->an[7])))
10556 +#define user_stack(regs) ((regs)->an[7])
10557 +#define instruction_pointer(regs) ((regs)->pc)
10558 +#define profile_pc(regs) instruction_pointer(regs)
10559 +extern void show_regs(struct pt_regs *);
10560 +#endif /* __KERNEL__ */
10561 +
10562 +#endif /* __ASSEMBLY__ */
10563 +
10564 +#endif /* _ASM_UBICOM32_PTRACE_H */
10565 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/range-protect-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect-asm.h
10566 --- linux-2.6.30.10/arch/ubicom32/include/asm/range-protect-asm.h       1970-01-01 02:00:00.000000000 +0200
10567 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect-asm.h   2009-12-11 11:45:11.000000000 +0200
10568 @@ -0,0 +1,91 @@
10569 +/*
10570 + * arch/ubicom32/include/asm/range-protect-asm.h
10571 + *   Assembly macros for enabling memory protection.
10572 + *
10573 + * (C) Copyright 2009, Ubicom, Inc.
10574 + *
10575 + * This file is part of the Ubicom32 Linux Kernel Port.
10576 + *
10577 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10578 + * it and/or modify it under the terms of the GNU General Public License
10579 + * as published by the Free Software Foundation, either version 2 of the
10580 + * License, or (at your option) any later version.
10581 + *
10582 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10583 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10584 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10585 + * the GNU General Public License for more details.
10586 + *
10587 + * You should have received a copy of the GNU General Public License
10588 + * along with the Ubicom32 Linux Kernel Port.  If not,
10589 + * see <http://www.gnu.org/licenses/>.
10590 + *
10591 + * Ubicom32 implementation derived from (with many thanks):
10592 + *   arch/m68knommu
10593 + *   arch/blackfin
10594 + *   arch/parisc
10595 + */
10596 +
10597 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10598 +#define _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10599 +
10600 +#if defined(__ASSEMBLY__)
10601 +
10602 +#include <asm/thread-asm.h>
10603 +
10604 +/*
10605 + * You should only use the enable/disable ranges when you have the atomic lock,
10606 + * if you do not there will be problems.
10607 + */
10608 +
10609 +/*
10610 + * enable_kernel_ranges
10611 + *     Enable the kernel ranges (disabling protection) for thread,
10612 + *     where thread == (1 << thread number)
10613 + */
10614 +.macro enable_kernel_ranges thread
10615 +#ifdef CONFIG_PROTECT_KERNEL
10616 +       or.4    I_RANGE0_EN, I_RANGE0_EN, \thread        /* Enable Range Register */
10617 +       or.4    D_RANGE0_EN, D_RANGE0_EN, \thread
10618 +       or.4    D_RANGE1_EN, D_RANGE1_EN, \thread
10619 +#endif
10620 +.endm
10621 +
10622 +/*
10623 + * enable_kernel_ranges_for_current
10624 + *     Enable the kernel ranges (disabling protection) for this thread
10625 + */
10626 +.macro enable_kernel_ranges_for_current scratch_reg
10627 +#ifdef CONFIG_PROTECT_KERNEL
10628 +       thread_get_self_mask \scratch_reg
10629 +       enable_kernel_ranges \scratch_reg
10630 +#endif
10631 +.endm
10632 +
10633 +/*
10634 + * disable_kernel_ranges
10635 + *     Disables the kernel ranges (enabling protection) for thread
10636 + *     where thread == (1 << thread number)
10637 + */
10638 +.macro disable_kernel_ranges thread
10639 +#ifdef CONFIG_PROTECT_KERNEL
10640 +       not.4   \thread, \thread
10641 +       and.4   I_RANGE0_EN, I_RANGE0_EN, \thread        /* Disable Range Register */
10642 +       and.4   D_RANGE0_EN, D_RANGE0_EN, \thread
10643 +       and.4   D_RANGE1_EN, D_RANGE1_EN, \thread
10644 +#endif
10645 +.endm
10646 +
10647 +/*
10648 + * disable_kernel_ranges_for_current
10649 + *     Disable kernel ranges (enabling protection) for this thread
10650 + */
10651 +.macro disable_kernel_ranges_for_current scratch_reg
10652 +#ifdef CONFIG_PROTECT_KERNEL
10653 +       thread_get_self_mask \scratch_reg
10654 +       disable_kernel_ranges \scratch_reg
10655 +#endif
10656 +.endm
10657 +#endif
10658 +
10659 +#endif  /* _ASM_UBICOM32_RANGE_PROTECT_ASM_H */
10660 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/range-protect.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect.h
10661 --- linux-2.6.30.10/arch/ubicom32/include/asm/range-protect.h   1970-01-01 02:00:00.000000000 +0200
10662 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect.h       2009-12-11 11:45:11.000000000 +0200
10663 @@ -0,0 +1,62 @@
10664 +/*
10665 + * arch/ubicom32/include/asm/range-protect.h
10666 + *   Assembly macros declared in C for enabling memory protection.
10667 + *
10668 + * (C) Copyright 2009, Ubicom, Inc.
10669 + *
10670 + * This file is part of the Ubicom32 Linux Kernel Port.
10671 + *
10672 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10673 + * it and/or modify it under the terms of the GNU General Public License
10674 + * as published by the Free Software Foundation, either version 2 of the
10675 + * License, or (at your option) any later version.
10676 + *
10677 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10678 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10679 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10680 + * the GNU General Public License for more details.
10681 + *
10682 + * You should have received a copy of the GNU General Public License
10683 + * along with the Ubicom32 Linux Kernel Port.  If not,
10684 + * see <http://www.gnu.org/licenses/>.
10685 + *
10686 + * Ubicom32 implementation derived from (with many thanks):
10687 + *   arch/m68knommu
10688 + *   arch/blackfin
10689 + *   arch/parisc
10690 + */
10691 +
10692 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_H
10693 +#define _ASM_UBICOM32_RANGE_PROTECT_H
10694 +
10695 +#if !defined(__ASSEMBLY__)
10696 +#include <asm/thread.h>
10697 +/*
10698 + * The following macros should be the identical to the ones in
10699 + * range-protect-asm.h
10700 + *
10701 + * You should only use the enable/disable ranges when you have the atomic lock,
10702 + * if you do not there will be problems.
10703 + */
10704 +
10705 +/*
10706 + * enable_kernel_ranges
10707 + *     Enable the kernel ranges (disabling protection) for thread,
10708 + *     where thread == (1 << thread number)
10709 + */
10710 +asm (
10711 +       ".macro enable_kernel_ranges thread                     \n\t"
10712 +#ifdef CONFIG_PROTECT_KERNEL
10713 +       "       or.4    I_RANGE0_EN, I_RANGE0_EN, \\thread      \n\t" /* Enable Range Register */
10714 +       "       or.4    D_RANGE0_EN, D_RANGE0_EN, \\thread      \n\t"
10715 +       "       or.4    D_RANGE1_EN, D_RANGE1_EN, \\thread      \n\t"
10716 +#endif
10717 +       ".endm                                                  \n\t"
10718 +);
10719 +
10720 +#else /* __ASSEMBLY__ */
10721 +
10722 +#include <asm/range-protect-asm.h>
10723 +
10724 +#endif
10725 +#endif  /* _ASM_UBICOM32_RANGE_PROTECT_H */
10726 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/resource.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/resource.h
10727 --- linux-2.6.30.10/arch/ubicom32/include/asm/resource.h        1970-01-01 02:00:00.000000000 +0200
10728 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/resource.h    2009-12-11 11:45:11.000000000 +0200
10729 @@ -0,0 +1,33 @@
10730 +/*
10731 + * arch/ubicom32/include/asm/resource.h
10732 + *   Generic definitions for Ubicom32 architecture.
10733 + *
10734 + * (C) Copyright 2009, Ubicom, Inc.
10735 + *
10736 + * This file is part of the Ubicom32 Linux Kernel Port.
10737 + *
10738 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10739 + * it and/or modify it under the terms of the GNU General Public License
10740 + * as published by the Free Software Foundation, either version 2 of the
10741 + * License, or (at your option) any later version.
10742 + *
10743 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10744 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10745 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10746 + * the GNU General Public License for more details.
10747 + *
10748 + * You should have received a copy of the GNU General Public License
10749 + * along with the Ubicom32 Linux Kernel Port.  If not,
10750 + * see <http://www.gnu.org/licenses/>.
10751 + *
10752 + * Ubicom32 implementation derived from (with many thanks):
10753 + *   arch/m68knommu
10754 + *   arch/blackfin
10755 + *   arch/parisc
10756 + */
10757 +#ifndef _ASM_UBICOM32_RESOURCE_H
10758 +#define _ASM_UBICOM32_RESOURCE_H
10759 +
10760 +#include <asm-generic/resource.h>
10761 +
10762 +#endif /* _ASM_UBICOM32_RESOURCE_H */
10763 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ring_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ring_tio.h
10764 --- linux-2.6.30.10/arch/ubicom32/include/asm/ring_tio.h        1970-01-01 02:00:00.000000000 +0200
10765 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ring_tio.h    2009-12-11 11:45:11.000000000 +0200
10766 @@ -0,0 +1,42 @@
10767 +/*
10768 + * arch/ubicom32/include/asm/ring_tio.h
10769 + *   Ubicom32 architecture Ring TIO definitions.
10770 + *
10771 + * (C) Copyright 2009, Ubicom, Inc.
10772 + *
10773 + * This file is part of the Ubicom32 Linux Kernel Port.
10774 + *
10775 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10776 + * it and/or modify it under the terms of the GNU General Public License
10777 + * as published by the Free Software Foundation, either version 2 of the
10778 + * License, or (at your option) any later version.
10779 + *
10780 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10781 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10782 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10783 + * the GNU General Public License for more details.
10784 + *
10785 + * You should have received a copy of the GNU General Public License
10786 + * along with the Ubicom32 Linux Kernel Port.  If not,
10787 + * see <http://www.gnu.org/licenses/>.
10788 + */
10789 +#ifndef _ASM_UBICOM32_RING_TIO_H
10790 +#define _ASM_UBICOM32_RING_TIO_H
10791 +
10792 +#include <asm/devtree.h>
10793 +
10794 +#define RING_TIO_NODE_VERSION  2
10795 +
10796 +/*
10797 + * Devtree node for ring
10798 + */
10799 +struct ring_tio_node {
10800 +       struct devtree_node     dn;
10801 +
10802 +       u32_t                   version;
10803 +       void                    *regs;
10804 +};
10805 +
10806 +extern void ring_tio_init(const char *node_name);
10807 +
10808 +#endif /* _ASM_UBICOM32_RING_TIO_H */
10809 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/scatterlist.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/scatterlist.h
10810 --- linux-2.6.30.10/arch/ubicom32/include/asm/scatterlist.h     1970-01-01 02:00:00.000000000 +0200
10811 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/scatterlist.h 2009-12-11 11:45:11.000000000 +0200
10812 @@ -0,0 +1,49 @@
10813 +/*
10814 + * arch/ubicom32/include/asm/scatterlist.h
10815 + *   Definitions of struct scatterlist for Ubicom32 architecture.
10816 + *
10817 + * (C) Copyright 2009, Ubicom, Inc.
10818 + *
10819 + * This file is part of the Ubicom32 Linux Kernel Port.
10820 + *
10821 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10822 + * it and/or modify it under the terms of the GNU General Public License
10823 + * as published by the Free Software Foundation, either version 2 of the
10824 + * License, or (at your option) any later version.
10825 + *
10826 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10827 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10828 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10829 + * the GNU General Public License for more details.
10830 + *
10831 + * You should have received a copy of the GNU General Public License
10832 + * along with the Ubicom32 Linux Kernel Port.  If not,
10833 + * see <http://www.gnu.org/licenses/>.
10834 + *
10835 + * Ubicom32 implementation derived from (with many thanks):
10836 + *   arch/m68knommu
10837 + *   arch/blackfin
10838 + *   arch/parisc
10839 + */
10840 +#ifndef _ASM_UBICOM32_SCATTERLIST_H
10841 +#define _ASM_UBICOM32_SCATTERLIST_H
10842 +
10843 +#include <linux/mm.h>
10844 +#include <asm/types.h>
10845 +
10846 +struct scatterlist {
10847 +#ifdef CONFIG_DEBUG_SG
10848 +       unsigned long   sg_magic;
10849 +#endif
10850 +       unsigned long   page_link;
10851 +       unsigned int    offset;
10852 +       dma_addr_t      dma_address;
10853 +       unsigned int    length;
10854 +};
10855 +
10856 +#define sg_dma_address(sg)      ((sg)->dma_address)
10857 +#define sg_dma_len(sg)          ((sg)->length)
10858 +
10859 +#define ISA_DMA_THRESHOLD      (0xffffffff)
10860 +
10861 +#endif /* _ASM_UBICOM32_SCATTERLIST_H */
10862 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sd_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sd_tio.h
10863 --- linux-2.6.30.10/arch/ubicom32/include/asm/sd_tio.h  1970-01-01 02:00:00.000000000 +0200
10864 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sd_tio.h      2009-12-11 11:45:11.000000000 +0200
10865 @@ -0,0 +1,36 @@
10866 +/*
10867 + * arch/ubicom32/include/asm/sd_tio.h
10868 + *   SD TIO definitions
10869 + *
10870 + * (C) Copyright 2009, Ubicom, Inc.
10871 + *
10872 + * This file is part of the Ubicom32 Linux Kernel Port.
10873 + *
10874 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10875 + * it and/or modify it under the terms of the GNU General Public License
10876 + * as published by the Free Software Foundation, either version 2 of the
10877 + * License, or (at your option) any later version.
10878 + *
10879 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10880 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10881 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10882 + * the GNU General Public License for more details.
10883 + *
10884 + * You should have received a copy of the GNU General Public License
10885 + * along with the Ubicom32 Linux Kernel Port.  If not,
10886 + * see <http://www.gnu.org/licenses/>.
10887 + */
10888 +#ifndef _ASM_UBICOM32_SD_TIO_H
10889 +#define _ASM_UBICOM32_SD_TIO_H
10890 +
10891 +#include <asm/devtree.h>
10892 +
10893 +/*
10894 + * Devtree node for SD
10895 + */
10896 +struct sd_tio_node {
10897 +       struct devtree_node     dn;
10898 +       void                    *regs;
10899 +};
10900 +
10901 +#endif /* _ASM_UBICOM32_SD_TIO_H */
10902 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sections.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sections.h
10903 --- linux-2.6.30.10/arch/ubicom32/include/asm/sections.h        1970-01-01 02:00:00.000000000 +0200
10904 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sections.h    2009-12-11 11:45:11.000000000 +0200
10905 @@ -0,0 +1,33 @@
10906 +/*
10907 + * arch/ubicom32/include/asm/sections.h
10908 + *   Generic sections.h definitions for Ubicom32 architecture.
10909 + *
10910 + * (C) Copyright 2009, Ubicom, Inc.
10911 + *
10912 + * This file is part of the Ubicom32 Linux Kernel Port.
10913 + *
10914 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10915 + * it and/or modify it under the terms of the GNU General Public License
10916 + * as published by the Free Software Foundation, either version 2 of the
10917 + * License, or (at your option) any later version.
10918 + *
10919 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10920 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10921 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10922 + * the GNU General Public License for more details.
10923 + *
10924 + * You should have received a copy of the GNU General Public License
10925 + * along with the Ubicom32 Linux Kernel Port.  If not,
10926 + * see <http://www.gnu.org/licenses/>.
10927 + *
10928 + * Ubicom32 implementation derived from (with many thanks):
10929 + *   arch/m68knommu
10930 + *   arch/blackfin
10931 + *   arch/parisc
10932 + */
10933 +#ifndef _ASM_UBICOM32_SECTIONS_H
10934 +#define _ASM_UBICOM32_SECTIONS_H
10935 +
10936 +#include <asm-generic/sections.h>
10937 +
10938 +#endif /* _ASM_UBICOM32_SECTIONS_H */
10939 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/segment.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/segment.h
10940 --- linux-2.6.30.10/arch/ubicom32/include/asm/segment.h 1970-01-01 02:00:00.000000000 +0200
10941 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/segment.h     2009-12-11 11:45:11.000000000 +0200
10942 @@ -0,0 +1,78 @@
10943 +/*
10944 + * arch/ubicom32/include/asm/segment.h
10945 + *   Memory segment definitions for Ubicom32 architecture.
10946 + *
10947 + * (C) Copyright 2009, Ubicom, Inc.
10948 + *
10949 + * This file is part of the Ubicom32 Linux Kernel Port.
10950 + *
10951 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10952 + * it and/or modify it under the terms of the GNU General Public License
10953 + * as published by the Free Software Foundation, either version 2 of the
10954 + * License, or (at your option) any later version.
10955 + *
10956 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10957 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10958 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10959 + * the GNU General Public License for more details.
10960 + *
10961 + * You should have received a copy of the GNU General Public License
10962 + * along with the Ubicom32 Linux Kernel Port.  If not,
10963 + * see <http://www.gnu.org/licenses/>.
10964 + *
10965 + * Ubicom32 implementation derived from (with many thanks):
10966 + *   arch/m68knommu
10967 + *   arch/blackfin
10968 + *   arch/parisc
10969 + */
10970 +#ifndef _ASM_UBICOM32_SEGMENT_H
10971 +#define _ASM_UBICOM32_SEGMENT_H
10972 +
10973 +/* define constants */
10974 +/* Address spaces (FC0-FC2) */
10975 +#define USER_DATA     (1)
10976 +#ifndef __USER_DS
10977 +#define __USER_DS     (USER_DATA)
10978 +#endif
10979 +#define USER_PROGRAM  (2)
10980 +#define SUPER_DATA    (5)
10981 +#ifndef __KERNEL_DS
10982 +#define __KERNEL_DS   (SUPER_DATA)
10983 +#endif
10984 +#define SUPER_PROGRAM (6)
10985 +#define CPU_SPACE     (7)
10986 +
10987 +#ifndef __ASSEMBLY__
10988 +
10989 +typedef struct {
10990 +       unsigned long seg;
10991 +} mm_segment_t;
10992 +
10993 +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
10994 +#define USER_DS                MAKE_MM_SEG(__USER_DS)
10995 +#define KERNEL_DS      MAKE_MM_SEG(__KERNEL_DS)
10996 +
10997 +/*
10998 + * Get/set the SFC/DFC registers for MOVES instructions
10999 + */
11000 +
11001 +static inline mm_segment_t get_fs(void)
11002 +{
11003 +    return USER_DS;
11004 +}
11005 +
11006 +static inline mm_segment_t get_ds(void)
11007 +{
11008 +    /* return the supervisor data space code */
11009 +    return KERNEL_DS;
11010 +}
11011 +
11012 +static inline void set_fs(mm_segment_t val)
11013 +{
11014 +}
11015 +
11016 +#define segment_eq(a,b)        ((a).seg == (b).seg)
11017 +
11018 +#endif /* __ASSEMBLY__ */
11019 +
11020 +#endif /* _ASM_UBICOM32_SEGMENT_H */
11021 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/semaphore.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore.h
11022 --- linux-2.6.30.10/arch/ubicom32/include/asm/semaphore.h       1970-01-01 02:00:00.000000000 +0200
11023 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore.h   2009-12-11 11:45:11.000000000 +0200
11024 @@ -0,0 +1,140 @@
11025 +/*
11026 + * arch/ubicom32/include/asm/semaphore.h
11027 + *   Interrupt-safe semaphores for Ubicom32 architecture.
11028 + *
11029 + * (C) Copyright 2009, Ubicom, Inc.
11030 + * (C) Copyright 1996 Linus Torvalds
11031 + * m68k version by Andreas Schwab
11032 + * Copyright (C) 2004   Microtronix Datacom Ltd
11033 + *
11034 + * This file is part of the Ubicom32 Linux Kernel Port.
11035 + *
11036 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11037 + * it and/or modify it under the terms of the GNU General Public License
11038 + * as published by the Free Software Foundation, either version 2 of the
11039 + * License, or (at your option) any later version.
11040 + *
11041 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11042 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11043 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11044 + * the GNU General Public License for more details.
11045 + *
11046 + * You should have received a copy of the GNU General Public License
11047 + * along with the Ubicom32 Linux Kernel Port.  If not,
11048 + * see <http://www.gnu.org/licenses/>.
11049 + *
11050 + * Ubicom32 implementation derived from (with many thanks):
11051 + *   arch/m68knommu
11052 + *   arch/blackfin
11053 + *   arch/parisc
11054 + */
11055 +#ifndef _ASM_UBICOM32_SEMAPHORE_H
11056 +#define _ASM_UBICOM32_SEMAPHORE_H
11057 +
11058 +#define RW_LOCK_BIAS            0x01000000
11059 +
11060 +#ifndef __ASSEMBLY__
11061 +
11062 +#include <linux/linkage.h>
11063 +#include <linux/wait.h>
11064 +#include <linux/spinlock.h>
11065 +#include <linux/rwsem.h>
11066 +
11067 +#include <asm/system.h>
11068 +#include <asm/atomic.h>
11069 +
11070 +struct semaphore {
11071 +       atomic_t count;
11072 +       atomic_t waking;
11073 +       wait_queue_head_t wait;
11074 +};
11075 +
11076 +#define __SEMAPHORE_INITIALIZER(name, n)                               \
11077 +{                                                                      \
11078 +       .count          = ATOMIC_INIT(n),                               \
11079 +       .waking         = ATOMIC_INIT(0),                               \
11080 +       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
11081 +}
11082 +
11083 +#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
11084 +       struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
11085 +
11086 +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
11087 +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
11088 +
11089 +static inline void sema_init (struct semaphore *sem, int val)
11090 +{
11091 +       *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
11092 +}
11093 +
11094 +static inline void init_MUTEX (struct semaphore *sem)
11095 +{
11096 +       sema_init(sem, 1);
11097 +}
11098 +
11099 +static inline void init_MUTEX_LOCKED (struct semaphore *sem)
11100 +{
11101 +       sema_init(sem, 0);
11102 +}
11103 +
11104 +asmlinkage void __down_failed(void /* special register calling convention */);
11105 +asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
11106 +asmlinkage int  __down_failed_trylock(void  /* params in registers */);
11107 +asmlinkage void __up_wakeup(void /* special register calling convention */);
11108 +
11109 +asmlinkage void __down(struct semaphore * sem);
11110 +asmlinkage int  __down_interruptible(struct semaphore * sem);
11111 +asmlinkage int  __down_trylock(struct semaphore * sem);
11112 +asmlinkage void __up(struct semaphore * sem);
11113 +
11114 +extern spinlock_t semaphore_wake_lock;
11115 +
11116 +/*
11117 + * This is ugly, but we want the default case to fall through.
11118 + * "down_failed" is a special asm handler that calls the C
11119 + * routine that actually waits.
11120 + */
11121 +static inline void down(struct semaphore * sem)
11122 +{
11123 +       might_sleep();
11124 +
11125 +       if (atomic_dec_return(&sem->count) < 0)
11126 +               __down(sem);
11127 +}
11128 +
11129 +static inline int down_interruptible(struct semaphore * sem)
11130 +{
11131 +       int ret = 0;
11132 +
11133 +
11134 +       might_sleep();
11135 +
11136 +       if(atomic_dec_return(&sem->count) < 0)
11137 +               ret = __down_interruptible(sem);
11138 +       return ret;
11139 +}
11140 +
11141 +static inline int down_trylock(struct semaphore * sem)
11142 +{
11143 +       int ret = 0;
11144 +
11145 +       if (atomic_dec_return (&sem->count) < 0)
11146 +               ret = __down_trylock(sem);
11147 +       return ret;
11148 +}
11149 +
11150 +/*
11151 + * Note! This is subtle. We jump to wake people up only if
11152 + * the semaphore was negative (== somebody was waiting on it).
11153 + * The default case (no contention) will result in NO
11154 + * jumps for both down() and up().
11155 + */
11156 +static inline void up(struct semaphore * sem)
11157 +{
11158 +       if (atomic_inc_return(&sem->count) <= 0)
11159 +               __up(sem);
11160 +}
11161 +
11162 +#endif /* __ASSEMBLY__ */
11163 +
11164 +#endif /* _ASM_UBICOM32_SEMAPHORE_H */
11165 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/semaphore-helper.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore-helper.h
11166 --- linux-2.6.30.10/arch/ubicom32/include/asm/semaphore-helper.h        1970-01-01 02:00:00.000000000 +0200
11167 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore-helper.h    2009-12-11 11:45:11.000000000 +0200
11168 @@ -0,0 +1,109 @@
11169 +/*
11170 + * arch/ubicom32/include/asm/semaphore-helper.h
11171 + *   Semaphore related definitions for Ubicom32 architecture.
11172 + *
11173 + * (C) Copyright 2009, Ubicom, Inc.
11174 + *
11175 + * This file is part of the Ubicom32 Linux Kernel Port.
11176 + *
11177 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11178 + * it and/or modify it under the terms of the GNU General Public License
11179 + * as published by the Free Software Foundation, either version 2 of the
11180 + * License, or (at your option) any later version.
11181 + *
11182 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11183 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11184 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11185 + * the GNU General Public License for more details.
11186 + *
11187 + * You should have received a copy of the GNU General Public License
11188 + * along with the Ubicom32 Linux Kernel Port.  If not,
11189 + * see <http://www.gnu.org/licenses/>.
11190 + *
11191 + * Ubicom32 implementation derived from (with many thanks):
11192 + *   arch/m68knommu
11193 + *   arch/blackfin
11194 + *   arch/parisc
11195 + */
11196 +#ifndef _ASM_UBICOM32_SEMAPHORE_HELPER_H
11197 +#define _ASM_UBICOM32_SEMAPHORE_HELPER_H
11198 +
11199 +/*
11200 + * SMP- and interrupt-safe semaphores helper functions.
11201 + *
11202 + * (C) Copyright 1996 Linus Torvalds
11203 + *
11204 + * m68k version by Andreas Schwab
11205 + */
11206 +
11207 +
11208 +/*
11209 + * These two _must_ execute atomically wrt each other.
11210 + */
11211 +static inline void wake_one_more(struct semaphore * sem)
11212 +{
11213 +       atomic_inc(&sem->waking);
11214 +}
11215 +
11216 +static inline int waking_non_zero(struct semaphore *sem)
11217 +{
11218 +       int ret;
11219 +       unsigned long flags;
11220 +
11221 +       spin_lock_irqsave(&semaphore_wake_lock, flags);
11222 +       ret = 0;
11223 +       if (atomic_read(&sem->waking) > 0) {
11224 +               atomic_dec(&sem->waking);
11225 +               ret = 1;
11226 +       }
11227 +       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11228 +       return ret;
11229 +}
11230 +
11231 +/*
11232 + * waking_non_zero_interruptible:
11233 + *     1       got the lock
11234 + *     0       go to sleep
11235 + *     -EINTR  interrupted
11236 + */
11237 +static inline int waking_non_zero_interruptible(struct semaphore *sem,
11238 +                                               struct task_struct *tsk)
11239 +{
11240 +       int ret;
11241 +       unsigned long flags;
11242 +
11243 +       spin_lock_irqsave(&semaphore_wake_lock, flags);
11244 +       ret = 0;
11245 +       if (atomic_read(&sem->waking) > 0) {
11246 +               atomic_dec(&sem->waking);
11247 +               ret = 1;
11248 +       } else if (signal_pending(tsk)) {
11249 +               atomic_inc(&sem->count);
11250 +               ret = -EINTR;
11251 +       }
11252 +       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11253 +       return ret;
11254 +}
11255 +
11256 +/*
11257 + * waking_non_zero_trylock:
11258 + *     1       failed to lock
11259 + *     0       got the lock
11260 + */
11261 +static inline int waking_non_zero_trylock(struct semaphore *sem)
11262 +{
11263 +       int ret;
11264 +       unsigned long flags;
11265 +
11266 +       spin_lock_irqsave(&semaphore_wake_lock, flags);
11267 +       ret = 1;
11268 +       if (atomic_read(&sem->waking) > 0) {
11269 +               atomic_dec(&sem->waking);
11270 +               ret = 0;
11271 +       } else
11272 +               atomic_inc(&sem->count);
11273 +       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11274 +       return ret;
11275 +}
11276 +
11277 +#endif /* _ASM_UBICOM32_SEMAPHORE_HELPER_H */
11278 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sembuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sembuf.h
11279 --- linux-2.6.30.10/arch/ubicom32/include/asm/sembuf.h  1970-01-01 02:00:00.000000000 +0200
11280 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sembuf.h      2009-12-11 11:45:11.000000000 +0200
11281 @@ -0,0 +1,52 @@
11282 +/*
11283 + * arch/ubicom32/include/asm/sembuf.h
11284 + *   The semid64_ds structure for Ubicom32 architecture.
11285 + *
11286 + * (C) Copyright 2009, Ubicom, Inc.
11287 + *
11288 + * This file is part of the Ubicom32 Linux Kernel Port.
11289 + *
11290 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11291 + * it and/or modify it under the terms of the GNU General Public License
11292 + * as published by the Free Software Foundation, either version 2 of the
11293 + * License, or (at your option) any later version.
11294 + *
11295 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11296 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11297 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11298 + * the GNU General Public License for more details.
11299 + *
11300 + * You should have received a copy of the GNU General Public License
11301 + * along with the Ubicom32 Linux Kernel Port.  If not,
11302 + * see <http://www.gnu.org/licenses/>.
11303 + *
11304 + * Ubicom32 implementation derived from (with many thanks):
11305 + *   arch/m68knommu
11306 + *   arch/blackfin
11307 + *   arch/parisc
11308 + */
11309 +#ifndef _ASM_UBICOM32_SEMBUF_H
11310 +#define _ASM_UBICOM32_SEMBUF_H
11311 +
11312 +/*
11313 + * The semid64_ds structure for ubicom32 architecture.
11314 + * Note extra padding because this structure is passed back and forth
11315 + * between kernel and user space.
11316 + *
11317 + * Pad space is left for:
11318 + * - 64-bit time_t to solve y2038 problem
11319 + * - 2 miscellaneous 32-bit values
11320 + */
11321 +
11322 +struct semid64_ds {
11323 +       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
11324 +       __kernel_time_t sem_otime;              /* last semop time */
11325 +       unsigned long   __unused1;
11326 +       __kernel_time_t sem_ctime;              /* last change time */
11327 +       unsigned long   __unused2;
11328 +       unsigned long   sem_nsems;              /* no. of semaphores in array */
11329 +       unsigned long   __unused3;
11330 +       unsigned long   __unused4;
11331 +};
11332 +
11333 +#endif /* _ASM_UBICOM32_SEMBUF_H */
11334 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/setup.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/setup.h
11335 --- linux-2.6.30.10/arch/ubicom32/include/asm/setup.h   1970-01-01 02:00:00.000000000 +0200
11336 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/setup.h       2009-12-11 11:45:11.000000000 +0200
11337 @@ -0,0 +1,35 @@
11338 +/*
11339 + * arch/ubicom32/include/asm/setup.h
11340 + *   Kernel command line length definition.
11341 + *
11342 + * (C) Copyright 2009, Ubicom, Inc.
11343 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
11344 + *
11345 + * This file is part of the Ubicom32 Linux Kernel Port.
11346 + *
11347 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11348 + * it and/or modify it under the terms of the GNU General Public License
11349 + * as published by the Free Software Foundation, either version 2 of the
11350 + * License, or (at your option) any later version.
11351 + *
11352 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11353 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11354 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11355 + * the GNU General Public License for more details.
11356 + *
11357 + * You should have received a copy of the GNU General Public License
11358 + * along with the Ubicom32 Linux Kernel Port.  If not,
11359 + * see <http://www.gnu.org/licenses/>.
11360 + *
11361 + * Ubicom32 implementation derived from (with many thanks):
11362 + *   arch/m68knommu
11363 + *   arch/blackfin
11364 + *   arch/parisc
11365 + */
11366 +
11367 +#ifndef _ASM_UBICOM32_SETUP_H
11368 +#define _ASM_UBICOM32_SETUP_H
11369 +
11370 +#define COMMAND_LINE_SIZE 512
11371 +
11372 +#endif /* _ASM_UBICOM32_SETUP_H */
11373 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/shmbuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmbuf.h
11374 --- linux-2.6.30.10/arch/ubicom32/include/asm/shmbuf.h  1970-01-01 02:00:00.000000000 +0200
11375 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmbuf.h      2009-12-11 11:45:11.000000000 +0200
11376 @@ -0,0 +1,69 @@
11377 +/*
11378 + * arch/ubicom32/include/asm/shmbuf.h
11379 + *   The shmid64_ds structure for the Ubicom32 architecture.
11380 + *
11381 + * (C) Copyright 2009, Ubicom, Inc.
11382 + *
11383 + * This file is part of the Ubicom32 Linux Kernel Port.
11384 + *
11385 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11386 + * it and/or modify it under the terms of the GNU General Public License
11387 + * as published by the Free Software Foundation, either version 2 of the
11388 + * License, or (at your option) any later version.
11389 + *
11390 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11391 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11392 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11393 + * the GNU General Public License for more details.
11394 + *
11395 + * You should have received a copy of the GNU General Public License
11396 + * along with the Ubicom32 Linux Kernel Port.  If not,
11397 + * see <http://www.gnu.org/licenses/>.
11398 + *
11399 + * Ubicom32 implementation derived from (with many thanks):
11400 + *   arch/m68knommu
11401 + *   arch/blackfin
11402 + *   arch/parisc
11403 + */
11404 +#ifndef _ASM_UBICOM32_SHMBUF_H
11405 +#define _ASM_UBICOM32_SHMBUF_H
11406 +
11407 +/*
11408 + * The shmid64_ds structure for m68k architecture.
11409 + * Note extra padding because this structure is passed back and forth
11410 + * between kernel and user space.
11411 + *
11412 + * Pad space is left for:
11413 + * - 64-bit time_t to solve y2038 problem
11414 + * - 2 miscellaneous 32-bit values
11415 + */
11416 +
11417 +struct shmid64_ds {
11418 +       struct ipc64_perm       shm_perm;       /* operation perms */
11419 +       size_t                  shm_segsz;      /* size of segment (bytes) */
11420 +       __kernel_time_t         shm_atime;      /* last attach time */
11421 +       unsigned long           __unused1;
11422 +       __kernel_time_t         shm_dtime;      /* last detach time */
11423 +       unsigned long           __unused2;
11424 +       __kernel_time_t         shm_ctime;      /* last change time */
11425 +       unsigned long           __unused3;
11426 +       __kernel_pid_t          shm_cpid;       /* pid of creator */
11427 +       __kernel_pid_t          shm_lpid;       /* pid of last operator */
11428 +       unsigned long           shm_nattch;     /* no. of current attaches */
11429 +       unsigned long           __unused4;
11430 +       unsigned long           __unused5;
11431 +};
11432 +
11433 +struct shminfo64 {
11434 +       unsigned long   shmmax;
11435 +       unsigned long   shmmin;
11436 +       unsigned long   shmmni;
11437 +       unsigned long   shmseg;
11438 +       unsigned long   shmall;
11439 +       unsigned long   __unused1;
11440 +       unsigned long   __unused2;
11441 +       unsigned long   __unused3;
11442 +       unsigned long   __unused4;
11443 +};
11444 +
11445 +#endif /* _ASM_UBICOM32_SHMBUF_H */
11446 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/shmparam.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmparam.h
11447 --- linux-2.6.30.10/arch/ubicom32/include/asm/shmparam.h        1970-01-01 02:00:00.000000000 +0200
11448 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmparam.h    2009-12-11 11:45:11.000000000 +0200
11449 @@ -0,0 +1,35 @@
11450 +/*
11451 + * arch/ubicom32/include/asm/shmparam.h
11452 + *   Shared memory definitions for Ubicom32 architecture.
11453 + *
11454 + * (C) Copyright 2009, Ubicom, Inc.
11455 + * Copyright (C) 2004   Microtronix Datacom Ltd
11456 + *
11457 + * This file is part of the Ubicom32 Linux Kernel Port.
11458 + *
11459 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11460 + * it and/or modify it under the terms of the GNU General Public License
11461 + * as published by the Free Software Foundation, either version 2 of the
11462 + * License, or (at your option) any later version.
11463 + *
11464 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11465 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11466 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11467 + * the GNU General Public License for more details.
11468 + *
11469 + * You should have received a copy of the GNU General Public License
11470 + * along with the Ubicom32 Linux Kernel Port.  If not,
11471 + * see <http://www.gnu.org/licenses/>.
11472 + *
11473 + * Ubicom32 implementation derived from (with many thanks):
11474 + *   arch/m68knommu
11475 + *   arch/blackfin
11476 + *   arch/parisc
11477 + *   Alpha, ix86, M68K, Sparc, ...et al
11478 + */
11479 +#ifndef _ASM_UBICOM32_SHMPARAM_H
11480 +#define _ASM_UBICOM32_SHMPARAM_H
11481 +
11482 +#define        SHMLBA          PAGE_SIZE       /* attach addr a multiple of this */
11483 +
11484 +#endif /* _ASM_UBICOM32_SHMPARAM_H */
11485 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sigcontext.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sigcontext.h
11486 --- linux-2.6.30.10/arch/ubicom32/include/asm/sigcontext.h      1970-01-01 02:00:00.000000000 +0200
11487 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sigcontext.h  2009-12-11 11:45:11.000000000 +0200
11488 @@ -0,0 +1,37 @@
11489 +/*
11490 + * arch/ubicom32/include/asm/sigcontext.h
11491 + *   Definition of sigcontext struct for Ubicom32 architecture.
11492 + *
11493 + * (C) Copyright 2009, Ubicom, Inc.
11494 + *
11495 + * This file is part of the Ubicom32 Linux Kernel Port.
11496 + *
11497 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11498 + * it and/or modify it under the terms of the GNU General Public License
11499 + * as published by the Free Software Foundation, either version 2 of the
11500 + * License, or (at your option) any later version.
11501 + *
11502 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11503 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11504 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11505 + * the GNU General Public License for more details.
11506 + *
11507 + * You should have received a copy of the GNU General Public License
11508 + * along with the Ubicom32 Linux Kernel Port.  If not,
11509 + * see <http://www.gnu.org/licenses/>.
11510 + *
11511 + * Ubicom32 implementation derived from (with many thanks):
11512 + *   arch/m68knommu
11513 + *   arch/blackfin
11514 + *   arch/parisc
11515 + */
11516 +#ifndef _ASM_UBICOM32_SIGCONTEXT_H
11517 +#define _ASM_UBICOM32_SIGCONTEXT_H
11518 +
11519 +#include <asm/ptrace.h>
11520 +
11521 +struct sigcontext {
11522 +       struct pt_regs sc_regs;
11523 +};
11524 +
11525 +#endif /* _ASM_UBICOM32_SIGCONTEXT_H */
11526 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/siginfo.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/siginfo.h
11527 --- linux-2.6.30.10/arch/ubicom32/include/asm/siginfo.h 1970-01-01 02:00:00.000000000 +0200
11528 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/siginfo.h     2009-12-11 11:45:11.000000000 +0200
11529 @@ -0,0 +1,33 @@
11530 +/*
11531 + * arch/ubicom32/include/asm/siginfo.h
11532 + *   Generic siginfo.h definitions for Ubicom32 architecture.
11533 + *
11534 + * (C) Copyright 2009, Ubicom, Inc.
11535 + *
11536 + * This file is part of the Ubicom32 Linux Kernel Port.
11537 + *
11538 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11539 + * it and/or modify it under the terms of the GNU General Public License
11540 + * as published by the Free Software Foundation, either version 2 of the
11541 + * License, or (at your option) any later version.
11542 + *
11543 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11544 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11545 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11546 + * the GNU General Public License for more details.
11547 + *
11548 + * You should have received a copy of the GNU General Public License
11549 + * along with the Ubicom32 Linux Kernel Port.  If not,
11550 + * see <http://www.gnu.org/licenses/>.
11551 + *
11552 + * Ubicom32 implementation derived from (with many thanks):
11553 + *   arch/m68knommu
11554 + *   arch/blackfin
11555 + *   arch/parisc
11556 + */
11557 +#ifndef _ASM_UBICOM32_SIGINFO_H
11558 +#define _ASM_UBICOM32_SIGINFO_H
11559 +
11560 +#include <asm-generic/siginfo.h>
11561 +
11562 +#endif /* _ASM_UBICOM32_SIGINFO_H */
11563 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/signal.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/signal.h
11564 --- linux-2.6.30.10/arch/ubicom32/include/asm/signal.h  1970-01-01 02:00:00.000000000 +0200
11565 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/signal.h      2009-12-11 11:45:11.000000000 +0200
11566 @@ -0,0 +1,180 @@
11567 +/*
11568 + * arch/ubicom32/include/asm/signal.h
11569 + *   Signal related definitions for Ubicom32 architecture.
11570 + *
11571 + * (C) Copyright 2009, Ubicom, Inc.
11572 + *
11573 + * This file is part of the Ubicom32 Linux Kernel Port.
11574 + *
11575 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11576 + * it and/or modify it under the terms of the GNU General Public License
11577 + * as published by the Free Software Foundation, either version 2 of the
11578 + * License, or (at your option) any later version.
11579 + *
11580 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11581 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11582 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11583 + * the GNU General Public License for more details.
11584 + *
11585 + * You should have received a copy of the GNU General Public License
11586 + * along with the Ubicom32 Linux Kernel Port.  If not,
11587 + * see <http://www.gnu.org/licenses/>.
11588 + *
11589 + * Ubicom32 implementation derived from (with many thanks):
11590 + *   arch/m68knommu
11591 + *   arch/blackfin
11592 + *   arch/parisc
11593 + */
11594 +#ifndef _ASM_UBICOM32_SIGNAL_H
11595 +#define _ASM_UBICOM32_SIGNAL_H
11596 +
11597 +#include <linux/types.h>
11598 +
11599 +/* Avoid too many header ordering problems.  */
11600 +struct siginfo;
11601 +
11602 +#ifdef __KERNEL__
11603 +/* Most things should be clean enough to redefine this at will, if care
11604 +   is taken to make libc match.  */
11605 +
11606 +#define _NSIG          64
11607 +#define _NSIG_BPW      32
11608 +#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
11609 +
11610 +typedef unsigned long old_sigset_t;            /* at least 32 bits */
11611 +
11612 +typedef struct {
11613 +       unsigned long sig[_NSIG_WORDS];
11614 +} sigset_t;
11615 +
11616 +#endif /* __KERNEL__ */
11617 +
11618 +#define SIGHUP          1
11619 +#define SIGINT          2
11620 +#define SIGQUIT                 3
11621 +#define SIGILL          4
11622 +#define SIGTRAP                 5
11623 +#define SIGABRT                 6
11624 +#define SIGIOT          6
11625 +#define SIGBUS          7
11626 +#define SIGFPE          8
11627 +#define SIGKILL                 9
11628 +#define SIGUSR1                10
11629 +#define SIGSEGV                11
11630 +#define SIGUSR2                12
11631 +#define SIGPIPE                13
11632 +#define SIGALRM                14
11633 +#define SIGTERM                15
11634 +#define SIGSTKFLT      16
11635 +#define SIGCHLD                17
11636 +#define SIGCONT                18
11637 +#define SIGSTOP                19
11638 +#define SIGTSTP                20
11639 +#define SIGTTIN                21
11640 +#define SIGTTOU                22
11641 +#define SIGURG         23
11642 +#define SIGXCPU                24
11643 +#define SIGXFSZ                25
11644 +#define SIGVTALRM      26
11645 +#define SIGPROF                27
11646 +#define SIGWINCH       28
11647 +#define SIGIO          29
11648 +#define SIGPOLL                SIGIO
11649 +/*
11650 +#define SIGLOST                29
11651 +*/
11652 +#define SIGPWR         30
11653 +#define SIGSYS         31
11654 +#define        SIGUNUSED       31
11655 +
11656 +/* These should not be considered constants from userland.  */
11657 +#define SIGRTMIN       32
11658 +#define SIGRTMAX       _NSIG
11659 +
11660 +/*
11661 + * SA_FLAGS values:
11662 + *
11663 + * SA_ONSTACK indicates that a registered stack_t will be used.
11664 + * SA_RESTART flag to get restarting signals (which were the default long ago)
11665 + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
11666 + * SA_RESETHAND clears the handler when the signal is delivered.
11667 + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
11668 + * SA_NODEFER prevents the current signal from being masked in the handler.
11669 + *
11670 + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
11671 + * Unix names RESETHAND and NODEFER respectively.
11672 + */
11673 +#define SA_NOCLDSTOP   0x00000001
11674 +#define SA_NOCLDWAIT   0x00000002
11675 +#define SA_SIGINFO     0x00000004
11676 +#define SA_ONSTACK     0x08000000
11677 +#define SA_RESTART     0x10000000
11678 +#define SA_NODEFER     0x40000000
11679 +#define SA_RESETHAND   0x80000000
11680 +
11681 +#define SA_NOMASK      SA_NODEFER
11682 +#define SA_ONESHOT     SA_RESETHAND
11683 +
11684 +/*
11685 + * sigaltstack controls
11686 + */
11687 +#define SS_ONSTACK     1
11688 +#define SS_DISABLE     2
11689 +
11690 +#define MINSIGSTKSZ    2048
11691 +#define SIGSTKSZ       8192
11692 +
11693 +#include <asm-generic/signal.h>
11694 +
11695 +#ifdef __KERNEL__
11696 +struct old_sigaction {
11697 +       __sighandler_t sa_handler;
11698 +       old_sigset_t sa_mask;
11699 +       unsigned long sa_flags;
11700 +       void (*sa_restorer)(void);
11701 +};
11702 +
11703 +struct sigaction {
11704 +       __sighandler_t sa_handler;
11705 +       unsigned long sa_flags;
11706 +       void (*sa_restorer)(void);
11707 +       sigset_t sa_mask;               /* mask last for extensibility */
11708 +};
11709 +
11710 +struct k_sigaction {
11711 +       struct sigaction sa;
11712 +};
11713 +#else
11714 +/* Here we must cater to libcs that poke about in kernel headers.  */
11715 +
11716 +struct sigaction {
11717 +       union {
11718 +         __sighandler_t _sa_handler;
11719 +         void (*_sa_sigaction)(int, struct siginfo *, void *);
11720 +       } _u;
11721 +       sigset_t sa_mask;
11722 +       unsigned long sa_flags;
11723 +       void (*sa_restorer)(void);
11724 +};
11725 +
11726 +#define sa_handler     _u._sa_handler
11727 +#define sa_sigaction   _u._sa_sigaction
11728 +
11729 +#endif /* __KERNEL__ */
11730 +
11731 +typedef struct sigaltstack {
11732 +       void *ss_sp;
11733 +       int ss_flags;
11734 +       size_t ss_size;
11735 +} stack_t;
11736 +
11737 +#ifdef __KERNEL__
11738 +
11739 +#include <asm/sigcontext.h>
11740 +#undef __HAVE_ARCH_SIG_BITOPS
11741 +
11742 +#define ptrace_signal_deliver(regs, cookie) do { } while (0)
11743 +
11744 +#endif /* __KERNEL__ */
11745 +
11746 +#endif /* _ASM_UBICOM32_SIGNAL_H */
11747 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/smp.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/smp.h
11748 --- linux-2.6.30.10/arch/ubicom32/include/asm/smp.h     1970-01-01 02:00:00.000000000 +0200
11749 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/smp.h 2009-12-11 11:45:11.000000000 +0200
11750 @@ -0,0 +1,87 @@
11751 +/*
11752 + * arch/ubicom32/include/asm/smp.h
11753 + *   SMP definitions for Ubicom32 architecture.
11754 + *
11755 + * (C) Copyright 2009, Ubicom, Inc.
11756 + *
11757 + * This file is part of the Ubicom32 Linux Kernel Port.
11758 + *
11759 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11760 + * it and/or modify it under the terms of the GNU General Public License
11761 + * as published by the Free Software Foundation, either version 2 of the
11762 + * License, or (at your option) any later version.
11763 + *
11764 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11765 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11766 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11767 + * the GNU General Public License for more details.
11768 + *
11769 + * You should have received a copy of the GNU General Public License
11770 + * along with the Ubicom32 Linux Kernel Port.  If not,
11771 + * see <http://www.gnu.org/licenses/>.
11772 + *
11773 + * Ubicom32 implementation derived from (with many thanks):
11774 + *   arch/m68knommu
11775 + *   arch/blackfin
11776 + *   arch/parisc
11777 + */
11778 +#ifndef _ASM_UBICOM32_SMP_H
11779 +#define _ASM_UBICOM32_SMP_H
11780 +
11781 +#ifndef CONFIG_SMP
11782 +#error you should not include smp.h if smp is off
11783 +#endif
11784 +
11785 +#ifndef ASSEMBLY
11786 +#include <linux/bitops.h>
11787 +#include <linux/threads.h>
11788 +#include <linux/cpumask.h>
11789 +#include <asm/ip5000.h>
11790 +
11791 +typedef unsigned long address_t;
11792 +extern unsigned int smp_ipi_irq;
11793 +
11794 +/*
11795 + * This magic constant controls our willingness to transfer
11796 + * a process across CPUs.
11797 + *
11798 + * Such a transfer incurs cache and tlb
11799 + * misses. The current value is inherited from i386. Still needs
11800 + * to be tuned for parisc.
11801 + */
11802 +#define PROC_CHANGE_PENALTY    15              /* Schedule penalty */
11803 +#define NO_PROC_ID             0xFF            /* No processor magic marker */
11804 +#define ANY_PROC_ID            0xFF            /* Any processor magic marker */
11805 +
11806 +#ifdef CONFIG_SMP
11807 +#define raw_smp_processor_id() (current_thread_info()->cpu)
11808 +#endif /* CONFIG_SMP */
11809 +
11810 +static inline int __cpu_disable (void)
11811 +{
11812 +  return 0;
11813 +}
11814 +
11815 +static inline void __cpu_die (unsigned int cpu)
11816 +{
11817 +       while(1) {
11818 +       };
11819 +}
11820 +
11821 +extern int __cpu_up(unsigned int cpu);
11822 +extern void smp_send_timer_all(void);
11823 +extern void smp_timer_broadcast(const struct cpumask *mask);
11824 +extern void smp_set_affinity(unsigned int irq, const struct cpumask *dest);
11825 +extern void arch_send_call_function_single_ipi(int cpu);
11826 +#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
11827 +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
11828 +
11829 +/*
11830 + * TODO: Once these are fully tested, we should turn them into
11831 + * inline macros for performance.
11832 + */
11833 +extern unsigned long smp_get_affinity(unsigned int irq, int *all);
11834 +extern void smp_reset_ipi(unsigned long mask);
11835 +
11836 +#endif /* !ASSEMBLY */
11837 +#endif /*  _ASM_UBICOM32_SMP_H */
11838 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/socket.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/socket.h
11839 --- linux-2.6.30.10/arch/ubicom32/include/asm/socket.h  1970-01-01 02:00:00.000000000 +0200
11840 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/socket.h      2009-12-11 11:45:11.000000000 +0200
11841 @@ -0,0 +1,87 @@
11842 +/*
11843 + * arch/ubicom32/include/asm/socket.h
11844 + *   Socket options definitions for Ubicom32 architecture.
11845 + *
11846 + * (C) Copyright 2009, Ubicom, Inc.
11847 + *
11848 + * This file is part of the Ubicom32 Linux Kernel Port.
11849 + *
11850 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11851 + * it and/or modify it under the terms of the GNU General Public License
11852 + * as published by the Free Software Foundation, either version 2 of the
11853 + * License, or (at your option) any later version.
11854 + *
11855 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11856 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11857 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11858 + * the GNU General Public License for more details.
11859 + *
11860 + * You should have received a copy of the GNU General Public License
11861 + * along with the Ubicom32 Linux Kernel Port.  If not,
11862 + * see <http://www.gnu.org/licenses/>.
11863 + *
11864 + * Ubicom32 implementation derived from (with many thanks):
11865 + *   arch/m68knommu
11866 + *   arch/blackfin
11867 + *   arch/parisc
11868 + */
11869 +#ifndef _ASM_UBICOM32_SOCKET_H
11870 +#define _ASM_UBICOM32_SOCKET_H
11871 +
11872 +#include <asm/sockios.h>
11873 +
11874 +/* For setsockopt(2) */
11875 +#define SOL_SOCKET     1
11876 +
11877 +#define SO_DEBUG       1
11878 +#define SO_REUSEADDR   2
11879 +#define SO_TYPE                3
11880 +#define SO_ERROR       4
11881 +#define SO_DONTROUTE   5
11882 +#define SO_BROADCAST   6
11883 +#define SO_SNDBUF      7
11884 +#define SO_RCVBUF      8
11885 +#define SO_SNDBUFFORCE 32
11886 +#define SO_RCVBUFFORCE 33
11887 +#define SO_KEEPALIVE   9
11888 +#define SO_OOBINLINE   10
11889 +#define SO_NO_CHECK    11
11890 +#define SO_PRIORITY    12
11891 +#define SO_LINGER      13
11892 +#define SO_BSDCOMPAT   14
11893 +/* To add :#define SO_REUSEPORT 15 */
11894 +#define SO_PASSCRED    16
11895 +#define SO_PEERCRED    17
11896 +#define SO_RCVLOWAT    18
11897 +#define SO_SNDLOWAT    19
11898 +#define SO_RCVTIMEO    20
11899 +#define SO_SNDTIMEO    21
11900 +
11901 +/* Security levels - as per NRL IPv6 - don't actually do anything */
11902 +#define SO_SECURITY_AUTHENTICATION             22
11903 +#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
11904 +#define SO_SECURITY_ENCRYPTION_NETWORK         24
11905 +
11906 +#define SO_BINDTODEVICE        25
11907 +
11908 +/* Socket filtering */
11909 +#define SO_ATTACH_FILTER        26
11910 +#define SO_DETACH_FILTER        27
11911 +
11912 +#define SO_PEERNAME             28
11913 +#define SO_TIMESTAMP           29
11914 +#define SCM_TIMESTAMP          SO_TIMESTAMP
11915 +
11916 +#define SO_ACCEPTCONN          30
11917 +
11918 +#define SO_PEERSEC              31
11919 +#define SO_PASSSEC             34
11920 +#define SO_TIMESTAMPNS         35
11921 +#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
11922 +
11923 +#define SO_MARK                        36
11924 +
11925 +#define SO_TIMESTAMPING                37
11926 +#define SCM_TIMESTAMPING       SO_TIMESTAMPING
11927 +
11928 +#endif /* _ASM_UBICOM32_SOCKET_H */
11929 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sockios.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sockios.h
11930 --- linux-2.6.30.10/arch/ubicom32/include/asm/sockios.h 1970-01-01 02:00:00.000000000 +0200
11931 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sockios.h     2009-12-11 11:45:11.000000000 +0200
11932 @@ -0,0 +1,40 @@
11933 +/*
11934 + * arch/ubicom32/include/asm/sockios.h
11935 + *   Socket-level ioctl definitions for Ubicom32 architecture.
11936 + *
11937 + * (C) Copyright 2009, Ubicom, Inc.
11938 + *
11939 + * This file is part of the Ubicom32 Linux Kernel Port.
11940 + *
11941 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11942 + * it and/or modify it under the terms of the GNU General Public License
11943 + * as published by the Free Software Foundation, either version 2 of the
11944 + * License, or (at your option) any later version.
11945 + *
11946 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11947 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11948 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11949 + * the GNU General Public License for more details.
11950 + *
11951 + * You should have received a copy of the GNU General Public License
11952 + * along with the Ubicom32 Linux Kernel Port.  If not,
11953 + * see <http://www.gnu.org/licenses/>.
11954 + *
11955 + * Ubicom32 implementation derived from (with many thanks):
11956 + *   arch/m68knommu
11957 + *   arch/blackfin
11958 + *   arch/parisc
11959 + */
11960 +#ifndef _ASM_UBICOM32_SOCKIOS_H
11961 +#define _ASM_UBICOM32_SOCKIOS_H
11962 +
11963 +/* Socket-level I/O control calls. */
11964 +#define FIOSETOWN      0x8901
11965 +#define SIOCSPGRP      0x8902
11966 +#define FIOGETOWN      0x8903
11967 +#define SIOCGPGRP      0x8904
11968 +#define SIOCATMARK     0x8905
11969 +#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
11970 +#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
11971 +
11972 +#endif /* _ASM_UBICOM32_SOCKIOS_H */
11973 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/spinlock.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock.h
11974 --- linux-2.6.30.10/arch/ubicom32/include/asm/spinlock.h        1970-01-01 02:00:00.000000000 +0200
11975 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock.h    2009-12-11 11:45:11.000000000 +0200
11976 @@ -0,0 +1,296 @@
11977 +/*
11978 + * arch/ubicom32/include/asm/spinlock.h
11979 + *   Spinlock related definitions for Ubicom32 architecture.
11980 + *
11981 + * (C) Copyright 2009, Ubicom, Inc.
11982 + *
11983 + * This file is part of the Ubicom32 Linux Kernel Port.
11984 + *
11985 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11986 + * it and/or modify it under the terms of the GNU General Public License
11987 + * as published by the Free Software Foundation, either version 2 of the
11988 + * License, or (at your option) any later version.
11989 + *
11990 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11991 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11992 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11993 + * the GNU General Public License for more details.
11994 + *
11995 + * You should have received a copy of the GNU General Public License
11996 + * along with the Ubicom32 Linux Kernel Port.  If not,
11997 + * see <http://www.gnu.org/licenses/>.
11998 + *
11999 + * Ubicom32 implementation derived from (with many thanks):
12000 + *   arch/m68knommu
12001 + *   arch/blackfin
12002 + *   arch/parisc
12003 + */
12004 +#ifndef _ASM_UBICOM32_SPINLOCK_H
12005 +#define _ASM_UBICOM32_SPINLOCK_H
12006 +
12007 +#include <asm/system.h>
12008 +#include <asm/processor.h>
12009 +#include <asm/spinlock_types.h>
12010 +
12011 +/*
12012 + * __raw_spin_lock()
12013 + *     Lock the lock.
12014 + */
12015 +static inline void __raw_spin_lock(raw_spinlock_t *x)
12016 +{
12017 +       asm volatile (
12018 +       "1:     bset    %0, %0, #0      \n\t"
12019 +       "       jmpne.f 1b              \n\t"
12020 +               : "+U4" (x->lock)
12021 +               :
12022 +               : "memory", "cc"
12023 +       );
12024 +}
12025 +
12026 +/*
12027 + * __raw_spin_unlock()
12028 + *     Unlock the lock.
12029 + */
12030 +static inline void __raw_spin_unlock(raw_spinlock_t *x)
12031 +{
12032 +       asm volatile (
12033 +       "       bclr    %0, %0, #0      \n\t"
12034 +               : "+U4" (x->lock)
12035 +               :
12036 +               : "memory", "cc"
12037 +       );
12038 +}
12039 +
12040 +/*
12041 + * __raw_spin_is_locked()
12042 + *     Test if the lock is locked.
12043 + */
12044 +static inline int __raw_spin_is_locked(raw_spinlock_t *x)
12045 +{
12046 +       return x->lock;
12047 +}
12048 +
12049 +/*
12050 + * __raw_spin_unlock_wait()
12051 + *     Wait for the lock to be unlocked.
12052 + *
12053 + * Note: the caller has not guarantee that the lock will not
12054 + * be acquired before they get to it.
12055 + */
12056 +static inline void __raw_spin_unlock_wait(raw_spinlock_t *x)
12057 +{
12058 +       do {
12059 +               cpu_relax();
12060 +       } while (__raw_spin_is_locked(x));
12061 +}
12062 +
12063 +/*
12064 + * __raw_spin_trylock()
12065 + *     Try the lock, return 0 on failure, 1 on success.
12066 + */
12067 +static inline int __raw_spin_trylock(raw_spinlock_t *x)
12068 +{
12069 +       int ret = 0;
12070 +
12071 +       asm volatile (
12072 +       "       bset    %1, %1, #0      \n\t"
12073 +       "       jmpne.f 1f              \n\t"
12074 +       "       move.4  %0, #1          \n\t"
12075 +       "1:                             \n\t"
12076 +               : "+r" (ret), "+U4" (x->lock)
12077 +               :
12078 +               : "memory", "cc"
12079 +       );
12080 +
12081 +       return ret;
12082 +}
12083 +
12084 +/*
12085 + * __raw_spin_lock_flags()
12086 + *     Spin waiting for the lock (enabling IRQ(s))
12087 + */
12088 +static inline void __raw_spin_lock_flags(raw_spinlock_t *x, unsigned long flags)
12089 +{
12090 +       mb();
12091 +       while (!__raw_spin_trylock(x)) {
12092 +               /*
12093 +                * If the flags from the IRQ are set, interrupts are disabled and we
12094 +                * need to re-enable them.
12095 +                */
12096 +               if (!flags) {
12097 +                       cpu_relax();
12098 +               } else {
12099 +                       raw_local_irq_enable();
12100 +                       cpu_relax();
12101 +                       raw_local_irq_disable();
12102 +               }
12103 +       }
12104 +       mb();
12105 +}
12106 +
12107 +/*
12108 + * Read-write spinlocks, allowing multiple readers but only one writer.
12109 + * Linux rwlocks are unfair to writers; they can be starved for an indefinite
12110 + * time by readers.  With care, they can also be taken in interrupt context.
12111 + *
12112 + * In Ubicom32 architecture implementation, we have a spinlock and a counter.
12113 + * Readers use the lock to serialise their access to the counter (which
12114 + * records how many readers currently hold the lock).
12115 + * Writers hold the spinlock, preventing any readers or other writers from
12116 + * grabbing the rwlock.
12117 + */
12118 +
12119 +/*
12120 + * __raw_read_lock()
12121 + *     Increment the counter in the rwlock.
12122 + *
12123 + * Note that we have to ensure interrupts are disabled in case we're
12124 + * interrupted by some other code that wants to grab the same read lock
12125 + */
12126 +static inline void __raw_read_lock(raw_rwlock_t *rw)
12127 +{
12128 +       unsigned long flags;
12129 +       raw_local_irq_save(flags);
12130 +       __raw_spin_lock_flags(&rw->lock, flags);
12131 +       rw->counter++;
12132 +       __raw_spin_unlock(&rw->lock);
12133 +       raw_local_irq_restore(flags);
12134 +}
12135 +
12136 +/*
12137 + * __raw_read_unlock()
12138 + *     Decrement the counter.
12139 + *
12140 + * Note that we have to ensure interrupts are disabled in case we're
12141 + * interrupted by some other code that wants to grab the same read lock
12142 + */
12143 +static inline void __raw_read_unlock(raw_rwlock_t *rw)
12144 +{
12145 +       unsigned long flags;
12146 +       raw_local_irq_save(flags);
12147 +       __raw_spin_lock_flags(&rw->lock, flags);
12148 +       rw->counter--;
12149 +       __raw_spin_unlock(&rw->lock);
12150 +       raw_local_irq_restore(flags);
12151 +}
12152 +
12153 +/*
12154 + * __raw_read_trylock()
12155 + *     Increment the counter if we can.
12156 + *
12157 + * Note that we have to ensure interrupts are disabled in case we're
12158 + * interrupted by some other code that wants to grab the same read lock
12159 + */
12160 +static inline int __raw_read_trylock(raw_rwlock_t *rw)
12161 +{
12162 +       unsigned long flags;
12163 + retry:
12164 +       raw_local_irq_save(flags);
12165 +       if (__raw_spin_trylock(&rw->lock)) {
12166 +               rw->counter++;
12167 +               __raw_spin_unlock(&rw->lock);
12168 +               raw_local_irq_restore(flags);
12169 +               return 1;
12170 +       }
12171 +
12172 +       raw_local_irq_restore(flags);
12173 +
12174 +       /*
12175 +        * If write-locked, we fail to acquire the lock
12176 +        */
12177 +       if (rw->counter < 0) {
12178 +               return 0;
12179 +       }
12180 +
12181 +       /*
12182 +        * Wait until we have a realistic chance at the lock
12183 +        */
12184 +       while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0) {
12185 +               cpu_relax();
12186 +       }
12187 +
12188 +       goto retry;
12189 +}
12190 +
12191 +/*
12192 + * __raw_write_lock()
12193 + *
12194 + * Note that we have to ensure interrupts are disabled in case we're
12195 + * interrupted by some other code that wants to read_trylock() this lock
12196 + */
12197 +static inline void __raw_write_lock(raw_rwlock_t *rw)
12198 +{
12199 +       unsigned long flags;
12200 +retry:
12201 +       raw_local_irq_save(flags);
12202 +       __raw_spin_lock_flags(&rw->lock, flags);
12203 +
12204 +       if (rw->counter != 0) {
12205 +               __raw_spin_unlock(&rw->lock);
12206 +               raw_local_irq_restore(flags);
12207 +
12208 +               while (rw->counter != 0)
12209 +                       cpu_relax();
12210 +
12211 +               goto retry;
12212 +       }
12213 +
12214 +       rw->counter = -1; /* mark as write-locked */
12215 +       mb();
12216 +       raw_local_irq_restore(flags);
12217 +}
12218 +
12219 +static inline void __raw_write_unlock(raw_rwlock_t *rw)
12220 +{
12221 +       rw->counter = 0;
12222 +       __raw_spin_unlock(&rw->lock);
12223 +}
12224 +
12225 +/* Note that we have to ensure interrupts are disabled in case we're
12226 + * interrupted by some other code that wants to read_trylock() this lock */
12227 +static inline int __raw_write_trylock(raw_rwlock_t *rw)
12228 +{
12229 +       unsigned long flags;
12230 +       int result = 0;
12231 +
12232 +       raw_local_irq_save(flags);
12233 +       if (__raw_spin_trylock(&rw->lock)) {
12234 +               if (rw->counter == 0) {
12235 +                       rw->counter = -1;
12236 +                       result = 1;
12237 +               } else {
12238 +                       /* Read-locked.  Oh well. */
12239 +                       __raw_spin_unlock(&rw->lock);
12240 +               }
12241 +       }
12242 +       raw_local_irq_restore(flags);
12243 +
12244 +       return result;
12245 +}
12246 +
12247 +/*
12248 + * read_can_lock - would read_trylock() succeed?
12249 + * @lock: the rwlock in question.
12250 + */
12251 +static inline int __raw_read_can_lock(raw_rwlock_t *rw)
12252 +{
12253 +       return rw->counter >= 0;
12254 +}
12255 +
12256 +/*
12257 + * write_can_lock - would write_trylock() succeed?
12258 + * @lock: the rwlock in question.
12259 + */
12260 +static inline int __raw_write_can_lock(raw_rwlock_t *rw)
12261 +{
12262 +       return !rw->counter;
12263 +}
12264 +
12265 +#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
12266 +#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
12267 +
12268 +#define _raw_spin_relax(lock)  cpu_relax()
12269 +#define _raw_read_relax(lock)  cpu_relax()
12270 +#define _raw_write_relax(lock) cpu_relax()
12271 +
12272 +#endif /* _ASM_UBICOM32_SPINLOCK_H */
12273 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/spinlock_types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock_types.h
12274 --- linux-2.6.30.10/arch/ubicom32/include/asm/spinlock_types.h  1970-01-01 02:00:00.000000000 +0200
12275 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock_types.h      2009-12-11 11:45:11.000000000 +0200
12276 @@ -0,0 +1,43 @@
12277 +/*
12278 + * arch/ubicom32/include/asm/spinlock_types.h
12279 + *   Spinlock related structure definitions for Ubicom32 architecture.
12280 + *
12281 + * (C) Copyright 2009, Ubicom, Inc.
12282 + *
12283 + * This file is part of the Ubicom32 Linux Kernel Port.
12284 + *
12285 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12286 + * it and/or modify it under the terms of the GNU General Public License
12287 + * as published by the Free Software Foundation, either version 2 of the
12288 + * License, or (at your option) any later version.
12289 + *
12290 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12291 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12292 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12293 + * the GNU General Public License for more details.
12294 + *
12295 + * You should have received a copy of the GNU General Public License
12296 + * along with the Ubicom32 Linux Kernel Port.  If not,
12297 + * see <http://www.gnu.org/licenses/>.
12298 + *
12299 + * Ubicom32 implementation derived from (with many thanks):
12300 + *   arch/m68knommu
12301 + *   arch/blackfin
12302 + *   arch/parisc
12303 + */
12304 +#ifndef _ASM_UBICOM32_SPINLOCK_TYPES_H
12305 +#define _ASM_UBICOM32_SPINLOCK_TYPES_H
12306 +
12307 +typedef struct {
12308 +       volatile unsigned int lock;
12309 +} raw_spinlock_t;
12310 +
12311 +typedef struct {
12312 +       raw_spinlock_t lock;
12313 +       volatile int counter;
12314 +} raw_rwlock_t;
12315 +
12316 +#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
12317 +#define __RAW_RW_LOCK_UNLOCKED         { __RAW_SPIN_LOCK_UNLOCKED, 0 }
12318 +
12319 +#endif /* _ASM_UBICOM32_SPINLOCK_TYPES_H */
12320 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/stacktrace.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stacktrace.h
12321 --- linux-2.6.30.10/arch/ubicom32/include/asm/stacktrace.h      1970-01-01 02:00:00.000000000 +0200
12322 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stacktrace.h  2009-12-11 11:45:11.000000000 +0200
12323 @@ -0,0 +1,72 @@
12324 +/*
12325 + * arch/ubicom32/include/asm/stacktrace.h
12326 + *   Stacktrace functions for the Ubicom32 architecture.
12327 + *
12328 + * (C) Copyright 2009, Ubicom, Inc.
12329 + *
12330 + * This file is part of the Ubicom32 Linux Kernel Port.
12331 + *
12332 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12333 + * it and/or modify it under the terms of the GNU General Public License
12334 + * as published by the Free Software Foundation, either version 2 of the
12335 + * License, or (at your option) any later version.
12336 + *
12337 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12338 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12339 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12340 + * the GNU General Public License for more details.
12341 + *
12342 + * You should have received a copy of the GNU General Public License
12343 + * along with the Ubicom32 Linux Kernel Port.  If not,
12344 + * see <http://www.gnu.org/licenses/>.
12345 + *
12346 + * Ubicom32 implementation derived from (with many thanks):
12347 + *   arch/m68knommu
12348 + *   arch/blackfin
12349 + *   arch/parisc
12350 + */
12351 +#ifndef _ASM_UBICOM32_STACKTRACE_H
12352 +#define _ASM_UBICOM32_STACKTRACE_H
12353 +
12354 +#define between(a, b, c)       (( \
12355 +                       ((unsigned long) a) >= ((unsigned long) b)) && \
12356 +                       (((unsigned long)a) <= ((unsigned long)c)))
12357 +
12358 +/*
12359 + * These symbols are filled in by the linker.
12360 + */
12361 +extern unsigned long _stext;
12362 +extern unsigned long _etext;
12363 +
12364 +/* OCM text goes from __ocm_text_run_begin to __data_begin */
12365 +extern unsigned long __ocm_text_run_begin;
12366 +extern unsigned long __data_begin;
12367 +
12368 +/* Account for OCM case - see stacktrace.c maybe combine(also trap.c) */
12369 +/*
12370 + * ubicom32_is_kernel()
12371 + *
12372 + *     Check to see if the given address belongs to the kernel.
12373 + * NOMMU does not permit any other means.
12374 + */
12375 +static inline int ubicom32_is_kernel(unsigned long addr)
12376 +{
12377 +       int is_kernel = between(addr, &_stext, &_etext) || \
12378 +                       between(addr, &__ocm_text_run_begin, &__data_begin);
12379 +
12380 +#ifdef CONFIG_MODULES
12381 +       if (!is_kernel)
12382 +               is_kernel = is_module_address(addr);
12383 +#endif
12384 +       return is_kernel;
12385 +}
12386 +
12387 +extern unsigned long stacktrace_iterate(
12388 +                               unsigned long **trace,
12389 +                               unsigned long stext, unsigned long etext,
12390 +                               unsigned long ocm_stext, unsigned long ocm_etext,
12391 +                               unsigned long sstack, unsigned long estack);
12392 +#ifdef CONFIG_STACKTRACE
12393 +void stacktrace_save_entries(struct task_struct *tsk, struct stack_trace *trace, unsigned long sp);
12394 +#endif
12395 +#endif /* _ASM_UBICOM32_STACKTRACE_H */
12396 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/statfs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/statfs.h
12397 --- linux-2.6.30.10/arch/ubicom32/include/asm/statfs.h  1970-01-01 02:00:00.000000000 +0200
12398 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/statfs.h      2009-12-11 11:45:11.000000000 +0200
12399 @@ -0,0 +1,33 @@
12400 +/*
12401 + * arch/ubicom32/include/asm/statfs.h
12402 + *   Generic statfs.h definitions
12403 + *
12404 + * (C) Copyright 2009, Ubicom, Inc.
12405 + *
12406 + * This file is part of the Ubicom32 Linux Kernel Port.
12407 + *
12408 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12409 + * it and/or modify it under the terms of the GNU General Public License
12410 + * as published by the Free Software Foundation, either version 2 of the
12411 + * License, or (at your option) any later version.
12412 + *
12413 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12414 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12415 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12416 + * the GNU General Public License for more details.
12417 + *
12418 + * You should have received a copy of the GNU General Public License
12419 + * along with the Ubicom32 Linux Kernel Port.  If not,
12420 + * see <http://www.gnu.org/licenses/>.
12421 + *
12422 + * Ubicom32 implementation derived from (with many thanks):
12423 + *   arch/m68knommu
12424 + *   arch/blackfin
12425 + *   arch/parisc
12426 + */
12427 +#ifndef _ASM_UBICOM32_STATFS_H
12428 +#define _ASM_UBICOM32_STATFS_H
12429 +
12430 +#include <asm-generic/statfs.h>
12431 +
12432 +#endif /* _ASM_UBICOM32_STATFS_H */
12433 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/stat.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stat.h
12434 --- linux-2.6.30.10/arch/ubicom32/include/asm/stat.h    1970-01-01 02:00:00.000000000 +0200
12435 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stat.h        2009-12-11 11:45:11.000000000 +0200
12436 @@ -0,0 +1,104 @@
12437 +/*
12438 + * arch/ubicom32/include/asm/stat.h
12439 + *   File status definitions for Ubicom32 architecture.
12440 + *
12441 + * (C) Copyright 2009, Ubicom, Inc.
12442 + *
12443 + * This file is part of the Ubicom32 Linux Kernel Port.
12444 + *
12445 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12446 + * it and/or modify it under the terms of the GNU General Public License
12447 + * as published by the Free Software Foundation, either version 2 of the
12448 + * License, or (at your option) any later version.
12449 + *
12450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12451 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12452 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12453 + * the GNU General Public License for more details.
12454 + *
12455 + * You should have received a copy of the GNU General Public License
12456 + * along with the Ubicom32 Linux Kernel Port.  If not,
12457 + * see <http://www.gnu.org/licenses/>.
12458 + *
12459 + * Ubicom32 implementation derived from (with many thanks):
12460 + *   arch/m68knommu
12461 + *   arch/blackfin
12462 + *   arch/parisc
12463 + */
12464 +#ifndef _ASM_UBICOM32_STAT_H
12465 +#define _ASM_UBICOM32_STAT_H
12466 +
12467 +struct __old_kernel_stat {
12468 +       unsigned short st_dev;
12469 +       unsigned short st_ino;
12470 +       unsigned short st_mode;
12471 +       unsigned short st_nlink;
12472 +       unsigned short st_uid;
12473 +       unsigned short st_gid;
12474 +       unsigned short st_rdev;
12475 +       unsigned long  st_size;
12476 +       unsigned long  st_atime;
12477 +       unsigned long  st_mtime;
12478 +       unsigned long  st_ctime;
12479 +};
12480 +
12481 +struct stat {
12482 +       unsigned short st_dev;
12483 +       unsigned short __pad1;
12484 +       unsigned long  st_ino;
12485 +       unsigned short st_mode;
12486 +       unsigned short st_nlink;
12487 +       unsigned short st_uid;
12488 +       unsigned short st_gid;
12489 +       unsigned short st_rdev;
12490 +       unsigned short __pad2;
12491 +       unsigned long  st_size;
12492 +       unsigned long  st_blksize;
12493 +       unsigned long  st_blocks;
12494 +       unsigned long  st_atime;
12495 +       unsigned long  __unused1;
12496 +       unsigned long  st_mtime;
12497 +       unsigned long  __unused2;
12498 +       unsigned long  st_ctime;
12499 +       unsigned long  __unused3;
12500 +       unsigned long  __unused4;
12501 +       unsigned long  __unused5;
12502 +};
12503 +
12504 +/* This matches struct stat64 in glibc2.1, hence the absolutely
12505 + * insane amounts of padding around dev_t's.
12506 + */
12507 +struct stat64 {
12508 +       unsigned long long      st_dev;
12509 +       unsigned char   __pad1[2];
12510 +
12511 +#define STAT64_HAS_BROKEN_ST_INO       1
12512 +       unsigned long   __st_ino;
12513 +
12514 +       unsigned int    st_mode;
12515 +       unsigned int    st_nlink;
12516 +
12517 +       unsigned long   st_uid;
12518 +       unsigned long   st_gid;
12519 +
12520 +       unsigned long long      st_rdev;
12521 +       unsigned char   __pad3[2];
12522 +
12523 +       long long       st_size;
12524 +       unsigned long   st_blksize;
12525 +
12526 +       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
12527 +
12528 +       unsigned long   st_atime;
12529 +       unsigned long   st_atime_nsec;
12530 +
12531 +       unsigned long   st_mtime;
12532 +       unsigned long   st_mtime_nsec;
12533 +
12534 +       unsigned long   st_ctime;
12535 +       unsigned long   st_ctime_nsec;
12536 +
12537 +       unsigned long long      st_ino;
12538 +};
12539 +
12540 +#endif /* _ASM_UBICOM32_STAT_H */
12541 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/string.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/string.h
12542 --- linux-2.6.30.10/arch/ubicom32/include/asm/string.h  1970-01-01 02:00:00.000000000 +0200
12543 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/string.h      2009-12-11 11:45:11.000000000 +0200
12544 @@ -0,0 +1,40 @@
12545 +/*
12546 + * arch/ubicom32/include/asm/string.h
12547 + *   String operation definitions for Ubicom32 architecture.
12548 + *
12549 + * (C) Copyright 2009, Ubicom, Inc.
12550 + *
12551 + * This file is part of the Ubicom32 Linux Kernel Port.
12552 + *
12553 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12554 + * it and/or modify it under the terms of the GNU General Public License
12555 + * as published by the Free Software Foundation, either version 2 of the
12556 + * License, or (at your option) any later version.
12557 + *
12558 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12559 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12560 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12561 + * the GNU General Public License for more details.
12562 + *
12563 + * You should have received a copy of the GNU General Public License
12564 + * along with the Ubicom32 Linux Kernel Port.  If not,
12565 + * see <http://www.gnu.org/licenses/>.
12566 + *
12567 + * Ubicom32 implementation derived from (with many thanks):
12568 + *   arch/m68knommu
12569 + *   arch/blackfin
12570 + *   arch/parisc
12571 + */
12572 +#ifndef _ASM_UBICOM32_STRING_H
12573 +#define _ASM_UBICOM32_STRING_H
12574 +
12575 +#define __HAVE_ARCH_MEMSET
12576 +extern void *memset(void *b, int c, size_t len);
12577 +
12578 +#define __HAVE_ARCH_MEMCPY
12579 +extern void *memcpy(void *to, const void *from, size_t len);
12580 +
12581 +#define __HAVE_ARCH_MEMMOVE
12582 +extern void * memmove(void *to, const void *from, size_t len);
12583 +
12584 +#endif /* _ASM_UBICOM32_STRING_H */
12585 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/swab.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/swab.h
12586 --- linux-2.6.30.10/arch/ubicom32/include/asm/swab.h    1970-01-01 02:00:00.000000000 +0200
12587 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/swab.h        2009-12-11 11:45:11.000000000 +0200
12588 @@ -0,0 +1,45 @@
12589 +/*
12590 + * arch/ubicom32/include/asm/byteorder.h
12591 + *   Byte order swapping utility routines.
12592 + *
12593 + * (C) Copyright 2009, Ubicom, Inc.
12594 + *
12595 + * This file is part of the Ubicom32 Linux Kernel Port.
12596 + *
12597 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12598 + * it and/or modify it under the terms of the GNU General Public License
12599 + * as published by the Free Software Foundation, either version 2 of the
12600 + * License, or (at your option) any later version.
12601 + *
12602 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12603 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12604 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12605 + * the GNU General Public License for more details.
12606 + *
12607 + * You should have received a copy of the GNU General Public License
12608 + * along with the Ubicom32 Linux Kernel Port.  If not,
12609 + * see <http://www.gnu.org/licenses/>.
12610 + *
12611 + * Ubicom32 implementation derived from (with many thanks):
12612 + *   arch/m68knommu
12613 + *   arch/blackfin
12614 + *   arch/parisc
12615 + */
12616 +#ifndef _ASM_UBICOM32_BYTEORDER_H
12617 +#define _ASM_UBICOM32_BYTEORDER_H
12618 +
12619 +#include <linux/types.h>
12620 +
12621 +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
12622 +#  define __BYTEORDER_HAS_U64__
12623 +#  define __SWAB_64_THRU_32__
12624 +#endif
12625 +
12626 +#if defined(IP7000) || defined(IP7000_REV2)
12627 +
12628 +#define __arch__swab16 __builtin_ubicom32_swapb_2
12629 +#define __arch__swab32 __builtin_ubicom32_swapb_4
12630 +
12631 +#endif /* IP7000 */
12632 +
12633 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
12634 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/switch-dev.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/switch-dev.h
12635 --- linux-2.6.30.10/arch/ubicom32/include/asm/switch-dev.h      1970-01-01 02:00:00.000000000 +0200
12636 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/switch-dev.h  2009-12-11 11:45:11.000000000 +0200
12637 @@ -0,0 +1,51 @@
12638 +/*
12639 + * arch/ubicom32/include/asm/switch-dev.h
12640 + *   generic Ethernet switch platform data definitions for Ubicom32 architecture.
12641 + *
12642 + * (C) Copyright 2009, Ubicom, Inc.
12643 + *
12644 + * This file is part of the Ubicom32 Linux Kernel Port.
12645 + *
12646 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12647 + * it and/or modify it under the terms of the GNU General Public License
12648 + * as published by the Free Software Foundation, either version 2 of the
12649 + * License, or (at your option) any later version.
12650 + *
12651 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12652 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12653 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12654 + * the GNU General Public License for more details.
12655 + *
12656 + * You should have received a copy of the GNU General Public License
12657 + * along with the Ubicom32 Linux Kernel Port.  If not,
12658 + * see <http://www.gnu.org/licenses/>.
12659 + *
12660 + * Ubicom32 implementation derived from (with many thanks):
12661 + *   arch/m68knommu
12662 + *   arch/blackfin
12663 + *   arch/parisc
12664 + */
12665 +#ifndef _ASM_UBICOM32_SWITCH_DEV_H
12666 +#define _ASM_UBICOM32_SWITCH_DEV_H
12667 +
12668 +#define SWITCH_DEV_FLAG_HW_RESET       0x01
12669 +#define SWITCH_DEV_FLAG_SW_RESET       0x02
12670 +
12671 +struct switch_core_platform_data {
12672 +       /*
12673 +        * See flags above
12674 +        */
12675 +       u32_t           flags;
12676 +
12677 +       /*
12678 +        * GPIO to use for nReset
12679 +        */
12680 +       int             pin_reset;
12681 +
12682 +       /*
12683 +        * Name of this switch
12684 +        */
12685 +       const char      *name;
12686 +};
12687 +
12688 +#endif /* _ASM_UBICOM32_SWITCH_DEV_H */
12689 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/system.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/system.h
12690 --- linux-2.6.30.10/arch/ubicom32/include/asm/system.h  1970-01-01 02:00:00.000000000 +0200
12691 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/system.h      2009-12-11 11:45:11.000000000 +0200
12692 @@ -0,0 +1,101 @@
12693 +/*
12694 + * arch/ubicom32/include/asm/system.h
12695 + *   Low level switching definitions.
12696 + *
12697 + * (C) Copyright 2009, Ubicom, Inc.
12698 + *
12699 + * This file is part of the Ubicom32 Linux Kernel Port.
12700 + *
12701 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12702 + * it and/or modify it under the terms of the GNU General Public License
12703 + * as published by the Free Software Foundation, either version 2 of the
12704 + * License, or (at your option) any later version.
12705 + *
12706 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12707 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12708 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12709 + * the GNU General Public License for more details.
12710 + *
12711 + * You should have received a copy of the GNU General Public License
12712 + * along with the Ubicom32 Linux Kernel Port.  If not,
12713 + * see <http://www.gnu.org/licenses/>.
12714 + *
12715 + * Ubicom32 implementation derived from (with many thanks):
12716 + *   arch/m68knommu
12717 + *   arch/blackfin
12718 + *   arch/parisc
12719 + */
12720 +#ifndef _ASM_UBICOM32_SYSTEM_H
12721 +#define _ASM_UBICOM32_SYSTEM_H
12722 +
12723 +#include <linux/irqflags.h>
12724 +#include <linux/linkage.h>
12725 +#include <asm/segment.h>
12726 +#include <asm/entry.h>
12727 +#include <asm/ldsr.h>
12728 +#include <asm/irq.h>
12729 +#include <asm/percpu.h>
12730 +#include <asm/ubicom32-common.h>
12731 +#include <asm/processor.h>
12732 +
12733 +/*
12734 + * switch_to(n) should switch tasks to task ptr, first checking that
12735 + * ptr isn't the current task, in which case it does nothing.
12736 + */
12737 +asmlinkage void resume(void);
12738 +extern void *__switch_to(struct task_struct *prev,
12739 +               struct thread_struct *prev_switch,
12740 +               struct thread_struct *next_switch);
12741 +
12742 +/*
12743 + * We will need a per linux thread sw_ksp for the switch_to macro to
12744 + * track the kernel stack pointer for the current thread on that linux thread.
12745 + */
12746 +#define switch_to(prev,next,last)                                      \
12747 +({                                                                     \
12748 +       void *_last;                                                    \
12749 +       _last = (void *)                                                \
12750 +               __switch_to(prev, &prev->thread, &next->thread);        \
12751 +       (last) = _last;                                                 \
12752 +})
12753 +
12754 +/*
12755 + * Force strict CPU ordering.
12756 + * Not really required on ubicom32...
12757 + */
12758 +#define nop()  asm volatile ("nop"::)
12759 +#define mb()   asm volatile (""   : : :"memory")
12760 +#define rmb()  asm volatile (""   : : :"memory")
12761 +#define wmb()  asm volatile (""   : : :"memory")
12762 +#define set_mb(var, value)     ({ (var) = (value); wmb(); })
12763 +
12764 +#ifdef CONFIG_SMP
12765 +#define smp_mb()       mb()
12766 +#define smp_rmb()      rmb()
12767 +#define smp_wmb()      wmb()
12768 +#define smp_read_barrier_depends()     read_barrier_depends()
12769 +#else
12770 +#define smp_mb()       mb()
12771 +#define smp_rmb()      rmb()
12772 +#define smp_wmb()      wmb()
12773 +#define smp_read_barrier_depends()     do { } while(0)
12774 +#endif
12775 +
12776 +#define read_barrier_depends()  ((void)0)
12777 +
12778 +/*
12779 + * The following defines change how the scheduler calls the switch_to()
12780 + * macro.
12781 + *
12782 + * 1) The first causes the runqueue to be unlocked on entry to
12783 + * switch_to().  Since our ctx code does not play with the runqueue
12784 + * we do not need it unlocked.
12785 + *
12786 + * 2) The later turns interrupts on during a ctxsw to reduce the latency of
12787 + * interrupts during ctx.  At this point in the port, we believe that this
12788 + * latency is not a problem since we have very little code to perform a ctxsw.
12789 + */
12790 +// #define __ARCH_WANT_UNLOCKED_CTXSW
12791 +// #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
12792 +
12793 +#endif /* _ASM_UBICOM32_SYSTEM_H */
12794 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/termbits.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termbits.h
12795 --- linux-2.6.30.10/arch/ubicom32/include/asm/termbits.h        1970-01-01 02:00:00.000000000 +0200
12796 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termbits.h    2009-12-11 11:45:11.000000000 +0200
12797 @@ -0,0 +1,227 @@
12798 +/*
12799 + * arch/ubicom32/include/asm/termbits.h
12800 + *   Terminal/serial port definitions for Ubicom32 architecture.
12801 + *
12802 + * (C) Copyright 2009, Ubicom, Inc.
12803 + *
12804 + * This file is part of the Ubicom32 Linux Kernel Port.
12805 + *
12806 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12807 + * it and/or modify it under the terms of the GNU General Public License
12808 + * as published by the Free Software Foundation, either version 2 of the
12809 + * License, or (at your option) any later version.
12810 + *
12811 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12812 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12813 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12814 + * the GNU General Public License for more details.
12815 + *
12816 + * You should have received a copy of the GNU General Public License
12817 + * along with the Ubicom32 Linux Kernel Port.  If not,
12818 + * see <http://www.gnu.org/licenses/>.
12819 + *
12820 + * Ubicom32 implementation derived from (with many thanks):
12821 + *   arch/m68knommu
12822 + *   arch/blackfin
12823 + *   arch/parisc
12824 + */
12825 +#ifndef _ASM_UBICOM32_TERMBITS_H
12826 +#define _ASM_UBICOM32_TERMBITS_H
12827 +
12828 +#include <linux/posix_types.h>
12829 +
12830 +typedef unsigned char  cc_t;
12831 +typedef unsigned int   speed_t;
12832 +typedef unsigned int   tcflag_t;
12833 +
12834 +#define NCCS 19
12835 +struct termios {
12836 +       tcflag_t c_iflag;               /* input mode flags */
12837 +       tcflag_t c_oflag;               /* output mode flags */
12838 +       tcflag_t c_cflag;               /* control mode flags */
12839 +       tcflag_t c_lflag;               /* local mode flags */
12840 +       cc_t c_line;                    /* line discipline */
12841 +       cc_t c_cc[NCCS];                /* control characters */
12842 +};
12843 +
12844 +struct termios2 {
12845 +       tcflag_t c_iflag;               /* input mode flags */
12846 +       tcflag_t c_oflag;               /* output mode flags */
12847 +       tcflag_t c_cflag;               /* control mode flags */
12848 +       tcflag_t c_lflag;               /* local mode flags */
12849 +       cc_t c_line;                    /* line discipline */
12850 +       cc_t c_cc[NCCS];                /* control characters */
12851 +       speed_t c_ispeed;               /* input speed */
12852 +       speed_t c_ospeed;               /* output speed */
12853 +};
12854 +
12855 +struct ktermios {
12856 +       tcflag_t c_iflag;               /* input mode flags */
12857 +       tcflag_t c_oflag;               /* output mode flags */
12858 +       tcflag_t c_cflag;               /* control mode flags */
12859 +       tcflag_t c_lflag;               /* local mode flags */
12860 +       cc_t c_line;                    /* line discipline */
12861 +       cc_t c_cc[NCCS];                /* control characters */
12862 +       speed_t c_ispeed;               /* input speed */
12863 +       speed_t c_ospeed;               /* output speed */
12864 +};
12865 +
12866 +/* c_cc characters */
12867 +#define VINTR 0
12868 +#define VQUIT 1
12869 +#define VERASE 2
12870 +#define VKILL 3
12871 +#define VEOF 4
12872 +#define VTIME 5
12873 +#define VMIN 6
12874 +#define VSWTC 7
12875 +#define VSTART 8
12876 +#define VSTOP 9
12877 +#define VSUSP 10
12878 +#define VEOL 11
12879 +#define VREPRINT 12
12880 +#define VDISCARD 13
12881 +#define VWERASE 14
12882 +#define VLNEXT 15
12883 +#define VEOL2 16
12884 +
12885 +
12886 +/* c_iflag bits */
12887 +#define IGNBRK 0000001
12888 +#define BRKINT 0000002
12889 +#define IGNPAR 0000004
12890 +#define PARMRK 0000010
12891 +#define INPCK  0000020
12892 +#define ISTRIP 0000040
12893 +#define INLCR  0000100
12894 +#define IGNCR  0000200
12895 +#define ICRNL  0000400
12896 +#define IUCLC  0001000
12897 +#define IXON   0002000
12898 +#define IXANY  0004000
12899 +#define IXOFF  0010000
12900 +#define IMAXBEL        0020000
12901 +#define IUTF8  0040000
12902 +
12903 +/* c_oflag bits */
12904 +#define OPOST  0000001
12905 +#define OLCUC  0000002
12906 +#define ONLCR  0000004
12907 +#define OCRNL  0000010
12908 +#define ONOCR  0000020
12909 +#define ONLRET 0000040
12910 +#define OFILL  0000100
12911 +#define OFDEL  0000200
12912 +#define NLDLY  0000400
12913 +#define   NL0  0000000
12914 +#define   NL1  0000400
12915 +#define CRDLY  0003000
12916 +#define   CR0  0000000
12917 +#define   CR1  0001000
12918 +#define   CR2  0002000
12919 +#define   CR3  0003000
12920 +#define TABDLY 0014000
12921 +#define   TAB0 0000000
12922 +#define   TAB1 0004000
12923 +#define   TAB2 0010000
12924 +#define   TAB3 0014000
12925 +#define   XTABS        0014000
12926 +#define BSDLY  0020000
12927 +#define   BS0  0000000
12928 +#define   BS1  0020000
12929 +#define VTDLY  0040000
12930 +#define   VT0  0000000
12931 +#define   VT1  0040000
12932 +#define FFDLY  0100000
12933 +#define   FF0  0000000
12934 +#define   FF1  0100000
12935 +
12936 +/* c_cflag bit meaning */
12937 +#define CBAUD  0010017
12938 +#define  B0    0000000         /* hang up */
12939 +#define  B50   0000001
12940 +#define  B75   0000002
12941 +#define  B110  0000003
12942 +#define  B134  0000004
12943 +#define  B150  0000005
12944 +#define  B200  0000006
12945 +#define  B300  0000007
12946 +#define  B600  0000010
12947 +#define  B1200 0000011
12948 +#define  B1800 0000012
12949 +#define  B2400 0000013
12950 +#define  B4800 0000014
12951 +#define  B9600 0000015
12952 +#define  B19200        0000016
12953 +#define  B38400        0000017
12954 +#define EXTA B19200
12955 +#define EXTB B38400
12956 +#define CSIZE  0000060
12957 +#define   CS5  0000000
12958 +#define   CS6  0000020
12959 +#define   CS7  0000040
12960 +#define   CS8  0000060
12961 +#define CSTOPB 0000100
12962 +#define CREAD  0000200
12963 +#define PARENB 0000400
12964 +#define PARODD 0001000
12965 +#define HUPCL  0002000
12966 +#define CLOCAL 0004000
12967 +#define CBAUDEX 0010000
12968 +#define    BOTHER 0010000
12969 +#define    B57600 0010001
12970 +#define   B115200 0010002
12971 +#define   B230400 0010003
12972 +#define   B460800 0010004
12973 +#define   B500000 0010005
12974 +#define   B576000 0010006
12975 +#define   B921600 0010007
12976 +#define  B1000000 0010010
12977 +#define  B1152000 0010011
12978 +#define  B1500000 0010012
12979 +#define  B2000000 0010013
12980 +#define  B2500000 0010014
12981 +#define  B3000000 0010015
12982 +#define  B3500000 0010016
12983 +#define  B4000000 0010017
12984 +#define CIBAUD   002003600000          /* input baud rate */
12985 +#define CMSPAR   010000000000          /* mark or space (stick) parity */
12986 +#define CRTSCTS          020000000000          /* flow control */
12987 +
12988 +#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
12989 +
12990 +/* c_lflag bits */
12991 +#define ISIG   0000001
12992 +#define ICANON 0000002
12993 +#define XCASE  0000004
12994 +#define ECHO   0000010
12995 +#define ECHOE  0000020
12996 +#define ECHOK  0000040
12997 +#define ECHONL 0000100
12998 +#define NOFLSH 0000200
12999 +#define TOSTOP 0000400
13000 +#define ECHOCTL        0001000
13001 +#define ECHOPRT        0002000
13002 +#define ECHOKE 0004000
13003 +#define FLUSHO 0010000
13004 +#define PENDIN 0040000
13005 +#define IEXTEN 0100000
13006 +
13007 +
13008 +/* tcflow() and TCXONC use these */
13009 +#define        TCOOFF          0
13010 +#define        TCOON           1
13011 +#define        TCIOFF          2
13012 +#define        TCION           3
13013 +
13014 +/* tcflush() and TCFLSH use these */
13015 +#define        TCIFLUSH        0
13016 +#define        TCOFLUSH        1
13017 +#define        TCIOFLUSH       2
13018 +
13019 +/* tcsetattr uses these */
13020 +#define        TCSANOW         0
13021 +#define        TCSADRAIN       1
13022 +#define        TCSAFLUSH       2
13023 +
13024 +#endif /* _ASM_UBICOM32_TERMBITS_H */
13025 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/termios.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termios.h
13026 --- linux-2.6.30.10/arch/ubicom32/include/asm/termios.h 1970-01-01 02:00:00.000000000 +0200
13027 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termios.h     2009-12-11 11:45:11.000000000 +0200
13028 @@ -0,0 +1,119 @@
13029 +/*
13030 + * arch/ubicom32/include/asm/termios.h
13031 + *   Ubicom32 termio definitions.
13032 + *
13033 + * (C) Copyright 2009, Ubicom, Inc.
13034 + *
13035 + * This file is part of the Ubicom32 Linux Kernel Port.
13036 + *
13037 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13038 + * it and/or modify it under the terms of the GNU General Public License
13039 + * as published by the Free Software Foundation, either version 2 of the
13040 + * License, or (at your option) any later version.
13041 + *
13042 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13043 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13044 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13045 + * the GNU General Public License for more details.
13046 + *
13047 + * You should have received a copy of the GNU General Public License
13048 + * along with the Ubicom32 Linux Kernel Port.  If not,
13049 + * see <http://www.gnu.org/licenses/>.
13050 + *
13051 + * Ubicom32 implementation derived from (with many thanks):
13052 + *   arch/m68knommu
13053 + *   arch/blackfin
13054 + *   arch/parisc
13055 + */
13056 +#ifndef _ASM_UBICOM32_TERMIOS_H
13057 +#define _ASM_UBICOM32_TERMIOS_H
13058 +
13059 +#include <asm/termbits.h>
13060 +#include <asm/ioctls.h>
13061 +
13062 +struct winsize {
13063 +       unsigned short ws_row;
13064 +       unsigned short ws_col;
13065 +       unsigned short ws_xpixel;
13066 +       unsigned short ws_ypixel;
13067 +};
13068 +
13069 +#define NCC 8
13070 +struct termio {
13071 +       unsigned short c_iflag;         /* input mode flags */
13072 +       unsigned short c_oflag;         /* output mode flags */
13073 +       unsigned short c_cflag;         /* control mode flags */
13074 +       unsigned short c_lflag;         /* local mode flags */
13075 +       unsigned char c_line;           /* line discipline */
13076 +       unsigned char c_cc[NCC];        /* control characters */
13077 +};
13078 +
13079 +#ifdef __KERNEL__
13080 +/*     intr=^C         quit=^|         erase=del       kill=^U
13081 +       eof=^D          vtime=\0        vmin=\1         sxtc=\0
13082 +       start=^Q        stop=^S         susp=^Z         eol=\0
13083 +       reprint=^R      discard=^U      werase=^W       lnext=^V
13084 +       eol2=\0
13085 +*/
13086 +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
13087 +#endif
13088 +
13089 +/* modem lines */
13090 +#define TIOCM_LE       0x001
13091 +#define TIOCM_DTR      0x002
13092 +#define TIOCM_RTS      0x004
13093 +#define TIOCM_ST       0x008
13094 +#define TIOCM_SR       0x010
13095 +#define TIOCM_CTS      0x020
13096 +#define TIOCM_CAR      0x040
13097 +#define TIOCM_RNG      0x080
13098 +#define TIOCM_DSR      0x100
13099 +#define TIOCM_CD       TIOCM_CAR
13100 +#define TIOCM_RI       TIOCM_RNG
13101 +#define TIOCM_OUT1     0x2000
13102 +#define TIOCM_OUT2     0x4000
13103 +#define TIOCM_LOOP     0x8000
13104 +
13105 +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
13106 +
13107 +#ifdef __KERNEL__
13108 +
13109 +/*
13110 + * Translate a "termio" structure into a "termios". Ugh.
13111 + */
13112 +#define user_termio_to_kernel_termios(termios, termio) \
13113 +({ \
13114 +       unsigned short tmp; \
13115 +       get_user(tmp, &(termio)->c_iflag); \
13116 +       (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
13117 +       get_user(tmp, &(termio)->c_oflag); \
13118 +       (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
13119 +       get_user(tmp, &(termio)->c_cflag); \
13120 +       (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
13121 +       get_user(tmp, &(termio)->c_lflag); \
13122 +       (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
13123 +       get_user((termios)->c_line, &(termio)->c_line); \
13124 +       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
13125 +})
13126 +
13127 +/*
13128 + * Translate a "termios" structure into a "termio". Ugh.
13129 + */
13130 +#define kernel_termios_to_user_termio(termio, termios) \
13131 +({ \
13132 +       put_user((termios)->c_iflag, &(termio)->c_iflag); \
13133 +       put_user((termios)->c_oflag, &(termio)->c_oflag); \
13134 +       put_user((termios)->c_cflag, &(termio)->c_cflag); \
13135 +       put_user((termios)->c_lflag, &(termio)->c_lflag); \
13136 +       put_user((termios)->c_line,  &(termio)->c_line); \
13137 +       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
13138 +})
13139 +
13140 +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
13141 +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
13142 +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
13143 +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
13144 +
13145 +#endif /* __KERNEL__ */
13146 +
13147 +#endif /* _ASM_UBICOM32_TERMIOS_H */
13148 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/thread-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread-asm.h
13149 --- linux-2.6.30.10/arch/ubicom32/include/asm/thread-asm.h      1970-01-01 02:00:00.000000000 +0200
13150 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread-asm.h  2009-12-11 11:45:11.000000000 +0200
13151 @@ -0,0 +1,51 @@
13152 +/*
13153 + * arch/ubicom32/include/asm/thread-asm.h
13154 + *   Ubicom32 architecture specific thread definitions.
13155 + *
13156 + * (C) Copyright 2009, Ubicom, Inc.
13157 + *
13158 + * This file is part of the Ubicom32 Linux Kernel Port.
13159 + *
13160 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13161 + * it and/or modify it under the terms of the GNU General Public License
13162 + * as published by the Free Software Foundation, either version 2 of the
13163 + * License, or (at your option) any later version.
13164 + *
13165 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13166 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13167 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13168 + * the GNU General Public License for more details.
13169 + *
13170 + * You should have received a copy of the GNU General Public License
13171 + * along with the Ubicom32 Linux Kernel Port.  If not,
13172 + * see <http://www.gnu.org/licenses/>.
13173 + *
13174 + * Ubicom32 implementation derived from (with many thanks):
13175 + *   arch/m68knommu
13176 + *   arch/blackfin
13177 + *   arch/parisc
13178 + */
13179 +#ifndef _ASM_UBICOM32_THREAD_ASM_H
13180 +#define _ASM_UBICOM32_THREAD_ASM_H
13181 +
13182 +/*
13183 + * thread_get_self
13184 + *     Read and shift the current thread into reg
13185 + *
13186 + * Note that we don't need to mask the result as bits 6 through 31 of the
13187 + * ROSR are zeroes.
13188 + */
13189 +.macro thread_get_self reg
13190 +       lsr.4   \reg, ROSR, #2
13191 +.endm
13192 +
13193 +/*
13194 + * thread_get_self_mask
13195 + *     Read and shift the current thread mask into reg
13196 + */
13197 +.macro thread_get_self_mask reg
13198 +       lsr.4   \reg, ROSR, #2
13199 +       lsl.4   \reg, #1, \reg   /* Thread bit */
13200 +.endm
13201 +
13202 +#endif /* _ASM_UBICOM32_THREAD_ASM_H */
13203 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/thread.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread.h
13204 --- linux-2.6.30.10/arch/ubicom32/include/asm/thread.h  1970-01-01 02:00:00.000000000 +0200
13205 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread.h      2009-12-11 11:45:11.000000000 +0200
13206 @@ -0,0 +1,320 @@
13207 +/*
13208 + * arch/ubicom32/include/asm/thread.h
13209 + *   Ubicom32 architecture specific thread definitions.
13210 + *
13211 + * (C) Copyright 2009, Ubicom, Inc.
13212 + *
13213 + * This file is part of the Ubicom32 Linux Kernel Port.
13214 + *
13215 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13216 + * it and/or modify it under the terms of the GNU General Public License
13217 + * as published by the Free Software Foundation, either version 2 of the
13218 + * License, or (at your option) any later version.
13219 + *
13220 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13221 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13222 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13223 + * the GNU General Public License for more details.
13224 + *
13225 + * You should have received a copy of the GNU General Public License
13226 + * along with the Ubicom32 Linux Kernel Port.  If not,
13227 + * see <http://www.gnu.org/licenses/>.
13228 + *
13229 + * Ubicom32 implementation derived from (with many thanks):
13230 + *   arch/m68knommu
13231 + *   arch/blackfin
13232 + *   arch/parisc
13233 + */
13234 +#ifndef _ASM_UBICOM32_THREAD_H
13235 +#define _ASM_UBICOM32_THREAD_H
13236 +
13237 +#if !defined(__ASSEMBLY__)
13238 +
13239 +#include <asm/ptrace.h>
13240 +#include <asm/ubicom32-common.h>
13241 +
13242 +typedef int thread_t;
13243 +typedef unsigned char thread_type_t;
13244 +typedef void (*thread_exec_fn_t)(void *arg);
13245 +
13246 +#define THREAD_NULL 0x40
13247 +#define THREAD_TYPE_HRT (1 << 0)
13248 +#define THREAD_TYPE_SPECIAL 0
13249 +#define THREAD_TYPE_NORMAL 0
13250 +#define THREAD_TYPE_BACKGROUND (1 << 1)
13251 +
13252 +/*
13253 + * This is the upper bound on the maximum hardware threads that one will find
13254 + * on a Ubicom processor. It is used to size per hardware thread data structures.
13255 + */
13256 +#define THREAD_ARCHITECTURAL_MAX 16
13257 +
13258 +/*
13259 + * TODO: Rename this at some point to be thread_
13260 + */
13261 +extern unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
13262 +
13263 +
13264 +/*
13265 + * thread_get_self()
13266 + */
13267 +static inline thread_t thread_get_self(void)
13268 +{
13269 +       thread_t result;
13270 +
13271 +       /*
13272 +        * Note that ROSR has zeroes in bits 6 through 31 and so we don't need
13273 +        * to do any additional bit masking here.
13274 +        */
13275 +       asm (
13276 +               "lsr.4  %0, ROSR, #2    \n\t"
13277 +               : "=d" (result)
13278 +               :
13279 +               : "cc"
13280 +       );
13281 +
13282 +       return result;
13283 +}
13284 +
13285 +/*
13286 + * thread_suspend()
13287 + */
13288 +static inline void thread_suspend(void)
13289 +{
13290 +       asm volatile (
13291 +               "suspend\n\t"
13292 +               :
13293 +               :
13294 +       );
13295 +}
13296 +
13297 +/*
13298 + * thread_resume()
13299 + */
13300 +static inline void thread_resume(thread_t thread)
13301 +{
13302 +       asm volatile (
13303 +               "move.4         MT_ACTIVE_SET, %0       \n\t"
13304 +               "pipe_flush     0                       \n\t"
13305 +               "pipe_flush     0                       \n\t"
13306 +               :
13307 +               : "d" (1 << thread)
13308 +       );
13309 +}
13310 +
13311 +
13312 +
13313 +/*
13314 + * thread_enable_mask()
13315 + *     Enable all threads in the mask.
13316 + *
13317 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13318 + */
13319 +static inline void thread_enable_mask(unsigned int mask)
13320 +{
13321 +       /*
13322 +        * must flush the pipeline twice.
13323 +        * first pipe_flush is to ensure write to MT_EN is completed
13324 +        * second one is to ensure any new instructions from
13325 +        * the targeted thread (the one being disabled), that
13326 +        * are issued while the write to MT_EN is being executed,
13327 +        * are completed.
13328 +        */
13329 +       UBICOM32_LOCK(MT_EN_LOCK_BIT);
13330 +       asm volatile (
13331 +               "or.4           MT_EN, MT_EN, %0        \n\t"
13332 +               "pipe_flush     0                       \n\t"
13333 +               "pipe_flush     0                       \n\t"
13334 +               :
13335 +               : "d" (mask)
13336 +               : "cc"
13337 +       );
13338 +       UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13339 +}
13340 +
13341 +/*
13342 + * thread_enable()
13343 + */
13344 +static inline void thread_enable(thread_t thread)
13345 +{
13346 +       thread_enable_mask(1 << thread);
13347 +}
13348 +
13349 +/*
13350 + * thread_disable_mask()
13351 + *     Disable all threads in the mask.
13352 + *
13353 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13354 + */
13355 +static inline void thread_disable_mask(unsigned int mask)
13356 +{
13357 +       /*
13358 +        * must flush the pipeline twice.
13359 +        * first pipe_flush is to ensure write to MT_EN is completed
13360 +        * second one is to ensure any new instructions from
13361 +        * the targeted thread (the one being disabled), that
13362 +        * are issued while the write to MT_EN is being executed,
13363 +        * are completed.
13364 +        */
13365 +       UBICOM32_LOCK(MT_EN_LOCK_BIT);
13366 +       asm volatile (
13367 +               "and.4          MT_EN, MT_EN, %0        \n\t"
13368 +               "pipe_flush     0                       \n\t"
13369 +               "pipe_flush     0                       \n\t"
13370 +               :
13371 +               : "d" (~mask)
13372 +               : "cc"
13373 +       );
13374 +       UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13375 +}
13376 +
13377 +/*
13378 + * thread_disable()
13379 + */
13380 +static inline void thread_disable(thread_t thread)
13381 +{
13382 +       thread_disable_mask(1 << thread);
13383 +}
13384 +
13385 +/*
13386 + * thread_disable_others()
13387 + *     Disable all other threads
13388 + */
13389 +static inline void thread_disable_others(void)
13390 +{
13391 +       thread_t self = thread_get_self();
13392 +       thread_disable_mask(~(1 << self));
13393 +}
13394 +
13395 +/*
13396 + * thread_is_trapped()
13397 + *     Is the specified tid trapped?
13398 + */
13399 +static inline int thread_is_trapped(thread_t tid)
13400 +{
13401 +       int thread_mask = (1 << tid);
13402 +       int trap_thread;
13403 +
13404 +       asm (
13405 +               "move.4         %0, MT_TRAP             \n\t"
13406 +               : "=d" (trap_thread)
13407 +               :
13408 +       );
13409 +       return (trap_thread & thread_mask);
13410 +}
13411 +
13412 +/*
13413 + * thread_is_enabled()
13414 + *     Is the specified tid enabled?
13415 + */
13416 +static inline int thread_is_enabled(thread_t tid)
13417 +{
13418 +       int thread_mask = (1 << tid);
13419 +       int enabled_threads;
13420 +
13421 +       asm (
13422 +               "move.4         %0, MT_EN               \n\t"
13423 +               : "=d" (enabled_threads)
13424 +               :
13425 +       );
13426 +       return (enabled_threads & thread_mask);
13427 +}
13428 +
13429 +/*
13430 + * thread_get_instruction_count()
13431 + */
13432 +static inline unsigned int thread_get_instruction_count(void)
13433 +{
13434 +       unsigned int result;
13435 +       asm (
13436 +               "move.4         %0, INST_CNT            \n\t"
13437 +               : "=r" (result)
13438 +       );
13439 +       return result;
13440 +}
13441 +
13442 +/*
13443 + * thread_get_pc()
13444 + *     pc could point to a speculative and cancelled instruction unless thread is disabled
13445 + */
13446 +static inline void *thread_get_pc(thread_t thread)
13447 +{
13448 +       void *result;
13449 +       asm (
13450 +               "move.4         csr, %1         \n\t"
13451 +               "setcsr_flush   0               \n\t"
13452 +               "move.4         %0, pc          \n\t"
13453 +               "move.4         csr, #0         \n\t"
13454 +               "setcsr_flush   0               \n\t"
13455 +               : "=r" (result)
13456 +               : "r" ((thread << 9) | (1 << 8))
13457 +       );
13458 +       return result;
13459 +}
13460 +
13461 +/*
13462 + * thread_get_trap_cause()
13463 + *     This should be called only when the thread is not running
13464 + */
13465 +static inline unsigned int thread_get_trap_cause(thread_t thread)
13466 +{
13467 +       unsigned int result;
13468 +       asm (
13469 +               "move.4         csr, %1         \n\t"
13470 +               "setcsr_flush   0               \n\t"
13471 +               "move.4         %0, trap_cause  \n\t"
13472 +               "move.4         csr, #0         \n\t"
13473 +               "setcsr_flush   0               \n\t"
13474 +               : "=r" (result)
13475 +               : "r" ((thread << 9) | (1 << 8))
13476 +       );
13477 +       return result;
13478 +}
13479 +
13480 +/*
13481 + * THREAD_STALL macro.
13482 + */
13483 +#define THREAD_STALL \
13484 +               asm volatile ( \
13485 +                       "move.4 mt_dbg_active_clr, #-1  \n\t" \
13486 +                       "pipe_flush 0                   \n\t" \
13487 +                       : \
13488 +                       : \
13489 +               )
13490 +
13491 +extern unsigned int thread_get_mainline(void);
13492 +extern void thread_set_mainline(thread_t tid);
13493 +extern thread_t thread_alloc(void);
13494 +extern thread_t thread_start(thread_t thread, thread_exec_fn_t exec, void *arg, unsigned int *sp_high, thread_type_t type);
13495 +
13496 +/*
13497 + * asm macros
13498 + */
13499 +asm (
13500 +/*
13501 + * thread_get_self
13502 + *     Read and shift the current thread into reg
13503 + *
13504 + * Note that we don't need to mask the result as bits 6 through 31 of the
13505 + * ROSR are zeroes.
13506 + */
13507 +".macro        thread_get_self reg             \n\t"
13508 +"      lsr.4   \\reg, ROSR, #2         \n\t"
13509 +".endm                                 \n\t"
13510 +
13511 +/*
13512 + * thread_get_self_mask
13513 + *     Read and shift the current thread mask into reg
13514 + */
13515 +".macro        thread_get_self_mask reg        \n\t"
13516 +"      lsr.4   \\reg, ROSR, #2         \n\t"
13517 +"      lsl.4   \\reg, #1, \\reg        \n\t"    /* Thread bit */
13518 +".endm                                 \n\t"
13519 +);
13520 +
13521 +#else /* __ASSEMBLY__ */
13522 +
13523 +#include <asm/thread-asm.h>
13524 +
13525 +#endif /* __ASSEMBLY__ */
13526 +#endif /* _ASM_UBICOM32_THREAD_H */
13527 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/thread_info.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread_info.h
13528 --- linux-2.6.30.10/arch/ubicom32/include/asm/thread_info.h     1970-01-01 02:00:00.000000000 +0200
13529 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread_info.h 2009-12-11 11:45:11.000000000 +0200
13530 @@ -0,0 +1,134 @@
13531 +/*
13532 + * arch/ubicom32/include/asm/thread_info.h
13533 + *   Ubicom32 architecture low-level thread information.
13534 + *
13535 + * (C) Copyright 2009, Ubicom, Inc.
13536 + * Adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
13537 + * Copyright (C) 2002  David Howells (dhowells@redhat.com)
13538 + * - Incorporating suggestions made by Linus Torvalds and Dave Miller
13539 + *
13540 + * This file is part of the Ubicom32 Linux Kernel Port.
13541 + *
13542 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13543 + * it and/or modify it under the terms of the GNU General Public License
13544 + * as published by the Free Software Foundation, either version 2 of the
13545 + * License, or (at your option) any later version.
13546 + *
13547 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13548 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13549 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13550 + * the GNU General Public License for more details.
13551 + *
13552 + * You should have received a copy of the GNU General Public License
13553 + * along with the Ubicom32 Linux Kernel Port.  If not,
13554 + * see <http://www.gnu.org/licenses/>.
13555 + *
13556 + * Ubicom32 implementation derived from (with many thanks):
13557 + *   arch/m68knommu
13558 + *   arch/blackfin
13559 + *   arch/parisc
13560 + */
13561 +
13562 +#ifndef _ASM_UBICOM32_THREAD_INFO_H
13563 +#define _ASM_UBICOM32_THREAD_INFO_H
13564 +
13565 +#include <asm/page.h>
13566 +
13567 +/*
13568 + * Size of kernel stack for each process. This must be a power of 2...
13569 + */
13570 +#ifdef CONFIG_4KSTACKS
13571 +#define THREAD_SIZE_ORDER (0)
13572 +#else
13573 +#define THREAD_SIZE_ORDER (1)
13574 +#endif
13575 +
13576 +/*
13577 + * for asm files, THREAD_SIZE is now generated by asm-offsets.c
13578 + */
13579 +#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
13580 +
13581 +#ifdef __KERNEL__
13582 +
13583 +#ifndef __ASSEMBLY__
13584 +
13585 +/*
13586 + * low level task data.
13587 + */
13588 +struct thread_info {
13589 +       struct task_struct *task;               /* main task structure */
13590 +       struct exec_domain *exec_domain;        /* execution domain */
13591 +       unsigned long      flags;               /* low level flags */
13592 +       int                cpu;                 /* cpu we're on */
13593 +       int                preempt_count;       /* 0 => preemptable, <0 => BUG */
13594 +       int                interrupt_nesting;   /* Interrupt nesting level. */
13595 +       struct restart_block restart_block;
13596 +};
13597 +
13598 +/*
13599 + * macros/functions for gaining access to the thread information structure
13600 + */
13601 +#define INIT_THREAD_INFO(tsk)                  \
13602 +{                                              \
13603 +       .task           = &tsk,                 \
13604 +       .exec_domain    = &default_exec_domain, \
13605 +       .flags          = 0,                    \
13606 +       .cpu            = 0,                    \
13607 +       .interrupt_nesting      = 0,            \
13608 +       .restart_block  = {                     \
13609 +               .fn = do_no_restart_syscall,    \
13610 +       },                                      \
13611 +}
13612 +
13613 +#define init_thread_info       (init_thread_union.thread_info)
13614 +#define init_stack             (init_thread_union.stack)
13615 +
13616 +
13617 +/* how to get the thread information struct from C */
13618 +static inline struct thread_info *current_thread_info(void)
13619 +{
13620 +       struct thread_info *ti;
13621 +
13622 +       asm (
13623 +               "and.4  %0, sp, %1\n\t"
13624 +               : "=&r" (ti)
13625 +               : "d" (~(THREAD_SIZE-1))
13626 +               : "cc"
13627 +       );
13628 +
13629 +       return ti;
13630 +}
13631 +
13632 +#define STACK_WARN (THREAD_SIZE / 8)
13633 +
13634 +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR 1
13635 +
13636 +/* thread information allocation */
13637 +#define alloc_thread_info(tsk) ((struct thread_info *) \
13638 +                               __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
13639 +#define free_thread_info(ti)   free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
13640 +#endif /* __ASSEMBLY__ */
13641 +
13642 +#define        PREEMPT_ACTIVE  0x4000000
13643 +
13644 +/*
13645 + * thread information flag bit numbers
13646 + */
13647 +#define TIF_SYSCALL_TRACE      0       /* syscall trace active */
13648 +#define TIF_SIGPENDING         1       /* signal pending */
13649 +#define TIF_NEED_RESCHED       2       /* rescheduling necessary */
13650 +#define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
13651 +                                          TIF_NEED_RESCHED */
13652 +#define TIF_MEMDIE             4
13653 +
13654 +/* as above, but as bit values */
13655 +#define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
13656 +#define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
13657 +#define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
13658 +#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
13659 +
13660 +#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
13661 +
13662 +#endif /* __KERNEL__ */
13663 +
13664 +#endif /* _ASM_UBICOM32_THREAD_INFO_H */
13665 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/timex.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/timex.h
13666 --- linux-2.6.30.10/arch/ubicom32/include/asm/timex.h   1970-01-01 02:00:00.000000000 +0200
13667 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/timex.h       2009-12-11 11:45:11.000000000 +0200
13668 @@ -0,0 +1,56 @@
13669 +/*
13670 + * arch/ubicom32/include/asm/timex.h
13671 + *   Ubicom32 architecture timex specifications.
13672 + *
13673 + * (C) Copyright 2009, Ubicom, Inc.
13674 + *
13675 + * This file is part of the Ubicom32 Linux Kernel Port.
13676 + *
13677 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13678 + * it and/or modify it under the terms of the GNU General Public License
13679 + * as published by the Free Software Foundation, either version 2 of the
13680 + * License, or (at your option) any later version.
13681 + *
13682 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13683 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13684 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13685 + * the GNU General Public License for more details.
13686 + *
13687 + * You should have received a copy of the GNU General Public License
13688 + * along with the Ubicom32 Linux Kernel Port.  If not,
13689 + * see <http://www.gnu.org/licenses/>.
13690 + *
13691 + * Ubicom32 implementation derived from (with many thanks):
13692 + *   arch/m68knommu
13693 + *   arch/blackfin
13694 + *   arch/parisc
13695 + */
13696 +#ifndef _ASM_UBICOM32_TIMEX_H
13697 +#define _ASM_UBICOM32_TIMEX_H
13698 +
13699 +#define CLOCK_TICK_RATE        266000000
13700 +
13701 +// #define ARCH_HAS_READ_CURRENT_TIMER
13702 +
13703 +typedef unsigned long cycles_t;
13704 +
13705 +static inline cycles_t get_cycles(void)
13706 +{
13707 +       return 0;
13708 +}
13709 +
13710 +extern int timer_alloc(void);
13711 +extern void timer_set(int timervector, unsigned int cycles);
13712 +extern int timer_reset(int timervector, unsigned int cycles);
13713 +extern void timer_tick_init(void);
13714 +extern void timer_device_init(void);
13715 +
13716 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13717 +extern void local_timer_interrupt(void);
13718 +#endif
13719 +
13720 +#if defined(CONFIG_LOCAL_TIMERS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13721 +extern int local_timer_setup(unsigned int cpu);
13722 +#endif
13723 +
13724 +#endif /* _ASM_UBICOM32_TIMEX_H */
13725 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/tlbflush.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlbflush.h
13726 --- linux-2.6.30.10/arch/ubicom32/include/asm/tlbflush.h        1970-01-01 02:00:00.000000000 +0200
13727 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlbflush.h    2009-12-11 11:45:11.000000000 +0200
13728 @@ -0,0 +1,79 @@
13729 +/*
13730 + * arch/ubicom32/include/asm/tlbflush.h
13731 + *   TLB operations for Ubicom32 architecture.
13732 + *
13733 + * (C) Copyright 2009, Ubicom, Inc.
13734 + * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
13735 + * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
13736 + *
13737 + * This file is part of the Ubicom32 Linux Kernel Port.
13738 + *
13739 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13740 + * it and/or modify it under the terms of the GNU General Public License
13741 + * as published by the Free Software Foundation, either version 2 of the
13742 + * License, or (at your option) any later version.
13743 + *
13744 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13745 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13746 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13747 + * the GNU General Public License for more details.
13748 + *
13749 + * You should have received a copy of the GNU General Public License
13750 + * along with the Ubicom32 Linux Kernel Port.  If not,
13751 + * see <http://www.gnu.org/licenses/>.
13752 + *
13753 + * Ubicom32 implementation derived from (with many thanks):
13754 + *   arch/m68knommu
13755 + *   arch/blackfin
13756 + *   arch/parisc
13757 + */
13758 +#ifndef _ASM_UBICOM32_TLB_FLUSH_H
13759 +#define _ASM_UBICOM32_TLB_FLUSH_H
13760 +
13761 +#include <asm/setup.h>
13762 +
13763 +/*
13764 + * flush all user-space atc entries.
13765 + */
13766 +static inline void __flush_tlb(void)
13767 +{
13768 +       BUG();
13769 +}
13770 +
13771 +static inline void __flush_tlb_one(unsigned long addr)
13772 +{
13773 +       BUG();
13774 +}
13775 +
13776 +#define flush_tlb() __flush_tlb()
13777 +
13778 +/*
13779 + * flush all atc entries (both kernel and user-space entries).
13780 + */
13781 +static inline void flush_tlb_all(void)
13782 +{
13783 +       BUG();
13784 +}
13785 +
13786 +static inline void flush_tlb_mm(struct mm_struct *mm)
13787 +{
13788 +       BUG();
13789 +}
13790 +
13791 +static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
13792 +{
13793 +       BUG();
13794 +}
13795 +
13796 +static inline void flush_tlb_range(struct mm_struct *mm,
13797 +                                  unsigned long start, unsigned long end)
13798 +{
13799 +       BUG();
13800 +}
13801 +
13802 +static inline void flush_tlb_kernel_page(unsigned long addr)
13803 +{
13804 +       BUG();
13805 +}
13806 +
13807 +#endif /* _ASM_UBICOM32_TLB_FLUSH_H */
13808 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/tlb.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlb.h
13809 --- linux-2.6.30.10/arch/ubicom32/include/asm/tlb.h     1970-01-01 02:00:00.000000000 +0200
13810 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlb.h 2009-12-11 11:45:11.000000000 +0200
13811 @@ -0,0 +1,47 @@
13812 +/*
13813 + * arch/ubicom32/include/asm/tlb.h
13814 + *   Ubicom32 architecture TLB operations.
13815 + *
13816 + * (C) Copyright 2009, Ubicom, Inc.
13817 + *
13818 + * This file is part of the Ubicom32 Linux Kernel Port.
13819 + *
13820 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13821 + * it and/or modify it under the terms of the GNU General Public License
13822 + * as published by the Free Software Foundation, either version 2 of the
13823 + * License, or (at your option) any later version.
13824 + *
13825 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13826 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13827 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13828 + * the GNU General Public License for more details.
13829 + *
13830 + * You should have received a copy of the GNU General Public License
13831 + * along with the Ubicom32 Linux Kernel Port.  If not,
13832 + * see <http://www.gnu.org/licenses/>.
13833 + *
13834 + * Ubicom32 implementation derived from (with many thanks):
13835 + *   arch/m68knommu
13836 + *   arch/blackfin
13837 + *   arch/parisc
13838 + */
13839 +#ifndef _ASM_UBICOM32_TLB_H
13840 +#define _ASM_UBICOM32_TLB_H
13841 +
13842 +/*
13843 + * ubicom32 doesn't need any special per-pte or
13844 + * per-vma handling..
13845 + */
13846 +#define tlb_start_vma(tlb, vma)        do { } while (0)
13847 +#define tlb_end_vma(tlb, vma)  do { } while (0)
13848 +#define __tlb_remove_tlb_entry(tlb, ptep, address)     do { } while (0)
13849 +
13850 +/*
13851 + * .. because we flush the whole mm when it
13852 + * fills up.
13853 + */
13854 +#define tlb_flush(tlb)
13855 +
13856 +#include <asm-generic/tlb.h>
13857 +
13858 +#endif /* _ASM_UBICOM32_TLB_H */
13859 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/topology.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/topology.h
13860 --- linux-2.6.30.10/arch/ubicom32/include/asm/topology.h        1970-01-01 02:00:00.000000000 +0200
13861 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/topology.h    2009-12-11 11:45:11.000000000 +0200
13862 @@ -0,0 +1,33 @@
13863 +/*
13864 + * arch/ubicom32/include/asm/topology.h
13865 + *   Generic topology.h definitions for Ubicom32 architecture.
13866 + *
13867 + * (C) Copyright 2009, Ubicom, Inc.
13868 + *
13869 + * This file is part of the Ubicom32 Linux Kernel Port.
13870 + *
13871 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13872 + * it and/or modify it under the terms of the GNU General Public License
13873 + * as published by the Free Software Foundation, either version 2 of the
13874 + * License, or (at your option) any later version.
13875 + *
13876 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13877 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13878 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13879 + * the GNU General Public License for more details.
13880 + *
13881 + * You should have received a copy of the GNU General Public License
13882 + * along with the Ubicom32 Linux Kernel Port.  If not,
13883 + * see <http://www.gnu.org/licenses/>.
13884 + *
13885 + * Ubicom32 implementation derived from (with many thanks):
13886 + *   arch/m68knommu
13887 + *   arch/blackfin
13888 + *   arch/parisc
13889 + */
13890 +#ifndef _ASM_UBICOM32_TOPOLOGY_H
13891 +#define _ASM_UBICOM32_TOPOLOGY_H
13892 +
13893 +#include <asm-generic/topology.h>
13894 +
13895 +#endif /* _ASM_UBICOM32_TOPOLOGY_H */
13896 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/traps.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/traps.h
13897 --- linux-2.6.30.10/arch/ubicom32/include/asm/traps.h   1970-01-01 02:00:00.000000000 +0200
13898 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/traps.h       2009-12-11 11:45:11.000000000 +0200
13899 @@ -0,0 +1,55 @@
13900 +/*
13901 + * arch/ubicom32/include/asm/traps.h
13902 + *   Trap related definitions for Ubicom32 architecture.
13903 + *
13904 + * (C) Copyright 2009, Ubicom, Inc.
13905 + *
13906 + * This file is part of the Ubicom32 Linux Kernel Port.
13907 + *
13908 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13909 + * it and/or modify it under the terms of the GNU General Public License
13910 + * as published by the Free Software Foundation, either version 2 of the
13911 + * License, or (at your option) any later version.
13912 + *
13913 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13914 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13915 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13916 + * the GNU General Public License for more details.
13917 + *
13918 + * You should have received a copy of the GNU General Public License
13919 + * along with the Ubicom32 Linux Kernel Port.  If not,
13920 + * see <http://www.gnu.org/licenses/>.
13921 + *
13922 + * Ubicom32 implementation derived from (with many thanks):
13923 + *   arch/m68knommu
13924 + *   arch/blackfin
13925 + *   arch/parisc
13926 + */
13927 +
13928 +#ifndef _ASM_UBICOM32_TRAPS_H
13929 +#define _ASM_UBICOM32_TRAPS_H
13930 +
13931 +/*
13932 + * Trap causes passed from ultra to Host OS
13933 + */
13934 +#define TRAP_CAUSE_TOTAL               13
13935 +#define TRAP_CAUSE_DST_RANGE_ERR       12
13936 +#define TRAP_CAUSE_SRC1_RANGE_ERR      11
13937 +#define TRAP_CAUSE_I_RANGE_ERR         10
13938 +#define TRAP_CAUSE_DCAPT               9
13939 +#define TRAP_CAUSE_DST_SERROR          8
13940 +#define TRAP_CAUSE_SRC1_SERROR         7
13941 +#define TRAP_CAUSE_DST_MISALIGNED      6
13942 +#define TRAP_CAUSE_SRC1_MISALIGNED     5
13943 +#define TRAP_CAUSE_DST_DECODE_ERR      4
13944 +#define TRAP_CAUSE_SRC1_DECODE_ERR     3
13945 +#define TRAP_CAUSE_ILLEGAL_INST                2
13946 +#define TRAP_CAUSE_I_SERROR            1
13947 +#define TRAP_CAUSE_I_DECODE_ERR                0
13948 +
13949 +extern void trap_handler(int irq, struct pt_regs *regs);
13950 +extern void trap_init_interrupt(void);
13951 +extern void unaligned_emulate(unsigned int thread);
13952 +extern int unaligned_only(unsigned int cause);
13953 +
13954 +#endif /* _ASM_UBICOM32_TRAPS_H */
13955 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/types.h
13956 --- linux-2.6.30.10/arch/ubicom32/include/asm/types.h   1970-01-01 02:00:00.000000000 +0200
13957 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/types.h       2009-12-11 11:45:11.000000000 +0200
13958 @@ -0,0 +1,75 @@
13959 +/*
13960 + * arch/ubicom32/include/asm/types.h
13961 + *   Date type definitions for Ubicom32 architecture.
13962 + *
13963 + * (C) Copyright 2009, Ubicom, Inc.
13964 + *
13965 + * This file is part of the Ubicom32 Linux Kernel Port.
13966 + *
13967 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13968 + * it and/or modify it under the terms of the GNU General Public License
13969 + * as published by the Free Software Foundation, either version 2 of the
13970 + * License, or (at your option) any later version.
13971 + *
13972 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13973 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13974 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13975 + * the GNU General Public License for more details.
13976 + *
13977 + * You should have received a copy of the GNU General Public License
13978 + * along with the Ubicom32 Linux Kernel Port.  If not,
13979 + * see <http://www.gnu.org/licenses/>.
13980 + *
13981 + * Ubicom32 implementation derived from (with many thanks):
13982 + *   arch/m68knommu
13983 + *   arch/blackfin
13984 + *   arch/parisc
13985 + */
13986 +#ifndef _ASM_UBICOM32_TYPES_H
13987 +#define _ASM_UBICOM32_TYPES_H
13988 +
13989 +/*
13990 + * This file is never included by application software unless
13991 + * explicitly requested (e.g., via linux/types.h) in which case the
13992 + * application is Linux specific so (user-) name space pollution is
13993 + * not a major issue.  However, for interoperability, libraries still
13994 + * need to be careful to avoid a name clashes.
13995 + */
13996 +
13997 +#include <asm-generic/int-ll64.h>
13998 +
13999 +#ifndef __ASSEMBLY__
14000 +
14001 +typedef unsigned short umode_t;
14002 +
14003 +#endif /* __ASSEMBLY__ */
14004 +
14005 +/*
14006 + * These aren't exported outside the kernel to avoid name space clashes
14007 + */
14008 +#ifdef __KERNEL__
14009 +
14010 +#define BITS_PER_LONG 32
14011 +
14012 +#ifndef __ASSEMBLY__
14013 +
14014 +/* DMA addresses are always 32-bits wide */
14015 +
14016 +typedef u32 dma_addr_t;
14017 +typedef u32 dma64_addr_t;
14018 +
14019 +/*
14020 + * XXX These are "Ubicom style" typedefs. They should be removed in all files used by linux.
14021 + */
14022 +typedef u32 u32_t;
14023 +typedef s32 s32_t;
14024 +typedef u16 u16_t;
14025 +typedef s16 s16_t;
14026 +typedef u8 u8_t;
14027 +typedef s8 s8_t;
14028 +
14029 +#endif /* __ASSEMBLY__ */
14030 +
14031 +#endif /* __KERNEL__ */
14032 +
14033 +#endif /* _ASM_UBICOM32_TYPES_H */
14034 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/uaccess.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uaccess.h
14035 --- linux-2.6.30.10/arch/ubicom32/include/asm/uaccess.h 1970-01-01 02:00:00.000000000 +0200
14036 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uaccess.h     2009-12-11 11:45:11.000000000 +0200
14037 @@ -0,0 +1,347 @@
14038 +/*
14039 + * arch/ubicom32/include/asm/uaccess.h
14040 + *   User space memory access functions for Ubicom32 architecture.
14041 + *
14042 + * (C) Copyright 2009, Ubicom, Inc.
14043 + *
14044 + * This file is part of the Ubicom32 Linux Kernel Port.
14045 + *
14046 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14047 + * it and/or modify it under the terms of the GNU General Public License
14048 + * as published by the Free Software Foundation, either version 2 of the
14049 + * License, or (at your option) any later version.
14050 + *
14051 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14052 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14053 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14054 + * the GNU General Public License for more details.
14055 + *
14056 + * You should have received a copy of the GNU General Public License
14057 + * along with the Ubicom32 Linux Kernel Port.  If not,
14058 + * see <http://www.gnu.org/licenses/>.
14059 + *
14060 + * Ubicom32 implementation derived from (with many thanks):
14061 + *   arch/m68knommu
14062 + *   arch/blackfin
14063 + *   arch/parisc
14064 + *   arch/alpha
14065 + */
14066 +#ifndef _ASM_UBICOM32_UACCESS_H
14067 +#define _ASM_UBICOM32_UACCESS_H
14068 +
14069 +/*
14070 + * User space memory access functions
14071 + */
14072 +#include <linux/sched.h>
14073 +#include <linux/mm.h>
14074 +#include <linux/string.h>
14075 +
14076 +#include <asm/segment.h>
14077 +
14078 +#define VERIFY_READ    0
14079 +#define VERIFY_WRITE   1
14080 +
14081 +/*
14082 + * The exception table consists of pairs of addresses: the first is the
14083 + * address of an instruction that is allowed to fault, and the second is
14084 + * the address at which the program should continue.  No registers are
14085 + * modified, so it is entirely up to the continuation code to figure out
14086 + * what to do.
14087 + *
14088 + * All the routines below use bits of fixup code that are out of line
14089 + * with the main instruction path.  This means when everything is well,
14090 + * we don't even have to jump over them.  Further, they do not intrude
14091 + * on our cache or tlb entries.
14092 + */
14093 +struct exception_table_entry
14094 +{
14095 +       unsigned long insn, fixup;
14096 +};
14097 +
14098 +/*
14099 + * Ubicom32 does not currently support the exception table handling.
14100 + */
14101 +extern unsigned long search_exception_table(unsigned long);
14102 +
14103 +
14104 +#if defined(CONFIG_ACCESS_OK_CHECKS_ENABLED)
14105 +extern int __access_ok(unsigned long addr, unsigned long size);
14106 +#else
14107 +static inline int __access_ok(unsigned long addr, unsigned long size)
14108 +{
14109 +       return 1;
14110 +}
14111 +#endif
14112 +#define access_ok(type, addr, size) \
14113 +       likely(__access_ok((unsigned long)(addr), (size)))
14114 +
14115 +/*
14116 + * The following functions do not exist.  They keep callers
14117 + * of put_user and get_user from passing unsupported argument
14118 + * types.  They result in a link time error.
14119 + */
14120 +extern int __put_user_bad(void);
14121 +extern int __get_user_bad(void);
14122 +
14123 +/*
14124 + * __put_user_no_check()
14125 + *     Put the requested data into the user space verifying the address
14126 + *
14127 + * Careful to not
14128 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
14129 + * (b) require any knowledge of processes at this stage
14130 + */
14131 +#define __put_user_no_check(x, ptr, size)              \
14132 +({                                                     \
14133 +       int __pu_err = 0;                               \
14134 +       __typeof__(*(ptr)) __user *__pu_addr = (ptr);   \
14135 +       switch (size) {                                 \
14136 +       case 1:                                         \
14137 +       case 2:                                         \
14138 +       case 4:                                         \
14139 +       case 8:                                         \
14140 +               *__pu_addr = (__typeof__(*(ptr)))x;     \
14141 +               break;                                  \
14142 +       default:                                        \
14143 +               __pu_err = __put_user_bad();            \
14144 +               break;                                  \
14145 +       }                                               \
14146 +       __pu_err;                                       \
14147 +})
14148 +
14149 +/*
14150 + * __put_user_check()
14151 + *     Put the requested data into the user space verifying the address
14152 + *
14153 + * Careful to not
14154 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
14155 + * (b) require any knowledge of processes at this stage
14156 + *
14157 + * If requested, access_ok() will verify that ptr is a valid user
14158 + * pointer.
14159 + */
14160 +#define __put_user_check(x, ptr, size)                         \
14161 +({                                                             \
14162 +       int __pu_err = -EFAULT;                                 \
14163 +       __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
14164 +       if (access_ok(VERIFY_WRITE, __pu_addr, size)) {         \
14165 +               __pu_err = 0;                                   \
14166 +               switch (size) {                                 \
14167 +               case 1:                                         \
14168 +               case 2:                                         \
14169 +               case 4:                                         \
14170 +               case 8:                                         \
14171 +                       *__pu_addr = (__typeof__(*(ptr)))x;     \
14172 +                       break;                                  \
14173 +               default:                                        \
14174 +                       __pu_err = __put_user_bad();            \
14175 +                       break;                                  \
14176 +               }                                               \
14177 +       }                                                       \
14178 +       __pu_err;                                               \
14179 +})
14180 +
14181 +/*
14182 + * __get_user_no_check()
14183 + *     Read the value at ptr into x.
14184 + *
14185 + * If requested, access_ok() will verify that ptr is a valid user
14186 + * pointer.  If the caller passes a modifying argument for ptr (e.g. x++)
14187 + * this macro will not work.
14188 + */
14189 +#define __get_user_no_check(x, ptr, size)                      \
14190 +({                                                             \
14191 +       int __gu_err = 0;                                       \
14192 +       __typeof__((x)) __gu_val = 0;                           \
14193 +       const __typeof__(*(ptr)) __user *__gu_addr = (ptr);     \
14194 +       switch (size) {                                         \
14195 +       case 1:                                                 \
14196 +       case 2:                                                 \
14197 +       case 4:                                                 \
14198 +       case 8:                                                 \
14199 +               __gu_val = (__typeof__((x)))*(__gu_addr);       \
14200 +               break;                                          \
14201 +       default:                                                \
14202 +               __gu_err = __get_user_bad();                    \
14203 +               (x) = 0;                                        \
14204 +               break;                                          \
14205 +       }                                                       \
14206 +       (x) = __gu_val;                                         \
14207 +       __gu_err;                                               \
14208 +})
14209 +
14210 +/*
14211 + * __get_user_check()
14212 + *     Read the value at ptr into x.
14213 + *
14214 + * If requested, access_ok() will verify that ptr is a valid user
14215 + * pointer.
14216 + */
14217 +#define __get_user_check(x, ptr, size)                                 \
14218 +({                                                                     \
14219 +       int __gu_err = -EFAULT;                                         \
14220 +       __typeof__(x) __gu_val = 0;                                     \
14221 +       const __typeof__(*(ptr)) __user *__gu_addr = (ptr);             \
14222 +       if (access_ok(VERIFY_READ, __gu_addr, size)) {                  \
14223 +               __gu_err = 0;                                           \
14224 +               switch (size) {                                         \
14225 +               case 1:                                                 \
14226 +               case 2:                                                 \
14227 +               case 4:                                                 \
14228 +               case 8:                                                 \
14229 +                       __gu_val = (__typeof__((x)))*(__gu_addr);       \
14230 +                       break;                                          \
14231 +               default:                                                \
14232 +                       __gu_err = __get_user_bad();                    \
14233 +                       (x) = 0;                                        \
14234 +                       break;                                          \
14235 +               }                                                       \
14236 +       }                                                               \
14237 +       (x) = __gu_val;                                                 \
14238 +       __gu_err;                                                       \
14239 +})
14240 +
14241 +/*
14242 + * The "xxx" versions are allowed to perform some amount of address
14243 + * space checking.  See access_ok().
14244 + */
14245 +#define put_user(x,ptr) \
14246 +       __put_user_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14247 +#define get_user(x,ptr) \
14248 +       __get_user_check((x), (ptr), sizeof(*(ptr)))
14249 +
14250 +/*
14251 + * The "__xxx" versions do not do address space checking, useful when
14252 + * doing multiple accesses to the same area (the programmer has to do the
14253 + * checks by hand with "access_ok()")
14254 + */
14255 +#define __put_user(x,ptr) \
14256 +       __put_user_no_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14257 +#define __get_user(x,ptr) \
14258 +       __get_user_no_check((x), (ptr), sizeof(*(ptr)))
14259 +
14260 +/*
14261 + * __copy_tofrom_user_no_check()
14262 + *     Copy the data either to or from user space.
14263 + *
14264 + * Return the number of bytes NOT copied.
14265 + */
14266 +static inline unsigned long
14267 +__copy_tofrom_user_no_check(void *to, const void *from, unsigned long n)
14268 +{
14269 +       memcpy(to, from, n);
14270 +       return 0;
14271 +}
14272 +
14273 +/*
14274 + * copy_to_user()
14275 + *     Copy the kernel data to user space.
14276 + *
14277 + * Return the number of bytes that were copied.
14278 + */
14279 +static inline unsigned long
14280 +copy_to_user(void __user *to, const void *from, unsigned long n)
14281 +{
14282 +       if (!access_ok(VERIFY_WRITE, to, n)) {
14283 +               return n;
14284 +       }
14285 +       return __copy_tofrom_user_no_check((__force void *)to, from, n);
14286 +}
14287 +
14288 +/*
14289 + * copy_from_user()
14290 + *     Copy the user data to kernel space.
14291 + *
14292 + * Return the number of bytes that were copied.  On error, we zero
14293 + * out the destination.
14294 + */
14295 +static inline unsigned long
14296 +copy_from_user(void *to, const void __user *from, unsigned long n)
14297 +{
14298 +       if (!access_ok(VERIFY_READ, from, n)) {
14299 +               return n;
14300 +       }
14301 +       return __copy_tofrom_user_no_check(to, (__force void *)from, n);
14302 +}
14303 +
14304 +#define __copy_to_user(to, from, n) \
14305 +       __copy_tofrom_user_no_check((__force void *)to, from, n)
14306 +#define __copy_from_user(to, from, n) \
14307 +       __copy_tofrom_user_no_check(to, (__force void *)from, n)
14308 +#define __copy_to_user_inatomic(to, from, n) \
14309 +       __copy_tofrom_user_no_check((__force void *)to, from, n)
14310 +#define __copy_from_user_inatomic(to, from, n) \
14311 +       __copy_tofrom_user_no_check(to, (__force void *)from, n)
14312 +
14313 +#define copy_to_user_ret(to, from, n, retval) \
14314 +       ({ if (copy_to_user(to, from, n)) return retval; })
14315 +
14316 +#define copy_from_user_ret(to, from, n, retval) \
14317 +       ({ if (copy_from_user(to, from, n)) return retval; })
14318 +
14319 +/*
14320 + * strncpy_from_user()
14321 + *     Copy a null terminated string from userspace.
14322 + *
14323 + * dst - Destination in kernel space.  The buffer must be at least count.
14324 + * src - Address of string in user space.
14325 + * count - Maximum number of bytes to copy (including the trailing NULL).
14326 + *
14327 + * Returns the length of the string (not including the trailing NULL.  If
14328 + * count is smaller than the length of the string, we copy count bytes
14329 + * and return count.
14330 + *
14331 + */
14332 +static inline long strncpy_from_user(char *dst, const __user char *src, long count)
14333 +{
14334 +       char *tmp;
14335 +       if (!access_ok(VERIFY_READ, src, 1)) {
14336 +               return -EFAULT;
14337 +       }
14338 +
14339 +       strncpy(dst, src, count);
14340 +       for (tmp = dst; *tmp && count > 0; tmp++, count--) {
14341 +               ;
14342 +       }
14343 +       return(tmp - dst);
14344 +}
14345 +
14346 +/*
14347 + * strnlen_user()
14348 + *     Return the size of a string (including the ending 0)
14349 + *
14350 + * Return -EFAULT on exception, a value greater than <n> if too long
14351 + */
14352 +static inline long strnlen_user(const __user char *src, long n)
14353 +{
14354 +       if (!access_ok(VERIFY_READ, src, 1)) {
14355 +               return -EFAULT;
14356 +       }
14357 +       return(strlen(src) + 1);
14358 +}
14359 +
14360 +#define strlen_user(str) strnlen_user(str, 32767)
14361 +
14362 +/*
14363 + * __clear_user()
14364 + *     Zero Userspace
14365 + */
14366 +static inline unsigned long __clear_user(__user void *to, unsigned long n)
14367 +{
14368 +       memset(to, 0, n);
14369 +       return 0;
14370 +}
14371 +
14372 +/*
14373 + * clear_user()
14374 + *     Zero user space (check for valid addresses)
14375 + */
14376 +static inline unsigned long clear_user(__user void *to, unsigned long n)
14377 +{
14378 +       if (!access_ok(VERIFY_WRITE, to, n)) {
14379 +               return -EFAULT;
14380 +       }
14381 +       return __clear_user(to, n);
14382 +}
14383 +
14384 +#endif /* _ASM_UBICOM32_UACCESS_H */
14385 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/uart_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uart_tio.h
14386 --- linux-2.6.30.10/arch/ubicom32/include/asm/uart_tio.h        1970-01-01 02:00:00.000000000 +0200
14387 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uart_tio.h    2009-12-11 11:45:11.000000000 +0200
14388 @@ -0,0 +1,126 @@
14389 +/*
14390 + * arch/ubicom32/include/asm/uart_tio.h
14391 + *   Ubicom32 architecture UART TIO definitions.
14392 + *
14393 + * (C) Copyright 2009, Ubicom, Inc.
14394 + *
14395 + * This file is part of the Ubicom32 Linux Kernel Port.
14396 + *
14397 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14398 + * it and/or modify it under the terms of the GNU General Public License
14399 + * as published by the Free Software Foundation, either version 2 of the
14400 + * License, or (at your option) any later version.
14401 + *
14402 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14403 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14404 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14405 + * the GNU General Public License for more details.
14406 + *
14407 + * You should have received a copy of the GNU General Public License
14408 + * along with the Ubicom32 Linux Kernel Port.  If not,
14409 + * see <http://www.gnu.org/licenses/>.
14410 + */
14411 +#ifndef _ASM_UBICOM32_UART_TIO_H
14412 +#define _ASM_UBICOM32_UART_TIO_H
14413 +
14414 +#include <asm/devtree.h>
14415 +
14416 +#define UARTTIO_RX_FIFO_SIZE           16
14417 +#define UARTTIO_TX_FIFO_SIZE           16
14418 +
14419 +/*
14420 + * Interrupt flags
14421 + */
14422 +#define UARTTIO_UART_INT_RX            0x00000001      // set when a character has been recevied (TODO: add watermark)
14423 +#define UARTTIO_UART_INT_RXOVF         0x00000002      // set when the receive buffer has overflowed
14424 +#define UARTTIO_UART_INT_RXFRAME       0x00000004      // set when there has been a framing error
14425 +
14426 +#define UARTTIO_UART_INT_TX            0x00000100      // set every time a character is transmitted
14427 +#define UARTTIO_UART_INT_TXBE          0x00000200      // set when the transmit buffer is empty (TODO: add watermark)
14428 +
14429 +#define UARTTIO_UART_FLAG_ENABLED      0x80000000
14430 +#define UARTTIO_UART_FLAG_SET_RATE      0x00000001      // set to update baud rate
14431 +#define UARTTIO_UART_FLAG_RESET         0x00000002      // set to reset the port
14432 +struct uarttio_uart {
14433 +       volatile u32_t                  flags;
14434 +
14435 +       volatile u32_t                  baud_rate;
14436 +       volatile u32_t                  current_baud_rate;
14437 +       u32_t                           bit_time;
14438 +
14439 +       /*
14440 +        * Modem status register
14441 +        */
14442 +       volatile u32_t                  status;
14443 +
14444 +       /*
14445 +        * Interrupt registers
14446 +        */
14447 +       volatile u32_t                  int_mask;
14448 +       volatile u32_t                  int_flags;
14449 +
14450 +       /*
14451 +        * Ports and pins
14452 +        */
14453 +       u32_t                           rx_port;
14454 +       u32_t                           tx_port;
14455 +
14456 +       u8_t                            rx_pin;
14457 +       u8_t                            tx_pin;
14458 +
14459 +       /*
14460 +        * Configuration Data
14461 +        */
14462 +       u8_t                            rx_bits;
14463 +       u8_t                            rx_stop_bits;
14464 +       u8_t                            tx_bits;
14465 +       u8_t                            tx_stop_bits;
14466 +
14467 +       /*
14468 +        * RX state machine data
14469 +        */
14470 +       u32_t                           rx_timer;
14471 +       u32_t                           rx_bit_pos;
14472 +       u32_t                           rx_byte;
14473 +       u32_t                           rx_fifo_head;
14474 +       u32_t                           rx_fifo_tail;
14475 +       u32_t                           rx_fifo_size;
14476 +
14477 +       /*
14478 +        * TX state machine data
14479 +        */
14480 +       u32_t                           tx_timer;
14481 +       u32_t                           tx_bit_pos;
14482 +       u32_t                           tx_byte;
14483 +       u32_t                           tx_fifo_head;
14484 +       u32_t                           tx_fifo_tail;
14485 +       u32_t                           tx_fifo_size;
14486 +
14487 +       /*
14488 +        * FIFOs
14489 +        */
14490 +       u8_t                            rx_fifo[UARTTIO_RX_FIFO_SIZE];
14491 +       u8_t                            tx_fifo[UARTTIO_TX_FIFO_SIZE];
14492 +};
14493 +
14494 +#define UARTTIO_VP_VERSION             1
14495 +struct uarttio_regs {
14496 +       u32_t                           version;
14497 +
14498 +       u32_t                           thread;
14499 +
14500 +       u32_t                           max_uarts;
14501 +
14502 +       struct uarttio_uart             uarts[0];
14503 +};
14504 +
14505 +#define UARTTIO_NODE_VERSION           1
14506 +struct uarttio_node {
14507 +       struct devtree_node             dn;
14508 +
14509 +       u32_t                           version;
14510 +       struct uarttio_regs             *regs;
14511 +       u32_t                           regs_sz;
14512 +};
14513 +
14514 +#endif /* _ASM_UBICOM32_UART_TIO_H */
14515 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-cs4384.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-cs4384.h
14516 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-cs4384.h    1970-01-01 02:00:00.000000000 +0200
14517 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-cs4384.h        2009-12-11 11:45:11.000000000 +0200
14518 @@ -0,0 +1,52 @@
14519 +/*
14520 + * arch/ubicom32/include/asm/ubi32-cs4384.h
14521 + *   Ubicom32 architecture CS4384 driver platform data definitions.
14522 + *
14523 + * (C) Copyright 2009, Ubicom, Inc.
14524 + *
14525 + * This file is part of the Ubicom32 Linux Kernel Port.
14526 + *
14527 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14528 + * it and/or modify it under the terms of the GNU General Public License
14529 + * as published by the Free Software Foundation, either version 2 of the
14530 + * License, or (at your option) any later version.
14531 + *
14532 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14533 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14534 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14535 + * the GNU General Public License for more details.
14536 + *
14537 + * You should have received a copy of the GNU General Public License
14538 + * along with the Ubicom32 Linux Kernel Port.  If not,
14539 + * see <http://www.gnu.org/licenses/>.
14540 + */
14541 +#ifndef _ASM_UBICOM32_UBI32_CS4384_H
14542 +#define _ASM_UBICOM32_UBI32_CS4384_H
14543 +
14544 +enum ubi32_cs4384_mclk_source {
14545 +       UBI32_CS4384_MCLK_PWM_0,
14546 +       UBI32_CS4384_MCLK_PWM_1,
14547 +       UBI32_CS4384_MCLK_PWM_2,
14548 +       UBI32_CS4384_MCLK_CLKDIV_1,
14549 +       UBI32_CS4384_MCLK_OTHER,
14550 +};
14551 +
14552 +struct ubi32_cs4384_mclk_entry {
14553 +       /*
14554 +        * Rate, in Hz, of this entry
14555 +        */
14556 +       int rate;
14557 +
14558 +       /*
14559 +        * The divider to program to get the rate
14560 +        */
14561 +       int div;
14562 +};
14563 +
14564 +struct ubi32_cs4384_platform_data {
14565 +       enum ubi32_cs4384_mclk_source   mclk_src;
14566 +
14567 +       int                             n_mclk;
14568 +       struct ubi32_cs4384_mclk_entry  *mclk_entries;
14569 +};
14570 +#endif /* _ASM_UBICOM32_UBI32_CS4384_H */
14571 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-pcm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-pcm.h
14572 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-pcm.h       1970-01-01 02:00:00.000000000 +0200
14573 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-pcm.h   2009-12-11 11:45:11.000000000 +0200
14574 @@ -0,0 +1,54 @@
14575 +/*
14576 + * arch/ubicom32/include/asm/ubi32-pcm.h
14577 + *   Ubicom32 architecture PCM driver platform data definitions.
14578 + *
14579 + * (C) Copyright 2009, Ubicom, Inc.
14580 + *
14581 + * This file is part of the Ubicom32 Linux Kernel Port.
14582 + *
14583 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14584 + * it and/or modify it under the terms of the GNU General Public License
14585 + * as published by the Free Software Foundation, either version 2 of the
14586 + * License, or (at your option) any later version.
14587 + *
14588 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14589 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14590 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14591 + * the GNU General Public License for more details.
14592 + *
14593 + * You should have received a copy of the GNU General Public License
14594 + * along with the Ubicom32 Linux Kernel Port.  If not,
14595 + * see <http://www.gnu.org/licenses/>.
14596 + */
14597 +#ifndef _ASM_UBICOM32_UBI32_PCM_H
14598 +#define _ASM_UBICOM32_UBI32_PCM_H
14599 +
14600 +/*
14601 + * This function is called when the sample rate has changed
14602 + */
14603 +typedef int (*ubi32_pcm_set_rate_fn_t)(void *appdata, int rate);
14604 +
14605 +struct ubi32pcm_platform_data {
14606 +       /*
14607 +        * Name of the audio node/inst
14608 +        */
14609 +       const char              *node_name;
14610 +       const char              *inst_name;
14611 +       int                     inst_num;
14612 +
14613 +       /*
14614 +        * Application specific data provided when calling functions
14615 +        */
14616 +       void                    *appdata;
14617 +
14618 +       /*
14619 +        * Functions called when various things happen
14620 +        */
14621 +       ubi32_pcm_set_rate_fn_t set_rate;
14622 +
14623 +       /*
14624 +        * Pointer to optional upper layer data (i.e. DAC config, etc)
14625 +        */
14626 +       void                    *priv_data;
14627 +};
14628 +#endif /* _ASM_UBICOM32_UBI32_PCM_H */
14629 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32bl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32bl.h
14630 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32bl.h      1970-01-01 02:00:00.000000000 +0200
14631 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32bl.h  2009-12-11 11:45:11.000000000 +0200
14632 @@ -0,0 +1,84 @@
14633 +/*
14634 + * arch/ubicom32/include/asm/ubicom32bl.h
14635 + *   Ubicom32 architecture backlight driver platform data definitions.
14636 + *
14637 + * (C) Copyright 2009, Ubicom, Inc.
14638 + *
14639 + * This file is part of the Ubicom32 Linux Kernel Port.
14640 + *
14641 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14642 + * it and/or modify it under the terms of the GNU General Public License
14643 + * as published by the Free Software Foundation, either version 2 of the
14644 + * License, or (at your option) any later version.
14645 + *
14646 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14647 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14648 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14649 + * the GNU General Public License for more details.
14650 + *
14651 + * You should have received a copy of the GNU General Public License
14652 + * along with the Ubicom32 Linux Kernel Port.  If not,
14653 + * see <http://www.gnu.org/licenses/>.
14654 + *
14655 + * Ubicom32 implementation derived from (with many thanks):
14656 + *   arch/m68knommu
14657 + *   arch/blackfin
14658 + *   arch/parisc
14659 + */
14660 +#ifndef _ASM_UBICOM32_UBICOM32_BL_H
14661 +#define _ASM_UBICOM32_UBICOM32_BL_H
14662 +
14663 +/*
14664 + * Different backlight control mechanisms
14665 + */
14666 +enum ubicom32bl_pwm_types {
14667 +       /*
14668 +        * PWM controlled backlight
14669 +        */
14670 +       UBICOM32BL_TYPE_PWM,
14671 +
14672 +       /*
14673 +        * HRT based PWM backlight
14674 +        */
14675 +       UBICOM32BL_TYPE_PWM_HRT,
14676 +
14677 +       /*
14678 +        * No dimming, just on or off
14679 +        */
14680 +       UBICOM32BL_TYPE_BINARY,
14681 +};
14682 +
14683 +struct ubicom32bl_platform_data {
14684 +       /*
14685 +        * Default intensity of the backlight 0-255
14686 +        */
14687 +       u8_t                            default_intensity;
14688 +
14689 +       /*
14690 +        * TRUE if the backlight sense is active low. (inverted)
14691 +        * FALSE if the backlight sense is active high.
14692 +        */
14693 +       bool                            invert;
14694 +
14695 +       /*
14696 +        * Type of the backlight
14697 +        */
14698 +       enum ubicom32bl_pwm_types       type;
14699 +
14700 +       /*
14701 +        * GPIO of the backlight if UBICOM32BL_TYPE_PWM_HRT, UBICOM32BL_TYPE_BINARY
14702 +        */
14703 +       unsigned                        gpio;
14704 +
14705 +       /*
14706 +        * PWM channel and parameters of the backlight if UBICOM32BL_TYPE_PWM
14707 +        *      pre_scaler: sets the rate at which the PWM timer is clocked. (clk_core / 2^pre_scaler)
14708 +        *      period: sets the period of the timer in timer cycles
14709 +        * The duty cycle will be directly proportional to the brightness setting.
14710 +        */
14711 +       u32_t                           pwm_channel;
14712 +       u8_t                            pwm_prescale;
14713 +       u16_t                           pwm_period;
14714 +};
14715 +
14716 +#endif /* _ASM_UBICOM32_UBICOM32_BL_H */
14717 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common-asm.h
14718 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common-asm.h     1970-01-01 02:00:00.000000000 +0200
14719 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common-asm.h 2009-12-11 11:45:11.000000000 +0200
14720 @@ -0,0 +1,49 @@
14721 +/*
14722 + * arch/ubicom32/include/asm/ubicom32-common-asm.h
14723 + *   Ubicom32 atomic lock operations.
14724 + *
14725 + * (C) Copyright 2009, Ubicom, Inc.
14726 + *
14727 + * This file is part of the Ubicom32 Linux Kernel Port.
14728 + *
14729 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14730 + * it and/or modify it under the terms of the GNU General Public License
14731 + * as published by the Free Software Foundation, either version 2 of the
14732 + * License, or (at your option) any later version.
14733 + *
14734 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14735 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14736 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14737 + * the GNU General Public License for more details.
14738 + *
14739 + * You should have received a copy of the GNU General Public License
14740 + * along with the Ubicom32 Linux Kernel Port.  If not,
14741 + * see <http://www.gnu.org/licenses/>.
14742 + *
14743 + * Ubicom32 implementation derived from (with many thanks):
14744 + *   arch/m68knommu
14745 + *   arch/blackfin
14746 + *   arch/parisc
14747 + */
14748 +
14749 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14750 +#define _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14751 +
14752 +/*
14753 + * atomic_lock_acquire macro
14754 + *     Equivalent to __atomic_lock_acquire()
14755 + */
14756 +.macro atomic_lock_acquire
14757 +       bset scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14758 +       jmpne.f .-4
14759 +.endm
14760 +
14761 +/*
14762 + * atomic_lock_release macro
14763 + *     Equivalent to __atomic_lock_release()
14764 + */
14765 +.macro atomic_lock_release
14766 +       bclr scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14767 +.endm
14768 +
14769 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_ASM_H */
14770 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common.h
14771 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common.h 1970-01-01 02:00:00.000000000 +0200
14772 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common.h     2009-12-11 11:45:11.000000000 +0200
14773 @@ -0,0 +1,128 @@
14774 +/*
14775 + * arch/ubicom32/include/asm/ubicom32-common.h
14776 + *   Ubicom32 atomic lock operations.
14777 + *
14778 + * (C) Copyright 2009, Ubicom, Inc.
14779 + *
14780 + * This file is part of the Ubicom32 Linux Kernel Port.
14781 + *
14782 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14783 + * it and/or modify it under the terms of the GNU General Public License
14784 + * as published by the Free Software Foundation, either version 2 of the
14785 + * License, or (at your option) any later version.
14786 + *
14787 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14788 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14789 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14790 + * the GNU General Public License for more details.
14791 + *
14792 + * You should have received a copy of the GNU General Public License
14793 + * along with the Ubicom32 Linux Kernel Port.  If not,
14794 + * see <http://www.gnu.org/licenses/>.
14795 + *
14796 + * Ubicom32 implementation derived from (with many thanks):
14797 + *   arch/m68knommu
14798 + *   arch/blackfin
14799 + *   arch/parisc
14800 + */
14801 +
14802 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_H
14803 +#define _ASM_UBICOM32_UBICOM32_COMMON_H
14804 +
14805 +#define S(arg) #arg
14806 +#define D(arg) S(arg)
14807 +/*
14808 + * scratchpad1 is owned by the LDSR.
14809 + *
14810 + * The upper bits provide 16 global spinlocks.  Acquiring one of these
14811 + * global spinlocks synchornizes across multiple threads and prevents
14812 + * the LDSR from delivering any interrupts while the lock is held.
14813 + * Use these locks only when absolutely required.
14814 + *
14815 + * The lower 16 bits of scratchpad1 are used as per thread interrupt
14816 + * enable/disable bits.  These bits will prevent a thread from receiving
14817 + * any interrupts.
14818 + *
14819 + * Bit Usage:
14820 + * - MT_EN_LOCK_BIT   - Protects writes to MT_EN, so code can read current value
14821 + *                     then write a new value atomically (profiler for example)
14822 + * - ATOMIC_LOCK_BIT - Used to provide general purpose atomic handling.
14823 + * - LDSR_LOCK_BIT   - Used by the LDSR exclusively to provide protection.
14824 + * - DCCR_LOCK_BIT   - Used to limit access to the DCCR cache control peripheral
14825 + * - ICCR_LOCK_BIT   - Used to limit access to the ICCR cache control peripheral
14826 + * - LSB 16 bits     - Used by the LDSR to represent thread enable/disable bits.
14827 + */
14828 +#define MT_EN_LOCK_BIT 31
14829 +#define ATOMIC_LOCK_BIT 30
14830 +#define LDSR_LOCK_BIT   29
14831 +#define PCI_LOCK_BIT   28
14832 +#define ICCR_LOCK_BIT  27
14833 +#define DCCR_LOCK_BIT  26
14834 +
14835 +#if !defined(__ASSEMBLY__)
14836 +
14837 +#define UBICOM32_TRYLOCK(bit) \
14838 +       asm volatile (                                                \
14839 +       "       move.4 %0, #0                                   \n\t" \
14840 +       "       bset scratchpad1, scratchpad1, #"D(bit)"        \n\t" \
14841 +       "       jmpne.f 1f                                      \n\t" \
14842 +       "       move.4 %0, #1                                   \n\t" \
14843 +       "1:                                                     \n\t" \
14844 +               : "=r" (ret)                                          \
14845 +               :                                                     \
14846 +               : "cc", "memory"                                      \
14847 +       )                                                             \
14848 +
14849 +#define UBICOM32_UNLOCK(bit) \
14850 +       asm volatile (                                                \
14851 +       "       bclr scratchpad1, scratchpad1, #"D(bit)"        \n\t" \
14852 +               :                                                     \
14853 +               :                                                     \
14854 +               : "cc", "memory"                                      \
14855 +       )                                                             \
14856 +
14857 +#define UBICOM32_LOCK(bit) \
14858 +       asm volatile (                                                \
14859 +       "1:     bset scratchpad1, scratchpad1, #"D(bit)"        \n\t" \
14860 +       "       jmpne.f 1b                                      \n\t" \
14861 +               :                                                     \
14862 +               :                                                     \
14863 +               : "cc", "memory"                                      \
14864 +       )                                                             \
14865 +
14866 +/*
14867 + * __atomic_lock_trylock()
14868 + *     Attempt to acquire the lock, return TRUE if acquired.
14869 + */
14870 +static inline int __atomic_lock_trylock(void)
14871 +{
14872 +       int ret;
14873 +       UBICOM32_TRYLOCK(ATOMIC_LOCK_BIT);
14874 +       return ret;
14875 +}
14876 +
14877 +/*
14878 + * __atomic_lock_release()
14879 + *     Release the global atomic lock.
14880 + *
14881 + * Note: no one is suspended waiting since this lock is a spinning lock.
14882 + */
14883 +static inline void __atomic_lock_release(void)
14884 +{
14885 +       UBICOM32_UNLOCK(ATOMIC_LOCK_BIT);
14886 +}
14887 +
14888 +/*
14889 + * __atomic_lock_acquire()
14890 + *     Acquire the global atomic lock, spin if not available.
14891 + */
14892 +static inline void __atomic_lock_acquire(void)
14893 +{
14894 +       UBICOM32_LOCK(ATOMIC_LOCK_BIT);
14895 +}
14896 +#else /* __ASSEMBLY__ */
14897 +
14898 +#include <asm/ubicom32-common-asm.h>
14899 +
14900 +#endif /* __ASSEMBLY__ */
14901 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_H */
14902 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32fb.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32fb.h
14903 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32fb.h      1970-01-01 02:00:00.000000000 +0200
14904 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32fb.h  2009-12-11 11:45:11.000000000 +0200
14905 @@ -0,0 +1,56 @@
14906 +/*
14907 + * arch/ubicom32/include/asm/ubicom32fb.h
14908 + *   Ubicom32 architecture video frame buffer definitions.
14909 + *
14910 + * (C) Copyright 2009, Ubicom, Inc.
14911 + *
14912 + * This file is part of the Ubicom32 Linux Kernel Port.
14913 + *
14914 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14915 + * it and/or modify it under the terms of the GNU General Public License
14916 + * as published by the Free Software Foundation, either version 2 of the
14917 + * License, or (at your option) any later version.
14918 + *
14919 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14920 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14921 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14922 + * the GNU General Public License for more details.
14923 + *
14924 + * You should have received a copy of the GNU General Public License
14925 + * along with the Ubicom32 Linux Kernel Port.  If not,
14926 + * see <http://www.gnu.org/licenses/>.
14927 + */
14928 +#ifndef _ASM_UBICOM32_UBICOM32FB_H
14929 +#define _ASM_UBICOM32_UBICOM32FB_H
14930 +
14931 +#include <linux/ioctl.h>
14932 +
14933 +/*
14934 + * Set next frame
14935 + */
14936 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME                _IOW('r',  1, void *)
14937 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC   _IOW('r',  2, void *)
14938 +
14939 +/*
14940 + * Set Mode
14941 + */
14942 +#define UBICOM32FB_IOCTL_SET_MODE              _IOW('r',  3, void *)
14943 +struct ubicom32fb_mode {
14944 +       unsigned long   width;
14945 +       unsigned long   height;
14946 +       unsigned long   flags;
14947 +       void            *next_frame;
14948 +};
14949 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER  (1 << 8)
14950 +
14951 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER (1 << 7)
14952 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV             (1 << 6)
14953 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB            (1 << 5)
14954 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255   (1 << 4)
14955 +
14956 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255    (1 << 3)
14957 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1                (1 << 2)
14958 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1                (1 << 1)
14959 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE    (1 << 0)
14960 +
14961 +#endif /* _ASM_UBICOM32_UBICOM32FB_H */
14962 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32hid.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32hid.h
14963 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32hid.h     1970-01-01 02:00:00.000000000 +0200
14964 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32hid.h 2009-12-11 11:45:11.000000000 +0200
14965 @@ -0,0 +1,133 @@
14966 +/*
14967 + * arch/ubicom32/include/asm/ubicom32hid.h
14968 + *   Ubicom32 architecture HID driver platform data definitions.
14969 + *
14970 + * (C) Copyright 2009, Ubicom, Inc.
14971 + *
14972 + * This file is part of the Ubicom32 Linux Kernel Port.
14973 + *
14974 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14975 + * it and/or modify it under the terms of the GNU General Public License
14976 + * as published by the Free Software Foundation, either version 2 of the
14977 + * License, or (at your option) any later version.
14978 + *
14979 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14980 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14981 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14982 + * the GNU General Public License for more details.
14983 + *
14984 + * You should have received a copy of the GNU General Public License
14985 + * along with the Ubicom32 Linux Kernel Port.  If not,
14986 + * see <http://www.gnu.org/licenses/>.
14987 + *
14988 + * Ubicom32 implementation derived from (with many thanks):
14989 + *   arch/m68knommu
14990 + *   arch/blackfin
14991 + *   arch/parisc
14992 + */
14993 +#ifndef _ASM_UBICOM32_UBICOM32_HID_H
14994 +#define _ASM_UBICOM32_UBICOM32_HID_H
14995 +
14996 +enum ubicom32hid_bl_types {
14997 +       /*
14998 +        * On or off, using command SET_BL_EN, PB4
14999 +        */
15000 +       UBICOM32HID_BL_TYPE_BINARY,
15001 +
15002 +       /*
15003 +        * Dimmable, using command SET_PWM, PB3
15004 +        */
15005 +       UBICOM32HID_BL_TYPE_PWM,
15006 +};
15007 +
15008 +/*
15009 + * IR code mapping to event code.
15010 + *     If there are no button mappings and no ir mappings
15011 + *     then no input driver will be registered.
15012 + */
15013 +struct ubicom32hid_ir {
15014 +       /*
15015 +        * Input event code (KEY_*, SW_*, etc)
15016 +        */
15017 +       int             code;
15018 +
15019 +       /*
15020 +        * Input event type (EV_KEY, EV_SW, etc)
15021 +        */
15022 +       int             type;
15023 +
15024 +       /*
15025 +        * The IR code of this button.
15026 +        */
15027 +       uint32_t        ir_code;
15028 +};
15029 +
15030 +/*
15031 + * Button mapping to event code.
15032 + *     If there are no button mappings and no ir mappings
15033 + *     then no input driver will be registered.
15034 + */
15035 +struct ubicom32hid_button {
15036 +       /*
15037 +        * Input event code (KEY_*, SW_*, etc)
15038 +        */
15039 +       int             code;
15040 +
15041 +       /*
15042 +        * Input event type (EV_KEY, EV_SW, etc)
15043 +        */
15044 +       int             type;
15045 +
15046 +       /*
15047 +        * Bit number of this button.
15048 +        */
15049 +       uint8_t         bit;
15050 +};
15051 +
15052 +struct ubicom32hid_platform_data {
15053 +       /*
15054 +        * Default intensity of the backlight 0-255
15055 +        */
15056 +       u8_t                            default_intensity;
15057 +
15058 +       /*
15059 +        * GPIO number of the reset line and its polarity.
15060 +        */
15061 +       unsigned                        gpio_reset;
15062 +       int                             gpio_reset_polarity;
15063 +
15064 +       /*
15065 +        * TRUE if the backlight sense is active low. (inverted)
15066 +        * FALSE if the backlight sense is active high.
15067 +        */
15068 +       bool                            invert;
15069 +
15070 +       /*
15071 +        * Type of the backlight we are controlling
15072 +        */
15073 +       enum ubicom32hid_bl_types       type;
15074 +
15075 +       /*
15076 +        * Optional polling rate for input, in ms, defaults to 100ms
15077 +        */
15078 +       int                             poll_interval;
15079 +
15080 +       /*
15081 +        * Optional name to register as input device
15082 +        */
15083 +       const char                      *input_name;
15084 +
15085 +       /*
15086 +        * Button mapping array
15087 +        */
15088 +       const struct ubicom32hid_button *buttons;
15089 +       int                             nbuttons;
15090 +
15091 +       /*
15092 +        * IR mapping array
15093 +        */
15094 +       const struct ubicom32hid_ir     *ircodes;
15095 +       int                             nircodes;
15096 +};
15097 +
15098 +#endif /* _ASM_UBICOM32_UBICOM32_HID_H */
15099 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input.h
15100 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input.h   1970-01-01 02:00:00.000000000 +0200
15101 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input.h       2009-12-11 11:45:11.000000000 +0200
15102 @@ -0,0 +1,76 @@
15103 +/*
15104 + * arch/ubicom32/include/asm/ubicom32input.h
15105 + *   Ubicom32 Input driver, based on gpio-keys
15106 + *
15107 + * (C) Copyright 2009, Ubicom, Inc.
15108 + *
15109 + * This file is part of the Ubicom32 Linux Kernel Port.
15110 + *
15111 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15112 + * it and/or modify it under the terms of the GNU General Public License
15113 + * as published by the Free Software Foundation, either version 2 of the
15114 + * License, or (at your option) any later version.
15115 + *
15116 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15117 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15118 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15119 + * the GNU General Public License for more details.
15120 + *
15121 + * You should have received a copy of the GNU General Public License
15122 + * along with the Ubicom32 Linux Kernel Port.  If not,
15123 + * see <http://www.gnu.org/licenses/>.
15124 + *
15125 + * Ubicom32 implementation derived from (with many thanks):
15126 + *   arch/m68knommu
15127 + *   arch/blackfin
15128 + *   arch/parisc
15129 + *
15130 + * TODO: add groups for inputs which can be sampled together
15131 + */
15132 +
15133 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_H
15134 +#define _ASM_UBICOM32_UBICOM32_INPUT_H
15135 +
15136 +struct ubicom32input_button {
15137 +       /*
15138 +        * Input event code (KEY_*, SW_*, etc)
15139 +        */
15140 +       int             code;
15141 +
15142 +       /*
15143 +        * Input event type (EV_KEY, EV_SW, etc)
15144 +        */
15145 +       int             type;
15146 +
15147 +       /*
15148 +        * GPIO to poll
15149 +        */
15150 +       int             gpio;
15151 +
15152 +       /*
15153 +        * 1 for active low, 0 for active high
15154 +        */
15155 +       int             active_low;
15156 +
15157 +       /*
15158 +        * Description, used for reserving GPIOs
15159 +        */
15160 +       const char      *desc;
15161 +};
15162 +
15163 +struct ubicom32input_platform_data {
15164 +       struct ubicom32input_button     *buttons;
15165 +       int                             nbuttons;
15166 +
15167 +       /*
15168 +        * Optional poll interval, in ms, defaults to 50ms
15169 +        */
15170 +       int                             poll_interval;
15171 +
15172 +       /*
15173 +        * Option Name of this driver
15174 +        */
15175 +       const char                      *name;
15176 +};
15177 +
15178 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_H */
15179 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input_i2c.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input_i2c.h
15180 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input_i2c.h       1970-01-01 02:00:00.000000000 +0200
15181 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input_i2c.h   2009-12-11 11:45:11.000000000 +0200
15182 @@ -0,0 +1,71 @@
15183 +/*
15184 + * arch/ubicom32/include/asm/ubicom32input_i2c.h
15185 + *   Ubicom32 architecture Input driver over I2C platform data definitions.
15186 + *
15187 + * (C) Copyright 2009, Ubicom, Inc.
15188 + *
15189 + * This file is part of the Ubicom32 Linux Kernel Port.
15190 + *
15191 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15192 + * it and/or modify it under the terms of the GNU General Public License
15193 + * as published by the Free Software Foundation, either version 2 of the
15194 + * License, or (at your option) any later version.
15195 + *
15196 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15197 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15198 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15199 + * the GNU General Public License for more details.
15200 + *
15201 + * You should have received a copy of the GNU General Public License
15202 + * along with the Ubicom32 Linux Kernel Port.  If not,
15203 + * see <http://www.gnu.org/licenses/>.
15204 + *
15205 + * Ubicom32 implementation derived from (with many thanks):
15206 + *   arch/m68knommu
15207 + *   arch/blackfin
15208 + *   arch/parisc
15209 + *
15210 + * TODO: add groups for inputs which can be sampled together
15211 + */
15212 +
15213 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15214 +#define _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15215 +
15216 +struct ubicom32input_i2c_button {
15217 +       /*
15218 +        * Input event code (KEY_*, SW_*, etc)
15219 +        */
15220 +       int             code;
15221 +
15222 +       /*
15223 +        * Input event type (EV_KEY, EV_SW, etc)
15224 +        */
15225 +       int             type;
15226 +
15227 +       /*
15228 +        * Bit number of this button. (0 - ngpio)
15229 +        */
15230 +       int             bit;
15231 +
15232 +       /*
15233 +        * 1 for active low, 0 for active high
15234 +        */
15235 +       int             active_low;
15236 +};
15237 +
15238 +struct ubicom32input_i2c_platform_data {
15239 +       struct ubicom32input_i2c_button *buttons;
15240 +       int                             nbuttons;
15241 +
15242 +       /*
15243 +        * Optional poll interval, in ms, defaults to 100ms
15244 +        */
15245 +       int                             poll_interval;
15246 +
15247 +       /*
15248 +        * Option Name of this driver
15249 +        */
15250 +       const char                      *name;
15251 +};
15252 +
15253 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_I2C_H */
15254 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcd.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcd.h
15255 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcd.h     1970-01-01 02:00:00.000000000 +0200
15256 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcd.h 2009-12-11 11:45:11.000000000 +0200
15257 @@ -0,0 +1,38 @@
15258 +/*
15259 + * arch/ubicom32/include/asm/ubicom32lcd.h
15260 + *   Ubicom32 architecture LCD driver platform data definitions.
15261 + *
15262 + * (C) Copyright 2009, Ubicom, Inc.
15263 + *
15264 + * This file is part of the Ubicom32 Linux Kernel Port.
15265 + *
15266 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15267 + * it and/or modify it under the terms of the GNU General Public License
15268 + * as published by the Free Software Foundation, either version 2 of the
15269 + * License, or (at your option) any later version.
15270 + *
15271 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15272 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15273 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15274 + * the GNU General Public License for more details.
15275 + *
15276 + * You should have received a copy of the GNU General Public License
15277 + * along with the Ubicom32 Linux Kernel Port.  If not,
15278 + * see <http://www.gnu.org/licenses/>.
15279 + */
15280 +#ifndef _ASM_UBICOM32_UBICOM32_LCD_H
15281 +#define _ASM_UBICOM32_UBICOM32_LCD_H
15282 +
15283 +#include <asm/ip5000.h>
15284 +
15285 +struct ubicom32lcd_platform_data {
15286 +       int                     pin_cs;
15287 +       int                     pin_rs;
15288 +       int                     pin_rd;
15289 +       int                     pin_wr;
15290 +       int                     pin_reset;
15291 +       int                     data_shift;
15292 +       struct ubicom32_io_port *port_data;
15293 +};
15294 +
15295 +#endif /* _ASM_UBICOM32_UBICOM32_LCD_H */
15296 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcdpower.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcdpower.h
15297 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcdpower.h        1970-01-01 02:00:00.000000000 +0200
15298 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcdpower.h    2009-12-11 11:45:11.000000000 +0200
15299 @@ -0,0 +1,39 @@
15300 +/*
15301 + * arch/ubicom32/include/asm/ubicom32lcdpower.h
15302 + *   Ubicom32 architecture LCD driver platform data definitions.
15303 + *
15304 + * (C) Copyright 2009, Ubicom, Inc.
15305 + *
15306 + * This file is part of the Ubicom32 Linux Kernel Port.
15307 + *
15308 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15309 + * it and/or modify it under the terms of the GNU General Public License
15310 + * as published by the Free Software Foundation, either version 2 of the
15311 + * License, or (at your option) any later version.
15312 + *
15313 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15314 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15315 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15316 + * the GNU General Public License for more details.
15317 + *
15318 + * You should have received a copy of the GNU General Public License
15319 + * along with the Ubicom32 Linux Kernel Port.  If not,
15320 + * see <http://www.gnu.org/licenses/>.
15321 + *
15322 + * Ubicom32 implementation derived from (with many thanks):
15323 + *   arch/m68knommu
15324 + *   arch/blackfin
15325 + *   arch/parisc
15326 + */
15327 +#ifndef _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15328 +#define _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15329 +
15330 +struct ubicom32lcdpower_platform_data {
15331 +       /*
15332 +        * GPIO and polarity for VGH signal.  A FALSE polarity is active low, TRUE is active high.
15333 +        */
15334 +       int             vgh_gpio;
15335 +       bool            vgh_polarity;
15336 +};
15337 +
15338 +#endif /* _ASM_UBICOM32_UBICOM32_LCDPOWER_H */
15339 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32ring.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32ring.h
15340 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32ring.h    1970-01-01 02:00:00.000000000 +0200
15341 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32ring.h        2009-12-11 11:45:11.000000000 +0200
15342 @@ -0,0 +1,103 @@
15343 +/*
15344 + * arch/ubicom32/include/asm/ubicom32ring.h
15345 + * Userspace I/O platform driver for Ubicom32 ring buffers
15346 + *
15347 + * (C) Copyright 2009, Ubicom, Inc.
15348 + *
15349 + * This file is part of the Ubicom32 Linux Kernel Port.
15350 + *
15351 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15352 + * it and/or modify it under the terms of the GNU General Public License
15353 + * as published by the Free Software Foundation, either version 2 of the
15354 + * License, or (at your option) any later version.
15355 + *
15356 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15357 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15358 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15359 + * the GNU General Public License for more details.
15360 + *
15361 + * You should have received a copy of the GNU General Public License
15362 + * along with the Ubicom32 Linux Kernel Port.  If not,
15363 + * see <http://www.gnu.org/licenses/>.
15364 + */
15365 +
15366 +#ifndef _ASM_UBICOM32_UBICOM32RING_H
15367 +#define _ASM_UBICOM32_UBICOM32RING_H
15368 +
15369 +#define UIO_UBICOM32RING_REG_VERSION   2
15370 +
15371 +struct uio_ubicom32ring_desc {
15372 +       volatile unsigned int           head;
15373 +       volatile unsigned int           tail;
15374 +       unsigned int                    entries;
15375 +       volatile unsigned int           ring[0];
15376 +};
15377 +
15378 +struct uio_ubicom32ring_regs {
15379 +       unsigned int                    version;
15380 +
15381 +       /*
15382 +        * Magic type used to identify the ring set.  Each driver will
15383 +        * have a different magic value.
15384 +        */
15385 +       unsigned int                    magic;
15386 +
15387 +       /*
15388 +        * Registers defined by the driver
15389 +        */
15390 +       unsigned int                    regs_size;
15391 +       void                            *regs;
15392 +
15393 +       /*
15394 +        * The locations of the rings
15395 +        *
15396 +        * DO NOT ADD ANYTHING BELOW THIS LINE
15397 +        */
15398 +       unsigned int                    num_rings;
15399 +       struct uio_ubicom32ring_desc    *rings[0];
15400 +};
15401 +
15402 +/*
15403 + * ringtio_ring_flush
15404 + */
15405 +static inline void ringtio_ring_flush(struct uio_ubicom32ring_desc *rd)
15406 +{
15407 +       rd->head = rd->tail = 0;
15408 +}
15409 +
15410 +/*
15411 + * ringtio_ring_get
15412 + */
15413 +static inline int ringtio_ring_get(struct uio_ubicom32ring_desc *rd, void **val)
15414 +{
15415 +       if (rd->head == rd->tail) {
15416 +               return 0;
15417 +       }
15418 +
15419 +       *val = (void *)rd->ring[rd->head++];
15420 +       if (rd->head == rd->entries) {
15421 +               rd->head = 0;
15422 +       }
15423 +       return 1;
15424 +}
15425 +
15426 +/*
15427 + * ringtio_ring_put
15428 + */
15429 +static inline int ringtio_ring_put(struct uio_ubicom32ring_desc *rd, void *val)
15430 +{
15431 +       unsigned int newtail = rd->tail + 1;
15432 +       if (newtail == rd->entries) {
15433 +               newtail = 0;
15434 +       }
15435 +
15436 +       if (newtail == rd->head) {
15437 +               return 0;
15438 +       }
15439 +
15440 +       rd->ring[rd->tail] = (unsigned int)val;
15441 +       rd->tail = newtail;
15442 +       return 1;
15443 +}
15444 +
15445 +#endif /* _ASM_UBICOM32_UBICOM32RING_H */
15446 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32sd.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32sd.h
15447 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32sd.h      1970-01-01 02:00:00.000000000 +0200
15448 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32sd.h  2009-12-11 11:45:11.000000000 +0200
15449 @@ -0,0 +1,45 @@
15450 +/*
15451 + * arch/ubicom32/include/asm/ubicom32sd.h
15452 + *   Ubicom32SD public include file
15453 + *
15454 + * (C) Copyright 2009, Ubicom, Inc.
15455 + *
15456 + * This file is part of the Ubicom32 Linux Kernel Port.
15457 + *
15458 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15459 + * it and/or modify it under the terms of the GNU General Public License
15460 + * as published by the Free Software Foundation, either version 2 of the
15461 + * License, or (at your option) any later version.
15462 + *
15463 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15464 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15465 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15466 + * the GNU General Public License for more details.
15467 + *
15468 + * You should have received a copy of the GNU General Public License
15469 + * along with the Ubicom32 Linux Kernel Port.  If not,
15470 + * see <http://www.gnu.org/licenses/>.
15471 + */
15472 +#ifndef _ASM_UBICOM32_UBICOM32_SD_H
15473 +#define _ASM_UBICOM32_UBICOM32_SD_H
15474 +
15475 +struct ubicom32sd_card {
15476 +       /*
15477 +        * GPIOs of PWR, WP and CD lines.
15478 +        * Polarity is 1 for active high and 0 for active low
15479 +        */
15480 +       int                             pin_pwr;
15481 +       bool                            pwr_polarity;
15482 +       int                             pin_wp;
15483 +       bool                            wp_polarity;
15484 +       int                             pin_cd;
15485 +       bool                            cd_polarity;
15486 +};
15487 +
15488 +struct ubicom32sd_platform_data {
15489 +       int                     ncards;
15490 +
15491 +       struct ubicom32sd_card  *cards;
15492 +};
15493 +
15494 +#endif /* _ASM_UBICOM32_UBICOM32_SD_H */
15495 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-spi-gpio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15496 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-spi-gpio.h       1970-01-01 02:00:00.000000000 +0200
15497 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-spi-gpio.h   2009-12-11 11:45:11.000000000 +0200
15498 @@ -0,0 +1,62 @@
15499 +/*
15500 + * arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15501 + *   Platform driver data definitions for GPIO based SPI driver.
15502 + *
15503 + * (C) Copyright 2009, Ubicom, Inc.
15504 + *
15505 + * This file is part of the Ubicom32 Linux Kernel Port.
15506 + *
15507 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15508 + * it and/or modify it under the terms of the GNU General Public License
15509 + * as published by the Free Software Foundation, either version 2 of the
15510 + * License, or (at your option) any later version.
15511 + *
15512 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15513 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15514 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15515 + * the GNU General Public License for more details.
15516 + *
15517 + * You should have received a copy of the GNU General Public License
15518 + * along with the Ubicom32 Linux Kernel Port.  If not,
15519 + * see <http://www.gnu.org/licenses/>.
15520 + *
15521 + * Ubicom32 implementation derived from (with many thanks):
15522 + *   arch/m68knommu
15523 + *   arch/blackfin
15524 + *   arch/parisc
15525 + */
15526 +#ifndef _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15527 +#define _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15528 +
15529 +struct ubicom32_spi_gpio_platform_data {
15530 +       /*
15531 +        * GPIO to use for MOSI, MISO, CLK
15532 +        */
15533 +       int     pin_mosi;
15534 +       int     pin_miso;
15535 +       int     pin_clk;
15536 +
15537 +       /*
15538 +        * Default state of CLK line
15539 +        */
15540 +       int     clk_default;
15541 +
15542 +       /*
15543 +        * Number of chip selects on this bus
15544 +        */
15545 +       int     num_chipselect;
15546 +
15547 +       /*
15548 +        * The bus number of this chip
15549 +        */
15550 +       int     bus_num;
15551 +};
15552 +
15553 +struct ubicom32_spi_gpio_controller_data {
15554 +       /*
15555 +        * GPIO to use for chip select
15556 +        */
15557 +       int     pin_cs;
15558 +};
15559 +
15560 +#endif /* _ASM_UBICOM32_UBICOM32_SPI_GPIO_H */
15561 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32suart.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32suart.h
15562 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32suart.h   1970-01-01 02:00:00.000000000 +0200
15563 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32suart.h       2009-12-11 11:45:11.000000000 +0200
15564 @@ -0,0 +1,36 @@
15565 +/*
15566 + * arch/ubicom32/include/asm/ubicom32suart.h
15567 + *   <TODO: Replace with short file description>
15568 + *
15569 + * (C) Copyright 2009, Ubicom, Inc.
15570 + *
15571 + * This file is part of the Ubicom32 Linux Kernel Port.
15572 + *
15573 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15574 + * it and/or modify it under the terms of the GNU General Public License
15575 + * as published by the Free Software Foundation, either version 2 of the
15576 + * License, or (at your option) any later version.
15577 + *
15578 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15579 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15580 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15581 + * the GNU General Public License for more details.
15582 + *
15583 + * You should have received a copy of the GNU General Public License
15584 + * along with the Ubicom32 Linux Kernel Port.  If not,
15585 + * see <http://www.gnu.org/licenses/>.
15586 + *
15587 + * Ubicom32 implementation derived from (with many thanks):
15588 + *   arch/m68knommu
15589 + *   arch/blackfin
15590 + *   arch/parisc
15591 + */
15592 +#ifndef _ASM_UBICOM32_UBICOM32_SUART_H
15593 +#define _ASM_UBICOM32_UBICOM32_SUART_H
15594 +
15595 +/*
15596 + * Platform resource id for serdes uart clock parameter
15597 + */
15598 +#define UBICOM32_SUART_IORESOURCE_CLOCK                (1)
15599 +
15600 +#endif /* _ASM_UBICOM32_UBICOM32_SUART_H */
15601 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-tio.h
15602 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-tio.h    1970-01-01 02:00:00.000000000 +0200
15603 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-tio.h        2009-12-11 11:45:11.000000000 +0200
15604 @@ -0,0 +1,42 @@
15605 +/*
15606 + * arch/ubicom32/include/asm/ubicom32-tio.h
15607 + *   Threaded I/O interface definitions.
15608 + *
15609 + * (C) Copyright 2009, Ubicom, Inc.
15610 + *
15611 + * This file is part of the Ubicom32 Linux Kernel Port.
15612 + *
15613 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15614 + * it and/or modify it under the terms of the GNU General Public License
15615 + * as published by the Free Software Foundation, either version 2 of the
15616 + * License, or (at your option) any later version.
15617 + *
15618 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15619 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15620 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15621 + * the GNU General Public License for more details.
15622 + *
15623 + * You should have received a copy of the GNU General Public License
15624 + * along with the Ubicom32 Linux Kernel Port.  If not,
15625 + * see <http://www.gnu.org/licenses/>.
15626 + *
15627 + * Ubicom32 implementation derived from (with many thanks):
15628 + *   arch/m68knommu
15629 + *   arch/blackfin
15630 + *   arch/parisc
15631 + */
15632 +#ifndef _ASM_UBICOM32_UBICOM32_TIO_H
15633 +#define _ASM_UBICOM32_UBICOM32_TIO_H
15634 +
15635 +extern u8_t usb_tio_read_u16(u32_t address, u16_t *data);
15636 +extern u8_t usb_tio_read_u8(u32_t address, u8_t *data);
15637 +
15638 +extern u8_t usb_tio_write_u16(u32_t address, u16_t data);
15639 +extern u8_t usb_tio_write_u8(u32_t address, u8_t data);
15640 +
15641 +extern u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes);
15642 +extern u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes);
15643 +extern u8_t usb_tio_write_fifo_sync(u32_t address, u32_t buffer, u32_t bytes);
15644 +extern void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx);
15645 +
15646 +#endif /* _ASM_UBICOM32_UBICOM32_TIO_H */
15647 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ucontext.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ucontext.h
15648 --- linux-2.6.30.10/arch/ubicom32/include/asm/ucontext.h        1970-01-01 02:00:00.000000000 +0200
15649 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ucontext.h    2009-12-11 11:45:11.000000000 +0200
15650 @@ -0,0 +1,39 @@
15651 +/*
15652 + * arch/ubicom32/include/asm/ucontext.h
15653 + *   Definition of ucontext structure for Ubicom32 architecture.
15654 + *
15655 + * (C) Copyright 2009, Ubicom, Inc.
15656 + *
15657 + * This file is part of the Ubicom32 Linux Kernel Port.
15658 + *
15659 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15660 + * it and/or modify it under the terms of the GNU General Public License
15661 + * as published by the Free Software Foundation, either version 2 of the
15662 + * License, or (at your option) any later version.
15663 + *
15664 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15665 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15666 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15667 + * the GNU General Public License for more details.
15668 + *
15669 + * You should have received a copy of the GNU General Public License
15670 + * along with the Ubicom32 Linux Kernel Port.  If not,
15671 + * see <http://www.gnu.org/licenses/>.
15672 + *
15673 + * Ubicom32 implementation derived from (with many thanks):
15674 + *   arch/m68knommu
15675 + *   arch/blackfin
15676 + *   arch/parisc
15677 + */
15678 +#ifndef _ASM_UBICOM32_UCONTEXT_H
15679 +#define _ASM_UBICOM32_UCONTEXT_H
15680 +
15681 +struct ucontext {
15682 +       unsigned long     uc_flags;
15683 +       struct ucontext  *uc_link;
15684 +       stack_t           uc_stack;
15685 +       struct sigcontext         uc_mcontext;
15686 +       sigset_t          uc_sigmask;   /* mask last for extensibility */
15687 +};
15688 +
15689 +#endif /* _ASM_UBICOM32_UCONTEXT_H */
15690 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/unaligned.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unaligned.h
15691 --- linux-2.6.30.10/arch/ubicom32/include/asm/unaligned.h       1970-01-01 02:00:00.000000000 +0200
15692 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unaligned.h   2009-12-11 11:45:11.000000000 +0200
15693 @@ -0,0 +1,44 @@
15694 +/*
15695 + * arch/ubicom32/include/asm/unaligned.h
15696 + *   Ubicom32 architecture unaligned memory access definitions.
15697 + *
15698 + * (C) Copyright 2009, Ubicom, Inc.
15699 + *
15700 + * This file is part of the Ubicom32 Linux Kernel Port.
15701 + *
15702 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15703 + * it and/or modify it under the terms of the GNU General Public License
15704 + * as published by the Free Software Foundation, either version 2 of the
15705 + * License, or (at your option) any later version.
15706 + *
15707 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15708 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15709 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15710 + * the GNU General Public License for more details.
15711 + *
15712 + * You should have received a copy of the GNU General Public License
15713 + * along with the Ubicom32 Linux Kernel Port.  If not,
15714 + * see <http://www.gnu.org/licenses/>.
15715 + *
15716 + * Ubicom32 implementation derived from (with many thanks):
15717 + *   arch/m68knommu
15718 + *   arch/blackfin
15719 + *   arch/parisc
15720 + *
15721 + * TODO: This is a copy of arm unaligned handling that probably needs
15722 + * to be optimized for UBICOM32, but it works for now.
15723 + */
15724 +
15725 +#ifndef _ASM_UBICOM32_UNALIGNED_H
15726 +#define _ASM_UBICOM32_UNALIGNED_H
15727 +
15728 +#include <asm/types.h>
15729 +
15730 +#include <linux/unaligned/le_byteshift.h>
15731 +#include <linux/unaligned/be_byteshift.h>
15732 +#include <linux/unaligned/generic.h>
15733 +
15734 +#define get_unaligned  __get_unaligned_be
15735 +#define put_unaligned  __put_unaligned_be
15736 +
15737 +#endif /* _ASM_UBICOM32_UNALIGNED_H */
15738 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/unistd.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unistd.h
15739 --- linux-2.6.30.10/arch/ubicom32/include/asm/unistd.h  1970-01-01 02:00:00.000000000 +0200
15740 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unistd.h      2009-12-11 11:45:11.000000000 +0200
15741 @@ -0,0 +1,400 @@
15742 +/*
15743 + * arch/ubicom32/include/asm/unistd.h
15744 + *   Ubicom32 architecture syscall definitions.
15745 + *
15746 + * (C) Copyright 2009, Ubicom, Inc.
15747 + *
15748 + * This file is part of the Ubicom32 Linux Kernel Port.
15749 + *
15750 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15751 + * it and/or modify it under the terms of the GNU General Public License
15752 + * as published by the Free Software Foundation, either version 2 of the
15753 + * License, or (at your option) any later version.
15754 + *
15755 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15756 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15757 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15758 + * the GNU General Public License for more details.
15759 + *
15760 + * You should have received a copy of the GNU General Public License
15761 + * along with the Ubicom32 Linux Kernel Port.  If not,
15762 + * see <http://www.gnu.org/licenses/>.
15763 + *
15764 + * Ubicom32 implementation derived from (with many thanks):
15765 + *   arch/m68knommu
15766 + *   arch/blackfin
15767 + *   arch/parisc
15768 + */
15769 +#ifndef _ASM_UBICOM32_UNISTD_H
15770 +#define _ASM_UBICOM32_UNISTD_H
15771 +
15772 +/*
15773 + * This file contains the system call numbers.
15774 + */
15775 +
15776 +#define __NR_restart_syscall      0
15777 +#define __NR_exit                1
15778 +#define __NR_fork                2
15779 +#define __NR_read                3
15780 +#define __NR_write               4
15781 +#define __NR_open                5
15782 +#define __NR_close               6
15783 +#define __NR_waitpid             7
15784 +#define __NR_creat               8
15785 +#define __NR_link                9
15786 +#define __NR_unlink             10
15787 +#define __NR_execve             11
15788 +#define __NR_chdir              12
15789 +#define __NR_time               13
15790 +#define __NR_mknod              14
15791 +#define __NR_chmod              15
15792 +#define __NR_chown              16
15793 +#define __NR_break              17
15794 +#define __NR_oldstat            18
15795 +#define __NR_lseek              19
15796 +#define __NR_getpid             20
15797 +#define __NR_mount              21
15798 +#define __NR_umount             22
15799 +#define __NR_setuid             23
15800 +#define __NR_getuid             24
15801 +#define __NR_stime              25
15802 +#define __NR_ptrace             26
15803 +#define __NR_alarm              27
15804 +#define __NR_oldfstat           28
15805 +#define __NR_pause              29
15806 +#define __NR_utime              30
15807 +#define __NR_stty               31
15808 +#define __NR_gtty               32
15809 +#define __NR_access             33
15810 +#define __NR_nice               34
15811 +#define __NR_ftime              35
15812 +#define __NR_sync               36
15813 +#define __NR_kill               37
15814 +#define __NR_rename             38
15815 +#define __NR_mkdir              39
15816 +#define __NR_rmdir              40
15817 +#define __NR_dup                41
15818 +#define __NR_pipe               42
15819 +#define __NR_times              43
15820 +#define __NR_prof               44
15821 +#define __NR_brk                45
15822 +#define __NR_setgid             46
15823 +#define __NR_getgid             47
15824 +#define __NR_signal             48
15825 +#define __NR_geteuid            49
15826 +#define __NR_getegid            50
15827 +#define __NR_acct               51
15828 +#define __NR_umount2            52
15829 +#define __NR_lock               53
15830 +#define __NR_ioctl              54
15831 +#define __NR_fcntl              55
15832 +#define __NR_mpx                56
15833 +#define __NR_setpgid            57
15834 +#define __NR_ulimit             58
15835 +#define __NR_oldolduname        59
15836 +#define __NR_umask              60
15837 +#define __NR_chroot             61
15838 +#define __NR_ustat              62
15839 +#define __NR_dup2               63
15840 +#define __NR_getppid            64
15841 +#define __NR_getpgrp            65
15842 +#define __NR_setsid             66
15843 +#define __NR_sigaction          67
15844 +#define __NR_sgetmask           68
15845 +#define __NR_ssetmask           69
15846 +#define __NR_setreuid           70
15847 +#define __NR_setregid           71
15848 +#define __NR_sigsuspend                 72
15849 +#define __NR_sigpending                 73
15850 +#define __NR_sethostname        74
15851 +#define __NR_setrlimit          75
15852 +#define __NR_getrlimit          76
15853 +#define __NR_getrusage          77
15854 +#define __NR_gettimeofday       78
15855 +#define __NR_settimeofday       79
15856 +#define __NR_getgroups          80
15857 +#define __NR_setgroups          81
15858 +#define __NR_select             82
15859 +#define __NR_symlink            83
15860 +#define __NR_oldlstat           84
15861 +#define __NR_readlink           85
15862 +#define __NR_uselib             86
15863 +#define __NR_swapon             87
15864 +#define __NR_reboot             88
15865 +#define __NR_readdir            89
15866 +#define __NR_mmap               90
15867 +#define __NR_munmap             91
15868 +#define __NR_truncate           92
15869 +#define __NR_ftruncate          93
15870 +#define __NR_fchmod             94
15871 +#define __NR_fchown             95
15872 +#define __NR_getpriority        96
15873 +#define __NR_setpriority        97
15874 +#define __NR_profil             98
15875 +#define __NR_statfs             99
15876 +#define __NR_fstatfs           100
15877 +#define __NR_ioperm            101
15878 +#define __NR_socketcall                102
15879 +#define __NR_syslog            103
15880 +#define __NR_setitimer         104
15881 +#define __NR_getitimer         105
15882 +#define __NR_stat              106
15883 +#define __NR_lstat             107
15884 +#define __NR_fstat             108
15885 +#define __NR_olduname          109
15886 +#define __NR_iopl              /* 110 */ not supported
15887 +#define __NR_vhangup           111
15888 +#define __NR_idle              /* 112 */ Obsolete
15889 +#define __NR_vm86              /* 113 */ not supported
15890 +#define __NR_wait4             114
15891 +#define __NR_swapoff           115
15892 +#define __NR_sysinfo           116
15893 +#define __NR_ipc               117
15894 +#define __NR_fsync             118
15895 +#define __NR_sigreturn         119
15896 +#define __NR_clone             120
15897 +#define __NR_setdomainname     121
15898 +#define __NR_uname             122
15899 +#define __NR_cacheflush                123
15900 +#define __NR_adjtimex          124
15901 +#define __NR_mprotect          125
15902 +#define __NR_sigprocmask       126
15903 +#define __NR_create_module     127
15904 +#define __NR_init_module       128
15905 +#define __NR_delete_module     129
15906 +#define __NR_get_kernel_syms   130
15907 +#define __NR_quotactl          131
15908 +#define __NR_getpgid           132
15909 +#define __NR_fchdir            133
15910 +#define __NR_bdflush           134
15911 +#define __NR_sysfs             135
15912 +#define __NR_personality       136
15913 +#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
15914 +#define __NR_setfsuid          138
15915 +#define __NR_setfsgid          139
15916 +#define __NR__llseek           140
15917 +#define __NR_getdents          141
15918 +#define __NR__newselect                142
15919 +#define __NR_flock             143
15920 +#define __NR_msync             144
15921 +#define __NR_readv             145
15922 +#define __NR_writev            146
15923 +#define __NR_getsid            147
15924 +#define __NR_fdatasync         148
15925 +#define __NR__sysctl           149
15926 +#define __NR_mlock             150
15927 +#define __NR_munlock           151
15928 +#define __NR_mlockall          152
15929 +#define __NR_munlockall                153
15930 +#define __NR_sched_setparam            154
15931 +#define __NR_sched_getparam            155
15932 +#define __NR_sched_setscheduler                156
15933 +#define __NR_sched_getscheduler                157
15934 +#define __NR_sched_yield               158
15935 +#define __NR_sched_get_priority_max    159
15936 +#define __NR_sched_get_priority_min    160
15937 +#define __NR_sched_rr_get_interval     161
15938 +#define __NR_nanosleep         162
15939 +#define __NR_mremap            163
15940 +#define __NR_setresuid         164
15941 +#define __NR_getresuid         165
15942 +#define __NR_getpagesize       166
15943 +#define __NR_query_module      167
15944 +#define __NR_poll              168
15945 +#define __NR_nfsservctl                169
15946 +#define __NR_setresgid         170
15947 +#define __NR_getresgid         171
15948 +#define __NR_prctl             172
15949 +#define __NR_rt_sigreturn      173
15950 +#define __NR_rt_sigaction      174
15951 +#define __NR_rt_sigprocmask    175
15952 +#define __NR_rt_sigpending     176
15953 +#define __NR_rt_sigtimedwait   177
15954 +#define __NR_rt_sigqueueinfo   178
15955 +#define __NR_rt_sigsuspend     179
15956 +#define __NR_pread64           180
15957 +#define __NR_pwrite64          181
15958 +#define __NR_lchown            182
15959 +#define __NR_getcwd            183
15960 +#define __NR_capget            184
15961 +#define __NR_capset            185
15962 +#define __NR_sigaltstack       186
15963 +#define __NR_sendfile          187
15964 +#define __NR_getpmsg           188     /* some people actually want streams */
15965 +#define __NR_putpmsg           189     /* some people actually want streams */
15966 +#define __NR_vfork             190
15967 +#define __NR_ugetrlimit                191
15968 +#define __NR_mmap2             192
15969 +#define __NR_truncate64                193
15970 +#define __NR_ftruncate64       194
15971 +#define __NR_stat64            195
15972 +#define __NR_lstat64           196
15973 +#define __NR_fstat64           197
15974 +#define __NR_chown32           198
15975 +#define __NR_getuid32          199
15976 +#define __NR_getgid32          200
15977 +#define __NR_geteuid32         201
15978 +#define __NR_getegid32         202
15979 +#define __NR_setreuid32                203
15980 +#define __NR_setregid32                204
15981 +#define __NR_getgroups32       205
15982 +#define __NR_setgroups32       206
15983 +#define __NR_fchown32          207
15984 +#define __NR_setresuid32       208
15985 +#define __NR_getresuid32       209
15986 +#define __NR_setresgid32       210
15987 +#define __NR_getresgid32       211
15988 +#define __NR_lchown32          212
15989 +#define __NR_setuid32          213
15990 +#define __NR_setgid32          214
15991 +#define __NR_setfsuid32                215
15992 +#define __NR_setfsgid32                216
15993 +#define __NR_pivot_root                217
15994 +#define __NR_getdents64                220
15995 +#define __NR_gettid            221
15996 +#define __NR_tkill             222
15997 +#define __NR_setxattr          223
15998 +#define __NR_lsetxattr         224
15999 +#define __NR_fsetxattr         225
16000 +#define __NR_getxattr          226
16001 +#define __NR_lgetxattr         227
16002 +#define __NR_fgetxattr         228
16003 +#define __NR_listxattr         229
16004 +#define __NR_llistxattr                230
16005 +#define __NR_flistxattr                231
16006 +#define __NR_removexattr       232
16007 +#define __NR_lremovexattr      233
16008 +#define __NR_fremovexattr      234
16009 +#define __NR_futex             235
16010 +#define __NR_sendfile64                236
16011 +#define __NR_mincore           237
16012 +#define __NR_madvise           238
16013 +#define __NR_fcntl64           239
16014 +#define __NR_readahead         240
16015 +#define __NR_io_setup          241
16016 +#define __NR_io_destroy                242
16017 +#define __NR_io_getevents      243
16018 +#define __NR_io_submit         244
16019 +#define __NR_io_cancel         245
16020 +#define __NR_fadvise64         246
16021 +#define __NR_exit_group                247
16022 +#define __NR_lookup_dcookie    248
16023 +#define __NR_epoll_create      249
16024 +#define __NR_epoll_ctl         250
16025 +#define __NR_epoll_wait                251
16026 +#define __NR_remap_file_pages  252
16027 +#define __NR_set_tid_address   253
16028 +#define __NR_timer_create      254
16029 +#define __NR_timer_settime     255
16030 +#define __NR_timer_gettime     256
16031 +#define __NR_timer_getoverrun  257
16032 +#define __NR_timer_delete      258
16033 +#define __NR_clock_settime     259
16034 +#define __NR_clock_gettime     260
16035 +#define __NR_clock_getres      261
16036 +#define __NR_clock_nanosleep   262
16037 +#define __NR_statfs64          263
16038 +#define __NR_fstatfs64         264
16039 +#define __NR_tgkill            265
16040 +#define __NR_utimes            266
16041 +#define __NR_fadvise64_64      267
16042 +#define __NR_mbind             268
16043 +#define __NR_get_mempolicy     269
16044 +#define __NR_set_mempolicy     270
16045 +#define __NR_mq_open           271
16046 +#define __NR_mq_unlink         272
16047 +#define __NR_mq_timedsend      273
16048 +#define __NR_mq_timedreceive   274
16049 +#define __NR_mq_notify         275
16050 +#define __NR_mq_getsetattr     276
16051 +#define __NR_waitid            277
16052 +#define __NR_vserver           278
16053 +#define __NR_add_key           279
16054 +#define __NR_request_key       280
16055 +#define __NR_keyctl            281
16056 +#define __NR_ioprio_set                282
16057 +#define __NR_ioprio_get                283
16058 +#define __NR_inotify_init      284
16059 +#define __NR_inotify_add_watch 285
16060 +#define __NR_inotify_rm_watch  286
16061 +#define __NR_migrate_pages     287
16062 +#define __NR_openat            288
16063 +#define __NR_mkdirat           289
16064 +#define __NR_mknodat           290
16065 +#define __NR_fchownat          291
16066 +#define __NR_futimesat         292
16067 +#define __NR_fstatat64         293
16068 +#define __NR_unlinkat          294
16069 +#define __NR_renameat          295
16070 +#define __NR_linkat            296
16071 +#define __NR_symlinkat         297
16072 +#define __NR_readlinkat                298
16073 +#define __NR_fchmodat          299
16074 +#define __NR_faccessat         300
16075 +#define __NR_pselect6          301
16076 +#define __NR_ppoll             302
16077 +#define __NR_unshare           303
16078 +#define __NR_set_robust_list   304
16079 +#define __NR_get_robust_list   305
16080 +#define __NR_splice            306
16081 +#define __NR_sync_file_range   307
16082 +#define __NR_tee               308
16083 +#define __NR_vmsplice          309
16084 +#define __NR_move_pages                310
16085 +#define __NR_sched_setaffinity 311
16086 +#define __NR_sched_getaffinity 312
16087 +#define __NR_kexec_load                313
16088 +#define __NR_getcpu            314
16089 +#define __NR_epoll_pwait       315
16090 +#define __NR_utimensat         316
16091 +#define __NR_signalfd          317
16092 +#define __NR_timerfd_create    318
16093 +#define __NR_eventfd           319
16094 +#define __NR_fallocate         320
16095 +#define __NR_timerfd_settime   321
16096 +#define __NR_timerfd_gettime   322
16097 +#define __NR_signalfd4         323
16098 +#define __NR_eventfd2          324
16099 +#define __NR_epoll_create1     325
16100 +#define __NR_dup3              326
16101 +#define __NR_pipe2             327
16102 +#define __NR_inotify_init1     328
16103 +
16104 +#ifdef __KERNEL__
16105 +
16106 +#define NR_syscalls            329
16107 +
16108 +#define __ARCH_WANT_IPC_PARSE_VERSION
16109 +#define __ARCH_WANT_OLD_READDIR
16110 +#define __ARCH_WANT_OLD_STAT
16111 +#define __ARCH_WANT_STAT64
16112 +#define __ARCH_WANT_SYS_ALARM
16113 +#define __ARCH_WANT_SYS_GETHOSTNAME
16114 +#define __ARCH_WANT_SYS_PAUSE
16115 +#define __ARCH_WANT_SYS_SGETMASK
16116 +#define __ARCH_WANT_SYS_SIGNAL
16117 +#define __ARCH_WANT_SYS_TIME
16118 +#define __ARCH_WANT_SYS_UTIME
16119 +#define __ARCH_WANT_SYS_WAITPID
16120 +#define __ARCH_WANT_SYS_SOCKETCALL
16121 +#define __ARCH_WANT_SYS_FADVISE64
16122 +#define __ARCH_WANT_SYS_GETPGRP
16123 +#define __ARCH_WANT_SYS_LLSEEK
16124 +#define __ARCH_WANT_SYS_NICE
16125 +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
16126 +#define __ARCH_WANT_SYS_OLDUMOUNT
16127 +#define __ARCH_WANT_SYS_SIGPENDING
16128 +#define __ARCH_WANT_SYS_SIGPROCMASK
16129 +#define __ARCH_WANT_SYS_RT_SIGACTION
16130 +
16131 +/*
16132 + * "Conditional" syscalls
16133 + *
16134 + * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
16135 + * but it doesn't work on all toolchains, so we just do it by hand
16136 + */
16137 +//#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
16138 +#define cond_syscall(x) long x(void)  __attribute__((weak,alias("sys_ni_syscall")))
16139 +#endif /* __KERNEL__ */
16140 +
16141 +#endif /* _ASM_UBICOM32_UNISTD_H */
16142 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/user.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/user.h
16143 --- linux-2.6.30.10/arch/ubicom32/include/asm/user.h    1970-01-01 02:00:00.000000000 +0200
16144 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/user.h        2009-12-11 11:45:11.000000000 +0200
16145 @@ -0,0 +1,82 @@
16146 +/*
16147 + * arch/ubicom32/include/asm/user.h
16148 + *   Ubicom32 architecture core file definitions.
16149 + *
16150 + * (C) Copyright 2009, Ubicom, Inc.
16151 + *
16152 + * This file is part of the Ubicom32 Linux Kernel Port.
16153 + *
16154 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16155 + * it and/or modify it under the terms of the GNU General Public License
16156 + * as published by the Free Software Foundation, either version 2 of the
16157 + * License, or (at your option) any later version.
16158 + *
16159 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16160 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16161 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16162 + * the GNU General Public License for more details.
16163 + *
16164 + * You should have received a copy of the GNU General Public License
16165 + * along with the Ubicom32 Linux Kernel Port.  If not,
16166 + * see <http://www.gnu.org/licenses/>.
16167 + *
16168 + * Ubicom32 implementation derived from (with many thanks):
16169 + *   arch/m68knommu
16170 + *   arch/blackfin
16171 + *   arch/parisc
16172 + */
16173 +#ifndef _ASM_UBICOM32_USER_H
16174 +#define _ASM_UBICOM32_USER_H
16175 +
16176 +#include <asm/ptrace.h>
16177 +#include <asm/page.h>
16178 +/*
16179 + * Adapted from <asm-powerpc/user.h>
16180 + *
16181 + * Core file format: The core file is written in such a way that gdb
16182 + * can understand it and provide useful information to the user (under
16183 + * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
16184 + * are as follows:
16185 + *
16186 + *  upage: 1 page consisting of a user struct that tells gdb
16187 + *     what is present in the file.  Directly after this is a
16188 + *     copy of the task_struct, which is currently not used by gdb,
16189 + *     but it may come in handy at some point.  All of the registers
16190 + *     are stored as part of the upage.  The upage should always be
16191 + *     only one page long.
16192 + *  data: The data segment follows next.  We use current->end_text to
16193 + *     current->brk to pick up all of the user variables, plus any memory
16194 + *     that may have been sbrk'ed.  No attempt is made to determine if a
16195 + *     page is demand-zero or if a page is totally unused, we just cover
16196 + *     the entire range.  All of the addresses are rounded in such a way
16197 + *     that an integral number of pages is written.
16198 + *  stack: We need the stack information in order to get a meaningful
16199 + *     backtrace.  We need to write the data from usp to
16200 + *     current->start_stack, so we round each of these in order to be able
16201 + *     to write an integer number of pages.
16202 + */
16203 +
16204 +struct user_ubicom32fp_struct {
16205 +};
16206 +
16207 +struct user {
16208 +       struct pt_regs  regs;                   /* entire machine state */
16209 +       size_t          u_tsize;                /* text size (pages) */
16210 +       size_t          u_dsize;                /* data size (pages) */
16211 +       size_t          u_ssize;                /* stack size (pages) */
16212 +       unsigned long   start_code;             /* text starting address */
16213 +       unsigned long   start_data;             /* data starting address */
16214 +       unsigned long   start_stack;            /* stack starting address */
16215 +       long int        signal;                 /* signal causing core dump */
16216 +       unsigned long   u_ar0;                  /* help gdb find registers */
16217 +       unsigned long   magic;                  /* identifies a core file */
16218 +       char            u_comm[32];             /* user command name */
16219 +};
16220 +
16221 +#define NBPG                   PAGE_SIZE
16222 +#define UPAGES                 1
16223 +#define HOST_TEXT_START_ADDR   (u.start_code)
16224 +#define HOST_DATA_START_ADDR   (u.start_data)
16225 +#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
16226 +
16227 +#endif /* _ASM_UBICOM32_USER_H */
16228 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/vdc_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vdc_tio.h
16229 --- linux-2.6.30.10/arch/ubicom32/include/asm/vdc_tio.h 1970-01-01 02:00:00.000000000 +0200
16230 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vdc_tio.h     2009-12-11 11:45:11.000000000 +0200
16231 @@ -0,0 +1,129 @@
16232 +/*
16233 + * arch/ubicom32/include/asm/vdc_tio.h
16234 + *   Ubicom32 architecture VDC TIO definitions.
16235 + *
16236 + * (C) Copyright 2009, Ubicom, Inc.
16237 + *
16238 + * This file is part of the Ubicom32 Linux Kernel Port.
16239 + *
16240 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16241 + * it and/or modify it under the terms of the GNU General Public License
16242 + * as published by the Free Software Foundation, either version 2 of the
16243 + * License, or (at your option) any later version.
16244 + *
16245 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16246 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16247 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16248 + * the GNU General Public License for more details.
16249 + *
16250 + * You should have received a copy of the GNU General Public License
16251 + * along with the Ubicom32 Linux Kernel Port.  If not,
16252 + * see <http://www.gnu.org/licenses/>.
16253 + *
16254 + * Ubicom32 implementation derived from (with many thanks):
16255 + *   arch/m68knommu
16256 + *   arch/blackfin
16257 + *   arch/parisc
16258 + */
16259 +#ifndef _ASM_UBICOM32_VDC_TIO_H
16260 +#define _ASM_UBICOM32_VDC_TIO_H
16261 +
16262 +#include <asm/devtree.h>
16263 +
16264 +#define VDCTIO_VP_VERSION                      5
16265 +
16266 +#define VDCTIO_SCALE_FLAG_VSUB                 (1 << 9)
16267 +#define VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER       (1 << 8)
16268 +#define VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER      (1 << 7)
16269 +#define VDCTIO_SCALE_FLAG_YUV                  (1 << 6)
16270 +#define VDCTIO_SCALE_FLAG_VRANGE_16_255                (1 << 5)
16271 +#define VDCTIO_SCALE_FLAG_VRANGE_0_255         (1 << 4)
16272 +#define VDCTIO_SCALE_FLAG_HSUB_2_1             (1 << 3)
16273 +#define VDCTIO_SCALE_FLAG_HSUB_1_1             (1 << 2)
16274 +#define VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER     (1 << 1)
16275 +#define VDCTIO_SCALE_FLAG_ENABLE               (1 << 0)
16276 +
16277 +#define VDCTIO_NEXT_FRAME_FLAG_YUV_BIT         0
16278 +#define VDCTIO_NEXT_FRAME_FLAG_YUV             (1 << (VDCTIO_NEXT_FRAME_FLAG_YUV_BIT))
16279 +
16280 +#define VDCTIO_CAPS_SUPPORTS_SCALING           (1 << 0)
16281 +
16282 +#define VDCTIO_COMMAND_START                   (1 << 3)
16283 +#define VDCTIO_COMMAND_SET_COEFF               (1 << 2)
16284 +#define VDCTIO_COMMAND_SET_LUT                 (1 << 1)
16285 +#define VDCTIO_COMMAND_SET_SCALE_MODE          (1 << 0)
16286 +
16287 +/*
16288 + * Command / Data registers to access the VDC
16289 + */
16290 +struct vdc_tio_vp_regs {
16291 +       /*
16292 +        * Version of this TIO register map
16293 +        */
16294 +       u32_t           version;
16295 +
16296 +       volatile u32_t  command;
16297 +
16298 +       /*
16299 +        * Next frame pointer, when the command VDCTIO_COMMAND_SET_FRAME_BUFFER is set,
16300 +        * the vdc will take the pointer here and display it.
16301 +        */
16302 +       void            *next_frame;
16303 +       u32_t           next_frame_flags;
16304 +
16305 +       /*
16306 +        * These map directly into the PIXP registers 0x20-0x80.
16307 +        * DO NOT change the order of these three variables.
16308 +        */
16309 +       u32_t           red_lut[6];
16310 +       u32_t           blue_lut[6];
16311 +       u32_t           green_lut[13];
16312 +
16313 +       /*
16314 +        * These map directly into the PIXP registers 0x04, 0x08
16315 +        */
16316 +       u32_t           coeff0;
16317 +       u32_t           coeff1;
16318 +
16319 +       /*
16320 +        * There are used to set the scaling parameters
16321 +        */
16322 +       u32_t           x_in;
16323 +       u32_t           x_out;
16324 +       u32_t           y_in;
16325 +       u32_t           y_out;
16326 +       u32_t           scale_flags;
16327 +
16328 +       /*
16329 +        * Current frame number, monotonically increasing number
16330 +        */
16331 +       u32_t           frame_number;
16332 +
16333 +       /*
16334 +        * These variables tell the guest OS what the underlying hardware looks like
16335 +        */
16336 +       u32_t           caps;
16337 +       u32_t           xres;
16338 +       u32_t           yres;
16339 +       u32_t           fb_align;
16340 +       u8_t            bpp;
16341 +       u8_t            rbits;
16342 +       u8_t            gbits;
16343 +       u8_t            bbits;
16344 +       u8_t            rshift;
16345 +       u8_t            gshift;
16346 +       u8_t            bshift;
16347 +};
16348 +
16349 +/*
16350 + * Devtree node for VDC
16351 + */
16352 +struct vdc_tio_node {
16353 +       struct devtree_node     dn;
16354 +
16355 +       struct vdc_tio_vp_regs  *regs;
16356 +};
16357 +
16358 +extern void vdc_tio_init(void);
16359 +
16360 +#endif /* _ASM_UBICOM32_VDC_TIO_H */
16361 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/vga.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vga.h
16362 --- linux-2.6.30.10/arch/ubicom32/include/asm/vga.h     1970-01-01 02:00:00.000000000 +0200
16363 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vga.h 2009-12-11 11:45:11.000000000 +0200
16364 @@ -0,0 +1,71 @@
16365 +/*
16366 + * arch/ubicom32/include/asm/vga.h
16367 + *   Ubicom32 low level  VGA/frame buffer definitions.
16368 + *
16369 + * (C) Copyright 2009, Ubicom, Inc.
16370 + * (c) 1998 Martin Mares <mj@ucw.cz>
16371 + *
16372 + * This file is part of the Ubicom32 Linux Kernel Port.
16373 + *
16374 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16375 + * it and/or modify it under the terms of the GNU General Public License
16376 + * as published by the Free Software Foundation, either version 2 of the
16377 + * License, or (at your option) any later version.
16378 + *
16379 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16380 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16381 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16382 + * the GNU General Public License for more details.
16383 + *
16384 + * You should have received a copy of the GNU General Public License
16385 + * along with the Ubicom32 Linux Kernel Port.  If not,
16386 + * see <http://www.gnu.org/licenses/>.
16387 + *
16388 + * Ubicom32 implementation derived from (with many thanks):
16389 + *   arch/m68knommu
16390 + *   arch/blackfin
16391 + *   arch/parisc
16392 + */
16393 +
16394 +#ifndef _ASM_UBICOM32_VGA_H
16395 +#define _ASM_UBICOM32_VGA_H
16396 +
16397 +#include <asm/byteorder.h>
16398 +
16399 +/*
16400 + *     On the PC, we can just recalculate addresses and then
16401 + *     access the videoram directly without any black magic.
16402 + */
16403 +
16404 +#define VGA_MAP_MEM(x, s)      (0xb0000000L + (unsigned long)(x))
16405 +
16406 +#define vga_readb(x)   (*(x))
16407 +#define vga_writeb(x, y)       (*(y) = (x))
16408 +
16409 +#define VT_BUF_HAVE_RW
16410 +/*
16411 + *  These are only needed for supporting VGA or MDA text mode, which use little
16412 + *  endian byte ordering.
16413 + *  In other cases, we can optimize by using native byte ordering and
16414 + *  <linux/vt_buffer.h> has already done the right job for us.
16415 + */
16416 +
16417 +#undef scr_writew
16418 +#undef scr_readw
16419 +
16420 +static inline void scr_writew(u16 val, volatile u16 *addr)
16421 +{
16422 +       *addr = cpu_to_le16(val);
16423 +}
16424 +
16425 +static inline u16 scr_readw(volatile const u16 *addr)
16426 +{
16427 +       return le16_to_cpu(*addr);
16428 +}
16429 +
16430 +#define scr_memcpyw(d, s, c) memcpy(d, s, c)
16431 +#define scr_memmovew(d, s, c) memmove(d, s, c)
16432 +#define VT_BUF_HAVE_MEMCPYW
16433 +#define VT_BUF_HAVE_MEMMOVEW
16434 +
16435 +#endif /* _ASM_UBICOM32_VGA_H */
16436 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/xor.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/xor.h
16437 --- linux-2.6.30.10/arch/ubicom32/include/asm/xor.h     1970-01-01 02:00:00.000000000 +0200
16438 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/xor.h 2009-12-11 11:45:11.000000000 +0200
16439 @@ -0,0 +1,33 @@
16440 +/*
16441 + * arch/ubicom32/include/asm/xor.h
16442 + *   Generic xor.h definitions for Ubicom32 architecture.
16443 + *
16444 + * (C) Copyright 2009, Ubicom, Inc.
16445 + *
16446 + * This file is part of the Ubicom32 Linux Kernel Port.
16447 + *
16448 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16449 + * it and/or modify it under the terms of the GNU General Public License
16450 + * as published by the Free Software Foundation, either version 2 of the
16451 + * License, or (at your option) any later version.
16452 + *
16453 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16454 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16455 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16456 + * the GNU General Public License for more details.
16457 + *
16458 + * You should have received a copy of the GNU General Public License
16459 + * along with the Ubicom32 Linux Kernel Port.  If not,
16460 + * see <http://www.gnu.org/licenses/>.
16461 + *
16462 + * Ubicom32 implementation derived from (with many thanks):
16463 + *   arch/m68knommu
16464 + *   arch/blackfin
16465 + *   arch/parisc
16466 + */
16467 +#ifndef _ASM_UBICOM32_XOR_H
16468 +#define _ASM_UBICOM32_XOR_H
16469 +
16470 +#include <asm-generic/xor.h>
16471 +
16472 +#endif /* _ASM_UBICOM32_XOR_H */
16473 diff -ruN linux-2.6.30.10/arch/ubicom32/Kconfig linux-2.6.30.10-ubi/arch/ubicom32/Kconfig
16474 --- linux-2.6.30.10/arch/ubicom32/Kconfig       1970-01-01 02:00:00.000000000 +0200
16475 +++ linux-2.6.30.10-ubi/arch/ubicom32/Kconfig   2009-12-11 11:45:11.000000000 +0200
16476 @@ -0,0 +1,403 @@
16477 +#
16478 +# For a description of the syntax of this configuration file,
16479 +# see Documentation/kbuild/kconfig-language.txt.
16480 +#
16481 +
16482 +mainmenu "uClinux/ubicom32 (w/o MMU) Kernel Configuration"
16483 +
16484 +config UBICOM32
16485 +       bool
16486 +       select HAVE_OPROFILE
16487 +       default y
16488 +
16489 +config RAMKERNEL
16490 +       bool
16491 +       default y
16492 +
16493 +config CPU_BIG_ENDIAN
16494 +       bool
16495 +       default y
16496 +
16497 +config FORCE_MAX_ZONEORDER
16498 +       int
16499 +       default "14"
16500 +
16501 +config HAVE_CLK
16502 +       bool
16503 +       default y
16504 +
16505 +config MMU
16506 +       bool
16507 +       default n
16508 +
16509 +config FPU
16510 +       bool
16511 +       default n
16512 +
16513 +config ZONE_DMA
16514 +       bool
16515 +       default y
16516 +
16517 +config RWSEM_GENERIC_SPINLOCK
16518 +       bool
16519 +       default y
16520 +
16521 +config RWSEM_XCHGADD_ALGORITHM
16522 +       bool
16523 +       default n
16524 +
16525 +config ARCH_HAS_ILOG2_U32
16526 +       bool
16527 +       default n
16528 +
16529 +config ARCH_HAS_ILOG2_U64
16530 +       bool
16531 +       default n
16532 +
16533 +config GENERIC_FIND_NEXT_BIT
16534 +       bool
16535 +       default y
16536 +
16537 +config GENERIC_GPIO
16538 +       bool
16539 +       default y
16540 +
16541 +config GPIOLIB
16542 +       bool
16543 +       default y
16544 +
16545 +config GENERIC_HWEIGHT
16546 +       bool
16547 +       default y
16548 +
16549 +config GENERIC_HARDIRQS
16550 +       bool
16551 +       default y
16552 +
16553 +config STACKTRACE_SUPPORT
16554 +       bool
16555 +       default y
16556 +
16557 +config LOCKDEP_SUPPORT
16558 +       bool
16559 +       default y
16560 +
16561 +config GENERIC_CALIBRATE_DELAY
16562 +       bool
16563 +       default y
16564 +
16565 +config GENERIC_TIME
16566 +       bool
16567 +       default y
16568 +
16569 +config TIME_LOW_RES
16570 +       bool
16571 +       default y
16572 +
16573 +config GENERIC_CLOCKEVENTS
16574 +       bool
16575 +       default y
16576 +
16577 +config GENERIC_CLOCKEVENTS_BROADCAST
16578 +       bool
16579 +       depends on GENERIC_CLOCKEVENTS
16580 +       default y if SMP && !LOCAL_TIMERS
16581 +
16582 +config NO_IOPORT
16583 +       def_bool y
16584 +
16585 +config ARCH_SUPPORTS_AOUT
16586 +       def_bool y
16587 +
16588 +config IRQ_PER_CPU
16589 +       bool
16590 +       default y
16591 +
16592 +config SCHED_NO_NO_OMIT_FRAME_POINTER
16593 +       bool
16594 +       default y
16595 +
16596 +config UBICOM32_PLIO
16597 +       bool
16598 +       default n
16599 +
16600 +menu "Processor type and features"
16601 +
16602 +comment "Processor type will be selected by Board"
16603 +
16604 +config UBICOM32_V3
16605 +       bool
16606 +       help
16607 +         Ubicom IP5xxx series processor support.
16608 +
16609 +config UBICOM32_V4
16610 +       bool
16611 +       help
16612 +         Ubicom IP7xxx series processor support.
16613 +
16614 +comment "Board"
16615 +choice
16616 +       prompt "Board type"
16617 +       help
16618 +               Select your board.
16619 +
16620 +config NOBOARD
16621 +       bool "No board selected"
16622 +       help
16623 +               Default. Don't select any board specific config. Will not build unless you change!
16624 +
16625 +# Add your boards here
16626 +source "arch/ubicom32/mach-ip5k/Kconfig"
16627 +source "arch/ubicom32/mach-ip7k/Kconfig"
16628 +
16629 +endchoice
16630 +
16631 +comment "Kernel Options"
16632 +config SMP
16633 +       bool "Symmetric multi-processing support"
16634 +       select USE_GENERIC_SMP_HELPERS
16635 +       default n
16636 +       help
16637 +         Enables multithreading support.  Enabling SMP support increases
16638 +         the size of system data structures.  SMP support can have either
16639 +         positive or negative impact on performance depending on workloads.
16640 +
16641 +         If you do not know what to do here, say N.
16642 +config OLD_40400010_SYSTEM_CALL
16643 +       bool "Provide old system call interface at 0x40400010"
16644 +       default y
16645 +       help
16646 +         Provides the old system call interface, does not affect the
16647 +         new system_call interface.
16648 +
16649 +config NR_CPUS
16650 +       int "Number of configured CPUs"
16651 +       range 2 32
16652 +       default 2
16653 +       depends on SMP
16654 +       help
16655 +               Upper bound on the number of CPUs. Space is reserved
16656 +               at compile time for this many CPUs.
16657 +
16658 +config LOCAL_TIMERS
16659 +       bool "Use local timer interrupts"
16660 +       depends on SMP
16661 +       default y
16662 +       help
16663 +         Enable support for local timers on SMP platforms, rather then the
16664 +         legacy IPI broadcast method.  Local timers allows the system
16665 +         accounting to be spread across the timer interval, preventing a
16666 +         "thundering herd" at every timer tick.  A physical timer is allocated
16667 +         per cpu.
16668 +
16669 +config TIMER_EXTRA_ALLOC
16670 +       int "Number of additional physical timer events to create"
16671 +       depends on GENERIC_CLOCKEVENTS
16672 +       default 0
16673 +       help
16674 +               The Ubicom32 processor has a number of event timers that can be wrapped
16675 +               in Linux clock event structures (assuming that the timers are not being
16676 +               used for another purpose).  Based on the value of LOCAL_TIMERS, either
16677 +               2 timers will be used or a timer will be used for every CPU.  This value
16678 +               allows the programmer to select additional timers over that amount.
16679 +
16680 +config IRQSTACKS
16681 +       bool "Create separate stacks for interrupt handling"
16682 +       default n
16683 +       help
16684 +               Selecting this causes interrupts to be created on a separate
16685 +               stack instead of nesting the interrupts on the kernel stack.
16686 +
16687 +config IRQSTACKS_USEOCM
16688 +       bool "Use OCM for interrupt stacks"
16689 +       default n
16690 +       depends on IRQSTACKS
16691 +       help
16692 +               Selecting this cause the interrupt stacks to be placed in OCM
16693 +               reducing cache misses at the expense of using the OCM for servicing
16694 +               interrupts.
16695 +
16696 +menu "OCM Instruction Heap"
16697 +
16698 +config OCM_MODULES_RESERVATION
16699 +       int "OCM Instruction heap reservation. 0-192 kB"
16700 +       range 0 192
16701 +       default "0"
16702 +       help
16703 +         The minimum amount of OCM memory to reserve for kernel loadable module
16704 +         code. If you are not using this memory it cannot be used for anything
16705 +         else. Leave it as 0 if you have prebuilt modules that are compiled with
16706 +         OCM support.
16707 +
16708 +config OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
16709 +       bool "Give all unused ocm code space to the ocm instruction heap."
16710 +       default n
16711 +       help
16712 +         Allow the OCM instruction heap allocation to consume any remaining
16713 +         unused OCM code space.  The result of this is that you will not have
16714 +         and deterministic results, but you will not have any waste either.
16715 +
16716 +config OCM_MODULES_FALLBACK_TO_DDR
16717 +       bool "Loadable Modules requiring OCM may fallback to use DDR."
16718 +       default n
16719 +       help
16720 +         If a module cannot get the OCM code it requires allow DDR to
16721 +         be used instead.
16722 +endmenu
16723 +
16724 +config HZ
16725 +       int "Frequency of 'jiffies' (for polling)"
16726 +       default 1000
16727 +       help
16728 +               100 is common for embedded systems, but 1000 allows
16729 +               you to do more drivers without actually having
16730 +               interrupts working properly.
16731 +
16732 +comment "RAM configuration"
16733 +
16734 +config MIN_RAMSIZE
16735 +       hex "Minimum Size of RAM (in bytes)"
16736 +       range 0x01000000 0x08000000
16737 +       default "0x02000000"
16738 +       help
16739 +               Define the minimum acceptable size of the system
16740 +               RAM. Must be at least 16MB (0x01000000)
16741 +
16742 +comment "Build options"
16743 +config LINKER_RELAXATION
16744 +       bool "Linker Relaxation"
16745 +       default y
16746 +       help
16747 +         Turns on linker relaxation that will produce smaller
16748 +         faster code. Increases link time.
16749 +
16750 +comment "Driver options"
16751 +menu "PCI Bus"
16752 +config PCI
16753 +       bool "PCI bus"
16754 +       default true
16755 +       help
16756 +         Enable/Disable PCI bus
16757 +       source "drivers/pci/Kconfig"
16758 +
16759 +
16760 +config PCI_DEV0_IDSEL
16761 +       hex "slot 0 address"
16762 +       depends on PCI
16763 +       default "0x01000000"
16764 +       help
16765 +         Slot 0 address.  This address should correspond to the address line
16766 +         which the IDSEL bit for this slot is connected to.
16767 +
16768 +config PCI_DEV1_IDSEL
16769 +       hex "slot 1 address"
16770 +       depends on PCI
16771 +       default "0x02000000"
16772 +       help
16773 +         Slot 1 address.  This address should correspond to the address line
16774 +         which the IDSEL bit for this slot is connected to.
16775 +endmenu
16776 +# End PCI
16777 +
16778 +menu "Input devices"
16779 +config UBICOM_INPUT
16780 +       bool "Ubicom polled GPIO input driver"
16781 +       select INPUT
16782 +       select INPUT_POLLDEV
16783 +       help
16784 +               Polling input driver, much like the GPIO input driver, except that it doesn't
16785 +               rely on interrupts.  It will report events via the input subsystem.
16786 +       default n
16787 +
16788 +config UBICOM_INPUT_I2C
16789 +       bool "Ubicom polled GPIO input driver over I2C"
16790 +       select INPUT
16791 +       select INPUT_POLLDEV
16792 +       help
16793 +               Polling input driver, much like the PCA953x driver, it can support a variety of
16794 +               different I2C I/O expanders.  This device polls the I2C I/O expander for events
16795 +               and reports them via the input subsystem.
16796 +       default n
16797 +endmenu
16798 +# Input devices
16799 +
16800 +source "arch/ubicom32/mach-common/Kconfig.switch"
16801 +
16802 +menu "Misc devices"
16803 +config UBICOM_HID
16804 +       bool "Ubicom HID driver"
16805 +       select INPUT
16806 +       select INPUT_POLLDEV
16807 +       select LCD_CLASS_DEVICE
16808 +       help
16809 +               Driver for HID chip found on some Ubicom reference designs.  This chip handles
16810 +               PWM, button input, and IR remote control.  It registers as an input device and
16811 +               a backlight device.
16812 +       default n
16813 +endmenu
16814 +# Misc devices
16815 +
16816 +config CMDLINE_BOOL
16817 +       bool "Built-in kernel command line"
16818 +       default n
16819 +       help
16820 +         Allow for specifying boot arguments to the kernel at
16821 +         build time.  On some systems (e.g. embedded ones), it is
16822 +         necessary or convenient to provide some or all of the
16823 +         kernel boot arguments with the kernel itself (that is,
16824 +         to not rely on the boot loader to provide them.)
16825 +
16826 +         To compile command line arguments into the kernel,
16827 +         set this option to 'Y', then fill in the
16828 +         the boot arguments in CONFIG_CMDLINE.
16829 +
16830 +         Systems with fully functional boot loaders (i.e. non-embedded)
16831 +         should leave this option set to 'N'.
16832 +
16833 +config CMDLINE
16834 +       string "Built-in kernel command string"
16835 +       depends on CMDLINE_BOOL
16836 +       default ""
16837 +       help
16838 +         Enter arguments here that should be compiled into the kernel
16839 +         image and used at boot time.  If the boot loader provides a
16840 +         command line at boot time, it is appended to this string to
16841 +         form the full kernel command line, when the system boots.
16842 +
16843 +         However, you can use the CONFIG_CMDLINE_OVERRIDE option to
16844 +         change this behavior.
16845 +
16846 +         In most cases, the command line (whether built-in or provided
16847 +         by the boot loader) should specify the device for the root
16848 +         file system.
16849 +
16850 +config CMDLINE_OVERRIDE
16851 +       bool "Built-in command line overrides boot loader arguments"
16852 +       default n
16853 +       depends on CMDLINE_BOOL
16854 +       help
16855 +         Set this option to 'Y' to have the kernel ignore the boot loader
16856 +         command line, and use ONLY the built-in command line.
16857 +
16858 +         This is used to work around broken boot loaders.  This should
16859 +         be set to 'N' under normal conditions.
16860 +
16861 +endmenu
16862 +# End Processor type and features
16863 +
16864 +source "arch/ubicom32/Kconfig.debug"
16865 +
16866 +menu "Executable file formats"
16867 +source "fs/Kconfig.binfmt"
16868 +endmenu
16869 +
16870 +source "init/Kconfig"
16871 +source "kernel/Kconfig.preempt"
16872 +source "kernel/time/Kconfig"
16873 +source "mm/Kconfig"
16874 +source "net/Kconfig"
16875 +source "drivers/Kconfig"
16876 +source "fs/Kconfig"
16877 +source "security/Kconfig"
16878 +source "crypto/Kconfig"
16879 +source "lib/Kconfig"
16880 diff -ruN linux-2.6.30.10/arch/ubicom32/Kconfig.debug linux-2.6.30.10-ubi/arch/ubicom32/Kconfig.debug
16881 --- linux-2.6.30.10/arch/ubicom32/Kconfig.debug 1970-01-01 02:00:00.000000000 +0200
16882 +++ linux-2.6.30.10-ubi/arch/ubicom32/Kconfig.debug     2009-12-11 11:45:11.000000000 +0200
16883 @@ -0,0 +1,129 @@
16884 +menu "Kernel hacking"
16885 +
16886 +config TRACE_IRQFLAGS_SUPPORT
16887 +       def_bool y
16888 +
16889 +config DEBUG_VERBOSE
16890 +        bool "Verbose fault messages"
16891 +        default y
16892 +        select PRINTK
16893 +        help
16894 +          When a program crashes due to an exception, or the kernel detects
16895 +          an internal error, the kernel can print a not so brief message
16896 +          explaining what the problem was. This debugging information is
16897 +          useful to developers and kernel hackers when tracking down problems,
16898 +          but mostly meaningless to other people. This is always helpful for
16899 +          debugging but serves no purpose on a production system.
16900 +          Most people should say N here.
16901 +
16902 +config PROTECT_KERNEL
16903 +       default y
16904 +       bool 'Enable Kernel range register Protection'
16905 +       help
16906 +         Adds code to enable/disable range registers to protect static
16907 +         kernel code/data from userspace.  Currently the ranges covered
16908 +         do no protect kernel loadable modules or dynamically allocated
16909 +         kernel data.
16910 +
16911 +config NO_KERNEL_MSG
16912 +       bool "Suppress Kernel BUG Messages"
16913 +       help
16914 +         Do not output any debug BUG messages within the kernel.
16915 +
16916 +config EARLY_PRINTK
16917 +       bool "Use the driver that you selected as console also for early printk (to debug kernel bootup)."
16918 +       default n
16919 +       help
16920 +         If you want to use the serdes driver (console=ttyUS0) for
16921 +         early printk, you must also supply an additional kernel boot
16922 +         parameter like this:
16923 +
16924 +               serdes=ioportaddr,irq,clockrate,baud
16925 +
16926 +         For an IP7160RGW eval board, you could use this:
16927 +
16928 +               serdes=0x2004000,61,250000000,57600
16929 +
16930 +         which will let you see early printk output at 57600 baud.
16931 +
16932 +config STOP_ON_TRAP
16933 +       bool "Enable stopping at the LDSR for all traps"
16934 +       default n
16935 +       help
16936 +       Cause the LDSR to stop all threads whenever a trap is about to be serviced
16937 +
16938 +config STOP_ON_BUG
16939 +       bool "Enable stopping on failed BUG_ON()"
16940 +       default n
16941 +       help
16942 +       Cause all BUG_ON failures to stop all threads
16943 +
16944 +config DEBUG_IRQMEASURE
16945 +       bool "Enable IRQ handler measurements"
16946 +       default n
16947 +       help
16948 +       When enabled each IRQ's min/avg/max times will be printed.  If the handler
16949 +       re-enables interrupt, the times will show the full time including to service
16950 +       nested interrupts.  See /proc/irq_measurements.
16951 +
16952 +config DEBUG_PCIMEASURE
16953 +       bool "Enable PCI transaction measurements"
16954 +       default n
16955 +       help
16956 +       When enabled the system will measure the min/avg/max timer for each PCI transactions.
16957 +       See /proc/pci_measurements.
16958 +
16959 +config ACCESS_OK_CHECKS_ENABLED
16960 +       bool "Enable user space access checks"
16961 +       default n
16962 +       help
16963 +       Enabling this check causes the kernel to verify that addresses passed
16964 +       to the kernel by the user space code are within the processes
16965 +       address space.  On a no-mmu system, this is done by examining the
16966 +       processes memory data structures (adversly affecting performance) but
16967 +       ensuring that a process does not ask the kernel to violate another
16968 +       processes address space.  Sadly, the kernel uses access_ok() for
16969 +       address that are in the kernel which results in a large volume of
16970 +       false positives.
16971 +
16972 +choice
16973 +       prompt "Unaligned Access Support"
16974 +       default UNALIGNED_ACCESS_ENABLED
16975 +       help
16976 +               Kernel / Userspace unaligned access handling.
16977 +
16978 +config  UNALIGNED_ACCESS_ENABLED
16979 +       bool "Kernel and Userspace"
16980 +       help
16981 +
16982 +config  UNALIGNED_ACCESS_USERSPACE_ONLY
16983 +       bool "Userspace Only"
16984 +       help
16985 +
16986 +config  UNALIGNED_ACCESS_DISABLED
16987 +       bool "Disabled"
16988 +       help
16989 +
16990 +endchoice
16991 +
16992 +config DEBUG_STACKOVERFLOW
16993 +       bool "Check for stack overflows"
16994 +       default n
16995 +       depends on DEBUG_KERNEL
16996 +       help
16997 +         This option will cause messages to be printed if free kernel stack space
16998 +         drops below a certain limit (THREAD_SIZE /8).
16999 +
17000 +config DEBUG_STACK_USAGE
17001 +       bool "Stack utilization instrumentation"
17002 +       default n
17003 +       depends on DEBUG_KERNEL
17004 +       help
17005 +         Enables the display of the minimum amount of free kernel stack which each
17006 +         task has ever had available in the sysrq-T and sysrq-P debug output.
17007 +
17008 +         This option will slow down process creation somewhat.
17009 +
17010 +source "lib/Kconfig.debug"
17011 +
17012 +endmenu
17013 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/asm-offsets.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/asm-offsets.c
17014 --- linux-2.6.30.10/arch/ubicom32/kernel/asm-offsets.c  1970-01-01 02:00:00.000000000 +0200
17015 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/asm-offsets.c      2009-12-11 11:45:11.000000000 +0200
17016 @@ -0,0 +1,161 @@
17017 +/*
17018 + * arch/ubicom32/kernel/asm-offsets.c
17019 + *   Ubicom32 architecture definitions needed by assembly language modules.
17020 + *
17021 + * (C) Copyright 2009, Ubicom, Inc.
17022 + *
17023 + * This file is part of the Ubicom32 Linux Kernel Port.
17024 + *
17025 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17026 + * it and/or modify it under the terms of the GNU General Public License
17027 + * as published by the Free Software Foundation, either version 2 of the
17028 + * License, or (at your option) any later version.
17029 + *
17030 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17031 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17032 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17033 + * the GNU General Public License for more details.
17034 + *
17035 + * You should have received a copy of the GNU General Public License
17036 + * along with the Ubicom32 Linux Kernel Port.  If not,
17037 + * see <http://www.gnu.org/licenses/>.
17038 + *
17039 + * Ubicom32 implementation derived from (with many thanks):
17040 + *   arch/m68knommu
17041 + *   arch/blackfin
17042 + *   arch/parisc
17043 + */
17044 +/*
17045 + * This program is used to generate definitions needed by
17046 + * assembly language modules.
17047 + *
17048 + * We use the technique used in the OSF Mach kernel code:
17049 + * generate asm statements containing #defines,
17050 + * compile this file to assembler, and then extract the
17051 + * #defines from the assembly-language output.
17052 + */
17053 +
17054 +#include <linux/module.h>
17055 +#include <linux/stddef.h>
17056 +#include <linux/sched.h>
17057 +#include <linux/kernel_stat.h>
17058 +#include <linux/ptrace.h>
17059 +#include <linux/hardirq.h>
17060 +#include <asm/bootinfo.h>
17061 +#include <asm/irq.h>
17062 +#include <asm/thread_info.h>
17063 +
17064 +#define DEFINE(sym, val) \
17065 +        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
17066 +
17067 +#define BLANK() asm volatile("\n->" : : )
17068 +
17069 +int main(void)
17070 +{
17071 +       /* offsets into the task struct */
17072 +       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
17073 +       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
17074 +       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
17075 +       DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
17076 +       DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
17077 +       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
17078 +       DEFINE(TASK_MM, offsetof(struct task_struct, mm));
17079 +       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
17080 +
17081 +       /* offsets into the kernel_stat struct */
17082 +//     DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
17083 +
17084 +       /* offsets into the irq_cpustat_t struct */
17085 +       DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
17086 +
17087 +       /* offsets into the thread struct */
17088 +       DEFINE(THREAD_D10, offsetof(struct thread_struct, d10));
17089 +       DEFINE(THREAD_D11, offsetof(struct thread_struct, d11));
17090 +       DEFINE(THREAD_D12, offsetof(struct thread_struct, d12));
17091 +       DEFINE(THREAD_D13, offsetof(struct thread_struct, d13));
17092 +       DEFINE(THREAD_A1, offsetof(struct thread_struct, a1));
17093 +       DEFINE(THREAD_A2, offsetof(struct thread_struct, a2));
17094 +       DEFINE(THREAD_A5, offsetof(struct thread_struct, a5));
17095 +       DEFINE(THREAD_A6, offsetof(struct thread_struct, a6));
17096 +       DEFINE(THREAD_SP, offsetof(struct thread_struct, sp));
17097 +
17098 +       /* offsets into the pt_regs */
17099 +       DEFINE(PT_D0, offsetof(struct pt_regs, dn[0]));
17100 +       DEFINE(PT_D1, offsetof(struct pt_regs, dn[1]));
17101 +       DEFINE(PT_D2, offsetof(struct pt_regs, dn[2]));
17102 +       DEFINE(PT_D3, offsetof(struct pt_regs, dn[3]));
17103 +       DEFINE(PT_D4, offsetof(struct pt_regs, dn[4]));
17104 +       DEFINE(PT_D5, offsetof(struct pt_regs, dn[5]));
17105 +       DEFINE(PT_D6, offsetof(struct pt_regs, dn[6]));
17106 +       DEFINE(PT_D7, offsetof(struct pt_regs, dn[7]));
17107 +       DEFINE(PT_D8, offsetof(struct pt_regs, dn[8]));
17108 +       DEFINE(PT_D9, offsetof(struct pt_regs, dn[9]));
17109 +       DEFINE(PT_D10, offsetof(struct pt_regs, dn[10]));
17110 +       DEFINE(PT_D11, offsetof(struct pt_regs, dn[11]));
17111 +       DEFINE(PT_D12, offsetof(struct pt_regs, dn[12]));
17112 +       DEFINE(PT_D13, offsetof(struct pt_regs, dn[13]));
17113 +       DEFINE(PT_D14, offsetof(struct pt_regs, dn[14]));
17114 +       DEFINE(PT_D15, offsetof(struct pt_regs, dn[15]));
17115 +       DEFINE(PT_A0, offsetof(struct pt_regs, an[0]));
17116 +       DEFINE(PT_A1, offsetof(struct pt_regs, an[1]));
17117 +       DEFINE(PT_A2, offsetof(struct pt_regs, an[2]));
17118 +       DEFINE(PT_A3, offsetof(struct pt_regs, an[3]));
17119 +       DEFINE(PT_A4, offsetof(struct pt_regs, an[4]));
17120 +       DEFINE(PT_A5, offsetof(struct pt_regs, an[5]));
17121 +       DEFINE(PT_A6, offsetof(struct pt_regs, an[6]));
17122 +       DEFINE(PT_A7, offsetof(struct pt_regs, an[7]));
17123 +       DEFINE(PT_SP, offsetof(struct pt_regs, an[7]));
17124 +
17125 +       DEFINE(PT_ACC0HI, offsetof(struct pt_regs, acc0[0]));
17126 +       DEFINE(PT_ACC0LO, offsetof(struct pt_regs, acc0[1]));
17127 +       DEFINE(PT_MAC_RC16, offsetof(struct pt_regs, mac_rc16));
17128 +
17129 +       DEFINE(PT_ACC1HI, offsetof(struct pt_regs, acc1[0]));
17130 +       DEFINE(PT_ACC1LO, offsetof(struct pt_regs, acc1[1]));
17131 +
17132 +       DEFINE(PT_SOURCE3, offsetof(struct pt_regs, source3));
17133 +       DEFINE(PT_INST_CNT, offsetof(struct pt_regs, inst_cnt));
17134 +       DEFINE(PT_CSR, offsetof(struct pt_regs, csr));
17135 +       DEFINE(PT_DUMMY_UNUSED, offsetof(struct pt_regs, dummy_unused));
17136 +
17137 +       DEFINE(PT_INT_MASK0, offsetof(struct pt_regs, int_mask0));
17138 +       DEFINE(PT_INT_MASK1, offsetof(struct pt_regs, int_mask1));
17139 +
17140 +       DEFINE(PT_PC, offsetof(struct pt_regs, pc));
17141 +
17142 +       DEFINE(PT_TRAP_CAUSE, offsetof(struct pt_regs, trap_cause));
17143 +
17144 +       DEFINE(PT_SIZE, sizeof(struct pt_regs));
17145 +
17146 +       DEFINE(PT_FRAME_TYPE, offsetof(struct pt_regs, frame_type));
17147 +
17148 +       DEFINE(PT_ORIGINAL_D0, offsetof(struct pt_regs, original_dn_0));
17149 +       DEFINE(PT_PREVIOUS_PC, offsetof(struct pt_regs, previous_pc));
17150 +
17151 +       /* offsets into the kernel_stat struct */
17152 +//     DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
17153 +
17154 +       /* signal defines */
17155 +       DEFINE(SIGSEGV, SIGSEGV);
17156 +       //DEFINE(SEGV_MAPERR, SEGV_MAPERR);
17157 +       DEFINE(SIGTRAP, SIGTRAP);
17158 +       //DEFINE(TRAP_TRACE, TRAP_TRACE);
17159 +
17160 +       DEFINE(PT_PTRACED, PT_PTRACED);
17161 +       DEFINE(PT_DTRACE, PT_DTRACE);
17162 +
17163 +       DEFINE(ASM_THREAD_SIZE, THREAD_SIZE);
17164 +
17165 +       /* Offsets in thread_info structure */
17166 +       DEFINE(TI_TASK, offsetof(struct thread_info, task));
17167 +       DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
17168 +       DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
17169 +       DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
17170 +       DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
17171 +       DEFINE(TI_INTR_NESTING, offsetof(struct thread_info, interrupt_nesting));
17172 +       DEFINE(ASM_TIF_NEED_RESCHED, TIF_NEED_RESCHED);
17173 +       DEFINE(ASM_TIF_SYSCALL_TRACE, TIF_SYSCALL_TRACE);
17174 +       DEFINE(ASM_TIF_SIGPENDING, TIF_SIGPENDING);
17175 +
17176 +       return 0;
17177 +}
17178 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/devtree.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/devtree.c
17179 --- linux-2.6.30.10/arch/ubicom32/kernel/devtree.c      1970-01-01 02:00:00.000000000 +0200
17180 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/devtree.c  2009-12-11 11:45:11.000000000 +0200
17181 @@ -0,0 +1,173 @@
17182 +/*
17183 + * arch/ubicom32/kernel/devtree.c
17184 + *   Ubicom32 architecture device tree implementation.
17185 + *
17186 + * (C) Copyright 2009, Ubicom, Inc.
17187 + *
17188 + * This file is part of the Ubicom32 Linux Kernel Port.
17189 + *
17190 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17191 + * it and/or modify it under the terms of the GNU General Public License
17192 + * as published by the Free Software Foundation, either version 2 of the
17193 + * License, or (at your option) any later version.
17194 + *
17195 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17196 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17197 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17198 + * the GNU General Public License for more details.
17199 + *
17200 + * You should have received a copy of the GNU General Public License
17201 + * along with the Ubicom32 Linux Kernel Port.  If not,
17202 + * see <http://www.gnu.org/licenses/>.
17203 + *
17204 + * Ubicom32 implementation derived from (with many thanks):
17205 + *   arch/m68knommu
17206 + *   arch/blackfin
17207 + *   arch/parisc
17208 + */
17209 +
17210 +#include <linux/module.h>
17211 +#include <linux/kernel.h>
17212 +#include <linux/string.h>
17213 +#include <linux/errno.h>
17214 +#include <asm/devtree.h>
17215 +
17216 +/*
17217 + * The device tree.
17218 + */
17219 +struct devtree_node *devtree;
17220 +
17221 +/*
17222 + * devtree_print()
17223 + *     Print the device tree.
17224 + */
17225 +void devtree_print(void)
17226 +{
17227 +       struct devtree_node *p = devtree;
17228 +       printk(KERN_INFO "Device Tree:\n");
17229 +       while (p) {
17230 +               if (p->magic != DEVTREE_NODE_MAGIC) {
17231 +                       printk(KERN_EMERG
17232 +                              "device tree has improper node: %p\n", p);
17233 +                       return;
17234 +               }
17235 +               printk(KERN_INFO "\t%p: sendirq=%03d, recvirq=%03d, "
17236 +                      " name=%s\n", p, p->sendirq, p->recvirq, p->name);
17237 +               p = p->next;
17238 +       }
17239 +}
17240 +EXPORT_SYMBOL(devtree_print);
17241 +
17242 +/*
17243 + * devtree_irq()
17244 + *     Return the IRQ(s) associated with devtree node.
17245 + */
17246 +int devtree_irq(struct devtree_node *dn,
17247 +               unsigned char *sendirq,
17248 +               unsigned char *recvirq)
17249 +{
17250 +       if (dn->magic != DEVTREE_NODE_MAGIC) {
17251 +               printk(KERN_EMERG "improper node: %p\n", dn);
17252 +               if (sendirq) {
17253 +                       *sendirq = DEVTREE_IRQ_NONE;
17254 +               }
17255 +               if (recvirq) {
17256 +                       *recvirq = DEVTREE_IRQ_NONE;
17257 +               }
17258 +               return -EFAULT;
17259 +       }
17260 +
17261 +       /*
17262 +        * Copy the devtree irq(s) to the output parameters.
17263 +        */
17264 +       if (sendirq) {
17265 +               *sendirq = dn->sendirq;
17266 +       }
17267 +       if (recvirq) {
17268 +               *recvirq = dn->recvirq;
17269 +       }
17270 +       return 0;
17271 +}
17272 +EXPORT_SYMBOL(devtree_irq);
17273 +
17274 +/*
17275 + * devtree_find_next()
17276 + *     Provide an iterator for walking the device tree.
17277 + */
17278 +struct devtree_node *devtree_find_next(struct devtree_node **cur)
17279 +{
17280 +       struct devtree_node *p = *cur;
17281 +       if (!p) {
17282 +               *cur = devtree;
17283 +               return devtree;
17284 +       }
17285 +       p = p->next;
17286 +       *cur = p;
17287 +       return p;
17288 +}
17289 +
17290 +/*
17291 + * devtree_find_by_irq()
17292 + *     Return the node associated with a given irq.
17293 + */
17294 +struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq)
17295 +{
17296 +       struct devtree_node *p = devtree;
17297 +
17298 +       if (sendirq == recvirq) {
17299 +               printk(KERN_EMERG "identical request makes no sense sendirq = "
17300 +                      "%d, recvirq= %d\n", sendirq, recvirq);
17301 +               return NULL;
17302 +       }
17303 +
17304 +       while (p) {
17305 +               if (p->magic != DEVTREE_NODE_MAGIC) {
17306 +                       printk(KERN_EMERG
17307 +                              "device tree has improper node: %p\n", p);
17308 +                       return NULL;
17309 +               }
17310 +
17311 +               /*
17312 +                * See if we can find a match on the IRQ(s) specified.
17313 +                */
17314 +               if ((sendirq == p->sendirq) && (recvirq == p->recvirq)) {
17315 +                       return p;
17316 +               }
17317 +
17318 +               if ((sendirq == DEVTREE_IRQ_DONTCARE) &&
17319 +                   (p->recvirq == recvirq)) {
17320 +                       return p;
17321 +               }
17322 +
17323 +               if ((recvirq == DEVTREE_IRQ_DONTCARE) &&
17324 +                   (p->sendirq == sendirq)) {
17325 +                       return p;
17326 +               }
17327 +
17328 +               p = p->next;
17329 +       }
17330 +       return NULL;
17331 +}
17332 +EXPORT_SYMBOL(devtree_find_by_irq);
17333 +
17334 +/*
17335 + * devtree_find_node()
17336 + *     Find a node in the device tree by name.
17337 + */
17338 +struct devtree_node *devtree_find_node(const char *str)
17339 +{
17340 +       struct devtree_node *p = devtree;
17341 +       while (p) {
17342 +               if (p->magic != DEVTREE_NODE_MAGIC) {
17343 +                       printk(KERN_EMERG
17344 +                              "device tree has improper node: %p\n", p);
17345 +                       return NULL;
17346 +               }
17347 +               if (strcmp(p->name, str) == 0) {
17348 +                       return p;
17349 +               }
17350 +               p = p->next;
17351 +       }
17352 +       return NULL;
17353 +}
17354 +EXPORT_SYMBOL(devtree_find_node);
17355 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/dma.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/dma.c
17356 --- linux-2.6.30.10/arch/ubicom32/kernel/dma.c  1970-01-01 02:00:00.000000000 +0200
17357 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/dma.c      2009-12-11 11:45:11.000000000 +0200
17358 @@ -0,0 +1,60 @@
17359 +/*
17360 + * arch/ubicom32/kernel/dma.c
17361 + *   Ubicom32 architecture dynamic DMA mapping support.
17362 + *
17363 + * (C) Copyright 2009, Ubicom, Inc.
17364 + *
17365 + * This file is part of the Ubicom32 Linux Kernel Port.
17366 + *
17367 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17368 + * it and/or modify it under the terms of the GNU General Public License
17369 + * as published by the Free Software Foundation, either version 2 of the
17370 + * License, or (at your option) any later version.
17371 + *
17372 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17373 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17374 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17375 + * the GNU General Public License for more details.
17376 + *
17377 + * You should have received a copy of the GNU General Public License
17378 + * along with the Ubicom32 Linux Kernel Port.  If not,
17379 + * see <http://www.gnu.org/licenses/>.
17380 + *
17381 + * Ubicom32 implementation derived from (with many thanks):
17382 + *   arch/m68knommu
17383 + *   arch/blackfin
17384 + *   arch/parisc
17385 + *
17386 + * We never have any address translations to worry about, so this
17387 + * is just alloc/free.
17388 + */
17389 +
17390 +#include <linux/types.h>
17391 +#include <linux/mm.h>
17392 +#include <linux/string.h>
17393 +#include <linux/device.h>
17394 +#include <linux/io.h>
17395 +
17396 +void *dma_alloc_coherent(struct device *dev, size_t size,
17397 +                          dma_addr_t *dma_handle, int gfp)
17398 +{
17399 +       void *ret;
17400 +       /* ignore region specifiers */
17401 +       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
17402 +
17403 +       if (dev == NULL || (*dev->dma_mask < 0xffffffff))
17404 +               gfp |= GFP_DMA;
17405 +       ret = (void *)__get_free_pages(gfp, get_order(size));
17406 +
17407 +       if (ret != NULL) {
17408 +               memset(ret, 0, size);
17409 +               *dma_handle = virt_to_phys(ret);
17410 +       }
17411 +       return ret;
17412 +}
17413 +
17414 +void dma_free_coherent(struct device *dev, size_t size,
17415 +                        void *vaddr, dma_addr_t dma_handle)
17416 +{
17417 +       free_pages((unsigned long)vaddr, get_order(size));
17418 +}
17419 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/flat.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/flat.c
17420 --- linux-2.6.30.10/arch/ubicom32/kernel/flat.c 1970-01-01 02:00:00.000000000 +0200
17421 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/flat.c     2009-12-11 11:45:11.000000000 +0200
17422 @@ -0,0 +1,206 @@
17423 +/*
17424 + * arch/ubicom32/kernel/flat.c
17425 + *   Ubicom32 architecture flat executable format support.
17426 + *
17427 + * (C) Copyright 2009, Ubicom, Inc.
17428 + *
17429 + * This file is part of the Ubicom32 Linux Kernel Port.
17430 + *
17431 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17432 + * it and/or modify it under the terms of the GNU General Public License
17433 + * as published by the Free Software Foundation, either version 2 of the
17434 + * License, or (at your option) any later version.
17435 + *
17436 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17437 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17438 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17439 + * the GNU General Public License for more details.
17440 + *
17441 + * You should have received a copy of the GNU General Public License
17442 + * along with the Ubicom32 Linux Kernel Port.  If not,
17443 + * see <http://www.gnu.org/licenses/>.
17444 + *
17445 + * Ubicom32 implementation derived from (with many thanks):
17446 + *   arch/m68knommu
17447 + *   arch/blackfin
17448 + *   arch/parisc
17449 + */
17450 +#include <linux/module.h>
17451 +#include <linux/types.h>
17452 +#include <linux/flat.h>
17453 +
17454 +unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp,
17455 +                                            u32_t relval,
17456 +                                            u32_t flags,
17457 +                                            unsigned long *persistent)
17458 +{
17459 +       u32_t relval_reloc_type = relval >> 27;
17460 +       u32_t insn = *rp;
17461 +
17462 +       if (*persistent) {
17463 +               /*
17464 +                * relval holds the relocation that has to be adjusted.
17465 +                */
17466 +               if (relval == 0) {
17467 +                       *persistent = 0;
17468 +               }
17469 +
17470 +               return relval;
17471 +       }
17472 +
17473 +       if (relval_reloc_type == R_UBICOM32_32) {
17474 +               /*
17475 +                * insn holds the relocation
17476 +                */
17477 +               return insn;
17478 +       }
17479 +
17480 +       /*
17481 +        * We don't know this one.
17482 +        */
17483 +       return 0;
17484 +}
17485 +
17486 +void ubicom32_flat_put_addr_at_rp(unsigned long *rp,
17487 +                                 u32_t val,
17488 +                                 u32_t relval,
17489 +                                 unsigned long *persistent)
17490 +{
17491 +       u32_t reloc_type = (relval >> 27) & 0x1f;
17492 +       u32_t insn = *rp;
17493 +
17494 +       /*
17495 +        * If persistent is set then it contains the relocation type.
17496 +        */
17497 +       if (*persistent) {
17498 +               /*
17499 +                * If persistent is set then it contains the relocation type.
17500 +                */
17501 +               reloc_type = (*persistent >> 27) & 0x1f;
17502 +       }
17503 +
17504 +       switch (reloc_type) {
17505 +       case R_UBICOM32_32:
17506 +               /*
17507 +                * Store the 32 bits as is.
17508 +                */
17509 +               *rp = val;
17510 +               break;
17511 +       case R_UBICOM32_HI24:
17512 +               {
17513 +                       /*
17514 +                        * 24 bit relocation that is part of the MOVEAI
17515 +                        * instruction. The 24 bits come from bits 7 - 30 of the
17516 +                        * relocation. The 24 bits eventually get split into 2
17517 +                        * fields in the instruction encoding.
17518 +                        *
17519 +                        * - Bits 7 - 27 of the relocation are encoded into bits
17520 +                        * 0 - 20 of the instruction.
17521 +                        *
17522 +                        * - Bits 28 - 30 of the relocation are encoded into bit
17523 +                        * 24 - 26 of the instruction.
17524 +                        */
17525 +                       u32_t mask = 0x1fffff | (0x7 << 24);
17526 +                       u32_t valid24bits = (val >> 7) & 0xffffff;
17527 +                       u32_t bot_21 = valid24bits & 0x1fffff;
17528 +                       u32_t upper_3_bits = ((valid24bits & 0xe00000) << 3);
17529 +                       insn &= ~mask;
17530 +
17531 +                       insn |= bot_21;
17532 +                       insn |= upper_3_bits;
17533 +                       *rp = insn;
17534 +               }
17535 +               break;
17536 +       case R_UBICOM32_LO7_S:
17537 +       case R_UBICOM32_LO7_2_S:
17538 +       case R_UBICOM32_LO7_4_S:
17539 +               {
17540 +                       /*
17541 +                        * Bits 0 - 6 of the relocation are encoded into the
17542 +                        * 7bit unsigned immediate fields of the SOURCE-1 field
17543 +                        * of the instruction.  The immediate value is left
17544 +                        * shifted by (0, 1, 2) based on the operand size.
17545 +                        */
17546 +                       u32_t mask = 0x1f | (0x3 << 8);
17547 +                       u32_t bottom, top;
17548 +                       val &= 0x7f;
17549 +                       if (reloc_type == R_UBICOM32_LO7_2_S) {
17550 +                               val >>= 1;
17551 +                       } else if (reloc_type == R_UBICOM32_LO7_4_S) {
17552 +                               val >>= 2;
17553 +                       }
17554 +
17555 +                       bottom  = val & 0x1f;
17556 +                       top = val >> 5;
17557 +                       insn &= ~mask;
17558 +                       insn |= bottom;
17559 +                       insn |= (top << 8);
17560 +                       BUG_ON(*rp != insn);
17561 +                       *rp = insn;
17562 +                       break;
17563 +               }
17564 +       case R_UBICOM32_LO7_D:
17565 +       case R_UBICOM32_LO7_2_D:
17566 +       case R_UBICOM32_LO7_4_D:
17567 +               {
17568 +                       /*
17569 +                        * Bits 0 - 6 of the relocation are encoded into the
17570 +                        * 7bit unsigned immediate fields of the DESTINATION
17571 +                        * field of the instruction.  The immediate value is
17572 +                        * left shifted by (0, 1, 2) based on the operand size.
17573 +                        */
17574 +                       u32_t mask = (0x1f | (0x3 << 8)) << 16;
17575 +                       u32_t bottom, top;
17576 +                       val &= 0x7f;
17577 +                       if (reloc_type == R_UBICOM32_LO7_2_D) {
17578 +                               val >>= 1;
17579 +                       } else if (reloc_type == R_UBICOM32_LO7_4_D) {
17580 +                               val >>= 2;
17581 +                       }
17582 +                       bottom  = (val & 0x1f) << 16;
17583 +                       top = (val >> 5) << 16;
17584 +                       insn &= ~mask;
17585 +                       insn |= bottom;
17586 +                       insn |= (top << 8);
17587 +                       BUG_ON(*rp != insn);
17588 +                       *rp = insn;
17589 +                       break;
17590 +               }
17591 +       case R_UBICOM32_LO7_CALLI:
17592 +       case R_UBICOM32_LO16_CALLI:
17593 +               {
17594 +                       /*
17595 +                        * Extract the offset for a CALLI instruction. The
17596 +                        * offsets can be either 7 bits or 18 bits. Since all
17597 +                        * instructions in ubicom32 architecture are at work
17598 +                        * aligned addresses the truncated offset is right
17599 +                        * shifted by 2 before being encoded in the instruction.
17600 +                        */
17601 +                       if (reloc_type == R_UBICOM32_LO7_CALLI) {
17602 +                               val &= 0x7f;
17603 +                       } else {
17604 +                               val &= 0x3ffff;
17605 +                       }
17606 +
17607 +                       val >>= 2;
17608 +
17609 +                       insn &= ~0x071f071f;
17610 +                       insn |= (val & 0x1f) << 0;
17611 +                       val >>= 5;
17612 +                       insn |= (val & 0x07) << 8;
17613 +                       val >>= 3;
17614 +                       insn |= (val & 0x1f) << 16;
17615 +                       val >>= 5;
17616 +                       insn |= (val & 0x07) << 24;
17617 +                       if (reloc_type == R_UBICOM32_LO7_CALLI) {
17618 +                               BUG_ON(*rp != insn);
17619 +                       }
17620 +                       *rp = insn;
17621 +               }
17622 +               break;
17623 +       }
17624 +
17625 +       if (*persistent) {
17626 +               *persistent = 0;
17627 +       }
17628 +}
17629 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/head.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/head.S
17630 --- linux-2.6.30.10/arch/ubicom32/kernel/head.S 1970-01-01 02:00:00.000000000 +0200
17631 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/head.S     2009-12-11 11:45:11.000000000 +0200
17632 @@ -0,0 +1,273 @@
17633 +/*
17634 + * arch/ubicom32/kernel/head.S
17635 + *     <TODO: Replace with short file description>
17636 + *
17637 + * (C) Copyright 2009, Ubicom, Inc.
17638 + *
17639 + * This file is part of the Ubicom32 Linux Kernel Port.
17640 + *
17641 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17642 + * it and/or modify it under the terms of the GNU General Public License
17643 + * as published by the Free Software Foundation, either version 2 of the
17644 + * License, or (at your option) any later version.
17645 + *
17646 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17647 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17648 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17649 + * the GNU General Public License for more details.
17650 + *
17651 + * You should have received a copy of the GNU General Public License
17652 + * along with the Ubicom32 Linux Kernel Port.  If not,
17653 + * see <http://www.gnu.org/licenses/>.
17654 + *
17655 + * Ubicom32 implementation derived from (with many thanks):
17656 + *   arch/m68knommu
17657 + *   arch/blackfin
17658 + *   arch/parisc
17659 + */
17660 +#include <linux/sys.h>
17661 +#include <linux/linkage.h>
17662 +#include <asm/asm-offsets.h>
17663 +#include <asm/page_offset.h>
17664 +#define __ASM__
17665 +#include <asm/ip5000.h>
17666 +
17667 +
17668 +#define SRC_AN A3
17669 +#define DST_AN A4
17670 +
17671 +#define PARAM_DN D0
17672 +#define TMP_DN D15
17673 +#define TMP2_DN D14
17674 +
17675 +/*
17676 + * The following code is placed at the start of the Linux section of memory.
17677 + * This is the primary entry point for Linux.
17678 + *
17679 + * However, we also want the syscall entry/exit code to be at a fixed address.
17680 + * So we take the primary entry point and reserve 16 bytes.  That address is
17681 + * where the system_call entry point exists.  This 16 bytes basically allows
17682 + * us to jump around the system_call entry point code to the actual startup
17683 + * code.
17684 + *
17685 + * Linux Memory Map (see vlinux.lds.S):
17686 + * 0x40400000 - Primary Entry Point for Linux (jump around code below).
17687 + * 0x40400010 - Old syscall Entry Point.
17688 + */
17689 +
17690 +       .sect   .skip_syscall, "ax", @progbits
17691 +       .global __skip_syscall_section
17692 +__skip_syscall_section:
17693 +       moveai          A3, #%hi(_start)
17694 +       lea.1           A3, %lo(_start)(A3)
17695 +       ret             A3
17696 +/*
17697 + * __os_node_offset contains the offset from KERNELBASE to the os_node, it is
17698 + * not intended to be used by anything except the boot code.
17699 + */
17700 +__os_node_offset:
17701 +.long  (_os_node - KERNELSTART)
17702 +
17703 +.text
17704 +.global        _start
17705 +
17706 +/*
17707 + * start()
17708 + *     This is the start of the Linux kernel.
17709 + */
17710 +_start:
17711 +       move.4          SCRATCHPAD1, #0
17712 +
17713 +
17714 +/*
17715 + * Setup the range registers... the loader has setup a few, but we will go ahead
17716 + * and correct them for our own limits. Note that once set these are never
17717 + * changed again.  The ranges are as follows
17718 + *
17719 + *  D_RANGE0 - io block (set up by loaded)
17720 + *
17721 + *  I_RANGE0 and D_RANGE1 - kernel/ultra loader address space bottom of ocm-> top
17722 + *     of ram typically 0x3ffc0000 - 0x440000000
17723 + *  I_RANGE1 - kernel / userspace transition area (aka syscalls, context switches)
17724 + *     typically 0x3FFC0030 - ~0x3FFC0200
17725 + *  I_RANGE2 / D_RANGE2 - slab area
17726 + *     typically 0x40A00000 - ~0x44000000
17727 + *  I_RANGE3
17728 + *     old system call interface if enabled.
17729 + *
17730 + *   D_RANGE3, D_RANGE4 - unused.
17731 + */
17732 +       moveai          SRC_AN, #%hi(PAGE_OFFSET_RAW)
17733 +       lea.4           SRC_AN, %lo(PAGE_OFFSET_RAW)(SRC_AN)
17734 +       move.4          D_RANGE1_LO, SRC_AN
17735 +       move.4          I_RANGE0_LO, SRC_AN
17736 +
17737 +; don't try to calculate I_RANGE_HI, see below
17738 +;      moveai          SRC_AN, #%hi(___init_end-4)
17739 +;      lea.4           SRC_AN, %lo(___init_end-4)(SRC_AN)
17740 +;      move.4          I_RANGE0_HI, SRC_AN
17741 +
17742 +       moveai          SRC_AN, #%hi(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)
17743 +       lea.4           SRC_AN, %lo(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)(SRC_AN)
17744 +       move.4          D_RANGE1_HI, SRC_AN
17745 +
17746 +; for now allow the whole ram to be executable as well so we don't run into problems
17747 +; once we load user more code.
17748 +       move.4          I_RANGE0_HI, SRC_AN
17749 +
17750 +#ifdef CONFIG_PROTECT_KERNEL
17751 +; when kernel protection is enabled, we only open up syscall and non kernel text
17752 +; for userspace apps, for now only irange registers registers 1 and 2 are used for userspace.
17753 +
17754 +       ;; syscall range
17755 +       moveai          SRC_AN, #%hi(__syscall_text_run_begin)
17756 +       lea.4           SRC_AN, %lo(__syscall_text_run_begin)(SRC_AN)
17757 +       move.4          I_RANGE1_LO, SRC_AN
17758 +       moveai          SRC_AN, #%hi(__syscall_text_run_end)
17759 +       lea.4           SRC_AN, %lo(__syscall_text_run_end)(SRC_AN)
17760 +       move.4          I_RANGE1_HI, SRC_AN
17761 +
17762 +       ;; slab instructions
17763 +       moveai          SRC_AN, #%hi(_edata)
17764 +       lea.4           SRC_AN, %lo(_edata)(SRC_AN)
17765 +       move.4          I_RANGE2_LO, SRC_AN
17766 +       ;; End of DDR is already in range0 hi so just copy it.
17767 +       move.4          I_RANGE2_HI, I_RANGE0_HI
17768 +
17769 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17770 +       ;; create a small hole for old syscall location
17771 +       moveai          SRC_AN, #%hi(0x40400000)
17772 +       lea.4           I_RANGE3_LO, 0x10(SRC_AN)
17773 +       lea.4           I_RANGE3_HI, 0x14(SRC_AN)
17774 +#endif
17775 +       ;; slab data (same as slab instructions but starting a little earlier).
17776 +       moveai          SRC_AN, #%hi(_data_protection_end)
17777 +       lea.4           SRC_AN, %lo(_data_protection_end)(SRC_AN)
17778 +       move.4          D_RANGE2_LO, SRC_AN
17779 +       move.4          D_RANGE2_HI, I_RANGE0_HI
17780 +
17781 +;; enable ranges
17782 +       ;; skip I_RANGE0_EN
17783 +       move.4          I_RANGE1_EN, #-1
17784 +       move.4          I_RANGE2_EN, #-1
17785 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17786 +       move.4          I_RANGE3_EN, #-1
17787 +#else
17788 +       move.4          I_RANGE3_EN, #0
17789 +#endif
17790 +       ;; skip D_RANGE0_EN or D_RANGE1_EN
17791 +       move.4          D_RANGE2_EN, #-1
17792 +       move.4          D_RANGE3_EN, #0
17793 +       move.4          D_RANGE4_EN, #0
17794 +#endif
17795 +
17796 +;
17797 +; If __ocm_free_begin is smaller than __ocm_free_end the
17798 +; setup OCM text and data ram banks properly
17799 +;
17800 +       moveai          DST_AN, #%hi(__ocm_free_begin)
17801 +       lea.4           TMP_DN, %lo(__ocm_free_begin)(DST_AN)
17802 +       moveai          DST_AN, #%hi(__ocm_free_end)
17803 +       lea.4           TMP2_DN, %lo(__ocm_free_end)(DST_AN)
17804 +       sub.4           #0, TMP2_DN, TMP_DN
17805 +       jmple.f         2f
17806 +       moveai          DST_AN, #%hi(__data_begin)
17807 +       lea.4           TMP_DN, %lo(__data_begin)(DST_AN)
17808 +       moveai          DST_AN, #%hi(OCMSTART)
17809 +       lea.4           TMP2_DN, %lo(OCMSTART)(DST_AN)
17810 +       sub.4           TMP_DN, TMP_DN, TMP2_DN
17811 +       lsr.4           TMP_DN, TMP_DN, #15
17812 +       lsl.4           TMP_DN, #1, TMP_DN
17813 +       moveai          DST_AN, #%hi(OCMC_BASE)
17814 +       add.4           OCMC_BANK_MASK(DST_AN), #-1, TMP_DN
17815 +       pipe_flush      0
17816 +2:
17817 +;
17818 +; Load .ocm_text
17819 +;
17820 +       moveai          DST_AN, #%hi(__ocm_text_run_end)
17821 +       lea.4           TMP_DN, %lo(__ocm_text_run_end)(DST_AN)
17822 +       moveai          DST_AN, #%hi(__ocm_text_run_begin)
17823 +       lea.4           DST_AN, %lo(__ocm_text_run_begin)(DST_AN)
17824 +       moveai          SRC_AN, #%hi(__ocm_text_load_begin)
17825 +       lea.4           SRC_AN, %lo(__ocm_text_load_begin)(SRC_AN)
17826 +       jmpt.t          2f
17827 +
17828 +1:      move.4          (DST_AN)4++, (SRC_AN)4++
17829 +
17830 +2:      sub.4           #0, DST_AN, TMP_DN
17831 +       jmpne.t         1b
17832 +;
17833 +; Load .syscall_text
17834 +;
17835 +       moveai          DST_AN, #%hi(__syscall_text_run_end)
17836 +       lea.4           TMP_DN, %lo(__syscall_text_run_end)(DST_AN)
17837 +       moveai          DST_AN, #%hi(__syscall_text_run_begin)
17838 +       lea.4           DST_AN, %lo(__syscall_text_run_begin)(DST_AN)
17839 +       moveai          SRC_AN, #%hi(__syscall_text_load_begin)
17840 +       lea.4           SRC_AN, %lo(__syscall_text_load_begin)(SRC_AN)
17841 +       jmpt.t          2f
17842 +
17843 +1:     move.4          (DST_AN)4++, (SRC_AN)4++
17844 +
17845 +2:     sub.4           #0, DST_AN, TMP_DN
17846 +       jmpne.t         1b
17847 +
17848 +;
17849 +; Load .ocm_data
17850 +;
17851 +       moveai          DST_AN, #%hi(__ocm_data_run_end)
17852 +       lea.4           TMP_DN, %lo(__ocm_data_run_end)(DST_AN)
17853 +       moveai          DST_AN, #%hi(__ocm_data_run_begin)
17854 +       lea.4           DST_AN, %lo(__ocm_data_run_begin)(DST_AN)
17855 +       moveai          SRC_AN, #%hi(__ocm_data_load_begin)
17856 +       lea.4           SRC_AN, %lo(__ocm_data_load_begin)(SRC_AN)
17857 +       jmpt.t          2f
17858 +
17859 +1:      move.4          (DST_AN)4++, (SRC_AN)4++
17860 +
17861 +2:      sub.4           #0, DST_AN, TMP_DN
17862 +       jmpne.t         1b
17863 +
17864 +; Clear .bss
17865 +;
17866 +       moveai          SRC_AN, #%hi(_ebss)
17867 +       lea.4           TMP_DN, %lo(_ebss)(SRC_AN)
17868 +       moveai          DST_AN, #%hi(_sbss)
17869 +       lea.4           DST_AN, %lo(_sbss)(DST_AN)
17870 +       jmpt.t          2f
17871 +
17872 +1:     move.4          (DST_AN)4++, #0
17873 +
17874 +2:     sub.4           #0, DST_AN, TMP_DN
17875 +       jmpne.t         1b
17876 +
17877 +; save our parameter to devtree (after clearing .bss)
17878 +       moveai          DST_AN, #%hi(devtree)
17879 +       lea.4           DST_AN, %lo(devtree)(DST_AN)
17880 +       move.4          (DST_AN), PARAM_DN
17881 +
17882 +       moveai          sp, #%hi(init_thread_union)
17883 +       lea.4           sp, %lo(init_thread_union)(sp)
17884 +       movei           TMP_DN, #ASM_THREAD_SIZE
17885 +       add.4           sp, sp, TMP_DN
17886 +       move.4          -4(sp)++, #0 ; nesting level = 0
17887 +       move.4          -4(sp)++, #1 ; KERNEL_THREAD
17888 +
17889 +;; ip3k-elf-gdb backend now sets scratchpad3 to 1 when either continue
17890 +;; or single step commands are issued. scratchpad3 is set to 0 when the
17891 +;; debugger detaches from the board.
17892 +       move.4          TMP_DN, scratchpad3
17893 +       lsl.4           TMP_DN, TMP_DN, #0x0
17894 +       jmpeq.f         _jump_to_start_kernel
17895 +_ok_to_set_break_points_in_linux:
17896 +;; THREAD_STALL
17897 +       move.4          mt_dbg_active_clr,#-1
17898 +;; stalling the threads isn't instantaneous.. need to flush the pipe.
17899 +       pipe_flush      0
17900 +       pipe_flush      0
17901 +
17902 +_jump_to_start_kernel:
17903 +       moveai          SRC_AN, #%hi(start_kernel)
17904 +       lea.4           SRC_AN, %lo(start_kernel)(SRC_AN)
17905 +       ret             SRC_AN
17906 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/init_task.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/init_task.c
17907 --- linux-2.6.30.10/arch/ubicom32/kernel/init_task.c    1970-01-01 02:00:00.000000000 +0200
17908 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/init_task.c        2009-12-11 11:45:11.000000000 +0200
17909 @@ -0,0 +1,62 @@
17910 +/*
17911 + * arch/ubicom32/kernel/init_task.c
17912 + *   Ubicom32 architecture task initialization implementation.
17913 + *
17914 + * (C) Copyright 2009, Ubicom, Inc.
17915 + *
17916 + * This file is part of the Ubicom32 Linux Kernel Port.
17917 + *
17918 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17919 + * it and/or modify it under the terms of the GNU General Public License
17920 + * as published by the Free Software Foundation, either version 2 of the
17921 + * License, or (at your option) any later version.
17922 + *
17923 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17924 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17925 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17926 + * the GNU General Public License for more details.
17927 + *
17928 + * You should have received a copy of the GNU General Public License
17929 + * along with the Ubicom32 Linux Kernel Port.  If not,
17930 + * see <http://www.gnu.org/licenses/>.
17931 + *
17932 + * Ubicom32 implementation derived from (with many thanks):
17933 + *   arch/m68knommu
17934 + *   arch/blackfin
17935 + *   arch/parisc
17936 + */
17937 +#include <linux/mm.h>
17938 +#include <linux/module.h>
17939 +#include <linux/sched.h>
17940 +#include <linux/init.h>
17941 +#include <linux/init_task.h>
17942 +#include <linux/fs.h>
17943 +#include <linux/mqueue.h>
17944 +#include <linux/uaccess.h>
17945 +#include <asm/pgtable.h>
17946 +
17947 +///static struct fs_struct init_fs = INIT_FS;
17948 +static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
17949 +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17950 +struct mm_struct init_mm = INIT_MM(init_mm);
17951 +EXPORT_SYMBOL(init_mm);
17952 +
17953 +/*
17954 + * Initial task structure.
17955 + *
17956 + * All other task structs will be allocated on slabs in fork.c
17957 + */
17958 +struct task_struct init_task = INIT_TASK(init_task);
17959 +
17960 +EXPORT_SYMBOL(init_task);
17961 +
17962 +/*
17963 + * Initial thread structure.
17964 + *
17965 + * We need to make sure that this is 8192-byte aligned due to the
17966 + * way process stacks are handled. This is done by having a special
17967 + * "init_task" linker map entry..
17968 + */
17969 +union thread_union init_thread_union
17970 +       __attribute__((__section__(".data.init_task"))) =
17971 +               { INIT_THREAD_INFO(init_task) };
17972 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/irq.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/irq.c
17973 --- linux-2.6.30.10/arch/ubicom32/kernel/irq.c  1970-01-01 02:00:00.000000000 +0200
17974 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/irq.c      2009-12-11 11:45:11.000000000 +0200
17975 @@ -0,0 +1,597 @@
17976 +/*
17977 + * arch/ubicom32/kernel/irq.c
17978 + *   Ubicom32 architecture IRQ support.
17979 + *
17980 + * (C) Copyright 2009, Ubicom, Inc.
17981 + * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
17982 + *
17983 + * This file is part of the Ubicom32 Linux Kernel Port.
17984 + *
17985 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17986 + * it and/or modify it under the terms of the GNU General Public License
17987 + * as published by the Free Software Foundation, either version 2 of the
17988 + * License, or (at your option) any later version.
17989 + *
17990 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17991 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17992 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17993 + * the GNU General Public License for more details.
17994 + *
17995 + * You should have received a copy of the GNU General Public License
17996 + * along with the Ubicom32 Linux Kernel Port.  If not,
17997 + * see <http://www.gnu.org/licenses/>.
17998 + *
17999 + * Ubicom32 implementation derived from (with many thanks):
18000 + *   arch/m68knommu
18001 + *   arch/blackfin
18002 + *   arch/parisc
18003 + */
18004 +
18005 +#include <linux/types.h>
18006 +#include <linux/irq.h>
18007 +#include <linux/init.h>
18008 +#include <linux/kernel.h>
18009 +#include <linux/kernel_stat.h>
18010 +#include <linux/module.h>
18011 +#include <linux/seq_file.h>
18012 +#include <linux/proc_fs.h>
18013 +#include <asm/system.h>
18014 +#include <asm/traps.h>
18015 +#include <asm/ldsr.h>
18016 +#include <asm/ip5000.h>
18017 +#include <asm/machdep.h>
18018 +#include <asm/asm-offsets.h>
18019 +#include <asm/thread.h>
18020 +#include <asm/devtree.h>
18021 +
18022 +unsigned int irq_soft_avail;
18023 +static struct irqaction ubicom32_reserve_action[NR_IRQS];
18024 +
18025 +#if !defined(CONFIG_DEBUG_IRQMEASURE)
18026 +#define IRQ_DECLARE_MEASUREMENT
18027 +#define IRQ_MEASUREMENT_START()
18028 +#define IRQ_MEASUREMENT_END(irq)
18029 +#else
18030 +#define IRQ_DECLARE_MEASUREMENT \
18031 +       int __diff;             \
18032 +       unsigned int __tstart;
18033 +
18034 +#define IRQ_MEASUREMENT_START() \
18035 +       __tstart = UBICOM32_IO_TIMER->sysval;
18036 +
18037 +#define IRQ_MEASUREMENT_END(irq) \
18038 +       __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
18039 +       irq_measurement_update((irq), __diff);
18040 +
18041 +/*
18042 + * We keep track of the time spent in both irq_enter()
18043 + * and irq_exit().
18044 + */
18045 +#define IRQ_WEIGHT 32
18046 +
18047 +struct irq_measurement {
18048 +       volatile unsigned int min;
18049 +       volatile unsigned int avg;
18050 +       volatile unsigned int max;
18051 +};
18052 +
18053 +static DEFINE_SPINLOCK(irq_measurement_lock);
18054 +
18055 +/*
18056 + *  Add 1 in for softirq (irq_exit());
18057 + */
18058 +static struct irq_measurement irq_measurements[NR_IRQS + 1];
18059 +
18060 +/*
18061 + * irq_measurement_update()
18062 + *     Update an entry in the measurement array for this irq.
18063 + */
18064 +static void irq_measurement_update(int irq, int sample)
18065 +{
18066 +       struct irq_measurement *im = &irq_measurements[irq];
18067 +       spin_lock(&irq_measurement_lock);
18068 +       if ((im->min == 0) || (im->min > sample)) {
18069 +               im->min = sample;
18070 +       }
18071 +       if (im->max < sample) {
18072 +               im->max = sample;
18073 +       }
18074 +       im->avg = ((im->avg * (IRQ_WEIGHT - 1)) + sample) / IRQ_WEIGHT;
18075 +       spin_unlock(&irq_measurement_lock);
18076 +}
18077 +#endif
18078 +
18079 +/*
18080 + * irq_kernel_stack_check()
18081 + *     See if the kernel stack is within STACK_WARN of the end.
18082 + */
18083 +static void irq_kernel_stack_check(int irq, struct pt_regs *regs)
18084 +{
18085 +#ifdef CONFIG_DEBUG_STACKOVERFLOW
18086 +       unsigned long sp;
18087 +
18088 +       /*
18089 +        * Make sure that we are not close to the top of the stack and thus
18090 +        * can not really service this interrupt.
18091 +        */
18092 +       asm volatile (
18093 +               "and.4          %0, SP, %1 \n\t"
18094 +               : "=d" (sp)
18095 +               : "d" (THREAD_SIZE - 1)
18096 +               : "cc"
18097 +       );
18098 +
18099 +       if (sp < (sizeof(struct thread_info) + STACK_WARN)) {
18100 +               printk(KERN_WARNING
18101 +                       "cpu[%d]: possible overflow detected sp remain: %p, "
18102 +                      "irq: %d, regs: %p\n",
18103 +                       thread_get_self(), (void *)sp, irq, regs);
18104 +               dump_stack();
18105 +       }
18106 +
18107 +       if (sp < (sizeof(struct thread_info) + 16)) {
18108 +               THREAD_STALL;
18109 +       }
18110 +#endif
18111 +}
18112 +
18113 +/*
18114 + * irq_get_lsb()
18115 + *     Get the LSB set in value
18116 + */
18117 +static int irq_get_lsb(unsigned int value)
18118 +{
18119 +       static unsigned char irq_bits[8] = {
18120 +               3, 0, 1, 0, 2, 0, 1, 0
18121 +       };
18122 +       u32_t nextbit = 0;
18123 +
18124 +       value = (value >> nextbit) | (value << ((sizeof(value) * 8) - nextbit));
18125 +
18126 +       /*
18127 +        * It's unlikely that we find that we execute the body of this while
18128 +        * loop.  50% of the time we won't take this at all and then of the
18129 +        * cases where we do about 50% of those we only execute once.
18130 +        */
18131 +       if (!(value & 0xffff)) {
18132 +               nextbit += 0x10;
18133 +               value >>= 16;
18134 +       }
18135 +
18136 +       if (!(value & 0xff)) {
18137 +               nextbit += 0x08;
18138 +               value >>= 8;
18139 +       }
18140 +
18141 +       if (!(value & 0xf)) {
18142 +               nextbit += 0x04;
18143 +               value >>= 4;
18144 +       }
18145 +
18146 +       nextbit += irq_bits[value & 0x7];
18147 +       if (nextbit > 63) {
18148 +               panic("nextbit out of range: %d\n", nextbit);
18149 +       }
18150 +       return nextbit;
18151 +}
18152 +
18153 +/*
18154 + * ubicom32_reserve_handler()
18155 + *     Bogus handler associated with pre-reserved IRQ(s).
18156 + */
18157 +static irqreturn_t ubicom32_reserve_handler(int irq, void *dev_id)
18158 +{
18159 +       BUG();
18160 +       return IRQ_HANDLED;
18161 +}
18162 +
18163 +/*
18164 + * __irq_disable_vector()
18165 + *     Disable the interrupt by clearing the appropriate bit in the
18166 + *     LDSR Mask Register.
18167 + */
18168 +static void __irq_disable_vector(unsigned int irq)
18169 +{
18170 +       ldsr_disable_vector(irq);
18171 +}
18172 +
18173 +/*
18174 + * __irq_ack_vector()
18175 + *     Acknowledge the specific interrupt by clearing the associate bit in
18176 + *     hardware
18177 + */
18178 +static void __irq_ack_vector(unsigned int irq)
18179 +{
18180 +       if (irq < 32) {
18181 +               asm volatile ("move.4 INT_CLR0, %0" : : "d" (1 << irq));
18182 +       } else {
18183 +               asm volatile ("move.4 INT_CLR1, %0" : : "d" (1 << (irq - 32)));
18184 +       }
18185 +}
18186 +
18187 +/*
18188 + * __irq_enable_vector()
18189 + *     Clean and then enable the interrupt by setting the appropriate bit in
18190 + *     the LDSR Mask Register.
18191 + */
18192 +static void __irq_enable_vector(unsigned int irq)
18193 +{
18194 +       /*
18195 +        * Acknowledge, really clear the vector.
18196 +        */
18197 +       __irq_ack_vector(irq);
18198 +       ldsr_enable_vector(irq);
18199 +}
18200 +
18201 +/*
18202 + * __irq_mask_vector()
18203 + */
18204 +static void __irq_mask_vector(unsigned int irq)
18205 +{
18206 +       ldsr_mask_vector(irq);
18207 +}
18208 +
18209 +/*
18210 + * __irq_unmask_vector()
18211 + */
18212 +static void __irq_unmask_vector(unsigned int irq)
18213 +{
18214 +       ldsr_unmask_vector(irq);
18215 +}
18216 +
18217 +/*
18218 + * __irq_end_vector()
18219 + *     Called once an interrupt is completed (reset the LDSR mask).
18220 + */
18221 +static void __irq_end_vector(unsigned int irq)
18222 +{
18223 +       ldsr_unmask_vector(irq);
18224 +}
18225 +
18226 +#if defined(CONFIG_SMP)
18227 +/*
18228 + * __irq_set_affinity()
18229 + *     Set the cpu affinity for this interrupt.
18230 + *     affinity container allocated at boot
18231 + */
18232 +static void __irq_set_affinity(unsigned int irq, const struct cpumask *dest)
18233 +{
18234 +       smp_set_affinity(irq, dest);
18235 +       cpumask_copy(irq_desc[irq].affinity, dest);
18236 +}
18237 +#endif
18238 +
18239 +/*
18240 + * On-Chip Generic Interrupt function handling.
18241 + */
18242 +static struct irq_chip ubicom32_irq_chip = {
18243 +       .name           = "Ubicom32",
18244 +       .startup        = NULL,
18245 +       .shutdown       = NULL,
18246 +       .enable         = __irq_enable_vector,
18247 +       .disable        = __irq_disable_vector,
18248 +       .ack            = __irq_ack_vector,
18249 +       .mask           = __irq_mask_vector,
18250 +       .unmask         = __irq_unmask_vector,
18251 +       .end            = __irq_end_vector,
18252 +#if defined(CONFIG_SMP)
18253 +       .set_affinity   = __irq_set_affinity,
18254 +#endif
18255 +};
18256 +
18257 +/*
18258 + * do_IRQ()
18259 + *     Primary interface for handling IRQ() requests.
18260 + */
18261 +asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
18262 +{
18263 +       struct pt_regs *oldregs;
18264 +       struct thread_info *ti = current_thread_info();
18265 +
18266 +       IRQ_DECLARE_MEASUREMENT;
18267 +
18268 +       /*
18269 +        * Mark that we are inside of an interrupt and
18270 +        * that interrupts are disabled.
18271 +        */
18272 +       oldregs = set_irq_regs(regs);
18273 +       ti->interrupt_nesting++;
18274 +       trace_hardirqs_off();
18275 +       irq_kernel_stack_check(irq, regs);
18276 +
18277 +       /*
18278 +        * Start the interrupt sequence
18279 +        */
18280 +       irq_enter();
18281 +
18282 +       /*
18283 +        * Execute the IRQ handler and any pending SoftIRQ requests.
18284 +        */
18285 +       BUG_ON(!irqs_disabled());
18286 +       IRQ_MEASUREMENT_START();
18287 +       __do_IRQ(irq);
18288 +       IRQ_MEASUREMENT_END(irq);
18289 +       BUG_ON(!irqs_disabled());
18290 +
18291 +       /*
18292 +        * TODO: Since IRQ's are disabled when calling irq_exit()
18293 +        * modify Kconfig to set __ARCH_IRQ_EXIT_IRQS_DISABLED flag.
18294 +        * This will slightly improve performance by enabling
18295 +        * softirq handling to avoid disabling/disabled interrupts.
18296 +        */
18297 +       IRQ_MEASUREMENT_START();
18298 +       irq_exit();
18299 +       IRQ_MEASUREMENT_END(NR_IRQS);
18300 +       BUG_ON(!irqs_disabled());
18301 +
18302 +       /*
18303 +        * Outside of an interrupt (or nested exit).
18304 +        */
18305 +       set_irq_regs(oldregs);
18306 +       trace_hardirqs_on();
18307 +       ti->interrupt_nesting--;
18308 +}
18309 +
18310 +/*
18311 + * irq_soft_alloc()
18312 + *     Allocate a soft IRQ.
18313 + */
18314 +int irq_soft_alloc(unsigned int *soft)
18315 +{
18316 +       if (irq_soft_avail == 0) {
18317 +               printk(KERN_NOTICE "no soft irqs to allocate\n");
18318 +               return -EFAULT;
18319 +       }
18320 +
18321 +       *soft = irq_get_lsb(irq_soft_avail);
18322 +       irq_soft_avail &= ~(1 << *soft);
18323 +       return 0;
18324 +}
18325 +
18326 +/*
18327 + * ack_bad_irq()
18328 + *     Called to handle an bad irq request.
18329 + */
18330 +void ack_bad_irq(unsigned int irq)
18331 +{
18332 +       printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
18333 +       __irq_end_vector(irq);
18334 +}
18335 +
18336 +/*
18337 + * show_interrupts()
18338 + *     Return a string that displays the state of each of the interrupts.
18339 + */
18340 +int show_interrupts(struct seq_file *p, void *v)
18341 +{
18342 +       struct irqaction *ap;
18343 +       int irq = *((loff_t *) v);
18344 +       int j;
18345 +
18346 +       if (irq >= NR_IRQS) {
18347 +               return 0;
18348 +       }
18349 +
18350 +       if (irq == 0) {
18351 +               seq_puts(p, "           ");
18352 +               for_each_online_cpu(j) {
18353 +                       seq_printf(p, "CPU%d       ", j);
18354 +               }
18355 +               seq_putc(p, '\n');
18356 +       }
18357 +
18358 +       ap = irq_desc[irq].action;
18359 +       if (ap) {
18360 +               seq_printf(p, "%3d: ", irq);
18361 +               for_each_online_cpu(j) {
18362 +                       seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
18363 +               }
18364 +               seq_printf(p, "%14s  ", irq_desc[irq].chip->name);
18365 +               seq_printf(p, "%s", ap->name);
18366 +               for (ap = ap->next; ap; ap = ap->next) {
18367 +                       seq_printf(p, ", %s", ap->name);
18368 +               }
18369 +               seq_putc(p, '\n');
18370 +       }
18371 +       return 0;
18372 +}
18373 +
18374 +#if defined(CONFIG_DEBUG_IRQMEASURE)
18375 +static unsigned int irq_cycles_to_micro(unsigned int cycles, unsigned int frequency)
18376 +{
18377 +       unsigned int micro = (cycles / (frequency / 1000000));
18378 +       return micro;
18379 +}
18380 +
18381 +/*
18382 + * irq_measurement_show()
18383 + *     Print out the min, avg, max values for each IRQ
18384 + *
18385 + * By request, the max value is reset after each dump.
18386 + */
18387 +static int irq_measurement_show(struct seq_file *p, void *v)
18388 +{
18389 +       struct irqaction *ap;
18390 +       unsigned int freq = processor_frequency();
18391 +       int irq = *((loff_t *) v);
18392 +
18393 +
18394 +       if (irq == 0) {
18395 +               seq_puts(p, "\tmin\tavg\tmax\t(micro-seconds)\n");
18396 +       }
18397 +
18398 +       if (irq > NR_IRQS) {
18399 +               return 0;
18400 +       }
18401 +
18402 +       if (irq == NR_IRQS) {
18403 +               unsigned int min, avg, max;
18404 +               spin_lock(&irq_measurement_lock);
18405 +               min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18406 +               avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18407 +               max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18408 +               irq_measurements[irq].max = 0;
18409 +               spin_unlock(&irq_measurement_lock);
18410 +               seq_printf(p, "   \t%u\t%u\t%u\tsoftirq\n", min, avg, max);
18411 +               return 0;
18412 +       }
18413 +
18414 +       ap = irq_desc[irq].action;
18415 +       if (ap) {
18416 +               unsigned int min, avg, max;
18417 +               spin_lock(&irq_measurement_lock);
18418 +               min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18419 +               avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18420 +               max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18421 +               irq_measurements[irq].max = 0;
18422 +               spin_unlock(&irq_measurement_lock);
18423 +               seq_printf(p, "%2u:\t%u\t%u\t%u\t%s\n", irq, min, avg, max, ap->name);
18424 +       }
18425 +       return 0;
18426 +}
18427 +
18428 +static void *irq_measurement_start(struct seq_file *f, loff_t *pos)
18429 +{
18430 +       return (*pos <= NR_IRQS) ? pos : NULL;
18431 +}
18432 +
18433 +static void *irq_measurement_next(struct seq_file *f, void *v, loff_t *pos)
18434 +{
18435 +       (*pos)++;
18436 +       if (*pos > NR_IRQS)
18437 +               return NULL;
18438 +       return pos;
18439 +}
18440 +
18441 +static void irq_measurement_stop(struct seq_file *f, void *v)
18442 +{
18443 +       /* Nothing to do */
18444 +}
18445 +
18446 +static const struct seq_operations irq_measurement_seq_ops = {
18447 +       .start = irq_measurement_start,
18448 +       .next  = irq_measurement_next,
18449 +       .stop  = irq_measurement_stop,
18450 +       .show  = irq_measurement_show,
18451 +};
18452 +
18453 +static int irq_measurement_open(struct inode *inode, struct file *filp)
18454 +{
18455 +       return seq_open(filp, &irq_measurement_seq_ops);
18456 +}
18457 +
18458 +static const struct file_operations irq_measurement_fops = {
18459 +       .open           = irq_measurement_open,
18460 +       .read           = seq_read,
18461 +       .llseek         = seq_lseek,
18462 +       .release        = seq_release,
18463 +};
18464 +
18465 +static int __init irq_measurement_init(void)
18466 +{
18467 +       proc_create("irq_measurements", 0, NULL, &irq_measurement_fops);
18468 +       return 0;
18469 +}
18470 +module_init(irq_measurement_init);
18471 +#endif
18472 +
18473 +/*
18474 + * init_IRQ(void)
18475 + *     Initialize the on-chip IRQ subsystem.
18476 + */
18477 +void __init init_IRQ(void)
18478 +{
18479 +       int irq;
18480 +       struct devtree_node *p = NULL;
18481 +       struct devtree_node *iter = NULL;
18482 +       unsigned int mask = 0;
18483 +       unsigned int reserved = 0;
18484 +
18485 +       /*
18486 +        * Pull out the list of software interrupts that are avialable to
18487 +        * Linux and provide an allocation function for them.  The first
18488 +        * 24 interrupts of INT0 are software interrupts.
18489 +        */
18490 +       irq_soft_avail = 0;
18491 +       if (processor_interrupts(&irq_soft_avail, NULL) < 0) {
18492 +               printk(KERN_WARNING "No Soft IRQ(s) available\n");
18493 +       }
18494 +       irq_soft_avail &= ((1 << 24) - 1);
18495 +
18496 +       /*
18497 +        * Initialize all of the on-chip interrupt handling
18498 +        * to use a common set of interrupt functions.
18499 +        */
18500 +       for (irq = 0; irq < NR_IRQS; irq++) {
18501 +               irq_desc[irq].status = IRQ_DISABLED;
18502 +               irq_desc[irq].action = NULL;
18503 +               irq_desc[irq].depth = 1;
18504 +               set_irq_chip(irq, &ubicom32_irq_chip);
18505 +       }
18506 +
18507 +       /*
18508 +        * The sendirq of a devnode is not registered within Linux but instead
18509 +        * is used by the software I/O thread.  These interrupts are reserved.
18510 +        * The recvirq is used by Linux and registered by a device driver, these
18511 +        * are not reserved.
18512 +        *
18513 +        * recvirq(s) that are in the software interrupt range are not supposed
18514 +        * to be marked as reserved.  We track this while we scan the device
18515 +        * nodes.
18516 +        */
18517 +       p = devtree_find_next(&iter);
18518 +       while (p) {
18519 +               unsigned char sendirq, recvirq;
18520 +               devtree_irq(p, &sendirq, &recvirq);
18521 +
18522 +               /*
18523 +                * If the sendirq is valid, mark that irq as taken by the
18524 +                * devtree node.
18525 +                */
18526 +               if (sendirq < NR_IRQS) {
18527 +                       ubicom32_reserve_action[sendirq].handler =
18528 +                               ubicom32_reserve_handler;
18529 +                       ubicom32_reserve_action[sendirq].name = p->name;
18530 +                       irq_desc[sendirq].action =
18531 +                               &ubicom32_reserve_action[sendirq];
18532 +                       mask |= (1 << sendirq);
18533 +               }
18534 +
18535 +               /*
18536 +                * Track the relevant recieve IRQ(s)
18537 +                */
18538 +               if (recvirq < 24) {
18539 +                       mask |= (1 << recvirq);
18540 +               }
18541 +
18542 +               /*
18543 +                * Move to the next node.
18544 +                */
18545 +               p = devtree_find_next(&iter);
18546 +       }
18547 +
18548 +       /*
18549 +        * Remove these bits from the irq_soft_avail list and then use the
18550 +        * result as the list of pre-reserved IRQ(s).
18551 +        */
18552 +       reserved = ~irq_soft_avail & ~mask;
18553 +       for (irq = 0; irq < 24; irq++) {
18554 +               if ((reserved & (1 << irq))) {
18555 +                       ubicom32_reserve_action[irq].handler =
18556 +                               ubicom32_reserve_handler;
18557 +                       ubicom32_reserve_action[irq].name = "reserved";
18558 +                       irq_desc[irq].action = &ubicom32_reserve_action[irq];
18559 +               }
18560 +       }
18561 +
18562 +       /*
18563 +        * Initialize the LDSR which is the Ubicom32 programmable
18564 +        * interrupt controller.
18565 +        */
18566 +       ldsr_init();
18567 +
18568 +       /*
18569 +        * The Ubicom trap code needs a 2nd init after IRQ(s) are setup.
18570 +        */
18571 +       trap_init_interrupt();
18572 +}
18573 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ldsr.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/ldsr.c
18574 --- linux-2.6.30.10/arch/ubicom32/kernel/ldsr.c 1970-01-01 02:00:00.000000000 +0200
18575 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ldsr.c     2009-12-11 11:45:11.000000000 +0200
18576 @@ -0,0 +1,1185 @@
18577 +/*
18578 + * arch/ubicom32/kernel/ldsr.c
18579 + *   Ubicom32 architecture Linux Device Services Driver Interface
18580 + *
18581 + * (C) Copyright 2009, Ubicom, Inc.
18582 + *
18583 + * This file is part of the Ubicom32 Linux Kernel Port.
18584 + *
18585 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
18586 + * it and/or modify it under the terms of the GNU General Public License
18587 + * as published by the Free Software Foundation, either version 2 of the
18588 + * License, or (at your option) any later version.
18589 + *
18590 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18591 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18592 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
18593 + * the GNU General Public License for more details.
18594 + *
18595 + * You should have received a copy of the GNU General Public License
18596 + * along with the Ubicom32 Linux Kernel Port.  If not,
18597 + * see <http://www.gnu.org/licenses/>.
18598 + *
18599 + * Ubicom32 implementation derived from (with many thanks):
18600 + *   arch/m68knommu
18601 + *   arch/blackfin
18602 + *   arch/parisc
18603 + *
18604 + * NOTES:
18605 + *
18606 + * The LDSR is a programmable interrupt controller that is written in software.
18607 + * It emulates the behavior of an pic by fielding the interrupts, choosing a
18608 + * victim thread to take the interrupt and forcing that thread to take a context
18609 + * switch to the appropriate interrupt handler.
18610 + *
18611 + * Because traps are treated as just a special class of interrupts, the LDSR
18612 + * also handles the processing of traps.
18613 + *
18614 + * Because we compile Linux both UP and SMP, we need the LDSR to use
18615 + * architectural locking that is not "compiled out" when compiling UP.  For now,
18616 + * we use the single atomic bit lock.
18617 + */
18618 +#include <linux/kernel.h>
18619 +#include <linux/init.h>
18620 +#include <linux/sched.h>
18621 +#include <linux/interrupt.h>
18622 +#include <linux/irq.h>
18623 +#include <linux/profile.h>
18624 +#include <linux/clocksource.h>
18625 +#include <linux/types.h>
18626 +#include <linux/module.h>
18627 +#include <linux/cpumask.h>
18628 +#include <linux/bug.h>
18629 +#include <linux/delay.h>
18630 +#include <asm/ip5000.h>
18631 +#include <asm/atomic.h>
18632 +#include <asm/machdep.h>
18633 +#include <asm/asm-offsets.h>
18634 +#include <asm/traps.h>
18635 +#include <asm/thread.h>
18636 +#include <asm/range-protect.h>
18637 +
18638 +/*
18639 + * One can not print from the LDSR so the best we can do is
18640 + * check a condition and stall all of the threads.
18641 + */
18642 +
18643 +// #define DEBUG_LDSR 1
18644 +#if defined(DEBUG_LDSR)
18645 +#define DEBUG_ASSERT(cond) \
18646 +       if (!(cond)) { \
18647 +               THREAD_STALL; \
18648 +       }
18649 +#else
18650 +#define DEBUG_ASSERT(cond)
18651 +#endif
18652 +
18653 +/*
18654 + * Make global so that we can use it in the RFI code in assembly.
18655 + */
18656 +unsigned int ldsr_soft_irq_mask;
18657 +EXPORT_SYMBOL(ldsr_soft_irq_mask);
18658 +
18659 +static unsigned int ldsr_suspend_mask;
18660 +static unsigned int ldsr_soft_irq;
18661 +static unsigned int ldsr_stack_space[1024];
18662 +
18663 +static struct ldsr_register_bank {
18664 +       volatile unsigned int enabled0;
18665 +       volatile unsigned int enabled1;
18666 +       volatile unsigned int mask0;
18667 +       volatile unsigned int mask1;
18668 +       unsigned int total;
18669 +       unsigned int retry;
18670 +       unsigned int backout;
18671 +} ldsr_interrupt;
18672 +
18673 +/*
18674 + * Which thread/cpu are we?
18675 + */
18676 +static int ldsr_tid = -1;
18677 +
18678 +#if defined(CONFIG_IRQSTACKS)
18679 +/*
18680 + * per-CPU IRQ stacks (thread information and stack)
18681 + *
18682 + * NOTE: Do not use DEFINE_PER_CPU() as it makes it harder
18683 + * to find the location of ctx from assembly language.
18684 + */
18685 +union irq_ctx {
18686 +       struct thread_info      tinfo;
18687 +       u32                     stack[THREAD_SIZE/sizeof(u32)];
18688 +};
18689 +static union irq_ctx *percpu_irq_ctxs[NR_CPUS];
18690 +
18691 +/*
18692 + *  Storage for the interrupt stack.
18693 + */
18694 +#if !defined(CONFIG_IRQSTACKS_USEOCM)
18695 +static char percpu_irq_stacks[(NR_CPUS * THREAD_SIZE) + (THREAD_SIZE - 1)];
18696 +#else
18697 +/*
18698 + *  For OCM, the linker will ensure that space is allocated for the stack
18699 + *  see (vmlinux.lds.S)
18700 + */
18701 +static char percpu_irq_stacks[];
18702 +#endif
18703 +
18704 +#endif
18705 +
18706 +/*
18707 + * Save trap IRQ because we need to un-suspend if it gets set.
18708 + */
18709 +static unsigned int ldsr_trap_irq_mask;
18710 +static unsigned int ldsr_trap_irq;
18711 +
18712 +/*
18713 + * ret_from_interrupt_to_kernel
18714 + *     Just restore the context and do nothing else.
18715 + */
18716 +asmlinkage void ret_from_interrupt_to_kernel(void)__attribute__((naked));
18717 +
18718 +/*
18719 + * ret_from_interrupt_to_user
18720 + *     Call scheduler if needed. Just restore the context.
18721 + */
18722 +asmlinkage void ret_from_interrupt_to_user(void)__attribute__((naked));
18723 +
18724 +#ifdef DEBUG_LDSR
18725 +u32_t old_sp, old_pc, old_a0, old_a5, old_a3;
18726 +struct pt_regs copy_regs, *copy_save_area;
18727 +#endif
18728 +
18729 +int __user_mode(unsigned long sp)
18730 +{
18731 +
18732 +       u32_t saved_stack_base = sp & ~(ASM_THREAD_SIZE - 1);
18733 +#if defined(CONFIG_IRQSTACKS_USEOCM)
18734 +       if ((union irq_ctx *)saved_stack_base == percpu_irq_ctxs[smp_processor_id()]) {
18735 +               /*
18736 +                *  On the interrupt stack.
18737 +                */
18738 +               return 0;
18739 +       }
18740 +#endif
18741 +
18742 +       if (!(u32_t)current) {
18743 +               return 0;
18744 +       }
18745 +       return saved_stack_base != ((u32_t)current->stack);
18746 +}
18747 +
18748 +/*
18749 + * ldsr_lock_release()
18750 + *     Release the LDSR lock.
18751 + */
18752 +static void ldsr_lock_release(void)
18753 +{
18754 +       UBICOM32_UNLOCK(LDSR_LOCK_BIT);
18755 +}
18756 +
18757 +/*
18758 + * ldsr_lock_acquire()
18759 + *     Acquire the LDSR lock, spin if not available.
18760 + */
18761 +static void ldsr_lock_acquire(void)
18762 +{
18763 +       UBICOM32_LOCK(LDSR_LOCK_BIT);
18764 +}
18765 +
18766 +/*
18767 + * ldsr_thread_irq_disable()
18768 + *     Disable interrupts for the specified thread.
18769 + */
18770 +static void ldsr_thread_irq_disable(unsigned int tid)
18771 +{
18772 +       unsigned int mask = (1 << tid);
18773 +
18774 +       asm volatile (
18775 +       "       or.4    scratchpad1, scratchpad1, %0    \n\t"
18776 +               :
18777 +               : "d"(mask)
18778 +               : "cc"
18779 +       );
18780 +}
18781 +
18782 +/*
18783 + * ldsr_thread_get_interrupts()
18784 + *     Get the interrupt state for all threads.
18785 + */
18786 +static unsigned long ldsr_thread_get_interrupts(void)
18787 +{
18788 +       unsigned long ret = 0;
18789 +       asm volatile (
18790 +       "       move.4  %0, scratchpad1 \n\t"
18791 +               : "=r" (ret)
18792 +               :
18793 +       );
18794 +       return ret;
18795 +}
18796 +
18797 +/*
18798 + * ldsr_emulate_and_run()
18799 + *     Emulate the instruction and then set the thread to run.
18800 + */
18801 +static void ldsr_emulate_and_run(unsigned int tid)
18802 +{
18803 +       unsigned int thread_mask = (1 << tid);
18804 +       u32_t write_csr = (tid << 15) | (1 << 14);
18805 +
18806 +       /*
18807 +        * Emulate the unaligned access.
18808 +        */
18809 +       unaligned_emulate(tid);
18810 +
18811 +       /*
18812 +        * Get the thread back in a running state.
18813 +        */
18814 +       asm volatile (
18815 +       "       setcsr  %0                      \n\t"
18816 +       "       setcsr_flush 0                  \n\t"
18817 +       "       move.4  trap_cause, #0          \n\t" /* Clear the trap cause
18818 +                                                      * register */
18819 +       "       setcsr  #0                      \n\t"
18820 +       "       setcsr_flush 0                  \n\t"
18821 +       "       move.4  mt_dbg_active_set, %1   \n\t" /* Activate thread even if
18822 +                                                      * in dbg/fault state */
18823 +       "       move.4  mt_active_set, %1       \n\t" /* Restart target
18824 +                                                      * thread. */
18825 +               :
18826 +               : "r" (write_csr), "d" (thread_mask)
18827 +               : "cc"
18828 +       );
18829 +       thread_enable_mask(thread_mask);
18830 +}
18831 +
18832 +/*
18833 + * ldsr_preemptive_context_save()
18834 + *     save thread context from another hardware thread.  The other thread must
18835 + *     be stalled.
18836 + */
18837 +static inline void ldsr_preemptive_context_save(u32_t thread,
18838 +                                               struct pt_regs *regs)
18839 +{
18840 +       /*
18841 +        * Save the current state of the specified thread
18842 +        */
18843 +       asm volatile (
18844 +       "       move.4  a3, %0                                  \n\t"
18845 +
18846 +               /* set src1 from the target thread */
18847 +       "       move.4  csr, %1                                 \n\t"
18848 +       "       setcsr_flush 0                                  \n\t"
18849 +       "       setcsr_flush 0                                  \n\t"
18850 +
18851 +               /* copy state from the other thread */
18852 +       "       move.4  "D(PT_D0)"(a3), d0                      \n\t"
18853 +       "       move.4  "D(PT_D1)"(a3), d1                      \n\t"
18854 +       "       move.4  "D(PT_D2)"(a3), d2                      \n\t"
18855 +       "       move.4  "D(PT_D3)"(a3), d3                      \n\t"
18856 +       "       move.4  "D(PT_D4)"(a3), d4                      \n\t"
18857 +       "       move.4  "D(PT_D5)"(a3), d5                      \n\t"
18858 +       "       move.4  "D(PT_D6)"(a3), d6                      \n\t"
18859 +       "       move.4  "D(PT_D7)"(a3), d7                      \n\t"
18860 +       "       move.4  "D(PT_D8)"(a3), d8                      \n\t"
18861 +       "       move.4  "D(PT_D9)"(a3), d9                      \n\t"
18862 +       "       move.4  "D(PT_D10)"(a3), d10                    \n\t"
18863 +       "       move.4  "D(PT_D11)"(a3), d11                    \n\t"
18864 +       "       move.4  "D(PT_D12)"(a3), d12                    \n\t"
18865 +       "       move.4  "D(PT_D13)"(a3), d13                    \n\t"
18866 +       "       move.4  "D(PT_D14)"(a3), d14                    \n\t"
18867 +       "       move.4  "D(PT_D15)"(a3), d15                    \n\t"
18868 +       "       move.4  "D(PT_A0)"(a3), a0                      \n\t"
18869 +       "       move.4  "D(PT_A1)"(a3), a1                      \n\t"
18870 +       "       move.4  "D(PT_A2)"(a3), a2                      \n\t"
18871 +       "       move.4  "D(PT_A3)"(a3), a3                      \n\t"
18872 +       "       move.4  "D(PT_A4)"(a3), a4                      \n\t"
18873 +       "       move.4  "D(PT_A5)"(a3), a5                      \n\t"
18874 +       "       move.4  "D(PT_A6)"(a3), a6                      \n\t"
18875 +       "       move.4  "D(PT_SP)"(a3), a7                      \n\t"
18876 +       "       move.4  "D(PT_ACC0HI)"(a3), acc0_hi             \n\t"
18877 +       "       move.4  "D(PT_ACC0LO)"(a3), acc0_lo             \n\t"
18878 +       "       move.4  "D(PT_MAC_RC16)"(a3), mac_rc16          \n\t"
18879 +       "       move.4  "D(PT_ACC1HI)"(a3), acc1_hi             \n\t"
18880 +       "       move.4  "D(PT_ACC1LO)"(a3), acc1_lo             \n\t"
18881 +       "       move.4  "D(PT_SOURCE3)"(a3), source3            \n\t"
18882 +       "       move.4  "D(PT_INST_CNT)"(a3), inst_cnt          \n\t"
18883 +       "       move.4  "D(PT_CSR)"(a3), csr                    \n\t"
18884 +       "       move.4  "D(PT_DUMMY_UNUSED)"(a3), #0            \n\t"
18885 +       "       move.4  "D(PT_INT_MASK0)"(a3), int_mask0        \n\t"
18886 +       "       move.4  "D(PT_INT_MASK1)"(a3), int_mask1        \n\t"
18887 +       "       move.4  "D(PT_TRAP_CAUSE)"(a3), trap_cause      \n\t"
18888 +       "       move.4  "D(PT_PC)"(a3), pc                      \n\t"
18889 +       "       move.4  "D(PT_PREVIOUS_PC)"(a3), previous_pc    \n\t"
18890 +               /* disable csr thread select */
18891 +       "       movei   csr, #0                                 \n\t"
18892 +       "       setcsr_flush 0                                  \n\t"
18893 +       :
18894 +       : "r" (regs->dn), "d" ((thread << 9) | (1 << 8))
18895 +       : "a3"
18896 +       );
18897 +}
18898 +
18899 +/*
18900 + * ldsr_rotate_threads()
18901 + *     Simple round robin algorithm for choosing the next cpu
18902 + */
18903 +static int ldsr_rotate_threads(unsigned long cpus)
18904 +{
18905 +       static unsigned char ldsr_bits[8] = {
18906 +               3, 0, 1, 0, 2, 0, 1, 0
18907 +       };
18908 +
18909 +       static int nextbit;
18910 +       int thisbit;
18911 +
18912 +       /*
18913 +        * Move the interrupts down so that we consider interrupts from where
18914 +        * we left off, then take the interrupts we would lose and move them
18915 +        * to the top half of the interrupts value.
18916 +        */
18917 +       cpus = (cpus >> nextbit) | (cpus << ((sizeof(cpus) * 8) - nextbit));
18918 +
18919 +       /*
18920 +        * 50% of the time we won't take this at all and then of the cases where
18921 +        * we do about 50% of those we only execute once.
18922 +        */
18923 +       if (!(cpus & 0xffff)) {
18924 +               nextbit += 16;
18925 +               cpus >>= 16;
18926 +       }
18927 +
18928 +       if (!(cpus & 0xff)) {
18929 +               nextbit += 8;
18930 +               cpus >>= 8;
18931 +       }
18932 +
18933 +       if (!(cpus & 0xf)) {
18934 +               nextbit += 4;
18935 +               cpus >>= 4;
18936 +       }
18937 +
18938 +       nextbit += ldsr_bits[cpus & 0x7];
18939 +       thisbit = (nextbit & ((sizeof(cpus) * 8) - 1));
18940 +       nextbit = (thisbit + 1) & ((sizeof(cpus) * 8) - 1);
18941 +       DEBUG_ASSERT(thisbit < THREAD_ARCHITECTURAL_MAX);
18942 +       return thisbit;
18943 +}
18944 +
18945 +/*
18946 + * ldsr_rotate_interrupts()
18947 + *     Get rotating next set bit value.
18948 + */
18949 +static int ldsr_rotate_interrupts(unsigned long long interrupts)
18950 +{
18951 +       static unsigned char ldsr_bits[8] = {
18952 +               3, 0, 1, 0, 2, 0, 1, 0
18953 +       };
18954 +
18955 +       static int nextbit;
18956 +       int thisbit;
18957 +
18958 +       /*
18959 +        * Move the interrupts down so that we consider interrupts from where
18960 +        * we left off, then take the interrupts we would lose and move them
18961 +        * to the top half of the interrupts value.
18962 +        */
18963 +       interrupts = (interrupts >> nextbit) |
18964 +               (interrupts << ((sizeof(interrupts) * 8) - nextbit));
18965 +
18966 +       /*
18967 +        * 50% of the time we won't take this at all and then of the cases where
18968 +        * we do about 50% of those we only execute once.
18969 +        */
18970 +       if (!(interrupts & 0xffffffff)) {
18971 +               nextbit += 32;
18972 +               interrupts >>= 32;
18973 +       }
18974 +
18975 +       if (!(interrupts & 0xffff)) {
18976 +               nextbit += 16;
18977 +               interrupts >>= 16;
18978 +       }
18979 +
18980 +       if (!(interrupts & 0xff)) {
18981 +               nextbit += 8;
18982 +               interrupts >>= 8;
18983 +       }
18984 +
18985 +       if (!(interrupts & 0xf)) {
18986 +               nextbit += 4;
18987 +               interrupts >>= 4;
18988 +       }
18989 +
18990 +       nextbit += ldsr_bits[interrupts & 0x7];
18991 +       thisbit = (nextbit & ((sizeof(interrupts) * 8) - 1));
18992 +       nextbit = (thisbit + 1) & ((sizeof(interrupts) * 8) - 1);
18993 +
18994 +       DEBUG_ASSERT(thisbit < (sizeof(interrupts) * 8));
18995 +       return thisbit;
18996 +}
18997 +
18998 +/*
18999 + * ldsr_backout_or_irq()
19000 + *
19001 + * One way or the other this interrupt is not being
19002 + * processed, make sure that it is reset.  We are
19003 + * not going to call irq_end_vector() so unmask the
19004 + * interrupt.
19005 + */
19006 +static void ldsr_backout_of_irq(int vector, unsigned long tid_mask)
19007 +{
19008 +#if defined(CONFIG_SMP)
19009 +       if (unlikely(vector == smp_ipi_irq)) {
19010 +               smp_reset_ipi(tid_mask);
19011 +       }
19012 +#endif
19013 +       ldsr_unmask_vector(vector);
19014 +       ldsr_interrupt.backout++;
19015 +}
19016 +
19017 +#if defined(CONFIG_IRQSTACKS)
19018 +/*
19019 + * ldsr_choose_savearea_and_returnvec()
19020 + *     Test our current state (user, kernel, interrupt) and set things up.
19021 + *
19022 + * This version of the function uses 3 stacks and nests interrupts
19023 + * on the interrupt stack.
19024 + */
19025 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
19026 +{
19027 +       struct pt_regs *save_area;
19028 +       u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
19029 +       struct thread_info * ti= (struct thread_info *)sw_ksp[tid];
19030 +
19031 +#if defined(CONFIG_SMP)
19032 +       union irq_ctx *icp = percpu_irq_ctxs[tid];
19033 +#else
19034 +       union irq_ctx *icp = percpu_irq_ctxs[0];
19035 +#endif
19036 +
19037 +       if (masked_linux_sp == (u32_t)icp) {
19038 +               /*
19039 +                * Fault/Interrupt occurred while on the interrupt stack.
19040 +                */
19041 +               save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
19042 +               *pvec = (u32_t)(&ret_from_interrupt_to_kernel);
19043 +       } else {
19044 +               /*
19045 +                *  Fault/Interrupt occurred while on user/kernel stack.  This is a new
19046 +                *  first use of the interrupt stack.
19047 +                */
19048 +               save_area = (struct pt_regs *) ((char *)icp + sizeof(icp->stack) - sizeof(struct pt_regs) - 8);
19049 +               if (masked_linux_sp == (u32_t)ti) {
19050 +                       *pvec  = (u32_t)(&ret_from_interrupt_to_kernel);
19051 +               } else {
19052 +                       *pvec  = (u32_t)(&ret_from_interrupt_to_user);
19053 +               }
19054 +
19055 +               /*
19056 +                * Because the softirq code will execute on the "interrupt" stack, we
19057 +                * need to maintain the knowledge of what "task" was executing on the
19058 +                * cpu.  This is done by copying the thread_info->task from the cpu
19059 +                * we are about to context switch into the interrupt contexts thread_info
19060 +                * structure.
19061 +                */
19062 +               icp->tinfo.task = ti->task;
19063 +               icp->tinfo.preempt_count =
19064 +                               (icp->tinfo.preempt_count & ~SOFTIRQ_MASK) |
19065 +                               (ti->preempt_count & SOFTIRQ_MASK);
19066 +               icp->tinfo.interrupt_nesting = 0;
19067 +       }
19068 +       save_area->nesting_level = icp->tinfo.interrupt_nesting;
19069 +       return save_area;
19070 +}
19071 +
19072 +#else
19073 +/*
19074 + * ldsr_choose_savearea_and_returnvec()
19075 + *     Test our current state (user, kernel, interrupt) and set things up.
19076 + *
19077 + * The version of the function uses just the user & kernel stack and
19078 + * nests interrupts on the existing kernel stack.
19079 + */
19080 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
19081 +{
19082 +       struct pt_regs *save_area;
19083 +       u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
19084 +       struct thread_info *ti = (struct thread_info *)sw_ksp[tid];
19085 +
19086 +       if (masked_linux_sp == (u32_t)ti) {
19087 +               /*
19088 +                * Fault/Interrupt occurred while on the kernel stack.
19089 +                */
19090 +               save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
19091 +               *pvec = (u32_t) (&ret_from_interrupt_to_kernel);
19092 +       } else {
19093 +               /*
19094 +                *  Fault/Interrupt occurred while on user stack.
19095 +                */
19096 +               ti->interrupt_nesting = 0;
19097 +               save_area = (struct pt_regs *)((u32_t)ti + THREAD_SIZE - sizeof(struct pt_regs) - 8);
19098 +               *pvec  = (u32_t) (&ret_from_interrupt_to_user);
19099 +       }
19100 +       save_area->nesting_level = ti->interrupt_nesting;
19101 +       return save_area;
19102 +}
19103 +#endif
19104 +
19105 +/*
19106 + * ldsr_ctxsw_thread()
19107 + *     Context switch a mainline thread to execute do_IRQ() for the specified
19108 + *     vector.
19109 + */
19110 +static void ldsr_ctxsw_thread(int vector, thread_t tid)
19111 +{
19112 +       u32_t linux_sp;
19113 +       u32_t return_vector;
19114 +       struct pt_regs *save_area, *regs;
19115 +       u32_t thread_mask = (1 << tid);
19116 +       u32_t read_csr = ((tid << 9) | (1 << 8));
19117 +       u32_t write_csr = (tid << 15) | (1 << 14);
19118 +       u32_t interrupt_vector = (u32_t)(&do_IRQ);
19119 +
19120 +       unsigned int frame_type = UBICOM32_FRAME_TYPE_INTERRUPT;
19121 +
19122 +
19123 +       DEBUG_ASSERT(!thread_is_enabled(tid));
19124 +
19125 +       /*
19126 +        * Acquire the necessary global and per thread locks for tid.
19127 +        * As a side effect, we ensure that the thread has not trapped
19128 +        * and return true if it has.
19129 +        */
19130 +       if (unlikely(thread_is_trapped(tid))) {
19131 +               /*
19132 +                * Read the trap cause, the sp and clear the MT_TRAP bits.
19133 +                */
19134 +               unsigned int cause;
19135 +               asm volatile (
19136 +               "       setcsr  %3              \n\t"
19137 +               "       setcsr_flush 0          \n\t"
19138 +               "       setcsr_flush 0          \n\t"
19139 +               "       move.4  %0, TRAP_CAUSE  \n\t"
19140 +               "       move.4  %1, SP          \n\t"
19141 +               "       setcsr  #0              \n\t"
19142 +               "       setcsr_flush 0          \n\t"
19143 +               "       move.4  MT_BREAK_CLR, %2\n\t"
19144 +               "       move.4  MT_TRAP_CLR, %2 \n\t"
19145 +                       : "=&r" (cause), "=&r" (linux_sp)
19146 +                       : "r" (thread_mask), "m" (read_csr)
19147 +               );
19148 +
19149 +               ldsr_backout_of_irq(vector, (1 << tid));
19150 +
19151 +#if !defined(CONFIG_UNALIGNED_ACCESS_DISABLED)
19152 +               /*
19153 +                * See if the unaligned trap handler can deal with this.
19154 +                * If so, emulate the instruction and then just restart
19155 +                * the thread.
19156 +                */
19157 +               if (unaligned_only(cause)) {
19158 +#if defined(CONFIG_UNALIGNED_ACCESS_USERSPACE_ONLY)
19159 +                       /*
19160 +                        * Check if this is a kernel stack if so we will not
19161 +                        * handle the trap
19162 +                        */
19163 +                       u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
19164 +                       if ((masked_linux_sp != (u32_t)sw_ksp[tid]) &&
19165 +                           unaligned_only(cause)) {
19166 +                               ldsr_emulate_and_run(tid);
19167 +                               return;
19168 +                       }
19169 +#else
19170 +                       ldsr_emulate_and_run(tid);
19171 +                       return;
19172 +#endif
19173 +
19174 +               }
19175 +#endif
19176 +
19177 +               interrupt_vector = (u32_t)(&trap_handler);
19178 +               frame_type = UBICOM32_FRAME_TYPE_TRAP;
19179 +       } else {
19180 +               /*
19181 +                * Read the target thread's SP
19182 +                */
19183 +               asm volatile (
19184 +               "       setcsr  %1              \n\t"
19185 +               "       setcsr_flush 0          \n\t"
19186 +               "       setcsr_flush 0          \n\t"
19187 +               "       move.4  %0, SP          \n\t"
19188 +               "       setcsr  #0              \n\t"
19189 +               "       setcsr_flush 0          \n\t"
19190 +                       : "=m" (linux_sp)
19191 +                       : "m" (read_csr)
19192 +               );
19193 +       }
19194 +
19195 +       /*
19196 +        * We are delivering an interrupt, count it.
19197 +        */
19198 +       ldsr_interrupt.total++;
19199 +
19200 +       /*
19201 +        * At this point, we will definitely force this thread to
19202 +        * a new context, show its interrupts as disabled.
19203 +        */
19204 +       ldsr_thread_irq_disable(tid);
19205 +
19206 +       /*
19207 +        * Test our current state (user, kernel, interrupt).  Save the
19208 +        * appropriate data and setup for the return.
19209 +        */
19210 +       save_area = ldsr_choose_savearea_and_returnvec(tid, linux_sp, &return_vector);
19211 +
19212 +       /*
19213 +        *  The pt_regs (save_area) contains the type of thread that we are dealing
19214 +        *  with (KERNEL/NORMAL) and is copied into each pt_regs area.  We get this
19215 +        *  from the current tasks kernel pt_regs area that always exists at the
19216 +        *  top of the kernel stack.
19217 +        */
19218 +       regs = (struct pt_regs *)((u32_t)sw_ksp[tid] + THREAD_SIZE - sizeof(struct pt_regs) - 8);
19219 +       save_area->thread_type = regs->thread_type;
19220 +
19221 +       /*
19222 +        * Preserve the context of the Linux thread.
19223 +        */
19224 +       ldsr_preemptive_context_save(tid, save_area);
19225 +
19226 +       /*
19227 +        * Load the fram_type into the save_area.
19228 +        */
19229 +       save_area->frame_type = frame_type;
19230 +
19231 +#ifdef CONFIG_STOP_ON_TRAP
19232 +       /*
19233 +        * Before we get backtrace and showing stacks working well, it sometimes
19234 +        * helps to enter the debugger when a trap occurs before we change the
19235 +        * thread to handle the fault.  This optional code causes all threads to
19236 +        * stop on every trap frame.  One assumes that GDB connected via the
19237 +        * mailbox interface will be used to recover from this state.
19238 +        */
19239 +       if (frame_type == UBICOM32_FRAME_TYPE_TRAP) {
19240 +               THREAD_STALL;
19241 +       }
19242 +#endif
19243 +
19244 +#ifdef DEBUG_LDSR
19245 +       copy_regs = *save_area;
19246 +       copy_save_area = save_area;
19247 +
19248 +       old_a0 = save_area->an[0];
19249 +       old_a3 = save_area->an[3];
19250 +       old_sp = save_area->an[7];
19251 +       old_a5 = save_area->an[5];
19252 +       old_pc = save_area->pc;
19253 +#endif
19254 +
19255 +       /*
19256 +        * Now we have to switch the kernel thread to run do_IRQ function.
19257 +        *      Set pc to do_IRQ
19258 +        *      Set d0 to vector
19259 +        *      Set d1 to save_area.
19260 +        *      Set a5 to the proper return vector.
19261 +        */
19262 +       asm volatile (
19263 +       "       setcsr  %0                      \n\t"
19264 +       "       setcsr_flush 0                  \n\t"
19265 +       "       move.4  d0, %5                  \n\t" /* d0 = 0 vector # */
19266 +       "       move.4  d1, %1                  \n\t" /* d1 = save_area */
19267 +       "       move.4  sp, %1                  \n\t" /* sp = save_area */
19268 +       "       move.4  a5, %2                  \n\t" /* a5 = return_vector */
19269 +       "       move.4  pc, %3                  \n\t" /* pc = do_IRQ routine. */
19270 +       "       move.4  trap_cause, #0          \n\t" /* Clear the trap cause
19271 +                                                      * register */
19272 +       "       setcsr  #0                      \n\t"
19273 +       "       setcsr_flush 0                  \n\t"
19274 +       "       enable_kernel_ranges %4         \n\t"
19275 +       "       move.4  mt_dbg_active_set, %4   \n\t" /* Activate thread even if
19276 +                                                      * in dbg/fault state */
19277 +       "       move.4  mt_active_set, %4       \n\t" /* Restart target
19278 +                                                      * thread. */
19279 +               :
19280 +               : "r" (write_csr), "r" (save_area),
19281 +                 "r" (return_vector), "r" (interrupt_vector),
19282 +                 "d" (thread_mask), "r" (vector)
19283 +               : "cc"
19284 +       );
19285 +       thread_enable_mask(thread_mask);
19286 +}
19287 +
19288 +/*
19289 + * ldsr_deliver_interrupt()
19290 + *     Deliver the interrupt to one of the threads or all of the threads.
19291 + */
19292 +static void ldsr_deliver_interrupt(int vector,
19293 +                                  unsigned long deliver_to,
19294 +                                  int all)
19295 +{
19296 +       unsigned long disabled_threads;
19297 +       unsigned long possible_threads;
19298 +       unsigned long trapped_threads;
19299 +       unsigned long global_locks;
19300 +
19301 +       /*
19302 +        * Disable all of the threads that we might want to send
19303 +        * this interrupt to.
19304 +        */
19305 +retry:
19306 +       DEBUG_ASSERT(deliver_to);
19307 +       thread_disable_mask(deliver_to);
19308 +
19309 +       /*
19310 +        * If any threads are in the trap state, we have to service the
19311 +        * trap for those threads first.
19312 +        */
19313 +       asm volatile (
19314 +               "move.4 %0, MT_TRAP             \n\t"
19315 +               : "=r" (trapped_threads)
19316 +               :
19317 +       );
19318 +
19319 +       trapped_threads &= deliver_to;
19320 +       if (unlikely(trapped_threads)) {
19321 +               /*
19322 +                * all traps will be handled, so clear the trap bit before restarting any threads
19323 +                */
19324 +               ubicom32_clear_interrupt(ldsr_trap_irq);
19325 +
19326 +               /*
19327 +                * Let the remaining untrapped threads, continue.
19328 +                */
19329 +               deliver_to &= ~trapped_threads;
19330 +               if (deliver_to) {
19331 +                       thread_enable_mask(deliver_to);
19332 +               }
19333 +
19334 +               /*
19335 +                * For the trapped threads force them to handle
19336 +                * a trap.
19337 +                */
19338 +               while (trapped_threads) {
19339 +                       unsigned long which = ffz(~trapped_threads);
19340 +                       trapped_threads &= ~(1 << which);
19341 +                       ldsr_ctxsw_thread(vector, which);
19342 +               }
19343 +               return;
19344 +       }
19345 +
19346 +       /*
19347 +        * Can we deliver an interrupt to any of the threads?
19348 +        */
19349 +       disabled_threads = ldsr_thread_get_interrupts();
19350 +       possible_threads = deliver_to & ~disabled_threads;
19351 +       if (unlikely(!possible_threads)) {
19352 +#if defined(CONFIG_SMP)
19353 +               /*
19354 +                * In the SMP case, we can not wait because 1 cpu might be
19355 +                * sending an IPI to another cpu which is currently blocked.
19356 +                * The only way to ensure IPI delivery is to backout and
19357 +                * keep trying.  For SMP, we don't sleep until the interrupts
19358 +                * are delivered.
19359 +                */
19360 +               thread_enable_mask(deliver_to);
19361 +               ldsr_backout_of_irq(vector, deliver_to);
19362 +               return;
19363 +#else
19364 +               /*
19365 +                * In the UP case, we have nothing to do so we should wait.
19366 +                *
19367 +                * Since the INT_MASK0 and INT_MASK1 are "re-loaded" before we
19368 +                * suspend in the outer loop, we do not need to save them here.
19369 +                *
19370 +                * We test that we were awakened for our specific interrupts
19371 +                * because the ldsr mask/unmask operations will force the ldsr
19372 +                * awake even if the interrupt on the mainline thread is not
19373 +                * completed.
19374 +                */
19375 +               unsigned int scratch = 0;
19376 +               thread_enable_mask(deliver_to);
19377 +               asm volatile (
19378 +               "       move.4  INT_MASK0, %1           \n\t"
19379 +               "       move.4  INT_MASK1, #0           \n\t"
19380 +
19381 +               "1:     suspend                         \n\t"
19382 +               "       move.4  %0, INT_STAT0           \n\t"
19383 +               "       and.4   %0, %0, %1              \n\t"
19384 +               "       jmpeq.f 1b                      \n\t"
19385 +
19386 +               "       move.4  INT_CLR0, %2            \n\t"
19387 +                       : "+r" (scratch)
19388 +                       : "d" (ldsr_suspend_mask), "r" (ldsr_soft_irq_mask)
19389 +                       : "cc"
19390 +               );
19391 +
19392 +               /*
19393 +                * This delay is sized to coincide with the time it takes a
19394 +                * thread to complete the exit (see return_from_interrupt).
19395 +                */
19396 +               ldsr_interrupt.retry++;
19397 +               __delay(10);
19398 +               goto retry;
19399 +#endif
19400 +       }
19401 +
19402 +       /*
19403 +        * If any of the global locks are held, we can not deliver any
19404 +        * interrupts, we spin delay(10) and then try again.  If our
19405 +        * spinning becomes a bottle neck, we will need to suspend but for
19406 +        * now lets just spin.
19407 +        */
19408 +       asm volatile (
19409 +               "move.4 %0, scratchpad1         \n\t"
19410 +               : "=r" (global_locks)
19411 +               :
19412 +       );
19413 +       if (unlikely(global_locks & 0xffff0000)) {
19414 +               thread_enable_mask(deliver_to);
19415 +
19416 +               /*
19417 +                * This delay is sized to coincide with the average time it
19418 +                * takes a thread to release a global lock.
19419 +                */
19420 +               ldsr_interrupt.retry++;
19421 +               __delay(10);
19422 +               goto retry;
19423 +       }
19424 +
19425 +       /*
19426 +        * Deliver to one cpu.
19427 +        */
19428 +       if (!all) {
19429 +               /*
19430 +                * Find our victim and then enable everyone else.
19431 +                */
19432 +               unsigned long victim = ldsr_rotate_threads(possible_threads);
19433 +               DEBUG_ASSERT((deliver_to & (1 << victim)));
19434 +               DEBUG_ASSERT((possible_threads & (1 << victim)));
19435 +
19436 +               deliver_to &= ~(1 << victim);
19437 +               if (deliver_to) {
19438 +                       thread_enable_mask(deliver_to);
19439 +               }
19440 +               ldsr_ctxsw_thread(vector, victim);
19441 +               return;
19442 +       }
19443 +
19444 +       /*
19445 +        * If we can't deliver to some threads, wake them
19446 +        * back up and reset things to deliver to them.
19447 +        */
19448 +       deliver_to &= ~possible_threads;
19449 +       if (unlikely(deliver_to)) {
19450 +               thread_enable_mask(deliver_to);
19451 +               ldsr_backout_of_irq(vector, deliver_to);
19452 +       }
19453 +
19454 +       /*
19455 +        * Deliver to all possible threads(s).
19456 +        */
19457 +       while (possible_threads) {
19458 +               unsigned long victim = ffz(~possible_threads);
19459 +               possible_threads &= ~(1 << victim);
19460 +               ldsr_ctxsw_thread(vector, victim);
19461 +       }
19462 +}
19463 +
19464 +/*
19465 + * ldsr_thread()
19466 + *     This thread acts as the interrupt controller for Linux.
19467 + */
19468 +static void ldsr_thread(void *arg)
19469 +{
19470 +       int stat0;
19471 +       int stat1;
19472 +       int interrupt0;
19473 +       int interrupt1;
19474 +       long long interrupts;
19475 +       unsigned long cpus;
19476 +
19477 +#if !defined(CONFIG_SMP)
19478 +       /*
19479 +        * In a non-smp configuration, we can not use the cpu(s) arrays because
19480 +        * there is not a 1-1 correspondence between cpus(s) and our threads.
19481 +        * Thus we must get a local idea of the mainline threads and use the
19482 +        * one and only 1 set as the victim.  We do this once before the ldsr
19483 +        * loop.
19484 +        *
19485 +        * In the SMP case, we will use the cpu(s) map to determine which cpu(s)
19486 +        * are valid to send interrupts to.
19487 +        */
19488 +       int victim = 0;
19489 +       unsigned int mainline = thread_get_mainline();
19490 +       if (mainline == 0) {
19491 +               panic("no mainline Linux threads to interrupt");
19492 +               return;
19493 +       }
19494 +       victim = ffz(~mainline);
19495 +       cpus = (1 << victim);
19496 +#endif
19497 +
19498 +       while (1) {
19499 +               /*
19500 +                * If one changes this code not to reload the INT_MASK(s), you
19501 +                * need to know that code in the lock waiting above does not
19502 +                * reset the MASK registers back; so that code will need to be
19503 +                * changed.
19504 +                */
19505 +               ldsr_lock_acquire();
19506 +               asm volatile (
19507 +               "       move.4 INT_MASK0, %0    \n\t"
19508 +               "       move.4 INT_MASK1, %1    \n\t"
19509 +                       :
19510 +                       : "U4" (ldsr_interrupt.mask0), "U4" (ldsr_interrupt.mask1)
19511 +               );
19512 +               ldsr_lock_release();
19513 +               thread_suspend();
19514 +
19515 +               /*
19516 +                * Read the interrupt status registers
19517 +                */
19518 +               asm volatile (
19519 +                       "move.4 %0, INT_STAT0   \n\t"
19520 +                       "move.4 %1, INT_STAT1   \n\t"
19521 +                       : "=r" (stat0), "=r" (stat1)
19522 +                       :
19523 +               );
19524 +
19525 +               /*
19526 +                * We only care about interrupts that we have been told to care
19527 +                * about.  The interrupt must be enabled, unmasked, and have
19528 +                * occurred in the hardware.
19529 +                */
19530 +               ldsr_lock_acquire();
19531 +               interrupt0 = ldsr_interrupt.enabled0 &
19532 +                       ldsr_interrupt.mask0 & stat0;
19533 +               interrupt1 = ldsr_interrupt.enabled1 &
19534 +                       ldsr_interrupt.mask1 & stat1;
19535 +               ldsr_lock_release();
19536 +
19537 +               /*
19538 +                * For each interrupt in the "snapshot" we will mask the
19539 +                * interrupt handle the interrupt (typically calling do_IRQ()).
19540 +                *
19541 +                * The interrupt is unmasked by desc->chip->end() function in
19542 +                * the per chip generic interrupt handling code
19543 +                * (arch/ubicom32/kernel/irq.c).8
19544 +                */
19545 +               interrupts = ((unsigned long long)interrupt1 << 32) |
19546 +                       interrupt0;
19547 +               while (interrupts) {
19548 +                       int all = 0;
19549 +                       int vector = ldsr_rotate_interrupts(interrupts);
19550 +                       interrupts &= ~((unsigned long long)1 << vector);
19551 +
19552 +                       /*
19553 +                        * Now mask off this vector so that the LDSR ignores
19554 +                        * it until it is acknowledged.
19555 +                        */
19556 +                       ldsr_mask_vector(vector);
19557 +#if !defined(CONFIG_SMP)
19558 +                       ldsr_deliver_interrupt(vector, cpus, all);
19559 +#else
19560 +                       cpus = smp_get_affinity(vector, &all);
19561 +                       if (!cpus) {
19562 +                               /*
19563 +                                * No CPU to deliver to so just leave
19564 +                                * the interrupt unmasked and increase
19565 +                                * the backout count.  We will eventually
19566 +                                * return and deliver it again.
19567 +                                */
19568 +                               ldsr_unmask_vector(vector);
19569 +                               ldsr_interrupt.backout++;
19570 +                               continue;
19571 +                       }
19572 +                       ldsr_deliver_interrupt(vector, cpus, all);
19573 +#endif
19574 +               }
19575 +       }
19576 +
19577 +       /* NOTREACHED */
19578 +}
19579 +
19580 +/*
19581 + * ldsr_mask_vector()
19582 + *     Temporarily mask the interrupt vector, turn off the bit in the mask
19583 + *     register.
19584 + */
19585 +void ldsr_mask_vector(unsigned int vector)
19586 +{
19587 +       unsigned int mask;
19588 +       if (vector < 32) {
19589 +               mask = ~(1 << vector);
19590 +               ldsr_lock_acquire();
19591 +               ldsr_interrupt.mask0 &= mask;
19592 +               ldsr_lock_release();
19593 +               thread_resume(ldsr_tid);
19594 +               return;
19595 +       }
19596 +
19597 +       mask = ~(1 << (vector - 32));
19598 +       ldsr_lock_acquire();
19599 +       ldsr_interrupt.mask1 &= mask;
19600 +       ldsr_lock_release();
19601 +       thread_resume(ldsr_tid);
19602 +}
19603 +
19604 +/*
19605 + * ldsr_unmask_vector()
19606 + *     Unmask the interrupt vector so that it can be used, turn on the bit in
19607 + *     the mask register.
19608 + *
19609 + * Because it is legal for the interrupt path to disable an interrupt,
19610 + * the unmasking code must ensure that disabled interrupts are not
19611 + * unmasked.
19612 + */
19613 +void ldsr_unmask_vector(unsigned int vector)
19614 +{
19615 +       unsigned int mask;
19616 +       if (vector < 32) {
19617 +               mask = (1 << vector);
19618 +               ldsr_lock_acquire();
19619 +               ldsr_interrupt.mask0 |= (mask & ldsr_interrupt.enabled0);
19620 +               ldsr_lock_release();
19621 +               thread_resume(ldsr_tid);
19622 +               return;
19623 +       }
19624 +
19625 +       mask = (1 << (vector - 32));
19626 +       ldsr_lock_acquire();
19627 +       ldsr_interrupt.mask1 |= (mask & ldsr_interrupt.enabled1);
19628 +       ldsr_lock_release();
19629 +       thread_resume(ldsr_tid);
19630 +}
19631 +
19632 +/*
19633 + * ldsr_enable_vector()
19634 + *     The LDSR implements an interrupt controller and has a local (to the
19635 + *     LDSR) copy of its interrupt mask.
19636 + */
19637 +void ldsr_enable_vector(unsigned int vector)
19638 +{
19639 +       unsigned int mask;
19640 +       if (vector < 32) {
19641 +               mask = (1 << vector);
19642 +               ldsr_lock_acquire();
19643 +               ldsr_interrupt.enabled0 |= mask;
19644 +               ldsr_interrupt.mask0 |= mask;
19645 +               ldsr_lock_release();
19646 +               thread_resume(ldsr_tid);
19647 +               return;
19648 +       }
19649 +
19650 +       mask = (1 << (vector - 32));
19651 +       ldsr_lock_acquire();
19652 +       ldsr_interrupt.enabled1 |= mask;
19653 +       ldsr_interrupt.mask1 |= mask;
19654 +       ldsr_lock_release();
19655 +       thread_resume(ldsr_tid);
19656 +}
19657 +
19658 +/*
19659 + * ldsr_disable_vector()
19660 + *     The LDSR implements an interrupt controller and has a local (to the
19661 + *     LDSR) copy of its interrupt mask.
19662 + */
19663 +void ldsr_disable_vector(unsigned int vector)
19664 +{
19665 +       unsigned int mask;
19666 +
19667 +       if (vector < 32) {
19668 +               mask = ~(1 << vector);
19669 +               ldsr_lock_acquire();
19670 +               ldsr_interrupt.enabled0 &= mask;
19671 +               ldsr_interrupt.mask0 &= mask;
19672 +               ldsr_lock_release();
19673 +               thread_resume(ldsr_tid);
19674 +               return;
19675 +       }
19676 +
19677 +       mask = ~(1 << (vector - 32));
19678 +       ldsr_lock_acquire();
19679 +       ldsr_interrupt.enabled1 &= mask;
19680 +       ldsr_interrupt.mask1 &= mask;
19681 +       ldsr_lock_release();
19682 +       thread_resume(ldsr_tid);
19683 +}
19684 +
19685 +/*
19686 + * ldsr_get_threadid()
19687 + *     Return the threadid of the LDSR thread.
19688 + */
19689 +thread_t ldsr_get_threadid(void)
19690 +{
19691 +       return ldsr_tid;
19692 +}
19693 +
19694 +/*
19695 + * ldsr_set_trap_irq()
19696 + *     Save away the trap Soft IRQ
19697 + *
19698 + * See the per thread lock suspend code above for an explination.
19699 + */
19700 +void ldsr_set_trap_irq(unsigned int irq)
19701 +{
19702 +       ldsr_trap_irq = irq;
19703 +       ldsr_trap_irq_mask = (1 << irq);
19704 +       ldsr_suspend_mask |= ldsr_trap_irq_mask;
19705 +}
19706 +
19707 +/*
19708 + * ldsr_init()
19709 + *     Initialize the LDSR (Interrupt Controller)
19710 + */
19711 +void ldsr_init(void)
19712 +{
19713 +#if defined(CONFIG_IRQSTACKS)
19714 +       int i;
19715 +       union irq_ctx *icp;
19716 +#endif
19717 +
19718 +       void *stack_high = (void *)ldsr_stack_space;
19719 +       stack_high += sizeof(ldsr_stack_space);
19720 +       stack_high -= 8;
19721 +
19722 +
19723 +       /*
19724 +        * Obtain a soft IRQ to use
19725 +        */
19726 +       if (irq_soft_alloc(&ldsr_soft_irq) < 0) {
19727 +               panic("no software IRQ is available\n");
19728 +               return;
19729 +       }
19730 +       ldsr_soft_irq_mask |= (1 << ldsr_soft_irq);
19731 +       ldsr_suspend_mask |= ldsr_soft_irq_mask;
19732 +
19733 +       /*
19734 +        * Now allocate and start the LDSR thread.
19735 +        */
19736 +       ldsr_tid = thread_alloc();
19737 +       if (ldsr_tid < 0) {
19738 +               panic("no thread available to run LDSR");
19739 +               return;
19740 +       }
19741 +
19742 +#if defined(CONFIG_IRQSTACKS)
19743 +       /*
19744 +        * Initialize the per-cpu irq thread_info structure that
19745 +        * is at the top of each per-cpu irq stack.
19746 +        */
19747 +       icp = (union irq_ctx *)
19748 +               (((unsigned long)percpu_irq_stacks + (THREAD_SIZE - 1)) & ~(THREAD_SIZE - 1));
19749 +       for (i = 0; i < NR_CPUS; i++) {
19750 +               struct thread_info *ti = &(icp->tinfo);
19751 +               ti->task = NULL;
19752 +               ti->exec_domain = NULL;
19753 +               ti->cpu = i;
19754 +               ti->preempt_count = 0;
19755 +               ti->interrupt_nesting = 0;
19756 +               percpu_irq_ctxs[i] = icp++;
19757 +       }
19758 +#endif
19759 +       thread_start(ldsr_tid, ldsr_thread, NULL,
19760 +                    stack_high, THREAD_TYPE_NORMAL);
19761 +}
19762 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/Makefile linux-2.6.30.10-ubi/arch/ubicom32/kernel/Makefile
19763 --- linux-2.6.30.10/arch/ubicom32/kernel/Makefile       1970-01-01 02:00:00.000000000 +0200
19764 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/Makefile   2009-12-11 11:45:11.000000000 +0200
19765 @@ -0,0 +1,64 @@
19766 +#
19767 +# arch/ubicom32/kernel/Makefile
19768 +#      Main Makefile for the Ubicom32 arch directory.
19769 +#
19770 +# (C) Copyright 2009, Ubicom, Inc.
19771 +#
19772 +# This file is part of the Ubicom32 Linux Kernel Port.
19773 +#
19774 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
19775 +# it and/or modify it under the terms of the GNU General Public License
19776 +# as published by the Free Software Foundation, either version 2 of the
19777 +# License, or (at your option) any later version.
19778 +#
19779 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
19780 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
19781 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
19782 +# the GNU General Public License for more details.
19783 +#
19784 +# You should have received a copy of the GNU General Public License
19785 +# along with the Ubicom32 Linux Kernel Port.  If not,
19786 +# see <http://www.gnu.org/licenses/>.
19787 +#
19788 +# Ubicom32 implementation derived from (with many thanks):
19789 +#   arch/m68knommu
19790 +#   arch/blackfin
19791 +#   arch/parisc
19792 +#
19793 +
19794 +extra-y := head.o vmlinux.lds
19795 +
19796 +obj-y += \
19797 +       devtree.o \
19798 +       dma.o \
19799 +       flat.o \
19800 +       init_task.o \
19801 +       irq.o \
19802 +       ldsr.o \
19803 +       os_node.o \
19804 +       process.o \
19805 +       processor.o \
19806 +       ptrace.o \
19807 +       setup.o \
19808 +       signal.o \
19809 +       stacktrace.o \
19810 +       sys_ubicom32.o \
19811 +       syscalltable.o \
19812 +       thread.o \
19813 +       time.o \
19814 +       traps.o \
19815 +       ubicom32_context_switch.o \
19816 +       ubicom32_ksyms.o \
19817 +       ubicom32_syscall.o \
19818 +       unaligned_trap.o
19819 +
19820 +obj-$(CONFIG_MODULES)                          += module.o
19821 +obj-$(CONFIG_COMEMPCI)                         += comempci.o
19822 +obj-$(CONFIG_SMP)                              += smp.o topology.o
19823 +obj-$(CONFIG_ACCESS_OK_CHECKS_ENABLED)         += uaccess.o
19824 +obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += timer_device.o
19825 +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += timer_broadcast.o
19826 +
19827 +ifndef CONFIG_GENERIC_CLOCKEVENTS
19828 +obj-y                  += timer_tick.o
19829 +endif
19830 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/module.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/module.c
19831 --- linux-2.6.30.10/arch/ubicom32/kernel/module.c       1970-01-01 02:00:00.000000000 +0200
19832 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/module.c   2009-12-11 11:45:11.000000000 +0200
19833 @@ -0,0 +1,463 @@
19834 +/*
19835 + * arch/ubicom32/kernel/module.c
19836 + *   Ubicom32 architecture loadable module support.
19837 + *
19838 + * (C) Copyright 2009, Ubicom, Inc.
19839 + *
19840 + * This file is part of the Ubicom32 Linux Kernel Port.
19841 + *
19842 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
19843 + * it and/or modify it under the terms of the GNU General Public License
19844 + * as published by the Free Software Foundation, either version 2 of the
19845 + * License, or (at your option) any later version.
19846 + *
19847 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19848 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19849 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
19850 + * the GNU General Public License for more details.
19851 + *
19852 + * You should have received a copy of the GNU General Public License
19853 + * along with the Ubicom32 Linux Kernel Port.  If not,
19854 + * see <http://www.gnu.org/licenses/>.
19855 + *
19856 + * Ubicom32 implementation derived from (with many thanks):
19857 + *   arch/m68knommu
19858 + *   arch/blackfin
19859 + *   arch/parisc
19860 + */
19861 +#include <linux/moduleloader.h>
19862 +#include <linux/bug.h>
19863 +#include <linux/elf.h>
19864 +#include <linux/vmalloc.h>
19865 +#include <linux/fs.h>
19866 +#include <linux/string.h>
19867 +#include <linux/kernel.h>
19868 +#include <asm/ocm-alloc.h>
19869 +
19870 +#if 0
19871 +#define DEBUGP printk
19872 +#else
19873 +#define DEBUGP(fmt...)
19874 +#endif
19875 +
19876 +static void _module_free_ocm(struct module *mod)
19877 +{
19878 +       printk(KERN_INFO "module arch cleanup %s: OCM instruction memory free "
19879 +              " of %d @%p\n", mod->name, mod->arch.ocm_inst_size,
19880 +              mod->arch.ocm_inst);
19881 +
19882 +       if (mod->arch.ocm_inst) {
19883 +               ocm_inst_free(mod->arch.ocm_inst);
19884 +               mod->arch.ocm_inst = 0;
19885 +               mod->arch.ocm_inst_size = 0;
19886 +       }
19887 +}
19888 +
19889 +void *module_alloc(unsigned long size)
19890 +{
19891 +       if (size == 0)
19892 +               return NULL;
19893 +       return vmalloc(size);
19894 +}
19895 +
19896 +
19897 +/* Free memory returned from module_alloc */
19898 +void module_free(struct module *mod, void *module_region)
19899 +{
19900 +       vfree(module_region);
19901 +       /* FIXME: If module_region == mod->init_region, trim exception
19902 +          table entries. */
19903 +
19904 +       /*
19905 +        * This is expected to be final module free, use this to prune the
19906 +        * ocm
19907 +        */
19908 +       if (module_region && module_region == mod->module_core)
19909 +               _module_free_ocm(mod);
19910 +
19911 +}
19912 +
19913 +/*
19914 + * module_frob_arch_sections()
19915 + *     Called from kernel/module.c allowing arch specific handling of
19916 + *     sections/headers.
19917 + */
19918 +int module_frob_arch_sections(Elf_Ehdr *hdr,
19919 +                             Elf_Shdr *sechdrs,
19920 +                             char *secstrings,
19921 +                             struct module *mod)
19922 +{
19923 +       Elf_Shdr *s, *sechdrs_end;
19924 +       void *ocm_inst = NULL;
19925 +       int ocm_inst_size = 0;
19926 +
19927 +       /*
19928 +        * Ubicom32 v3 and v4 are almost binary compatible but not completely.
19929 +        * To be safe check that the module was compiled with the correct -march
19930 +        * which is flags.
19931 +        */
19932 +#ifdef CONFIG_UBICOM32_V4
19933 +       if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V4) {
19934 +               printk(KERN_WARNING "Module %s was not compiled for "
19935 +                      "ubicom32v4, elf_flags:%x,\n",
19936 +                      mod->name, hdr->e_flags);
19937 +               return -ENOEXEC;
19938 +       }
19939 +#elif defined CONFIG_UBICOM32_V3
19940 +       if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V3) {
19941 +               printk(KERN_WARNING "Module %s was not compiled for "
19942 +                      "ubicom32v3, elf_flags:%x\n",
19943 +                      mod->name, hdr->e_flags);
19944 +               return -ENOEXEC;
19945 +       }
19946 +#else
19947 +#error Unknown/Unsupported ubicom32 architecture.
19948 +#endif
19949 +
19950 +       /*
19951 +        * XXX: sechdrs are vmalloced in kernel/module.c
19952 +        * and would be vfreed just after module is loaded,
19953 +        * so we hack to keep the only information we needed
19954 +        * in mod->arch to correctly free L1 I/D sram later.
19955 +        * NOTE: this breaks the semantic of mod->arch structure.
19956 +        */
19957 +       sechdrs_end = sechdrs + hdr->e_shnum;
19958 +       for (s = sechdrs; s < sechdrs_end; ++s) {
19959 +               if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0)
19960 +                       ocm_inst_size += s->sh_size;
19961 +       }
19962 +
19963 +       if (!ocm_inst_size)
19964 +               return 0;
19965 +
19966 +       ocm_inst = ocm_inst_alloc(ocm_inst_size, 0 /* internal */);
19967 +       if (ocm_inst == NULL) {
19968 +#ifdef CONFIG_OCM_MODULES_FALLBACK_TO_DDR
19969 +               printk(KERN_WARNING
19970 +                      "module %s: OCM instruction memory allocation of %d"
19971 +                      "failed, fallback to DDR\n", mod->name, ocm_inst_size);
19972 +               return 0;
19973 +#else
19974 +               printk(KERN_ERR
19975 +                      "module %s: OCM instruction memory allocation of %d"
19976 +                      "failed.\n", mod->name, ocm_inst_size);
19977 +               return -ENOMEM;
19978 +#endif
19979 +       }
19980 +
19981 +       mod->arch.ocm_inst = ocm_inst;
19982 +       mod->arch.ocm_inst_size = ocm_inst_size;
19983 +
19984 +       printk(KERN_INFO
19985 +              "module %s: OCM instruction memory allocation of %d @%p\n",
19986 +              mod->name, mod->arch.ocm_inst_size, mod->arch.ocm_inst);
19987 +
19988 +       for (s = sechdrs; s < sechdrs_end; ++s) {
19989 +               if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0) {
19990 +                       memcpy(ocm_inst, (void *)s->sh_addr, s->sh_size);
19991 +                       s->sh_flags &= ~SHF_ALLOC;
19992 +                       s->sh_addr = (unsigned long)ocm_inst;
19993 +                       ocm_inst += s->sh_size;
19994 +               }
19995 +       }
19996 +
19997 +       return 0;
19998 +}
19999 +
20000 +int apply_relocate(Elf32_Shdr *sechdrs,
20001 +                  const char *strtab,
20002 +                  unsigned int symindex,
20003 +                  unsigned int relsec,
20004 +                  struct module *me)
20005 +{
20006 +       DEBUGP("Invalid Applying relocate section %u to %u\n", relsec,
20007 +              sechdrs[relsec].sh_info);
20008 +       return -EINVAL;
20009 +}
20010 +
20011 +int apply_relocate_add(Elf32_Shdr *sechdrs,
20012 +                      const char *strtab,
20013 +                      unsigned int symindex,
20014 +                      unsigned int relsec,
20015 +                      struct module *me)
20016 +{
20017 +       unsigned int i;
20018 +       Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
20019 +       Elf32_Sym *sym;
20020 +       uint32_t *location;
20021 +       uint32_t insn;
20022 +
20023 +       DEBUGP("Applying relocate_add section %u to %u\n", relsec,
20024 +              sechdrs[relsec].sh_info);
20025 +       for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
20026 +               uint32_t v;
20027 +               const int elf32_rtype = ELF32_R_TYPE(rel[i].r_info);
20028 +
20029 +               /* This is where to make the change */
20030 +               location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
20031 +                       + rel[i].r_offset;
20032 +               /* This is the symbol it is referring to.  Note that all
20033 +                  undefined symbols have been resolved.  */
20034 +               sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
20035 +                       + ELF32_R_SYM(rel[i].r_info);
20036 +
20037 +               v = rel[i].r_addend + sym->st_value;
20038 +
20039 +
20040 +               switch (elf32_rtype) {
20041 +               case R_UBICOM32_32:
20042 +               {
20043 +                       /*
20044 +                        * Store the 32 bit relocation as is.
20045 +                        */
20046 +                       *location = v;
20047 +                       break;
20048 +               }
20049 +               case R_UBICOM32_HI24:
20050 +               {
20051 +                       /*
20052 +                        * 24 bit relocation that is part of the MOVEAI
20053 +                        * instruction. The 24 bits come from bits 7 - 30 of the
20054 +                        * relocation. Theses bits eventually get split into 2
20055 +                        * fields in the instruction encoding.
20056 +                        *
20057 +                        * - Bits 7 - 27 of the relocation are encoded into bits
20058 +                        * 0 - 20 of the instruction.
20059 +                        *
20060 +                        *  - Bits 28 - 30 of the relocation are encoded into
20061 +                        *  bit 24 - 26 of the instruction.
20062 +                        */
20063 +                       uint32_t valid24 = (v >> 7) & 0xffffff;
20064 +                       insn = *location;
20065 +
20066 +                       insn &= ~(0x1fffff | (0x7 << 24));
20067 +                       insn |= (valid24 & 0x1fffff);
20068 +                       insn |= ((valid24 & 0xe00000) << 3);
20069 +                       *location = insn;
20070 +               }
20071 +               break;
20072 +               case R_UBICOM32_LO7_S:
20073 +               case R_UBICOM32_LO7_2_S:
20074 +               case R_UBICOM32_LO7_4_S:
20075 +               {
20076 +                       /*
20077 +                        * Bits 0 - 6 of the relocation are encoded into the
20078 +                        * 7bit unsigned immediate fields of the SOURCE-1 field
20079 +                        * of the instruction.  The immediate value is left
20080 +                        * shifted by (0, 1, 2) based on the operand size.
20081 +                        */
20082 +                       uint32_t valid7 = v & 0x7f;
20083 +                       insn = *location;
20084 +
20085 +                       if (elf32_rtype == R_UBICOM32_LO7_2_S) {
20086 +                               valid7 >>= 1;
20087 +                       } else if (elf32_rtype == R_UBICOM32_LO7_4_S) {
20088 +                               valid7 >>= 2;
20089 +                       }
20090 +
20091 +                       insn &= ~(0x1f | (0x3 << 8));
20092 +                       insn |= (valid7 & 0x1f);
20093 +                       insn |= ((valid7 & 0x60) << 3);
20094 +                       *location = insn;
20095 +               }
20096 +               break;
20097 +               case R_UBICOM32_LO7_D:
20098 +               case R_UBICOM32_LO7_2_D:
20099 +               case R_UBICOM32_LO7_4_D:
20100 +               {
20101 +                       /*
20102 +                        * Bits 0 - 6 of the relocation are encoded into the
20103 +                        * 7bit unsigned immediate fields of the DESTINATION
20104 +                        * field of the instruction.  The immediate value is
20105 +                        * left shifted by (0, 1, 2) based on the operand size.
20106 +                        */
20107 +                       uint32_t valid7 = v & 0x7f;
20108 +                       insn = *location;
20109 +
20110 +                       if (elf32_rtype == R_UBICOM32_LO7_2_D) {
20111 +                               valid7 >>= 1;
20112 +                       } else if (elf32_rtype == R_UBICOM32_LO7_4_D) {
20113 +                               valid7 >>= 2;
20114 +                       }
20115 +
20116 +                       insn &= ~((0x1f | (0x3 << 8)) << 16);
20117 +                       insn |= ((valid7 & 0x1f) << 16);
20118 +                       insn |= ((valid7 & 0x60) << 19);
20119 +                       *location = insn;
20120 +               }
20121 +               break;
20122 +               case R_UBICOM32_LO7_CALLI:
20123 +               case R_UBICOM32_LO16_CALLI:
20124 +               {
20125 +                       /*
20126 +                        * Extract the offset for a CALLI instruction. The
20127 +                        * offsets can be either 7 bits or 18 bits. Since all
20128 +                        * instructions in ubicom32 architecture are at work
20129 +                        * aligned addresses the truncated offset is right
20130 +                        * shifted by 2 before being encoded in the instruction.
20131 +                        */
20132 +                       uint32_t val;
20133 +                       if (elf32_rtype == R_UBICOM32_LO7_CALLI) {
20134 +                               val  = v & 0x7f;
20135 +                       } else {
20136 +                               val  = v & 0x3ffff;
20137 +                       }
20138 +
20139 +                       val >>= 2;
20140 +
20141 +                       insn = *location;
20142 +
20143 +                       insn &= ~0x071f071f;
20144 +                       insn |= (val & 0x1f) << 0;
20145 +                       val >>= 5;
20146 +                       insn |= (val & 0x07) << 8;
20147 +                       val >>= 3;
20148 +                       insn |= (val & 0x1f) << 16;
20149 +                       val >>= 5;
20150 +                       insn |= (val & 0x07) << 24;
20151 +                       *location = insn;
20152 +               }
20153 +               break;
20154 +               case R_UBICOM32_24_PCREL:
20155 +               {
20156 +                       /*
20157 +                        * Extract 26 bit signed PC relative offset for CALL
20158 +                        * instructions. Since instruction addresses are word
20159 +                        * aligned the offset is right shited by 2 before
20160 +                        * encoding into instruction.
20161 +                        */
20162 +                       int32_t val = v - (int32_t)location;
20163 +
20164 +                       /*
20165 +                        * Check that the top 7 bits are all equal to the sign
20166 +                        * bit (26), i.e all 0's or all 1's.  If they are not then
20167 +                        * the absolute difference is greater than 25 bits.
20168 +                        */
20169 +                       if (((uint32_t)val & 0xFE000000) != 0xFE000000 &&
20170 +                               ((uint32_t)val & 0xFE000000) != 0x0) {
20171 +                               /*
20172 +                                * The relocation is beyond our addressable
20173 +                                * range with a 26 bit call.
20174 +                                */
20175 +                               printk(KERN_ERR "module %s: PC Relative "
20176 +                                       "relocation out of range: "
20177 +                                       "%u (%x->%x, %x)\n",
20178 +                                       me->name, elf32_rtype,
20179 +                                       v, (uint32_t) location, val);
20180 +                               return -ENOEXEC;
20181 +                       }
20182 +
20183 +                       val = (val & 0x3ffffff) >> 2;
20184 +                       insn = *location;
20185 +                       insn = insn & 0xf8e00000;
20186 +
20187 +                       insn |= (val >> 21) << 24;
20188 +                       insn |= (val & 0x1fffff);
20189 +                       *location = insn;
20190 +               }
20191 +               break;
20192 +               case R_UBICOM32_LO16:
20193 +               case R_UBICOM32_HI16:
20194 +               {
20195 +                       /*
20196 +                        * 16 bit immediate value that is encoded into bit 0 -
20197 +                        * 15 of the instruction.
20198 +                        */
20199 +                       uint32_t val;
20200 +
20201 +                       if (elf32_rtype == R_UBICOM32_LO16) {
20202 +                               val  = v & 0xffff;
20203 +                       } else {
20204 +                               val  = (v >> 16) & 0xffff;
20205 +                       }
20206 +
20207 +                       insn = *location;
20208 +                       insn &= 0xffff0000;
20209 +
20210 +                       insn |= val;
20211 +                       *location = insn;
20212 +               }
20213 +               break;
20214 +               case R_UBICOM32_21_PCREL:
20215 +               {
20216 +                       /*
20217 +                        * Extract 23 bit signed PC relative offset for JMP<cc>
20218 +                        * instructions. Since instruction addresses are word
20219 +                        * aligned the offset is right shited by 2 before
20220 +                        * encoding into instruction.
20221 +                        */
20222 +                       int32_t val = v - (int32_t)location;
20223 +
20224 +                       val = (val & 0x7fffff) >> 2;
20225 +                       insn = *location;
20226 +                       insn = insn & 0xffe00000;
20227 +
20228 +                       insn |= (val >> 21) << 24;
20229 +                       insn |= val;
20230 +                       *location = insn;
20231 +               }
20232 +               break;
20233 +               default:
20234 +                       BUG();
20235 +                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
20236 +                              me->name, elf32_rtype);
20237 +                       return -ENOEXEC;
20238 +               }
20239 +       }
20240 +       return 0;
20241 +}
20242 +
20243 +int module_finalize(const Elf_Ehdr *hdr,
20244 +                   const Elf_Shdr *sechdrs,
20245 +                   struct module *mod)
20246 +{
20247 +       unsigned int i, strindex = 0, symindex = 0;
20248 +       char *secstrings;
20249 +       int err;
20250 +
20251 +       err = module_bug_finalize(hdr, sechdrs, mod);
20252 +       if (err)
20253 +               return err;
20254 +
20255 +       if (!mod->arch.ocm_inst) {
20256 +               /*
20257 +                * No OCM code, so nothing more to do.
20258 +                */
20259 +               return 0;
20260 +       }
20261 +
20262 +       secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
20263 +
20264 +       for (i = 1; i < hdr->e_shnum; i++) {
20265 +               /* Internal symbols and strings. */
20266 +               if (sechdrs[i].sh_type == SHT_SYMTAB) {
20267 +                       symindex = i;
20268 +                       strindex = sechdrs[i].sh_link;
20269 +               }
20270 +       }
20271 +
20272 +       for (i = 1; i < hdr->e_shnum; i++) {
20273 +               const char *strtab = (char *)sechdrs[strindex].sh_addr;
20274 +               unsigned int info = sechdrs[i].sh_info;
20275 +
20276 +               /* Not a valid relocation section? */
20277 +               if (info >= hdr->e_shnum)
20278 +                       continue;
20279 +
20280 +               if ((sechdrs[i].sh_type == SHT_RELA) &&
20281 +                   (strncmp(".rela.ocm_text",
20282 +                            secstrings + sechdrs[i].sh_name, 5 + 9) == 0)) {
20283 +                       err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
20284 +                                                symindex, i, mod);
20285 +                       if (err)
20286 +                               return err;
20287 +               }
20288 +       }
20289 +
20290 +       return 0;
20291 +}
20292 +
20293 +void module_arch_cleanup(struct module *mod)
20294 +{
20295 +       module_bug_cleanup(mod);
20296 +}
20297 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/os_node.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/os_node.c
20298 --- linux-2.6.30.10/arch/ubicom32/kernel/os_node.c      1970-01-01 02:00:00.000000000 +0200
20299 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/os_node.c  2009-12-11 11:45:11.000000000 +0200
20300 @@ -0,0 +1,88 @@
20301 +/*
20302 + * arch/ubicom32/kernel/os_node.c
20303 + *   <TODO: Replace with short file description>
20304 + *
20305 + * (C) Copyright 2009, Ubicom, Inc.
20306 + *
20307 + * This file is part of the Ubicom32 Linux Kernel Port.
20308 + *
20309 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20310 + * it and/or modify it under the terms of the GNU General Public License
20311 + * as published by the Free Software Foundation, either version 2 of the
20312 + * License, or (at your option) any later version.
20313 + *
20314 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20315 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20316 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
20317 + * the GNU General Public License for more details.
20318 + *
20319 + * You should have received a copy of the GNU General Public License
20320 + * along with the Ubicom32 Linux Kernel Port.  If not,
20321 + * see <http://www.gnu.org/licenses/>.
20322 + *
20323 + */
20324 +#include "linux/types.h"
20325 +#include "linux/linkage.h"
20326 +#include "linux/uts.h"
20327 +#include "linux/utsrelease.h"
20328 +#include "linux/version.h"
20329 +#include <asm/ocm_size.h>
20330 +#include <asm/devtree.h>
20331 +#include <asm/ip5000.h>
20332 +
20333 +extern asmlinkage void *_start;
20334 +
20335 +/*
20336 + * This file provides static information to the boot code allowing it to decide
20337 + * if the os is compatible. Thus hopefully enabling the boot code to prevent
20338 + * accidentally booting a kernel that has no hope of running.
20339 + */
20340 +struct os_node {
20341 +       struct devtree_node node;
20342 +       unsigned long version; /* Always 1 */
20343 +       unsigned long entry_point;
20344 +       const char    os_name[32]; /* For diagnostic purposes only */
20345 +       const char    os_version_str[32];
20346 +       unsigned long os_version_num;
20347 +       unsigned long expected_ocm_code_start;/* OS Code */
20348 +       unsigned long expected_ocm_data_end;  /* OS Data */
20349 +       unsigned long expected_ram_start;
20350 +       unsigned long expected_ram_end;
20351 +       unsigned long arch_version;
20352 +       unsigned long expected_os_syscall_begin;
20353 +       unsigned long expected_os_syscall_end;
20354 +};
20355 +
20356 +
20357 +extern void __os_syscall_begin;
20358 +extern void __os_syscall_end;
20359 +/*
20360 + * The os_node is only referenced by head.S and should never be modified at
20361 + * run-time.
20362 + */
20363 +asmlinkage const struct os_node _os_node = {
20364 +       .node = {
20365 +               .next = NULL,
20366 +               .name = { "OS" },
20367 +               .magic = 0x10203040,
20368 +       },
20369 +       .version = 0x10002,
20370 +       .entry_point = (unsigned long)&_start,
20371 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
20372 +       .expected_ocm_code_start = OCMSTART + APP_OCM_CODE_SIZE,
20373 +       .expected_ocm_data_end   = OCMEND   - APP_OCM_DATA_SIZE,
20374 +#else
20375 +       .expected_ocm_code_start = OCMEND,
20376 +       .expected_ocm_data_end   = OCMEND,
20377 +#endif
20378 +       .os_name = { UTS_SYSNAME },
20379 +       .os_version_str = { UTS_RELEASE },
20380 +       .os_version_num = LINUX_VERSION_CODE,
20381 +       .expected_ram_start = KERNELSTART,
20382 +       .expected_ram_end = SDRAMSTART + CONFIG_MIN_RAMSIZE,
20383 +       .arch_version = UBICOM32_ARCH_VERSION,
20384 +       .expected_os_syscall_begin = (unsigned long)&__os_syscall_begin,
20385 +       .expected_os_syscall_end = (unsigned long)&__os_syscall_end,
20386 +
20387 +
20388 +};
20389 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/process.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/process.c
20390 --- linux-2.6.30.10/arch/ubicom32/kernel/process.c      1970-01-01 02:00:00.000000000 +0200
20391 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/process.c  2009-12-11 11:45:11.000000000 +0200
20392 @@ -0,0 +1,634 @@
20393 +/*
20394 + * arch/ubicom32/kernel/process.c
20395 + *   Ubicom32 architecture-dependent process handling.
20396 + *
20397 + * (C) Copyright 2009, Ubicom, Inc.
20398 + * Copyright (C) 1995  Hamish Macdonald
20399 + *
20400 + * 68060 fixes by Jesper Skov
20401 + *
20402 + * uClinux changes
20403 + * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
20404 + *
20405 + * This file is part of the Ubicom32 Linux Kernel Port.
20406 + *
20407 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20408 + * it and/or modify it under the terms of the GNU General Public License
20409 + * as published by the Free Software Foundation, either version 2 of the
20410 + * License, or (at your option) any later version.
20411 + *
20412 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20413 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20414 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
20415 + * the GNU General Public License for more details.
20416 + *
20417 + * You should have received a copy of the GNU General Public License
20418 + * along with the Ubicom32 Linux Kernel Port.  If not,
20419 + * see <http://www.gnu.org/licenses/>.
20420 + *
20421 + * Ubicom32 implementation derived from (with many thanks):
20422 + *   arch/m68knommu
20423 + *   arch/blackfin
20424 + *   arch/parisc
20425 + */
20426 +
20427 +/*
20428 + * This file handles the architecture-dependent parts of process handling..
20429 + */
20430 +
20431 +#include <linux/module.h>
20432 +#include <linux/errno.h>
20433 +#include <linux/sched.h>
20434 +#include <linux/kernel.h>
20435 +#include <linux/mm.h>
20436 +#include <linux/smp.h>
20437 +#include <linux/smp_lock.h>
20438 +#include <linux/stddef.h>
20439 +#include <linux/unistd.h>
20440 +#include <linux/ptrace.h>
20441 +#include <linux/slab.h>
20442 +#include <linux/user.h>
20443 +#include <linux/a.out.h>
20444 +#include <linux/interrupt.h>
20445 +#include <linux/reboot.h>
20446 +#include <linux/fs.h>
20447 +#include <linux/pm.h>
20448 +
20449 +#include <linux/uaccess.h>
20450 +#include <asm/system.h>
20451 +#include <asm/traps.h>
20452 +#include <asm/machdep.h>
20453 +#include <asm/setup.h>
20454 +#include <asm/pgtable.h>
20455 +#include <asm/ip5000.h>
20456 +#include <asm/range-protect.h>
20457 +
20458 +#define DUMP_RANGE_REGISTER(REG, IDX) asm volatile ( \
20459 +        "       move.4          %0, "REG"_RANGE"IDX"_EN \n\t" \
20460 +        "       move.4          %1, "REG"_RANGE"IDX"_LO \n\t" \
20461 +        "       move.4          %2, "REG"_RANGE"IDX"_HI \n\t" \
20462 +                : "=d"(en), "=d"(lo), "=d"(hi) \
20463 +        ); \
20464 +        printk(KERN_NOTICE REG"Range"IDX": en:%08x, range: %08x-%08x\n", \
20465 +                (unsigned int)en, \
20466 +                (unsigned int)lo, \
20467 +                (unsigned int)hi)
20468 +
20469 +asmlinkage void ret_from_fork(void);
20470 +
20471 +void (*pm_power_off)(void) = machine_power_off;
20472 +EXPORT_SYMBOL(pm_power_off);
20473 +
20474 +/* machine-dependent / hardware-specific power functions */
20475 +void (*mach_reset)(void);
20476 +void (*mach_halt)(void);
20477 +void (*mach_power_off)(void);
20478 +
20479 +/*
20480 + * cpu_idle()
20481 + *     The idle thread.
20482 + *
20483 + * Our idle loop suspends and is woken up by a timer interrupt.
20484 + */
20485 +void cpu_idle(void)
20486 +{
20487 +       while (1) {
20488 +               local_irq_disable();
20489 +               while (!need_resched()) {
20490 +                       local_irq_enable();
20491 +                       thread_suspend();
20492 +                       local_irq_disable();
20493 +               }
20494 +               local_irq_enable();
20495 +               preempt_enable_no_resched();
20496 +               schedule();
20497 +               preempt_disable();
20498 +       }
20499 +}
20500 +
20501 +/*
20502 + * dump_fpu()
20503 + *
20504 + *     Fill in the fpu structure for a core dump. (just a stub as we don't have
20505 + *     an fpu)
20506 + */
20507 +int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
20508 +{
20509 +       return 1;
20510 +}
20511 +
20512 +/*
20513 + * machine_restart()
20514 + *     Resets the system.
20515 + */
20516 +void machine_restart(char *__unused)
20517 +{
20518 +       /*
20519 +        * Disable all threads except myself. We can do this
20520 +        * directly without needing to call smp_send_stop
20521 +        * because we have a unique architecture where
20522 +        * one thread can disable one or more other threads.
20523 +        */
20524 +       thread_disable_others();
20525 +
20526 +       /*
20527 +        * Call the hardware-specific machine reset function.
20528 +        */
20529 +       if (mach_reset) {
20530 +               mach_reset();
20531 +       }
20532 +
20533 +       printk(KERN_EMERG "System Restarting\n");
20534 +
20535 +       /*
20536 +        * Set watchdog to trigger (after 1ms delay) (12 Mhz is the fixed OSC)
20537 +        */
20538 +       UBICOM32_IO_TIMER->tkey = TIMER_TKEYVAL;
20539 +       UBICOM32_IO_TIMER->wdcom = UBICOM32_IO_TIMER->mptval +
20540 +               (12000000 / 1000);
20541 +       UBICOM32_IO_TIMER->wdcfg = 0;
20542 +       UBICOM32_IO_TIMER->tkey = 0;
20543 +
20544 +       /*
20545 +        * Wait for watchdog
20546 +        */
20547 +       asm volatile (
20548 +               "       move.4          MT_EN, #0               \n\t"
20549 +               "       pipe_flush      0                       \n\t"
20550 +       );
20551 +
20552 +       local_irq_disable();
20553 +       for (;;) {
20554 +               thread_suspend();
20555 +       }
20556 +}
20557 +
20558 +/*
20559 + * machine_halt()
20560 + *     Halt the machine.
20561 + *
20562 + * Similar to machine_power_off, but don't shut off power.  Add code
20563 + * here to freeze the system for e.g. post-mortem debug purpose when
20564 + * possible.  This halt has nothing to do with the idle halt.
20565 + */
20566 +void machine_halt(void)
20567 +{
20568 +       /*
20569 +        * Disable all threads except myself. We can do this
20570 +        * directly without needing to call smp_send_stop
20571 +        * because we have a unique architecture where
20572 +        * one thread can disable one or more other threads.
20573 +        */
20574 +       thread_disable_others();
20575 +
20576 +       /*
20577 +        * Call the hardware-specific machine halt function.
20578 +        */
20579 +       if (mach_halt) {
20580 +               mach_halt();
20581 +       }
20582 +
20583 +       printk(KERN_EMERG "System Halted, OK to turn off power\n");
20584 +       local_irq_disable();
20585 +       for (;;) {
20586 +               thread_suspend();
20587 +       }
20588 +}
20589 +
20590 +/*
20591 + * machine_power_off()
20592 + *     Turn the power off, if a power off handler is defined, otherwise, spin
20593 + *     endlessly.
20594 + */
20595 +void machine_power_off(void)
20596 +{
20597 +       /*
20598 +        * Disable all threads except myself. We can do this
20599 +        * directly without needing to call smp_send_stop
20600 +        * because we have a unique architecture where
20601 +        * one thread can disable one or more other threads.
20602 +        */
20603 +       thread_disable_others();
20604 +
20605 +       /*
20606 +        * Call the hardware-specific machine power off function.
20607 +        */
20608 +       if (mach_power_off) {
20609 +               mach_power_off();
20610 +       }
20611 +
20612 +       printk(KERN_EMERG "System Halted, OK to turn off power\n");
20613 +       local_irq_disable();
20614 +       for (;;) {
20615 +               thread_suspend();
20616 +       }
20617 +}
20618 +
20619 +/*
20620 + * address_is_valid()
20621 + *     check if an address is valid -- (for read access)
20622 + */
20623 +static bool address_is_valid(const void *address)
20624 +{
20625 +       int addr = (int)address;
20626 +       unsigned long socm, eocm, sdram, edram;
20627 +
20628 +       if (addr & 3)
20629 +               return false;
20630 +
20631 +       processor_ocm(&socm, &eocm);
20632 +       processor_dram(&sdram, &edram);
20633 +       if (addr >= socm && addr < eocm)
20634 +               return true;
20635 +
20636 +       if (addr >= sdram && addr < edram)
20637 +               return true;
20638 +
20639 +       return false;
20640 +}
20641 +
20642 +/*
20643 + * vma_path_name_is_valid()
20644 + *     check if path_name of a vma is a valid string
20645 + */
20646 +static bool vma_path_name_is_valid(const char *str)
20647 +{
20648 +#define MAX_NAME_LEN 256
20649 +       int i = 0;
20650 +       if (!address_is_valid(str))
20651 +               return false;
20652 +
20653 +       for (; i < MAX_NAME_LEN; i++, str++) {
20654 +               if (*str == '\0')
20655 +                       return true;
20656 +       }
20657 +
20658 +       return false;
20659 +}
20660 +
20661 +/*
20662 + * show_vmas()
20663 + *     show vma info of a process
20664 + */
20665 +void show_vmas(struct task_struct *task)
20666 +{
20667 +#ifdef CONFIG_DEBUG_VERBOSE
20668 +#define UBICOM32_MAX_VMA_COUNT 1024
20669 +
20670 +       struct vm_area_struct *vma;
20671 +       struct file *file;
20672 +       char *name = "";
20673 +       int flags, loop = 0;
20674 +
20675 +       printk(KERN_NOTICE "Start of vma list\n");
20676 +
20677 +       if (!address_is_valid(task) || !address_is_valid(task->mm))
20678 +               goto error;
20679 +
20680 +       vma = task->mm->mmap;
20681 +       while (vma) {
20682 +               if (!address_is_valid(vma))
20683 +                       goto error;
20684 +
20685 +               flags = vma->vm_flags;
20686 +               file = vma->vm_file;
20687 +
20688 +               if (file) {
20689 +                       /* seems better to use dentry op here, but sanity check is easier this way */
20690 +                       if (!address_is_valid(file) || !address_is_valid(file->f_path.dentry) || !vma_path_name_is_valid(file->f_path.dentry->d_name.name))
20691 +                               goto error;
20692 +
20693 +                       name = (char *)file->f_path.dentry->d_name.name;
20694 +               }
20695 +
20696 +               /* Similar to /proc/pid/maps format */
20697 +               printk(KERN_NOTICE "%08lx-%08lx %c%c%c%c %08lx %s\n",
20698 +                       vma->vm_start,
20699 +                       vma->vm_end,
20700 +                       flags & VM_READ ? 'r' : '-',
20701 +                       flags & VM_WRITE ? 'w' : '-',
20702 +                       flags & VM_EXEC ? 'x' : '-',
20703 +                       flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
20704 +                       vma->vm_pgoff << PAGE_SHIFT,
20705 +                       name);
20706 +
20707 +               vma = vma->vm_next;
20708 +
20709 +               if (loop++ > UBICOM32_MAX_VMA_COUNT)
20710 +                       goto error;
20711 +       }
20712 +
20713 +       printk(KERN_NOTICE "End of vma list\n");
20714 +       return;
20715 +
20716 +error:
20717 +       printk(KERN_NOTICE "\nCorrupted vma list, abort!\n");
20718 +#endif
20719 +}
20720 +
20721 +/*
20722 + * show_regs()
20723 + *     Print out all of the registers.
20724 + */
20725 +void show_regs(struct pt_regs *regs)
20726 +{
20727 +       unsigned int i;
20728 +       unsigned int en, lo, hi;
20729 +
20730 +       printk(KERN_NOTICE "regs: %p, tid: %d\n",
20731 +               (void *)regs,
20732 +               thread_get_self());
20733 +
20734 +       printk(KERN_NOTICE "pc: %08x, previous_pc: %08x\n\n",
20735 +               (unsigned int)regs->pc,
20736 +               (unsigned int)regs->previous_pc);
20737 +
20738 +       printk(KERN_NOTICE "Data registers\n");
20739 +       for (i = 0; i < 16; i++) {
20740 +               printk("D%02d: %08x, ", i, (unsigned int)regs->dn[i]);
20741 +               if ((i % 4) == 3) {
20742 +                       printk("\n");
20743 +               }
20744 +       }
20745 +       printk("\n");
20746 +
20747 +       printk(KERN_NOTICE "Address registers\n");
20748 +       for (i = 0; i < 8; i++) {
20749 +               printk("A%02d: %08x, ", i, (unsigned int)regs->an[i]);
20750 +               if ((i % 4) == 3) {
20751 +                       printk("\n");
20752 +               }
20753 +       }
20754 +       printk("\n");
20755 +
20756 +       printk(KERN_NOTICE "acc0: %08x-%08x, acc1: %08x-%08x\n",
20757 +               (unsigned int)regs->acc0[1],
20758 +               (unsigned int)regs->acc0[0],
20759 +               (unsigned int)regs->acc1[1],
20760 +               (unsigned int)regs->acc1[0]);
20761 +
20762 +       printk(KERN_NOTICE "mac_rc16: %08x, source3: %08x\n",
20763 +               (unsigned int)regs->mac_rc16,
20764 +               (unsigned int)regs->source3);
20765 +
20766 +       printk(KERN_NOTICE "inst_cnt: %08x, csr: %08x\n",
20767 +               (unsigned int)regs->inst_cnt,
20768 +               (unsigned int)regs->csr);
20769 +
20770 +       printk(KERN_NOTICE "int_mask0: %08x, int_mask1: %08x\n",
20771 +               (unsigned int)regs->int_mask0,
20772 +               (unsigned int)regs->int_mask1);
20773 +
20774 +       /*
20775 +        * Dump range registers
20776 +        */
20777 +       DUMP_RANGE_REGISTER("I", "0");
20778 +       DUMP_RANGE_REGISTER("I", "1");
20779 +       DUMP_RANGE_REGISTER("I", "2");
20780 +       DUMP_RANGE_REGISTER("I", "3");
20781 +       DUMP_RANGE_REGISTER("D", "0");
20782 +       DUMP_RANGE_REGISTER("D", "1");
20783 +       DUMP_RANGE_REGISTER("D", "2");
20784 +       DUMP_RANGE_REGISTER("D", "3");
20785 +       DUMP_RANGE_REGISTER("D", "4");
20786 +
20787 +       printk(KERN_NOTICE "frame_type: %d, nesting_level: %d, thread_type %d\n\n",
20788 +               (int)regs->frame_type,
20789 +               (int)regs->nesting_level,
20790 +               (int)regs->thread_type);
20791 +}
20792 +
20793 +/*
20794 + * kernel_thread_helper()
20795 + *     On execution d0 will be 0, d1 will be the argument to be passed to the
20796 + *     kernel function.  d2 contains the kernel function that needs to get
20797 + *     called. d3 will contain address to do_exit which need to get moved
20798 + *     into a5. On return from fork the child thread d0 will be 0. We call
20799 + *     this dummy function which in turn loads the argument
20800 + */
20801 +asmlinkage void kernel_thread_helper(void);
20802 +
20803 +/*
20804 + * kernel_thread()
20805 + *     Create a kernel thread
20806 + */
20807 +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
20808 +{
20809 +       struct pt_regs regs;
20810 +
20811 +       memset(&regs, 0, sizeof(regs));
20812 +
20813 +       regs.dn[1] = (unsigned long)arg;
20814 +       regs.dn[2] = (unsigned long)fn;
20815 +       regs.dn[3] = (unsigned long)do_exit;
20816 +       regs.an[5] = (unsigned long)kernel_thread_helper;
20817 +       regs.pc = (unsigned long)kernel_thread_helper;
20818 +       regs.nesting_level = 0;
20819 +       regs.thread_type = KERNEL_THREAD;
20820 +
20821 +       return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
20822 +                      0, &regs, 0, NULL, NULL);
20823 +}
20824 +EXPORT_SYMBOL(kernel_thread);
20825 +
20826 +/*
20827 + * flush_thread()
20828 + *     XXX todo
20829 + */
20830 +void flush_thread(void)
20831 +{
20832 +       /* XXX todo */
20833 +}
20834 +
20835 +/*
20836 + * sys_fork()
20837 + *     Not implemented on no-mmu.
20838 + */
20839 +asmlinkage int sys_fork(struct pt_regs *regs)
20840 +{
20841 +       /* fork almost works, enough to trick you into looking elsewhere :-( */
20842 +       return -EINVAL;
20843 +}
20844 +
20845 +/*
20846 + * sys_vfork()
20847 + *     By the time we get here, the non-volatile registers have also been saved
20848 + *     on the stack. We do some ugly pointer stuff here.. (see also copy_thread
20849 + *     which does context copy).
20850 + */
20851 +asmlinkage int sys_vfork(struct pt_regs *regs)
20852 +{
20853 +       unsigned long old_sp = regs->an[7];
20854 +       unsigned long old_a5 = regs->an[5];
20855 +       unsigned long old_return_address;
20856 +       long do_fork_return;
20857 +
20858 +       /*
20859 +        * Read the old retrun address from the stack.
20860 +        */
20861 +       if (copy_from_user(&old_return_address,
20862 +                          (void *)old_sp, sizeof(unsigned long))) {
20863 +               force_sig(SIGSEGV, current);
20864 +               return 0;
20865 +       }
20866 +
20867 +       /*
20868 +        * Pop the vfork call frame by setting a5 and pc to the old_return
20869 +        * address and incrementing the stack pointer by 4.
20870 +        */
20871 +       regs->an[5] = old_return_address;
20872 +       regs->pc = old_return_address;
20873 +       regs->an[7] += 4;
20874 +
20875 +       do_fork_return = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
20876 +                                regs->an[7], regs, 0, NULL, NULL);
20877 +
20878 +       /*
20879 +        * Now we have to test if the return code is an error. If it is an error
20880 +        * then restore the frame and we will execute error processing in user
20881 +        * space. Other wise the child and the parent will return to the correct
20882 +        * places.
20883 +        */
20884 +       if ((unsigned long)(do_fork_return) >= (unsigned long)(-125)) {
20885 +               /*
20886 +                * Error case. We need to restore the frame.
20887 +                */
20888 +               regs->an[5] = old_a5;
20889 +               regs->pc = old_a5;
20890 +               regs->an[7] = old_sp;
20891 +       }
20892 +
20893 +       return do_fork_return;
20894 +}
20895 +
20896 +/*
20897 + * sys_clone()
20898 + *     creates a child thread.
20899 + */
20900 +asmlinkage int sys_clone(unsigned long clone_flags,
20901 +                        unsigned long newsp,
20902 +                        struct pt_regs *regs)
20903 +{
20904 +       if (!newsp)
20905 +               newsp = regs->an[7];
20906 +       return do_fork(clone_flags, newsp, regs, 0,
20907 +                      NULL, NULL);
20908 +}
20909 +
20910 +/*
20911 + * copy_thread()
20912 + *     low level thread copy, only used by do_fork in kernel/fork.c
20913 + */
20914 +int copy_thread(unsigned long clone_flags,
20915 +               unsigned long usp, unsigned long topstk,
20916 +               struct task_struct *p, struct pt_regs *regs)
20917 +
20918 +{
20919 +       struct pt_regs *childregs;
20920 +
20921 +       childregs = (struct pt_regs *)
20922 +               (task_stack_page(p) + THREAD_SIZE - 8) - 1;
20923 +
20924 +       *childregs = *regs;
20925 +
20926 +       /*
20927 +        * Set return value for child to be 0.
20928 +        */
20929 +       childregs->dn[0] = 0;
20930 +
20931 +       if (usp)
20932 +               childregs->an[7] = usp;
20933 +       else
20934 +               childregs->an[7] = (unsigned long)task_stack_page(p) +
20935 +                       THREAD_SIZE - 8;
20936 +
20937 +       /*
20938 +        * Set up the switch_to frame to return to "ret_from_fork"
20939 +        */
20940 +       p->thread.a5 = (unsigned long)ret_from_fork;
20941 +       p->thread.sp = (unsigned long)childregs;
20942 +
20943 +       return 0;
20944 +}
20945 +
20946 +/*
20947 + * sys_execve()
20948 + *     executes a new program.
20949 + */
20950 +asmlinkage int sys_execve(char *name, char **argv,
20951 +                         char **envp, struct pt_regs *regs)
20952 +{
20953 +       int error;
20954 +       char *filename;
20955 +
20956 +       lock_kernel();
20957 +       filename = getname(name);
20958 +       error = PTR_ERR(filename);
20959 +       if (IS_ERR(filename))
20960 +               goto out;
20961 +       error = do_execve(filename, argv, envp, regs);
20962 +       putname(filename);
20963 +       asm ("       .global sys_execve_complete\n"
20964 +            "       sys_execve_complete:");
20965 +out:
20966 +       unlock_kernel();
20967 +       return error;
20968 +}
20969 +
20970 +/*
20971 + * Return saved PC of a blocked thread.
20972 + */
20973 +unsigned long thread_saved_pc(struct task_struct *tsk)
20974 +{
20975 +       return tsk->thread.a5;
20976 +}
20977 +
20978 +
20979 +unsigned long get_wchan(struct task_struct *p)
20980 +{
20981 +       unsigned long pc;
20982 +
20983 +       /*
20984 +        * If we don't have a process, or it is not the current
20985 +        * one or not RUNNING, it makes no sense to ask for a
20986 +        * wchan.
20987 +        */
20988 +       if (!p || p == current || p->state == TASK_RUNNING)
20989 +               return 0;
20990 +
20991 +       /*
20992 +        * TODO: If the process is in the middle of schedule, we
20993 +        * are supposed to do something different but for now we
20994 +        * will return the same thing in both situations.
20995 +        */
20996 +       pc = thread_saved_pc(p);
20997 +       if (in_sched_functions(pc))
20998 +               return pc;
20999 +       return pc;
21000 +}
21001 +
21002 +
21003 +/*
21004 + * Infrequently used interface to dump task registers to core files.
21005 + */
21006 +int dump_task_regs(struct task_struct *task, elf_gregset_t *elfregs)
21007 +{
21008 +       struct pt_regs *regs = task_pt_regs(task);
21009 +       *(struct pt_regs *)elfregs = *regs;
21010 +
21011 +       return 1;
21012 +}
21013 +
21014 +/*
21015 + * __switch_to is the function that implements the contex save and
21016 + * switch within the kernel. Since this is a function call very few
21017 + * registers have to be saved to pull this off. d0 holds prev and we
21018 + * want to preserve it. prev_switch is a pointer to task->thread
21019 + * structure. This is where we will save the register state. next_switch
21020 + * is pointer to the next task's thread structure that holds the
21021 + * registers.
21022 + */
21023 +asmlinkage void *__switch_to(struct task_struct *prev,
21024 +                            struct thread_struct *prev_switch,
21025 +                            struct thread_struct *next_switch)
21026 +       __attribute__((naked));
21027 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/processor.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/processor.c
21028 --- linux-2.6.30.10/arch/ubicom32/kernel/processor.c    1970-01-01 02:00:00.000000000 +0200
21029 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/processor.c        2009-12-11 11:45:11.000000000 +0200
21030 @@ -0,0 +1,348 @@
21031 +/*
21032 + * arch/ubicom32/kernel/processor.c
21033 + *   Ubicom32 architecture processor info implementation.
21034 + *
21035 + * (C) Copyright 2009, Ubicom, Inc.
21036 + *
21037 + * This file is part of the Ubicom32 Linux Kernel Port.
21038 + *
21039 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21040 + * it and/or modify it under the terms of the GNU General Public License
21041 + * as published by the Free Software Foundation, either version 2 of the
21042 + * License, or (at your option) any later version.
21043 + *
21044 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21045 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21046 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21047 + * the GNU General Public License for more details.
21048 + *
21049 + * You should have received a copy of the GNU General Public License
21050 + * along with the Ubicom32 Linux Kernel Port.  If not,
21051 + * see <http://www.gnu.org/licenses/>.
21052 + *
21053 + * Ubicom32 implementation derived from (with many thanks):
21054 + *   arch/m68knommu
21055 + *   arch/blackfin
21056 + *   arch/parisc
21057 + */
21058 +#include <linux/module.h>
21059 +#include <linux/kernel.h>
21060 +#include <linux/init.h>
21061 +#include <linux/sched.h>
21062 +#include <linux/interrupt.h>
21063 +#include <linux/irq.h>
21064 +#include <linux/profile.h>
21065 +#include <linux/clocksource.h>
21066 +#include <linux/types.h>
21067 +#include <linux/seq_file.h>
21068 +#include <linux/delay.h>
21069 +#include <linux/cpu.h>
21070 +#include <asm/devtree.h>
21071 +#include <asm/processor.h>
21072 +#include <asm/cpu.h>
21073 +#include <asm/ocm_size.h>
21074 +
21075 +struct procnode {
21076 +       struct devtree_node dn;
21077 +       unsigned int threads;
21078 +       unsigned int timers;
21079 +       unsigned int frequency;
21080 +       unsigned int ddr_frequency;
21081 +       unsigned int interrupt0;
21082 +       unsigned int interrupt1;
21083 +       void *socm;
21084 +       void *eocm;
21085 +       void *sdram;
21086 +       void *edram;
21087 +       unsigned int arch_version;
21088 +       void *os_syscall_begin;
21089 +       void *os_syscall_end;
21090 +};
21091 +
21092 +struct procnode *pn;
21093 +
21094 +/*
21095 + * show_processorinfo()
21096 + *     Print the actual processor information.
21097 + */
21098 +static void show_processorinfo(struct seq_file *m)
21099 +{
21100 +       char *cpu, *mmu, *fpu;
21101 +       unsigned int clockfreq;
21102 +       unsigned int chipid;
21103 +
21104 +       cpu = CPU;
21105 +       mmu = "none";
21106 +       fpu = "none";
21107 +
21108 +       asm volatile (
21109 +       "move.4         %0, CHIP_ID     \n\t"
21110 +       : "=r" (chipid)
21111 +       );
21112 +
21113 +       /*
21114 +        * General Processor Information.
21115 +        */
21116 +       seq_printf(m, "Vendor:\t\t%s\n", "Ubicom");
21117 +       seq_printf(m, "CPU:\t\t%s\n", cpu);
21118 +       seq_printf(m, "MMU:\t\t%s\n", mmu);
21119 +       seq_printf(m, "FPU:\t\t%s\n", fpu);
21120 +       seq_printf(m, "Arch:\t\t%hx\n", chipid >> 16);
21121 +       seq_printf(m, "Rev:\t\t%hx\n", (chipid & 0xffff));
21122 +
21123 +       /*
21124 +        * Now compute the clock frequency in Mhz.
21125 +        */
21126 +       clockfreq = processor_frequency();
21127 +       seq_printf(m, "Clock Freq:\t%u.0 MHz\n",
21128 +                  clockfreq / 1000000);
21129 +       seq_printf(m, "DDR Freq:\t%u.0 MHz\n",
21130 +                  pn ? pn->ddr_frequency / 1000000 : 0);
21131 +       seq_printf(m, "BogoMips:\t%lu.%02lu\n",
21132 +                  (loops_per_jiffy * HZ) / 500000,
21133 +                  ((loops_per_jiffy * HZ) / 5000) % 100);
21134 +       seq_printf(m, "Calibration:\t%lu loops\n", (loops_per_jiffy * HZ));
21135 +}
21136 +
21137 +/*
21138 + * show_cpuinfo()
21139 + *     Get CPU information for use by the procfs.
21140 + */
21141 +static int show_cpuinfo(struct seq_file *m, void *v)
21142 +{
21143 +       unsigned long n = (unsigned long)v - 1;
21144 +
21145 +#if defined(CONFIG_SMP)
21146 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, n);
21147 +#endif
21148 +
21149 +       /*
21150 +        * Print the general processor information on the first
21151 +        * call.
21152 +        */
21153 +       if (n == 0) {
21154 +               show_processorinfo(m);
21155 +       }
21156 +
21157 +#if defined(CONFIG_SMP)
21158 +       /*
21159 +        * For each hwthread, print if this hwthread is running Linux
21160 +        * or is an I/O thread.
21161 +        */
21162 +       if (cpu_isset(n, cpu_online_map)) {
21163 +               seq_printf(m, "cpu[%02lu]:\tthread id - %lu\n", n, p->tid);
21164 +       } else {
21165 +               seq_printf(m, "cpu[%02lu]:\toff-line\n", n);
21166 +       }
21167 +#endif
21168 +       return 0;
21169 +
21170 +}
21171 +
21172 +static void *c_start(struct seq_file *m, loff_t *pos)
21173 +{
21174 +       unsigned long i = *pos;
21175 +
21176 +       return i < NR_CPUS ? (void *)(i + 1) : NULL;
21177 +}
21178 +
21179 +static void *c_next(struct seq_file *m, void *v, loff_t *pos)
21180 +{
21181 +       ++*pos;
21182 +       return c_start(m, pos);
21183 +}
21184 +
21185 +static void c_stop(struct seq_file *m, void *v)
21186 +{
21187 +}
21188 +
21189 +const struct seq_operations cpuinfo_op = {
21190 +       .start  = c_start,
21191 +       .next   = c_next,
21192 +       .stop   = c_stop,
21193 +       .show   = show_cpuinfo,
21194 +};
21195 +
21196 +/*
21197 + * processor_timers()
21198 + *     Returns the timers available to Linux.
21199 + */
21200 +unsigned int processor_timers(void)
21201 +{
21202 +       if (!pn) {
21203 +               return 0;
21204 +       }
21205 +       return pn->timers;
21206 +}
21207 +
21208 +/*
21209 + * processor_threads()
21210 + *     Returns the threads available to Linux.
21211 + */
21212 +unsigned int processor_threads(void)
21213 +{
21214 +       if (!pn) {
21215 +               return 0;
21216 +       }
21217 +       return pn->threads;
21218 +}
21219 +
21220 +/*
21221 + * processor_frequency()
21222 + *     Returns the frequency of the system clock.
21223 + */
21224 +unsigned int processor_frequency(void)
21225 +{
21226 +       if (!pn) {
21227 +               return 0;
21228 +       }
21229 +       return pn->frequency;
21230 +}
21231 +EXPORT_SYMBOL(processor_frequency);
21232 +
21233 +/*
21234 + * processor_interrupts()
21235 + *     Return the interrupts that are setup at boot time.
21236 + */
21237 +int processor_interrupts(unsigned int *int0, unsigned int *int1)
21238 +{
21239 +       if (!pn) {
21240 +               return -EFAULT;
21241 +       }
21242 +
21243 +       if (int0) {
21244 +               *int0 = pn->interrupt0;
21245 +       }
21246 +
21247 +       if (int1) {
21248 +               *int1 = pn->interrupt1;
21249 +       }
21250 +       return 0;
21251 +}
21252 +
21253 +/*
21254 + * processor_ocm()
21255 + *     Returns the start and end of OCM available to Linux.
21256 + */
21257 +void processor_ocm(unsigned long *socm, unsigned long *eocm)
21258 +{
21259 +       *socm = (unsigned long)pn->socm;
21260 +       *eocm = (unsigned long)pn->eocm;
21261 +}
21262 +
21263 +/*
21264 + * processor_dram()
21265 + *     Returns the start and end of dram available to Linux.
21266 + */
21267 +void processor_dram(unsigned long *sdram, unsigned long *edram)
21268 +{
21269 +       *sdram = (unsigned long)pn->sdram;
21270 +       *edram = (unsigned long)pn->edram;
21271 +}
21272 +
21273 +/*
21274 + * processor_validate_failed()
21275 + *     Returns the dram available to Linux.
21276 + */
21277 +static noinline void processor_validate_failed(void)
21278 +{
21279 +       while (1)
21280 +               THREAD_STALL;
21281 +}
21282 +
21283 +/*
21284 + * processor_validate()
21285 + *     Validates the procnode against limitations of this link/built.
21286 + */
21287 +static void processor_validate(void)
21288 +{
21289 +       void *dram_start = (void *)(KERNELSTART);
21290 +       void *dram_end   = (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE);
21291 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21292 +       void *ocm_code_start = (void *)(OCMSTART + APP_OCM_CODE_SIZE);
21293 +       void *ocm_data_end   = (void *)(OCMEND   - APP_OCM_DATA_SIZE);
21294 +#endif
21295 +       extern void __os_syscall_begin;
21296 +       extern void __os_syscall_end;
21297 +       int proc_node_valid = 1;
21298 +
21299 +       if (!pn) {
21300 +               printk(KERN_ERR "ERROR: processor node not found\n");
21301 +               goto error;
21302 +       }
21303 +
21304 +
21305 +       if (dram_start < pn->sdram || dram_end > pn->edram) {
21306 +               printk(KERN_ERR "ERROR: processor dram mismatch %p-%p "
21307 +                      "available but we are expecting %p-%p\n",
21308 +                      pn->sdram, pn->edram, dram_start, dram_end);
21309 +               proc_node_valid = 0;
21310 +       } else {
21311 +               printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21312 +                      pn->sdram, pn->edram, dram_start, dram_end);
21313 +       }
21314 +       if (&__os_syscall_begin < pn->os_syscall_begin ||
21315 +           &__os_syscall_end > pn->os_syscall_end) {
21316 +               printk(KERN_ERR "ERROR: processor syscall area mismatch "
21317 +                      "%p-%p available but we are expecting %p-%p\n",
21318 +                      pn->os_syscall_begin, pn->os_syscall_end,
21319 +                      &__os_syscall_begin, &__os_syscall_end);
21320 +               proc_node_valid = 0;
21321 +       } else {
21322 +               printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21323 +                      pn->sdram, pn->edram, dram_start, dram_end);
21324 +       }
21325 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21326 +       if (ocm_code_start < pn->socm ||  ocm_data_end > pn->eocm) {
21327 +               printk(KERN_ERR "ERROR: processor ocm mismatch %p-%p "
21328 +                      "available but we are expecting %p-%p\n",
21329 +                      pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21330 +               proc_node_valid = 0;
21331 +       } else {
21332 +               printk(KERN_INFO "processor ocm %p-%p, expecting %p-%p\n",
21333 +                      pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21334 +
21335 +       }
21336 +#endif
21337 +
21338 +       if (UBICOM32_ARCH_VERSION != pn->arch_version) {
21339 +               printk(KERN_ERR "ERROR: processor arch mismatch, kernel"
21340 +                      "compiled for %d found %d\n",
21341 +                      UBICOM32_ARCH_VERSION, pn->arch_version);
21342 +               proc_node_valid = 0;
21343 +       }
21344 +
21345 +       if (proc_node_valid)
21346 +               return;
21347 +error:
21348 +       processor_validate_failed();
21349 +}
21350 +
21351 +void __init processor_init(void)
21352 +{
21353 +       /*
21354 +        * If we do not have a trap node in the device tree, we leave the fault
21355 +        * handling to the underlying hardware.
21356 +        */
21357 +       pn = (struct procnode *)devtree_find_node("processor");
21358 +
21359 +       processor_validate();
21360 +
21361 +       /*
21362 +        * If necessary correct the initial range registers to cover the
21363 +        * complete physical space
21364 +        */
21365 +       if (pn->edram > (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE)) {
21366 +               printk(KERN_INFO "updating range registers for expanded dram\n");
21367 +               asm volatile (
21368 +                       "       move.4 D_RANGE1_HI, %0          \t\n"
21369 +                       "       move.4 I_RANGE0_HI, %0          \t\n"
21370 +#ifdef CONFIG_PROTECT_KERNEL
21371 +                       "       move.4 D_RANGE2_HI, %0          \t\n"
21372 +                       "       move.4 I_RANGE2_HI, %0          \t\n"
21373 +#endif
21374 +               : : "a"((unsigned long)pn->edram - 4)
21375 +                       );
21376 +       }
21377 +
21378 +}
21379 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ptrace.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/ptrace.c
21380 --- linux-2.6.30.10/arch/ubicom32/kernel/ptrace.c       1970-01-01 02:00:00.000000000 +0200
21381 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ptrace.c   2009-12-11 11:45:11.000000000 +0200
21382 @@ -0,0 +1,275 @@
21383 +/*
21384 + * arch/ubicom32/kernel/ptrace.c
21385 + *   Ubicom32 architecture ptrace implementation.
21386 + *
21387 + * (C) Copyright 2009, Ubicom, Inc.
21388 + * (C) 1994 by Hamish Macdonald
21389 + * Taken from linux/kernel/ptrace.c and modified for M680x0.
21390 + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
21391 + *
21392 + * This file is part of the Ubicom32 Linux Kernel Port.
21393 + *
21394 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21395 + * it and/or modify it under the terms of the GNU General Public License
21396 + * as published by the Free Software Foundation, either version 2 of the
21397 + * License, or (at your option) any later version.
21398 + *
21399 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21400 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21401 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21402 + * the GNU General Public License for more details.
21403 + *
21404 + * You should have received a copy of the GNU General Public License
21405 + * along with the Ubicom32 Linux Kernel Port.  If not,
21406 + * see <http://www.gnu.org/licenses/>.
21407 + *
21408 + * Ubicom32 implementation derived from (with many thanks):
21409 + *   arch/m68knommu
21410 + *   arch/blackfin
21411 + *   arch/parisc
21412 + */
21413 +
21414 +#include <linux/module.h>
21415 +#include <linux/kernel.h>
21416 +#include <linux/sched.h>
21417 +#include <linux/mm.h>
21418 +#include <linux/smp.h>
21419 +#include <linux/errno.h>
21420 +#include <linux/ptrace.h>
21421 +#include <linux/user.h>
21422 +#include <linux/signal.h>
21423 +#include <linux/uaccess.h>
21424 +
21425 +#include <asm/page.h>
21426 +#include <asm/pgtable.h>
21427 +#include <asm/system.h>
21428 +#include <asm/cacheflush.h>
21429 +#include <asm/processor.h>
21430 +
21431 +/*
21432 + * ptrace_getregs()
21433 + *
21434 + *     Get all user integer registers.
21435 + */
21436 +static inline int ptrace_getregs(struct task_struct *task, void __user *uregs)
21437 +{
21438 +       struct pt_regs *regs = task_pt_regs(task);
21439 +       return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
21440 +}
21441 +
21442 +/*
21443 + * ptrace_get_reg()
21444 + *
21445 + *     Get contents of register REGNO in task TASK.
21446 + */
21447 +static unsigned long ptrace_get_reg(struct task_struct *task, int regno)
21448 +{
21449 +       if (regno < sizeof(struct pt_regs)) {
21450 +               struct pt_regs *pt_regs = task_pt_regs(task);
21451 +               return *(unsigned long *)((long) pt_regs + regno);
21452 +       }
21453 +
21454 +       return -EIO;
21455 +}
21456 +
21457 +/*
21458 + * ptrace_put_reg()
21459 + *     Write contents of register REGNO in task TASK.
21460 + */
21461 +static int ptrace_put_reg(struct task_struct *task, int regno,
21462 +                         unsigned long data)
21463 +{
21464 +       if (regno <= sizeof(struct pt_regs) && regno != PT_FRAME_TYPE) {
21465 +               struct pt_regs *pt_regs = task_pt_regs(task);
21466 +               *(unsigned long *)((long) pt_regs + regno) = data;
21467 +               return 0;
21468 +       }
21469 +       return -EIO;
21470 +}
21471 +
21472 +/*
21473 + * ptrace_disable_single_step()
21474 + *     Disable Single Step
21475 + */
21476 +static int ptrace_disable_single_step(struct task_struct *task)
21477 +{
21478 +       /*
21479 +        * Single Step not yet implemented, so must always be disabled
21480 +        */
21481 +       return 0;
21482 +}
21483 +
21484 +/*
21485 + * ptrace_disable()
21486 + *     Make sure the single step bit is not set.
21487 + * Called by kernel/ptrace.c when detaching..
21488 + */
21489 +void ptrace_disable(struct task_struct *child)
21490 +{
21491 +       ptrace_disable_single_step(child);
21492 +}
21493 +
21494 +/*
21495 + * arch_ptrace()
21496 + *     architecture specific ptrace routine.
21497 + */
21498 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
21499 +{
21500 +       int ret;
21501 +       switch (request) {
21502 +       /* when I and D space are separate, these will need to be fixed. */
21503 +       case PTRACE_PEEKTEXT: /* read word at location addr. */
21504 +       case PTRACE_PEEKDATA:
21505 +               ret = generic_ptrace_peekdata(child, addr, data);
21506 +               break;
21507 +
21508 +       /* read the word at location addr in the USER area. */
21509 +       case PTRACE_PEEKUSR: {
21510 +               unsigned long tmp;
21511 +
21512 +               ret = -EIO;
21513 +               if (((unsigned long) addr > PT_INTERP_FDPIC_LOADMAP)
21514 +                   || (addr & 3))
21515 +                       break;
21516 +
21517 +               tmp = 0;  /* Default return condition */
21518 +
21519 +               ret = -EIO;
21520 +               if (addr < sizeof(struct pt_regs)) {
21521 +                       tmp = ptrace_get_reg(child, addr);
21522 +               } else if (addr == PT_TEXT_ADDR) {
21523 +                       tmp = child->mm->start_code;
21524 +               } else if (addr == PT_TEXT_END_ADDR) {
21525 +                       tmp = child->mm->end_code;
21526 +               } else if (addr == PT_DATA_ADDR) {
21527 +                       tmp = child->mm->start_data;
21528 +               } else if (addr == PT_EXEC_FDPIC_LOADMAP) {
21529 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21530 +                       tmp = child->mm->context.exec_fdpic_loadmap;
21531 +#endif
21532 +               } else if (addr == PT_INTERP_FDPIC_LOADMAP) {
21533 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21534 +                       tmp = child->mm->context.interp_fdpic_loadmap;
21535 +#endif
21536 +               } else {
21537 +                       break;
21538 +               }
21539 +
21540 +               ret = put_user(tmp, (unsigned long *)data);
21541 +               break;
21542 +       }
21543 +
21544 +       case PTRACE_POKETEXT: /* write the word at location addr. */
21545 +       case PTRACE_POKEDATA:
21546 +               ret = generic_ptrace_pokedata(child, addr, data);
21547 +
21548 +               /*
21549 +                * If we just changed some code so we need to
21550 +                * correct the caches
21551 +                */
21552 +               if (request == PTRACE_POKETEXT && ret == 0) {
21553 +                       flush_icache_range(addr, addr + 4);
21554 +               }
21555 +               break;
21556 +
21557 +       case PTRACE_POKEUSR: /* write the word at location addr
21558 +                             * in the USER area */
21559 +               ret = -EIO;
21560 +
21561 +               if (((unsigned long) addr > PT_DATA_ADDR) || (addr & 3))
21562 +                       break;
21563 +
21564 +               if (addr < sizeof(struct pt_regs)) {
21565 +                       ret = ptrace_put_reg(child, addr, data);
21566 +               }
21567 +               break;
21568 +
21569 +       case PTRACE_SYSCALL: /* continue and stop at next (return from)
21570 +                             * syscall */
21571 +       case PTRACE_CONT: { /* restart after signal. */
21572 +
21573 +               ret = -EIO;
21574 +               if (!valid_signal(data))
21575 +                       break;
21576 +               if (request == PTRACE_SYSCALL)
21577 +                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21578 +               else
21579 +                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21580 +               child->exit_code = data;
21581 +               /* make sure the single step bit is not set. */
21582 +               ptrace_disable_single_step(child);
21583 +               wake_up_process(child);
21584 +               ret = 0;
21585 +               break;
21586 +       }
21587 +
21588 +       /*
21589 +        * make the child exit.  Best I can do is send it a sigkill.
21590 +        * perhaps it should be put in the status that it wants to exit.
21591 +        */
21592 +       case PTRACE_KILL: {
21593 +               ret = 0;
21594 +               if (child->exit_state == EXIT_ZOMBIE) /* already dead */
21595 +                       break;
21596 +               child->exit_code = SIGKILL;
21597 +               /* make sure the single step bit is not set. */
21598 +               ptrace_disable_single_step(child);
21599 +               wake_up_process(child);
21600 +               break;
21601 +       }
21602 +
21603 +       case PTRACE_DETACH:     /* detach a process that was attached. */
21604 +               ret = ptrace_detach(child, data);
21605 +               break;
21606 +
21607 +       case PTRACE_GETREGS:    /* Get all gp regs from the child. */
21608 +               ptrace_getregs(child, (unsigned long *)data);
21609 +               ret = 0;
21610 +               break;
21611 +
21612 +       case PTRACE_SETREGS: { /* Set all gp regs in the child. */
21613 +               int i;
21614 +               unsigned long tmp;
21615 +               int count = sizeof(struct pt_regs) / sizeof(unsigned long);
21616 +               for (i = 0; i < count; i++) {
21617 +                       if (get_user(tmp, (unsigned long *) data)) {
21618 +                               ret = -EFAULT;
21619 +                               break;
21620 +                       }
21621 +                       ptrace_put_reg(child, sizeof(unsigned long) * i, tmp);
21622 +                       data += sizeof(long);
21623 +               }
21624 +               ret = 0;
21625 +               break;
21626 +       }
21627 +
21628 +       default:
21629 +               return ptrace_request(child, request, addr, data);
21630 +               break;
21631 +       }
21632 +       return ret;
21633 +}
21634 +/*
21635 + * syscall_trace
21636 + *
21637 + * called by syscall enter/exit when the TIF_SYSCALL_TRACE bit is set.
21638 + */
21639 +asmlinkage void syscall_trace(void)
21640 +{
21641 +       struct task_struct *cur = current;
21642 +       if (!test_thread_flag(TIF_SYSCALL_TRACE))
21643 +               return;
21644 +       if (!(cur->ptrace & PT_PTRACED))
21645 +               return;
21646 +       ptrace_notify(SIGTRAP | ((cur->ptrace & PT_TRACESYSGOOD)
21647 +                                ? 0x80 : 0));
21648 +       /*
21649 +        * this isn't the same as continuing with a signal, but it will do
21650 +        * for normal use.  strace only continues with a signal if the
21651 +        * stopping signal is not SIGTRAP.  -brl
21652 +        */
21653 +       if (cur->exit_code) {
21654 +               send_sig(cur->exit_code, current, 1);
21655 +               current->exit_code = 0;
21656 +       }
21657 +}
21658 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/semaphore.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/semaphore.c
21659 --- linux-2.6.30.10/arch/ubicom32/kernel/semaphore.c    1970-01-01 02:00:00.000000000 +0200
21660 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/semaphore.c        2009-12-11 11:45:11.000000000 +0200
21661 @@ -0,0 +1,159 @@
21662 +/*
21663 + * arch/ubicom32/kernel/semaphore.c
21664 + *   Ubicom32 architecture semaphore implementation.
21665 + *
21666 + * (C) Copyright 2009, Ubicom, Inc.
21667 + *
21668 + * This file is part of the Ubicom32 Linux Kernel Port.
21669 + *
21670 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21671 + * it and/or modify it under the terms of the GNU General Public License
21672 + * as published by the Free Software Foundation, either version 2 of the
21673 + * License, or (at your option) any later version.
21674 + *
21675 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21676 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21677 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21678 + * the GNU General Public License for more details.
21679 + *
21680 + * You should have received a copy of the GNU General Public License
21681 + * along with the Ubicom32 Linux Kernel Port.  If not,
21682 + * see <http://www.gnu.org/licenses/>.
21683 + *
21684 + * Ubicom32 implementation derived from (with many thanks):
21685 + *   arch/m68knommu
21686 + *   arch/blackfin
21687 + *   arch/parisc
21688 + */
21689 +/*
21690 + *  Generic semaphore code. Buyer beware. Do your own
21691 + * specific changes in <asm/semaphore-helper.h>
21692 + */
21693 +
21694 +#include <linux/sched.h>
21695 +#include <linux/err.h>
21696 +#include <linux/init.h>
21697 +#include <asm/semaphore-helper.h>
21698 +
21699 +#ifndef CONFIG_RMW_INSNS
21700 +spinlock_t semaphore_wake_lock;
21701 +#endif
21702 +
21703 +/*
21704 + * Semaphores are implemented using a two-way counter:
21705 + * The "count" variable is decremented for each process
21706 + * that tries to sleep, while the "waking" variable is
21707 + * incremented when the "up()" code goes to wake up waiting
21708 + * processes.
21709 + *
21710 + * Notably, the inline "up()" and "down()" functions can
21711 + * efficiently test if they need to do any extra work (up
21712 + * needs to do something only if count was negative before
21713 + * the increment operation.
21714 + *
21715 + * waking_non_zero() (from asm/semaphore.h) must execute
21716 + * atomically.
21717 + *
21718 + * When __up() is called, the count was negative before
21719 + * incrementing it, and we need to wake up somebody.
21720 + *
21721 + * This routine adds one to the count of processes that need to
21722 + * wake up and exit.  ALL waiting processes actually wake up but
21723 + * only the one that gets to the "waking" field first will gate
21724 + * through and acquire the semaphore.  The others will go back
21725 + * to sleep.
21726 + *
21727 + * Note that these functions are only called when there is
21728 + * contention on the lock, and as such all this is the
21729 + * "non-critical" part of the whole semaphore business. The
21730 + * critical part is the inline stuff in <asm/semaphore.h>
21731 + * where we want to avoid any extra jumps and calls.
21732 + */
21733 +void __up(struct semaphore *sem)
21734 +{
21735 +       wake_one_more(sem);
21736 +       wake_up(&sem->wait);
21737 +}
21738 +
21739 +/*
21740 + * Perform the "down" function.  Return zero for semaphore acquired,
21741 + * return negative for signalled out of the function.
21742 + *
21743 + * If called from __down, the return is ignored and the wait loop is
21744 + * not interruptible.  This means that a task waiting on a semaphore
21745 + * using "down()" cannot be killed until someone does an "up()" on
21746 + * the semaphore.
21747 + *
21748 + * If called from __down_interruptible, the return value gets checked
21749 + * upon return.  If the return value is negative then the task continues
21750 + * with the negative value in the return register (it can be tested by
21751 + * the caller).
21752 + *
21753 + * Either form may be used in conjunction with "up()".
21754 + *
21755 + */
21756 +
21757 +
21758 +#define DOWN_HEAD(task_state)                                          \
21759 +                                                                       \
21760 +                                                                       \
21761 +       current->state = (task_state);                                  \
21762 +       add_wait_queue(&sem->wait, &wait);                              \
21763 +                                                                       \
21764 +       /*                                                              \
21765 +        * Ok, we're set up.  sem->count is known to be less than zero  \
21766 +        * so we must wait.                                             \
21767 +        *                                                              \
21768 +        * We can let go the lock for purposes of waiting.              \
21769 +        * We re-acquire it after awaking so as to protect              \
21770 +        * all semaphore operations.                                    \
21771 +        *                                                              \
21772 +        * If "up()" is called before we call waking_non_zero() then    \
21773 +        * we will catch it right away.  If it is called later then     \
21774 +        * we will have to go through a wakeup cycle to catch it.       \
21775 +        *                                                              \
21776 +        * Multiple waiters contend for the semaphore lock to see       \
21777 +        * who gets to gate through and who has to wait some more.      \
21778 +        */                                                             \
21779 +       for (;;) {
21780 +
21781 +#define DOWN_TAIL(task_state)                  \
21782 +               current->state = (task_state);  \
21783 +       }                                       \
21784 +       current->state = TASK_RUNNING;          \
21785 +       remove_wait_queue(&sem->wait, &wait);
21786 +
21787 +void __sched __down(struct semaphore *sem)
21788 +{
21789 +       DECLARE_WAITQUEUE(wait, current);
21790 +
21791 +       DOWN_HEAD(TASK_UNINTERRUPTIBLE)
21792 +       if (waking_non_zero(sem))
21793 +               break;
21794 +       schedule();
21795 +       DOWN_TAIL(TASK_UNINTERRUPTIBLE)
21796 +}
21797 +
21798 +int __sched __down_interruptible(struct semaphore *sem)
21799 +{
21800 +       DECLARE_WAITQUEUE(wait, current);
21801 +       int ret = 0;
21802 +
21803 +       DOWN_HEAD(TASK_INTERRUPTIBLE)
21804 +
21805 +       ret = waking_non_zero_interruptible(sem, current);
21806 +       if (ret) {
21807 +               if (ret == 1)
21808 +                       /* ret != 0 only if we get interrupted -arca */
21809 +                       ret = 0;
21810 +               break;
21811 +       }
21812 +       schedule();
21813 +       DOWN_TAIL(TASK_INTERRUPTIBLE)
21814 +       return ret;
21815 +}
21816 +
21817 +int __down_trylock(struct semaphore *sem)
21818 +{
21819 +       return waking_non_zero_trylock(sem);
21820 +}
21821 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/setup.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/setup.c
21822 --- linux-2.6.30.10/arch/ubicom32/kernel/setup.c        1970-01-01 02:00:00.000000000 +0200
21823 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/setup.c    2009-12-11 11:45:11.000000000 +0200
21824 @@ -0,0 +1,194 @@
21825 +/*
21826 + * arch/ubicom32/kernel/setup.c
21827 + *   Ubicom32 architecture-dependent parts of system setup.
21828 + *
21829 + * (C) Copyright 2009, Ubicom, Inc.
21830 + * Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com)
21831 + * Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org>
21832 + * Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
21833 + * Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
21834 + * Copyright (C) 1995       Hamish Macdonald
21835 + * Copyright (C) 2000       Lineo Inc. (www.lineo.com)
21836 + * Copyright (C) 2001      Lineo, Inc. <www.lineo.com>
21837 + * 68VZ328 Fixes/support    Evan Stawnyczy <e@lineo.ca>
21838 + *
21839 + * This file is part of the Ubicom32 Linux Kernel Port.
21840 + *
21841 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21842 + * it and/or modify it under the terms of the GNU General Public License
21843 + * as published by the Free Software Foundation, either version 2 of the
21844 + * License, or (at your option) any later version.
21845 + *
21846 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21847 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21848 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21849 + * the GNU General Public License for more details.
21850 + *
21851 + * You should have received a copy of the GNU General Public License
21852 + * along with the Ubicom32 Linux Kernel Port.  If not,
21853 + * see <http://www.gnu.org/licenses/>.
21854 + *
21855 + * Ubicom32 implementation derived from (with many thanks):
21856 + *   arch/m68knommu
21857 + *   arch/blackfin
21858 + *   arch/parisc
21859 + */
21860 +
21861 +#include <linux/kernel.h>
21862 +#include <linux/sched.h>
21863 +#include <linux/delay.h>
21864 +#include <linux/interrupt.h>
21865 +#include <linux/fb.h>
21866 +#include <linux/module.h>
21867 +#include <linux/console.h>
21868 +#include <linux/errno.h>
21869 +#include <linux/string.h>
21870 +#include <linux/bootmem.h>
21871 +#include <linux/seq_file.h>
21872 +#include <linux/init.h>
21873 +
21874 +#include <asm/devtree.h>
21875 +#include <asm/setup.h>
21876 +#include <asm/irq.h>
21877 +#include <asm/machdep.h>
21878 +#include <asm/pgtable.h>
21879 +#include <asm/pgalloc.h>
21880 +#include <asm/ubicom32-common.h>
21881 +#include <asm/processor.h>
21882 +#include <asm/bootargs.h>
21883 +#include <asm/thread.h>
21884 +
21885 +unsigned long memory_start;
21886 +EXPORT_SYMBOL(memory_start);
21887 +
21888 +unsigned long memory_end;
21889 +EXPORT_SYMBOL(memory_end);
21890 +
21891 +static char __initdata command_line[COMMAND_LINE_SIZE];
21892 +#ifdef CONFIG_CMDLINE_BOOL
21893 +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
21894 +#endif
21895 +
21896 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
21897 +
21898 +/*
21899 + * setup_arch()
21900 + *     Setup the architecture dependent portions of the system.
21901 + */
21902 +void __init setup_arch(char **cmdline_p)
21903 +{
21904 +       int bootmap_size;
21905 +       unsigned long ram_start;
21906 +
21907 +       processor_init();
21908 +       bootargs_init();
21909 +
21910 +       /*
21911 +        * Use the link for memory_start from the link and the processor
21912 +        * node for memory_end.
21913 +        */
21914 +       memory_start = PAGE_ALIGN(((unsigned long)&_end));
21915 +       processor_dram(&ram_start, &memory_end);
21916 +
21917 +       init_mm.start_code = (unsigned long) &_stext;
21918 +       init_mm.end_code = (unsigned long) &_etext;
21919 +       init_mm.end_data = (unsigned long) &_edata;
21920 +       init_mm.brk = (unsigned long) 0;
21921 +
21922 +       /*
21923 +        * bootexec copies the original default command line to end of memory.
21924 +        * u-boot can modify it there (i.e. to enable network boot) and the
21925 +        * kernel picks up the modified version.
21926 +        *
21927 +        * mainexec creates a `new default' command_line which is in the
21928 +        * bootargs devnode. It is updated on every firmware update but
21929 +        * not used at the moment.
21930 +        */
21931 +       strlcpy(boot_command_line, (char *)(memory_end - COMMAND_LINE_SIZE), COMMAND_LINE_SIZE);
21932 +
21933 +#ifdef CONFIG_CMDLINE_BOOL
21934 +#ifdef CONFIG_CMDLINE_OVERRIDE
21935 +       strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21936 +#else
21937 +       if (builtin_cmdline[0]) {
21938 +               /* append boot loader cmdline to builtin */
21939 +               strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
21940 +               strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
21941 +               strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21942 +       }
21943 +#endif
21944 +#endif
21945 +
21946 +       strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
21947 +       *cmdline_p = command_line;
21948 +
21949 +       parse_early_param();
21950 +
21951 +       printk(KERN_INFO "%s Processor, Ubicom, Inc. <www.ubicom.com>\n", CPU);
21952 +
21953 +#if defined(DEBUG)
21954 +       printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
21955 +               "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
21956 +               (int) &_sdata, (int) &_edata,
21957 +               (int) &_sbss, (int) &_ebss);
21958 +       printk(KERN_DEBUG "MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
21959 +               (int) &_ebss, (int) memory_start,
21960 +               (int) memory_start, (int) memory_end);
21961 +#endif
21962 +
21963 +#ifdef DEBUG
21964 +       if (strlen(*cmdline_p))
21965 +               printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
21966 +#endif
21967 +
21968 +#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
21969 +       conswitchp = &dummy_con;
21970 +#endif
21971 +
21972 +       /*
21973 +        * If we have a device tree, see if we have the nodes we need.
21974 +        */
21975 +       if (devtree) {
21976 +               devtree_print();
21977 +       }
21978 +
21979 +       /*
21980 +        * From the arm initialization comment:
21981 +        *
21982 +        * This doesn't seem to be used by the Linux memory manager any
21983 +        * more, but is used by ll_rw_block.  If we can get rid of it, we
21984 +        * also get rid of some of the stuff above as well.
21985 +        *
21986 +        * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
21987 +        * the system, not the maximum PFN.
21988 +        */
21989 +       max_pfn = max_low_pfn = (memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
21990 +
21991 +       /*
21992 +        * Give all the memory to the bootmap allocator, tell it to put the
21993 +        * boot mem_map at the start of memory.
21994 +        */
21995 +       bootmap_size = init_bootmem_node(
21996 +                       NODE_DATA(0),
21997 +                       memory_start >> PAGE_SHIFT,     /* map goes here */
21998 +                       PAGE_OFFSET >> PAGE_SHIFT,      /* 0 on coldfire */
21999 +                       memory_end >> PAGE_SHIFT);
22000 +       /*
22001 +        * Free the usable memory, we have to make sure we do not free
22002 +        * the bootmem bitmap so we then reserve it after freeing it :-)
22003 +        */
22004 +       free_bootmem(memory_start, memory_end - memory_start);
22005 +       reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
22006 +
22007 +       /*
22008 +        * Get kmalloc into gear.
22009 +        */
22010 +       paging_init();
22011 +
22012 +       /*
22013 +        * Fix up the thread_info structure, indicate this is a mainline Linux
22014 +        * thread and setup the sw_ksp().
22015 +        */
22016 +       sw_ksp[thread_get_self()] = (unsigned int) current_thread_info();
22017 +       thread_set_mainline(thread_get_self());
22018 +}
22019 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/signal.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/signal.c
22020 --- linux-2.6.30.10/arch/ubicom32/kernel/signal.c       1970-01-01 02:00:00.000000000 +0200
22021 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/signal.c   2009-12-11 11:45:11.000000000 +0200
22022 @@ -0,0 +1,458 @@
22023 +/*
22024 + * arch/ubicom32/kernel/signal.c
22025 + *   Ubicom32 architecture signal handling implementation.
22026 + *
22027 + * (C) Copyright 2009, Ubicom, Inc.
22028 + * Copyright (C) 1991, 1992  Linus Torvalds
22029 + * Linux/m68k support by Hamish Macdonald
22030 + * 68060 fixes by Jesper Skov
22031 + * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
22032 + * mathemu support by Roman Zippel
22033 + * ++roman (07/09/96): implemented signal stacks
22034 + *
22035 + * This file is part of the Ubicom32 Linux Kernel Port.
22036 + *
22037 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
22038 + * it and/or modify it under the terms of the GNU General Public License
22039 + * as published by the Free Software Foundation, either version 2 of the
22040 + * License, or (at your option) any later version.
22041 + *
22042 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
22043 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22044 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
22045 + * the GNU General Public License for more details.
22046 + *
22047 + * You should have received a copy of the GNU General Public License
22048 + * along with the Ubicom32 Linux Kernel Port.  If not,
22049 + * see <http://www.gnu.org/licenses/>.
22050 + *
22051 + * Ubicom32 implementation derived from (with many thanks):
22052 + *   arch/m68knommu
22053 + *   arch/blackfin
22054 + *   arch/parisc
22055 + *
22056 + * mathemu support by Roman Zippel
22057 + *  (Note: fpstate in the signal context is completely ignored for the emulator
22058 + *         and the internal floating point format is put on stack)
22059 + *
22060 + * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
22061 + * Atari :-) Current limitation: Only one sigstack can be active at one time.
22062 + * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
22063 + * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
22064 + * signal handlers!
22065 + */
22066 +
22067 +#include <linux/module.h>
22068 +#include <linux/sched.h>
22069 +#include <linux/mm.h>
22070 +#include <linux/kernel.h>
22071 +#include <linux/signal.h>
22072 +#include <linux/syscalls.h>
22073 +#include <linux/errno.h>
22074 +#include <linux/wait.h>
22075 +#include <linux/ptrace.h>
22076 +#include <linux/unistd.h>
22077 +#include <linux/stddef.h>
22078 +#include <linux/highuid.h>
22079 +#include <linux/tty.h>
22080 +#include <linux/personality.h>
22081 +#include <linux/binfmts.h>
22082 +
22083 +#include <asm/setup.h>
22084 +#include <asm/uaccess.h>
22085 +#include <asm/pgtable.h>
22086 +#include <asm/traps.h>
22087 +#include <asm/ucontext.h>
22088 +
22089 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
22090 +
22091 +/*
22092 + * asm signal return handlers.
22093 + */
22094 +void ret_from_user_signal(void);
22095 +void ret_from_user_rt_signal(void);
22096 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
22097 +
22098 +/*
22099 + * Common signal suspend implementation
22100 + */
22101 +static int signal_suspend(sigset_t *saveset, struct pt_regs *regs)
22102 +{
22103 +       regs->dn[0] = -EINTR;
22104 +       while (1) {
22105 +               current->state = TASK_INTERRUPTIBLE;
22106 +               schedule();
22107 +               if (!do_signal(saveset, regs)) {
22108 +                       continue;
22109 +               }
22110 +               /*
22111 +                * If the current frame type is a signal trampoline we are
22112 +                * actually going to call the signal handler so we return the
22113 +                * desired d0 as the return value.
22114 +                */
22115 +               if (regs->frame_type == UBICOM32_FRAME_TYPE_SIGTRAMP) {
22116 +                       return regs->dn[0];
22117 +               }
22118 +               return -EINTR;
22119 +       }
22120 +       /*
22121 +        * Should never get here
22122 +        */
22123 +       BUG();
22124 +       return 0;
22125 +}
22126 +
22127 +/*
22128 + * Atomically swap in the new signal mask, and wait for a signal.
22129 + */
22130 +asmlinkage int do_sigsuspend(struct pt_regs *regs)
22131 +{
22132 +       old_sigset_t mask = regs->dn[0];
22133 +       sigset_t saveset;
22134 +
22135 +       mask &= _BLOCKABLE;
22136 +       spin_lock_irq(&current->sighand->siglock);
22137 +       saveset = current->blocked;
22138 +       siginitset(&current->blocked, mask);
22139 +       recalc_sigpending();
22140 +       spin_unlock_irq(&current->sighand->siglock);
22141 +
22142 +       /*
22143 +        * Call common handler
22144 +        */
22145 +       return signal_suspend(&saveset, regs);
22146 +}
22147 +
22148 +asmlinkage int
22149 +do_rt_sigsuspend(struct pt_regs *regs)
22150 +{
22151 +       sigset_t *unewset = (sigset_t *)regs->dn[0];
22152 +       size_t sigsetsize = (size_t)regs->dn[1];
22153 +       sigset_t saveset, newset;
22154 +
22155 +       /* XXX: Don't preclude handling different sized sigset_t's.  */
22156 +       if (sigsetsize != sizeof(sigset_t))
22157 +               return -EINVAL;
22158 +
22159 +       if (copy_from_user(&newset, unewset, sizeof(newset)))
22160 +               return -EFAULT;
22161 +       sigdelsetmask(&newset, ~_BLOCKABLE);
22162 +
22163 +       spin_lock_irq(&current->sighand->siglock);
22164 +       saveset = current->blocked;
22165 +       current->blocked = newset;
22166 +       recalc_sigpending();
22167 +       spin_unlock_irq(&current->sighand->siglock);
22168 +
22169 +       /*
22170 +        * Call common handler
22171 +        */
22172 +       return signal_suspend(&saveset, regs);
22173 +}
22174 +
22175 +asmlinkage int
22176 +sys_sigaction(int sig, const struct old_sigaction *act,
22177 +             struct old_sigaction *oact)
22178 +{
22179 +       struct k_sigaction new_ka, old_ka;
22180 +       int ret;
22181 +
22182 +       if (act) {
22183 +               old_sigset_t mask;
22184 +               if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
22185 +                   __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
22186 +                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
22187 +                       return -EFAULT;
22188 +               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
22189 +               __get_user(mask, &act->sa_mask);
22190 +               siginitset(&new_ka.sa.sa_mask, mask);
22191 +       }
22192 +
22193 +       ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
22194 +
22195 +       if (!ret && oact) {
22196 +               if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
22197 +                   __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
22198 +                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
22199 +                       return -EFAULT;
22200 +               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
22201 +               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
22202 +       }
22203 +
22204 +       return ret;
22205 +}
22206 +
22207 +asmlinkage int
22208 +do_sys_sigaltstack(struct pt_regs *regs)
22209 +{
22210 +       const stack_t *uss = (stack_t *) regs->dn[0];
22211 +       stack_t *uoss = (stack_t *)regs->dn[1];
22212 +       return do_sigaltstack(uss, uoss, regs->an[7]);
22213 +}
22214 +
22215 +/*
22216 + * fdpic_func_descriptor describes sa_handler when the application is FDPIC
22217 + */
22218 +struct fdpic_func_descriptor {
22219 +       unsigned long   text;
22220 +       unsigned long   GOT;
22221 +};
22222 +
22223 +/*
22224 + * rt_sigframe is stored on the user stack immediately before (above)
22225 + * the signal handlers stack.
22226 + */
22227 +struct rt_sigframe
22228 +{
22229 +       unsigned long syscall_number;   /* This holds __NR_rt_sigreturn. */
22230 +       unsigned long restore_all_regs; /* This field gets set to 1 if the frame
22231 +                                        * type is TRAP or INTERRUPT. */
22232 +       siginfo_t *info;
22233 +       struct ucontext uc;
22234 +       int sig;
22235 +       void *pretcode;
22236 +};
22237 +
22238 +/*
22239 + * Do a signal return; undo the signal stack.
22240 + */
22241 +asmlinkage int do_sigreturn(unsigned long __unused)
22242 +{
22243 +       BUG();
22244 +       return 0;
22245 +}
22246 +
22247 +asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
22248 +{
22249 +       unsigned long usp = regs->an[7];
22250 +       struct rt_sigframe *frame = (struct rt_sigframe *)(usp);
22251 +       sigset_t set;
22252 +
22253 +       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
22254 +               goto badframe;
22255 +       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
22256 +               goto badframe;
22257 +
22258 +       sigdelsetmask(&set, ~_BLOCKABLE);
22259 +       spin_lock_irq(&current->sighand->siglock);
22260 +       current->blocked = set;
22261 +       recalc_sigpending();
22262 +       spin_unlock_irq(&current->sighand->siglock);
22263 +
22264 +       if (copy_from_user(regs, &frame->uc.uc_mcontext, sizeof(struct pt_regs)))
22265 +               goto badframe;
22266 +       return regs->dn[0];
22267 +
22268 +badframe:
22269 +       force_sig(SIGSEGV, current);
22270 +       return 0;
22271 +}
22272 +
22273 +static inline void *
22274 +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
22275 +{
22276 +       unsigned long usp;
22277 +
22278 +       /* Default to using normal stack.  */
22279 +       usp = regs->an[7];
22280 +
22281 +       /* This is the X/Open sanctioned signal stack switching.  */
22282 +       if (ka->sa.sa_flags & SA_ONSTACK) {
22283 +               if (!sas_ss_flags(usp))
22284 +                       usp = current->sas_ss_sp + current->sas_ss_size;
22285 +       }
22286 +       return (void *)((usp - frame_size) & ~0x3);
22287 +}
22288 +
22289 +/*
22290 + * signal_trampoline:  Defined in ubicom32_syscall.S
22291 + */
22292 +asmlinkage void signal_trampoline(void)__attribute__((naked));
22293 +
22294 +static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
22295 +                           sigset_t *set, struct pt_regs *regs)
22296 +{
22297 +       struct rt_sigframe *frame;
22298 +       int err = 0;
22299 +
22300 +       frame = (struct rt_sigframe *) get_sigframe(ka, regs, sizeof(*frame));
22301 +
22302 +       /*
22303 +        * The 'err |=' have been may criticized as bad code style, but I
22304 +        * strongly suspect that we want this code to be fast.  So for
22305 +        * now it stays as is.
22306 +        */
22307 +       err |= __put_user( (  (current_thread_info()->exec_domain)
22308 +                          && (current_thread_info()->exec_domain->signal_invmap)
22309 +                          && (sig < 32) )
22310 +                          ? current_thread_info()->exec_domain->signal_invmap[sig]
22311 +                          : sig, &frame->sig);
22312 +       err |= __put_user(info, &frame->info);
22313 +
22314 +       /* Create the ucontext.  */
22315 +       err |= __put_user(0, &frame->uc.uc_flags);
22316 +       err |= __put_user(0, &frame->uc.uc_link);
22317 +       err |= __put_user((void *)current->sas_ss_sp,
22318 +                         &frame->uc.uc_stack.ss_sp);
22319 +       err |= __put_user(sas_ss_flags(regs->an[7]),
22320 +                         &frame->uc.uc_stack.ss_flags);
22321 +       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
22322 +       err |= __put_user(__NR_rt_sigreturn, &frame->syscall_number);
22323 +       if ((regs->frame_type == UBICOM32_FRAME_TYPE_TRAP) ||
22324 +           (regs->frame_type == UBICOM32_FRAME_TYPE_INTERRUPT)) {
22325 +               err |= __put_user(1, &frame->restore_all_regs);
22326 +       } else {
22327 +               err |= __put_user(0, &frame->restore_all_regs);
22328 +       }
22329 +       err |= copy_to_user (&frame->uc.uc_mcontext.sc_regs, regs, sizeof(struct pt_regs));
22330 +       err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
22331 +
22332 +       if (err)
22333 +               goto give_sigsegv;
22334 +
22335 +       /*
22336 +        * Set up registers for signal handler NOTE: Do not modify dn[14], it
22337 +        * contains the userspace tls pointer, so it important that it carries
22338 +        * over to the signal handler.
22339 +        */
22340 +       regs->an[7] = (unsigned long)frame;
22341 +       regs->pc = (unsigned long) signal_trampoline;
22342 +       regs->an[5] = (unsigned long) signal_trampoline;
22343 +       regs->dn[0] = sig;
22344 +       regs->dn[1] = (unsigned long) frame->info;
22345 +       regs->dn[2] = (unsigned int) &frame->uc;
22346 +
22347 +       /*
22348 +        * If this is FDPIC then the signal handler is actually a function
22349 +        * descriptor.
22350 +        */
22351 +       if (current->personality & FDPIC_FUNCPTRS) {
22352 +               struct fdpic_func_descriptor __user *funcptr =
22353 +                       (struct fdpic_func_descriptor *) ka->sa.sa_handler;
22354 +               err |= __get_user(regs->dn[3], &funcptr->text);
22355 +               err |= __get_user(regs->an[0], &funcptr->GOT);
22356 +               if (err)
22357 +                       goto give_sigsegv;
22358 +
22359 +               /*
22360 +                * The funcdesc must be in a3 as this is required for the lazy
22361 +                * resolver in ld.so, if the application is not FDPIC a3 is not
22362 +                * used.
22363 +                */
22364 +               regs->an[3] = (unsigned long) funcptr;
22365 +
22366 +       } else {
22367 +               regs->dn[3] = (unsigned long)ka->sa.sa_handler;
22368 +               regs->an[0] = 0;
22369 +       }
22370 +
22371 +       regs->frame_type =  UBICOM32_FRAME_TYPE_SIGTRAMP;
22372 +
22373 +       return;
22374 +
22375 +give_sigsegv:
22376 +       /* user space exception */
22377 +       force_sigsegv(sig, current);
22378 +}
22379 +
22380 +static inline void
22381 +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
22382 +{
22383 +       switch (regs->dn[0]) {
22384 +       case -ERESTARTNOHAND:
22385 +               if (!has_handler)
22386 +                       goto do_restart;
22387 +               regs->dn[0] = -EINTR;
22388 +               break;
22389 +
22390 +       case -ERESTARTSYS:
22391 +               if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
22392 +                       regs->dn[0] = -EINTR;
22393 +                       break;
22394 +               }
22395 +       /* fallthrough */
22396 +       case -ERESTARTNOINTR:
22397 +       do_restart:
22398 +               regs->dn[0] = regs->original_dn_0;
22399 +               regs->pc -= 8;
22400 +               regs->an[5] -= 8;
22401 +               break;
22402 +       }
22403 +}
22404 +
22405 +/*
22406 + * OK, we're invoking a handler
22407 + */
22408 +static void
22409 +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
22410 +             sigset_t *oldset, struct pt_regs *regs)
22411 +{
22412 +       /* are we from a system call? */
22413 +       if (regs->frame_type == -1)
22414 +               /* If so, check system call restarting.. */
22415 +               handle_restart(regs, ka, 1);
22416 +
22417 +       /* set up the stack frame */
22418 +       setup_rt_frame(sig, ka, info, oldset, regs);
22419 +
22420 +       if (ka->sa.sa_flags & SA_ONESHOT)
22421 +               ka->sa.sa_handler = SIG_DFL;
22422 +
22423 +       spin_lock_irq(&current->sighand->siglock);
22424 +       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
22425 +       if (!(ka->sa.sa_flags & SA_NODEFER))
22426 +               sigaddset(&current->blocked,sig);
22427 +       recalc_sigpending();
22428 +       spin_unlock_irq(&current->sighand->siglock);
22429 +}
22430 +
22431 +/*
22432 + * Note that 'init' is a special process: it doesn't get signals it doesn't
22433 + * want to handle. Thus you cannot kill init even with a SIGKILL even by
22434 + * mistake.
22435 + */
22436 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
22437 +{
22438 +       struct k_sigaction ka;
22439 +       siginfo_t info;
22440 +       int signr;
22441 +
22442 +       /*
22443 +        * We want the common case to go fast, which
22444 +        * is why we may in certain cases get here from
22445 +        * kernel mode. Just return without doing anything
22446 +        * if so.
22447 +        */
22448 +       if (!user_mode(regs))
22449 +               return 1;
22450 +
22451 +       if (!oldset)
22452 +               oldset = &current->blocked;
22453 +
22454 +       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
22455 +       if (signr > 0) {
22456 +               /* Whee!  Actually deliver the signal.  */
22457 +               handle_signal(signr, &ka, &info, oldset, regs);
22458 +               return 1;
22459 +       }
22460 +
22461 +       /* Did we come from a system call? */
22462 +       if (regs->frame_type == -1) {
22463 +               /* Restart the system call - no handlers present */
22464 +               handle_restart(regs, NULL, 0);
22465 +       }
22466 +
22467 +       return 0;
22468 +}
22469 +
22470 +/*
22471 + * sys_sigreturn()
22472 + *     Return handler for signal clean-up.
22473 + *
22474 + * NOTE: Ubicom32 does not use this syscall.  Instead we rely
22475 + * on do_rt_sigreturn().
22476 + */
22477 +asmlinkage long sys_sigreturn(void)
22478 +{
22479 +       return -ENOSYS;
22480 +}
22481 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/smp.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/smp.c
22482 --- linux-2.6.30.10/arch/ubicom32/kernel/smp.c  1970-01-01 02:00:00.000000000 +0200
22483 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/smp.c      2009-12-11 11:45:11.000000000 +0200
22484 @@ -0,0 +1,806 @@
22485 +/*
22486 + * arch/ubicom32/kernel/smp.c
22487 + *   SMP implementation for Ubicom32 processors.
22488 + *
22489 + * (C) Copyright 2009, Ubicom, Inc.
22490 + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
22491 + * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
22492 + * Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org>
22493 + *
22494 + * This file is part of the Ubicom32 Linux Kernel Port.
22495 + *
22496 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
22497 + * it and/or modify it under the terms of the GNU General Public License
22498 + * as published by the Free Software Foundation, either version 2 of the
22499 + * License, or (at your option) any later version.
22500 + *
22501 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
22502 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22503 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
22504 + * the GNU General Public License for more details.
22505 + *
22506 + * You should have received a copy of the GNU General Public License
22507 + * along with the Ubicom32 Linux Kernel Port.  If not,
22508 + * see <http://www.gnu.org/licenses/>.
22509 + *
22510 + * Ubicom32 implementation derived from (with many thanks):
22511 + *   arch/m68knommu
22512 + *   arch/blackfin
22513 + *   arch/parisc
22514 + */
22515 +
22516 +#include <linux/types.h>
22517 +#include <linux/spinlock.h>
22518 +#include <linux/slab.h>
22519 +
22520 +#include <linux/kernel.h>
22521 +#include <linux/bootmem.h>
22522 +#include <linux/module.h>
22523 +#include <linux/sched.h>
22524 +#include <linux/init.h>
22525 +#include <linux/interrupt.h>
22526 +#include <linux/smp.h>
22527 +#include <linux/kernel_stat.h>
22528 +#include <linux/mm.h>
22529 +#include <linux/err.h>
22530 +#include <linux/delay.h>
22531 +#include <linux/bitops.h>
22532 +#include <linux/cpu.h>
22533 +#include <linux/profile.h>
22534 +#include <linux/delay.h>
22535 +#include <linux/io.h>
22536 +#include <linux/ptrace.h>
22537 +#include <linux/unistd.h>
22538 +#include <linux/irq.h>
22539 +
22540 +#include <asm/system.h>
22541 +#include <asm/atomic.h>
22542 +#include <asm/current.h>
22543 +#include <asm/tlbflush.h>
22544 +#include <asm/timex.h>
22545 +#include <asm/cpu.h>
22546 +#include <asm/irq.h>
22547 +#include <asm/processor.h>
22548 +#include <asm/thread.h>
22549 +#include <asm/sections.h>
22550 +#include <asm/ip5000.h>
22551 +
22552 +/*
22553 + * Mask the debug printout for IPI because they are too verbose
22554 + * for regular debugging.
22555 + */
22556 +
22557 +// #define DEBUG_SMP 1
22558 +#if !defined(DEBUG_SMP)
22559 +#define smp_debug(lvl, ...)
22560 +#else
22561 +static unsigned int smp_debug_lvl = 50;
22562 +#define smp_debug(lvl, printargs...)           \
22563 +       if (lvl >= smp_debug_lvl) {             \
22564 +                       printk(printargs);      \
22565 +       }
22566 +#endif
22567 +
22568 +#if !defined(DEBUG_SMP)
22569 +#define DEBUG_ASSERT(cond)
22570 +#else
22571 +#define DEBUG_ASSERT(cond) \
22572 +       if (!(cond)) { \
22573 +               THREAD_STALL; \
22574 +       }
22575 +#endif
22576 +
22577 +/*
22578 + * List of IPI Commands (more than one can be set at a time).
22579 + */
22580 +enum ipi_message_type {
22581 +       IPI_NOP,
22582 +       IPI_RESCHEDULE,
22583 +       IPI_CALL_FUNC,
22584 +       IPI_CALL_FUNC_SINGLE,
22585 +       IPI_CPU_STOP,
22586 +       IPI_CPU_TIMER,
22587 +};
22588 +
22589 +/*
22590 + * We maintain a hardware thread oriented view of online threads
22591 + * and those involved or needing IPI.
22592 + */
22593 +static volatile unsigned long smp_online_threads = 0;
22594 +static volatile unsigned long smp_needs_ipi = 0;
22595 +static volatile unsigned long smp_inside_ipi = 0;
22596 +static unsigned long smp_irq_affinity[NR_IRQS];
22597 +
22598 +/*
22599 + * What do we need to track on a per cpu/thread basis?
22600 + */
22601 +DEFINE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
22602 +
22603 +/*
22604 + * Each thread cpuinfo IPI information is guarded by a lock
22605 + * that is kept local to this file.
22606 + */
22607 +DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
22608 +
22609 +/*
22610 + * The IPI(s) are based on a software IRQ through the LDSR.
22611 + */
22612 +unsigned int smp_ipi_irq;
22613 +
22614 +/*
22615 + * Define a spinlock so that only one cpu is able to modify the
22616 + * smp_needs_ipi and to set/clear the IRQ at a time.
22617 + */
22618 +DEFINE_SPINLOCK(smp_ipi_lock);
22619 +
22620 +/*
22621 + * smp_halt_processor()
22622 + *     Halt this hardware thread.
22623 + */
22624 +static void smp_halt_processor(void)
22625 +{
22626 +       int cpuid = thread_get_self();
22627 +       cpu_clear(smp_processor_id(), cpu_online_map);
22628 +       local_irq_disable();
22629 +       printk(KERN_EMERG "cpu[%d] has halted. It is not OK to turn off power \
22630 +               until all cpu's are off.\n", cpuid);
22631 +       for (;;) {
22632 +               thread_suspend();
22633 +       }
22634 +}
22635 +
22636 +/*
22637 + * ipi_interrupt()
22638 + *     Handle an Interprocessor Interrupt.
22639 + */
22640 +static irqreturn_t ipi_interrupt(int irq, void *dev_id)
22641 +{
22642 +       int cpuid = smp_processor_id();
22643 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22644 +       unsigned long ops;
22645 +
22646 +       /*
22647 +        * Count this now; we may make a call that never returns.
22648 +        */
22649 +       p->ipi_count++;
22650 +
22651 +       /*
22652 +        * We are about to process all ops.  If another cpu has stated
22653 +        * that we need an IPI, we will have already processed it.  By
22654 +        * clearing our smp_needs_ipi, and processing all ops,
22655 +        * we reduce the number of IPI interrupts.  However, this introduces
22656 +        * the possibility that smp_needs_ipi will be clear and the soft irq
22657 +        * will have gone off; so we need to make the get_affinity() path
22658 +        * tolerant of spurious interrupts.
22659 +        */
22660 +       spin_lock(&smp_ipi_lock);
22661 +       smp_needs_ipi &= ~(1 << p->tid);
22662 +       spin_unlock(&smp_ipi_lock);
22663 +
22664 +       for (;;) {
22665 +               /*
22666 +                * Read the set of IPI commands we should handle.
22667 +                */
22668 +               spinlock_t *lock = &per_cpu(ipi_lock, cpuid);
22669 +               spin_lock(lock);
22670 +               ops = p->ipi_pending;
22671 +               p->ipi_pending = 0;
22672 +               spin_unlock(lock);
22673 +
22674 +               /*
22675 +                * If we have no IPI commands to execute, break out.
22676 +                */
22677 +               if (!ops) {
22678 +                       break;
22679 +               }
22680 +
22681 +               /*
22682 +                * Execute the set of commands in the ops word, one command
22683 +                * at a time in no particular order.  Strip of each command
22684 +                * as we execute it.
22685 +                */
22686 +               while (ops) {
22687 +                       unsigned long which = ffz(~ops);
22688 +                       ops &= ~(1 << which);
22689 +
22690 +                       BUG_ON(!irqs_disabled());
22691 +                       switch (which) {
22692 +                       case IPI_NOP:
22693 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22694 +                                         "IPI_NOP\n", cpuid);
22695 +                               break;
22696 +
22697 +                       case IPI_RESCHEDULE:
22698 +                               /*
22699 +                                * Reschedule callback.  Everything to be
22700 +                                * done is done by the interrupt return path.
22701 +                                */
22702 +                               smp_debug(200, KERN_INFO "cpu[%d]: "
22703 +                                         "IPI_RESCHEDULE\n", cpuid);
22704 +                               break;
22705 +
22706 +                       case IPI_CALL_FUNC:
22707 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22708 +                                         "IPI_CALL_FUNC\n", cpuid);
22709 +                               generic_smp_call_function_interrupt();
22710 +                               break;
22711 +
22712 +                       case IPI_CALL_FUNC_SINGLE:
22713 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22714 +                                         "IPI_CALL_FUNC_SINGLE\n", cpuid);
22715 +                               generic_smp_call_function_single_interrupt();
22716 +                               break;
22717 +
22718 +                       case IPI_CPU_STOP:
22719 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22720 +                                         "IPI_CPU_STOP\n", cpuid);
22721 +                               smp_halt_processor();
22722 +                               break;
22723 +
22724 +#if !defined(CONFIG_LOCAL_TIMERS)
22725 +                       case IPI_CPU_TIMER:
22726 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22727 +                                         "IPI_CPU_TIMER\n", cpuid);
22728 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
22729 +                               local_timer_interrupt();
22730 +#else
22731 +                               update_process_times(user_mode(get_irq_regs()));
22732 +                               profile_tick(CPU_PROFILING);
22733 +#endif
22734 +#endif
22735 +                               break;
22736 +
22737 +                       default:
22738 +                               printk(KERN_CRIT "cpu[%d]: "
22739 +                                         "Unknown IPI: %lu\n", cpuid, which);
22740 +
22741 +                               return IRQ_NONE;
22742 +                       }
22743 +
22744 +                       /*
22745 +                        * Let in any pending interrupts
22746 +                        */
22747 +                       BUG_ON(!irqs_disabled());
22748 +                       local_irq_enable();
22749 +                       local_irq_disable();
22750 +               }
22751 +       }
22752 +       return IRQ_HANDLED;
22753 +}
22754 +
22755 +/*
22756 + * ipi_send()
22757 + *     Send an Interprocessor Interrupt.
22758 + */
22759 +static void ipi_send(int cpu, enum ipi_message_type op)
22760 +{
22761 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
22762 +       spinlock_t *lock = &per_cpu(ipi_lock, cpu);
22763 +       unsigned long flags;
22764 +
22765 +       /*
22766 +        * We protect the setting of the ipi_pending field and ensure
22767 +        * that the ipi delivery mechanism and interrupt are atomically
22768 +        * handled.
22769 +        */
22770 +       spin_lock_irqsave(lock, flags);
22771 +       p->ipi_pending |= 1 << op;
22772 +       spin_unlock_irqrestore(lock, flags);
22773 +
22774 +       spin_lock_irqsave(&smp_ipi_lock, flags);
22775 +       smp_needs_ipi |= (1 << p->tid);
22776 +       ubicom32_set_interrupt(smp_ipi_irq);
22777 +       spin_unlock_irqrestore(&smp_ipi_lock, flags);
22778 +       smp_debug(100, KERN_INFO "cpu[%d]: send: %d\n", cpu, op);
22779 +}
22780 +
22781 +/*
22782 + * ipi_send_mask
22783 + *     Send an IPI to each cpu in mask.
22784 + */
22785 +static inline void ipi_send_mask(unsigned int op, const struct cpumask mask)
22786 +{
22787 +       int cpu;
22788 +       for_each_cpu_mask(cpu, mask) {
22789 +               ipi_send(cpu, op);
22790 +       }
22791 +}
22792 +
22793 +/*
22794 + * ipi_send_allbutself()
22795 + *     Send an IPI to all threads but ourselves.
22796 + */
22797 +static inline void ipi_send_allbutself(unsigned int op)
22798 +{
22799 +       int self = smp_processor_id();
22800 +       struct cpumask result;
22801 +       cpumask_copy(&result, &cpu_online_map);
22802 +       cpu_clear(self, result);
22803 +       ipi_send_mask(op, result);
22804 +}
22805 +
22806 +/*
22807 + * smp_enable_vector()
22808 + */
22809 +static void smp_enable_vector(unsigned int irq)
22810 +{
22811 +       ubicom32_clear_interrupt(smp_ipi_irq);
22812 +       ldsr_enable_vector(irq);
22813 +}
22814 +
22815 +/*
22816 + * smp_disable_vector()
22817 + *     Disable the interrupt by clearing the appropriate bit in the
22818 + *     LDSR Mask Register.
22819 + */
22820 +static void smp_disable_vector(unsigned int irq)
22821 +{
22822 +       ldsr_disable_vector(irq);
22823 +}
22824 +
22825 +/*
22826 + * smp_mask_vector()
22827 + */
22828 +static void smp_mask_vector(unsigned int irq)
22829 +{
22830 +       ldsr_mask_vector(irq);
22831 +}
22832 +
22833 +/*
22834 + * smp_unmask_vector()
22835 + */
22836 +static void smp_unmask_vector(unsigned int irq)
22837 +{
22838 +       ldsr_unmask_vector(irq);
22839 +}
22840 +
22841 +/*
22842 + * smp_end_vector()
22843 + *     Called once an interrupt is completed (reset the LDSR mask).
22844 + */
22845 +static void smp_end_vector(unsigned int irq)
22846 +{
22847 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, smp_processor_id());
22848 +       spin_lock(&smp_ipi_lock);
22849 +       smp_inside_ipi &= ~(1 << p->tid);
22850 +       if (smp_inside_ipi) {
22851 +               spin_unlock(&smp_ipi_lock);
22852 +               return;
22853 +       }
22854 +       spin_unlock(&smp_ipi_lock);
22855 +       ldsr_unmask_vector(irq);
22856 +       smp_debug(100, KERN_INFO "cpu[%d]: unamesk vector\n", smp_processor_id());
22857 +}
22858 +
22859 +/*
22860 + * Special hanlder functions for SMP.
22861 + */
22862 +static struct irq_chip ubicom32_smp_chip = {
22863 +       .name           = "UbicoIPI",
22864 +       .startup        = NULL,
22865 +       .shutdown       = NULL,
22866 +       .enable         = smp_enable_vector,
22867 +       .disable        = smp_disable_vector,
22868 +       .ack            = NULL,
22869 +       .mask           = smp_mask_vector,
22870 +       .unmask         = smp_unmask_vector,
22871 +       .end            = smp_end_vector,
22872 +};
22873 +
22874 +/*
22875 + * smp_reset_ipi()
22876 + *     None of these cpu(s) got their IPI, turn it back on.
22877 + *
22878 + * Note: This is called by the LDSR which is not a full
22879 + * Linux cpu.  Thus you must use the raw form of locks
22880 + * because lock debugging will not work on the partial
22881 + * cpu nature of the LDSR.
22882 + */
22883 +void smp_reset_ipi(unsigned long mask)
22884 +{
22885 +       __raw_spin_lock(&smp_ipi_lock.raw_lock);
22886 +       smp_needs_ipi |= mask;
22887 +       smp_inside_ipi &= ~mask;
22888 +       ubicom32_set_interrupt(smp_ipi_irq);
22889 +       __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22890 +       smp_debug(100, KERN_INFO "smp: reset IPIs for: 0x%x\n", mask);
22891 +}
22892 +
22893 +/*
22894 + * smp_get_affinity()
22895 + *     Choose the thread affinity for this interrupt.
22896 + *
22897 + * Note: This is called by the LDSR which is not a full
22898 + * Linux cpu.  Thus you must use the raw form of locks
22899 + * because lock debugging will not work on the partial
22900 + * cpu nature of the LDSR.
22901 + */
22902 +unsigned long smp_get_affinity(unsigned int irq, int *all)
22903 +{
22904 +       unsigned long mask = 0;
22905 +
22906 +       /*
22907 +        * Most IRQ(s) are delivered in a round robin fashion.
22908 +        */
22909 +       if (irq != smp_ipi_irq) {
22910 +               unsigned long result = smp_irq_affinity[irq] & smp_online_threads;
22911 +               DEBUG_ASSERT(result);
22912 +               *all = 0;
22913 +               return result;
22914 +       }
22915 +
22916 +       /*
22917 +        * This is an IPI request.  Return all cpu(s) scheduled for an IPI.
22918 +        * We also track those cpu(s) that are going to be "receiving" IPI this
22919 +        * round.  When all CPU(s) have called smp_end_vector(),
22920 +        * we will unmask the IPI interrupt.
22921 +        */
22922 +       __raw_spin_lock(&smp_ipi_lock.raw_lock);
22923 +       ubicom32_clear_interrupt(smp_ipi_irq);
22924 +       if (smp_needs_ipi) {
22925 +               mask = smp_needs_ipi;
22926 +               smp_inside_ipi |= smp_needs_ipi;
22927 +               smp_needs_ipi = 0;
22928 +       }
22929 +       __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22930 +       *all = 1;
22931 +       return mask;
22932 +}
22933 +
22934 +/*
22935 + *  smp_set_affinity()
22936 + *     Set the affinity for this irq but store the value in tid(s).
22937 + */
22938 +void smp_set_affinity(unsigned int irq, const struct cpumask *dest)
22939 +{
22940 +       int cpuid;
22941 +       unsigned long *paffinity = &smp_irq_affinity[irq];
22942 +
22943 +       /*
22944 +        *  If none specified, all cpus are allowed.
22945 +        */
22946 +       if (cpus_empty(*dest)) {
22947 +               *paffinity = 0xffffffff;
22948 +               return;
22949 +       }
22950 +
22951 +       /*
22952 +        * Make sure to clear the old value before setting up the
22953 +        * list.
22954 +        */
22955 +       *paffinity = 0;
22956 +       for_each_cpu_mask(cpuid, *dest) {
22957 +               struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22958 +               *paffinity |= (1 << p->tid);
22959 +       }
22960 +}
22961 +
22962 +/*
22963 + * smp_send_stop()
22964 + *     Send a stop request to all CPU but this one.
22965 + */
22966 +void smp_send_stop(void)
22967 +{
22968 +       ipi_send_allbutself(IPI_CPU_STOP);
22969 +}
22970 +
22971 +/*
22972 + * smp_send_timer_all()
22973 + *     Send all cpu(s) but this one, a request to update times.
22974 + */
22975 +void smp_send_timer_all(void)
22976 +{
22977 +       ipi_send_allbutself(IPI_CPU_TIMER);
22978 +}
22979 +
22980 +/*
22981 + * smp_timer_broadcast()
22982 + *     Use an IPI to broadcast a timer message
22983 + */
22984 +void smp_timer_broadcast(const struct cpumask *mask)
22985 +{
22986 +       ipi_send_mask(IPI_CPU_TIMER, *mask);
22987 +}
22988 +
22989 +/*
22990 + * smp_send_reschedule()
22991 + *     Send a reschedule request to the specified cpu.
22992 + */
22993 +void smp_send_reschedule(int cpu)
22994 +{
22995 +       ipi_send(cpu, IPI_RESCHEDULE);
22996 +}
22997 +
22998 +/*
22999 + * arch_send_call_function_ipi()
23000 + *     Cause each cpu in the mask to call the generic function handler.
23001 + */
23002 +void arch_send_call_function_ipi_mask(const struct cpumask *mask)
23003 +{
23004 +       int cpu;
23005 +       for_each_cpu_mask(cpu, *mask) {
23006 +               ipi_send(cpu, IPI_CALL_FUNC);
23007 +       }
23008 +}
23009 +
23010 +/*
23011 + * arch_send_call_function_single_ipi()
23012 + *     Cause the specified cpu to call the generic function handler.
23013 + */
23014 +void arch_send_call_function_single_ipi(int cpu)
23015 +{
23016 +       ipi_send(cpu, IPI_CALL_FUNC_SINGLE);
23017 +}
23018 +
23019 +/*
23020 + * setup_profiling_timer()
23021 + *     Dummy function created to keep Oprofile happy in the SMP case.
23022 + */
23023 +int setup_profiling_timer(unsigned int multiplier)
23024 +{
23025 +       return 0;
23026 +}
23027 +
23028 +/*
23029 + * smp_mainline_start()
23030 + *     Start a slave thread executing a mainline Linux context.
23031 + */
23032 +static void __init smp_mainline_start(void *arg)
23033 +{
23034 +       int cpuid = smp_processor_id();
23035 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
23036 +
23037 +       BUG_ON(p->tid != thread_get_self());
23038 +
23039 +       /*
23040 +        * Well, support 2.4 linux scheme as well.
23041 +        */
23042 +       if (cpu_test_and_set(cpuid, cpu_online_map)) {
23043 +               printk(KERN_CRIT "cpu[%d]: already initialized!\n", cpuid);
23044 +               smp_halt_processor();
23045 +               return;
23046 +       }
23047 +
23048 +       /*
23049 +        * Initialise the idle task for this CPU
23050 +        */
23051 +       atomic_inc(&init_mm.mm_count);
23052 +       current->active_mm = &init_mm;
23053 +       if (current->mm) {
23054 +               printk(KERN_CRIT "cpu[%d]: idle task already has memory "
23055 +                      "management\n", cpuid);
23056 +               smp_halt_processor();
23057 +               return;
23058 +       }
23059 +
23060 +       /*
23061 +        * TODO: X86 does this prior to calling notify, try to understand why?
23062 +        */
23063 +       preempt_disable();
23064 +
23065 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
23066 +       /*
23067 +        * Setup a local timer event so that this cpu will get timer interrupts
23068 +        */
23069 +       if (local_timer_setup(cpuid) == -1) {
23070 +               printk(KERN_CRIT "cpu[%d]: timer alloc failed\n", cpuid);
23071 +               smp_halt_processor();
23072 +               return;
23073 +       }
23074 +#endif
23075 +
23076 +       /*
23077 +        * Notify those interested that we are up and alive.  This must
23078 +        * be done before interrupts are enabled.  It must also be completed
23079 +        * before the bootstrap cpu returns from __cpu_up() (see comment
23080 +        * above cpu_set() of the cpu_online_map).
23081 +        */
23082 +       notify_cpu_starting(cpuid);
23083 +
23084 +       /*
23085 +        * Indicate that this thread is now online and present.   Setting
23086 +        * cpu_online_map has the side effect of allowing the bootstrap
23087 +        * cpu to continue along; so anything that MUST be done prior to the
23088 +        * bootstrap cpu returning from __cpu_up() needs to go above here.
23089 +        */
23090 +       cpu_set(cpuid, cpu_online_map);
23091 +       cpu_set(cpuid, cpu_present_map);
23092 +
23093 +       /*
23094 +        * Maintain a thread mapping in addition to the cpu mapping.
23095 +        */
23096 +       smp_online_threads |= (1 << p->tid);
23097 +
23098 +       /*
23099 +        * Enable interrupts for this thread.
23100 +        */
23101 +       local_irq_enable();
23102 +
23103 +       /*
23104 +        * Enter the idle loop and wait for a timer to schedule some work.
23105 +        */
23106 +       printk(KERN_INFO "cpu[%d]: entering cpu_idle()\n", cpuid);
23107 +       cpu_idle();
23108 +
23109 +       /* Not Reached */
23110 +}
23111 +
23112 +/*
23113 + * smp_cpus_done()
23114 + *     Called once the kernel_init() has brought up all cpu(s).
23115 + */
23116 +void smp_cpus_done(unsigned int cpu_max)
23117 +{
23118 +       /* Do Nothing */
23119 +}
23120 +
23121 +/*
23122 + * __cpu_up()
23123 + *     Called to startup a sepcific cpu.
23124 + */
23125 +int __cpuinit __cpu_up(unsigned int cpu)
23126 +{
23127 +       struct task_struct *idle;
23128 +       unsigned int *stack;
23129 +       long timeout;
23130 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
23131 +
23132 +       /*
23133 +        * Create an idle task for this CPU.
23134 +        */
23135 +       idle = fork_idle(cpu);
23136 +       if (IS_ERR(idle)) {
23137 +               panic("cpu[%d]: fork failed\n", cpu);
23138 +               return -ENOSYS;
23139 +       }
23140 +       task_thread_info(idle)->cpu = cpu;
23141 +
23142 +       /*
23143 +        * Setup the sw_ksp[] to point to this new task.
23144 +        */
23145 +       sw_ksp[p->tid] = (unsigned int)idle->stack;
23146 +       stack = (unsigned int *)(sw_ksp[p->tid] + PAGE_SIZE - 8);
23147 +
23148 +       /*
23149 +        * Cause the specified thread to execute our smp_mainline_start
23150 +        * function as a TYPE_NORMAL thread.
23151 +        */
23152 +       printk(KERN_INFO "cpu[%d]: launching mainline Linux thread\n", cpu);
23153 +       if (thread_start(p->tid, smp_mainline_start, (void *)NULL, stack,
23154 +                        THREAD_TYPE_NORMAL) == -1) {
23155 +               printk(KERN_WARNING "cpu[%d]: failed thread_start\n", cpu);
23156 +               return -ENOSYS;
23157 +       }
23158 +
23159 +       /*
23160 +        * Wait for the thread to start up.  The thread will set
23161 +        * the online bit when it is running.  Our caller execpts the
23162 +        * cpu to be online if we return 0.
23163 +        */
23164 +       for (timeout = 0; timeout < 10000; timeout++) {
23165 +               if (cpu_online(cpu)) {
23166 +                       break;
23167 +               }
23168 +
23169 +               udelay(100);
23170 +               barrier();
23171 +               continue;
23172 +       }
23173 +
23174 +       if (!cpu_online(cpu)) {
23175 +               printk(KERN_CRIT "cpu[%d]: failed to live after %ld us\n",
23176 +                      cpu, timeout * 100);
23177 +               return -ENOSYS;
23178 +       }
23179 +
23180 +       printk(KERN_INFO "cpu[%d]: came alive after %ld us\n",
23181 +              cpu, timeout * 100);
23182 +       return 0;
23183 +}
23184 +
23185 +/*
23186 + * Data used by setup_irq for the IPI.
23187 + */
23188 +static struct irqaction ipi_irq = {
23189 +       .name    = "ipi",
23190 +       .flags   = IRQF_DISABLED | IRQF_PERCPU,
23191 +       .handler = ipi_interrupt,
23192 +};
23193 +
23194 +/*
23195 + * smp_prepare_cpus()
23196 + *     Mark threads that are available to Linux as possible cpus(s).
23197 + */
23198 +void __init smp_prepare_cpus(unsigned int max_cpus)
23199 +{
23200 +       int i;
23201 +
23202 +       /*
23203 +        * We will need a software IRQ to send IPI(s).  We will use
23204 +        * a single software IRQ for all IPI(s).
23205 +        */
23206 +       if (irq_soft_alloc(&smp_ipi_irq) < 0) {
23207 +               panic("no software IRQ is available\n");
23208 +               return;
23209 +       }
23210 +
23211 +       /*
23212 +        * For the IPI interrupt, we want to use our own chip definition.
23213 +        * This allows us to define what happens in SMP IPI without affecting
23214 +        * the performance of the other interrupts.
23215 +        *
23216 +        * Next, Register the IPI interrupt function against the soft IRQ.
23217 +        */
23218 +       set_irq_chip(smp_ipi_irq, &ubicom32_smp_chip);
23219 +       setup_irq(smp_ipi_irq, &ipi_irq);
23220 +
23221 +       /*
23222 +        * We use the device tree node to determine how many
23223 +        * free cpus we will have (up to NR_CPUS) and we indicate
23224 +        * that those cpus are present.
23225 +        *
23226 +        * We need to do this very early in the SMP case
23227 +        * because the Linux init code uses the cpu_present_map.
23228 +        */
23229 +       for_each_possible_cpu(i) {
23230 +               thread_t tid;
23231 +               struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, i);
23232 +
23233 +               /*
23234 +                *  Skip the bootstrap cpu
23235 +                */
23236 +               if (i == 0) {
23237 +                       continue;
23238 +               }
23239 +
23240 +               /*
23241 +                * If we have a free thread left in the mask,
23242 +                * indicate that the cpu is present.
23243 +                */
23244 +               tid = thread_alloc();
23245 +               if (tid == (thread_t)-1) {
23246 +                       break;
23247 +               }
23248 +
23249 +               /*
23250 +                * Save the hardware thread id for this cpu.
23251 +                */
23252 +               p->tid = tid;
23253 +               cpu_set(i, cpu_present_map);
23254 +               printk(KERN_INFO "cpu[%d]: added to cpu_present_map - tid: %d\n", i, tid);
23255 +       }
23256 +}
23257 +
23258 +/*
23259 + * smp_prepare_boot_cpu()
23260 + *     Copy the per_cpu data into the appropriate spot for the bootstrap cpu.
23261 + *
23262 + * The code in boot_cpu_init() has already set the boot cpu's
23263 + * state in the possible, present, and online maps.
23264 + */
23265 +void __devinit smp_prepare_boot_cpu(void)
23266 +{
23267 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23268 +
23269 +       smp_online_threads |= (1 << p->tid);
23270 +       printk(KERN_INFO "cpu[%d]: bootstrap CPU online - tid: %ld\n",
23271 +                       current_thread_info()->cpu, p->tid);
23272 +}
23273 +
23274 +/*
23275 + * smp_setup_processor_id()
23276 + *     Set the current_thread_info() structure cpu value.
23277 + *
23278 + * We set the value to the true hardware thread value that we are running on.
23279 + * NOTE: this function overrides the weak alias function in main.c
23280 + */
23281 +void __init smp_setup_processor_id(void)
23282 +{
23283 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23284 +       int i;
23285 +       for_each_cpu_mask(i, CPU_MASK_ALL)
23286 +               set_cpu_possible(i, true);
23287 +
23288 +       current_thread_info()->cpu = 0;
23289 +       p->tid = thread_get_self();
23290 +}
23291 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/stacktrace.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/stacktrace.c
23292 --- linux-2.6.30.10/arch/ubicom32/kernel/stacktrace.c   1970-01-01 02:00:00.000000000 +0200
23293 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/stacktrace.c       2009-12-11 11:45:11.000000000 +0200
23294 @@ -0,0 +1,244 @@
23295 +/*
23296 + * arch/ubicom32/kernel/stacktrace.c
23297 + *   Ubicom32 architecture stack back trace implementation.
23298 + *
23299 + * (C) Copyright 2009, Ubicom, Inc.
23300 + *
23301 + * This file is part of the Ubicom32 Linux Kernel Port.
23302 + *
23303 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23304 + * it and/or modify it under the terms of the GNU General Public License
23305 + * as published by the Free Software Foundation, either version 2 of the
23306 + * License, or (at your option) any later version.
23307 + *
23308 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23309 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23310 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23311 + * the GNU General Public License for more details.
23312 + *
23313 + * You should have received a copy of the GNU General Public License
23314 + * along with the Ubicom32 Linux Kernel Port.  If not,
23315 + * see <http://www.gnu.org/licenses/>.
23316 + *
23317 + * Ubicom32 implementation derived from (with many thanks):
23318 + *   arch/m68knommu
23319 + *   arch/blackfin
23320 + *   arch/parisc
23321 + */
23322 +#include <linux/sched.h>
23323 +#include <linux/stacktrace.h>
23324 +#include <linux/module.h>
23325 +#include <asm/stacktrace.h>
23326 +#include <asm/thread.h>
23327 +#include <asm/ip5000.h>
23328 +
23329 +/*
23330 + * These symbols are filled in by the linker.
23331 + */
23332 +extern unsigned long _stext;
23333 +extern unsigned long _etext;
23334 +
23335 +extern unsigned long __ocm_text_run_begin;
23336 +extern unsigned long __data_begin;
23337 +
23338 +/*
23339 + * stacktrace_iterate()
23340 + *     Walk the stack looking for call and calli instructions on an aligned
23341 + *     boundary.
23342 + *
23343 + * Trace must point to the top of the current stack frame.
23344 + */
23345 +unsigned long stacktrace_iterate(unsigned long **trace,
23346 +                                unsigned long stext,
23347 +                                unsigned long etext,
23348 +                                unsigned long ocm_stext,
23349 +                                unsigned long ocm_etext,
23350 +                                unsigned long sstack,
23351 +                                unsigned long estack)
23352 +{
23353 +       unsigned int thread_trap_en, instruction;
23354 +       unsigned long address;
23355 +       unsigned int limit = 0;
23356 +       unsigned long result = 0;
23357 +       unsigned long *sp = *trace;
23358 +
23359 +       /*
23360 +        * Exclude the current thread from being monitored for traps.
23361 +        */
23362 +       asm volatile(
23363 +               "       thread_get_self_mask d15                \n\t"
23364 +                       /* save current trap status */
23365 +               "       and.4   %0, MT_TRAP_EN, d15             \n\t"
23366 +               "       not.4   d15, d15                        \n\t"
23367 +                       /* disable trap */
23368 +               "       and.4   MT_TRAP_EN, MT_TRAP_EN, d15     \n\t"
23369 +               "       pipe_flush 0                            \n\t"
23370 +               : "=r" (thread_trap_en)
23371 +               :
23372 +               : "d15", "cc"
23373 +       );
23374 +
23375 +       while (limit++ < 256) {
23376 +               /*
23377 +                * See if we have a valid stack.
23378 +                */
23379 +               if (!between((unsigned long)sp, sstack, estack)) {
23380 +#ifdef TRAP_DEBUG_STACK_TRACE
23381 +                       printk(KERN_EMERG "stack address is out of range - "
23382 +                              "sp: %x, sstack: %x, estack: %x\n",
23383 +                              (unsigned int)sp, (unsigned int)sstack,
23384 +                              (unsigned int)estack);
23385 +#endif
23386 +                       result = 0;
23387 +                       *trace = 0;
23388 +                       break;
23389 +               }
23390 +
23391 +               /*
23392 +                * Get the value off the stack and back up 4 bytes to what
23393 +                * should be the address of a call or calli.
23394 +                */
23395 +               address = (*sp++) - 4;
23396 +
23397 +               /*
23398 +                * If the address is not within the text segment, skip this
23399 +                * value.
23400 +                */
23401 +               if (!between(address, stext, etext) &&
23402 +                   !between(address, ocm_stext, ocm_etext)) {
23403 +#ifdef TRAP_DEBUG_STACK_TRACE
23404 +                       printk(KERN_EMERG "not a text address - "
23405 +                              "address: %08x, stext: %08x, etext: %08x\n"
23406 +                              "ocm_stext: %08x, ocm_etext: %08x\n",
23407 +                              (unsigned int)address,
23408 +                              (unsigned int)stext,
23409 +                              (unsigned int)etext,
23410 +                              (unsigned int)ocm_stext,
23411 +                              (unsigned int)ocm_etext);
23412 +#endif
23413 +                       continue;
23414 +
23415 +               }
23416 +
23417 +               /*
23418 +                * If the address is not on an aligned boundary it can not be a
23419 +                * return address.
23420 +                */
23421 +               if (address & 0x3) {
23422 +                       continue;
23423 +               }
23424 +
23425 +               /*
23426 +                * Read the probable instruction.
23427 +                */
23428 +               instruction = *(unsigned int *)address;
23429 +
23430 +               /*
23431 +                * Is this a call instruction?
23432 +                */
23433 +               if ((instruction & 0xF8000000) == (u32_t)(0x1B << 27)) {
23434 +#ifdef TRAP_DEBUG_STACK_TRACE
23435 +                       printk(KERN_EMERG "call inst. result: %x, "
23436 +                              "test: %x\n", (unsigned int)address,
23437 +                              (unsigned int)instruction);
23438 +#endif
23439 +                       *trace = sp;
23440 +                       result = address;
23441 +                       break;
23442 +               }
23443 +
23444 +               /*
23445 +                * Is this a calli instruction?
23446 +                */
23447 +               if ((instruction & 0xF8000000) == (u32_t)(0x1E << 27)) {
23448 +#ifdef TRAP_DEBUG_STACK_TRACE
23449 +                       printk(KERN_EMERG "calli inst. result: %x, "
23450 +                              "test: %x\n", (unsigned int)address,
23451 +                              (unsigned int)instruction);
23452 +#endif
23453 +                       *trace = sp;
23454 +                       result = address;
23455 +                       break;
23456 +               }
23457 +       }
23458 +
23459 +       /*
23460 +        * Restore the current thread to be monitored for traps.
23461 +        */
23462 +       if (thread_trap_en) {
23463 +               asm volatile(
23464 +               "       thread_get_self_mask d15                \n\t"
23465 +               "       or.4    MT_TRAP_EN, MT_TRAP_EN, d15     \n\t"
23466 +                       :
23467 +                       :
23468 +                       : "d15", "cc"
23469 +               );
23470 +       }
23471 +       return result;
23472 +}
23473 +
23474 +#ifdef CONFIG_STACKTRACE
23475 +/*
23476 + * stacktrace_save_entries()
23477 + *     Save stack back trace information into the provided trace structure.
23478 + */
23479 +void stacktrace_save_entries(struct task_struct *tsk,
23480 +                            struct stack_trace *trace,
23481 +                            unsigned long sp)
23482 +{
23483 +       unsigned long code_start = (unsigned long)&_stext;
23484 +       unsigned long code_end = (unsigned long)&_etext;
23485 +       unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
23486 +       unsigned long ocm_code_end = (unsigned long)&__data_begin;
23487 +       unsigned long stack_end = (unsigned long)(tsk->stack + THREAD_SIZE - 8);
23488 +       unsigned long stack = (unsigned long)sp;
23489 +       unsigned int idx = 0;
23490 +       unsigned long *handle;
23491 +       int skip = trace->skip;
23492 +
23493 +       handle = (unsigned long *)stack;
23494 +       while (idx < trace->max_entries) {
23495 +               if (skip) {
23496 +                       skip--;
23497 +                       continue;
23498 +               }
23499 +               trace->entries[idx] = stacktrace_iterate(&handle,
23500 +                                       code_start, code_end,
23501 +                                       ocm_code_start, ocm_code_end,
23502 +                                       (unsigned long)stack, stack_end);
23503 +               if (trace->entries[idx] == 0) {
23504 +                       break;
23505 +               }
23506 +               idx++;
23507 +       }
23508 +}
23509 +
23510 +/*
23511 + * save_stack_trace()
23512 + *     Save the specified amount of the kernel stack trace information
23513 + *     for the current task.
23514 + */
23515 +void save_stack_trace(struct stack_trace *trace)
23516 +{
23517 +       unsigned long sp = 0;
23518 +       asm volatile (
23519 +       "       move.4  %0, SP          \n\t"
23520 +               : "=r" (sp)
23521 +       );
23522 +       stacktrace_save_entries(current, trace, sp);
23523 +}
23524 +EXPORT_SYMBOL_GPL(save_stack_trace);
23525 +
23526 +/*
23527 + * save_stack_trace_tsk()
23528 + *     Save the specified amount of the kernel stack trace information
23529 + *     for the specified task.
23530 + *
23531 + * Note: We assume the specified task is not currently running.
23532 + */
23533 +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
23534 +{
23535 +       stacktrace_save_entries(tsk, trace, tsk->thread.sp);
23536 +}
23537 +EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
23538 +#endif /* CONFIG_STACKTRACE */
23539 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/syscalltable.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/syscalltable.S
23540 --- linux-2.6.30.10/arch/ubicom32/kernel/syscalltable.S 1970-01-01 02:00:00.000000000 +0200
23541 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/syscalltable.S     2009-12-11 11:45:11.000000000 +0200
23542 @@ -0,0 +1,376 @@
23543 +/*
23544 + * arch/ubicom32/kernel/syscalltable.S
23545 + *     <TODO: Replace with short file description>
23546 + *
23547 + * (C) Copyright 2009, Ubicom, Inc.
23548 + *
23549 + * This file is part of the Ubicom32 Linux Kernel Port.
23550 + *
23551 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23552 + * it and/or modify it under the terms of the GNU General Public License
23553 + * as published by the Free Software Foundation, either version 2 of the
23554 + * License, or (at your option) any later version.
23555 + *
23556 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23557 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23558 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23559 + * the GNU General Public License for more details.
23560 + *
23561 + * You should have received a copy of the GNU General Public License
23562 + * along with the Ubicom32 Linux Kernel Port.  If not,
23563 + * see <http://www.gnu.org/licenses/>.
23564 + *
23565 + * Ubicom32 implementation derived from (with many thanks):
23566 + *   arch/m68knommu
23567 + *   arch/blackfin
23568 + *   arch/parisc
23569 + */
23570 +/*
23571 + *
23572 + *  Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
23573 + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>, Kenneth Albanowski <kjahds@kjahds.com>,
23574 + *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
23575 + *  Copyright (C) 1991, 1992  Linus Torvalds
23576 + */
23577 +
23578 +#include <linux/sys.h>
23579 +#include <linux/linkage.h>
23580 +#include <asm/unistd.h>
23581 +
23582 +.text
23583 +ALIGN
23584 +       .global sys_call_table
23585 +sys_call_table:
23586 +       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
23587 +       .long sys_exit
23588 +       .long sys_fork
23589 +       .long sys_read
23590 +       .long sys_write
23591 +       .long sys_open          /* 5 */
23592 +       .long sys_close
23593 +       .long sys_waitpid
23594 +       .long sys_creat
23595 +       .long sys_link
23596 +       .long sys_unlink        /* 10 */
23597 +       .long execve_intercept
23598 +       .long sys_chdir
23599 +       .long sys_time
23600 +       .long sys_mknod
23601 +       .long sys_chmod         /* 15 */
23602 +       .long sys_chown16
23603 +       .long sys_ni_syscall    /* old break syscall holder */
23604 +       .long sys_stat
23605 +       .long sys_lseek
23606 +       .long sys_getpid        /* 20 */
23607 +       .long sys_mount
23608 +       .long sys_oldumount
23609 +       .long sys_setuid16
23610 +       .long sys_getuid16
23611 +       .long sys_stime         /* 25 */
23612 +       .long sys_ptrace
23613 +       .long sys_alarm
23614 +       .long sys_fstat
23615 +       .long sys_pause
23616 +       .long sys_utime         /* 30 */
23617 +       .long sys_ni_syscall    /* old stty syscall holder */
23618 +       .long sys_ni_syscall    /* old gtty syscall holder */
23619 +       .long sys_access
23620 +       .long sys_nice
23621 +       .long sys_ni_syscall    /* 35 */ /* old ftime syscall holder */
23622 +       .long sys_sync
23623 +       .long sys_kill
23624 +       .long sys_rename
23625 +       .long sys_mkdir
23626 +       .long sys_rmdir         /* 40 */
23627 +       .long sys_dup
23628 +       .long sys_pipe
23629 +       .long sys_times
23630 +       .long sys_ni_syscall    /* old prof syscall holder */
23631 +       .long sys_brk           /* 45 */
23632 +       .long sys_setgid16
23633 +       .long sys_getgid16
23634 +       .long sys_signal
23635 +       .long sys_geteuid16
23636 +       .long sys_getegid16     /* 50 */
23637 +       .long sys_acct
23638 +       .long sys_umount        /* recycled never used phys() */
23639 +       .long sys_ni_syscall    /* old lock syscall holder */
23640 +       .long sys_ioctl
23641 +       .long sys_fcntl         /* 55 */
23642 +       .long sys_ni_syscall    /* old mpx syscall holder */
23643 +       .long sys_setpgid
23644 +       .long sys_ni_syscall    /* old ulimit syscall holder */
23645 +       .long sys_ni_syscall
23646 +       .long sys_umask         /* 60 */
23647 +       .long sys_chroot
23648 +       .long sys_ustat
23649 +       .long sys_dup2
23650 +       .long sys_getppid
23651 +       .long sys_getpgrp       /* 65 */
23652 +       .long sys_setsid
23653 +       .long sys_sigaction
23654 +       .long sys_sgetmask
23655 +       .long sys_ssetmask
23656 +       .long sys_setreuid16    /* 70 */
23657 +       .long sys_setregid16
23658 +       .long sys_sigsuspend
23659 +       .long sys_sigpending
23660 +       .long sys_sethostname
23661 +       .long sys_setrlimit     /* 75 */
23662 +       .long sys_old_getrlimit
23663 +       .long sys_getrusage
23664 +       .long sys_gettimeofday
23665 +       .long sys_settimeofday
23666 +       .long sys_getgroups16   /* 80 */
23667 +       .long sys_setgroups16
23668 +       .long old_select
23669 +       .long sys_symlink
23670 +       .long sys_lstat
23671 +       .long sys_readlink      /* 85 */
23672 +       .long sys_uselib
23673 +       .long sys_ni_syscall    /* _sys_swapon */
23674 +       .long sys_reboot
23675 +       .long sys_old_readdir
23676 +       .long old_mmap          /* 90 */
23677 +       .long sys_munmap
23678 +       .long sys_truncate
23679 +       .long sys_ftruncate
23680 +       .long sys_fchmod
23681 +       .long sys_fchown16      /* 95 */
23682 +       .long sys_getpriority
23683 +       .long sys_setpriority
23684 +       .long sys_ni_syscall    /* old profil syscall holder */
23685 +       .long sys_statfs
23686 +       .long sys_fstatfs       /* 100 */
23687 +       .long sys_ni_syscall    /* ioperm for i386 */
23688 +       .long sys_socketcall
23689 +       .long sys_syslog
23690 +       .long sys_setitimer
23691 +       .long sys_getitimer     /* 105 */
23692 +       .long sys_newstat
23693 +       .long sys_newlstat
23694 +       .long sys_newfstat
23695 +       .long sys_ni_syscall
23696 +       .long sys_ni_syscall    /* iopl for i386 */ /* 110 */
23697 +       .long sys_vhangup
23698 +       .long sys_ni_syscall    /* obsolete idle() syscall */
23699 +       .long sys_ni_syscall    /* vm86old for i386 */
23700 +       .long sys_wait4
23701 +       .long sys_ni_syscall    /* 115 */ /* _sys_swapoff */
23702 +       .long sys_sysinfo
23703 +       .long sys_ipc
23704 +       .long sys_fsync
23705 +       .long sys_sigreturn
23706 +       .long clone_intercept   /* 120 */
23707 +       .long sys_setdomainname
23708 +       .long sys_newuname
23709 +       .long sys_cacheflush    /* modify_ldt for i386 */
23710 +       .long sys_adjtimex
23711 +       .long sys_ni_syscall    /* 125 */ /* _sys_mprotect */
23712 +       .long sys_sigprocmask
23713 +       .long sys_ni_syscall    /* old "creat_module" */
23714 +       .long sys_init_module
23715 +       .long sys_delete_module
23716 +       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
23717 +       .long sys_quotactl
23718 +       .long sys_getpgid
23719 +       .long sys_fchdir
23720 +       .long sys_bdflush
23721 +       .long sys_sysfs         /* 135 */
23722 +       .long sys_personality
23723 +       .long sys_ni_syscall    /* for afs_syscall */
23724 +       .long sys_setfsuid16
23725 +       .long sys_setfsgid16
23726 +       .long sys_llseek        /* 140 */
23727 +       .long sys_getdents
23728 +       .long sys_select
23729 +       .long sys_flock
23730 +       .long sys_ni_syscall    /* _sys_msync */
23731 +       .long sys_readv         /* 145 */
23732 +       .long sys_writev
23733 +       .long sys_getsid
23734 +       .long sys_fdatasync
23735 +       .long sys_sysctl
23736 +       .long sys_ni_syscall    /* 150 */ /* _sys_mlock */
23737 +       .long sys_ni_syscall    /* _sys_munlock */
23738 +       .long sys_ni_syscall    /* _sys_mlockall */
23739 +       .long sys_ni_syscall    /* _sys_munlockall */
23740 +       .long sys_sched_setparam
23741 +       .long sys_sched_getparam /* 155 */
23742 +       .long sys_sched_setscheduler
23743 +       .long sys_sched_getscheduler
23744 +       .long sys_sched_yield
23745 +       .long sys_sched_get_priority_max
23746 +       .long sys_sched_get_priority_min  /* 160 */
23747 +       .long sys_sched_rr_get_interval
23748 +       .long sys_nanosleep
23749 +       .long sys_ni_syscall    /* _sys_mremap */
23750 +       .long sys_setresuid16
23751 +       .long sys_getresuid16   /* 165 */
23752 +       .long sys_getpagesize   /* _sys_getpagesize */
23753 +       .long sys_ni_syscall    /* old "query_module" */
23754 +       .long sys_poll
23755 +       .long sys_ni_syscall    /* _sys_nfsservctl */
23756 +       .long sys_setresgid16   /* 170 */
23757 +       .long sys_getresgid16
23758 +       .long sys_prctl
23759 +       .long sys_rt_sigreturn
23760 +       .long sys_rt_sigaction
23761 +       .long sys_rt_sigprocmask /* 175 */
23762 +       .long sys_rt_sigpending
23763 +       .long sys_rt_sigtimedwait
23764 +       .long sys_rt_sigqueueinfo
23765 +       .long sys_rt_sigsuspend
23766 +       .long sys_pread64       /* 180 */
23767 +       .long sys_pwrite64
23768 +       .long sys_lchown16
23769 +       .long sys_getcwd
23770 +       .long sys_capget
23771 +       .long sys_capset        /* 185 */
23772 +       .long sys_sigaltstack
23773 +       .long sys_sendfile
23774 +       .long sys_ni_syscall    /* streams1 */
23775 +       .long sys_ni_syscall    /* streams2 */
23776 +       .long vfork_intercept           /* 190 */
23777 +       .long sys_getrlimit
23778 +       .long sys_mmap2
23779 +       .long sys_truncate64
23780 +       .long sys_ftruncate64
23781 +       .long sys_stat64        /* 195 */
23782 +       .long sys_lstat64
23783 +       .long sys_fstat64
23784 +       .long sys_chown
23785 +       .long sys_getuid
23786 +       .long sys_getgid        /* 200 */
23787 +       .long sys_geteuid
23788 +       .long sys_getegid
23789 +       .long sys_setreuid
23790 +       .long sys_setregid
23791 +       .long sys_getgroups     /* 205 */
23792 +       .long sys_setgroups
23793 +       .long sys_fchown
23794 +       .long sys_setresuid
23795 +       .long sys_getresuid
23796 +       .long sys_setresgid     /* 210 */
23797 +       .long sys_getresgid
23798 +       .long sys_lchown
23799 +       .long sys_setuid
23800 +       .long sys_setgid
23801 +       .long sys_setfsuid      /* 215 */
23802 +       .long sys_setfsgid
23803 +       .long sys_pivot_root
23804 +       .long sys_ni_syscall
23805 +       .long sys_ni_syscall
23806 +       .long sys_getdents64    /* 220 */
23807 +       .long sys_gettid
23808 +       .long sys_tkill
23809 +       .long sys_setxattr
23810 +       .long sys_lsetxattr
23811 +       .long sys_fsetxattr     /* 225 */
23812 +       .long sys_getxattr
23813 +       .long sys_lgetxattr
23814 +       .long sys_fgetxattr
23815 +       .long sys_listxattr
23816 +       .long sys_llistxattr    /* 230 */
23817 +       .long sys_flistxattr
23818 +       .long sys_removexattr
23819 +       .long sys_lremovexattr
23820 +       .long sys_fremovexattr
23821 +       .long sys_futex         /* 235 */
23822 +       .long sys_sendfile64
23823 +       .long sys_ni_syscall    /* _sys_mincore */
23824 +       .long sys_ni_syscall    /* _sys_madvise */
23825 +       .long sys_fcntl64
23826 +       .long sys_readahead     /* 240 */
23827 +       .long sys_io_setup
23828 +       .long sys_io_destroy
23829 +       .long sys_io_getevents
23830 +       .long sys_io_submit
23831 +       .long sys_io_cancel     /* 245 */
23832 +       .long sys_fadvise64
23833 +       .long sys_exit_group
23834 +       .long sys_lookup_dcookie
23835 +       .long sys_epoll_create
23836 +       .long sys_epoll_ctl     /* 250 */
23837 +       .long sys_epoll_wait
23838 +       .long sys_ni_syscall    /* _sys_remap_file_pages */
23839 +       .long sys_set_tid_address
23840 +       .long sys_timer_create
23841 +       .long sys_timer_settime /* 255 */
23842 +       .long sys_timer_gettime
23843 +       .long sys_timer_getoverrun
23844 +       .long sys_timer_delete
23845 +       .long sys_clock_settime
23846 +       .long sys_clock_gettime /* 260 */
23847 +       .long sys_clock_getres
23848 +       .long sys_clock_nanosleep
23849 +       .long sys_statfs64
23850 +       .long sys_fstatfs64
23851 +       .long sys_tgkill        /* 265 */
23852 +       .long sys_utimes
23853 +       .long sys_fadvise64_64
23854 +       .long sys_mbind
23855 +       .long sys_get_mempolicy
23856 +       .long sys_set_mempolicy /* 270 */
23857 +       .long sys_mq_open
23858 +       .long sys_mq_unlink
23859 +       .long sys_mq_timedsend
23860 +       .long sys_mq_timedreceive
23861 +       .long sys_mq_notify     /* 275 */
23862 +       .long sys_mq_getsetattr
23863 +       .long sys_waitid
23864 +       .long sys_ni_syscall    /* for _sys_vserver */
23865 +       .long sys_add_key
23866 +       .long sys_request_key   /* 280 */
23867 +       .long sys_keyctl
23868 +       .long sys_ioprio_set
23869 +       .long sys_ioprio_get
23870 +       .long sys_inotify_init
23871 +       .long sys_inotify_add_watch     /* 285 */
23872 +       .long sys_inotify_rm_watch
23873 +       .long sys_migrate_pages
23874 +       .long sys_openat
23875 +       .long sys_mkdirat
23876 +       .long sys_mknodat               /* 290 */
23877 +       .long sys_fchownat
23878 +       .long sys_futimesat
23879 +       .long sys_fstatat64
23880 +       .long sys_unlinkat
23881 +       .long sys_renameat              /* 295 */
23882 +       .long sys_linkat
23883 +       .long sys_symlinkat
23884 +       .long sys_readlinkat
23885 +       .long sys_fchmodat
23886 +       .long sys_faccessat             /* 300 */
23887 +       .long sys_ni_syscall            /* Reserved for pselect6 */
23888 +       .long sys_ni_syscall            /* Reserved for ppoll */
23889 +       .long sys_unshare
23890 +       .long sys_set_robust_list
23891 +       .long sys_get_robust_list       /* 305 */
23892 +       .long sys_splice
23893 +       .long sys_sync_file_range
23894 +       .long sys_tee
23895 +       .long sys_vmsplice
23896 +       .long sys_move_pages            /* 310 */
23897 +       .long sys_sched_setaffinity
23898 +       .long sys_sched_getaffinity
23899 +       .long sys_kexec_load
23900 +       .long sys_getcpu
23901 +       .long sys_epoll_pwait           /* 315 */
23902 +       .long sys_utimensat
23903 +       .long sys_signalfd
23904 +       .long sys_timerfd_create
23905 +       .long sys_eventfd
23906 +       .long sys_fallocate             /* 320 */
23907 +       .long sys_timerfd_settime
23908 +       .long sys_timerfd_gettime
23909 +       .long sys_ni_syscall            /* sys_signalfd4 */
23910 +       .long sys_ni_syscall            /* sys_eventfd2 */
23911 +       .long sys_ni_syscall            /* sys_epoll_create1 */
23912 +                                       /* 325 */
23913 +       .long sys_ni_syscall            /* sys_dup3 */
23914 +       .long sys_ni_syscall            /* sys_pipe2 */
23915 +       .long sys_ni_syscall            /* sys_inotify_init1 */
23916 +       .rept NR_syscalls-(.-sys_call_table)/4
23917 +               .long sys_ni_syscall
23918 +       .endr
23919 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/sys_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/sys_ubicom32.c
23920 --- linux-2.6.30.10/arch/ubicom32/kernel/sys_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
23921 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/sys_ubicom32.c     2009-12-11 11:45:11.000000000 +0200
23922 @@ -0,0 +1,237 @@
23923 +/*
23924 + * arch/ubicom32/kernel/sys_ubicom32.c
23925 + *   Ubicom32 architecture system call support implementation.
23926 + *
23927 + * (C) Copyright 2009, Ubicom, Inc.
23928 + *
23929 + * This file is part of the Ubicom32 Linux Kernel Port.
23930 + *
23931 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23932 + * it and/or modify it under the terms of the GNU General Public License
23933 + * as published by the Free Software Foundation, either version 2 of the
23934 + * License, or (at your option) any later version.
23935 + *
23936 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23937 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23938 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23939 + * the GNU General Public License for more details.
23940 + *
23941 + * You should have received a copy of the GNU General Public License
23942 + * along with the Ubicom32 Linux Kernel Port.  If not,
23943 + * see <http://www.gnu.org/licenses/>.
23944 + *
23945 + * Ubicom32 implementation derived from (with many thanks):
23946 + *   arch/m68knommu
23947 + *   arch/blackfin
23948 + *   arch/parisc
23949 + *
23950 + * This file contains various random system calls that
23951 + * have a non-standard calling sequence on the Linux/ubicom32
23952 + * platform.
23953 + */
23954 +
23955 +#include <linux/module.h>
23956 +#include <linux/errno.h>
23957 +#include <linux/sched.h>
23958 +#include <linux/mm.h>
23959 +#include <linux/smp.h>
23960 +#include <linux/sem.h>
23961 +#include <linux/msg.h>
23962 +#include <linux/shm.h>
23963 +#include <linux/stat.h>
23964 +#include <linux/syscalls.h>
23965 +#include <linux/mman.h>
23966 +#include <linux/file.h>
23967 +#include <linux/utsname.h>
23968 +#include <linux/ipc.h>
23969 +#include <linux/fs.h>
23970 +#include <linux/uaccess.h>
23971 +#include <linux/unistd.h>
23972 +
23973 +#include <asm/setup.h>
23974 +#include <asm/traps.h>
23975 +#include <asm/cacheflush.h>
23976 +
23977 +/* common code for old and new mmaps */
23978 +static inline long do_mmap2(
23979 +       unsigned long addr, unsigned long len,
23980 +       unsigned long prot, unsigned long flags,
23981 +       unsigned long fd, unsigned long pgoff)
23982 +{
23983 +       int error = -EBADF;
23984 +       struct file *file = NULL;
23985 +
23986 +       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
23987 +       if (!(flags & MAP_ANONYMOUS)) {
23988 +               file = fget(fd);
23989 +               if (!file)
23990 +                       goto out;
23991 +       }
23992 +
23993 +       down_write(&current->mm->mmap_sem);
23994 +       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
23995 +       up_write(&current->mm->mmap_sem);
23996 +
23997 +       if (file)
23998 +               fput(file);
23999 +out:
24000 +       return error;
24001 +}
24002 +
24003 +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
24004 +       unsigned long prot, unsigned long flags,
24005 +       unsigned long fd, unsigned long pgoff)
24006 +{
24007 +       return do_mmap2(addr, len, prot, flags, fd, pgoff);
24008 +}
24009 +
24010 +/*
24011 + * Perform the select(nd, in, out, ex, tv) and mmap() system
24012 + * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
24013 + * handle more than 4 system call parameters, so these system calls
24014 + * used a memory block for parameter passing..
24015 + */
24016 +
24017 +struct mmap_arg_struct {
24018 +       unsigned long addr;
24019 +       unsigned long len;
24020 +       unsigned long prot;
24021 +       unsigned long flags;
24022 +       unsigned long fd;
24023 +       unsigned long offset;
24024 +};
24025 +
24026 +asmlinkage int old_mmap(struct mmap_arg_struct *arg)
24027 +{
24028 +       struct mmap_arg_struct a;
24029 +       int error = -EFAULT;
24030 +
24031 +       if (copy_from_user(&a, arg, sizeof(a)))
24032 +               goto out;
24033 +
24034 +       error = -EINVAL;
24035 +       if (a.offset & ~PAGE_MASK)
24036 +               goto out;
24037 +
24038 +       a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
24039 +
24040 +       error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd,
24041 +                        a.offset >> PAGE_SHIFT);
24042 +out:
24043 +       return error;
24044 +}
24045 +
24046 +struct sel_arg_struct {
24047 +       unsigned long n;
24048 +       fd_set *inp, *outp, *exp;
24049 +       struct timeval *tvp;
24050 +};
24051 +
24052 +asmlinkage int old_select(struct sel_arg_struct *arg)
24053 +{
24054 +       struct sel_arg_struct a;
24055 +
24056 +       if (copy_from_user(&a, arg, sizeof(a)))
24057 +               return -EFAULT;
24058 +       /* sys_select() does the appropriate kernel locking */
24059 +       return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
24060 +}
24061 +
24062 +/*
24063 + * sys_ipc() is the de-multiplexer for the SysV IPC calls..
24064 + *
24065 + * This is really horribly ugly.
24066 + */
24067 +asmlinkage int sys_ipc(uint call, int first, int second,
24068 +                       int third, void *ptr, long fifth)
24069 +{
24070 +       int version, ret;
24071 +
24072 +       version = call >> 16; /* hack for backward compatibility */
24073 +       call &= 0xffff;
24074 +
24075 +       if (call <= SEMCTL)
24076 +               switch (call) {
24077 +               case SEMOP:
24078 +                       return sys_semop(first, (struct sembuf *)ptr, second);
24079 +               case SEMGET:
24080 +                       return sys_semget(first, second, third);
24081 +               case SEMCTL: {
24082 +                       union semun fourth;
24083 +                       if (!ptr)
24084 +                               return -EINVAL;
24085 +                       if (get_user(fourth.__pad, (void **) ptr))
24086 +                               return -EFAULT;
24087 +                       return sys_semctl(first, second, third, fourth);
24088 +                       }
24089 +               default:
24090 +                       return -EINVAL;
24091 +               }
24092 +       if (call <= MSGCTL)
24093 +               switch (call) {
24094 +               case MSGSND:
24095 +                       return sys_msgsnd(first, (struct msgbuf *) ptr,
24096 +                                         second, third);
24097 +               case MSGRCV:
24098 +                       switch (version) {
24099 +                       case 0: {
24100 +                               struct ipc_kludge tmp;
24101 +                               if (!ptr)
24102 +                                       return -EINVAL;
24103 +                               if (copy_from_user(&tmp,
24104 +                                                  (struct ipc_kludge *)ptr,
24105 +                                                  sizeof(tmp)))
24106 +                                       return -EFAULT;
24107 +                               return sys_msgrcv(first, tmp.msgp, second,
24108 +                                                  tmp.msgtyp, third);
24109 +                               }
24110 +                       default:
24111 +                               return sys_msgrcv(first,
24112 +                                                 (struct msgbuf *) ptr,
24113 +                                                 second, fifth, third);
24114 +                       }
24115 +               case MSGGET:
24116 +                       return sys_msgget((key_t) first, second);
24117 +               case MSGCTL:
24118 +                       return sys_msgctl(first, second,
24119 +                                          (struct msqid_ds *) ptr);
24120 +               default:
24121 +                       return -EINVAL;
24122 +               }
24123 +       if (call <= SHMCTL)
24124 +               switch (call) {
24125 +               case SHMAT:
24126 +                       switch (version) {
24127 +                       default: {
24128 +                               ulong raddr;
24129 +                               ret = do_shmat(first, ptr, second, &raddr);
24130 +                               if (ret)
24131 +                                       return ret;
24132 +                               return put_user(raddr, (ulong __user *) third);
24133 +                       }
24134 +                       }
24135 +               case SHMDT:
24136 +                       return sys_shmdt(ptr);
24137 +               case SHMGET:
24138 +                       return sys_shmget(first, second, third);
24139 +               case SHMCTL:
24140 +                       return sys_shmctl(first, second, ptr);
24141 +               default:
24142 +                       return -ENOSYS;
24143 +               }
24144 +
24145 +       return -EINVAL;
24146 +}
24147 +
24148 +/* sys_cacheflush -- flush (part of) the processor cache.  */
24149 +asmlinkage int
24150 +sys_cacheflush(unsigned long addr, int scope, int cache, unsigned long len)
24151 +{
24152 +       flush_cache_all();
24153 +       return 0;
24154 +}
24155 +
24156 +asmlinkage int sys_getpagesize(void)
24157 +{
24158 +       return PAGE_SIZE;
24159 +}
24160 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/thread.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/thread.c
24161 --- linux-2.6.30.10/arch/ubicom32/kernel/thread.c       1970-01-01 02:00:00.000000000 +0200
24162 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/thread.c   2009-12-11 11:45:11.000000000 +0200
24163 @@ -0,0 +1,228 @@
24164 +/*
24165 + * arch/ubicom32/kernel/thread.c
24166 + *   Ubicom32 architecture hardware thread support.
24167 + *
24168 + * (C) Copyright 2009, Ubicom, Inc.
24169 + *
24170 + * This file is part of the Ubicom32 Linux Kernel Port.
24171 + *
24172 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24173 + * it and/or modify it under the terms of the GNU General Public License
24174 + * as published by the Free Software Foundation, either version 2 of the
24175 + * License, or (at your option) any later version.
24176 + *
24177 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24178 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24179 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24180 + * the GNU General Public License for more details.
24181 + *
24182 + * You should have received a copy of the GNU General Public License
24183 + * along with the Ubicom32 Linux Kernel Port.  If not,
24184 + * see <http://www.gnu.org/licenses/>.
24185 + *
24186 + * Ubicom32 implementation derived from (with many thanks):
24187 + *   arch/m68knommu
24188 + *   arch/blackfin
24189 + *   arch/parisc
24190 + */
24191 +
24192 +#include <linux/module.h>
24193 +#include <linux/kernel.h>
24194 +#include <linux/init.h>
24195 +#include <linux/sched.h>
24196 +#include <linux/interrupt.h>
24197 +#include <linux/irq.h>
24198 +#include <linux/profile.h>
24199 +#include <linux/clocksource.h>
24200 +#include <linux/types.h>
24201 +#include <asm/ip5000.h>
24202 +#include <asm/machdep.h>
24203 +#include <asm/asm-offsets.h>
24204 +#include <asm/thread.h>
24205 +
24206 +/*
24207 + * TODO: At some point change the name here to be thread_ksp
24208 + */
24209 +unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
24210 +
24211 +static unsigned int thread_mask = -1;
24212 +static unsigned int thread_mainline_mask;
24213 +
24214 +/*
24215 + * thread_entry()
24216 + *     Returning from the called function will disable the thread.
24217 + *
24218 + * This could be a naked call to allow for hwthreads that do not have stacks.
24219 + * However, with -O0, the code still writes to thex stack, and this was
24220 + * corrupting memory just after the callers stack.
24221 + */
24222 +static void thread_entry(void *arg, thread_exec_fn_t exec)
24223 +{
24224 +       /*
24225 +        * Call thread function
24226 +        */
24227 +       exec(arg);
24228 +
24229 +       /*
24230 +        * Complete => Disable self
24231 +        */
24232 +       thread_disable(thread_get_self());
24233 +}
24234 +
24235 +/*
24236 + * thread_start()
24237 + *     Start the specified function on the specified hardware thread.
24238 + */
24239 +thread_t thread_start(thread_t thread,
24240 +                     thread_exec_fn_t exec,
24241 +                     void *arg,
24242 +                     unsigned int *sp_high,
24243 +                     thread_type_t type)
24244 +{
24245 +       /*
24246 +        * Sanity check
24247 +        */
24248 +       unsigned int enabled, mask, csr;
24249 +       asm volatile (
24250 +               "move.4         %0, MT_EN\n\t"
24251 +               : "=m" (enabled)
24252 +       );
24253 +
24254 +       mask = 1 << thread;
24255 +       if (enabled & mask) {
24256 +               printk(KERN_WARNING "request to enable a previously enabled thread\n");
24257 +               return (thread_t)-1;
24258 +       }
24259 +
24260 +       /*
24261 +        * Update thread state
24262 +        */
24263 +       csr = (thread << 15) | (1 << 14);
24264 +       asm volatile (
24265 +               "setcsr         %0              \n\t"
24266 +               "setcsr_flush   0               \n\t"
24267 +
24268 +               "move.4         A0, #0          \n\t"
24269 +               "move.4         A1, #0          \n\t"
24270 +               "move.4         A2, #0          \n\t"
24271 +               "move.4         A3, #0          \n\t"
24272 +               "move.4         A4, #0          \n\t"
24273 +               "move.4         A5, #0          \n\t"
24274 +               "move.4         A6, #0          \n\t"
24275 +               "move.4         SP, %4          \n\t"   /* A7 is SP */
24276 +
24277 +               "move.4         D0, %3          \n\t"
24278 +               "move.4         D1, %2          \n\t"
24279 +               "move.4         D2, #0          \n\t"
24280 +               "move.4         D3, #0          \n\t"
24281 +               "move.4         D4, #0          \n\t"
24282 +               "move.4         D5, #0          \n\t"
24283 +               "move.4         D6, #0          \n\t"
24284 +               "move.4         D7, #0          \n\t"
24285 +               "move.4         D8, #0          \n\t"
24286 +               "move.4         D9, #0          \n\t"
24287 +               "move.4         D10, #0         \n\t"
24288 +               "move.4         D11, #0         \n\t"
24289 +               "move.4         D12, #0         \n\t"
24290 +               "move.4         D13, #0         \n\t"
24291 +               "move.4         D14, #0         \n\t"
24292 +               "move.4         D15, #0         \n\t"
24293 +
24294 +               "move.4         INT_MASK0, #0   \n\t"
24295 +               "move.4         INT_MASK1, #0   \n\t"
24296 +               "move.4         PC, %1          \n\t"
24297 +               "setcsr         #0              \n\t"
24298 +               "setcsr_flush   0               \n\t"
24299 +               :
24300 +               : "r" (csr), "r" (thread_entry), "r" (exec),
24301 +                 "r" (arg), "r" (sp_high)
24302 +       );
24303 +
24304 +       /*
24305 +        * Apply HRT state
24306 +        */
24307 +       if (type & THREAD_TYPE_HRT) {
24308 +               asm volatile (
24309 +                       "or.4           MT_HRT, MT_HRT, %0\n\t"
24310 +                       :
24311 +                       : "d" (mask)
24312 +                       : "cc"
24313 +               );
24314 +       } else {
24315 +               asm volatile (
24316 +                       "and.4          MT_HRT, MT_HRT, %0\n\t"
24317 +                       :
24318 +                       : "d" (~mask)
24319 +                       : "cc"
24320 +               );
24321 +       }
24322 +
24323 +       /*
24324 +        * Set priority
24325 +        */
24326 +       asm volatile (
24327 +               "or.4           MT_HPRI, MT_HPRI, %0\n\t"
24328 +               :
24329 +               : "d" (mask)
24330 +               : "cc"
24331 +       );
24332 +
24333 +       /*
24334 +        * Enable thread
24335 +        */
24336 +       asm volatile (
24337 +               "move.4         MT_ACTIVE_SET, %0       \n\t"
24338 +               :
24339 +               : "d" (mask)
24340 +       );
24341 +       thread_enable_mask(mask);
24342 +       return thread;
24343 +}
24344 +
24345 +/*
24346 + * thread_get_mainline()
24347 + *     Return a mask of those threads that are Linux mainline threads.
24348 + */
24349 +unsigned int thread_get_mainline(void)
24350 +{
24351 +       return thread_mainline_mask;
24352 +}
24353 +
24354 +/*
24355 + * thread_set_mainline()
24356 + *     Indicate that the specified thread is a Linux mainline thread.
24357 + */
24358 +void thread_set_mainline(thread_t tid)
24359 +{
24360 +       thread_mainline_mask |= (1 << tid);
24361 +}
24362 +
24363 +/*
24364 + * thread_alloc()
24365 + *     Allocate an unused hardware thread.
24366 + */
24367 +thread_t thread_alloc(void)
24368 +{
24369 +       thread_t tid;
24370 +
24371 +       /*
24372 +        * If this is the first time we are here get the list of unused
24373 +        * threads from the processor device tree node.
24374 +        */
24375 +       if (thread_mask == -1) {
24376 +               thread_mask = processor_threads();
24377 +       }
24378 +
24379 +       if (!thread_mask) {
24380 +               return (thread_t)-1;
24381 +       }
24382 +
24383 +       tid = ffs(thread_mask);
24384 +       if (tid != 0) {
24385 +               tid--;
24386 +               thread_mask &= ~(1 << tid);
24387 +               return tid;
24388 +       }
24389 +
24390 +       return (thread_t)-1;
24391 +}
24392 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/time.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/time.c
24393 --- linux-2.6.30.10/arch/ubicom32/kernel/time.c 1970-01-01 02:00:00.000000000 +0200
24394 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/time.c     2009-12-11 11:45:11.000000000 +0200
24395 @@ -0,0 +1,212 @@
24396 +/*
24397 + * arch/ubicom32/kernel/time.c
24398 + *     Initialize the timer list and start the appropriate timers.
24399 + *
24400 + * (C) Copyright 2009, Ubicom, Inc.
24401 + * Copyright (C) 1991, 1992, 1995  Linus Torvalds
24402 + *
24403 + * This file is part of the Ubicom32 Linux Kernel Port.
24404 + *
24405 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24406 + * it and/or modify it under the terms of the GNU General Public License
24407 + * as published by the Free Software Foundation, either version 2 of the
24408 + * License, or (at your option) any later version.
24409 + *
24410 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24411 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24412 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24413 + * the GNU General Public License for more details.
24414 + *
24415 + * You should have received a copy of the GNU General Public License
24416 + * along with the Ubicom32 Linux Kernel Port.  If not,
24417 + * see <http://www.gnu.org/licenses/>.
24418 + *
24419 + * Ubicom32 implementation derived from (with many thanks):
24420 + *   arch/m68knommu
24421 + *   arch/blackfin
24422 + *   arch/parisc
24423 + */
24424 +
24425 +#include <linux/profile.h>
24426 +#include <linux/smp.h>
24427 +#include <asm/ip5000.h>
24428 +#include <asm/machdep.h>
24429 +
24430 +/*
24431 + * A bitmap of the timers on the processor indicates
24432 + * that the timer is free or in-use.
24433 + */
24434 +static unsigned int timers;
24435 +
24436 +/*
24437 + * timer_set()
24438 + *     Init the specified compare register to go off <n> cycles from now.
24439 + */
24440 +void timer_set(int timervector, unsigned int cycles)
24441 +{
24442 +       int idx = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24443 +       UBICOM32_IO_TIMER->syscom[idx] =
24444 +                       UBICOM32_IO_TIMER->sysval + cycles;
24445 +       ldsr_enable_vector(timervector);
24446 +}
24447 +
24448 +/*
24449 + * timer_reset()
24450 + *     Set/reset the timer to go off again.
24451 + *
24452 + * Because sysval is a continuous timer, this function is able
24453 + * to ensure that we do not have clock sku by using the previous
24454 + * value in syscom to set the next value for syscom.
24455 + *
24456 + * Returns the number of ticks that transpired since the last event.
24457 + */
24458 +int timer_reset(int timervector, unsigned int cycles)
24459 +{
24460 +       /*
24461 +        * Reset the timer in the LDSR thread to go off appropriately.
24462 +        *
24463 +        * Use the previous value of the timer to calculate the new stop
24464 +        * time.  This allows us to account for it taking an
24465 +        * indeterminate amount of time to get here.
24466 +        */
24467 +       const int timer_index = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24468 +       unsigned int prev = UBICOM32_IO_TIMER->syscom[timer_index];
24469 +       unsigned int next = prev + cycles;
24470 +       int scratchpad3;
24471 +       int diff;
24472 +       int ticks = 1;
24473 +
24474 +       /*
24475 +        * If the difference is negative, we have missed at least one
24476 +        * timer tick.
24477 +        *
24478 +        * TODO: Decide if we want to "ignore" time (as done below) or
24479 +        * if we want to process time (unevenly) by calling timer_tick()
24480 +        * lost_ticks times.
24481 +        */
24482 +       while (1) {
24483 +               /*
24484 +                * Set our future time first.
24485 +                */
24486 +               UBICOM32_IO_TIMER->syscom[timer_index] = next;
24487 +
24488 +               /*
24489 +                * Then check if we are really set time in the futrue.
24490 +                */
24491 +               diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24492 +               if (diff >= 0) {
24493 +                       break;
24494 +               }
24495 +
24496 +               /*
24497 +                * Oops, we are too slow. Playing catch up.
24498 +                *
24499 +                * If the debugger is connected the there is a good
24500 +                * chance that we lost time because we were in a
24501 +                * break-point, so in this case we do not print out
24502 +                * diagnostics.
24503 +                */
24504 +               asm volatile ("move.4 %0, scratchpad3"
24505 +                             : "=r" (scratchpad3));
24506 +               if ((scratchpad3 & 0x1) == 0) {
24507 +                       /*
24508 +                        * No debugger attached, print to the console
24509 +                        */
24510 +                       printk(KERN_EMERG "diff: %d, timer has lost %u "
24511 +                              "ticks [rounded up]\n",
24512 +                              -diff,
24513 +                              (unsigned int)((-diff + cycles - 1) / cycles));
24514 +               }
24515 +
24516 +               do {
24517 +                       next += cycles;
24518 +                       diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24519 +                       ticks++;
24520 +               } while (diff < 0);
24521 +       }
24522 +       return ticks;
24523 +}
24524 +
24525 +/*
24526 + * sched_clock()
24527 + *     Returns current time in nano-second units.
24528 + *
24529 + * Notes:
24530 + * 1) This is an override for the weak alias in
24531 + * kernel/sched_clock.c.
24532 + * 2) Do not use xtime_lock as this function is
24533 + * sometimes called with xtime_lock held.
24534 + * 3) We use a retry algorithm to ensure that
24535 + * we get a consistent value.
24536 + * 4) sched_clock must be overwritten if IRQ tracing
24537 + * is enabled because the default implementation uses
24538 + * the xtime_lock sequence while holding xtime_lock.
24539 + */
24540 +unsigned long long sched_clock(void)
24541 +{
24542 +       unsigned long long my_jiffies;
24543 +       unsigned long jiffies_top;
24544 +       unsigned long jiffies_bottom;
24545 +
24546 +       do {
24547 +               jiffies_top = jiffies_64 >> 32;
24548 +               jiffies_bottom = jiffies_64 & 0xffffffff;
24549 +       } while (unlikely(jiffies_top != (unsigned long)(jiffies_64 >> 32)));
24550 +
24551 +       my_jiffies = ((unsigned long long)jiffies_top << 32) | (jiffies_bottom);
24552 +       return (my_jiffies - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
24553 +}
24554 +
24555 +/*
24556 + * timer_free()
24557 + *     Free a hardware timer.
24558 + */
24559 +void timer_free(int interrupt)
24560 +{
24561 +       unsigned int bit = interrupt - TIMER_INT(0);
24562 +
24563 +       /*
24564 +        * The timer had not been allocated.
24565 +        */
24566 +       BUG_ON(timers & (1 << bit));
24567 +       timers |= (1 << bit);
24568 +}
24569 +
24570 +/*
24571 + * timer_alloc()
24572 + *     Allocate a hardware timer.
24573 + */
24574 +int timer_alloc(void)
24575 +{
24576 +       unsigned int bit = find_first_bit((unsigned long *)&timers, 32);
24577 +       if (!bit) {
24578 +               printk(KERN_WARNING "no more free timers\n");
24579 +               return -1;
24580 +       }
24581 +
24582 +       timers &= ~(1 << bit);
24583 +       return bit + TIMER_INT(0);
24584 +}
24585 +
24586 +/*
24587 + * time_init()
24588 + *     Time init function.
24589 + */
24590 +void time_init(void)
24591 +{
24592 +       /*
24593 +        * Find the processor node and determine what timers are
24594 +        * available for us.
24595 +        */
24596 +       timers = processor_timers();
24597 +       if (timers == 0) {
24598 +               printk(KERN_WARNING "no timers are available for Linux\n");
24599 +               return;
24600 +       }
24601 +
24602 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
24603 +       timer_device_init();
24604 +#else
24605 +       timer_tick_init();
24606 +#endif
24607 +}
24608 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/timer_broadcast.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_broadcast.c
24609 --- linux-2.6.30.10/arch/ubicom32/kernel/timer_broadcast.c      1970-01-01 02:00:00.000000000 +0200
24610 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_broadcast.c  2009-12-11 11:45:11.000000000 +0200
24611 @@ -0,0 +1,102 @@
24612 +/*
24613 + * arch/ubicom32/kernel/timer_broadcast.c
24614 + *   Implements a dummy clock event for each cpu.
24615 + *
24616 + * Copyright (C) 2008  Paul Mundt
24617 + * (C) Copyright 2009, Ubicom, Inc.
24618 + *
24619 + * This file is part of the Ubicom32 Linux Kernel Port.
24620 + *
24621 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24622 + * it and/or modify it under the terms of the GNU General Public License
24623 + * as published by the Free Software Foundation, either version 2 of the
24624 + * License, or (at your option) any later version.
24625 + *
24626 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24627 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24628 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24629 + * the GNU General Public License for more details.
24630 + *
24631 + * You should have received a copy of the GNU General Public License
24632 + * along with the Ubicom32 Linux Kernel Port.  If not,
24633 + * see <http://www.gnu.org/licenses/>.
24634 + *
24635 + * Ubicom32 implementation derived from (with many thanks):
24636 + *   arch/m68knommu
24637 + *   arch/blackfin
24638 + *   arch/parisc
24639 + *   arch/arm
24640 + *   arch/sh
24641 + */
24642 +#include <linux/init.h>
24643 +#include <linux/kernel.h>
24644 +#include <linux/delay.h>
24645 +#include <linux/device.h>
24646 +#include <linux/smp.h>
24647 +#include <linux/jiffies.h>
24648 +#include <linux/percpu.h>
24649 +#include <linux/clockchips.h>
24650 +#include <linux/irq.h>
24651 +
24652 +static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
24653 +
24654 +/*
24655 + *  The broadcast trick only works when the timer will be used in a periodic mode.
24656 + *  If the user has configured either NO_HZ or HIGH_RES_TIMERS they must have
24657 + *  a per cpu timer.
24658 + */
24659 +#if defined(CONFIG_NO_HZ) || defined(CONFIG_HIGH_RES_TIMERS)
24660 +#error "Tickless and High Resolution Timers require per-CPU local timers: CONFIG_LOCAL_TIMERS"
24661 +#endif
24662 +
24663 +/*
24664 + * local_timer_interrupt()
24665 + *     Used on SMP for local timer interrupt sent via an IPI.
24666 + */
24667 +void local_timer_interrupt(void)
24668 +{
24669 +       struct clock_event_device *dev = &__get_cpu_var(local_clockevent);
24670 +
24671 +       dev->event_handler(dev);
24672 +}
24673 +
24674 +/*
24675 + * dummy_timer_set_next_event()
24676 + *     Cause the timer to go off "cycles" from now.
24677 + */
24678 +static int dummy_timer_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24679 +{
24680 +       return 0;
24681 +}
24682 +
24683 +/*
24684 + * dummy_timer_set_mode()
24685 + *     Do Nothing.
24686 + */
24687 +static void dummy_timer_set_mode(enum clock_event_mode mode,
24688 +                                struct clock_event_device *clk)
24689 +{
24690 +}
24691 +
24692 +/*
24693 + * local_timer_setup()
24694 + *     Adds a clock event for the specified cpu.
24695 + */
24696 +int __cpuinit local_timer_setup(unsigned int cpu)
24697 +{
24698 +       struct clock_event_device *dev = &per_cpu(local_clockevent, cpu);
24699 +
24700 +       dev->name               = "timer-dummy";
24701 +       dev->features           = CLOCK_EVT_FEAT_DUMMY;
24702 +       dev->rating             = 200;
24703 +       dev->mult               = 1;
24704 +       dev->set_mode           = dummy_timer_set_mode;
24705 +       dev->set_next_event     = dummy_timer_set_next_event;
24706 +       dev->broadcast          = smp_timer_broadcast;
24707 +       dev->cpumask            = cpumask_of_cpu(cpu);
24708 +       dev->irq                = -1;
24709 +       printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24710 +
24711 +       clockevents_register_device(dev);
24712 +       return 0;
24713 +}
24714 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/timer_device.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_device.c
24715 --- linux-2.6.30.10/arch/ubicom32/kernel/timer_device.c 1970-01-01 02:00:00.000000000 +0200
24716 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_device.c     2009-12-11 11:45:11.000000000 +0200
24717 @@ -0,0 +1,301 @@
24718 +/*
24719 + * arch/ubicom32/kernel/timer_device.c
24720 + *   Implements a Ubicom32 clock device and event devices.
24721 + *
24722 + * (C) Copyright 2009, Ubicom, Inc.
24723 + *
24724 + * This file is part of the Ubicom32 Linux Kernel Port.
24725 + *
24726 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24727 + * it and/or modify it under the terms of the GNU General Public License
24728 + * as published by the Free Software Foundation, either version 2 of the
24729 + * License, or (at your option) any later version.
24730 + *
24731 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24732 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24733 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24734 + * the GNU General Public License for more details.
24735 + *
24736 + * You should have received a copy of the GNU General Public License
24737 + * along with the Ubicom32 Linux Kernel Port.  If not,
24738 + * see <http://www.gnu.org/licenses/>.
24739 + *
24740 + * Ubicom32 implementation derived from (with many thanks):
24741 + *   arch/m68knommu
24742 + *   arch/blackfin
24743 + *   arch/parisc
24744 + */
24745 +#include <linux/types.h>
24746 +#include <linux/clockchips.h>
24747 +#include <linux/clocksource.h>
24748 +#include <linux/spinlock.h>
24749 +#include <asm/ip5000.h>
24750 +#include <asm/machdep.h>
24751 +
24752 +#if defined(CONFIG_SMP)
24753 +#include <asm/smp.h>
24754 +#endif
24755 +
24756 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
24757 +#define MAX_TIMERS (2 + CONFIG_TIMER_EXTRA_ALLOC)
24758 +#else
24759 +#define MAX_TIMERS (NR_CPUS + CONFIG_TIMER_EXTRA_ALLOC)
24760 +#endif
24761 +
24762 +#if (MAX_TIMERS > 10)
24763 +#error "Ubicom32 only has 10 timers"
24764 +#endif
24765 +
24766 +static unsigned int frequency;
24767 +static struct clock_event_device timer_device_devs[MAX_TIMERS];
24768 +static struct irqaction timer_device_irqs[MAX_TIMERS];
24769 +static int timer_device_next_timer = 0;
24770 +
24771 +DEFINE_SPINLOCK(timer_device_lock);
24772 +
24773 +/*
24774 + * timer_device_set_next_event()
24775 + *     Cause the timer to go off "cycles" from now.
24776 + */
24777 +static int timer_device_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24778 +{
24779 +       timer_set(dev->irq, cycles);
24780 +       return 0;
24781 +}
24782 +
24783 +/*
24784 + * timer_device_set_mode()
24785 + *     Handle the mode switch for a clock event device.
24786 + */
24787 +static void timer_device_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
24788 +{
24789 +       switch (mode) {
24790 +       case CLOCK_EVT_MODE_SHUTDOWN:
24791 +               /*
24792 +                * Make sure the vector is disabled
24793 +                * until the next event is set.
24794 +                */
24795 +               printk(KERN_NOTICE "timer[%d]: shutdown\n", dev->irq);
24796 +               ldsr_disable_vector(dev->irq);
24797 +               break;
24798 +
24799 +       case CLOCK_EVT_MODE_ONESHOT:
24800 +               /*
24801 +                * Make sure the vector is disabled
24802 +                * until the next event is set.
24803 +                */
24804 +               printk(KERN_NOTICE "timer[%d]: oneshot\n", dev->irq);
24805 +               ldsr_disable_vector(dev->irq);
24806 +               break;
24807 +
24808 +       case CLOCK_EVT_MODE_PERIODIC:
24809 +               /*
24810 +                * The periodic request is 1 per jiffies
24811 +                */
24812 +               printk(KERN_NOTICE "timer[%d]: periodic: %d cycles\n",
24813 +                       dev->irq, frequency / CONFIG_HZ);
24814 +               timer_set(dev->irq, frequency / CONFIG_HZ);
24815 +               break;
24816 +
24817 +       case CLOCK_EVT_MODE_UNUSED:
24818 +       case CLOCK_EVT_MODE_RESUME:
24819 +               printk(KERN_WARNING "timer[%d]: unimplemented mode: %d\n",
24820 +                       dev->irq, mode);
24821 +               break;
24822 +       };
24823 +}
24824 +
24825 +/*
24826 + * timer_device_event()
24827 + *     Call the device's event handler.
24828 + *
24829 + * The pointer is initialized by the generic Linux code
24830 + * to the function to be called.
24831 + */
24832 +static irqreturn_t timer_device_event(int irq, void *dev_id)
24833 +{
24834 +       struct clock_event_device *dev = (struct clock_event_device *)dev_id;
24835 +
24836 +       if (dev->mode == CLOCK_EVT_MODE_PERIODIC) {
24837 +               /*
24838 +                * The periodic request is 1 per jiffies
24839 +                */
24840 +               timer_reset(dev->irq, frequency / CONFIG_HZ);
24841 +       } else {
24842 +               /*
24843 +                * The timer will go off again at the rollover
24844 +                * point.  We must disable the IRQ to prevent
24845 +                * getting a spurious interrupt.
24846 +                */
24847 +               ldsr_disable_vector(dev->irq);
24848 +       }
24849 +
24850 +       if (!dev->event_handler) {
24851 +               printk(KERN_CRIT "no registered event handler\n");
24852 +               return IRQ_HANDLED;
24853 +       }
24854 +
24855 +       dev->event_handler(dev);
24856 +       return IRQ_HANDLED;
24857 +}
24858 +
24859 +/*
24860 + * timer_device_clockbase_read()
24861 + *     Provide a primary clocksource around the sysval timer.
24862 + */
24863 +static cycle_t timer_device_clockbase_read(void)
24864 +{
24865 +       return (cycle_t)UBICOM32_IO_TIMER->sysval;
24866 +}
24867 +
24868 +/*
24869 + * Primary Clock Source Description
24870 + *
24871 + * We use 24 for the shift factor because we want
24872 + * to ensure there are less than 2^24 clocks
24873 + * in a jiffie of 10 ms.
24874 + */
24875 +static struct clocksource timer_device_clockbase = {
24876 +       .name   = "sysval",
24877 +       .rating = 400,
24878 +       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
24879 +       .mask   = CLOCKSOURCE_MASK(32),
24880 +       .shift  = 24,
24881 +       .mult   = 0,
24882 +       .read   = timer_device_clockbase_read,
24883 +};
24884 +
24885 +/*
24886 + * timer_device_alloc_event()
24887 + *     Allocate a timer device event.
24888 + */
24889 +static int timer_device_alloc_event(const char *name, int cpuid, const cpumask_t *mask)
24890 +{
24891 +       struct clock_event_device *dev;
24892 +       struct irqaction *action;
24893 +
24894 +       /*
24895 +        * Are we out of configured timers?
24896 +        */
24897 +       spin_lock(&timer_device_lock);
24898 +       if (timer_device_next_timer >= MAX_TIMERS) {
24899 +               spin_unlock(&timer_device_lock);
24900 +               printk(KERN_WARNING "out of timer event entries\n");
24901 +               return -1;
24902 +       }
24903 +       dev = &timer_device_devs[timer_device_next_timer];
24904 +       action = &timer_device_irqs[timer_device_next_timer];
24905 +       timer_device_next_timer++;
24906 +       spin_unlock(&timer_device_lock);
24907 +
24908 +       /*
24909 +        * Now allocate a timer to ourselves.
24910 +        */
24911 +       dev->irq = timer_alloc();
24912 +       if (dev->irq == -1) {
24913 +               spin_lock(&timer_device_lock);
24914 +               timer_device_next_timer--;
24915 +               spin_unlock(&timer_device_lock);
24916 +               printk(KERN_WARNING "out of hardware timers\n");
24917 +               return -1;
24918 +       }
24919 +
24920 +       /*
24921 +        * Init the IRQ action structure.  Make sure
24922 +        * this in place before you register the clock
24923 +        * event device.
24924 +        */
24925 +       action->name = name;
24926 +       action->flags = IRQF_DISABLED | IRQF_TIMER;
24927 +       action->handler = timer_device_event;
24928 +       cpumask_copy(&action->mask, mask);
24929 +       action->dev_id = dev;
24930 +       setup_irq(dev->irq, action);
24931 +       irq_set_affinity(dev->irq, mask);
24932 +       ldsr_disable_vector(dev->irq);
24933 +
24934 +       /*
24935 +        * init clock dev structure.
24936 +        *
24937 +        * The min_delta_ns is chosen to ensure that setting next
24938 +        * event will never be requested with too small of value.
24939 +        */
24940 +       dev->name = name;
24941 +       dev->rating = timer_device_clockbase.rating;
24942 +       dev->shift = timer_device_clockbase.shift;
24943 +       dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
24944 +       dev->set_mode = timer_device_set_mode;
24945 +       dev->set_next_event = timer_device_set_next_event;
24946 +       dev->mult = div_sc(frequency, NSEC_PER_SEC, dev->shift);
24947 +       dev->max_delta_ns = clockevent_delta2ns(0xffffffff, dev);
24948 +       dev->min_delta_ns = clockevent_delta2ns(100, dev);
24949 +       dev->cpumask = mask;
24950 +       printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24951 +
24952 +       /*
24953 +        * Now register the device.
24954 +        */
24955 +       clockevents_register_device(dev);
24956 +       return dev->irq;
24957 +}
24958 +
24959 +#if defined(CONFIG_LOCAL_TIMERS)
24960 +/*
24961 + * local_timer_setup()
24962 + *     Allocation function for creating a per cpu local timer.
24963 + */
24964 +int __cpuinit local_timer_setup(unsigned int cpu)
24965 +{
24966 +       return timer_device_alloc_event("timer-cpu", cpu, cpumask_of(cpu));
24967 +}
24968 +#endif
24969 +
24970 +/*
24971 + * timer_device_init()
24972 + *     Create and init a generic clock driver for Ubicom32.
24973 + */
24974 +void timer_device_init(void)
24975 +{
24976 +       int i;
24977 +
24978 +       /*
24979 +        * Get the frequency from the processor device tree node or use
24980 +        * the default if not available. We will store this as the frequency
24981 +        * of the timer to avoid future calculations.
24982 +        */
24983 +       frequency = processor_frequency();
24984 +       if (frequency == 0) {
24985 +               frequency = CLOCK_TICK_RATE;
24986 +       }
24987 +
24988 +       /*
24989 +        * Setup the primary clock source around sysval.  Linux does not
24990 +        * supply a Mhz multiplier so convert down to khz.
24991 +        */
24992 +       timer_device_clockbase.mult =
24993 +               clocksource_khz2mult(frequency / 1000,
24994 +                       timer_device_clockbase.shift);
24995 +       if (clocksource_register(&timer_device_clockbase)) {
24996 +               printk(KERN_ERR "timer: clocksource failed to register\n");
24997 +               return;
24998 +       }
24999 +
25000 +       /*
25001 +        * Always allocate a primary timer.
25002 +        */
25003 +       timer_device_alloc_event("timer-primary", -1, CPU_MASK_ALL_PTR);
25004 +
25005 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
25006 +       /*
25007 +        * If BROADCAST is selected we need to add a broadcast timer.
25008 +        */
25009 +       timer_device_alloc_event("timer-broadcast", -1, CPU_MASK_ALL_PTR);
25010 +#endif
25011 +
25012 +       /*
25013 +        * Allocate extra timers that are requested.
25014 +        */
25015 +       for (i = 0; i < CONFIG_TIMER_EXTRA_ALLOC; i++) {
25016 +               timer_device_alloc_event("timer-extra", -1, CPU_MASK_ALL_PTR);
25017 +       }
25018 +}
25019 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/timer_tick.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_tick.c
25020 --- linux-2.6.30.10/arch/ubicom32/kernel/timer_tick.c   1970-01-01 02:00:00.000000000 +0200
25021 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_tick.c       2009-12-11 11:45:11.000000000 +0200
25022 @@ -0,0 +1,109 @@
25023 +/*
25024 + * arch/ubicom32/kernel/timer_tick.c
25025 + *     Impelemets a perodic timer.
25026 + *
25027 + * (C) Copyright 2009, Ubicom, Inc.
25028 + * Copyright (C) 1991, 1992, 1995  Linus Torvalds
25029 + *
25030 + * This file is part of the Ubicom32 Linux Kernel Port.
25031 + *
25032 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25033 + * it and/or modify it under the terms of the GNU General Public License
25034 + * as published by the Free Software Foundation, either version 2 of the
25035 + * License, or (at your option) any later version.
25036 + *
25037 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25038 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25039 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25040 + * the GNU General Public License for more details.
25041 + *
25042 + * You should have received a copy of the GNU General Public License
25043 + * along with the Ubicom32 Linux Kernel Port.  If not,
25044 + * see <http://www.gnu.org/licenses/>.
25045 + *
25046 + * Ubicom32 implementation derived from (with many thanks):
25047 + *   arch/m68knommu
25048 + *   arch/blackfin
25049 + *   arch/parisc
25050 + */
25051 +
25052 +#include <linux/profile.h>
25053 +
25054 +#include <asm/ip5000.h>
25055 +#include <asm/machdep.h>
25056 +#if defined(CONFIG_SMP)
25057 +#include <asm/smp.h>
25058 +#endif
25059 +
25060 +static unsigned int timervector;
25061 +static unsigned int frequency;
25062 +
25063 +/*
25064 + * timer_tick()
25065 + *     Kernel system timer support. Needs to keep up the real-time clock,
25066 + *     as well as call the "do_timer()" routine every clocktick.
25067 + */
25068 +static irqreturn_t timer_tick(int irq, void *dummy)
25069 +{
25070 +       int ticks;
25071 +
25072 +       BUG_ON(!irqs_disabled());
25073 +       ticks = timer_reset(timervector, frequency);
25074 +
25075 +       write_seqlock(&xtime_lock);
25076 +       do_timer(ticks);
25077 +       write_sequnlock(&xtime_lock);
25078 +
25079 +       update_process_times(user_mode(get_irq_regs()));
25080 +       profile_tick(CPU_PROFILING);
25081 +
25082 +#if defined(CONFIG_SMP)
25083 +       smp_send_timer_all();
25084 +#endif
25085 +       return(IRQ_HANDLED);
25086 +}
25087 +
25088 +/*
25089 + * Data used by setup_irq for the timer.
25090 + */
25091 +static struct irqaction timer_irq = {
25092 +       .name    = "timer",
25093 +       .flags   = IRQF_DISABLED | IRQF_TIMER,
25094 +       .handler = timer_tick,
25095 +};
25096 +
25097 +/*
25098 + * timer_tick_init()
25099 + *     Implements a periodic timer
25100 + *
25101 + * This implementation directly calls the timer_tick() and move
25102 + * the Linux kernel forward.  This is used when the user has not
25103 + * selected GENERIC_CLOCKEVENTS.
25104 + */
25105 +void timer_tick_init(void)
25106 +{
25107 +       /*
25108 +        * Now allocate a timer to ourselves.
25109 +        */
25110 +       timervector = timer_alloc();
25111 +       if (timervector == -1) {
25112 +               printk(KERN_WARNING "where did the timer go?\n");
25113 +               return;
25114 +       }
25115 +
25116 +       setup_irq(timervector, &timer_irq);
25117 +
25118 +       /*
25119 +        * Get the frequency from the processor device tree node or use
25120 +        * the default if not available. We will store this as the frequency
25121 +        * of the timer to avoid future calculations.
25122 +        */
25123 +       frequency = processor_frequency();
25124 +       if (frequency == 0) {
25125 +               frequency = CLOCK_TICK_RATE;
25126 +       }
25127 +       frequency /= CONFIG_HZ;
25128 +
25129 +       printk(KERN_NOTICE "timer will interrupt every: %d cycles\n", frequency);
25130 +       timer_set(timervector, frequency);
25131 +}
25132 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/topology.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/topology.c
25133 --- linux-2.6.30.10/arch/ubicom32/kernel/topology.c     1970-01-01 02:00:00.000000000 +0200
25134 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/topology.c 2009-12-11 11:45:11.000000000 +0200
25135 @@ -0,0 +1,47 @@
25136 +/*
25137 + * arch/ubicom32/kernel/topology.c
25138 + *   Ubicom32 architecture sysfs topology information.
25139 + *
25140 + * (C) Copyright 2009, Ubicom, Inc.
25141 + *
25142 + * This file is part of the Ubicom32 Linux Kernel Port.
25143 + *
25144 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25145 + * it and/or modify it under the terms of the GNU General Public License
25146 + * as published by the Free Software Foundation, either version 2 of the
25147 + * License, or (at your option) any later version.
25148 + *
25149 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25150 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25151 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25152 + * the GNU General Public License for more details.
25153 + *
25154 + * You should have received a copy of the GNU General Public License
25155 + * along with the Ubicom32 Linux Kernel Port.  If not,
25156 + * see <http://www.gnu.org/licenses/>.
25157 + *
25158 + * Ubicom32 implementation derived from (with many thanks):
25159 + *   arch/m68knommu
25160 + *   arch/blackfin
25161 + *   arch/parisc
25162 + */
25163 +
25164 +#include <linux/init.h>
25165 +#include <linux/smp.h>
25166 +#include <linux/cpu.h>
25167 +#include <linux/cache.h>
25168 +
25169 +static struct cpu cpu_devices[NR_CPUS] __read_mostly;
25170 +
25171 +static int __init topology_init(void)
25172 +{
25173 +       int num;
25174 +
25175 +       for_each_present_cpu(num) {
25176 +               cpu_devices[num].hotpluggable = 0;
25177 +               register_cpu(&cpu_devices[num], num);
25178 +       }
25179 +       return 0;
25180 +}
25181 +
25182 +subsys_initcall(topology_init);
25183 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/traps.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/traps.c
25184 --- linux-2.6.30.10/arch/ubicom32/kernel/traps.c        1970-01-01 02:00:00.000000000 +0200
25185 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/traps.c    2009-12-11 11:45:11.000000000 +0200
25186 @@ -0,0 +1,514 @@
25187 +/*
25188 + * arch/ubicom32/kernel/traps.c
25189 + *   Ubicom32 architecture trap handling support.
25190 + *
25191 + * (C) Copyright 2009, Ubicom, Inc.
25192 + *
25193 + * This file is part of the Ubicom32 Linux Kernel Port.
25194 + *
25195 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25196 + * it and/or modify it under the terms of the GNU General Public License
25197 + * as published by the Free Software Foundation, either version 2 of the
25198 + * License, or (at your option) any later version.
25199 + *
25200 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25201 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25202 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25203 + * the GNU General Public License for more details.
25204 + *
25205 + * You should have received a copy of the GNU General Public License
25206 + * along with the Ubicom32 Linux Kernel Port.  If not,
25207 + * see <http://www.gnu.org/licenses/>.
25208 + *
25209 + * Ubicom32 implementation derived from (with many thanks):
25210 + *   arch/m68knommu
25211 + *   arch/blackfin
25212 + *   arch/parisc
25213 + */
25214 +
25215 +/*
25216 + * Sets up all exception vectors
25217 + */
25218 +#include <linux/sched.h>
25219 +#include <linux/signal.h>
25220 +#include <linux/kernel.h>
25221 +#include <linux/mm.h>
25222 +#include <linux/module.h>
25223 +#include <linux/types.h>
25224 +#include <linux/a.out.h>
25225 +#include <linux/user.h>
25226 +#include <linux/string.h>
25227 +#include <linux/linkage.h>
25228 +#include <linux/init.h>
25229 +#include <linux/ptrace.h>
25230 +#include <linux/kallsyms.h>
25231 +#include <linux/compiler.h>
25232 +#include <linux/stacktrace.h>
25233 +#include <linux/personality.h>
25234 +
25235 +#include <asm/uaccess.h>
25236 +#include <asm/stacktrace.h>
25237 +#include <asm/devtree.h>
25238 +#include <asm/setup.h>
25239 +#include <asm/fpu.h>
25240 +#include <asm/system.h>
25241 +#include <asm/traps.h>
25242 +#include <asm/pgtable.h>
25243 +#include <asm/processor.h>
25244 +#include <asm/machdep.h>
25245 +#include <asm/siginfo.h>
25246 +#include <asm/ip5000.h>
25247 +#include <asm/thread.h>
25248 +
25249 +#define TRAP_MAX_STACK_DEPTH 20
25250 +
25251 +/*
25252 + * These symbols are filled in by the linker.
25253 + */
25254 +extern unsigned long _stext;
25255 +extern unsigned long _etext;
25256 +
25257 +extern unsigned long __ocm_text_run_begin;
25258 +extern unsigned long __data_begin;
25259 +
25260 +extern void show_vmas(struct task_struct *task);
25261 +
25262 +const char *trap_cause_strings[] = {
25263 +       /*0*/   "inst address decode error",
25264 +       /*1*/   "inst sync error",
25265 +       /*2*/   "inst illegal",
25266 +       /*3*/   "src1 address decode error",
25267 +       /*4*/   "dst address decode error",
25268 +       /*5*/   "src1 alignment error",
25269 +       /*6*/   "dst alignment error",
25270 +       /*7*/   "src1 sync error",
25271 +       /*8*/   "dst sync error",
25272 +       /*9*/   "DCAPT error",
25273 +       /*10*/  "inst range error",
25274 +       /*11*/  "src1 range error",
25275 +       /*12*/  "dst range error",
25276 +};
25277 +
25278 +/*
25279 + * The device tree trap node definition.
25280 + */
25281 +struct trapnode {
25282 +       struct devtree_node dn;
25283 +       unsigned int intthread;
25284 +};
25285 +
25286 +static struct trapnode *tn;;
25287 +
25288 +/*
25289 + * trap_interrupt_handler()
25290 + *     Software Interrupt to ensure that a trap is serviced.
25291 + */
25292 +static irqreturn_t trap_interrupt_handler(int irq, void *dummy)
25293 +{
25294 +       /* Do Nothing */
25295 +       return IRQ_HANDLED;
25296 +}
25297 +
25298 +/*
25299 + * Data used by setup_irq for the timer.
25300 + */
25301 +static struct irqaction trap_irq = {
25302 +       .name    = "trap",
25303 +       .flags   = IRQF_DISABLED,
25304 +       .handler = trap_interrupt_handler,
25305 +};
25306 +
25307 +/*
25308 + * trap_cause_to_str()
25309 + *     Convert a trap_cause into a series of printk
25310 + */
25311 +static void trap_cause_to_str(long status)
25312 +{
25313 +       int bit;
25314 +
25315 +       if ((status & ((1 << TRAP_CAUSE_TOTAL) - 1)) == 0) {
25316 +               printk(KERN_NOTICE "decode: UNKNOWN CAUSES\n");
25317 +               return;
25318 +       }
25319 +
25320 +       for (bit = 0; bit < TRAP_CAUSE_TOTAL; bit++) {
25321 +               if (status & (1 << bit)) {
25322 +                       printk(KERN_NOTICE "\tdecode: %08x %s\n",
25323 +                              1 << bit, trap_cause_strings[bit]);
25324 +               }
25325 +       }
25326 +}
25327 +
25328 +/*
25329 + * trap_print_information()
25330 + *     Print the cause of the trap and additional info.
25331 + */
25332 +static void trap_print_information(const char *str, struct pt_regs *regs)
25333 +{
25334 +       printk(KERN_WARNING "\n");
25335 +
25336 +       if (current) {
25337 +               printk(KERN_WARNING "Process %s (pid: %d)\n",
25338 +                       current->comm, current->pid);
25339 +       }
25340 +
25341 +       if (current && current->mm) {
25342 +               printk(KERN_NOTICE "text = 0x%p-0x%p  data = 0x%p-0x%p\n"
25343 +                       KERN_NOTICE "bss = 0x%p-0x%p   user-stack = 0x%p\n"
25344 +                       KERN_NOTICE "\n",
25345 +                       (void *)current->mm->start_code,
25346 +                       (void *)current->mm->end_code,
25347 +                       (void *)current->mm->start_data,
25348 +                       (void *)current->mm->end_data,
25349 +                       (void *)current->mm->end_data,
25350 +                       (void *)current->mm->brk,
25351 +                       (void *)current->mm->start_stack);
25352 +       }
25353 +
25354 +       printk(KERN_WARNING "%s: Causes: 0x%08x\n", str,
25355 +                       (unsigned int)regs->trap_cause);
25356 +       trap_cause_to_str(regs->trap_cause);
25357 +       show_regs(regs);
25358 +       show_stack(NULL, (unsigned long *)regs->an[7]);
25359 +       printk(KERN_NOTICE "--- End Trap --- \n");
25360 +}
25361 +
25362 +/*
25363 + * dump_stack()
25364 + *     Dump the stack of the current task.
25365 + */
25366 +void dump_stack(void)
25367 +{
25368 +       show_stack(NULL, NULL);
25369 +}
25370 +EXPORT_SYMBOL(dump_stack);
25371 +
25372 +/*
25373 + * show_stack()
25374 + *     Print out information from the current stack.
25375 + */
25376 +void show_stack(struct task_struct *task, unsigned long *sp)
25377 +{
25378 +       /*
25379 +        *  Allocate just enough entries on the stack.
25380 +        */
25381 +       unsigned int calls[TRAP_MAX_STACK_DEPTH];
25382 +       unsigned long code_start;
25383 +       unsigned long code_end;
25384 +       unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
25385 +       unsigned long ocm_code_end = (unsigned long)&__data_begin;
25386 +       unsigned long stack_end = (unsigned long)(current->stack + THREAD_SIZE - 8);
25387 +       unsigned long stack = (unsigned long)sp;
25388 +       int kernel_stack = 1;
25389 +
25390 +       processor_dram(&code_start, &code_end);
25391 +
25392 +       /*
25393 +        * Which task are we talking about.
25394 +        */
25395 +       if (!task) {
25396 +               task = current;
25397 +       }
25398 +
25399 +       /*
25400 +        * Find the stack for the task if one was not specified.  Otherwise
25401 +        * use the specified stack.
25402 +        */
25403 +       if (!stack) {
25404 +               if (task != current) {
25405 +                       stack = task->thread.sp;
25406 +                       stack_end = (unsigned long)task->stack + THREAD_SIZE - 8;
25407 +               } else {
25408 +                       asm volatile (
25409 +                               "move.4         %0, SP          \n\t"
25410 +                               : "=r" (stack)
25411 +                       );
25412 +               }
25413 +       }
25414 +
25415 +       printk(KERN_NOTICE "Starting backtrace: PID %d '%s'\n",
25416 +                       task->pid, task->comm);
25417 +
25418 +       /*
25419 +        * We do 2 passes the first pass is Kernel stack is the second
25420 +        * User stack.
25421 +        */
25422 +       while (kernel_stack) {
25423 +               unsigned long *handle;
25424 +               unsigned int i, idx = 0;
25425 +               struct pt_regs *pt = task_pt_regs(task);
25426 +
25427 +               /*
25428 +                * If the task is in user mode, reset the start
25429 +                * and end values for text.
25430 +                */
25431 +               if (__user_mode(stack)) {
25432 +                       if (!(task->personality & FDPIC_FUNCPTRS)) {
25433 +                               printk(KERN_NOTICE "  User Stack:\n");
25434 +                               code_start = task->mm->start_code;
25435 +                               code_end = task->mm->end_code;
25436 +                       } else {
25437 +                               printk(KERN_NOTICE "  User Stack (fdpic):\n");
25438 +                               show_vmas(task);
25439 +                       }
25440 +                       stack_end = task->mm->start_stack;
25441 +                       ocm_code_end = ocm_code_start = 0;
25442 +                       kernel_stack = 0;
25443 +               } else {
25444 +                       printk(KERN_NOTICE "  Kernel Stack:\n");
25445 +               }
25446 +
25447 +               /*
25448 +                * Collect the stack back trace information.
25449 +                */
25450 +               printk("    code[0x%lx-0x%lx]", code_start, code_end);
25451 +               if (ocm_code_start) {
25452 +                       printk(" ocm_code[0x%lx-0x%lx]",
25453 +                              ocm_code_start, ocm_code_end);
25454 +               }
25455 +               printk("\n    stack[0x%lx-0x%lx]\n", stack, stack_end);
25456 +
25457 +               handle = (unsigned long*)stack;
25458 +               while (idx < TRAP_MAX_STACK_DEPTH) {
25459 +                       calls[idx] = stacktrace_iterate(&handle,
25460 +                                       code_start, code_end,
25461 +                                       ocm_code_start, ocm_code_end,
25462 +                                       (unsigned long)stack, stack_end);
25463 +                       if (calls[idx] == 0) {
25464 +                               break;
25465 +                       }
25466 +                       idx++;
25467 +               }
25468 +
25469 +               /*
25470 +                * Now print out the data.
25471 +                */
25472 +               printk(KERN_NOTICE "  CALL && CALLI on stack:");
25473 +               for (i = 0; i < idx; i++) {
25474 +                       printk("%s0x%x, ", (i & 0x3) == 0 ?  "\n    " : "",
25475 +                                       calls[i]);
25476 +               }
25477 +               printk(idx == TRAP_MAX_STACK_DEPTH ? "...\n" : "\n");
25478 +
25479 +               /*
25480 +                * If we are doing user stack we are done
25481 +                */
25482 +               if (!kernel_stack) {
25483 +                       break;
25484 +               }
25485 +
25486 +               /*
25487 +                * Does this kernel stack have a mm (i.e. is it user)
25488 +                */
25489 +               if (!task->mm) {
25490 +                       printk("No mm for userspace stack.\n");
25491 +                       break;
25492 +               }
25493 +               /*
25494 +                * Get the user-mode stack (if any)
25495 +                */
25496 +               stack = pt->an[7];
25497 +               printk(KERN_NOTICE "Userspace stack at 0x%lx frame type %d\n",
25498 +                               stack, (int)pt->frame_type);
25499 +               if (!__user_mode(stack)) {
25500 +                       break;
25501 +               }
25502 +       }
25503 +}
25504 +
25505 +/*
25506 + * die_if_kernel()
25507 + *     Determine if we are in kernel mode and if so print stuff out and die.
25508 + */
25509 +void die_if_kernel(char *str, struct pt_regs *regs, long trap_cause)
25510 +{
25511 +       unsigned int s3value;
25512 +
25513 +       if (user_mode(regs)) {
25514 +               return;
25515 +       }
25516 +
25517 +       console_verbose();
25518 +       trap_print_information(str, regs);
25519 +
25520 +       /*
25521 +        * If the debugger is attached via the hardware mailbox protocol,
25522 +        * go into an infinite loop and the debugger will figure things out.
25523 +        */
25524 +       asm volatile (
25525 +             "move.4 %0, scratchpad3"
25526 +             : "=r" (s3value)
25527 +       );
25528 +       if (s3value) {
25529 +               asm volatile("1:        jmpt.t 1b");
25530 +       }
25531 +
25532 +       /*
25533 +        * Set the debug taint value.
25534 +        */
25535 +       add_taint(TAINT_DIE);
25536 +       do_exit(SIGSEGV);
25537 +}
25538 +
25539 +/*
25540 + * trap_handler()
25541 + *     Handle traps.
25542 + *
25543 + * Traps are treated as interrupts and registered with the LDSR.  When
25544 + * the LDSR takes the interrupt, it will determine if a trap has occurred
25545 + * and service the trap prior to servicing the interrupt.
25546 + *
25547 + * This function is directly called by the LDSR.
25548 + */
25549 +void trap_handler(int irq, struct pt_regs *regs)
25550 +{
25551 +       int sig = SIGSEGV;
25552 +       siginfo_t info;
25553 +       unsigned int trap_cause = regs->trap_cause;
25554 +
25555 +       BUG_ON(!irqs_disabled());
25556 +
25557 +       /*
25558 +        * test if in kernel and die.
25559 +        */
25560 +       die_if_kernel("Kernel Trap", regs, trap_cause);
25561 +
25562 +       /*
25563 +        * User process problem, setup a signal for this process
25564 +        */
25565 +       if ((trap_cause & (1 << TRAP_CAUSE_DST_RANGE_ERR)) ||
25566 +           (trap_cause & (1 << TRAP_CAUSE_SRC1_RANGE_ERR)) ||
25567 +           (trap_cause & (1 << TRAP_CAUSE_I_RANGE_ERR))) {
25568 +               sig = SIGSEGV;
25569 +               info.si_code = SEGV_MAPERR;
25570 +       } else if ((trap_cause & (1 << TRAP_CAUSE_DST_MISALIGNED)) ||
25571 +                  (trap_cause & (1 << TRAP_CAUSE_SRC1_MISALIGNED))) {
25572 +               sig = SIGBUS;
25573 +               info.si_code = BUS_ADRALN;
25574 +       } else if ((trap_cause & (1 << TRAP_CAUSE_DST_DECODE_ERR)) ||
25575 +                  (trap_cause & (1 << TRAP_CAUSE_SRC1_DECODE_ERR))) {
25576 +               sig = SIGILL;
25577 +               info.si_code = ILL_ILLOPN;
25578 +       } else if ((trap_cause & (1 << TRAP_CAUSE_ILLEGAL_INST))) {
25579 +               /*
25580 +                * Check for software break point and if found signal trap
25581 +                * not illegal instruction.
25582 +                */
25583 +               unsigned long instruction;
25584 +               if (between(regs->pc, KERNELSTART, memory_end) &&
25585 +                       (regs->pc & 3) == 0 &&
25586 +                       get_user(instruction, (unsigned long *)regs->pc) == 0) {
25587 +
25588 +                       /*
25589 +                        * This used to be 0xaabbccdd but it turns out
25590 +                        * that is now valid in ubicom32v4 isa so we
25591 +                        * have switched to 0xfabbccdd
25592 +                        */
25593 +                       if ((instruction == 0xfabbccdd) ||
25594 +                           (instruction == 0xaabbccdd)) {
25595 +                               sig = SIGTRAP;
25596 +                               info.si_code = TRAP_BRKPT;
25597 +                               goto send_signal;
25598 +                       }
25599 +               }
25600 +               sig = SIGILL;
25601 +               info.si_code = ILL_ILLOPC;
25602 +       } else if ((trap_cause & (1 << TRAP_CAUSE_I_DECODE_ERR))) {
25603 +               sig = SIGILL;
25604 +               info.si_code = ILL_ILLOPC;
25605 +       } else if ((trap_cause & (1 << TRAP_CAUSE_DCAPT))) {
25606 +               sig = SIGTRAP;
25607 +               info.si_code = TRAP_TRACE;
25608 +       }
25609 +
25610 +       /*
25611 +        * Print a trap information block to the console, do not
25612 +        * print this above the case because we don't want it
25613 +        * printed for software break points.
25614 +        */
25615 +       trap_print_information("User Trap", regs);
25616 +
25617 +send_signal:
25618 +
25619 +       force_sig_info(sig, &info, current);
25620 +
25621 +       /*
25622 +        * Interrupts are disabled, re-enable them now.
25623 +        */
25624 +       if (!irqs_disabled()) {
25625 +               printk(KERN_EMERG "interrupts enabled on exit, irq=%d, regs=%p",
25626 +                               irq, regs);
25627 +               BUG();
25628 +       }
25629 +}
25630 +
25631 +/*
25632 + * trap_init_interrupt()
25633 + *     We need a 2nd trap handling init that will occur after init_IRQ().
25634 + */
25635 +void __init trap_init_interrupt(void)
25636 +{
25637 +       int err;
25638 +       unsigned char tirq;
25639 +       struct devtree_node *dn = (struct devtree_node *)tn;
25640 +
25641 +       /*
25642 +        * Now setup the Software IRQ so that if a trap occurs the LDSR
25643 +        * is started.  The irq is there just to "force" the LDSR to run.
25644 +        */
25645 +       if (!tn) {
25646 +               printk(KERN_WARNING "trap_init_interrupt skipped.\n");
25647 +               return;
25648 +       }
25649 +
25650 +       err = devtree_irq(dn, NULL, &tirq);
25651 +       if (err) {
25652 +               printk(KERN_WARNING "error obtaining trap irq value: %d\n",
25653 +                       err);
25654 +               return;
25655 +       }
25656 +
25657 +       if (tirq == DEVTREE_IRQ_NONE) {
25658 +               printk(KERN_WARNING "trap irq not available: %d\n", tirq);
25659 +               return;
25660 +       }
25661 +
25662 +       err = setup_irq(tirq, &trap_irq);
25663 +       if (err) {
25664 +               printk(KERN_WARNING "trap irq setup failed: %d\n", err);
25665 +               return;
25666 +       }
25667 +
25668 +       /*
25669 +        * Let ultra know which thread is handling the traps and
25670 +        * what the interrupt to use is.
25671 +        */
25672 +       tn->intthread = ldsr_get_threadid();
25673 +
25674 +       /*
25675 +        * Tell the LDSR about our IRQ so that it will unsuspend
25676 +        * if one occurs while waiting for the per thread lock.
25677 +        */
25678 +       ldsr_set_trap_irq(tirq);
25679 +}
25680 +
25681 +/*
25682 + * trap_init()
25683 + *     init trap handling
25684 + *
25685 + * Trap handling is done through the ldsr.  Every time an interrupt
25686 + * occurs, the LDSR looks for threads that are listed in the TRAP
25687 + * register and forces a call to the trap handler.
25688 + */
25689 +void __init trap_init(void)
25690 +{
25691 +       /*
25692 +        * If we do not have a trap node in the device tree, we leave the fault
25693 +        * handling to the underlying hardware.
25694 +        */
25695 +       tn = (struct trapnode *)devtree_find_node("traps");
25696 +       if (!tn) {
25697 +               printk(KERN_WARNING "traps are not handled by linux\n");
25698 +               return;
25699 +       }
25700 +}
25701 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/uaccess.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/uaccess.c
25702 --- linux-2.6.30.10/arch/ubicom32/kernel/uaccess.c      1970-01-01 02:00:00.000000000 +0200
25703 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/uaccess.c  2009-12-11 11:45:11.000000000 +0200
25704 @@ -0,0 +1,109 @@
25705 +/*
25706 + * arch/ubicom32/include/asm/uaccess.c
25707 + *   User space memory access functions for Ubicom32 architecture.
25708 + *
25709 + * (C) Copyright 2009, Ubicom, Inc.
25710 + *
25711 + * This file is part of the Ubicom32 Linux Kernel Port.
25712 + *
25713 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25714 + * it and/or modify it under the terms of the GNU General Public License
25715 + * as published by the Free Software Foundation, either version 2 of the
25716 + * License, or (at your option) any later version.
25717 + *
25718 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25719 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25720 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25721 + * the GNU General Public License for more details.
25722 + *
25723 + * You should have received a copy of the GNU General Public License
25724 + * along with the Ubicom32 Linux Kernel Port.  If not,
25725 + * see <http://www.gnu.org/licenses/>.
25726 + *
25727 + * Ubicom32 implementation derived from (with many thanks):
25728 + *   arch/m68knommu
25729 + *   arch/blackfin
25730 + *   arch/parisc
25731 + */
25732 +
25733 +#include <linux/sched.h>
25734 +#include <linux/mm.h>
25735 +#include <linux/string.h>
25736 +#include <linux/module.h>
25737 +
25738 +#include <asm/segment.h>
25739 +#include <asm/uaccess.h>
25740 +
25741 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
25742 +
25743 +/*
25744 + * __access_ok()
25745 + *     Check that the address is in the current processes.
25746 + *
25747 + * NOTE: The kernel uses "pretend" user addresses that wind
25748 + * up calling access_ok() so this approach has only marginal
25749 + * value because you wind up with lots of false positives.
25750 + */
25751 +int __access_ok(unsigned long addr, unsigned long size)
25752 +{
25753 +       // struct vm_area_struct *vma;
25754 +
25755 +       /*
25756 +        * Don't do anything if we are not a running system yet.
25757 +        */
25758 +       if (system_state != SYSTEM_RUNNING) {
25759 +               return 1;
25760 +       }
25761 +
25762 +       /*
25763 +        * It appears that Linux will call this function even when we are not
25764 +        * in the context of a user space application that has a VM address
25765 +        * space.  So we must check that current and mm are valid before
25766 +        * performing the check.
25767 +        */
25768 +       if ((!current) || (!current->mm)) {
25769 +               return 1;
25770 +       }
25771 +
25772 +       /*
25773 +        * We perform some basic checks on the address to ensure that it
25774 +        * is at least within the range of DRAM.
25775 +        */
25776 +       if ((addr < (int)&_etext) || (addr > memory_end)) {
25777 +               printk(KERN_WARNING "pid=%d[%s]: range [%lx - %lx] not in memory area: [%lx - %lx]\n",
25778 +                       current->pid, current->comm,
25779 +                       addr, addr + size,
25780 +                       memory_start, memory_end);
25781 +               return 0;
25782 +       }
25783 +
25784 +       /*
25785 +        * For nommu Linux we can check this by looking at the allowed
25786 +        * memory map for the process.
25787 +        *
25788 +        * TODO: Since the kernel passes addresses in it's own space as though
25789 +        * they were user address, we can not validate the addresses this way.
25790 +        */
25791 +#if 0
25792 +       if (!down_read_trylock(&current->mm->mmap_sem)) {
25793 +               return 1;
25794 +       }
25795 +       vma = find_vma(current->mm, addr);
25796 +       if (!vma) {
25797 +               up_read(&current->mm->mmap_sem);
25798 +               printk(KERN_WARNING "pid=%d[%s]: possible invalid acesss on range: [%lx - %lx]\n",
25799 +                               current->pid, current->comm, addr, addr + size);
25800 +               return 1;
25801 +       }
25802 +       if ((addr + size) > vma->vm_end) {
25803 +               up_read(&current->mm->mmap_sem);
25804 +               printk(KERN_WARNING "pid=%d[%s]: possible invalid length on range: [%lx - %lx]\n",
25805 +                               current->pid, current->comm, addr, addr + size);
25806 +               return 1;
25807 +       }
25808 +       up_read(&current->mm->mmap_sem);
25809 +#endif
25810 +       return 1;
25811 +}
25812 +
25813 +EXPORT_SYMBOL(__access_ok);
25814 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_context_switch.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_context_switch.S
25815 --- linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_context_switch.S      1970-01-01 02:00:00.000000000 +0200
25816 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_context_switch.S  2009-12-11 11:45:11.000000000 +0200
25817 @@ -0,0 +1,359 @@
25818 +/*
25819 + * arch/ubicom32/kernel/ubicom32_context_switch.S
25820 + *     Implements context switch and return functions.
25821 + *
25822 + * (C) Copyright 2009, Ubicom, Inc.
25823 + *
25824 + * This file is part of the Ubicom32 Linux Kernel Port.
25825 + *
25826 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25827 + * it and/or modify it under the terms of the GNU General Public License
25828 + * as published by the Free Software Foundation, either version 2 of the
25829 + * License, or (at your option) any later version.
25830 + *
25831 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25832 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25833 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25834 + * the GNU General Public License for more details.
25835 + *
25836 + * You should have received a copy of the GNU General Public License
25837 + * along with the Ubicom32 Linux Kernel Port.  If not,
25838 + * see <http://www.gnu.org/licenses/>.
25839 + *
25840 + * Ubicom32 implementation derived from (with many thanks):
25841 + *   arch/m68knommu
25842 + *   arch/blackfin
25843 + *   arch/parisc
25844 + */
25845 +#include <linux/sys.h>
25846 +#include <linux/linkage.h>
25847 +#include <asm/asm-offsets.h>
25848 +#include <asm/ubicom32-common.h>
25849 +#include <asm/ip5000.h>
25850 +#include <asm/range-protect.h>
25851 +
25852 +/*
25853 + * begin_restore_context()
25854 + *     Restore most of the context from sp (struct pt_reg *)
25855 + *
25856 + * This *can* be called without the global atomic lock. (because sp is
25857 + * not restored!)  Only d15 and a3 are allowed to be used after this
25858 + * before calling complete_restore_context
25859 + */
25860 +.macro begin_restore_context
25861 +       move.4  d0, PT_D0(sp)
25862 +       move.4  d1, PT_D1(sp)
25863 +       move.4  d2, PT_D2(sp)
25864 +       move.4  d3, PT_D3(sp)
25865 +       move.4  d4, PT_D4(sp)
25866 +       move.4  d5, PT_D5(sp)
25867 +       move.4  d6, PT_D6(sp)
25868 +       move.4  d7, PT_D7(sp)
25869 +       move.4  d8, PT_D8(sp)
25870 +       move.4  d9, PT_D9(sp)
25871 +       move.4  d10, PT_D10(sp)
25872 +       move.4  d11, PT_D11(sp)
25873 +       move.4  d12, PT_D12(sp)
25874 +       move.4  d13, PT_D13(sp)
25875 +       move.4  d14, PT_D14(sp)
25876 +;;     move.4  d15, PT_D15(sp)
25877 +       move.4  a0, PT_A0(sp)
25878 +       move.4  a1, PT_A1(sp)
25879 +       move.4  a2, PT_A2(sp)
25880 +;;     move.4  a3, PT_A3(sp)
25881 +       move.4  a4, PT_A4(sp)
25882 +       move.4  a5, PT_A5(sp)
25883 +       move.4  a6, PT_A6(sp)
25884 +       move.4  acc0_hi, PT_ACC0HI(sp)
25885 +       move.4  acc0_lo, PT_ACC0LO(sp)
25886 +       move.4  mac_rc16, PT_MAC_RC16(sp)
25887 +       move.4  acc1_hi, PT_ACC1HI(sp)
25888 +       move.4  acc1_lo, PT_ACC1LO(sp)
25889 +       move.4  source3, PT_SOURCE3(sp)
25890 +       move.4  int_mask0, PT_INT_MASK0(sp)
25891 +       move.4  int_mask1, PT_INT_MASK1(sp)
25892 +.endm
25893 +
25894 +/*
25895 + * complete_restore_context()
25896 + *     Completely restore the context from sp (struct pt_reg *)
25897 + *
25898 + * Note: Recovered PC and CSR are saved on the stack and are to be
25899 + * popped off before returning.
25900 + */
25901 +.macro complete_restore_context
25902 +       move.4  a3, sp
25903 +       move.4  d15, PT_D15(sp)
25904 +       move.4  sp, PT_SP(a3)           ; Recover Stack pointer from save area
25905 +       move.4  -4(sp)++, PT_PC(a3)     ; Recover saved PC and save to stack
25906 +       move.4  -4(sp)++, PT_CSR(a3)    ; Recover saved csr and save to stack
25907 +       move.4  a3, PT_A3(a3)
25908 +.endm
25909 +
25910 +/*
25911 + * old restore_context macro
25912 + */
25913 +.macro restore_context
25914 +       begin_restore_context
25915 +       complete_restore_context
25916 +.endm
25917 +
25918 +/*
25919 + * ldsr_thread_enable_interrupts()
25920 + *     An assembly version of the enable interrupts function.
25921 + *
25922 + * The stack is fair game but all registers MUST be preserved.
25923 + *
25924 + */
25925 +.macro ldsr_thread_enable_interrupts
25926 +       move.4  -4(sp)++, d3    ; Push d3
25927 +       move.4  -4(sp)++, a3    ; Push a3
25928 +
25929 +       /*
25930 +        * Read the ROSR and obtain ~(1 << tid)
25931 +        */
25932 +       lsr.4   d3, rosr, #0x2  ; Move the thread portion of ROSR into d3
25933 +       lsl.4   d3, #1, d3      ; perform a (1 << tid)
25934 +       not.4   d3, d3          ; Negate the value of d3 == ~(1 << threadid)
25935 +
25936 +       /*
25937 +        * Get the value of the ldsr_soft_irq_mask
25938 +        */
25939 +       moveai  a3, #%hi(ldsr_soft_irq_mask)
25940 +       move.4  a3, %lo(ldsr_soft_irq_mask)(a3)
25941 +
25942 +       /*
25943 +        * Now re-enable interrupts for this thread and then
25944 +        * wakeup the LDSR.
25945 +        */
25946 +       and.4   scratchpad1, scratchpad1, d3
25947 +       move.4  int_set0, a3
25948 +
25949 +       /*
25950 +        * Restore the registers.
25951 +        */
25952 +       move.4  a3, (sp)4++
25953 +       move.4  d3, (sp)4++
25954 +.endm
25955 +
25956 +/*
25957 + * ret_from_interrupt_to_kernel()
25958 + *     RFI function that is where do_IRQ() returns to if the thread was
25959 + *     in kernel space.
25960 + */
25961 +       .section .text.ret_from_interrupt_to_kernel, "ax", @progbits
25962 +       .global ret_from_interrupt_to_kernel
25963 +ret_from_interrupt_to_kernel:
25964 +       begin_restore_context           ; Restore the thread context
25965 +       atomic_lock_acquire             ; Enter critical section
25966 +       complete_restore_context        ; Restore the thread context
25967 +       atomic_lock_release             ; Leave critical section
25968 +       ldsr_thread_enable_interrupts   ; enable the threads interrupts
25969 +       move.4  csr, (sp)4++            ; Restore csr from the stack
25970 +       ret     (sp)4++
25971 +
25972 +/*
25973 + * ret_from_interrupt_to_user()
25974 + *     RFI function that is where do_IRQ() returns to if the thread was
25975 + *     in user space.
25976 + *
25977 + * TODO: Do we really need the critical section handling in this code?
25978 + *
25979 + */
25980 +       .section .text.ret_from_interrupt_to_user, "ax", @progbits
25981 +       .global ret_from_interrupt_to_user
25982 +ret_from_interrupt_to_user:
25983 +       ldsr_thread_enable_interrupts                   ; enable the threads interrupts
25984 +       /*
25985 +        * Set a1 to the thread info pointer, no need to save it as we are
25986 +        * restoring userspace and will never return
25987 +        */
25988 +       movei   d0, #(~(ASM_THREAD_SIZE-1))
25989 +       and.4   a1, sp, d0
25990 +
25991 +       /*
25992 +        * Test if the scheduler needs to be called.
25993 +        */
25994 +       btst    TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
25995 +       jmpeq.t 2f
25996 +       call    a5, schedule                    ; Call the scheduler. I will come back here.
25997 +
25998 +       /*
25999 +        * See if we have pending signals and call do_signal
26000 +        * if needed.
26001 +        */
26002 +2:
26003 +       btst    TI_FLAGS(a1), #ASM_TIF_SIGPENDING       ; Any signals needed?
26004 +       jmpeq.t 1f
26005 +
26006 +       /*
26007 +        * Now call do_signal()
26008 +        */
26009 +       move.4  d0, #0                                  ; oldset pointer is NULL
26010 +       move.4  d1, sp                                  ; d1 is the regs pointer
26011 +       call    a5, do_signal                           ; Call do_signal()
26012 +
26013 +       /*
26014 +        * Back from do_signal(), re-enter critical section.
26015 +        */
26016 +1:
26017 +       begin_restore_context                           ; Restore the thread context
26018 +       atomic_lock_acquire                             ; Enter critical section
26019 +       call a3, __complete_and_return_to_userspace     ; jump to unprotected section
26020 +
26021 +/*
26022 + * restore_all_registers()
26023 + *
26024 + * restore_all_registers will be the alternate exit route for
26025 + * preempted processes that have called a signal handler
26026 + * and are returning back to user space.
26027 + */
26028 +       .section .text.restore_all_registers, "ax", @progbits
26029 +       .global restore_all_registers
26030 +restore_all_registers:
26031 +       begin_restore_context                   ; Restore the thread context
26032 +       atomic_lock_acquire                     ; Enter critical section
26033 +       call a3, __complete_and_return_to_userspace
26034 +
26035 +/*
26036 + * __complete_and_return_to_userspace
26037 + *
26038 + * restores the second half of the context and returns
26039 + * You must have the atomic lock when you call this function
26040 + */
26041 +       .section .kernel_unprotected, "ax", @progbits
26042 +__complete_and_return_to_userspace:
26043 +       disable_kernel_ranges_for_current d15   ; disable kernel ranges
26044 +       complete_restore_context                ; restore previous context
26045 +       atomic_lock_release                     ; Leave critical section
26046 +       move.4  csr, (sp)4++                    ; Restore csr from the stack
26047 +       ret     (sp)4++
26048 +
26049 +/*
26050 + * ret_from_fork()
26051 + *     Called on the child's return from fork system call.
26052 + */
26053 +       .section .text.ret_from_fork, "ax", @progbits
26054 +       .global ret_from_fork
26055 +ret_from_fork:
26056 +       ;;;  d0 contains the arg for schedule_tail
26057 +       ;;;  the others we don't care about as they are in PT_REGS (sp)
26058 +       call   a5, schedule_tail
26059 +
26060 +       atomic_lock_acquire             ; Enter critical section
26061 +
26062 +       move.4  a3, sp
26063 +       move.4  d0, PT_D0(a3)           ; Restore D0
26064 +       move.4  d1, PT_D1(a3)           ; Restore D1
26065 +       move.4  d2, PT_D2(a3)           ; Restore D2
26066 +       move.4  d3, PT_D3(a3)           ; Restore D3
26067 +       move.4  d10, PT_D10(a3)         ; Restore D10
26068 +       move.4  d11, PT_D11(a3)         ; Restore D11
26069 +       move.4  d12, PT_D12(a3)         ; Restore D12
26070 +       move.4  d13, PT_D13(a3)         ; Restore D13
26071 +       move.4  a1, PT_A1(a3)           ; Restore A1
26072 +       move.4  a2, PT_A2(a3)           ; Restore A2
26073 +       move.4  a5, PT_A5(a3)           ; Restore A5
26074 +       move.4  a6, PT_A6(a3)           ; Restore A6
26075 +       ;;  I think atomic_lock_acquire could be moved here..
26076 +       move.4  sp, PT_SP(a3)           ; Restore sp
26077 +       move.4  a4, PT_PC(a3)           ; Restore pc in register a4
26078 +       move.4  PT_FRAME_TYPE(a3), #0   ; Clear frame_type to indicate it is invalid.
26079 +
26080 +#ifdef CONFIG_PROTECT_KERNEL
26081 +       call a3, __ret_from_fork_bottom_half
26082 +       .section .kernel_unprotected, "ax", @progbits
26083 +__ret_from_fork_bottom_half:
26084 +       disable_kernel_ranges_for_current d15
26085 +#endif
26086 +       atomic_lock_release             ; Leave critical section
26087 +       calli   a4, 0(a4)               ; Return.
26088 +
26089 +/*
26090 + * __switch_to()
26091 + *
26092 + * Call with:
26093 + *     void *__switch_to(struct task_struct *prev, struct thread_struct *prev_switch,
26094 + *                             struct thread_struct *next_switch)
26095 + */
26096 +       .section .text.__switch_to, "ax", @progbits
26097 +       .global __switch_to
26098 +__switch_to:
26099 +
26100 +       /*
26101 +        * Set up register a3 to point to save area.
26102 +        */
26103 +       movea   a3, d1                  ; a3 now holds prev_switch
26104 +       move.4  (a3)4++, d10
26105 +       move.4  (a3)4++, d11
26106 +       move.4  (a3)4++, d12
26107 +       move.4  (a3)4++, d13
26108 +       move.4  (a3)4++, a1
26109 +       move.4  (a3)4++, a2
26110 +       move.4  (a3)4++, a5
26111 +       move.4  (a3)4++, a6
26112 +       move.4  (a3)4++, a7
26113 +
26114 +       /*
26115 +        * Set up register a3 to point to restore area.
26116 +        */
26117 +       movea   a3, d2                  ; a3 now holds next_switch
26118 +       move.4  d10 , (a3)4++
26119 +       move.4  d11 , (a3)4++
26120 +       move.4  d12 , (a3)4++
26121 +       move.4  d13 , (a3)4++
26122 +       move.4  a1 , (a3)4++
26123 +       move.4  a2 , (a3)4++
26124 +       move.4  a5 , (a3)4++
26125 +       move.4  a6 , (a3)4++
26126 +       move.4  a7 , (a3)4++
26127 +
26128 +       /*
26129 +        * Load the sw_ksp with the proper thread_info pointer.
26130 +        */
26131 +       movei   d15, #(~(ASM_THREAD_SIZE-1))
26132 +       and.4   a3, sp, d15             ; a3 now has the thread info pointer
26133 +       moveai  a4, #%hi(sw_ksp)
26134 +       lea.1   a4, %lo(sw_ksp)(a4)     ; a4 now has the base address of sw_ksp array
26135 +       lsr.4   d15, ROSR, #2           ; Thread number - bit's 6 through 31 are zeroes anyway.
26136 +       move.4  (a4, d15), a3           ; Load the thread info pointer into the hw_ksp array..
26137 +
26138 +       /*
26139 +        * We are done with context switch. Time to return..
26140 +        */
26141 +       calli   a5, 0(a5)
26142 +       .size __switch_to, . - __switch_to
26143 +
26144 +/*
26145 + * ubicom32_emulate_insn()
26146 + *     Emulates the instruction.
26147 + *
26148 + * Call with:
26149 + *     unsigned int ubicom32_emulate_insn(int source1, int source2, int source3, int *save_acc, int *save_csr);
26150 + */
26151 +       .section .text.ubicom32_emulate_insn, "ax", @progbits
26152 +       .global ubicom32_emulate_insn
26153 +       .global trap_emulate
26154 +ubicom32_emulate_insn:
26155 +       movea   a3, d3          ; a3 holds save_acc pointer
26156 +       movea   a4, d4          ; a4 hods save_csr pointer
26157 +       move.4  source3, d2
26158 +       move.4  acc0_lo, (a3)
26159 +       move.4  acc0_hi, 4(a3)
26160 +       move.4  acc1_lo, 8(a3)
26161 +       move.4  acc1_hi, 12(a3)
26162 +       move.4  mac_rc16, 16(a3)
26163 +       move.4  CSR, (a4)
26164 +       setcsr_flush 0
26165 +
26166 +trap_emulate:
26167 +       move.4  d0, d1
26168 +       setcsr_flush 0
26169 +       move.4  (a4), CSR       ; Save csr
26170 +       move.4  (a3), acc0_lo
26171 +       move.4  4(a3), acc0_hi
26172 +       move.4  8(a3), acc1_lo
26173 +       move.4  12(a3), acc1_hi
26174 +       move.4  16(a3), mac_rc16
26175 +       ret     a5
26176 +       .size ubicom32_emulate_insn, . - ubicom32_emulate_insn
26177 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_ksyms.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_ksyms.c
26178 --- linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_ksyms.c       1970-01-01 02:00:00.000000000 +0200
26179 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_ksyms.c   2009-12-11 11:45:11.000000000 +0200
26180 @@ -0,0 +1,98 @@
26181 +/*
26182 + * arch/ubicom32/kernel/ubicom32_ksyms.c
26183 + *   Ubicom32 architecture compiler support and misc symbols.
26184 + *
26185 + * (C) Copyright 2009, Ubicom, Inc.
26186 + *
26187 + * This file is part of the Ubicom32 Linux Kernel Port.
26188 + *
26189 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26190 + * it and/or modify it under the terms of the GNU General Public License
26191 + * as published by the Free Software Foundation, either version 2 of the
26192 + * License, or (at your option) any later version.
26193 + *
26194 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26195 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26196 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26197 + * the GNU General Public License for more details.
26198 + *
26199 + * You should have received a copy of the GNU General Public License
26200 + * along with the Ubicom32 Linux Kernel Port.  If not,
26201 + * see <http://www.gnu.org/licenses/>.
26202 + *
26203 + * Ubicom32 implementation derived from (with many thanks):
26204 + *   arch/m68knommu
26205 + *   arch/blackfin
26206 + *   arch/parisc
26207 + */
26208 +#include <linux/module.h>
26209 +#include <linux/linkage.h>
26210 +#include <linux/sched.h>
26211 +#include <linux/string.h>
26212 +#include <linux/mm.h>
26213 +#include <linux/user.h>
26214 +#include <linux/elfcore.h>
26215 +#include <linux/in6.h>
26216 +#include <linux/interrupt.h>
26217 +#include <linux/io.h>
26218 +#include <linux/semaphore.h>
26219 +
26220 +#include <asm/setup.h>
26221 +#include <asm/machdep.h>
26222 +#include <asm/pgalloc.h>
26223 +#include <asm/irq.h>
26224 +#include <asm/checksum.h>
26225 +#include <asm/current.h>
26226 +
26227 +/* platform dependent support */
26228 +
26229 +EXPORT_SYMBOL(__ioremap);
26230 +EXPORT_SYMBOL(iounmap);
26231 +
26232 +EXPORT_SYMBOL(ip_fast_csum);
26233 +
26234 +
26235 +/* Networking helper routines. */
26236 +EXPORT_SYMBOL(csum_partial_copy_nocheck);
26237 +
26238 +/* The following are special because they're not called
26239 +   explicitly (the C compiler generates them).  Fortunately,
26240 +   their interface isn't gonna change any time soon now, so
26241 +   it's OK to leave it out of version control.  */
26242 +EXPORT_SYMBOL(memcpy);
26243 +EXPORT_SYMBOL(memset);
26244 +EXPORT_SYMBOL(memmove);
26245 +
26246 +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4
26247 +/*
26248 + * libgcc functions - functions that are used internally by the
26249 + * compiler...  (prototypes are not correct though, but that
26250 + * doesn't really matter since they're not versioned).
26251 + */
26252 +extern void __ashldi3(void);
26253 +extern void __ashrdi3(void);
26254 +extern void __divsi3(void);
26255 +extern void __divdi3(void);
26256 +extern void __lshrdi3(void);
26257 +extern void __modsi3(void);
26258 +extern void __muldi3(void);
26259 +extern void __udivsi3(void);
26260 +extern void __umodsi3(void);
26261 +
26262 +/* gcc lib functions */
26263 +EXPORT_SYMBOL(__ashldi3);
26264 +EXPORT_SYMBOL(__ashrdi3);
26265 +EXPORT_SYMBOL(__divsi3);
26266 +EXPORT_SYMBOL(__divdi3);
26267 +EXPORT_SYMBOL(__lshrdi3);
26268 +EXPORT_SYMBOL(__modsi3);
26269 +EXPORT_SYMBOL(__muldi3);
26270 +EXPORT_SYMBOL(__udivsi3);
26271 +EXPORT_SYMBOL(__umodsi3);
26272 +#else
26273 +extern void __libgcc_udivmodsi(void);
26274 +extern void __libgcc_divmodsi(void);
26275 +
26276 +EXPORT_SYMBOL(__libgcc_udivmodsi);
26277 +EXPORT_SYMBOL(__libgcc_divmodsi);
26278 +#endif
26279 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_syscall.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_syscall.S
26280 --- linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_syscall.S     1970-01-01 02:00:00.000000000 +0200
26281 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_syscall.S 2009-12-11 11:45:11.000000000 +0200
26282 @@ -0,0 +1,694 @@
26283 +/*
26284 + * arch/ubicom32/kernel/ubicom32_syscall.S
26285 + *     <TODO: Replace with short file description>
26286 + *
26287 + * (C) Copyright 2009, Ubicom, Inc.
26288 + *
26289 + * This file is part of the Ubicom32 Linux Kernel Port.
26290 + *
26291 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26292 + * it and/or modify it under the terms of the GNU General Public License
26293 + * as published by the Free Software Foundation, either version 2 of the
26294 + * License, or (at your option) any later version.
26295 + *
26296 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26297 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26298 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26299 + * the GNU General Public License for more details.
26300 + *
26301 + * You should have received a copy of the GNU General Public License
26302 + * along with the Ubicom32 Linux Kernel Port.  If not,
26303 + * see <http://www.gnu.org/licenses/>.
26304 + *
26305 + * Ubicom32 implementation derived from (with many thanks):
26306 + *   arch/m68knommu
26307 + *   arch/blackfin
26308 + *   arch/parisc
26309 + */
26310 +#include <linux/sys.h>
26311 +#include <linux/linkage.h>
26312 +#include <linux/unistd.h>
26313 +
26314 +#include <asm/ubicom32-common.h>
26315 +#include <asm/thread_info.h>
26316 +#include <asm/asm-offsets.h>
26317 +#include <asm/range-protect.h>
26318 +
26319 +/*
26320 + * __old_system_call()
26321 + */
26322 +       .section .old_syscall_entry.text, "ax", @progbits
26323 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
26324 +__old_system_call:
26325 +       call a3, system_call
26326 +       .size __old_system_call, . - __old_system_call ;
26327 +#else
26328 +       /*
26329 +        * something that will crash the userspace application, but
26330 +        * should not take down the kernel, if protection is enabled
26331 +        * this will never even get executed.
26332 +        */
26333 +       .long   0xFABBCCDE                      ; illegal instruction
26334 +       bkpt #-1                                ; we will never get here
26335 +#endif
26336 +
26337 +/*
26338 + * system_call()
26339 + */
26340 +       .section .syscall_entry.text, "ax", @progbits
26341 +       .global system_call
26342 +system_call:
26343 +       /*
26344 +        * Regular ABI rules for function calls apply for syscall.  d8 holds
26345 +        * the syscall number. We will use that to index into the syscall table.
26346 +        * d0 - d5 hold the parameters.
26347 +        *
26348 +        * First we get the current thread_info and swap to the kernel stack.
26349 +        * This is done by reading the current thread and looking up the ksp
26350 +        * from the sw_ksp array and storing it in a3.
26351 +        *
26352 +        * Then we reserve space for the syscall context a struct pt_regs and
26353 +        * save it using a4 initially and later as sp.
26354 +        * Once sp is set to the kernel sp we can leave the critical section.
26355 +        *
26356 +        * For the user case the kernel stack will have the following layout.
26357 +        *
26358 +        *  a3           ksp[0] +-----------------------+
26359 +        *                      | Thread info area      |
26360 +        *                      | struct thread_info    |
26361 +        *                      +-----------------------+
26362 +        *                      :                       :
26363 +        *                      |   Kernel Stack Area   |
26364 +        *                      |                       |
26365 +        *  a4 / sp >>>         +-----------------------+
26366 +        *                      | Context save area     |
26367 +        *                      | struct pt_reg         |
26368 +        *  ksp[THREAD_SIZE-8]  +-----------------------+
26369 +        *                      | 8 Byte Buffer Zone    |
26370 +        *  ksp[THREAD_SIZE]    +-----------------------+
26371 +
26372 +        *
26373 +        * For kernel syscalls the layout is as follows.
26374 +        *
26375 +        *  a3           ksp[0] +-----------------------+
26376 +        *                      | Thread info area      |
26377 +        *                      | struct thread_info    |
26378 +        *                      +-----------------------+
26379 +        *                      :                       :
26380 +        *                      |   Kernel Stack Area   |
26381 +        *                      |                       |
26382 +        *  a4 / sp >>>         +-----------------------+
26383 +        *                      | Context save area     |
26384 +        *                      | struct pt_reg         |
26385 +        * sp at syscall entry  +-----------------------+
26386 +        *                      | Callers Kernel Stack  |
26387 +        *                      :                       :
26388 +        *
26389 +        * Once the context is saved we optionally call syscall_trace and setup
26390 +        * the exit routine and jump to the syscall.
26391 +        */
26392 +
26393 +       /*
26394 +        * load the base address for sw_ksp into a3
26395 +        * Note.. we cannot access it just yet as protection is still on.
26396 +        */
26397 +       moveai  a3, #%hi(sw_ksp)
26398 +       lea.1   a3, %lo(sw_ksp)(a3)
26399 +
26400 +       /*
26401 +        * Enter critical section .
26402 +        *
26403 +        * The 'critical' aspects here are the switching the to the ksp and
26404 +        * changing the protection registers, these both use per thread
26405 +        * information so we need to protect from a context switch. For now this
26406 +        * is done using the global atomic lock.
26407 +        */
26408 +       atomic_lock_acquire
26409 +
26410 +       thread_get_self d15                     ; Load current thread number
26411 +#ifdef CONFIG_PROTECT_KERNEL
26412 +       lsl.4   d9, #1, d15                     ; Convert to thread bit
26413 +       enable_kernel_ranges d9
26414 +#endif
26415 +       /*
26416 +        * in order to reduce the size of code in the syscall section we get
26417 +        * out of it right now
26418 +        */
26419 +       call a4, __system_call_bottom_half
26420 +       .size system_call, . - system_call
26421 +
26422 +       .section .text.__system_call_bottom_half, "ax", @progbits
26423 +__system_call_bottom_half:
26424 +
26425 +       /*
26426 +        * We need to Determine if this is a kernel syscall or user syscall.
26427 +        * Start by loading the pointer for the thread_info structure for the
26428 +        * current process in to a3.
26429 +        */
26430 +       move.4  a3, (a3, d15)                   ; a3 = sw_ksp[d15]
26431 +
26432 +       /*
26433 +        * Now if this is a kernel thread the same value can be a acheived by
26434 +        * masking off the lower bits on the current stack pointer.
26435 +        */
26436 +       movei   d9, #(~(ASM_THREAD_SIZE-1))     ; load mask
26437 +       and.4   d9, sp, d9                      ; apply mask
26438 +
26439 +       /*
26440 +        * d9 now has the masked version of the sp. If this is identical to
26441 +        * what is in a3 then don't switch to ksp as we are already in the
26442 +        * kernel.
26443 +        */
26444 +       sub.4   #0, a3, d9
26445 +
26446 +       /*
26447 +        * if d9 and a3 are not equal. We are usespace and have to shift to
26448 +        * ksp.
26449 +        */
26450 +       jmpne.t 1f
26451 +
26452 +       /*
26453 +        * Kernel Syscall.
26454 +        *
26455 +        * The kernel has called this routine. We have to pdec space for pt_regs
26456 +        * from sp.
26457 +        */
26458 +       pdec    a4, PT_SIZE(sp)                 ; a4 = ksp - PT_SIZE
26459 +       jmpt.t  2f
26460 +
26461 +       /*
26462 +        * Userspace Syscall.
26463 +        *
26464 +        * Add THREAD_SIZE and subtract PT_SIZE to create the proper ksp
26465 +        */
26466 +1:     movei   d15, #(ASM_THREAD_SIZE - 8 - PT_SIZE)
26467 +       lea.1   a4, (a3, d15)                   ; a4 = ksp + d15
26468 +
26469 +       /*
26470 +        * Replace user stack pointer with kernel stack pointer (a4)
26471 +        * Load -1 into frame_type in save area to indicate this is system call
26472 +        * frame.
26473 +        */
26474 +2:     move.4  PT_A7(a4), a7                   ; Save old sp/A7 on kernel stack
26475 +       move.4  PT_FRAME_TYPE(a4), #-1          ; Set the frame type.
26476 +       move.4  sp, a4                          ; Change to ksp.
26477 +       /*
26478 +        * We are now officially back in the kernel!
26479 +        */
26480 +
26481 +       /*
26482 +        * Now that we are on the ksp we can leave the critical section
26483 +        */
26484 +       atomic_lock_release
26485 +
26486 +       /*
26487 +        * We need to save a0 because we need to be able to restore it in
26488 +        * the event that we need to handle a signal.  It's not generally
26489 +        * a callee-saved register but is the GOT pointer.
26490 +        */
26491 +       move.4  PT_A0(sp), a0                   ; Save A0 on kernel stack
26492 +
26493 +       /*
26494 +        * We still need to save d10-d13, a1, a2, a5, a6 in the kernel frame
26495 +        * for this process, we also save the system call params in the case of
26496 +        * syscall restart. (note a7 was saved above)
26497 +        */
26498 +       move.4  PT_A1(sp), a1                   ; Save A1 on kernel stack
26499 +       move.4  PT_A2(sp), a2                   ; Save A2 on kernel stack
26500 +       move.4  PT_A5(sp), a5                   ; Save A5 on kernel stack
26501 +       move.4  PT_A6(sp), a6                   ; Save A6 on kernel stack
26502 +       move.4  PT_PC(sp), a5                   ; Save A5 at the PC location
26503 +       move.4  PT_D10(sp), d10                 ; Save D10 on kernel stack
26504 +       move.4  PT_D11(sp), d11                 ; Save D11 on kernel stack
26505 +       move.4  PT_D12(sp), d12                 ; Save D12 on kernel stack
26506 +       move.4  PT_D13(sp), d13                 ; Save D13 on kernel stack
26507 +
26508 +       /*
26509 +        * Now save the syscall parameters
26510 +        */
26511 +       move.4  PT_D0(sp), d0                   ; Save d0 on kernel stack
26512 +       move.4  PT_ORIGINAL_D0(sp), d0          ; Save d0 on kernel stack
26513 +       move.4  PT_D1(sp), d1                   ; Save d1 on kernel stack
26514 +       move.4  PT_D2(sp), d2                   ; Save d2 on kernel stack
26515 +       move.4  PT_D3(sp), d3                   ; Save d3 on kernel stack
26516 +       move.4  PT_D4(sp), d4                   ; Save d4 on kernel stack
26517 +       move.4  PT_D5(sp), d5                   ; Save d5 on kernel stack
26518 +       move.4  PT_D8(sp), d8                   ; Save d8 on kernel stack
26519 +
26520 +       /*
26521 +        * Test if syscalls are being traced and if they are jump to syscall
26522 +        * trace (it will comeback here)
26523 +        */
26524 +       btst    TI_FLAGS(a3), #ASM_TIF_SYSCALL_TRACE
26525 +       jmpne.f .Lsystem_call__trace
26526 +.Lsystem_call__trace_complete:
26527 +       /*
26528 +        * Check for a valid call number [ 0 <= syscall_number < NR_syscalls ]
26529 +        */
26530 +       cmpi    d8, #0
26531 +       jmplt.f 3f
26532 +       cmpi    d8, #NR_syscalls
26533 +       jmplt.t 4f
26534 +
26535 +       /*
26536 +        * They have passed an invalid number. Call sys_ni_syscall staring by
26537 +        * load a4 with the base address of sys_ni_syscall
26538 +        */
26539 +3:     moveai  a4, #%hi(sys_ni_syscall)
26540 +       lea.1   a4, %lo(sys_ni_syscall)(a4)
26541 +       jmpt.t  5f                              ; Jump to regular processing
26542 +
26543 +       /*
26544 +        * Validated syscall, load the syscall table base address into a3 and
26545 +        * read the syscall ptr out.
26546 +        */
26547 +4:     moveai  a3, #%hi(sys_call_table)
26548 +       lea.1   a3, %lo(sys_call_table)(a3)     ; a3 = sys_call_table
26549 +       move.4  a4, (a3, d8)                    ; a4 = sys_call_table[d8]
26550 +
26551 +       /*
26552 +        * Before calling the syscall, setup a5 so that syscall_exit is called
26553 +        * on return from syscall
26554 +        */
26555 +5:     moveai  a5, #%hi(syscall_exit)          ; Setup return address
26556 +       lea.1   a5, %lo(syscall_exit)(a5)       ; from system call
26557 +
26558 +       /*
26559 +        * If the syscall is __NR_rt_rigreturn then we have to test d1 to
26560 +        * figure out if we have to change change the return routine to restore
26561 +        * all registers.
26562 +        */
26563 +       cmpi    d8, #__NR_rt_sigreturn
26564 +       jmpeq.f 6f
26565 +
26566 +       /*
26567 +        * Launch system call (it will return through a5 - syscall_exit)
26568 +        */
26569 +       calli   a3, 0(a4)
26570 +
26571 +       /*
26572 +        * System call is rt_sigreturn. Test d1. If it is 1 we have to
26573 +        * change the return address to restore_all_registers
26574 +        */
26575 +6:     cmpi    d1, #1
26576 +       jmpne.t 7f
26577 +
26578 +       moveai  a5, #%hi(restore_all_registers)  ; Setup return address
26579 +       lea.1   a5, %lo(restore_all_registers)(a5) ; to restore_all_registers.
26580 +
26581 +       /*
26582 +        * Launch system call  (it will return through a5)
26583 +        */
26584 +7:     calli   a3, 0(a4)                        ; Launch system call
26585 +
26586 +.Lsystem_call__trace:
26587 +       /*
26588 +        * Syscalls are being traced.
26589 +        * Call syscall_trace, (return here)
26590 +        */
26591 +       call    a5, syscall_trace
26592 +
26593 +       /*
26594 +        * Restore syscall state (it would have been discarded during the
26595 +        * syscall trace)
26596 +        */
26597 +       move.4  d0, PT_D0(sp)                   ; Restore d0 from kernel stack
26598 +       move.4  d1, PT_D1(sp)                   ; Restore d1 from kernel stack
26599 +       move.4  d2, PT_D2(sp)                   ; Restore d2 from kernel stack
26600 +       move.4  d3, PT_D3(sp)                   ; Restore d3 from kernel stack
26601 +       move.4  d4, PT_D4(sp)                   ; Restore d4 from kernel stack
26602 +       move.4  d5, PT_D5(sp)                   ; Restore d5 from kernel stack
26603 +       /* add this back if we ever have a syscall with 7 args */
26604 +       move.4  d8, PT_D8(sp)                   ; Restore d8 from kernel stack
26605 +
26606 +       /*
26607 +        * return to syscall
26608 +        */
26609 +       jmpt.t .Lsystem_call__trace_complete
26610 +       .size __system_call_bottom_half, . - __system_call_bottom_half
26611 +
26612 +/*
26613 + * syscall_exit()
26614 + */
26615 +       .section .text.syscall_exit
26616 +       .global syscall_exit
26617 +syscall_exit:
26618 +       /*
26619 +        * d0 contains the return value. We should move that into the kernel
26620 +        * stack d0 location.  We will be transitioning from kernel to user
26621 +        * mode. Test the flags and see if we have to call schedule. If we are
26622 +        * going to truly exit then all that has to be done is that from the
26623 +        * kernel stack we have to restore d0, a0, a1, a2, a5, a6 and sp (a7)bb
26624 +        * and then return via a5.
26625 +        */
26626 +
26627 +       /*
26628 +        * Save d0 to pt_regs
26629 +        */
26630 +       move.4  PT_D0(sp), d0                   ; Save d0 into the kernel stack
26631 +
26632 +       /*
26633 +        * load the thread_info structure by masking off the THREAD_SIZE
26634 +        * bits.
26635 +        *
26636 +        * Note: we used to push a1, but now we don't as we are going
26637 +        * to eventually restore it to the userspace a1.
26638 +        */
26639 +       movei   d9, #(~(ASM_THREAD_SIZE-1))
26640 +       and.4   a1, sp, d9
26641 +
26642 +       /*
26643 +        * Are any interesting bits set on TI flags, if there are jump
26644 +        * aside to post_processing.
26645 +        */
26646 +       move.4  d9, #(_TIF_SYSCALL_TRACE | _TIF_NEED_RESCHED | _TIF_SIGPENDING)
26647 +       and.4   #0, TI_FLAGS(a1), d9
26648 +       jmpne.f .Lsyscall_exit__post_processing ; jump to handler
26649 +.Lsyscall_exit__post_processing_complete:
26650 +
26651 +       move.4  d0, PT_D0(sp)                   ; Restore D0 from kernel stack
26652 +       move.4  d1, PT_D1(sp)                   ; Restore d1 from kernel stack
26653 +       move.4  d2, PT_D2(sp)                   ; Restore d2 from kernel stack
26654 +       move.4  d3, PT_D3(sp)                   ; Restore d3 from kernel stack
26655 +       move.4  d4, PT_D4(sp)                   ; Restore d4 from kernel stack
26656 +       move.4  d5, PT_D5(sp)                   ; Restore d5 from kernel stack
26657 +       move.4  d8, PT_D8(sp)                   ; Restore d8 from kernel stack
26658 +       move.4  d10, PT_D10(sp)                 ; Restore d10 from kernel stack
26659 +       move.4  d11, PT_D11(sp)                 ; Restore d11 from kernel stack
26660 +       move.4  d12, PT_D12(sp)                 ; Restore d12 from kernel stack
26661 +       move.4  d13, PT_D13(sp)                 ; Restore d13 from kernel stack
26662 +       move.4  a1, PT_A1(sp)                   ; Restore A1 from kernel stack
26663 +       move.4  a2, PT_A2(sp)                   ; Restore A2 from kernel stack
26664 +       move.4  a5, PT_A5(sp)                   ; Restore A5 from kernel stack
26665 +       move.4  a6, PT_A6(sp)                   ; Restore A6 from kernel stack
26666 +       move.4  a0, PT_A0(sp)                   ; Restore A6 from kernel stack
26667 +
26668 +       /*
26669 +        * this is only for debug, and could be removed for production builds
26670 +        */
26671 +       move.4  PT_FRAME_TYPE(sp), #0           ; invalidate frame_type
26672 +
26673 +#ifdef CONFIG_PROTECT_KERNEL
26674 +
26675 +       call a4, __syscall_exit_bottom_half
26676 +
26677 +       .section .kernel_unprotected, "ax", @progbits
26678 +__syscall_exit_bottom_half:
26679 +       /*
26680 +        * Enter critical section
26681 +        */
26682 +       atomic_lock_acquire
26683 +       disable_kernel_ranges_for_current d15
26684 +#endif
26685 +       /*
26686 +        * Lastly restore userspace stack ptr
26687 +        *
26688 +        * Note: that when protection is on we need to hold the lock around the
26689 +        * stack swap as well because otherwise the protection could get
26690 +        * inadvertently disabled again at the end of a context switch.
26691 +        */
26692 +       move.4  a7, PT_A7(sp)                   ; Restore A7 from kernel stack
26693 +
26694 +       /*
26695 +        * We are now officially back in userspace!
26696 +        */
26697 +
26698 +#ifdef CONFIG_PROTECT_KERNEL
26699 +       /*
26700 +        * Leave critical section and return to user space.
26701 +        */
26702 +       atomic_lock_release
26703 +#endif
26704 +       calli   a5, 0(a5)                       ; Back to userspace code.
26705 +
26706 +       bkpt #-1                                ; we will never get here
26707 +
26708 +       /*
26709 +        * Post syscall processing. (unlikely part of syscall_exit)
26710 +        *
26711 +        * Are we tracing syscalls. If TIF_SYSCALL_TRACE is set, call
26712 +        * syscall_trace routine and return here.
26713 +        */
26714 +       .section .text.syscall_exit, "ax", @progbits
26715 +.Lsyscall_exit__post_processing:
26716 +       btst    TI_FLAGS(a1), #ASM_TIF_SYSCALL_TRACE
26717 +       jmpeq.t 1f
26718 +       call    a5, syscall_trace
26719 +
26720 +       /*
26721 +        * Do we need to resched ie call schedule. If TIF_NEED_RESCHED is set,
26722 +        * call the scheduler, it will come back here.
26723 +        */
26724 +1:     btst    TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
26725 +       jmpeq.t 2f
26726 +       call    a5, schedule
26727 +
26728 +       /*
26729 +        * Do we need to post a signal, if TIF_SIGPENDING is set call the
26730 +        * do_signal.
26731 +        */
26732 +2:     btst    TI_FLAGS(a1), #ASM_TIF_SIGPENDING
26733 +       jmpeq.t .Lsyscall_exit__post_processing_complete
26734 +
26735 +       /*
26736 +        * setup the do signal call
26737 +        */
26738 +       move.4  d0, #0                          ; oldset pointer is NULL
26739 +       lea.1   d1, (sp)                        ; d1 is the regs pointer.
26740 +       call    a5, do_signal
26741 +
26742 +       jmpt.t  .Lsyscall_exit__post_processing_complete
26743 +
26744 +/*     .size syscall_exit, . - syscall_exit */
26745 +
26746 +/*
26747 + * kernel_execve()
26748 + *     kernel_execv is called when we the kernel is starting a
26749 + *     userspace application.
26750 + */
26751 +       .section .kernel_unprotected, "ax", @progbits
26752 +       .global kernel_execve
26753 +kernel_execve:
26754 +       move.4  -4(sp)++, a5                    ; Save return address
26755 +       /*
26756 +        * Call execve
26757 +        */
26758 +       movei   d8, #__NR_execve                ; call execve
26759 +       call    a5, system_call
26760 +       move.4  a5, (sp)4++
26761 +
26762 +       /*
26763 +        * protection was enabled again at syscall exit, but we want
26764 +        * to return to kernel so we enable it again.
26765 +        */
26766 +#ifdef CONFIG_PROTECT_KERNEL
26767 +       /*
26768 +        * We are entering the kernel so we need to disable the protection.
26769 +        * Enter critical section, disable ranges and leave critical section.
26770 +        */
26771 +       call a3, __enable_kernel_ranges ;  and jump back to kernel
26772 +#else
26773 +       ret a5                                  ; jump back to the kernel
26774 +#endif
26775 +
26776 +       .size kernel_execve, . - kernel_execve
26777 +
26778 +/*
26779 + * signal_trampoline()
26780 + *
26781 + *     Deals with transitioning from to userspace signal handlers and returning
26782 + *     to userspace, only called from the kernel.
26783 + *
26784 + */
26785 +       .section .kernel_unprotected, "ax", @progbits
26786 +       .global signal_trampoline
26787 +signal_trampoline:
26788 +       /*
26789 +        * signal_trampoline is called when we are jumping from the kernel to
26790 +        * the userspace signal handler.
26791 +        *
26792 +        * The following registers are relevant. (set setup_rt_frame)
26793 +        *   sp is the user space stack not the kernel stack
26794 +        *  d0 = signal number
26795 +        *  d1 = siginfo_t *
26796 +        *  d2 = ucontext *
26797 +        *  d3 = the user space signal handler
26798 +        *  a0 is set to the GOT if userspace application is FDPIC, otherwise 0
26799 +        *  a3 is set to the FD for the signal if userspace application is FDPIC
26800 +        */
26801 +#ifdef CONFIG_PROTECT_KERNEL
26802 +       /*
26803 +        * We are leaving the kernel so we need to enable the protection.
26804 +        * Enter critical section, disable ranges and leave critical section.
26805 +        */
26806 +       atomic_lock_acquire                     ; Enter critical section
26807 +       disable_kernel_ranges_for_current d15   ; disable kernel ranges
26808 +       atomic_lock_release                     ; Leave critical section
26809 +#endif
26810 +       /*
26811 +        * The signal handler pointer is in register d3 so tranfer it to a4 and
26812 +        * call it
26813 +        */
26814 +       movea   a4, d3                          ; signal handler
26815 +       calli   a5, 0(a4)
26816 +
26817 +       /*
26818 +        * Return to userspace through rt_syscall which is stored on top of the
26819 +        * stack d1 contains ret_via_interrupt status.
26820 +        */
26821 +       move.4  d8, (sp)                        ; d8 (syscall #) = rt_syscall
26822 +       move.4  d1, 4(sp)                       ; d1 = ret_via_interrupt
26823 +       call    a5, system_call         ; as we are 'in' the kernel
26824 +                                               ; we can call kernel_syscall
26825 +
26826 +       bkpt #-1                                ; will never get here.
26827 +       .size signal_trampoline, . - signal_trampoline
26828 +
26829 +/*
26830 + * kernel_thread_helper()
26831 + *
26832 + *     Entry point for kernel threads (only referenced by kernel_thread()).
26833 + *
26834 + *     On execution d0 will be 0, d1 will be the argument to be passed to the
26835 + *     kernel function.
26836 + *     d2 contains the kernel function that needs to get called.
26837 + *     d3 will contain address to do_exit which needs to get moved into a5.
26838 + *
26839 + *     On return from fork the child thread d0 will be 0. We call this dummy
26840 + *     function which in turn loads the argument
26841 + */
26842 +       .section .kernel_unprotected, "ax", @progbits
26843 +       .global kernel_thread_helper
26844 +kernel_thread_helper:
26845 +       /*
26846 +        * Create a kernel thread. This is called from ret_from_vfork (a
26847 +        * userspace return routine) so we need to put it in an unprotected
26848 +        * section and re-enable protection before calling the vector in d2.
26849 +        */
26850 +
26851 +#ifdef CONFIG_PROTECT_KERNEL
26852 +       /*
26853 +        * We are entering the kernel so we need to disable the protection.
26854 +        * Enter critical section, disable ranges and leave critical section.
26855 +        */
26856 +       call a5, __enable_kernel_ranges
26857 +#endif
26858 +       /*
26859 +        * Move argument for kernel function into d0, and set a5 return address
26860 +        * (a5) to do_exit and return through a2
26861 +        */
26862 +       move.4  d0, d1                          ; d0 = arg
26863 +       move.4  a5, d3                          ; a5 = do_exit
26864 +       ret     d2                              ; call function ptr in d2
26865 +       .size kernel_thread_helper, . - kernel_thread_helper
26866 +
26867 +#ifdef CONFIG_PROTECT_KERNEL
26868 +       .section .kernel_unprotected, "ax", @progbits
26869 +__enable_kernel_ranges:
26870 +       atomic_lock_acquire                     ; Enter critical section
26871 +       enable_kernel_ranges_for_current d15
26872 +       atomic_lock_release                     ; Leave critical section
26873 +       calli a5, 0(a5)
26874 +       .size __enable_kernel_ranges, . - __enable_kernel_ranges
26875 +
26876 +#endif
26877 +
26878 +/*
26879 + * The following system call intercept functions where we setup the
26880 + * input to the real system call.  In all cases these are just taking
26881 + * the current sp which is pointing to pt_regs and pushing it into the
26882 + * last arg of the system call.
26883 + *
26884 + * i.e. the public definition of sys_execv is
26885 + *     sys_execve(     char *name,
26886 + *                     char **argv,
26887 + *                     char **envp )
26888 + * but process.c defines it as
26889 + *     sys_execve(     char *name,
26890 + *                     char **argv,
26891 + *                     char **envp,
26892 + *                     struct pt_regs *regs )
26893 + *
26894 + * so execve_intercept needs to populate the 4th arg with pt_regs*,
26895 + * which is the stack pointer as we know we must be coming out of
26896 + * system_call
26897 + *
26898 + * The intercept vectors are referenced by syscalltable.S
26899 + */
26900 +
26901 +/*
26902 + * execve_intercept()
26903 + */
26904 +       .section .text.execve_intercept, "ax", @progbits
26905 +       .global execve_intercept
26906 +execve_intercept:
26907 +       move.4  d3, sp  ; Save pt_regs address
26908 +       call    a3, sys_execve
26909 +
26910 +       .size execve_intercept, . - execve_intercept
26911 +
26912 +/*
26913 + * vfork_intercept()
26914 + */
26915 +       .section .text.vfork_intercept, "ax", @progbits
26916 +       .global vfork_intercept
26917 +vfork_intercept:
26918 +       move.4  d0, sp  ; Save pt_regs address
26919 +       call    a3, sys_vfork
26920 +
26921 +       .size vfork_intercept, . - vfork_intercept
26922 +
26923 +/*
26924 + * clone_intercept()
26925 + */
26926 +       .section .text.clone_intercept, "ax", @progbits
26927 +       .global clone_intercept
26928 +clone_intercept:
26929 +       move.4  d2, sp  ; Save pt_regs address
26930 +       call    a3, sys_clone
26931 +
26932 +       .size clone_intercept, . - clone_intercept
26933 +
26934 +/*
26935 + * sys_sigsuspend()
26936 + */
26937 +       .section .text.sigclone_intercept, "ax", @progbits
26938 +       .global sys_sigsuspend
26939 +sys_sigsuspend:
26940 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26941 +       call    a3, do_sigsuspend
26942 +
26943 +       .size sys_sigsuspend, . - sys_sigsuspend
26944 +
26945 +/*
26946 + * sys_rt_sigsuspend()
26947 + */
26948 +       .section .text.sys_rt_sigsuspend, "ax", @progbits
26949 +       .global sys_rt_sigsuspend
26950 +sys_rt_sigsuspend:
26951 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26952 +       call    a3, do_rt_sigsuspend
26953 +
26954 +       .size sys_rt_sigsuspend, . - sys_rt_sigsuspend
26955 +
26956 +/*
26957 + * sys_rt_sigreturn()
26958 + */
26959 +       .section .text.sys_rt_sigreturn, "ax", @progbits
26960 +       .global sys_rt_sigreturn
26961 +sys_rt_sigreturn:
26962 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26963 +       call    a3, do_rt_sigreturn
26964 +
26965 +       .size sys_rt_sigreturn, . - sys_rt_sigreturn
26966 +
26967 +/*
26968 + * sys_sigaltstack()
26969 + */
26970 +       .section .text.sys_sigaltstack, "ax", @progbits
26971 +       .global sys_sigaltstack
26972 +sys_sigaltstack:
26973 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26974 +       call    a3, do_sys_sigaltstack
26975 +
26976 +       .size sys_sigaltstack, . - sys_sigaltstack
26977 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/unaligned_trap.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/unaligned_trap.c
26978 --- linux-2.6.30.10/arch/ubicom32/kernel/unaligned_trap.c       1970-01-01 02:00:00.000000000 +0200
26979 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/unaligned_trap.c   2009-12-11 11:45:11.000000000 +0200
26980 @@ -0,0 +1,698 @@
26981 +/*
26982 + * arch/ubicom32/kernel/unaligned_trap.c
26983 + *   Handle unaligned traps in both user or kernel space.
26984 + *
26985 + * (C) Copyright 2009, Ubicom, Inc.
26986 + *
26987 + * This file is part of the Ubicom32 Linux Kernel Port.
26988 + *
26989 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26990 + * it and/or modify it under the terms of the GNU General Public License
26991 + * as published by the Free Software Foundation, either version 2 of the
26992 + * License, or (at your option) any later version.
26993 + *
26994 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26995 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26996 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26997 + * the GNU General Public License for more details.
26998 + *
26999 + * You should have received a copy of the GNU General Public License
27000 + * along with the Ubicom32 Linux Kernel Port.  If not,
27001 + * see <http://www.gnu.org/licenses/>.
27002 + *
27003 + * Ubicom32 implementation derived from (with many thanks):
27004 + *   arch/m68knommu
27005 + *   arch/blackfin
27006 + *   arch/parisc
27007 + */
27008 +
27009 +#include <linux/types.h>
27010 +#include <linux/kernel.h>
27011 +#include <asm/cacheflush.h>
27012 +#include <asm/traps.h>
27013 +
27014 +#define FALSE 0
27015 +#define TRUE 1
27016 +
27017 +/* no possible trap */
27018 +#define UNUSED 0
27019 +/* possible source operand trap */
27020 +#define SRC 1
27021 +#define SRC_2 2
27022 +/* possible destination operand trap */
27023 +#define DEST 3
27024 +#define DEST_2 4
27025 +/* can be either source or destination or both */
27026 +#define TWO_OP 5
27027 +#define TWO_OP_2 6
27028 +
27029 +/* TODO: What is the real value here, put something in to make it compile for
27030 + * now */
27031 +#define MOVE_2 0x0d
27032 +#define LSL_2  0x11
27033 +#define LSR_2  0x13
27034 +#define MOVEI  0x19
27035 +#define CMPI   0x18
27036 +
27037 +static int op_format[32] =
27038 +{
27039 +       TWO_OP,         /* 0x00 */
27040 +       UNUSED,
27041 +       SRC,
27042 +       UNUSED,
27043 +       TWO_OP,         /* 0x04 */
27044 +       TWO_OP,
27045 +       SRC,
27046 +       UNUSED,
27047 +       TWO_OP_2,       /* 0x08 */
27048 +       TWO_OP,
27049 +       TWO_OP_2,
27050 +       TWO_OP,
27051 +       TWO_OP_2,       /* 0x0C */
27052 +       TWO_OP,
27053 +       TWO_OP_2,
27054 +       TWO_OP,
27055 +       TWO_OP,         /* 0x10 */
27056 +       TWO_OP_2,
27057 +       TWO_OP,
27058 +       TWO_OP,
27059 +       UNUSED,         /* 0x14 */
27060 +       UNUSED,
27061 +       UNUSED,
27062 +       UNUSED,
27063 +       SRC_2,          /* 0x18 */
27064 +       DEST_2,
27065 +       UNUSED,
27066 +       UNUSED,
27067 +       UNUSED,         /* 0x1C */
27068 +       UNUSED,
27069 +       UNUSED,         /* unaligned CALLI will not be fixed. */
27070 +       UNUSED
27071 +};
27072 +
27073 +static int op_0_format[32] =
27074 +{
27075 +       UNUSED,         /* 0x00 */
27076 +       UNUSED,
27077 +       UNUSED,
27078 +       UNUSED,
27079 +       UNUSED,         /* 0x04 - ret don't fix - bad ret is always wrong */
27080 +       UNUSED,
27081 +       UNUSED,
27082 +       UNUSED,
27083 +       UNUSED,         /* 0x08 */
27084 +       UNUSED,
27085 +       TWO_OP,
27086 +       TWO_OP_2,
27087 +       TWO_OP,         /* 0x0c */
27088 +       TWO_OP_2,
27089 +       TWO_OP,
27090 +       UNUSED,         /* .1 can't trap */
27091 +       UNUSED,         /* 0x10 */
27092 +       UNUSED,
27093 +       SRC,
27094 +       UNUSED,
27095 +       UNUSED,         /* 0x14 */
27096 +       TWO_OP_2,
27097 +       UNUSED,
27098 +       UNUSED,
27099 +       UNUSED,         /* 0x18 */
27100 +       UNUSED,
27101 +       UNUSED,
27102 +       UNUSED,
27103 +       DEST,           /* 0x1c */
27104 +       DEST,
27105 +       DEST,
27106 +       DEST,           /* all lea have 32-bit destination */
27107 +};
27108 +
27109 +static int op_2_format[32] =
27110 +{
27111 +       UNUSED,         /* 0x00 */
27112 +       UNUSED,
27113 +       UNUSED,
27114 +       UNUSED,
27115 +       UNUSED,         /* 0x04 */
27116 +       UNUSED,
27117 +       SRC,
27118 +       UNUSED,
27119 +       UNUSED,         /* 0x08 crcgen is .1 */
27120 +       UNUSED,
27121 +       UNUSED,
27122 +       UNUSED,
27123 +       UNUSED,         /* 0x0c */
27124 +       UNUSED,
27125 +       UNUSED,
27126 +       UNUSED,
27127 +       SRC,            /* 0x10 */
27128 +       SRC_2,
27129 +       SRC,
27130 +       SRC_2,
27131 +       SRC,            /* 0x14 */
27132 +       SRC_2,
27133 +       SRC,
27134 +       UNUSED,
27135 +       UNUSED,         /* 0x18 */
27136 +       UNUSED,
27137 +       SRC,
27138 +       UNUSED,
27139 +       SRC,            /* 0x1c */
27140 +       UNUSED,
27141 +       SRC_2,
27142 +       UNUSED,
27143 +};
27144 +
27145 +static int op_6_format[32] =
27146 +{
27147 +       SRC_2,          /* 0x00 */
27148 +       SRC_2,
27149 +       SRC_2,
27150 +       SRC_2,
27151 +       SRC_2,          /* 0x04 */
27152 +       SRC_2,
27153 +       UNUSED,
27154 +       SRC_2,
27155 +       SRC,            /* 0x08 MULS.4 */
27156 +       SRC_2,
27157 +       SRC,
27158 +       UNUSED,
27159 +       UNUSED,         /* 0x0c */
27160 +       UNUSED,
27161 +       UNUSED,
27162 +       UNUSED,
27163 +       SRC,            /* 0x10 */
27164 +       SRC_2,
27165 +       SRC,
27166 +       SRC_2,
27167 +       UNUSED,         /* 0x14 */
27168 +       UNUSED,
27169 +       UNUSED,
27170 +       UNUSED,
27171 +       UNUSED,         /* 0x18 */
27172 +       UNUSED,
27173 +       UNUSED,
27174 +       UNUSED,
27175 +       UNUSED,         /* 0x1c */
27176 +       UNUSED,
27177 +       UNUSED,
27178 +       UNUSED,
27179 +};
27180 +
27181 +/*
27182 + * unaligned_get_address()
27183 + *     get an address using save_an and save_dn registers, and updates save_an
27184 + *     with side effects
27185 + */
27186 +unsigned char *unaligned_get_address(int thread, int specifier, int four_byte,
27187 +                                    unsigned int save_an[],
27188 +                                    unsigned int save_dn[], int *write_back_an)
27189 +{
27190 +       unsigned char *address;
27191 +
27192 +       int areg = (specifier >> 5) & 7;
27193 +       if ((specifier >> 8) == 2) {
27194 +               int offset = specifier & 0xf;
27195 +               offset = ((offset << 28) >> 28);
27196 +               if (likely(four_byte)) {
27197 +                       offset <<= 2;
27198 +               } else {
27199 +                       offset <<= 1;
27200 +               }
27201 +               if (specifier & 0x10) {
27202 +                       address = (unsigned char *)(save_an[areg] + offset);
27203 +               } else {
27204 +                       address = (unsigned char *)save_an[areg];
27205 +               }
27206 +               save_an[areg] = save_an[areg] + offset;
27207 +
27208 +               /*
27209 +                * Let caller know An registers have been modified.
27210 +                */
27211 +               *write_back_an = 1;
27212 +       } else if ((specifier >> 8) == 3) {
27213 +               int dreg = specifier & 0xf;
27214 +               if (likely(four_byte)) {
27215 +                       address = (unsigned char *)(save_an[areg] +
27216 +                                                   (save_dn[dreg] << 2));
27217 +               } else {
27218 +                       address = (unsigned char *)(save_an[areg] +
27219 +                                                   (save_dn[dreg] << 1));
27220 +               }
27221 +       } else {
27222 +               int offset = ((specifier >> 3) & 0x60) | (specifier & 0x1f);
27223 +               if (likely(four_byte)) {
27224 +                       address = (unsigned char *)(save_an[areg] +
27225 +                                                   (offset << 2));
27226 +               } else {
27227 +                       address = (unsigned char *)(save_an[areg] +
27228 +                                                   (offset << 1));
27229 +               }
27230 +       }
27231 +
27232 +       return address;
27233 +}
27234 +
27235 +static int save_dn[16];
27236 +static int save_an[8];
27237 +static int save_acc[5];
27238 +
27239 +/*
27240 + * unaligned_emulate()
27241 + *     emulate the instruction at thread's pc that has taken an unaligned data
27242 + *     trap.
27243 + *
27244 + * source or destination or both might be unaligned
27245 + * the instruction must have a memory source or destination or both
27246 + * the emulated instruction is copied and executed in this thread
27247 + *
27248 + *     TODO: Protection is handled outside of this function
27249 + *     TODO: handling simultaneous unaligned and memory protection traps
27250 + *
27251 + *     Get thread state
27252 + *             the PC and instruction (and local copy, emulate_inst), and An
27253 + *             and Dn registers
27254 + *             All implicit soruce state (source3, CSR, accumulators)
27255 +
27256 + *     if the instruction has a memory source
27257 + *             Use the instruction, An and Dn registers to form src_address
27258 + *             get unaligned source data from src_address (usually sign
27259 + *             extended)
27260 + *                     (2 bytes, with or without sign extension, or 4 bytes)
27261 + *             modify emulate_inst to use d0 as source
27262 + *     else
27263 + *             get the soure operand from one of thread's registers
27264 + *     if instruction has a memory destination
27265 + *             Use the instruction, An and Dn registers to form dest_address
27266 + *             modify emulate_inst to use d0 as destination
27267 + *     if there was a memory source
27268 + *             put the source data in thread's d0
27269 + *     get the source-2 Dn operand and source 3 operand from thread
27270 + *     execute modified inst
27271 + *             (save it, flush caches, set up local values for implicit
27272 + *             sources, execute, save explicit and implicit results)
27273 + *     if inst has destination address
27274 + *             copy result to dest_address, possibly unaligned, 1, 2, or 4
27275 + *             bytes
27276 + *     restore thread's implicit results (modified address registers, CSR,
27277 + *     accumulators) add 4 to thread's pc
27278 + */
27279 +void unaligned_emulate(unsigned int thread)
27280 +{
27281 +       unsigned int pc;
27282 +       unsigned int inst;
27283 +       unsigned int op;
27284 +       unsigned int subop;
27285 +       int format;
27286 +       unsigned int emulate_inst;
27287 +       int four_byte;
27288 +       int src_operand, dest_operand;
27289 +       int save_csr;
27290 +       int source3;
27291 +       unsigned int source1;
27292 +       unsigned int source_data;
27293 +       unsigned char *dest_address = NULL;
27294 +       int source2 = 0;
27295 +       unsigned int result;
27296 +       unsigned int write_back_an = 0;
27297 +       unsigned int chip_id_copy;
27298 +
27299 +       extern unsigned int trap_emulate;
27300 +       extern unsigned int ubicom32_emulate_insn(int source1, int source2,
27301 +                                                 int source3, int *save_acc,
27302 +                                                 int *save_csr);
27303 +
27304 +       /*
27305 +        * get the chip_id
27306 +        */
27307 +       asm volatile (
27308 +       "       move.4          %0, chip_id             \n\t" /* get chip_id. */
27309 +               : "=r"(chip_id_copy)
27310 +               :
27311 +       );
27312 +
27313 +       /*
27314 +        * get the pc
27315 +        */
27316 +       asm volatile (
27317 +       "       move.4          CSR, %1         \n\t" /* set source thread in
27318 +                                                      * CSR */
27319 +       "       setcsr_flush    0               \n\t"
27320 +       "       move.4          %0, pc          \n\t"
27321 +       "       move.4          CSR, #0         \n\t" /* restore CSR */
27322 +       "       setcsr_flush    0               \n\t"
27323 +               : "=a"(pc)
27324 +               : "d" ((1 << 8) | (thread << 9))
27325 +               : "cc"
27326 +       );
27327 +
27328 +       inst = *((unsigned int *)pc);
27329 +       op = inst >> 27;
27330 +       if (unlikely(op == 2 || op == 6)) {
27331 +               subop = (inst >> 21) & 0x1f;
27332 +       } else {
27333 +               subop = (inst >> 11) & 0x1f;
27334 +       }
27335 +       format = op_format[op];
27336 +       emulate_inst = inst;
27337 +
27338 +       if (op == 0) {
27339 +               format = op_0_format[subop];
27340 +       } else if (op == 2) {
27341 +               format = op_2_format[subop];
27342 +       } else if (op == 6) {
27343 +               format = op_6_format[subop];
27344 +       }
27345 +
27346 +       if (unlikely(format == UNUSED)) {
27347 +               /*
27348 +                * We are not going to emulate this. Bump PC by 4 and move on.
27349 +                */
27350 +               asm volatile (
27351 +               "       move.4          CSR, %0                 \n\t"
27352 +               "       setcsr_flush    0                       \n\t"
27353 +               "       move.4          pc, %1                  \n\t"
27354 +               "       setcsr          #0                      \n\t"
27355 +               "       setcsr_flush    0                       \n\t"
27356 +                       :
27357 +                       : "d"((1 << 14) | (thread << 15)), "d"(pc + 4)
27358 +                       : "cc"
27359 +               );
27360 +               return;
27361 +       }
27362 +
27363 +       four_byte = (format == TWO_OP || format == DEST || format == SRC);
27364 +
27365 +       /*
27366 +        * source or destination memory operand needs emulation
27367 +        */
27368 +       src_operand = (format == SRC ||
27369 +                      format == SRC_2 ||
27370 +                      format == TWO_OP ||
27371 +                      format == TWO_OP_2) &&
27372 +               ((inst >> 8) & 7) > 1;
27373 +
27374 +       dest_operand = (format == DEST ||
27375 +                       format == DEST_2 ||
27376 +                       format == TWO_OP ||
27377 +                       format == TWO_OP_2) &&
27378 +               ((inst >> 24) & 7) > 1;
27379 +
27380 +       /*
27381 +        * get thread's implicit sources (not covered by source context select).
27382 +        * data and address registers and CSR (for flag bits) and src3 and
27383 +        * accumulators
27384 +        */
27385 +       asm volatile (
27386 +       "       move.4          CSR, %2         \n\t"   /* set source thread in
27387 +                                                        * CSR */
27388 +       "       setcsr_flush    0               \n\t"
27389 +       "       move.4          (%3), d0        \n\t"   /* get dn registers */
27390 +       "       move.4          4(%3), d1       \n\t"
27391 +       "       move.4          8(%3), d2       \n\t"
27392 +       "       move.4          12(%3), d3      \n\t"
27393 +       "       move.4          16(%3), d4      \n\t"
27394 +       "       move.4          20(%3), d5      \n\t"
27395 +       "       move.4          24(%3), d6      \n\t"
27396 +       "       move.4          28(%3), d7      \n\t"
27397 +       "       move.4          32(%3), d8      \n\t"
27398 +       "       move.4          36(%3), d9      \n\t"
27399 +       "       move.4          40(%3), d10     \n\t"
27400 +       "       move.4          44(%3), d11     \n\t"
27401 +       "       move.4          48(%3), d12     \n\t"
27402 +       "       move.4          52(%3), d13     \n\t"
27403 +       "       move.4          56(%3), d14     \n\t"
27404 +       "       move.4          60(%3), d15     \n\t"
27405 +       "       move.4          (%4), a0        \n\t"   /* get an registers */
27406 +       "       move.4          4(%4), a1       \n\t"
27407 +       "       move.4          8(%4), a2       \n\t"
27408 +       "       move.4          12(%4), a3      \n\t"
27409 +       "       move.4          16(%4), a4      \n\t"
27410 +       "       move.4          20(%4), a5      \n\t"
27411 +       "       move.4          24(%4), a6      \n\t"
27412 +       "       move.4          28(%4), a7      \n\t"
27413 +       "       move.4          %0, CSR         \n\t"   /* get csr and source3
27414 +                                                        * implicit operands */
27415 +       "       move.4          %1, source3     \n\t"
27416 +       "       move.4          (%5), acc0_lo   \n\t"   /* get accumulators */
27417 +       "       move.4          4(%5), acc0_hi  \n\t"
27418 +       "       move.4          8(%5), acc1_lo  \n\t"
27419 +       "       move.4          12(%5), acc1_hi \n\t"
27420 +       "       move.4          16(%5), mac_rc16        \n\t"
27421 +       "       move.4          CSR, #0         \n\t"   /* restore CSR */
27422 +       "       setcsr_flush    0               \n\t"
27423 +               : "=m"(save_csr), "=m"(source3)
27424 +               : "d"((1 << 8) | (thread << 9)),
27425 +                 "a"(save_dn), "a"(save_an), "a"(save_acc)
27426 +               : "cc"
27427 +       );
27428 +
27429 +       /*
27430 +        * turn off thread select bits if they were on
27431 +        */
27432 +       BUG_ON((save_csr & 0x04100) != 0);
27433 +       if (unlikely(save_csr & 0x04100)) {
27434 +               /*
27435 +                * Things are in funny state as thread select bits are on in
27436 +                * csr. PANIC.
27437 +                */
27438 +               panic("In unaligned trap handler. Trap thread CSR has thread "
27439 +                     "select bits on.\n");
27440 +       }
27441 +
27442 +       save_csr = save_csr & 0x1000ff;
27443 +
27444 +       /*
27445 +        * get the source1 operand
27446 +        */
27447 +       source1 = 0;
27448 +       if (src_operand) {
27449 +               unsigned char *src_address;
27450 +
27451 +               /*
27452 +                * source1 comes from memory
27453 +                */
27454 +               BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27455 +                        format == SRC || format == SRC_2));
27456 +               src_address = unaligned_get_address(thread, inst & 0x7ff,
27457 +                                                   four_byte, save_an,
27458 +                                                   save_dn, &write_back_an);
27459 +
27460 +               /*
27461 +                * get data (possibly unaligned)
27462 +                */
27463 +               if (likely(four_byte)) {
27464 +                       source_data = (*src_address << 24) |
27465 +                               (*(src_address + 1) << 16) |
27466 +                               (*(src_address + 2) << 8) |
27467 +                               *(src_address + 3);
27468 +                       source1 = source_data;
27469 +               } else {
27470 +                       source1 = *src_address << 8 |
27471 +                               *(src_address + 1);
27472 +
27473 +                       /*
27474 +                        * Source is not extended if the instrution is MOVE.2 or
27475 +                        * if the cpu CHIP_ID >= 0x30000 and the instruction is
27476 +                        * either LSL.2 or LSR.2.  All other cases have to be
27477 +                        * sign extended.
27478 +                        */
27479 +                       if ((!(op == 2 && subop == MOVE_2)) &&
27480 +                           (!((chip_id_copy >= 0x30000) &&
27481 +                              (subop == LSL_2 || subop == LSR_2)))) {
27482 +                               /*
27483 +                                * Have to sign extend the .2 entry.
27484 +                                */
27485 +                               source1 = ((unsigned int)
27486 +                                          ((signed int)
27487 +                                           ((signed short) source1)));
27488 +                       }
27489 +               }
27490 +       } else if (likely(op != MOVEI)) {
27491 +               /*
27492 +                * source1 comes from a register, using move.4 d0, src1
27493 +                * unaligned_emulate_get_source is pointer to code to insert remulated instruction
27494 +                */
27495 +               extern unsigned int unaligned_emulate_get_src;
27496 +               *((int *)&unaligned_emulate_get_src) &= ~(0x7ff);
27497 +               *((int *)&unaligned_emulate_get_src) |= (inst & 0x7ff);
27498 +               flush_dcache_range((unsigned long)(&unaligned_emulate_get_src),
27499 +                                  (unsigned long)(&unaligned_emulate_get_src) + 4);
27500 +
27501 +               asm volatile (
27502 +                       /* source1 uses thread's registers */
27503 +               "       move.4          CSR, %1                 \n\t"
27504 +               "       setcsr_flush 0                          \n\t"
27505 +               "unaligned_emulate_get_src:                     \n\t"
27506 +               "       move.4  %0, #0                          \n\t"
27507 +               "       setcsr          #0                      \n\t"
27508 +               "       setcsr_flush    0                       \n\t"
27509 +                       : "=d" (source1)
27510 +                       : "d" ((1 << 8) | (thread << 9))
27511 +                       : "cc"
27512 +               );
27513 +       }
27514 +
27515 +       /*
27516 +        * get the destination address
27517 +        */
27518 +       if (dest_operand) {
27519 +               BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27520 +                        format == DEST || format == DEST_2));
27521 +               dest_address = unaligned_get_address(thread,
27522 +                                                    ((inst >> 16) & 0x7ff),
27523 +                                                    four_byte, save_an,
27524 +                                                    save_dn, &write_back_an);
27525 +       }
27526 +
27527 +       if (write_back_an) {
27528 +               /*
27529 +                * restore any modified An registers
27530 +                */
27531 +               asm volatile (
27532 +               "       move.4          CSR, %0                 \n\t"
27533 +               "       setcsr_flush    0                       \n\t"
27534 +               "       move.4          a0, (%1)                \n\t"
27535 +               "       move.4          a1, 4(%1)               \n\t"
27536 +               "       move.4          a2, 8(%1)               \n\t"
27537 +               "       move.4          a3, 12(%1)              \n\t"
27538 +               "       move.4          a4, 16(%1)              \n\t"
27539 +               "       move.4          a5, 20(%1)              \n\t"
27540 +               "       move.4          a6, 24(%1)              \n\t"
27541 +               "       move.4          a7, 28(%1)              \n\t"
27542 +               "       setcsr          #0                      \n\t"
27543 +               "       setcsr_flush    0                       \n\t"
27544 +                       :
27545 +                       : "d" ((1 << 14) | (thread << 15)), "a" (save_an)
27546 +                       : "cc"
27547 +               );
27548 +       }
27549 +
27550 +       /*
27551 +        * get source 2 register if needed, and modify inst to use d1 for
27552 +        * source-2 source-2 will come from this thread, not the trapping thread
27553 +        */
27554 +       source2 = 0;
27555 +       if ((op >= 8 && op <= 0x17) ||
27556 +           ((op == 2 || op == 6) && (inst & 0x4000000))) {
27557 +               int src_dn = (inst >> 11) & 0xf;
27558 +               source2 = save_dn[src_dn];
27559 +               /*
27560 +                * force the emulated instruction to use d1 for source2 operand
27561 +                */
27562 +               emulate_inst = (emulate_inst & 0xffff07ff) | 0x800;
27563 +       }
27564 +
27565 +       if (likely(op != MOVEI)) {
27566 +               /*
27567 +                * change emulated instruction source1 to d0
27568 +                */
27569 +               emulate_inst &= ~0x7ff;
27570 +               emulate_inst |= 1 << 8;
27571 +       }
27572 +
27573 +       if (unlikely(op == 6 || op == 2)) {
27574 +               /*
27575 +                * Set destination to d0
27576 +                */
27577 +               emulate_inst &= ~(0xf << 16);
27578 +       } else if (likely(op != CMPI)) {
27579 +               /*
27580 +                * Set general destination field to d0.
27581 +                */
27582 +               emulate_inst &= ~(0x7ff << 16);
27583 +               emulate_inst |= 1 << 24;
27584 +       }
27585 +
27586 +       /*
27587 +        * execute emulated instruction d0, to d0, no memory access
27588 +        * source2 if needed will be in d1
27589 +        * source3, CSR, and accumulators are set up before execution
27590 +        */
27591 +       *((unsigned int *)&trap_emulate) = emulate_inst;
27592 +       flush_dcache_range((unsigned long)(&trap_emulate),
27593 +                          (unsigned long)(&trap_emulate) + 4);
27594 +
27595 +       result = ubicom32_emulate_insn(source1, source2, source3,
27596 +                                      save_acc, &save_csr);
27597 +
27598 +       /*
27599 +        * set the result value
27600 +        */
27601 +       if (dest_operand) {
27602 +               /*
27603 +                * copy result to memory
27604 +                */
27605 +               if (four_byte) {
27606 +                       *dest_address++ =
27607 +                               (unsigned char)((result >> 24) & 0xff);
27608 +                       *dest_address++ =
27609 +                               (unsigned char)((result >> 16) & 0xff);
27610 +               }
27611 +               *dest_address++ = (unsigned char)((result >> 8) & 0xff);
27612 +               *dest_address = (unsigned char)(result & 0xff);
27613 +       } else if (likely(op != CMPI)) {
27614 +               /*
27615 +                * copy result to a register, using move.4 dest, result
27616 +                */
27617 +               extern unsigned int unaligned_trap_set_result;
27618 +               *((unsigned int *)&unaligned_trap_set_result) &= ~0x7ff0000;
27619 +
27620 +               if (op == 2 || op == 6) {
27621 +                       *((unsigned int *)&unaligned_trap_set_result) |=
27622 +                               ((inst & 0x000f0000) | 0x01000000);
27623 +               } else {
27624 +                       *((unsigned int *)&unaligned_trap_set_result) |=
27625 +                               (inst & 0x7ff0000);
27626 +               }
27627 +               flush_dcache_range((unsigned long)&unaligned_trap_set_result,
27628 +                                  ((unsigned long)(&unaligned_trap_set_result) + 4));
27629 +
27630 +               asm volatile (
27631 +                       /* result uses thread's registers */
27632 +               "       move.4          CSR, %1                 \n\t"
27633 +               "       setcsr_flush 0                          \n\t"
27634 +               "unaligned_trap_set_result:                     \n\t"
27635 +               "       move.4 #0, %0                           \n\t"
27636 +               "       setcsr          #0                      \n\t"
27637 +               "       setcsr_flush    0                       \n\t"
27638 +                       :
27639 +                       : "d"(result), "d" ((1 << 14) | (thread << 15))
27640 +                       : "cc"
27641 +               );
27642 +       }
27643 +
27644 +       /*
27645 +        * bump PC in thread and restore implicit register changes
27646 +        */
27647 +       asm volatile (
27648 +       "       move.4          CSR, %0                 \n\t"
27649 +       "       setcsr_flush    0                       \n\t"
27650 +       "       move.4          pc, %1                  \n\t"
27651 +       "       move.4          acc0_lo, (%3)           \n\t"
27652 +       "       move.4          acc0_hi, 4(%3)          \n\t"
27653 +       "       move.4          acc1_lo, 8(%3)          \n\t"
27654 +       "       move.4          acc1_hi, 12(%3)         \n\t"
27655 +       "       move.4          mac_rc16, 16(%3)        \n\t"
27656 +       "       move.4          CSR, %2                 \n\t"
27657 +       "       setcsr          #0                      \n\t"
27658 +       "       setcsr_flush    0                       \n\t"
27659 +               :
27660 +               : "d"((1 << 14) | (thread << 15)),
27661 +                 "d"(pc + 4), "d"(save_csr), "a"(save_acc)
27662 +               : "cc"
27663 +       );
27664 +}
27665 +
27666 +/*
27667 + * unaligned_only()
27668 + *     Return true if either of the unaligned causes are set (and no others).
27669 + */
27670 +int unaligned_only(unsigned int cause)
27671 +{
27672 +       unsigned int unaligned_cause_mask =
27673 +               (1 << TRAP_CAUSE_DST_MISALIGNED) |
27674 +               (1 << TRAP_CAUSE_SRC1_MISALIGNED);
27675 +
27676 +       BUG_ON(cause == 0);
27677 +       return (cause & unaligned_cause_mask) == cause;
27678 +}
27679 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/vmlinux.lds.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/vmlinux.lds.S
27680 --- linux-2.6.30.10/arch/ubicom32/kernel/vmlinux.lds.S  1970-01-01 02:00:00.000000000 +0200
27681 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/vmlinux.lds.S      2009-12-11 11:45:11.000000000 +0200
27682 @@ -0,0 +1,370 @@
27683 +/*
27684 + * arch/ubicom32/kernel/vmlinux.lds.S
27685 + *     vmlinux primary linker script
27686 + *
27687 + * (C) Copyright 2009, Ubicom, Inc.
27688 + *
27689 + * This file is part of the Ubicom32 Linux Kernel Port.
27690 + *
27691 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
27692 + * it and/or modify it under the terms of the GNU General Public License
27693 + * as published by the Free Software Foundation, either version 2 of the
27694 + * License, or (at your option) any later version.
27695 + *
27696 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
27697 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
27698 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
27699 + * the GNU General Public License for more details.
27700 + *
27701 + * You should have received a copy of the GNU General Public License
27702 + * along with the Ubicom32 Linux Kernel Port.  If not,
27703 + * see <http://www.gnu.org/licenses/>.
27704 + *
27705 + * Ubicom32 implementation derived from (with many thanks):
27706 + *   arch/m68knommu
27707 + *   arch/blackfin
27708 + *   arch/parisc
27709 + */
27710 +#include <asm-generic/vmlinux.lds.h>
27711 +#include <asm/ocm_size.h>
27712 +#include <asm/memory_map.h>
27713 +#include <asm/thread_info.h>
27714 +#include <linux/threads.h>
27715 +
27716 +/*
27717 + * Sanity checks to prevent errors later on that are much harder to understand
27718 + */
27719 +#if !defined APP_OCM_CODE_SIZE
27720 +#error APP_OCM_CODE_SIZE has not been defined in ocm_size.h
27721 +#endif
27722 +
27723 +#if !defined APP_OCM_DATA_SIZE
27724 +#error APP_OCM_DATA_SIZE has not been defined in ocm_size.h
27725 +#endif
27726 +
27727 +/*
27728 + * The `free' ocm area that ultra does not use.
27729 + */
27730 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
27731 +#define OCM_FREE_START (OCMSTART + APP_OCM_CODE_SIZE)
27732 +#define OCM_FREE_LENGTH        (OCMSIZE - APP_OCM_CODE_SIZE - APP_OCM_DATA_SIZE)
27733 +#else
27734 +#define OCM_FREE_START OCMEND
27735 +#define OCM_FREE_LENGTH 0
27736 +#endif
27737 +
27738 +/*
27739 + * If you want to limit OCM use for text/data or completely disable it
27740 + * you can change these values.
27741 + */
27742 +#define OCM_TEXT_LENGTH        OCM_FREE_LENGTH
27743 +#define OCM_DATA_LENGTH        OCM_FREE_LENGTH
27744 +
27745 +#define        RAM_START       KERNELSTART
27746 +#define        RAM_LENGTH      ((SDRAMSTART + CONFIG_MIN_RAMSIZE) - RAM_START)
27747 +#define        TEXT            ram
27748 +#define        DATA            ram
27749 +#define        INIT            ram
27750 +#define        BSS             ram
27751 +
27752 +#ifndef DATA_ADDR
27753 +#define        DATA_ADDR
27754 +#endif
27755 +
27756 +#include <asm-generic/vmlinux.lds.h>
27757 +
27758 +OUTPUT_ARCH(ubicom32)
27759 +ENTRY(_start)
27760 +
27761 +MEMORY {
27762 +       ram             : ORIGIN = RAM_START, LENGTH = RAM_LENGTH
27763 +       syscall         : ORIGIN = OS_SYSCALL_BEGIN, LENGTH = (OS_SYSCALL_END - OS_SYSCALL_BEGIN)
27764 +       ocm             : ORIGIN = OCM_FREE_START, LENGTH = OCM_FREE_LENGTH
27765 +}
27766 +
27767 +jiffies = jiffies_64 + 4;
27768 +
27769 +/*
27770 + * Fixed locations required by gdb coredumps.
27771 + *
27772 + * Note that the names are what gdb is expecting so renaming will break
27773 + * the toolchain.
27774 + */
27775 +__ocm_begin            = OCMSTART;
27776 +__ocm_limit            = __ocm_begin + OCMSIZE;
27777 +__sdram_begin          = SDRAMSTART;
27778 +__sdram_limit          = __sdram_begin + CONFIG_MIN_RAMSIZE;
27779 +__filemedia_begin_addr = FLASHSTART;
27780 +__filemedia_end_addr   = __filemedia_begin_addr + 0x00800000;
27781 +
27782 +/*
27783 + * For internal diagnostics
27784 + */
27785 +__os_syscall_begin     = OS_SYSCALL_BEGIN;
27786 +__os_syscall_end       = OS_SYSCALL_END;
27787 +
27788 +SECTIONS {
27789 +
27790 +       .fixed_text : {
27791 +               _begin = .;
27792 +               *(.skip_syscall)
27793 +               *(.old_syscall_entry.text)
27794 +               __fixed_text_end = .;
27795 +       } > TEXT
27796 +       . = _begin + SIZEOF(.fixed_text) ;
27797 +
27798 +       /*
27799 +        * System call text in lower ocm (fixed location, can never change)
27800 +        */
27801 +       __syscall_text_load_begin = .;
27802 +       __syscall_text_run_begin = OS_SYSCALL_BEGIN;
27803 +
27804 +       .syscall_text __syscall_text_run_begin : AT(__syscall_text_load_begin) {
27805 +               *(.syscall_entry.text) /* Must be at OS_SYSCALL_BEGIN 0x3ffc0040 */
27806 +               *(.kernel_unprotected)
27807 +               . = ALIGN(4);
27808 +               __syscall_text_run_end = .;
27809 +       } > syscall /* .syscall_text */
27810 +       . = __syscall_text_load_begin + __syscall_text_run_end - __syscall_text_run_begin ;
27811 +       __ocm_text_load_begin = .;
27812 +       __ocm_text_run_begin = OCM_FREE_START ;
27813 +       .ocm_text __ocm_text_run_begin : AT(__ocm_text_load_begin) {
27814 +#if OCM_TEXT_LENGTH
27815 +               *(.ocm_text)
27816 +               *(.sched.text)
27817 +               *(.spinlock.text)
27818 +#include <asm/ocm_text.lds.inc>
27819 +               . = ALIGN(4);
27820 +#endif
27821 +               __ocm_text_run_end = .;
27822 +               __data_begin = ALIGN(OCM_SECTOR_SIZE);
27823 +       } > ocm /* .ocm_text */
27824 +
27825 +       .ocm_module_text __ocm_text_run_end (NOLOAD) : AT(__ocm_text_run_end) {
27826 +               __ocm_inst_heap_begin = .;
27827 +               /* Reserve the min requested */
27828 +               . += (CONFIG_OCM_MODULES_RESERVATION) * 1024;
27829 +#ifdef CONFIG_OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
27830 +               /* Round up to OCM sector size (we cannot use it for data) */
27831 +               . = ALIGN(OCM_SECTOR_SIZE);
27832 +#endif
27833 +               __ocm_inst_heap_end = .;
27834 +               /* update __data_begin */
27835 +               __data_begin = ALIGN(OCM_SECTOR_SIZE);
27836 +       } > ocm  /* .ocm_module_text */
27837 +
27838 +       . = __ocm_text_load_begin + __ocm_text_run_end - __ocm_text_run_begin ;
27839 +       __ocm_text_load_end = .;
27840 +
27841 +       __ocm_data_load_begin = .;
27842 +       __ocm_data_run_begin = __data_begin ;
27843 +#if OCM_DATA_LENGTH
27844 +       .ocm_data __ocm_data_run_begin : AT(__ocm_data_load_begin) {
27845 +#if defined(CONFIG_IRQSTACKS_USEOCM)
27846 +               percpu_irq_stacks = .;
27847 +               . += NR_CPUS * THREAD_SIZE;
27848 +#endif
27849 +               *(.ocm_data)
27850 +               . = ALIGN(4) ;
27851 +               __ocm_data_run_end = .;
27852 +       } > ocm
27853 +       . = __ocm_data_load_begin + __ocm_data_run_end - __ocm_data_run_begin ;
27854 +#else
27855 +       __ocm_data_run_end = __ocm_data_run_begin;
27856 +#endif
27857 +       __ocm_data_load_end = .;
27858 +
27859 +       __ocm_free_begin = __ocm_data_run_end;
27860 +       __ocm_free_end = OCM_FREE_START + OCM_FREE_LENGTH;
27861 +
27862 +       .text __ocm_data_load_end : AT(__ocm_data_load_end) {
27863 +               . = ALIGN(4);
27864 +               _stext = .;
27865 +               _text = .;
27866 +               TEXT_TEXT
27867 +               SCHED_TEXT
27868 +               LOCK_TEXT
27869 +               *(.text.lock)
27870 +               *(.text.__libgcc_udivmodsi)
27871 +               *(.text.__libgcc_divmodsi)
27872 +               *(.text.__libgcc_muldi3)
27873 +               *(.text.__libgcc_udivmoddi)
27874 +               *(.text.__libgcc_divmoddi)
27875 +               *(.text.*)
27876 +#if OCM_TEXT_LENGTH == 0
27877 +               *(.ocm_text)
27878 +               *(.sched.text)
27879 +               *(.spinlock.text)
27880 +#endif
27881 +               . = ALIGN(16);          /* Exception table              */
27882 +               __start___ex_table = .;
27883 +               *(__ex_table)
27884 +               __stop___ex_table = .;
27885 +
27886 +               *(.rodata) *(.rodata.*)
27887 +               *(__vermagic)           /* Kernel version magic */
27888 +               *(__markers_strings)
27889 +               *(.rodata1)
27890 +               *(.rodata.str1.1)
27891 +               *(__tracepoints_strings)
27892 +
27893 +                /* PCI quirks */
27894 +               __start_pci_fixups_early = . ;
27895 +                       *(.pci_fixup_early)
27896 +               __end_pci_fixups_early = . ;
27897 +               __start_pci_fixups_header = . ;
27898 +                       *(.pci_fixup_header)
27899 +               __end_pci_fixups_header = . ;
27900 +               __start_pci_fixups_final = . ;
27901 +                       *(.pci_fixup_final)
27902 +               __end_pci_fixups_final = . ;
27903 +               __start_pci_fixups_enable = . ;
27904 +                       *(.pci_fixup_enable)
27905 +               __end_pci_fixups_enable = . ;
27906 +               __start_pci_fixups_resume = . ;
27907 +                      *(.pci_fixup_resume)
27908 +               __end_pci_fixups_resume = . ;
27909 +               __start_pci_fixups_resume_early = . ;
27910 +                      *(.pci_fixup_resume_early)
27911 +               __end_pci_fixups_resume_early = . ;
27912 +               __start_pci_fixups_suspend  = . ;
27913 +                      *(.pci_fixup_suspend)
27914 +               __end_pci_fixups_suspend = . ;
27915 +
27916 +               __start_builtin_fw = . ;
27917 +                       *(.builtin_fw)
27918 +               __end_builtin_fw = . ;
27919 +
27920 +
27921 +               /* Kernel symbol table: Normal symbols */
27922 +               . = ALIGN(4);
27923 +               __start___ksymtab = .;
27924 +               *(__ksymtab)
27925 +               __stop___ksymtab = .;
27926 +
27927 +               /* Kernel symbol table: GPL-only symbols */
27928 +               __start___ksymtab_gpl = .;
27929 +               *(__ksymtab_gpl)
27930 +               __stop___ksymtab_gpl = .;
27931 +
27932 +               /* Kernel symbol table: Normal unused symbols */
27933 +               __start___ksymtab_unused = .;
27934 +               *(__ksymtab_unused)
27935 +               __stop___ksymtab_unused = .;
27936 +
27937 +               /* Kernel symbol table: GPL-only unused symbols */
27938 +               __start___ksymtab_unused_gpl = .;
27939 +               *(__ksymtab_unused_gpl)
27940 +               __stop___ksymtab_unused_gpl = .;
27941 +
27942 +               /* Kernel symbol table: GPL-future symbols */
27943 +               __start___ksymtab_gpl_future = .;
27944 +               *(__ksymtab_gpl_future)
27945 +               __stop___ksymtab_gpl_future = .;
27946 +
27947 +               /* Kernel symbol table: Normal symbols */
27948 +               __start___kcrctab = .;
27949 +               *(__kcrctab)
27950 +               __stop___kcrctab = .;
27951 +
27952 +               /* Kernel symbol table: GPL-only symbols */
27953 +               __start___kcrctab_gpl = .;
27954 +               *(__kcrctab_gpl)
27955 +               __stop___kcrctab_gpl = .;
27956 +
27957 +               /* Kernel symbol table: GPL-future symbols */
27958 +               __start___kcrctab_gpl_future = .;
27959 +               *(__kcrctab_gpl_future)
27960 +               __stop___kcrctab_gpl_future = .;
27961 +
27962 +               /* Kernel symbol table: strings */
27963 +               *(__ksymtab_strings)
27964 +
27965 +               /* Built-in module parameters */
27966 +               . = ALIGN(4) ;
27967 +               __start___param = .;
27968 +               *(__param)
27969 +               __stop___param = .;
27970 +
27971 +               . = ALIGN(4) ;
27972 +               _etext = . ;
27973 +       } > TEXT
27974 +
27975 +       .data DATA_ADDR : {
27976 +               . = ALIGN(4);
27977 +               _sdata = . ;
27978 +               DATA_DATA
27979 +#if OCM_DATA_LENGTH == 0
27980 +               *(.ocm_data)
27981 +#endif
27982 +               . = ALIGN(8192) ;
27983 +               _data_protection_end = .;
27984 +               *(.data.init_task)
27985 +               . = ALIGN(4);
27986 +               _edata = . ;
27987 +       } > DATA
27988 +
27989 +       .init : {
27990 +               . = ALIGN(4096);
27991 +               __init_begin = .;
27992 +               _sinittext = .;
27993 +               INIT_TEXT
27994 +               _einittext = .;
27995 +               *(.init.rodata)
27996 +               INIT_DATA
27997 +               . = ALIGN(16);
27998 +               __setup_start = .;
27999 +               *(.init.setup)
28000 +               __setup_end = .;
28001 +               __initcall_start = .;
28002 +               INITCALLS
28003 +               __initcall_end = .;
28004 +               __con_initcall_start = .;
28005 +               *(.con_initcall.init)
28006 +               __con_initcall_end = .;
28007 +               ___security_initcall_start = .;
28008 +               *(.security_initcall.init)
28009 +               ___security_initcall_end = .;
28010 +#ifdef CONFIG_BLK_DEV_INITRD
28011 +               . = ALIGN(4);
28012 +               __initramfs_start = .;
28013 +               *(.init.ramfs)
28014 +               __initramfs_end = .;
28015 +#endif
28016 +               . = ALIGN(4096);
28017 +               __per_cpu_start = .;
28018 +                       *(.data.percpu)
28019 +                       *(.data.percpu.shared_aligned)
28020 +               __per_cpu_end = .;
28021 +
28022 +               . = ALIGN(4096);
28023 +               __init_end = .;
28024 +       } > INIT
28025 +
28026 +         .eh_frame   :
28027 +         {
28028 +           PROVIDE (___eh_frame_begin = .);
28029 +           *(.eh_frame)
28030 +           LONG (0);
28031 +           PROVIDE (___eh_frame_end = .);
28032 +         } > INIT
28033 +
28034 +       /DISCARD/ : {
28035 +               EXIT_TEXT
28036 +               EXIT_DATA
28037 +               *(.exitcall.exit)
28038 +       }
28039 +
28040 +       .bss : {
28041 +               . = ALIGN(4);
28042 +               _sbss = . ;
28043 +               *(.bss)
28044 +               *(COMMON)
28045 +               . = ALIGN(4) ;
28046 +               _ebss = . ;
28047 +               _end = . ;
28048 +       } > BSS
28049 +
28050 +       NOTES > BSS
28051 +
28052 +}
28053 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/checksum.c linux-2.6.30.10-ubi/arch/ubicom32/lib/checksum.c
28054 --- linux-2.6.30.10/arch/ubicom32/lib/checksum.c        1970-01-01 02:00:00.000000000 +0200
28055 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/checksum.c    2009-12-11 11:45:11.000000000 +0200
28056 @@ -0,0 +1,250 @@
28057 +/*
28058 + * arch/ubicom32/lib/checksum.c
28059 + *   Optimized checksum utilities for IP.
28060 + *
28061 + * (C) Copyright 2009, Ubicom, Inc.
28062 + *
28063 + * This file is part of the Ubicom32 Linux Kernel Port.
28064 + *
28065 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28066 + * it and/or modify it under the terms of the GNU General Public License
28067 + * as published by the Free Software Foundation, either version 2 of the
28068 + * License, or (at your option) any later version.
28069 + *
28070 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28071 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28072 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28073 + * the GNU General Public License for more details.
28074 + *
28075 + * You should have received a copy of the GNU General Public License
28076 + * along with the Ubicom32 Linux Kernel Port.  If not,
28077 + * see <http://www.gnu.org/licenses/>.
28078 + *
28079 + * Ubicom32 implementation derived from (with many thanks):
28080 + *   arch/m68knommu
28081 + *   arch/blackfin
28082 + *   arch/parisc
28083 + */
28084 +/*
28085 + * INET                An implementation of the TCP/IP protocol suite for the LINUX
28086 + *             operating system.  INET is implemented using the  BSD Socket
28087 + *             interface as the means of communication with the user level.
28088 + *
28089 + *             IP/TCP/UDP checksumming routines
28090 + *
28091 + * Authors:    Jorge Cwik, <jorge@laser.satlink.net>
28092 + *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
28093 + *             Tom May, <ftom@netcom.com>
28094 + *             Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
28095 + *             Lots of code moved from tcp.c and ip.c; see those files
28096 + *             for more names.
28097 + *
28098 + * 03/02/96    Jes Sorensen, Andreas Schwab, Roman Hodek:
28099 + *             Fixed some nasty bugs, causing some horrible crashes.
28100 + *             A: At some points, the sum (%0) was used as
28101 + *             length-counter instead of the length counter
28102 + *             (%1). Thanks to Roman Hodek for pointing this out.
28103 + *             B: GCC seems to mess up if one uses too many
28104 + *             data-registers to hold input values and one tries to
28105 + *             specify d0 and d1 as scratch registers. Letting gcc choose these
28106 + *             registers itself solves the problem.
28107 + *
28108 + *             This program is free software; you can redistribute it and/or
28109 + *             modify it under the terms of the GNU General Public License
28110 + *             as published by the Free Software Foundation; either version
28111 + *             2 of the License, or (at your option) any later version.
28112 + */
28113 +
28114 +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
28115 +   of the assembly has to go. */
28116 +
28117 +#include <linux/module.h>
28118 +#include <net/checksum.h>
28119 +
28120 +static unsigned long do_csum(const unsigned char * buff, int len)
28121 +{
28122 +       int count;
28123 +       unsigned long result = 0;
28124 +
28125 +       /*
28126 +        * The following optimized assembly code cannot handle data length less than 7 bytes!
28127 +        */
28128 +       if (likely(len >= 7)) {
28129 +               len -= (4 - (int)buff) & 3;
28130 +               count = len >> 2;
28131 +               asm (
28132 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28133 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28134 +
28135 +               "       bfextu          d14, %0, #2             \n\t"   // test 2 LSB of buff
28136 +               "       jmpne.w.f       100f                    \n\t"
28137 +               "       add.4           %1, #0, %1              \n\t"   // clear C
28138 +               "       moveai          a3, #%%hi(1f)           \n\t"   // table jump
28139 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28140 +               "       lea.4           a3, (a3,d15)            \n\t"
28141 +               "       calli           a3, 0(a3)               \n\t"
28142 +
28143 +               "100:   sub.4           %0, %0, d14             \n\t"
28144 +               "       sub.4           d14, #4, d14            \n\t"
28145 +               "       lsl.4           d14, d14, #3            \n\t"
28146 +               "       add.4           %1, #0, %1              \n\t"   // clear C
28147 +               "       moveai          a3, #%%hi(1f)           \n\t"   // table jump
28148 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28149 +               "       lea.4           a3, (a3,d15)            \n\t"
28150 +               "       bfextu          %1, (%0)4++, d14        \n\t"   // read first partial word
28151 +               "       calli           a3, 0(a3)               \n\t"
28152 +#if 1
28153 +               "200:   lsl.4           %3, %3, #3              \n\t"
28154 +               "       bfrvrs          d15, (%0), #0           \n\t"   // read last word (partial)
28155 +               "       bfextu          d15, d15, %3            \n\t"
28156 +               "       bfrvrs          d15, d15, #0            \n\t"
28157 +               "       add.4           %1, d15, %1             \n\t"
28158 +               "       addc            %1, #0, %1              \n\t"   // sample C again
28159 +               "       jmpt.w.t        2f                      \n\t"
28160 +#else
28161 +               "200:   move.1          d15, 0(%0)              \n\t"
28162 +               "       lsl.4           d15, d15, #8            \n\t"
28163 +               "       add.4           %1, d15, %1             \n\t"
28164 +               "       addc            %1, #0, %1              \n\t"   // sample C again
28165 +               "       add.4           %3, #-1, %3             \n\t"
28166 +               "       jmpeq.w.t       2f                      \n\t"
28167 +
28168 +               "       move.1          d15, 1(%0)              \n\t"
28169 +               "       add.4           %1, d15, %1             \n\t"
28170 +               "       addc            %1, #0, %1              \n\t"   // sample C again
28171 +               "       add.4           %3, #-1, %3             \n\t"
28172 +               "       jmpeq.w.t       2f                      \n\t"
28173 +
28174 +               "       move.1          d15, 2(%0)              \n\t"
28175 +               "       lsl.4           d15, d15, #8            \n\t"
28176 +               "       add.4           %1, d15, %1             \n\t"
28177 +               "       addc            %1, #0, %1              \n\t"   // sample C again
28178 +               "       jmpt.w.t        2f                      \n\t"
28179 +#endif
28180 +#if defined(IP7000) || defined(IP7000_REV2)
28181 +               "300:   swapb.2         %1, %1                  \n\t"
28182 +#else
28183 +               "300:   shmrg.2         %1, %1, %1              \n\t"
28184 +               "       lsr.4           %1, %1, #8              \n\t"
28185 +               "       bfextu          %1, %1, #16             \n\t"
28186 +#endif
28187 +               "       jmpt.w.t        3f                      \n\t"
28188 +
28189 +               "1:     add.4           %1, (%0)4++, %1         \n\t"   // first add without C
28190 +               "       .rept           31                      \n\t"
28191 +               "       addc            %1, (%0)4++, %1         \n\t"
28192 +               "       .endr                                   \n\t"
28193 +               "       addc            %1, #0, %1              \n\t"   // sample C again
28194 +               "       add.4           %2, #-32, %2            \n\t"
28195 +               "       jmpgt.w.t       1b                      \n\t"
28196 +
28197 +               "       and.4           %3, #3, %3              \n\t"   // check n
28198 +               "       jmpne.w.f       200b                    \n\t"
28199 +
28200 +               "2:     .rept           2                       \n\t"
28201 +               "       lsr.4           d15, %1, #16            \n\t"
28202 +               "       bfextu          %1, %1, #16             \n\t"
28203 +               "       add.4           %1, d15, %1             \n\t"
28204 +               "       .endr                                   \n\t"
28205 +               "       btst            d14, #3                 \n\t"   // start from odd address (<< 3)?
28206 +               "       jmpne.w.f       300b                    \n\t"
28207 +               "3:                                             \n\t"
28208 +
28209 +                       : "+a"(buff), "+d"(result), "+d"(count), "+d"(len)
28210 +                       :
28211 +                       : "d15", "d14", "a3", "cc"
28212 +               );
28213 +
28214 +               return result;
28215 +       }
28216 +
28217 +       /*
28218 +        * handle a few bytes and fold result into 16-bit
28219 +        */
28220 +       while (len-- > 0) {
28221 +               result += (*buff++ << 8);
28222 +               if (len) {
28223 +                       result += *buff++;
28224 +                       len--;
28225 +               }
28226 +       }
28227 +       asm (
28228 +       "       .rept           2                       \n\t"
28229 +       "       lsr.4           d15, %0, #16            \n\t"
28230 +       "       bfextu          %0, %0, #16             \n\t"
28231 +       "       add.4           %0, d15, %0             \n\t"
28232 +       "       .endr                                   \n\t"
28233 +               : "+d" (result)
28234 +               :
28235 +               : "d15", "cc"
28236 +       );
28237 +
28238 +       return result;
28239 +}
28240 +
28241 +/*
28242 + *     This is a version of ip_compute_csum() optimized for IP headers,
28243 + *     which always checksum on 4 octet boundaries.
28244 + */
28245 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
28246 +{
28247 +       return (__force __sum16)~do_csum(iph,ihl*4);
28248 +}
28249 +
28250 +/*
28251 + * computes the checksum of a memory block at buff, length len,
28252 + * and adds in "sum" (32-bit)
28253 + *
28254 + * returns a 32-bit number suitable for feeding into itself
28255 + * or csum_tcpudp_magic
28256 + *
28257 + * this function must be called with even lengths, except
28258 + * for the last fragment, which may be odd
28259 + *
28260 + * it's best to have buff aligned on a 32-bit boundary
28261 + */
28262 +__wsum csum_partial(const void *buff, int len, __wsum sum)
28263 +{
28264 +       unsigned int result = do_csum(buff, len);
28265 +
28266 +       /* add in old sum, and carry.. */
28267 +       result += (__force u32)sum;
28268 +       if ((__force u32)sum > result)
28269 +               result += 1;
28270 +       return (__force __wsum)result;
28271 +}
28272 +
28273 +EXPORT_SYMBOL(csum_partial);
28274 +
28275 +/*
28276 + * this routine is used for miscellaneous IP-like checksums, mainly
28277 + * in icmp.c
28278 + */
28279 +__sum16 ip_compute_csum(const void *buff, int len)
28280 +{
28281 +       return (__force __sum16)~do_csum(buff,len);
28282 +}
28283 +
28284 +/*
28285 + * copy from fs while checksumming, otherwise like csum_partial
28286 + */
28287 +
28288 +__wsum
28289 +csum_partial_copy_from_user(const void __user *src, void *dst,
28290 +                           int len, __wsum sum, int *csum_err)
28291 +{
28292 +       if (csum_err) *csum_err = 0;
28293 +       memcpy(dst, (__force const void *)src, len);
28294 +       return csum_partial(dst, len, sum);
28295 +}
28296 +
28297 +/*
28298 + * copy from ds while checksumming, otherwise like csum_partial
28299 + */
28300 +
28301 +__wsum
28302 +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
28303 +{
28304 +       memcpy(dst, src, len);
28305 +       return csum_partial(dst, len, sum);
28306 +}
28307 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/delay.c linux-2.6.30.10-ubi/arch/ubicom32/lib/delay.c
28308 --- linux-2.6.30.10/arch/ubicom32/lib/delay.c   1970-01-01 02:00:00.000000000 +0200
28309 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/delay.c       2009-12-11 11:45:11.000000000 +0200
28310 @@ -0,0 +1,49 @@
28311 +/*
28312 + * arch/ubicom32/lib/delay.c
28313 + *   Ubicom32 implementation of udelay()
28314 + *
28315 + * (C) Copyright 2009, Ubicom, Inc.
28316 + *
28317 + * This file is part of the Ubicom32 Linux Kernel Port.
28318 + *
28319 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28320 + * it and/or modify it under the terms of the GNU General Public License
28321 + * as published by the Free Software Foundation, either version 2 of the
28322 + * License, or (at your option) any later version.
28323 + *
28324 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28325 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28326 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28327 + * the GNU General Public License for more details.
28328 + *
28329 + * You should have received a copy of the GNU General Public License
28330 + * along with the Ubicom32 Linux Kernel Port.  If not,
28331 + * see <http://www.gnu.org/licenses/>.
28332 + *
28333 + * Ubicom32 implementation derived from (with many thanks):
28334 + *   arch/m68knommu
28335 + *   arch/blackfin
28336 + *   arch/parisc
28337 + */
28338 +
28339 +#include <linux/module.h>
28340 +#include <asm/param.h>
28341 +#include <asm/delay.h>
28342 +#include <asm/ip5000.h>
28343 +
28344 +/*
28345 + * read_current_timer()
28346 + *     Return the current value of sysval.
28347 + */
28348 +int __devinit read_current_timer(unsigned long *timer_val)
28349 +{
28350 +       *timer_val = (long)(UBICOM32_IO_TIMER->sysval);
28351 +       return 0;
28352 +}
28353 +
28354 +
28355 +void udelay(unsigned long usecs)
28356 +{
28357 +       _udelay(usecs);
28358 +}
28359 +EXPORT_SYMBOL(udelay);
28360 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/Makefile linux-2.6.30.10-ubi/arch/ubicom32/lib/Makefile
28361 --- linux-2.6.30.10/arch/ubicom32/lib/Makefile  1970-01-01 02:00:00.000000000 +0200
28362 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/Makefile      2009-12-11 11:45:11.000000000 +0200
28363 @@ -0,0 +1,32 @@
28364 +#
28365 +# arch/ubicom32/lib/Makefile
28366 +#      <TODO: Replace with short file description>
28367 +#
28368 +# (C) Copyright 2009, Ubicom, Inc.
28369 +#
28370 +# This file is part of the Ubicom32 Linux Kernel Port.
28371 +#
28372 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
28373 +# it and/or modify it under the terms of the GNU General Public License
28374 +# as published by the Free Software Foundation, either version 2 of the
28375 +# License, or (at your option) any later version.
28376 +#
28377 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
28378 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
28379 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28380 +# the GNU General Public License for more details.
28381 +#
28382 +# You should have received a copy of the GNU General Public License
28383 +# along with the Ubicom32 Linux Kernel Port.  If not,
28384 +# see <http://www.gnu.org/licenses/>.
28385 +#
28386 +# Ubicom32 implementation derived from (with many thanks):
28387 +#   arch/m68knommu
28388 +#   arch/blackfin
28389 +#   arch/parisc
28390 +#
28391 +#
28392 +# Makefile for m68knommu specific library files..
28393 +#
28394 +
28395 +lib-y  := checksum.o delay.o mem_ubicom32.o
28396 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/mem_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/lib/mem_ubicom32.c
28397 --- linux-2.6.30.10/arch/ubicom32/lib/mem_ubicom32.c    1970-01-01 02:00:00.000000000 +0200
28398 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/mem_ubicom32.c        2009-12-11 11:45:11.000000000 +0200
28399 @@ -0,0 +1,343 @@
28400 +/*
28401 + * arch/ubicom32/lib/mem_ubicom32.c
28402 + *   String functions.
28403 + *
28404 + * (C) Copyright 2009, Ubicom, Inc.
28405 + *
28406 + * This file is part of the Ubicom32 Linux Kernel Port.
28407 + *
28408 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28409 + * it and/or modify it under the terms of the GNU General Public License
28410 + * as published by the Free Software Foundation, either version 2 of the
28411 + * License, or (at your option) any later version.
28412 + *
28413 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28414 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28415 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28416 + * the GNU General Public License for more details.
28417 + *
28418 + * You should have received a copy of the GNU General Public License
28419 + * along with the Ubicom32 Linux Kernel Port.  If not,
28420 + * see <http://www.gnu.org/licenses/>.
28421 + *
28422 + * Ubicom32 implementation derived from (with many thanks):
28423 + *   arch/m68knommu
28424 + *   arch/blackfin
28425 + *   arch/parisc
28426 + */
28427 +
28428 +#include <linux/module.h>
28429 +#include <linux/types.h>
28430 +#include <linux/compiler.h>
28431 +
28432 +#define LIKELY likely
28433 +#define UNLIKELY unlikely
28434 +
28435 +typedef u32_t addr_t;
28436 +
28437 +/*
28438 + * memcpy()
28439 + */
28440 +void *memcpy(void *dest, const void *src, size_t n)
28441 +{
28442 +       void *dest_ret = dest;
28443 +
28444 +       if (LIKELY((((addr_t)dest ^ (addr_t)src) & 3) == 0) && LIKELY(n > 6)) {
28445 +               size_t m;
28446 +               n -= (4 - (addr_t)dest) & 0x03;
28447 +               m = n >> 2;
28448 +               asm volatile (
28449 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28450 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28451 +               "       moveai          a3, #%%hi(1f)           \n\t"
28452 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28453 +               "       lea.4           a3, (a3,d15)            \n\t"
28454 +
28455 +               "       bfextu          d15, %0, #2             \n\t"   // d15 = (dest & 3)
28456 +               "       jmpne.w.f       100f                    \n\t"
28457 +               "       calli           a3, 0(a3)               \n\t"   // 4-byte alignment
28458 +
28459 +               "100:   cmpi            d15, #2                 \n\t"
28460 +               "       jmpne.s.f       101f                    \n\t"
28461 +               "       move.2          (%0)2++, (%1)2++        \n\t"
28462 +               "       calli           a3, 0(a3)               \n\t"   // 2-byte alignment
28463 +
28464 +               "101:   move.1          (%0)1++, (%1)1++        \n\t"
28465 +               "       jmpgt.s.f       102f                    \n\t"   // 3-byte alignment
28466 +               "       move.2          (%0)2++, (%1)2++        \n\t"   // 1-byte alignment
28467 +               "102:   calli           a3, 0(a3)               \n\t"
28468 +
28469 +               "200:   cmpi            %3, #2                  \n\t"
28470 +               "       jmplt.s.f       201f                    \n\t"
28471 +               "       move.2          (%0)2++, (%1)2++        \n\t"
28472 +               "       jmpeq.s.t       2f                      \n\t"
28473 +               "201:   move.1          (%0)1++, (%1)1++        \n\t"
28474 +               "       jmpt.w.t        2f                      \n\t"
28475 +
28476 +               "1:     .rept           25                      \n\t"
28477 +               "       movea           (%0)4++, (%1)4++        \n\t"
28478 +               "       .endr                                   \n\t"
28479 +               "       .rept           7                       \n\t"
28480 +               "       move.4          (%0)4++, (%1)4++        \n\t"
28481 +               "       .endr                                   \n\t"
28482 +               "       add.4           %2, #-32, %2            \n\t"
28483 +               "       jmpgt.w.f       1b                      \n\t"
28484 +
28485 +               "       and.4           %3, #3, %3              \n\t"   // check n
28486 +               "       jmpne.w.f       200b                    \n\t"
28487 +               "2:                                             \n\t"
28488 +                       : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28489 +                       :
28490 +                       : "d15", "a3", "memory", "cc"
28491 +               );
28492 +
28493 +               return dest_ret;
28494 +       }
28495 +
28496 +       if (LIKELY((((addr_t)dest ^ (addr_t)src) & 1) == 0) && LIKELY(n > 2)) {
28497 +               size_t m;
28498 +               n -= (addr_t)dest & 0x01;
28499 +               m = n >> 1;
28500 +               asm volatile (
28501 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28502 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28503 +               "       moveai          a3, #%%hi(1f)           \n\t"
28504 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28505 +               "       lea.4           a3, (a3,d15)            \n\t"
28506 +
28507 +               "       btst            %0, #0                  \n\t"   // check bit 0
28508 +               "       jmpne.w.f       100f                    \n\t"
28509 +               "       calli           a3, 0(a3)               \n\t"   // 4-byte alignment
28510 +
28511 +               "100:   move.1          (%0)1++, (%1)1++        \n\t"
28512 +               "       calli           a3, 0(a3)               \n\t"
28513 +
28514 +               "200:   move.1          (%0)1++, (%1)1++        \n\t"
28515 +               "       jmpt.w.t        2f                      \n\t"
28516 +
28517 +               "1:     .rept           32                      \n\t"
28518 +               "       move.2          (%0)2++, (%1)2++        \n\t"
28519 +               "       .endr                                   \n\t"
28520 +               "       add.4           %2, #-32, %2            \n\t"
28521 +               "       jmpgt.w.f       1b                      \n\t"
28522 +
28523 +               "       and.4           %3, #1, %3              \n\t"   // check n
28524 +               "       jmpne.w.f       200b                    \n\t"
28525 +               "2:                                             \n\t"
28526 +
28527 +                       : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28528 +                       :
28529 +                       : "d15", "a3", "memory", "cc"
28530 +               );
28531 +
28532 +               return dest_ret;
28533 +       }
28534 +
28535 +       asm volatile (
28536 +       "       sub.4           d15, #0, %2             \n\t"
28537 +       "       jmpeq.w.f       2f                      \n\t"
28538 +       "       and.4           d15, #(16-1), d15       \n\t"   // d15 = (-n) & (16 - 1)
28539 +       "       moveai          a3, #%%hi(1f)           \n\t"
28540 +       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28541 +       "       lea.4           a3, (a3,d15)            \n\t"
28542 +       "       calli           a3, 0(a3)               \n\t"
28543 +
28544 +       "1:     .rept           16                      \n\t"
28545 +       "       move.1          (%0)1++, (%1)1++        \n\t"
28546 +       "       .endr                                   \n\t"
28547 +       "       add.4           %2, #-16, %2            \n\t"
28548 +       "       jmpgt.w.f       1b                      \n\t"
28549 +       "2:                                             \n\t"
28550 +
28551 +               : "+a" (dest), "+a" (src), "+d" (n)
28552 +               :
28553 +               : "d15", "a3", "memory", "cc"
28554 +       );
28555 +
28556 +       return dest_ret;
28557 +}
28558 +
28559 +/*
28560 + * memset()
28561 + */
28562 +void *memset(void *s, int c, size_t n)
28563 +{
28564 +       void *s_ret = s;
28565 +
28566 +       if (LIKELY(n > 6)) {
28567 +               size_t m;
28568 +               n -= (4 - (addr_t)s) & 0x03;
28569 +               m = n >> 2;
28570 +               asm volatile (
28571 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28572 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28573 +               "       shmrg.1         %1, %1, %1              \n\t"
28574 +               "       shmrg.2         %1, %1, %1              \n\t"   // %1 = (c<<24)|(c<<16)|(c<<8)|c
28575 +               "       moveai          a3, #%%hi(1f)           \n\t"
28576 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28577 +               "       lea.4           a3, (a3,d15)            \n\t"
28578 +
28579 +               "       bfextu          d15, %0, #2             \n\t"   // d15 = (s & 3)
28580 +               "       jmpne.w.f       100f                    \n\t"
28581 +               "       calli           a3, 0(a3)               \n\t"   // 4-byte alignment
28582 +
28583 +               "100:   cmpi            d15, #2                 \n\t"
28584 +               "       jmpne.s.f       101f                    \n\t"
28585 +               "       move.2          (%0)2++, %1             \n\t"
28586 +               "       calli           a3, 0(a3)               \n\t"   // 2-byte alignment
28587 +
28588 +               "101:   move.1          (%0)1++, %1             \n\t"
28589 +               "       jmpgt.s.f       102f                    \n\t"   // 3-byte alignment
28590 +               "       move.2          (%0)2++, %1             \n\t"   // 1-byte alignment
28591 +               "102:   calli           a3, 0(a3)               \n\t"
28592 +
28593 +               "200:   cmpi            %3, #2                  \n\t"
28594 +               "       jmplt.s.f       201f                    \n\t"
28595 +               "       move.2          (%0)2++, %1             \n\t"
28596 +               "       jmpeq.s.t       2f                      \n\t"
28597 +               "201:   move.1          (%0)1++, %1             \n\t"
28598 +               "       jmpt.w.t        2f                      \n\t"
28599 +
28600 +               "1:     .rept           25                      \n\t"
28601 +               "       movea           (%0)4++, %1             \n\t"
28602 +               "       .endr                                   \n\t"
28603 +               "       .rept           7                       \n\t"
28604 +               "       move.4          (%0)4++, %1             \n\t"
28605 +               "       .endr                                   \n\t"
28606 +               "       add.4           %2, #-32, %2            \n\t"
28607 +               "       jmpgt.w.f       1b                      \n\t"
28608 +
28609 +               "       and.4           %3, #3, %3              \n\t"   // test bit 1 of n
28610 +               "       jmpne.w.f       200b                    \n\t"
28611 +               "2:                                             \n\t"
28612 +
28613 +                       : "+a" (s), "+d" (c), "+d" (m), "+d" (n)
28614 +                       :
28615 +                       : "d15", "a3", "memory", "cc"
28616 +               );
28617 +
28618 +               return s_ret;
28619 +       }
28620 +
28621 +       asm volatile (
28622 +       "       sub.4           d15, #0, %2             \n\t"
28623 +       "       jmpeq.w.f       2f                      \n\t"
28624 +       "       and.4           d15, #(8-1), d15        \n\t"   // d15 = (-%2) & (16 - 1)
28625 +       "       moveai          a3, #%%hi(1f)           \n\t"
28626 +       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28627 +       "       lea.4           a3, (a3,d15)            \n\t"
28628 +       "       calli           a3, 0(a3)               \n\t"
28629 +
28630 +       "1:     .rept           8                       \n\t"
28631 +       "       move.1          (%0)1++, %1             \n\t"
28632 +       "       .endr                                   \n\t"
28633 +       "2:                                             \n\t"
28634 +
28635 +               : "+a" (s), "+d" (c), "+d" (n)
28636 +               :
28637 +               : "d15", "a3", "memory", "cc"
28638 +       );
28639 +
28640 +       return s_ret;
28641 +}
28642 +
28643 +void *memmove(void *dest, const void *src, size_t n)
28644 +{
28645 +       char *tmp;
28646 +       const char *s;
28647 +
28648 +       if (n == 0)
28649 +               return dest;
28650 +
28651 +       tmp = dest;
28652 +       s = src;
28653 +
28654 +       /*
28655 +        * Will perform 16-bit move if possible
28656 +        */
28657 +       if (likely((((u32)dest | (u32)src | n) & 1) == 0)) {
28658 +               if (dest <= src) {
28659 +                       asm volatile (
28660 +                       "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28661 +                       "       and.4           d15, #(32-2), d15       \n\t"   // d15 = (- count) & (32 - 2)
28662 +                       "       moveai          a3, #%%hi(1f)           \n\t"
28663 +                       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28664 +                       "       lea.2           a3, (a3,d15)            \n\t"
28665 +                       "       calli           a3, 0(a3)               \n\t"
28666 +
28667 +                       "1:     .rept           16                      \n\t"
28668 +                       "       move.2          (%0)2++, (%1)2++        \n\t"
28669 +                       "       .endr                                   \n\t"
28670 +                       "       add.4           %2, #-32, %2            \n\t"
28671 +                       "       jmpgt.w.f       1b                      \n\t"
28672 +
28673 +                       : "+a" (tmp), "+a" (s), "+d" (n)
28674 +                       :
28675 +                       : "d15", "a3", "memory", "cc"
28676 +                       );
28677 +               } else {
28678 +                       tmp += n;
28679 +                       s += n;
28680 +                       asm volatile (
28681 +                       "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28682 +                       "       and.4           d15, #(32-2), d15       \n\t"   // d15 = (- count) & (32 - 2)
28683 +                       "       moveai          a3, #%%hi(1f)           \n\t"
28684 +                       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28685 +                       "       lea.2           a3, (a3,d15)            \n\t"
28686 +                       "       calli           a3, 0(a3)               \n\t"
28687 +
28688 +                       "1:     .rept           16                      \n\t"
28689 +                       "       move.2          -2(%0)++, -2(%1)++      \n\t"
28690 +                       "       .endr                                   \n\t"
28691 +                       "       add.4           %2, #-32, %2            \n\t"
28692 +                       "       jmpgt.w.f       1b                      \n\t"
28693 +
28694 +                       : "+a" (tmp), "+a" (s), "+d" (n)
28695 +                       :
28696 +                       : "d15", "a3", "memory", "cc"
28697 +                       );
28698 +               }
28699 +               return dest;
28700 +       }
28701 +
28702 +       if (dest <= src) {
28703 +               asm volatile (
28704 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28705 +               "       and.4           d15, #(16-1), d15       \n\t"   // d15 = (- count) & (16 - 1)
28706 +               "       moveai          a3, #%%hi(1f)           \n\t"
28707 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28708 +               "       lea.4           a3, (a3,d15)            \n\t"
28709 +               "       calli           a3, 0(a3)               \n\t"
28710 +
28711 +               "1:     .rept           16                      \n\t"
28712 +               "       move.1          (%0)1++, (%1)1++        \n\t"
28713 +               "       .endr                                   \n\t"
28714 +               "       add.4           %2, #-16, %2            \n\t"
28715 +               "       jmpgt.w.f       1b                      \n\t"
28716 +               : "+a" (tmp), "+a" (s), "+d" (n)
28717 +               :
28718 +               : "d15", "a3", "memory", "cc"
28719 +               );
28720 +       } else {
28721 +               tmp += n;
28722 +               s += n;
28723 +               asm volatile (
28724 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28725 +               "       and.4           d15, #(16-1), d15       \n\t"   // d15 = (- count) & (16 - 1)
28726 +               "       moveai          a3, #%%hi(1f)           \n\t"
28727 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28728 +               "       lea.4           a3, (a3,d15)            \n\t"
28729 +               "       calli           a3, 0(a3)               \n\t"
28730 +
28731 +               "1:     .rept           16                      \n\t"
28732 +               "       move.1          -1(%0)++, -1(%1)++      \n\t"
28733 +               "       .endr                                   \n\t"
28734 +               "       add.4           %2, #-16, %2            \n\t"
28735 +               "       jmpgt.w.f       1b                      \n\t"
28736 +               : "+a" (tmp), "+a" (s), "+d" (n)
28737 +               :
28738 +               : "d15", "a3", "memory", "cc"
28739 +               );
28740 +       }
28741 +       return dest;
28742 +}
28743 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/audio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/audio.c
28744 --- linux-2.6.30.10/arch/ubicom32/mach-common/audio.c   1970-01-01 02:00:00.000000000 +0200
28745 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/audio.c       2009-12-11 11:45:11.000000000 +0200
28746 @@ -0,0 +1,134 @@
28747 +/*
28748 + * arch/ubicom32/mach-common/audio.c
28749 + *   Generic initialization for Ubicom32 Audio
28750 + *
28751 + * (C) Copyright 2009, Ubicom, Inc.
28752 + *
28753 + * This file is part of the Ubicom32 Linux Kernel Port.
28754 + *
28755 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28756 + * it and/or modify it under the terms of the GNU General Public License
28757 + * as published by the Free Software Foundation, either version 2 of the
28758 + * License, or (at your option) any later version.
28759 + *
28760 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28761 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28762 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28763 + * the GNU General Public License for more details.
28764 + *
28765 + * You should have received a copy of the GNU General Public License
28766 + * along with the Ubicom32 Linux Kernel Port.  If not,
28767 + * see <http://www.gnu.org/licenses/>.
28768 + */
28769 +
28770 +#include <linux/platform_device.h>
28771 +#include <linux/types.h>
28772 +
28773 +#include <asm/devtree.h>
28774 +#include <asm/audio.h>
28775 +#include <asm/ubi32-pcm.h>
28776 +
28777 +/*
28778 + * The number of audio devices currently allocated, used for .id
28779 + */
28780 +static int __initdata audio_device_count;
28781 +
28782 +/*
28783 + * The maximum number of resources (cards) that the audio will have.
28784 + * Currently 3, a register space, and up to 2 interrupts.
28785 + */
28786 +#define AUDIO_MAX_RESOURCES    3
28787 +
28788 +/*
28789 + * audio_device_alloc
28790 + *     Checks the device tree and allocates a platform_device if found
28791 + */
28792 +struct platform_device * __init audio_device_alloc(const char *driver_name,
28793 +               const char *node_name, const char *inst_name, int priv_bytes)
28794 +{
28795 +       struct platform_device *pdev;
28796 +       struct resource *res;
28797 +       struct audio_node *audio_node;
28798 +       struct ubi32pcm_platform_data *pdata;
28799 +       struct audio_dev_regs *adr;
28800 +       int idx;
28801 +
28802 +       /*
28803 +        * Check the device tree for the audio node
28804 +        */
28805 +       audio_node = (struct audio_node *)devtree_find_node(node_name);
28806 +       if (!audio_node) {
28807 +               printk(KERN_WARNING "audio device '%s' not found\n", node_name);
28808 +               return NULL;
28809 +       }
28810 +
28811 +       if (audio_node->version != AUDIONODE_VERSION) {
28812 +               printk(KERN_WARNING "audio node not compatible\n");
28813 +               return NULL;
28814 +       }
28815 +
28816 +       /*
28817 +        * Find the instance in this node
28818 +        */
28819 +       adr = audio_node->regs->adr;
28820 +       for (idx = 0; idx < audio_node->regs->max_devs; idx++) {
28821 +               if ((adr->version == AUDIO_DEV_REGS_VERSION) &&
28822 +                  (strcmp(adr->name, inst_name) == 0)) {
28823 +                       break;
28824 +               }
28825 +               adr++;
28826 +       }
28827 +       if (idx == audio_node->regs->max_devs) {
28828 +               printk(KERN_WARNING "audio inst '%s' not found in device '%s'\n", inst_name, node_name);
28829 +               return NULL;
28830 +       }
28831 +
28832 +       /*
28833 +        * Dynamically create the platform_device structure and resources
28834 +        */
28835 +       pdev = kzalloc(sizeof(struct platform_device) +
28836 +                      sizeof(struct ubi32pcm_platform_data) +
28837 +                      priv_bytes , GFP_KERNEL);
28838 +       if (!pdev) {
28839 +               printk(KERN_WARNING "audio could not alloc pdev\n");
28840 +               return NULL;
28841 +       }
28842 +
28843 +       res = kzalloc(sizeof(struct resource) * AUDIO_MAX_RESOURCES,
28844 +                       GFP_KERNEL);
28845 +       if (!res) {
28846 +               kfree(pdev);
28847 +               printk(KERN_WARNING "audio could not alloc res\n");
28848 +               return NULL;
28849 +       }
28850 +
28851 +       pdev->name = driver_name;
28852 +       pdev->id = audio_device_count++;
28853 +       pdev->resource = res;
28854 +
28855 +       /*
28856 +        * Fill in the resources and platform data from devtree information
28857 +        */
28858 +       res[0].start = (u32_t)(audio_node->regs);
28859 +       res[0].end = (u32_t)(audio_node->regs);
28860 +       res[0].flags = IORESOURCE_MEM;
28861 +       res[1 + AUDIO_TX_IRQ_RESOURCE].start = audio_node->dn.sendirq;
28862 +       res[1 + AUDIO_TX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28863 +       res[1 + AUDIO_RX_IRQ_RESOURCE].start = audio_node->dn.recvirq;
28864 +       res[1 + AUDIO_RX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28865 +       pdev->num_resources = 3;
28866 +
28867 +       printk(KERN_INFO "Audio.%d '%s':'%s' found irq=%d/%d.%d regs=%p pdev=%p/%p\n",
28868 +               pdev->id, node_name, inst_name, audio_node->dn.sendirq,
28869 +               audio_node->dn.recvirq, idx, audio_node->regs, pdev, res);
28870 +       pdata = (struct ubi32pcm_platform_data *)(pdev + 1);
28871 +       pdev->dev.platform_data = pdata;
28872 +       pdata->node_name = node_name;
28873 +       pdata->inst_name = inst_name;
28874 +       pdata->inst_num = idx;
28875 +       if (priv_bytes) {
28876 +               pdata->priv_data = pdata + 1;
28877 +       }
28878 +
28879 +       return pdev;
28880 +}
28881 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/board.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/board.c
28882 --- linux-2.6.30.10/arch/ubicom32/mach-common/board.c   1970-01-01 02:00:00.000000000 +0200
28883 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/board.c       2009-12-11 11:45:11.000000000 +0200
28884 @@ -0,0 +1,63 @@
28885 +/*
28886 + * arch/ubicom32/mach-common/board.c
28887 + *   Board init and support code.
28888 + *
28889 + * (C) Copyright 2009, Ubicom, Inc.
28890 + *
28891 + * This file is part of the Ubicom32 Linux Kernel Port.
28892 + *
28893 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28894 + * it and/or modify it under the terms of the GNU General Public License
28895 + * as published by the Free Software Foundation, either version 2 of the
28896 + * License, or (at your option) any later version.
28897 + *
28898 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28899 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28900 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28901 + * the GNU General Public License for more details.
28902 + *
28903 + * You should have received a copy of the GNU General Public License
28904 + * along with the Ubicom32 Linux Kernel Port.  If not,
28905 + * see <http://www.gnu.org/licenses/>.
28906 + *
28907 + * Ubicom32 implementation derived from (with many thanks):
28908 + *   arch/m68knommu
28909 + *   arch/blackfin
28910 + *   arch/parisc
28911 + */
28912 +#include <linux/module.h>
28913 +#include <linux/types.h>
28914 +#include <linux/cpu.h>
28915 +#include <asm/devtree.h>
28916 +
28917 +struct boardnode {
28918 +       struct devtree_node dn;
28919 +       const char *revision;
28920 +};
28921 +
28922 +static const struct boardnode *bn;
28923 +
28924 +/*
28925 + * board_get_revision()
28926 + *     Returns revision string of the board.
28927 + */
28928 +const char *board_get_revision(void)
28929 +{
28930 +       if (!bn) {
28931 +               return "NULL";
28932 +       }
28933 +
28934 +       return bn->revision;
28935 +}
28936 +
28937 +/*
28938 + * board_init
28939 + */
28940 +void __init board_init(void)
28941 +{
28942 +       bn = (struct boardnode *)devtree_find_node("board");
28943 +       if (!bn) {
28944 +               printk(KERN_WARNING "board node not found\n");
28945 +               return;
28946 +       }
28947 +}
28948 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/bootargs.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/bootargs.c
28949 --- linux-2.6.30.10/arch/ubicom32/mach-common/bootargs.c        1970-01-01 02:00:00.000000000 +0200
28950 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/bootargs.c    2009-12-11 11:45:11.000000000 +0200
28951 @@ -0,0 +1,63 @@
28952 +/*
28953 + * arch/ubicom32/mach-common/bootargs.c
28954 + *   Board init and support code.
28955 + *
28956 + * (C) Copyright 2009, Ubicom, Inc.
28957 + *
28958 + * This file is part of the Ubicom32 Linux Kernel Port.
28959 + *
28960 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28961 + * it and/or modify it under the terms of the GNU General Public License
28962 + * as published by the Free Software Foundation, either version 2 of the
28963 + * License, or (at your option) any later version.
28964 + *
28965 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28966 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28967 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28968 + * the GNU General Public License for more details.
28969 + *
28970 + * You should have received a copy of the GNU General Public License
28971 + * along with the Ubicom32 Linux Kernel Port.  If not,
28972 + * see <http://www.gnu.org/licenses/>.
28973 + *
28974 + * Ubicom32 implementation derived from (with many thanks):
28975 + *   arch/m68knommu
28976 + *   arch/blackfin
28977 + *   arch/parisc
28978 + */
28979 +#include <linux/module.h>
28980 +#include <linux/types.h>
28981 +#include <linux/cpu.h>
28982 +#include <asm/devtree.h>
28983 +
28984 +struct bootargsnode {
28985 +       struct devtree_node dn;
28986 +       const char cmdline[512];
28987 +};
28988 +
28989 +static const struct bootargsnode *ban;
28990 +
28991 +/*
28992 + * bootargs_get_cmdline()
28993 + *     Returns kernel boot arguments set by the bootloader.
28994 + */
28995 +const char *bootargs_get_cmdline(void)
28996 +{
28997 +       if (!ban) {
28998 +               return "";
28999 +       }
29000 +
29001 +       return ban->cmdline;
29002 +}
29003 +
29004 +/*
29005 + * bootargs_init
29006 + */
29007 +void __init bootargs_init(void)
29008 +{
29009 +       ban = (struct bootargsnode *)devtree_find_node("bootargs");
29010 +       if (!ban) {
29011 +               printk(KERN_WARNING "bootargs node not found\n");
29012 +               return;
29013 +       }
29014 +}
29015 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/cachectl.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/cachectl.c
29016 --- linux-2.6.30.10/arch/ubicom32/mach-common/cachectl.c        1970-01-01 02:00:00.000000000 +0200
29017 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/cachectl.c    2009-12-11 11:45:11.000000000 +0200
29018 @@ -0,0 +1,136 @@
29019 +/*
29020 + * arch/ubicom32/mach-common/cachectl.c
29021 + *   Architecture cache control support
29022 + *
29023 + * (C) Copyright 2009, Ubicom, Inc.
29024 + *
29025 + * This file is part of the Ubicom32 Linux Kernel Port.
29026 + *
29027 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29028 + * it and/or modify it under the terms of the GNU General Public License
29029 + * as published by the Free Software Foundation, either version 2 of the
29030 + * License, or (at your option) any later version.
29031 + *
29032 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29033 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29034 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29035 + * the GNU General Public License for more details.
29036 + *
29037 + * You should have received a copy of the GNU General Public License
29038 + * along with the Ubicom32 Linux Kernel Port.  If not,
29039 + * see <http://www.gnu.org/licenses/>.
29040 + *
29041 + * Ubicom32 implementation derived from (with many thanks):
29042 + *   arch/m68knommu
29043 + *   arch/blackfin
29044 + *   arch/parisc
29045 + */
29046 +
29047 +#include <linux/types.h>
29048 +#include <linux/module.h>
29049 +#include <asm/cachectl.h>
29050 +
29051 +/*
29052 + * The write queue flush procedure in mem_cache_control needs to make
29053 + * DCACHE_WRITE_QUEUE_LENGTH writes to DDR (not OCM). Here we reserve some
29054 + * memory for this operation.
29055 + * Allocate array of cache lines of least DCACHE_WRITE_QUEUE_LENGTH + 1 words in
29056 + * length rounded up to the nearest cache line.
29057 + */
29058 +#define CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE \
29059 +       ALIGN(sizeof(int) * (DCACHE_WRITE_QUEUE_LENGTH + 1), CACHE_LINE_SIZE)
29060 +
29061 +static char cache_write_queue_flush_area[CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE]
29062 +       __attribute__((aligned(CACHE_LINE_SIZE)));
29063 +
29064 +/*
29065 + * ONE_CCR_ADDR_OP is a helper macro that executes a single CCR operation.
29066 + */
29067 +#define ONE_CCR_ADDR_OP(cc, op_addr, op)                               \
29068 +       do {                                                            \
29069 +               asm volatile (                                          \
29070 +               "       btst    "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)"                         \n\t" \
29071 +               "       jmpne.f .-4                                                             \n\t" \
29072 +               "       move.4  "D(CCR_ADDR)"(%0), %1                                           \n\t" \
29073 +               "       move.1  "D(CCR_CTRL+3)"(%0), %2                                         \n\t" \
29074 +               "       bset    "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)"      \n\t" \
29075 +               "       cycles  2                                                               \n\t" \
29076 +               "       btst    "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_DONE)"                          \n\t" \
29077 +               "       jmpeq.f .-4                                                             \n\t" \
29078 +                       :                                               \
29079 +                       : "a"(cc), "r"(op_addr), "r"(op & 0xff)         \
29080 +                       : "cc"                                          \
29081 +               );                                                      \
29082 +       } while (0)
29083 +
29084 +/*
29085 + * mem_cache_control()
29086 + *     Special cache control operation
29087 + */
29088 +void mem_cache_control(unsigned long cc, unsigned long begin_addr,
29089 +                      unsigned long end_addr, unsigned long op)
29090 +{
29091 +       unsigned long op_addr;
29092 +       int dccr = cc == DCCR_BASE;
29093 +       if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
29094 +               /*
29095 +                * We ensure all previous writes have left the data cache write
29096 +                * queue by sending DCACHE_WRITE_QUEUE_LENGTH writes (to
29097 +                * different words) down the queue.  If this is not done it's
29098 +                * possible that the data we are trying to flush hasn't even
29099 +                * entered the data cache.
29100 +                * The +1 ensure that the final 'flush' is actually a flush.
29101 +                */
29102 +               int *flush_area = (int *)cache_write_queue_flush_area;
29103 +               asm volatile(
29104 +                       "       .rept "D(DCACHE_WRITE_QUEUE_LENGTH + 1)"        \n\t"
29105 +                       "       move.4 (%0)4++, d0                              \n\t"
29106 +                       "       .endr                                           \n\t"
29107 +                       : "+a"(flush_area)
29108 +                       );
29109 +       }
29110 +
29111 +       if (dccr)
29112 +               UBICOM32_LOCK(DCCR_LOCK_BIT);
29113 +       else
29114 +               UBICOM32_LOCK(ICCR_LOCK_BIT);
29115 +
29116 +       /*
29117 +        * Calculate the cache lines we need to operate on that include
29118 +        * begin_addr though end_addr.
29119 +        */
29120 +       begin_addr = begin_addr & ~(CACHE_LINE_SIZE - 1);
29121 +       end_addr = (end_addr + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
29122 +       op_addr = begin_addr;
29123 +
29124 +       do {
29125 +               ONE_CCR_ADDR_OP(cc, op_addr, op);
29126 +               op_addr += CACHE_LINE_SIZE;
29127 +       } while (likely(op_addr < end_addr));
29128 +
29129 +       if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
29130 +               /*
29131 +                * It turns out that when flushing the data cache the last flush
29132 +                * isn't actually complete at this point. This is because there
29133 +                * is another write buffer on the DDR side of the cache that is
29134 +                * arbitrated with the I-Cache.
29135 +                *
29136 +                * The only foolproof method that ensures that the last data
29137 +                * cache flush *actually* completed is to do another flush on a
29138 +                * dirty cache line. This flush will block until the DDR write
29139 +                * buffer is empty.
29140 +                *
29141 +                * Rather than creating a another dirty cache line, we use the
29142 +                * flush_area above as we know that it is dirty from previous
29143 +                * writes.
29144 +                */
29145 +               ONE_CCR_ADDR_OP(cc, cache_write_queue_flush_area, op);
29146 +       }
29147 +
29148 +       if (dccr)
29149 +               UBICOM32_UNLOCK(DCCR_LOCK_BIT);
29150 +       else
29151 +               UBICOM32_UNLOCK(ICCR_LOCK_BIT);
29152 +
29153 +}
29154 +EXPORT_SYMBOL(mem_cache_control);
29155 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/common.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/common.c
29156 --- linux-2.6.30.10/arch/ubicom32/mach-common/common.c  1970-01-01 02:00:00.000000000 +0200
29157 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/common.c      2009-12-11 11:45:11.000000000 +0200
29158 @@ -0,0 +1,64 @@
29159 +/*
29160 + * arch/ubicom32/mach-common/common.c
29161 + *   Common platform support.
29162 + *
29163 + * (C) Copyright 2009, Ubicom, Inc.
29164 + *
29165 + * This file is part of the Ubicom32 Linux Kernel Port.
29166 + *
29167 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29168 + * it and/or modify it under the terms of the GNU General Public License
29169 + * as published by the Free Software Foundation, either version 2 of the
29170 + * License, or (at your option) any later version.
29171 + *
29172 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29173 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29174 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29175 + * the GNU General Public License for more details.
29176 + *
29177 + * You should have received a copy of the GNU General Public License
29178 + * along with the Ubicom32 Linux Kernel Port.  If not,
29179 + * see <http://www.gnu.org/licenses/>.
29180 + *
29181 + * Ubicom32 implementation derived from (with many thanks):
29182 + *   arch/m68knommu
29183 + *   arch/blackfin
29184 + *   arch/parisc
29185 + */
29186 +#include <linux/version.h>
29187 +#include <linux/kernel.h>
29188 +#include <linux/init.h>
29189 +#include <linux/module.h>
29190 +#include <linux/list.h>
29191 +#include <linux/errno.h>
29192 +#include <linux/err.h>
29193 +#include <linux/string.h>
29194 +#include <linux/clk.h>
29195 +#include <linux/mutex.h>
29196 +#include <linux/platform_device.h>
29197 +
29198 +
29199 +/* Minimum CLK support */
29200 +
29201 +struct clk *clk_get(struct device *dev, const char *id)
29202 +{
29203 +       return ERR_PTR(-ENOENT);
29204 +}
29205 +EXPORT_SYMBOL(clk_get);
29206 +
29207 +void clk_put(struct clk *clk)
29208 +{
29209 +}
29210 +EXPORT_SYMBOL(clk_put);
29211 +
29212 +int clk_enable(struct clk *clk)
29213 +{
29214 +       return 0;
29215 +}
29216 +EXPORT_SYMBOL(clk_enable);
29217 +
29218 +
29219 +void clk_disable(struct clk *clk)
29220 +{
29221 +}
29222 +EXPORT_SYMBOL(clk_disable);
29223 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/io.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/io.c
29224 --- linux-2.6.30.10/arch/ubicom32/mach-common/io.c      1970-01-01 02:00:00.000000000 +0200
29225 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/io.c  2009-12-11 11:45:11.000000000 +0200
29226 @@ -0,0 +1,250 @@
29227 +/*
29228 + * arch/ubicom32/mach-common/io.c
29229 + *   PCI I/O memory read/write support functions.
29230 + *
29231 + * (C) Copyright 2009, Ubicom, Inc.
29232 + *
29233 + * This file is part of the Ubicom32 Linux Kernel Port.
29234 + *
29235 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29236 + * it and/or modify it under the terms of the GNU General Public License
29237 + * as published by the Free Software Foundation, either version 2 of the
29238 + * License, or (at your option) any later version.
29239 + *
29240 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29241 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29242 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29243 + * the GNU General Public License for more details.
29244 + *
29245 + * You should have received a copy of the GNU General Public License
29246 + * along with the Ubicom32 Linux Kernel Port.  If not,
29247 + * see <http://www.gnu.org/licenses/>.
29248 + *
29249 + * Ubicom32 implementation derived from (with many thanks):
29250 + *   arch/m68knommu
29251 + *   arch/blackfin
29252 + *   arch/parisc
29253 + */
29254 +#include <linux/module.h>
29255 +#include <linux/kernel.h>
29256 +#include <linux/io.h>
29257 +
29258 +#ifdef CONFIG_PCI
29259 +unsigned char  ioread8(void __iomem *addr)
29260 +{
29261 +       if (IS_PCI_ADDRESS(addr))
29262 +               return ubi32_pci_read_u8(addr);
29263 +       else
29264 +               return (unsigned char)(*(volatile unsigned char *)addr);
29265 +}
29266 +EXPORT_SYMBOL(ioread8);
29267 +
29268 +unsigned short  ioread16(void __iomem *addr)
29269 +{
29270 +       if (IS_PCI_ADDRESS(addr))
29271 +               return ubi32_pci_read_u16(addr);
29272 +       else
29273 +               return (unsigned short)(*(volatile unsigned short *)addr);
29274 +}
29275 +EXPORT_SYMBOL(ioread16);
29276 +
29277 +unsigned int  ioread32(void __iomem *addr)
29278 +{
29279 +       if (IS_PCI_ADDRESS(addr))
29280 +               return ubi32_pci_read_u32(addr);
29281 +       else
29282 +               return (unsigned int)(*(volatile unsigned int *)addr);
29283 +}
29284 +EXPORT_SYMBOL(ioread32);
29285 +
29286 +void iowrite32(unsigned int val, void __iomem *addr)
29287 +{
29288 +       if (IS_PCI_ADDRESS(addr))
29289 +               ubi32_pci_write_u32(val, addr);
29290 +       else
29291 +               *(volatile unsigned int *)addr = val;
29292 +}
29293 +EXPORT_SYMBOL(iowrite32);
29294 +
29295 +void iowrite16(unsigned short val, void __iomem *addr)
29296 +{
29297 +       if (IS_PCI_ADDRESS(addr))
29298 +               ubi32_pci_write_u16(val, addr);
29299 +       else
29300 +               *(volatile unsigned short *)addr = val;
29301 +}
29302 +EXPORT_SYMBOL(iowrite16);
29303 +
29304 +void iowrite8(unsigned char val, void __iomem *addr)
29305 +{
29306 +       if (IS_PCI_ADDRESS(addr))
29307 +               ubi32_pci_write_u8(val, addr);
29308 +       else
29309 +               *(volatile unsigned char *)addr = val;
29310 +}
29311 +EXPORT_SYMBOL(iowrite8);
29312 +
29313 +void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len)
29314 +{
29315 +       if (IS_PCI_ADDRESS(from)) {
29316 +               if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29317 +                       while ((int)len >= 4) {
29318 +                               *(u32_t *)to = ubi32_pci_read_u32(from);
29319 +                               to += 4;
29320 +                               from += 4;
29321 +                               len -= 4;
29322 +                       }
29323 +               } else if ((((u32_t)from & 0x1) == 0) &&
29324 +                          (((u32_t)to & 0x1) == 0)) {
29325 +                       while ((int)len >= 2) {
29326 +                                *(u16_t *)to = ubi32_pci_read_u16(from);
29327 +                                to += 2;
29328 +                                from += 2;
29329 +                                len -= 2;
29330 +                       }
29331 +               }
29332 +
29333 +               while (len) {
29334 +                       *(u8_t *)to = ubi32_pci_read_u8(from);
29335 +                       to++;
29336 +                       from++;
29337 +                       len--;
29338 +               }
29339 +       } else
29340 +               memcpy(to, (void *)from, len);
29341 +}
29342 +EXPORT_SYMBOL(memcpy_fromio);
29343 +
29344 +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len)
29345 +{
29346 +       if (IS_PCI_ADDRESS(to)) {
29347 +               if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29348 +                       while ((int)len >= 4) {
29349 +                               ubi32_pci_write_u32(*(u32_t *)from, to);
29350 +                               to += 4;
29351 +                               from += 4;
29352 +                               len -= 4;
29353 +                       }
29354 +               } else if ((((u32_t)from & 0x1) == 0) &&
29355 +                          (((u32_t)to & 0x1) == 0)) {
29356 +                       while ((int)len >= 2) {
29357 +                               ubi32_pci_write_u16(*(u16_t *)from, to);
29358 +                               to += 2;
29359 +                               from += 2;
29360 +                               len -= 2;
29361 +                       }
29362 +               }
29363 +
29364 +               while (len) {
29365 +                       ubi32_pci_write_u8(*(u8_t *)from, to);
29366 +                       from++;
29367 +                       to++;
29368 +                       len--;
29369 +               }
29370 +       } else
29371 +               memcpy((void *)to, from, len);
29372 +
29373 +}
29374 +EXPORT_SYMBOL(memcpy_toio);
29375 +
29376 +void memset_io(volatile void __iomem *addr, int val, size_t len)
29377 +{
29378 +       if (IS_PCI_ADDRESS(addr)) {
29379 +               while (len) {
29380 +                       ubi32_pci_write_u8((unsigned char)val, addr);
29381 +                       addr++;
29382 +                       len--;
29383 +               }
29384 +       } else
29385 +               memset((void *)addr, val, len);
29386 +
29387 +}
29388 +EXPORT_SYMBOL(memset_io);
29389 +
29390 +void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
29391 +{
29392 +       if (IS_PCI_ADDRESS(port)) {
29393 +               while (count) {
29394 +                       *(u8_t *)buf = ioread8(port);
29395 +                       buf++;
29396 +                       count--;
29397 +               }
29398 +       } else {
29399 +               insb((unsigned int)port, buf, count);
29400 +       }
29401 +
29402 +}
29403 +EXPORT_SYMBOL(ioread8_rep);
29404 +
29405 +void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
29406 +{
29407 +       if (IS_PCI_ADDRESS(port)) {
29408 +               while (count) {
29409 +                       *(u16_t *)buf = ioread16(port);
29410 +                       buf += 2;
29411 +                       count--;
29412 +               }
29413 +       } else {
29414 +               insw((unsigned int)port, buf, count);
29415 +       }
29416 +}
29417 +EXPORT_SYMBOL(ioread16_rep);
29418 +
29419 +void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
29420 +{
29421 +        if (IS_PCI_ADDRESS(port)) {
29422 +               while (count) {
29423 +                       *(u32_t *)buf = ioread32(port);
29424 +                       buf += 4;
29425 +                       count--;
29426 +               }
29427 +       } else {
29428 +               insl((unsigned int)port, buf, count);
29429 +       }
29430 +}
29431 +EXPORT_SYMBOL(ioread32_rep);
29432 +
29433 +void  iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
29434 +{
29435 +         if (IS_PCI_ADDRESS(port)) {
29436 +               while (count) {
29437 +                       iowrite8(*(u8_t *)buf, port);
29438 +                       buf++;
29439 +                       count--;
29440 +               }
29441 +       } else {
29442 +               outsb((unsigned int)port, buf, count);
29443 +       }
29444 +
29445 +}
29446 +EXPORT_SYMBOL(iowrite8_rep);
29447 +
29448 +void  iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
29449 +{
29450 +       if (IS_PCI_ADDRESS(port)) {
29451 +               while (count) {
29452 +                       iowrite16(*(u16_t *)buf, port);
29453 +                       buf += 2;
29454 +                       count--;
29455 +               }
29456 +       } else {
29457 +               outsw((unsigned int)port, buf, count);
29458 +       }
29459 +}
29460 +EXPORT_SYMBOL(iowrite16_rep);
29461 +
29462 +void  iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
29463 +{
29464 +       if (IS_PCI_ADDRESS(port)) {
29465 +               while (count) {
29466 +                       iowrite32(*(u32_t *)buf, port);
29467 +                       buf += 4;
29468 +                       count--;
29469 +               }
29470 +       } else {
29471 +               outsl((unsigned int)port, buf, count);
29472 +       }
29473 +}
29474 +EXPORT_SYMBOL(iowrite32_rep);
29475 +
29476 +#endif /* CONFIG_PCI */
29477 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/Kconfig.switch linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Kconfig.switch
29478 --- linux-2.6.30.10/arch/ubicom32/mach-common/Kconfig.switch    1970-01-01 02:00:00.000000000 +0200
29479 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Kconfig.switch        2009-12-11 11:45:11.000000000 +0200
29480 @@ -0,0 +1,12 @@
29481 +menuconfig UBICOM_SWITCH
29482 +       tristate "Switch devices"
29483 +       help
29484 +               This option provides Ethernet switch management options via proc fs
29485 +
29486 +if UBICOM_SWITCH
29487 +config UBICOM_SWITCH_BCM539X
29488 +       tristate "Broadcom BCM539X series (SPI)"
29489 +       depends on SPI_MASTER
29490 +       help
29491 +               Supports Broadcom BCM539X Gigabit Ethernet Switches over SPI
29492 +endif
29493 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Makefile
29494 --- linux-2.6.30.10/arch/ubicom32/mach-common/Makefile  1970-01-01 02:00:00.000000000 +0200
29495 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Makefile      2009-12-11 11:45:11.000000000 +0200
29496 @@ -0,0 +1,41 @@
29497 +#
29498 +# arch/ubicom32/mach-common/Makefile
29499 +#      Makefile for Ubicom32 generic drivers/code.
29500 +#
29501 +# (C) Copyright 2009, Ubicom, Inc.
29502 +#
29503 +# This file is part of the Ubicom32 Linux Kernel Port.
29504 +#
29505 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
29506 +# it and/or modify it under the terms of the GNU General Public License
29507 +# as published by the Free Software Foundation, either version 2 of the
29508 +# License, or (at your option) any later version.
29509 +#
29510 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
29511 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
29512 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29513 +# the GNU General Public License for more details.
29514 +#
29515 +# You should have received a copy of the GNU General Public License
29516 +# along with the Ubicom32 Linux Kernel Port.  If not,
29517 +# see <http://www.gnu.org/licenses/>.
29518 +#
29519 +# Ubicom32 implementation derived from (with many thanks):
29520 +#   arch/m68knommu
29521 +#   arch/blackfin
29522 +#   arch/parisc
29523 +#
29524 +
29525 +obj-y += cachectl.o common.o usb_tio.o usb.o ubi32-gpio.o board.o bootargs.o profile.o
29526 +obj-$(CONFIG_PCI) += pci.o io.o
29527 +
29528 +obj-$(CONFIG_FB_UBICOM32) += vdc_tio.o
29529 +obj-$(CONFIG_UBICOM_HID) += ubicom32hid.o
29530 +obj-$(CONFIG_UBICOM_INPUT) += ubicom32input.o
29531 +obj-$(CONFIG_UBICOM_INPUT_I2C) += ubicom32input_i2c.o
29532 +obj-$(CONFIG_UBICOM_SWITCH) += switch-core.o
29533 +obj-$(CONFIG_UBICOM_SWITCH_BCM539X) += switch-bcm539x.o
29534 +obj-$(CONFIG_UIO_UBICOM32RING) += ring_tio.o
29535 +obj-$(CONFIG_SND_UBI32) += audio.o
29536 +obj-$(CONFIG_UBICOM32_PLIO) += plio.o
29537 +
29538 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/pci.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/pci.c
29539 --- linux-2.6.30.10/arch/ubicom32/mach-common/pci.c     1970-01-01 02:00:00.000000000 +0200
29540 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/pci.c 2009-12-11 11:45:11.000000000 +0200
29541 @@ -0,0 +1,1157 @@
29542 +/*
29543 + * arch/ubicom32/mach-common/pci.c
29544 + *     PCI interface management.
29545 + *
29546 + * (C) Copyright 2009, Ubicom, Inc.
29547 + *
29548 + * This file is part of the Ubicom32 Linux Kernel Port.
29549 + *
29550 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29551 + * it and/or modify it under the terms of the GNU General Public License
29552 + * as published by the Free Software Foundation, either version 2 of the
29553 + * License, or (at your option) any later version.
29554 + *
29555 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29556 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29557 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29558 + * the GNU General Public License for more details.
29559 + *
29560 + * You should have received a copy of the GNU General Public License
29561 + * along with the Ubicom32 Linux Kernel Port.  If not,
29562 + * see <http://www.gnu.org/licenses/>.
29563 + *
29564 + * Ubicom32 implementation derived from (with many thanks):
29565 + *   arch/m68knommu
29566 + *   arch/blackfin
29567 + *   arch/parisc
29568 + */
29569 +
29570 +#include <linux/module.h>
29571 +#include <linux/kernel.h>
29572 +#include <linux/pci.h>
29573 +#include <linux/slab.h>
29574 +#include <linux/init.h>
29575 +#include <linux/io.h>
29576 +#include <linux/seq_file.h>
29577 +#include <linux/proc_fs.h>
29578 +
29579 +#include <asm/devtree.h>
29580 +#include <asm/ip5000.h>
29581 +#include <asm/ubicom32-common.h>
29582 +
29583 +static int debug_pci = 1 ;
29584 +
29585 +/* #define PCI_USE_INTERNAL_LOCK 1 */
29586 +
29587 +#ifdef PCI_USE_INTERNAL_LOCK
29588 +#define PCI_LOCK(lock, irqflag)        pci_lock_acquire(irqflag)
29589 +#define PCI_UNLOCK(lock, irqflag) pci_lock_release(irqflag)
29590 +#elif defined(CONFIG_SMP)
29591 +static DEFINE_SPINLOCK(pci_master_lock);
29592 +#define PCI_LOCK(lock, irqflag)        spin_lock_irqsave(lock, irqflag)
29593 +#define PCI_UNLOCK(lock, irqflag) spin_unlock_irqrestore(lock, irqflag)
29594 +#else
29595 +#define PCI_LOCK(lock, irqflag)                local_irq_save(irqflag)
29596 +#define PCI_UNLOCK(lock, irqflag)      local_irq_restore(irqflag)
29597 +#endif
29598 +
29599 +#define PCI_DEV0_IDSEL CONFIG_PCI_DEV0_IDSEL
29600 +#define PCI_DEV1_IDSEL CONFIG_PCI_DEV1_IDSEL
29601 +
29602 +/*
29603 + * PCI commands
29604 + */
29605 +#define PCI_CMD_INT_ACK                0x00    /* not supported */
29606 +#define PCI_CMD_SPECIAL                0x01    /* not supported */
29607 +#define PCI_CMD_IO_READ                0x02
29608 +#define PCI_CMD_IO_WRITE       0x03
29609 +#define PCI_CMD_MEM_READ       0x06
29610 +#define PCI_CMD_MEM_WRITE      0x07
29611 +#define PCI_CMD_CFG_READ       0x0a
29612 +#define PCI_CMD_CFG_WRITE      0x0b
29613 +#define PCI_CMD_MEM_READ_MULT  0x0c    /* not supported */
29614 +#define PCI_CMD_DUAL_ADDR      0x0d    /* not supported */
29615 +#define PCI_CMD_MEM_READ_LINE  0x0e    /* not supported */
29616 +#define PCI_CMD_MEM_WRITE_INVAL        0x0f    /* not supported */
29617 +/*
29618 + * Status codes, returned by pci_read_u32() and pci_write_u32()
29619 + */
29620 +#define PCI_RESP_IN_PROGRESS   0xff  /* request still in queue */
29621 +#define PCI_RESP_OK            0
29622 +/*
29623 + * The following codes indicate that the request has completed
29624 + */
29625 +#define PCI_RESP_NO_DEVSEL             1  /* timeout before target asserted
29626 +                                           * DEVSEL! */
29627 +#define PCI_RESP_LOST_DEVSEL           2  /* had DEVSEL, but went away before
29628 +                                           * transfer completed! */
29629 +#define PCI_RESP_BAD_TRDY              3  /* target asserted TRDY without
29630 +                                           * DEVSEL! */
29631 +#define PCI_RESP_NO_TRDY               4  /* timeout before target asserted
29632 +                                           * TRDY! */
29633 +#define PCI_RESP_BAD_STOP              5  /* target asserted STOP and TRDY
29634 +                                           * without DEVSEL! */
29635 +#define PCI_RESP_TARGET_ABORT          6
29636 +#define PCI_RESP_TARGET_RETRY          7
29637 +#define        PCI_RESP_TARGET_DISCONNECT      8
29638 +#define PCI_RESP_MISMATCH              9  /* data read back doesn't match data
29639 +                                           * written - debug only, the core PCI
29640 +                                           * routines never return this */
29641 +#define PCI_RESP_DET_SERR              10
29642 +#define PCI_RESP_DET_PERR              11
29643 +#define PCI_RESP_MALFORMED_REQ         12 /* Could be due to misaligned
29644 +                                           * requests or invalid address */
29645 +#define PCI_RESP_NO_RESOURCE           13 /* Could be memory or other resourse
29646 +                                           * like queue space */
29647 +#define PCI_RESP_ERROR                 14 /* All emcompassing error */
29648 +
29649 +/* registers in PCI config space */
29650 +#define PCI_DEVICE_VENDOR_ID_REG       0x00
29651 +#define PCI_STATUS_COMMAND_REG         0x04
29652 +#define PCI_CLASS_REVISION_REG         0x08
29653 +#define PCI_BHLC_REG                   0x0c  /* BIST, Header type, Latency
29654 +                                              * timer, Cache line size */
29655 +#define PCI_BASE_ADDR_REG              0x10
29656 +#define PCI_BASE_REG_COUNT             6
29657 +#define CARDBUS_CIS_PTR_REG            0x28
29658 +#define PCI_SUB_SYSTEM_ID_REG          0x2c
29659 +#define PCI_EXP_ROM_ADDR_REG           0x30
29660 +#define PCI_CAP_PTR_REG                        0x34
29661 +#define PCI_LGPL_REG                   0x3C  /* max Latency, min Gnt, interrupt
29662 +                                              * Pin, interrupt Line */
29663 +
29664 +struct pci_master_request {
29665 +       volatile u32_t pci_address;     /* must be 4-byte aligned */
29666 +       volatile u32_t data;            /* must be 4-byte aligned */
29667 +       volatile u8_t cmd;
29668 +       volatile u8_t byte_valid;
29669 +       volatile u8_t status;
29670 +};
29671 +
29672 +struct pci_devnode {
29673 +       struct devtree_node dn;
29674 +       u32_t pci_idsel_0;
29675 +       u32_t pci_idsel_1;
29676 +       u32_t pci_cpu_address;
29677 +       struct pci_master_request volatile *volatile req;
29678 +};
29679 +
29680 +static struct pci_master_request req;  /* globally used for faster master write
29681 +                                        * (discarding result when possible) */
29682 +static struct pci_devnode *pci_node;
29683 +
29684 +#if !defined(CONFIG_DEBUG_PCIMEASURE)
29685 +#define PCI_DECLARE_MEASUREMENT
29686 +#define PCI_MEASUREMENT_START()
29687 +#define PCI_MEASUREMENT_END(idx)
29688 +#else
29689 +#define PCI_DECLARE_MEASUREMENT \
29690 +       int __diff;             \
29691 +       unsigned int __tstart;
29692 +
29693 +#define PCI_MEASUREMENT_START() \
29694 +       __tstart = UBICOM32_IO_TIMER->sysval;
29695 +
29696 +#define PCI_MEASUREMENT_END(idx) \
29697 +       __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
29698 +       pci_measurement_update((idx), __diff);
29699 +
29700 +#define PCI_WEIGHT 32
29701 +
29702 +struct pci_measurement {
29703 +       volatile unsigned int min;
29704 +       volatile unsigned int avg;
29705 +       volatile unsigned int max;
29706 +};
29707 +
29708 +enum pci_measurement_list {
29709 +       PCI_MEASUREMENT_READ32,
29710 +       PCI_MEASUREMENT_WRITE32,
29711 +       PCI_MEASUREMENT_READ16,
29712 +       PCI_MEASUREMENT_WRITE16,
29713 +       PCI_MEASUREMENT_READ8,
29714 +       PCI_MEASUREMENT_WRITE8,
29715 +       PCI_MEASUREMENT_LAST,
29716 +};
29717 +
29718 +static const char *pci_measurement_name_list[PCI_MEASUREMENT_LAST] = {
29719 +       "READ32",
29720 +       "WRITE32",
29721 +       "READ16",
29722 +       "WRITE16",
29723 +       "READ8",
29724 +       "WRITE8"
29725 +};
29726 +static struct pci_measurement pci_measurements[PCI_MEASUREMENT_LAST];
29727 +
29728 +/*
29729 + * pci_measurement_update()
29730 + *     Update an entry in the measurement array for this idx.
29731 + */
29732 +static void pci_measurement_update(int idx, int sample)
29733 +{
29734 +       struct pci_measurement *pm = &pci_measurements[idx];
29735 +       if ((pm->min == 0) || (pm->min > sample)) {
29736 +               pm->min = sample;
29737 +       }
29738 +       if (pm->max < sample) {
29739 +               pm->max = sample;
29740 +       }
29741 +       pm->avg = ((pm->avg * (PCI_WEIGHT - 1)) + sample) / PCI_WEIGHT;
29742 +}
29743 +#endif
29744 +
29745 +#if defined(PCI_USE_INTERNAL_LOCK)
29746 +/*
29747 + * pci_lock_release()
29748 + *     Release the PCI lock.
29749 + */
29750 +static void pci_lock_release(unsigned long irqflag)
29751 +{
29752 +       UBICOM32_UNLOCK(PCI_LOCK_BIT);
29753 +}
29754 +
29755 +/*
29756 + * pci_lock_acquire()
29757 + *     Acquire the PCI lock, spin if not available.
29758 + */
29759 +static void pci_lock_acquire(unsigned long irqflag)
29760 +{
29761 +       UBICOM32_LOCK(PCI_LOCK_BIT);
29762 +}
29763 +#endif
29764 +
29765 +/*
29766 + * pci_set_hrt_interrupt()
29767 + */
29768 +static inline void pci_set_hrt_interrupt(struct pci_devnode *pci_node)
29769 +{
29770 +       ubicom32_set_interrupt(pci_node->dn.sendirq);
29771 +}
29772 +
29773 +/*
29774 + * pci_read_u32()
29775 + *     Synchronously read 32 bits from PCI space.
29776 + */
29777 +u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data)
29778 +{
29779 +       u8 status;
29780 +       unsigned long irqflag;
29781 +
29782 +
29783 +       /*
29784 +        * Fill in the request.
29785 +        */
29786 +       volatile struct pci_master_request lreq;
29787 +       PCI_DECLARE_MEASUREMENT;
29788 +
29789 +       lreq.pci_address = address;
29790 +       lreq.cmd = pci_cmd;
29791 +       lreq.byte_valid = 0xf;          /* enable all bytes */
29792 +
29793 +       /*
29794 +        * Wait for any previous request to complete and then make this request.
29795 +        */
29796 +       PCI_MEASUREMENT_START();
29797 +       PCI_LOCK(&pci_master_lock, irqflag);
29798 +       while (unlikely(pci_node->req == &req))
29799 +               ;
29800 +       pci_node->req = &lreq;
29801 +       pci_set_hrt_interrupt(pci_node);
29802 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29803 +
29804 +       /*
29805 +        * Wait for the result to show up.
29806 +        */
29807 +       while (unlikely(pci_node->req == &lreq))
29808 +               ;
29809 +       status = lreq.status;
29810 +       if (likely(status == PCI_RESP_OK))
29811 +               *data = le32_to_cpu(lreq.data);
29812 +       else
29813 +               *data = 0;
29814 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ32);
29815 +       return status;
29816 +}
29817 +
29818 +/*
29819 + * pci_write_u32()
29820 + *     Asyncrhnously or synchronously write 32 bits to PCI master space.
29821 + */
29822 +u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data)
29823 +{
29824 +       unsigned long irqflag;
29825 +       PCI_DECLARE_MEASUREMENT;
29826 +
29827 +       /*
29828 +        * Wait for any previous write or pending read to complete.
29829 +        *
29830 +        * We use a global data block because once we write the request
29831 +        * we do not wait for it to complete before exiting.
29832 +        */
29833 +       PCI_MEASUREMENT_START();
29834 +       PCI_LOCK(&pci_master_lock, irqflag);
29835 +       while (unlikely(pci_node->req == &req))
29836 +               ;
29837 +       req.pci_address = address;
29838 +       req.data = cpu_to_le32(data);
29839 +       req.cmd = pci_cmd;
29840 +       req.byte_valid = 0xf;           /* enable all bytes */
29841 +       pci_node->req = &req;
29842 +       pci_set_hrt_interrupt(pci_node);
29843 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29844 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE32);
29845 +       return PCI_RESP_OK;
29846 +}
29847 +
29848 +/*
29849 + * pci_read_u16()
29850 + *     Synchronously read 16 bits from PCI space.
29851 + */
29852 +u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data)
29853 +{
29854 +       u8 status;
29855 +       unsigned long irqflag;
29856 +
29857 +       /*
29858 +        * Fill in the request.
29859 +        */
29860 +       volatile struct pci_master_request lreq;
29861 +       PCI_DECLARE_MEASUREMENT;
29862 +
29863 +       lreq.pci_address = address & ~2;
29864 +       lreq.cmd = pci_cmd;
29865 +       lreq.byte_valid = (address & 2) ? 0xc : 0x3;
29866 +
29867 +       /*
29868 +        * Wait for any previous request to complete and then make this request.
29869 +        */
29870 +       PCI_MEASUREMENT_START();
29871 +       PCI_LOCK(&pci_master_lock, irqflag);
29872 +       while (unlikely(pci_node->req == &req))
29873 +               ;
29874 +       pci_node->req = &lreq;
29875 +       pci_set_hrt_interrupt(pci_node);
29876 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29877 +
29878 +       /*
29879 +        * Wait for the result to show up.
29880 +        */
29881 +       while (unlikely(pci_node->req == &lreq))
29882 +               ;
29883 +       status = lreq.status;
29884 +       if (likely(status == PCI_RESP_OK)) {
29885 +               lreq.data = le32_to_cpu(lreq.data);
29886 +               *data = (u16)((address & 2) ? (lreq.data >> 16) : lreq.data);
29887 +       } else
29888 +               *data = 0;
29889 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ16);
29890 +       return status;
29891 +}
29892 +
29893 +/*
29894 + * pci_write_u16()
29895 + *     Asyncrhnously or synchronously write 16 bits to PCI master space.
29896 + */
29897 +u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data)
29898 +{
29899 +       unsigned long irqflag;
29900 +       PCI_DECLARE_MEASUREMENT;
29901 +
29902 +       /*
29903 +        * Wait for any previous write or pending read to complete.
29904 +        *
29905 +        * We use a global data block because once we write the request
29906 +        * we do not wait for it to complete before exiting.
29907 +        */
29908 +       PCI_MEASUREMENT_START();
29909 +       PCI_LOCK(&pci_master_lock, irqflag);
29910 +       while (unlikely(pci_node->req == &req))
29911 +               ;
29912 +       req.pci_address = address & ~2;
29913 +       req.data = (u32)data;
29914 +       req.data = cpu_to_le32((address & 2) ? (req.data << 16) : req.data);
29915 +       req.cmd = pci_cmd;
29916 +       req.byte_valid = (address & 2) ? 0xc : 0x3;
29917 +       pci_node->req = &req;
29918 +       pci_set_hrt_interrupt(pci_node);
29919 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29920 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE16);
29921 +       return PCI_RESP_OK;
29922 +}
29923 +
29924 +/*
29925 + * pci_read_u8()
29926 + *     Synchronously read 8 bits from PCI space.
29927 + */
29928 +u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data)
29929 +{
29930 +       u8 status;
29931 +       unsigned long irqflag;
29932 +
29933 +       /*
29934 +        * Fill in the request.
29935 +        */
29936 +       volatile struct pci_master_request lreq;
29937 +       PCI_DECLARE_MEASUREMENT;
29938 +
29939 +       lreq.pci_address = address & ~3;
29940 +       lreq.cmd = pci_cmd;
29941 +       lreq.byte_valid = 1 << (address & 0x3);
29942 +
29943 +       /*
29944 +        * Wait for any previous request to complete and then make this request.
29945 +        */
29946 +       PCI_MEASUREMENT_START();
29947 +       PCI_LOCK(&pci_master_lock, irqflag);
29948 +       while (unlikely(pci_node->req == &req))
29949 +               ;
29950 +       pci_node->req = &lreq;
29951 +       pci_set_hrt_interrupt(pci_node);
29952 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29953 +
29954 +       /*
29955 +        * Wait for the result to show up.
29956 +        */
29957 +       while (unlikely(pci_node->req == &lreq))
29958 +               ;
29959 +       status = lreq.status;
29960 +       if (likely(status == PCI_RESP_OK)) {
29961 +               *data = (u8)(lreq.data >> (24 - ((address & 0x3) << 3)));
29962 +       } else
29963 +               *data = 0;
29964 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ8);
29965 +       return status;
29966 +}
29967 +
29968 +/*
29969 + * pci_write_u8()
29970 + *     Asyncrhnously or synchronously write 8 bits to PCI master space.
29971 + */
29972 +u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data)
29973 +{
29974 +       unsigned long irqflag;
29975 +       PCI_DECLARE_MEASUREMENT;
29976 +
29977 +       /*
29978 +        * Wait for any previous write or pending read to complete.
29979 +        *
29980 +        * We use a global data block because once we write the request
29981 +        * we do not wait for it to complete before exiting.
29982 +        */
29983 +       PCI_MEASUREMENT_START();
29984 +       PCI_LOCK(&pci_master_lock, irqflag);
29985 +       while (unlikely(pci_node->req == &req))
29986 +               ;
29987 +       req.pci_address = address & ~3;
29988 +       req.data = ((u32)data << (24 - ((address & 0x3) << 3)));
29989 +       req.cmd = pci_cmd;
29990 +       req.byte_valid = 1 << (address & 0x3);
29991 +       pci_node->req = &req;
29992 +       pci_set_hrt_interrupt(pci_node);
29993 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29994 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE8);
29995 +       return PCI_RESP_OK;
29996 +}
29997 +
29998 +unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr)
29999 +{
30000 +       unsigned int data;
30001 +       pci_read_u32(PCI_CMD_MEM_READ, (u32)addr, &data);
30002 +       return data;
30003 +}
30004 +EXPORT_SYMBOL(ubi32_pci_read_u32);
30005 +
30006 +unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr)
30007 +{
30008 +       unsigned short data;
30009 +       pci_read_u16(PCI_CMD_MEM_READ, (u32)addr, &data);
30010 +       return data;
30011 +}
30012 +EXPORT_SYMBOL(ubi32_pci_read_u16);
30013 +
30014 +unsigned char  ubi32_pci_read_u8(const volatile void __iomem *addr)
30015 +{
30016 +       unsigned char  data;
30017 +       pci_read_u8(PCI_CMD_MEM_READ, (u32)addr, &data);
30018 +       return data;
30019 +}
30020 +EXPORT_SYMBOL(ubi32_pci_read_u8);
30021 +
30022 +void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr)
30023 +{
30024 +       pci_write_u32(PCI_CMD_MEM_WRITE, (u32)addr, val);
30025 +}
30026 +EXPORT_SYMBOL(ubi32_pci_write_u32);
30027 +
30028 +void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr)
30029 +{
30030 +       pci_write_u16(PCI_CMD_MEM_WRITE, (u32)addr, val);
30031 +}
30032 +EXPORT_SYMBOL(ubi32_pci_write_u16);
30033 +
30034 +void ubi32_pci_write_u8(unsigned char val, const void volatile __iomem *addr)
30035 +{
30036 +       pci_write_u8(PCI_CMD_MEM_WRITE, (u32)addr, val);
30037 +}
30038 +EXPORT_SYMBOL(ubi32_pci_write_u8);
30039 +
30040 +#if defined(CONFIG_DEBUG_PCIMEASURE)
30041 +static unsigned int pci_cycles_to_nano(unsigned int cycles, unsigned int frequency)
30042 +{
30043 +       unsigned int nano = ((cycles * 1000) / (frequency / 1000000));
30044 +       return nano;
30045 +}
30046 +
30047 +/*
30048 + * pci_measurement_show()
30049 + *     Print out the min, avg, max values for each PCI transaction type.
30050 + *
30051 + * By request, the max value is reset after each dump.
30052 + */
30053 +static int pci_measurement_show(struct seq_file *p, void *v)
30054 +{
30055 +       unsigned int min, avg, max;
30056 +       unsigned int freq = processor_frequency();
30057 +       int trans = *((loff_t *) v);
30058 +
30059 +       if (trans == 0) {
30060 +               seq_puts(p, "min\tavg\tmax\t(nano-seconds)\n");
30061 +       }
30062 +
30063 +       if (trans >= PCI_MEASUREMENT_LAST) {
30064 +               return 0;
30065 +       }
30066 +
30067 +       min = pci_cycles_to_nano(pci_measurements[trans].min, freq);
30068 +       avg = pci_cycles_to_nano(pci_measurements[trans].avg, freq);
30069 +       max = pci_cycles_to_nano(pci_measurements[trans].max, freq);
30070 +       pci_measurements[trans].max = 0;
30071 +       seq_printf(p, "%u\t%u\t%u\t%s\n", min, avg, max, pci_measurement_name_list[trans]);
30072 +       return 0;
30073 +}
30074 +
30075 +static void *pci_measurement_start(struct seq_file *f, loff_t *pos)
30076 +{
30077 +       return (*pos < PCI_MEASUREMENT_LAST) ? pos : NULL;
30078 +}
30079 +
30080 +static void *pci_measurement_next(struct seq_file *f, void *v, loff_t *pos)
30081 +{
30082 +       (*pos)++;
30083 +       if (*pos >= PCI_MEASUREMENT_LAST)
30084 +               return NULL;
30085 +       return pos;
30086 +}
30087 +
30088 +static void pci_measurement_stop(struct seq_file *f, void *v)
30089 +{
30090 +       /* Nothing to do */
30091 +}
30092 +
30093 +static const struct seq_operations pci_measurement_seq_ops = {
30094 +       .start = pci_measurement_start,
30095 +       .next  = pci_measurement_next,
30096 +       .stop  = pci_measurement_stop,
30097 +       .show  = pci_measurement_show,
30098 +};
30099 +
30100 +static int pci_measurement_open(struct inode *inode, struct file *filp)
30101 +{
30102 +       return seq_open(filp, &pci_measurement_seq_ops);
30103 +}
30104 +
30105 +static const struct file_operations pci_measurement_fops = {
30106 +       .open           = pci_measurement_open,
30107 +       .read           = seq_read,
30108 +       .llseek         = seq_lseek,
30109 +       .release        = seq_release,
30110 +};
30111 +
30112 +static int __init pci_measurement_init(void)
30113 +{
30114 +       proc_create("pci_measurements", 0, NULL, &pci_measurement_fops);
30115 +       return 0;
30116 +}
30117 +module_init(pci_measurement_init);
30118 +#endif
30119 +
30120 +static int ubi32_pci_read_config(struct pci_bus *bus, unsigned int devfn,
30121 +                                int where, int size, u32 *value)
30122 +{
30123 +       u8 cmd;
30124 +       u32 addr;
30125 +       u8  data8;
30126 +       u16 data16;
30127 +
30128 +       u8 slot = PCI_SLOT(devfn);
30129 +       u8 fn = PCI_FUNC(devfn);
30130 +
30131 +       if (slot > 1) {
30132 +               return PCIBIOS_DEVICE_NOT_FOUND;
30133 +       } else if (slot == 0) {
30134 +               addr = PCI_DEV0_IDSEL + where;
30135 +       } else {
30136 +               addr = PCI_DEV1_IDSEL + where;
30137 +       }
30138 +
30139 +       addr += (fn << 8);
30140 +
30141 +       cmd = PCI_CMD_CFG_READ;
30142 +       if (size == 1) {
30143 +               pci_read_u8(cmd, addr, &data8);
30144 +               *value = (u32)data8;
30145 +       } else if (size == 2) {
30146 +               pci_read_u16(cmd, addr, &data16);
30147 +               *value = (u32)data16;
30148 +       } else {
30149 +               pci_read_u32(cmd, addr, value);
30150 +       }
30151 +
30152 +       return PCIBIOS_SUCCESSFUL;
30153 +}
30154 +
30155 +static int ubi32_pci_write_config(struct pci_bus *bus, unsigned int devfn,
30156 +                                 int where, int size, u32 value)
30157 +{
30158 +       u8 cmd;
30159 +       u32 addr;
30160 +       u8 slot = PCI_SLOT(devfn);
30161 +       u8 fn = PCI_FUNC(devfn);
30162 +
30163 +       if (slot > 1) {
30164 +               return PCIBIOS_DEVICE_NOT_FOUND;
30165 +       } else if (slot == 0) {
30166 +               addr = PCI_DEV0_IDSEL + where;
30167 +       } else {
30168 +               addr = PCI_DEV1_IDSEL + where;
30169 +       }
30170 +
30171 +       addr += (fn << 8);
30172 +
30173 +       cmd = PCI_CMD_CFG_WRITE;
30174 +       if (size == 1) {
30175 +               pci_write_u8(cmd, addr, (u8)value);
30176 +       } else if (size == 2) {
30177 +               pci_write_u16(cmd, addr, (u16)value);
30178 +       } else {
30179 +               pci_write_u32(cmd, addr, value);
30180 +       }
30181 +
30182 +       return PCIBIOS_SUCCESSFUL;
30183 +}
30184 +
30185 +int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
30186 +{
30187 +       return -EIO;
30188 +}
30189 +EXPORT_SYMBOL(pci_set_dma_max_seg_size);
30190 +
30191 +int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
30192 +{
30193 +       return -EIO;
30194 +}
30195 +EXPORT_SYMBOL(pci_set_dma_seg_boundary);
30196 +
30197 +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
30198 +{
30199 +       resource_size_t start = pci_resource_start(dev, bar);
30200 +       resource_size_t len   = pci_resource_len(dev, bar);
30201 +       unsigned long flags = pci_resource_flags(dev, bar);
30202 +
30203 +       if (!len || !start) {
30204 +               return NULL;
30205 +       }
30206 +
30207 +       if (maxlen && len > maxlen) {
30208 +               len = maxlen;
30209 +       }
30210 +
30211 +       if (flags & IORESOURCE_IO) {
30212 +               return ioport_map(start, len);
30213 +       }
30214 +
30215 +       if (flags & IORESOURCE_MEM) {
30216 +               if (flags & IORESOURCE_CACHEABLE) {
30217 +                       return ioremap(start, len);
30218 +               }
30219 +               return ioremap_nocache(start, len);
30220 +       }
30221 +       return NULL;
30222 +}
30223 +EXPORT_SYMBOL(pci_iomap);
30224 +
30225 +void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
30226 +{
30227 +       if ((unsigned long)addr >= VMALLOC_START &&
30228 +           (unsigned long)addr < VMALLOC_END) {
30229 +               iounmap(addr);
30230 +       }
30231 +}
30232 +EXPORT_SYMBOL(pci_iounmap);
30233 +
30234 +/*
30235 + *  From arch/arm/kernel/bios32.c
30236 + *
30237 + *  PCI bios-type initialisation for PCI machines
30238 + *
30239 + *  Bits taken from various places.
30240 + */
30241 +static void __init pcibios_init_hw(struct hw_pci *hw)
30242 +{
30243 +       struct pci_sys_data *sys = NULL;
30244 +       int ret;
30245 +       int nr, busnr;
30246 +
30247 +       for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
30248 +               sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
30249 +               if (!sys)
30250 +                       panic("PCI: unable to allocate sys data!");
30251 +
30252 +               sys->hw      = hw;
30253 +               sys->busnr   = busnr;
30254 +               sys->map_irq = hw->map_irq;
30255 +               sys->resource[0] = &ioport_resource;
30256 +               sys->resource[1] = &iomem_resource;
30257 +
30258 +               ret = hw->setup(nr, sys);
30259 +
30260 +               if (ret > 0) {
30261 +                       sys->bus = hw->scan(nr, sys);
30262 +
30263 +                       if (!sys->bus)
30264 +                               panic("PCI: unable to scan bus!");
30265 +
30266 +                       busnr = sys->bus->subordinate + 1;
30267 +
30268 +                       list_add(&sys->node, &hw->buses);
30269 +               } else {
30270 +                       kfree(sys);
30271 +                       if (ret < 0)
30272 +                               break;
30273 +               }
30274 +       }
30275 +}
30276 +
30277 +/*
30278 + * Swizzle the device pin each time we cross a bridge.
30279 + * This might update pin and returns the slot number.
30280 + */
30281 +static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
30282 +{
30283 +       struct pci_sys_data *sys = dev->sysdata;
30284 +       int slot = 0, oldpin = *pin;
30285 +
30286 +       if (sys->swizzle)
30287 +               slot = sys->swizzle(dev, pin);
30288 +
30289 +       if (debug_pci)
30290 +               printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
30291 +                       pci_name(dev), oldpin, *pin, slot);
30292 +       return slot;
30293 +}
30294 +
30295 +/*
30296 + * Map a slot/pin to an IRQ.
30297 + */
30298 +static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30299 +{
30300 +       struct pci_sys_data *sys = dev->sysdata;
30301 +       int irq = -1;
30302 +
30303 +       if (sys->map_irq)
30304 +               irq = sys->map_irq(dev, slot, pin);
30305 +
30306 +       if (debug_pci)
30307 +               printk("PCI: %s mapping slot %d pin %d => irq %d\n",
30308 +                       pci_name(dev), slot, pin, irq);
30309 +
30310 +       return irq;
30311 +}
30312 +
30313 +void __init pci_common_init(struct hw_pci *hw)
30314 +{
30315 +       struct pci_sys_data *sys;
30316 +
30317 +       INIT_LIST_HEAD(&hw->buses);
30318 +
30319 +       if (hw->preinit)
30320 +               hw->preinit();
30321 +       pcibios_init_hw(hw);
30322 +       if (hw->postinit)
30323 +               hw->postinit();
30324 +
30325 +       pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
30326 +       list_for_each_entry(sys, &hw->buses, node) {
30327 +               struct pci_bus *bus = sys->bus;
30328 +               /*
30329 +                * Size the bridge windows.
30330 +                */
30331 +               pci_bus_size_bridges(bus);
30332 +               /*
30333 +                * Assign resources.
30334 +                */
30335 +               pci_bus_assign_resources(bus);
30336 +
30337 +               /*
30338 +                * Tell drivers about devices found.
30339 +                */
30340 +               pci_bus_add_devices(bus);
30341 +       }
30342 +}
30343 +
30344 +char * __init pcibios_setup(char *str)
30345 +{
30346 +       if (!strcmp(str, "debug")) {
30347 +               debug_pci = 1;
30348 +               return NULL;
30349 +       }
30350 +       return str;
30351 +}
30352 +
30353 +/*
30354 + * From arch/i386/kernel/pci-i386.c:
30355 + *
30356 + * We need to avoid collisions with `mirrored' VGA ports
30357 + * and other strange ISA hardware, so we always want the
30358 + * addresses to be allocated in the 0x000-0x0ff region
30359 + * modulo 0x400.
30360 + *
30361 + * Why? Because some silly external IO cards only decode
30362 + * the low 10 bits of the IO address. The 0x00-0xff region
30363 + * is reserved for motherboard devices that decode all 16
30364 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
30365 + * but we want to try to avoid allocating at 0x2900-0x2bff
30366 + * which might be mirrored at 0x0100-0x03ff..
30367 + */
30368 +void pcibios_align_resource(void *data, struct resource *res,
30369 +                           resource_size_t size, resource_size_t align)
30370 +{
30371 +       resource_size_t start = res->start;
30372 +
30373 +       if (res->flags & IORESOURCE_IO && start & 0x300)
30374 +               start = (start + 0x3ff) & ~0x3ff;
30375 +
30376 +       res->start = (start + align - 1) & ~(align - 1);
30377 +}
30378 +
30379 +
30380 +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
30381 +{
30382 +       if (debug_pci)
30383 +               printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
30384 +       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
30385 +}
30386 +
30387 +/*
30388 + * If the bus contains any of these devices, then we must not turn on
30389 + * parity checking of any kind.  Currently this is CyberPro 20x0 only.
30390 + */
30391 +static inline int pdev_bad_for_parity(struct pci_dev *dev)
30392 +{
30393 +       return (dev->vendor == PCI_VENDOR_ID_INTERG &&
30394 +               (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
30395 +                dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
30396 +               (dev->vendor == PCI_VENDOR_ID_ITE &&
30397 +                dev->device == PCI_DEVICE_ID_ITE_8152);
30398 +
30399 +}
30400 +
30401 +/*
30402 + * Adjust the device resources from bus-centric to Linux-centric.
30403 + */
30404 +static void __devinit
30405 +pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
30406 +{
30407 +       resource_size_t offset;
30408 +       int i;
30409 +
30410 +       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
30411 +               if (dev->resource[i].start == 0)
30412 +                       continue;
30413 +               if (dev->resource[i].flags & IORESOURCE_MEM)
30414 +                       offset = root->mem_offset;
30415 +               else
30416 +                       offset = root->io_offset;
30417 +
30418 +               dev->resource[i].start += offset;
30419 +               dev->resource[i].end   += offset;
30420 +       }
30421 +}
30422 +
30423 +static void __devinit
30424 +pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
30425 +{
30426 +       struct pci_dev *dev = bus->self;
30427 +       int i;
30428 +
30429 +       if (!dev) {
30430 +               /*
30431 +                * Assign root bus resources.
30432 +                */
30433 +               for (i = 0; i < 3; i++)
30434 +                       bus->resource[i] = root->resource[i];
30435 +       }
30436 +}
30437 +
30438 +/*
30439 + * pcibios_fixup_bus - Called after each bus is probed,
30440 + * but before its children are examined.
30441 + */
30442 +void pcibios_fixup_bus(struct pci_bus *bus)
30443 +{
30444 +       struct pci_sys_data *root = bus->sysdata;
30445 +       struct pci_dev *dev;
30446 +       u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
30447 +               PCI_COMMAND_FAST_BACK;
30448 +
30449 +       pbus_assign_bus_resources(bus, root);
30450 +
30451 +       /*
30452 +        * Walk the devices on this bus, working out what we can
30453 +        * and can't support.
30454 +        */
30455 +       list_for_each_entry(dev, &bus->devices, bus_list) {
30456 +               u16 status;
30457 +
30458 +               pdev_fixup_device_resources(root, dev);
30459 +
30460 +               pci_read_config_word(dev, PCI_STATUS, &status);
30461 +
30462 +               /*
30463 +                * If any device on this bus does not support fast back
30464 +                * to back transfers, then the bus as a whole is not able
30465 +                * to support them.  Having fast back to back transfers
30466 +                * on saves us one PCI cycle per transaction.
30467 +                */
30468 +               if (!(status & PCI_STATUS_FAST_BACK))
30469 +                       features &= ~PCI_COMMAND_FAST_BACK;
30470 +
30471 +               if (pdev_bad_for_parity(dev))
30472 +                       features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
30473 +
30474 +               switch (dev->class >> 8) {
30475 +               case PCI_CLASS_BRIDGE_PCI:
30476 +                       pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
30477 +                       status |= PCI_BRIDGE_CTL_PARITY |
30478 +                               PCI_BRIDGE_CTL_MASTER_ABORT;
30479 +                       status &= ~(PCI_BRIDGE_CTL_BUS_RESET |
30480 +                                   PCI_BRIDGE_CTL_FAST_BACK);
30481 +                       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
30482 +                       break;
30483 +
30484 +               case PCI_CLASS_BRIDGE_CARDBUS:
30485 +                       pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30486 +                                            &status);
30487 +                       status |= PCI_CB_BRIDGE_CTL_PARITY |
30488 +                               PCI_CB_BRIDGE_CTL_MASTER_ABORT;
30489 +                       pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30490 +                                             status);
30491 +                       break;
30492 +               }
30493 +       }
30494 +
30495 +       /*
30496 +        * Now walk the devices again, this time setting them up.
30497 +        */
30498 +       list_for_each_entry(dev, &bus->devices, bus_list) {
30499 +               u16 cmd;
30500 +
30501 +               pci_read_config_word(dev, PCI_COMMAND, &cmd);
30502 +               cmd |= features;
30503 +               pci_write_config_word(dev, PCI_COMMAND, cmd);
30504 +
30505 +               pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
30506 +                                     L1_CACHE_BYTES >> 2);
30507 +       }
30508 +
30509 +       /*
30510 +        * Propagate the flags to the PCI bridge.
30511 +        */
30512 +       if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
30513 +               if (features & PCI_COMMAND_FAST_BACK)
30514 +                       bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
30515 +               if (features & PCI_COMMAND_PARITY)
30516 +                       bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
30517 +       }
30518 +
30519 +       /*
30520 +        * Report what we did for this bus
30521 +        */
30522 +       printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
30523 +               bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
30524 +}
30525 +/*
30526 + * Convert from Linux-centric to bus-centric addresses for bridge devices.
30527 + */
30528 +void
30529 +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
30530 +                        struct resource *res)
30531 +{
30532 +       struct pci_sys_data *root = dev->sysdata;
30533 +       unsigned long offset = 0;
30534 +
30535 +       if (res->flags & IORESOURCE_IO)
30536 +               offset = root->io_offset;
30537 +       if (res->flags & IORESOURCE_MEM)
30538 +               offset = root->mem_offset;
30539 +
30540 +       region->start = res->start - offset;
30541 +       region->end   = res->end - offset;
30542 +}
30543 +
30544 +void __devinit
30545 +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
30546 +                       struct pci_bus_region *region)
30547 +{
30548 +       struct pci_sys_data *root = dev->sysdata;
30549 +       unsigned long offset = 0;
30550 +
30551 +       if (res->flags & IORESOURCE_IO)
30552 +               offset = root->io_offset;
30553 +       if (res->flags & IORESOURCE_MEM)
30554 +               offset = root->mem_offset;
30555 +
30556 +       res->start = region->start + offset;
30557 +       res->end   = region->end + offset;
30558 +}
30559 +
30560 +#ifdef CONFIG_HOTPLUG
30561 +EXPORT_SYMBOL(pcibios_fixup_bus);
30562 +EXPORT_SYMBOL(pcibios_resource_to_bus);
30563 +EXPORT_SYMBOL(pcibios_bus_to_resource);
30564 +#endif
30565 +
30566 +/**
30567 + * pcibios_enable_device - Enable I/O and memory.
30568 + * @dev: PCI device to be enabled
30569 + */
30570 +int pcibios_enable_device(struct pci_dev *dev, int mask)
30571 +{
30572 +       u16 cmd, old_cmd;
30573 +       int idx;
30574 +       struct resource *r;
30575 +
30576 +       pci_read_config_word(dev, PCI_COMMAND, &cmd);
30577 +       old_cmd = cmd;
30578 +       for (idx = 0; idx < 6; idx++) {
30579 +               /* Only set up the requested stuff */
30580 +               if (!(mask & (1 << idx)))
30581 +                       continue;
30582 +
30583 +               r = dev->resource + idx;
30584 +               if (!r->start && r->end) {
30585 +                       printk(KERN_ERR "PCI: Device %s not available because"
30586 +                              " of resource collisions\n", pci_name(dev));
30587 +                       return -EINVAL;
30588 +               }
30589 +               if (r->flags & IORESOURCE_IO)
30590 +                       cmd |= PCI_COMMAND_IO;
30591 +               if (r->flags & IORESOURCE_MEM)
30592 +                       cmd |= PCI_COMMAND_MEMORY;
30593 +       }
30594 +
30595 +       /*
30596 +        * Bridges (eg, cardbus bridges) need to be fully enabled
30597 +        */
30598 +       if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
30599 +               cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
30600 +
30601 +       if (cmd != old_cmd) {
30602 +               printk("PCI: enabling device %s (%04x -> %04x)\n",
30603 +                      pci_name(dev), old_cmd, cmd);
30604 +               pci_write_config_word(dev, PCI_COMMAND, cmd);
30605 +       }
30606 +       return 0;
30607 +}
30608 +
30609 +
30610 +struct pci_ops ubi32_pci_ops = {
30611 +       .read   = ubi32_pci_read_config,
30612 +       .write  = ubi32_pci_write_config,
30613 +};
30614 +
30615 +static struct pci_bus *ubi32_pci_scan_bus(int nr, struct pci_sys_data *sys)
30616 +{
30617 +       return pci_scan_bus(sys->busnr, &ubi32_pci_ops, sys);
30618 +}
30619 +
30620 +#define UBI32_PCI_MEM_BASE PCI_DEV_REG_BASE
30621 +#define UBI32_PCI_MEM_LEN  0x80000000
30622 +
30623 +#define UBI32_PCI_IO_BASE 0x0
30624 +#define UBI32_PCI_IO_END  0x0
30625 +
30626 +static struct resource ubi32_pci_mem = {
30627 +       .name   = "PCI memory space",
30628 +       .start  = UBI32_PCI_MEM_BASE,
30629 +       .end    = UBI32_PCI_MEM_BASE + UBI32_PCI_MEM_LEN - 1,
30630 +       .flags  = IORESOURCE_MEM,
30631 +};
30632 +
30633 +static struct resource ubi32_pci_io = {
30634 +       .name   = "PCI IO space",
30635 +       .start  = UBI32_PCI_IO_BASE,
30636 +       .end    = UBI32_PCI_IO_END,
30637 +       .flags  = IORESOURCE_IO,
30638 +};
30639 +
30640 +static int __init ubi32_pci_setup(int nr, struct pci_sys_data *sys)
30641 +{
30642 +       if (nr > 0)
30643 +               return 0;
30644 +
30645 +       request_resource(&iomem_resource, &ubi32_pci_mem);
30646 +       request_resource(&ioport_resource, &ubi32_pci_io);
30647 +
30648 +       sys->resource[0] = &ubi32_pci_io;
30649 +       sys->resource[1] = &ubi32_pci_mem;
30650 +       sys->resource[2] = NULL;
30651 +
30652 +       return 1;
30653 +}
30654 +
30655 +static void __init ubi32_pci_preinit(void)
30656 +{
30657 +}
30658 +
30659 +static int __init ubi32_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30660 +{
30661 +       return pci_node->dn.recvirq;
30662 +}
30663 +
30664 +struct hw_pci ubi32_pci __initdata = {
30665 +       .nr_controllers = 1,
30666 +       .preinit        = ubi32_pci_preinit,
30667 +       .setup          = ubi32_pci_setup,
30668 +       .scan           = ubi32_pci_scan_bus,
30669 +       .map_irq        = ubi32_pci_map_irq,
30670 +};
30671 +
30672 +static int __init ubi32_pci_init(void)
30673 +{
30674 +       pci_node = (struct pci_devnode *)devtree_find_node("pci");
30675 +       if (pci_node == NULL) {
30676 +               printk(KERN_WARNING "PCI init failed\n");
30677 +               return -ENOSYS;
30678 +       }
30679 +       pci_common_init(&ubi32_pci);
30680 +       return 0;
30681 +}
30682 +
30683 +subsys_initcall(ubi32_pci_init);
30684 +
30685 +/*
30686 + * workaround for dual PCI card interrupt
30687 + */
30688 +#define PCI_COMMON_INT_BIT (1 << 19)
30689 +void ubi32_pci_int_wr(void)
30690 +{
30691 +       volatile unsigned int pci_int_line;
30692 +       pci_int_line = UBICOM32_IO_PORT(RB)->gpio_in;
30693 +       if (!(pci_int_line & PCI_COMMON_INT_BIT))
30694 +       {
30695 +               ubicom32_set_interrupt(pci_node->dn.recvirq);
30696 +       }
30697 +}
30698 +EXPORT_SYMBOL(ubi32_pci_int_wr);
30699 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/plio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/plio.c
30700 --- linux-2.6.30.10/arch/ubicom32/mach-common/plio.c    1970-01-01 02:00:00.000000000 +0200
30701 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/plio.c        2009-12-11 11:45:11.000000000 +0200
30702 @@ -0,0 +1,92 @@
30703 +/*
30704 + * plio.c
30705 + *     PLIO state machine support functions
30706 + *
30707 + * Copyright Â© 2009 Ubicom Inc. <www.ubicom.com>.  All rights reserved.
30708 + *
30709 + * This file is part of the Ubicom32 Linux Kernel Port.
30710 + *
30711 + * The Ubicom32 Linux Kernel Port is free software: you can
30712 + * redistribute it and/or modify it under the terms of the GNU General
30713 + * Public License as published by the Free Software Foundation, either
30714 + * version 2 of the License, or (at your option) any later version.
30715 + *
30716 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30717 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30718 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30719 + * See the GNU General Public License for more details.
30720 + *
30721 + * You should have received a copy of the GNU General Public License
30722 + * along with the Ubicom32 Linux Kernel Port.  If not,
30723 + * see <http://www.gnu.org/licenses/>.
30724 + */
30725 +
30726 +#include <linux/types.h>
30727 +#include <linux/string.h>
30728 +#include <linux/delay.h>
30729 +#include <asm/plio.h>
30730 +
30731 +/*
30732 + * plio_reset
30733 + *     Select and reset PLIO function
30734 + */
30735 +static void plio_reset(const plio_fctl_t *plio_fctl) {
30736 +       plio_io_function_t plio_function = {
30737 +               .fn_sel         = PLIO_FN,
30738 +               .fn_reset       = 1,
30739 +       };
30740 +
30741 +       /*
30742 +        * enable extension port
30743 +        */
30744 +       PEXT_NBR->function = plio_function;
30745 +
30746 +       /*
30747 +        * program clock dividers
30748 +        */
30749 +       PLIO_NBR->fctl2 = plio_fctl->fctl2;
30750 +
30751 +       /*
30752 +        * select plio function and assert function reset
30753 +        */
30754 +       plio_function.br_thread = thread_get_self();
30755 +       plio_function.fn_reset = 1;
30756 +       PLIO_NBR->function = plio_function;
30757 +
30758 +       /*
30759 +        * program plio controls
30760 +        */
30761 +       PLIO_NBR->fctl0 = plio_fctl->fctl0;
30762 +       PLIO_NBR->fctl1 = plio_fctl->fctl1;
30763 +
30764 +       /*
30765 +        * deassert function reset
30766 +        */
30767 +       plio_function.fn_reset = 0;
30768 +       PLIO_NBR->function = plio_function;
30769 +}
30770 +
30771 +/*
30772 + * plio_init
30773 + *     configure and initialize PLIO.
30774 + */
30775 +void plio_init(const plio_fctl_t *plio_fctl, const plio_config_t *plio_config, const plio_sram_t plio_sram_cfg[], int sram_cfg_size){
30776 +       /*
30777 +        * first reset to start plio clock
30778 +        */
30779 +       plio_reset(plio_fctl);
30780 +
30781 +       udelay(1);
30782 +
30783 +       /*
30784 +        * configure pfsm
30785 +        */
30786 +       PLIO_NBR->fctl0.pfsm_prog = 1;
30787 +       memcpy(PLIO_BR->pfsm_sram, plio_sram_cfg, sram_cfg_size);
30788 +       PLIO_NBR->fctl0.pfsm_prog = 0;
30789 +
30790 +       /*
30791 +        * program rest of plio
30792 +        */
30793 +       memcpy(&PLIO_BR->config, plio_config, sizeof(plio_config_t));
30794 +}
30795 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/profile.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.c
30796 --- linux-2.6.30.10/arch/ubicom32/mach-common/profile.c 1970-01-01 02:00:00.000000000 +0200
30797 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.c     2009-12-11 11:45:11.000000000 +0200
30798 @@ -0,0 +1,549 @@
30799 +/*
30800 + * arch/ubicom32/mach-common/profile.c
30801 + *   Implementation for Ubicom32 Profiler
30802 + *
30803 + * (C) Copyright 2009, Ubicom, Inc.
30804 + *
30805 + * This file is part of the Ubicom32 Linux Kernel Port.
30806 + *
30807 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
30808 + * it and/or modify it under the terms of the GNU General Public License
30809 + * as published by the Free Software Foundation, either version 2 of the
30810 + * License, or (at your option) any later version.
30811 + *
30812 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30813 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30814 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
30815 + * the GNU General Public License for more details.
30816 + *
30817 + * You should have received a copy of the GNU General Public License
30818 + * along with the Ubicom32 Linux Kernel Port.  If not,
30819 + * see <http://www.gnu.org/licenses/>.
30820 + */
30821 +
30822 +#include <linux/platform_device.h>
30823 +#include "profile.h"
30824 +#include <linux/seq_file.h>
30825 +#include <linux/proc_fs.h>
30826 +#include <linux/mm.h>
30827 +#include <linux/mmzone.h>
30828 +#include <linux/fs.h>
30829 +#include <linux/page-flags.h>
30830 +#include <asm/uaccess.h>
30831 +#include <asm/devtree.h>
30832 +#include <asm/profilesample.h>
30833 +#include <asm/memory_map.h>
30834 +#include <asm/page.h>
30835 +#include <asm/ip5000.h>
30836 +
30837 +/*
30838 + * spacs for all memory blocks so we can hold locks for short time when walking tables
30839 + */
30840 +#define PROFILE_NUM_MAPS 5000
30841 +static struct profile_map profile_pm[PROFILE_NUM_MAPS];
30842 +
30843 +static struct profilenode *node = NULL;
30844 +static int profile_first_packet = 1;
30845 +
30846 +static int profile_open(struct inode *inode, struct file *filp)
30847 +{
30848 +       if (!node) {
30849 +               return -ENOENT;
30850 +       }
30851 +       node->busy = 1;
30852 +       if (!node->enabled) {
30853 +               node->enabled = 1;
30854 +               node->busy = 0;
30855 +               profile_first_packet = 1;
30856 +               return 0;
30857 +       }
30858 +       node->busy = 0;
30859 +       return -EBUSY;
30860 +}
30861 +
30862 +static int profile_sequence_num;
30863 +
30864 +/*
30865 + * make a packet full of sample data
30866 + */
30867 +static int profile_make_data_packet(char *buf, int count)
30868 +{
30869 +       int samples;            /* number of samples requested */
30870 +       int i;
30871 +       struct profile_header ph;
30872 +       char *ptr;
30873 +
30874 +       if (count < sizeof(struct profile_header) + sizeof(struct profile_sample)) {
30875 +               return -EINVAL;
30876 +       }
30877 +
30878 +       /*
30879 +        * fill in the packet header
30880 +        */
30881 +       memset(&ph, 0, sizeof(struct profile_header));
30882 +       ph.magic = PROF_MAGIC + PROFILE_VERSION;
30883 +       ph.header_size = sizeof(struct profile_header);
30884 +       ph.clocks = node->clocks;
30885 +       for (i = 0; i < PROFILE_MAX_THREADS; ++i) {
30886 +               ph.instruction_count[i] = node->inst_count[i];
30887 +       }
30888 +       ph.profile_instructions = 0;
30889 +       ph.enabled = node->enabled_threads;
30890 +       ph.hrt = node->hrt;
30891 +       ph.high = 0;
30892 +       ph.profiler_thread = node->profiler_thread;
30893 +       ph.clock_freq = node->clock_freq;
30894 +       ph.seq_num = profile_sequence_num++;
30895 +       ph.cpu_id = node->cpu_id;
30896 +       ph.perf_counters[0] = node->stats[0];
30897 +       ph.perf_counters[1] = node->stats[1];
30898 +       ph.perf_counters[2] = node->stats[2];
30899 +       ph.perf_counters[3] = node->stats[3];
30900 +       ph.ddr_freq = node->ddr_freq;
30901 +
30902 +       ptr = buf + sizeof(struct profile_header);
30903 +
30904 +       samples = (count - sizeof(struct profile_header)) / sizeof(struct profile_sample);
30905 +       for (i = 0; i < samples && node->count; ++i) {
30906 +               if (copy_to_user(ptr, &node->samples[node->tail], sizeof(struct profile_sample)) != 0) {
30907 +                       return -EFAULT;
30908 +               }
30909 +               node->count--;
30910 +               node->tail++;
30911 +               if (node->tail >= node->max_samples) {
30912 +                       node->tail = 0;
30913 +               }
30914 +               ptr += sizeof(struct profile_sample);
30915 +       }
30916 +       ph.sample_count = i;
30917 +       if (copy_to_user(buf, &ph, sizeof(struct profile_header)) != 0) {
30918 +               return -EFAULT;
30919 +       }
30920 +       if (ph.sample_count == 0)
30921 +               return 0;
30922 +       else
30923 +               return sizeof(struct profile_header) + ph.sample_count * sizeof(struct profile_sample);
30924 +}
30925 +
30926 +static void profile_get_memory_stats(unsigned int *total_free, unsigned int *max_free)
30927 +{
30928 +       struct list_head *p;
30929 +       struct zone *zone;
30930 +       unsigned int size;
30931 +
30932 +       *total_free = 0;
30933 +       *max_free = 0;
30934 +
30935 +       /*
30936 +        * get all the free regions.  In each zone, the array of free_area lists contains the first page of each frame of size 1 << order
30937 +        */
30938 +       for_each_zone(zone) {
30939 +               unsigned long order, flags, i;
30940 +
30941 +               if (!populated_zone(zone))
30942 +                       continue;
30943 +
30944 +               if (!is_normal(zone))
30945 +                       continue;
30946 +
30947 +               spin_lock_irqsave(&zone->lock, flags);
30948 +               for_each_migratetype_order(order, i) {
30949 +                       size = ((1 << order) << PAGE_SHIFT) >> 10;
30950 +                       list_for_each(p, &(zone->free_area[order].free_list[i])) {
30951 +                               if (size > *max_free) {
30952 +                                       *max_free = size;
30953 +                               }
30954 +                               *total_free += size;
30955 +                       }
30956 +               }
30957 +               spin_unlock_irqrestore(&zone->lock, flags);
30958 +       }
30959 +}
30960 +
30961 +struct profile_counter_pkt profile_builtin_stats[] =
30962 +{
30963 +       {
30964 +       "Free memory(KB)", 0
30965 +       },
30966 +       {
30967 +       "Max free Block(KB)", 0
30968 +       }
30969 +};
30970 +
30971 +/*
30972 + * make a packet full of performance counters
30973 + */
30974 +static char prof_pkt[PROFILE_MAX_PACKET_SIZE];
30975 +static int profile_make_stats_packet(char *buf, int count)
30976 +{
30977 +       char *ptr = prof_pkt;
30978 +       struct profile_header_counters hdr;
30979 +       int stat_count = 0;
30980 +       int i;
30981 +       unsigned int total_free, max_free;
30982 +       int builtin_count = sizeof(profile_builtin_stats) / sizeof(struct profile_counter_pkt);
30983 +
30984 +       if (count > PROFILE_MAX_PACKET_SIZE) {
30985 +               count = PROFILE_MAX_PACKET_SIZE;
30986 +       }
30987 +       stat_count = (count - sizeof(struct profile_header_counters)) / sizeof (struct profile_counter_pkt);
30988 +       stat_count -= builtin_count;
30989 +
30990 +       if (stat_count <= 0) {
30991 +               return 0;
30992 +       }
30993 +
30994 +       if (stat_count > node->num_counters) {
30995 +               stat_count = node->num_counters;
30996 +       }
30997 +
30998 +       hdr.magic = PROF_MAGIC_COUNTERS;
30999 +       hdr.ultra_sample_time = node->clocks;
31000 +       hdr.ultra_count = stat_count;
31001 +       hdr.linux_sample_time = UBICOM32_IO_TIMER->sysval;
31002 +       hdr.linux_count = builtin_count;
31003 +       memcpy(ptr, (void *)&hdr, sizeof(struct profile_header_counters));
31004 +       ptr += sizeof(struct profile_header_counters);
31005 +
31006 +
31007 +       for (i = 0; i < stat_count; ++i) {
31008 +               memcpy(ptr, (void *)(&(node->counters[i])), sizeof(struct profile_counter));
31009 +               ptr += sizeof(struct profile_counter);
31010 +       }
31011 +
31012 +       /*
31013 +        * built in statistics
31014 +        */
31015 +       profile_get_memory_stats(&total_free, &max_free);
31016 +       profile_builtin_stats[0].value = total_free;
31017 +       profile_builtin_stats[1].value = max_free;
31018 +       memcpy(ptr, (void *)profile_builtin_stats, sizeof(profile_builtin_stats));
31019 +       ptr += sizeof(profile_builtin_stats);
31020 +
31021 +       if (copy_to_user(buf, prof_pkt, ptr - prof_pkt) != 0) {
31022 +               return -EFAULT;
31023 +       }
31024 +       return ptr - prof_pkt;
31025 +}
31026 +
31027 +/*
31028 + * return a udp packet ready to send to the profiler tool
31029 + * when there are no packets left to make, return 0
31030 + */
31031 +static int profile_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
31032 +{
31033 +       int result = 0;
31034 +       if (!node) {
31035 +               return -ENOENT;
31036 +       }
31037 +       node->busy = 1;
31038 +       if (!node->enabled) {
31039 +               node->busy = 0;
31040 +               return -EPERM;
31041 +       }
31042 +       if (!node->samples) {
31043 +               node->busy = 0;
31044 +               return -ENOMEM;
31045 +       }
31046 +
31047 +       if (profile_first_packet) {
31048 +               result = profile_make_stats_packet(buf, count);
31049 +               profile_first_packet = 0;
31050 +       }
31051 +       if (result == 0) {
31052 +               result = profile_make_data_packet(buf, count);
31053 +               if (result == 0) {
31054 +                       profile_first_packet = 1;
31055 +               }
31056 +       }
31057 +       node->busy = 0;
31058 +       return result;
31059 +
31060 +}
31061 +
31062 +static int profile_release(struct inode *inode, struct file *filp)
31063 +{
31064 +       if (!node) {
31065 +               return -ENOENT;
31066 +       }
31067 +       node->busy = 1;
31068 +       if (node->enabled) {
31069 +               node->enabled = 0;
31070 +               node->count = 0;
31071 +               node->tail = node->head;
31072 +               node->busy = 0;
31073 +               return 0;
31074 +       }
31075 +       node->busy = 0;
31076 +       profile_first_packet = 1;
31077 +       return -EBADF;
31078 +}
31079 +
31080 +static const struct file_operations profile_fops = {
31081 +       .open           = profile_open,
31082 +       .read           = profile_read,
31083 +       .release        = profile_release,
31084 +};
31085 +
31086 +static int page_aligned(void *x)
31087 +{
31088 +       return !((unsigned int)x & ((1 << PAGE_SHIFT) - 1));
31089 +}
31090 +
31091 +static int profile_maps_open(struct inode *inode, struct file *filp)
31092 +{
31093 +       struct rb_node *rb;
31094 +       int num = 0;
31095 +       int slab_start;
31096 +       struct vm_area_struct *vma;
31097 +       int type = PROFILE_MAP_TYPE_UNKNOWN;
31098 +       int flags, i;
31099 +       struct list_head *p;
31100 +       struct zone *zone;
31101 +
31102 +       /*
31103 +        * get the slab data (first so dups will show up as vmas)
31104 +        */
31105 +       slab_start = num;
31106 +       num += kmem_cache_block_info("size-512", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31107 +       num += kmem_cache_block_info("size-1024", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31108 +       num += kmem_cache_block_info("size-2048", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31109 +       num += kmem_cache_block_info("size-4096", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31110 +       num += kmem_cache_block_info("size-8192", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31111 +
31112 +       for (i = slab_start; i < num; ++i) {
31113 +               profile_pm[i].type_size |= PROFILE_MAP_TYPE_SMALL << PROFILE_MAP_TYPE_SHIFT;
31114 +       }
31115 +
31116 +       slab_start = num;
31117 +       num += kmem_cache_block_info("dentry", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31118 +       num += kmem_cache_block_info("inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31119 +       num += kmem_cache_block_info("sysfs_dir_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31120 +       num += kmem_cache_block_info("proc_inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31121 +
31122 +       for (i = slab_start; i < num; ++i) {
31123 +               profile_pm[i].type_size |= PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT;
31124 +       }
31125 +
31126 +       /*
31127 +        * get all the vma regions (allocated by mmap, most likely
31128 +        */
31129 +#if 0
31130 +       down_read(&nommu_vma_sem);
31131 +       for (rb = rb_first(&nommu_vma_tree); rb && num < PROFILE_NUM_MAPS; rb = rb_next(rb)) {
31132 +               vma = rb_entry(rb, struct vm_area_struct, vm_rb);
31133 +               profile_pm[num].start = (vma->vm_start - SDRAMSTART) >> PAGE_SHIFT;
31134 +               profile_pm[num].type_size = (vma->vm_end - vma->vm_start + (1 << PAGE_SHIFT) - 1) >> PAGE_SHIFT;
31135 +               flags = vma->vm_flags & 0xf;
31136 +               if (flags == (VM_READ | VM_EXEC)) {
31137 +                       type = PROFILE_MAP_TYPE_TEXT;
31138 +               } else if (flags == (VM_READ | VM_WRITE | VM_EXEC)) {
31139 +                       type = PROFILE_MAP_TYPE_STACK;
31140 +               } else if (flags == (VM_READ | VM_WRITE)) {
31141 +                       type = PROFILE_MAP_TYPE_APP_DATA;
31142 +               }
31143 +               profile_pm[num].type_size |= type << PROFILE_MAP_TYPE_SHIFT;
31144 +               num++;
31145 +       }
31146 +       up_read(&nommu_vma_sem);
31147 +       if (rb) {
31148 +               return -ENOMEM;
31149 +       }
31150 +#endif
31151 +
31152 +       /*
31153 +        * get all the free regions.  In each zone, the array of free_area lists contains the first page of each frame of size 1 << order
31154 +        */
31155 +       for_each_zone(zone) {
31156 +               unsigned long order, flags, i;
31157 +               struct page *page;
31158 +
31159 +               if (!populated_zone(zone))
31160 +                       continue;
31161 +
31162 +               if (!is_normal(zone))
31163 +                       continue;
31164 +
31165 +               spin_lock_irqsave(&zone->lock, flags);
31166 +               for_each_migratetype_order(order, i) {
31167 +                       list_for_each(p, &(zone->free_area[order].free_list[i])) {
31168 +                               page = list_entry(p, struct page, lru);
31169 +                               profile_pm[num].start = ((page_to_phys(page) - SDRAMSTART) >> PAGE_SHIFT) - 0x40;
31170 +                               profile_pm[num].type_size = (PROFILE_MAP_TYPE_FREE << PROFILE_MAP_TYPE_SHIFT) | order;
31171 +                               num++;
31172 +                               if (num >= PROFILE_NUM_MAPS) {
31173 +                                       spin_unlock_irqrestore(&zone->lock, flags);
31174 +                                       return -ENOMEM;
31175 +                               }
31176 +                       }
31177 +               }
31178 +               spin_unlock_irqrestore(&zone->lock, flags);
31179 +       }
31180 +
31181 +       /*
31182 +        * get the filesystem inodes
31183 +        */
31184 +       list_for_each(p, &(super_blocks)) {
31185 +               struct super_block *sb;
31186 +               struct list_head *q;
31187 +               if (num >= PROFILE_NUM_MAPS)
31188 +                       break;
31189 +               sb = list_entry(p, struct super_block, s_list);
31190 +               if (page_aligned(sb)) {
31191 +                       profile_pm[num].start = ((unsigned int)sb - SDRAMSTART) >> PAGE_SHIFT;
31192 +                       profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
31193 +                       num++;
31194 +               }
31195 +               list_for_each(q, &(sb->s_inodes)) {
31196 +                       struct inode *in;
31197 +                       if (num >= PROFILE_NUM_MAPS)
31198 +                               break;
31199 +                       in = list_entry(q, struct inode, i_sb_list);
31200 +                       if (page_aligned(in)) {
31201 +                               profile_pm[num].start = ((unsigned int)in - SDRAMSTART) >> PAGE_SHIFT;
31202 +                               profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
31203 +                               num++;
31204 +                       }
31205 +               }
31206 +       }
31207 +
31208 +       /*
31209 +        * get the buffer cache pages
31210 +        */
31211 +       for (i = 0; i < num_physpages && num < PROFILE_NUM_MAPS; ++i) {
31212 +               if ((mem_map + i)->flags & (1 << PG_lru)) {
31213 +                       int start = i;
31214 +                       while ((mem_map + i)->flags & (1 << PG_lru) && i < num_physpages)
31215 +                               i++;
31216 +                       profile_pm[num].start = start;
31217 +                       profile_pm[num].type_size = (i - start) | (PROFILE_MAP_TYPE_CACHE << PROFILE_MAP_TYPE_SHIFT);
31218 +                       num++;
31219 +               }
31220 +       }
31221 +
31222 +       filp->private_data = (void *)num;
31223 +       return 0;
31224 +}
31225 +
31226 +/*
31227 + * return one packet of map data, or 0 if all maps have been returned already
31228 + */
31229 +static int profile_maps_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
31230 +{
31231 +       struct profile_header_maps header;
31232 +       char *p = buf + sizeof(header);
31233 +       int total = (int)filp->private_data;
31234 +
31235 +       header.count = (count - sizeof(header)) / sizeof(struct profile_map);
31236 +       if (header.count > PROFILE_MAX_MAPS) {
31237 +               header.count = PROFILE_MAX_MAPS;;
31238 +       }
31239 +       if (header.count > total - *f_pos) {
31240 +               header.count = total - *f_pos;
31241 +       }
31242 +
31243 +       if (header.count == 0) {
31244 +               return 0;
31245 +       }
31246 +
31247 +       header.magic = PROF_MAGIC_MAPS;
31248 +       header.page_shift = PAGE_SHIFT;
31249 +
31250 +       if (copy_to_user(buf, &header, sizeof(header)) != 0) {
31251 +               return -EFAULT;
31252 +       }
31253 +       if (copy_to_user(p, (void *)&profile_pm[*f_pos], sizeof(struct profile_map) * header.count) != 0) {
31254 +               return -EFAULT;
31255 +       }
31256 +       *f_pos += header.count;
31257 +
31258 +       return sizeof(header) + sizeof(struct profile_map) * header.count;
31259 +}
31260 +
31261 +static int profile_maps_release(struct inode *inode, struct file *filp)
31262 +{
31263 +       return 0;
31264 +}
31265 +
31266 +static const struct file_operations profile_maps_fops = {
31267 +       .open           = profile_maps_open,
31268 +       .read           = profile_maps_read,
31269 +       .release        = profile_maps_release,
31270 +};
31271 +
31272 +static int profile_rate_show(struct seq_file *m, void *v)
31273 +{
31274 +       if (node) {
31275 +               seq_printf(m, "%d samples per second.  %d virtual counters.\n", node->rate, node->num_counters);
31276 +       } else {
31277 +               seq_printf(m, "Profiler is not initialized.\n");
31278 +       }
31279 +       return 0;
31280 +}
31281 +
31282 +static int profile_rate_open(struct inode *inode, struct file *filp)
31283 +{
31284 +       return single_open(filp, profile_rate_show, NULL);
31285 +}
31286 +
31287 +static int profile_rate_write(struct file *filp, const char *buf, size_t len, loff_t *off)
31288 +{
31289 +       *off = 0;
31290 +       return 0;
31291 +}
31292 +
31293 +static const struct file_operations profile_rate_fops = {
31294 +       .open           = profile_rate_open,
31295 +       .read           = seq_read,
31296 +       .llseek         = seq_lseek,
31297 +       .release        = single_release,
31298 +       .write          = profile_rate_write,
31299 +};
31300 +
31301 +int ubi32_profile_init_module(void)
31302 +{
31303 +       struct proc_dir_entry *pdir;
31304 +
31305 +       /*
31306 +        * find the device
31307 +        */
31308 +       node = (struct profilenode *)devtree_find_node("profiler");
31309 +       if (!node) {
31310 +               printk(KERN_INFO "Profiler does not exist.\n");
31311 +               return -ENODEV;
31312 +       }
31313 +
31314 +       /*
31315 +        * allocate the sample buffer
31316 +        */
31317 +       node->max_samples = PROFILE_MAX_SAMPLES;
31318 +       node->samples = kmalloc(node->max_samples * sizeof(struct profile_sample), GFP_KERNEL);
31319 +       if (!node->samples) {
31320 +               printk(KERN_INFO "Profiler sample buffer kmalloc failed.\n");
31321 +               return -ENOMEM;
31322 +       }
31323 +
31324 +       /*
31325 +        * connect to the file system
31326 +        */
31327 +       pdir = proc_mkdir("profile", NULL);
31328 +       if (!pdir) {
31329 +               return -ENOMEM;
31330 +       }
31331 +       if (!proc_create("data", 0, pdir, &profile_fops)) {
31332 +               return -ENOMEM;
31333 +       }
31334 +       if (!proc_create("rate", 0, pdir, &profile_rate_fops)) {
31335 +               return -ENOMEM;
31336 +       }
31337 +       if (!proc_create("maps", 0, pdir, &profile_maps_fops)) {
31338 +               return -ENOMEM;
31339 +       }
31340 +       return 0;
31341 +}
31342 +
31343 +
31344 +module_init(ubi32_profile_init_module);
31345 +
31346 +MODULE_AUTHOR("David Fotland");
31347 +MODULE_LICENSE("GPL");
31348 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/profile.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.h
31349 --- linux-2.6.30.10/arch/ubicom32/mach-common/profile.h 1970-01-01 02:00:00.000000000 +0200
31350 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.h     2009-12-11 11:45:11.000000000 +0200
31351 @@ -0,0 +1,82 @@
31352 +/*
31353 + * arch/ubicom32/mach-common/profile.h
31354 + *   Private data for the profile module
31355 + *
31356 + * (C) Copyright 2009, Ubicom, Inc.
31357 + *
31358 + * This file is part of the Ubicom32 Linux Kernel Port.
31359 + *
31360 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31361 + * it and/or modify it under the terms of the GNU General Public License
31362 + * as published by the Free Software Foundation, either version 2 of the
31363 + * License, or (at your option) any later version.
31364 + *
31365 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31366 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31367 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31368 + * the GNU General Public License for more details.
31369 + *
31370 + * You should have received a copy of the GNU General Public License
31371 + * along with the Ubicom32 Linux Kernel Port.  If not,
31372 + * see <http://www.gnu.org/licenses/>.
31373 + *
31374 + * Ubicom32 implementation derived from (with many thanks):
31375 + *   arch/m68knommu
31376 + *   arch/blackfin
31377 + *   arch/parisc
31378 + */
31379 +
31380 +#include <linux/types.h>
31381 +#include <asm/devtree.h>
31382 +#include "profpkt.h"
31383 +
31384 +#ifndef _PROFILE_H_
31385 +#define _PROFILE_H_
31386 +
31387 +#define PROFILE_MAX_THREADS 16
31388 +#define PROFILE_MAX_SAMPLES 1024
31389 +
31390 +struct profile_sample;
31391 +struct oprofile_sample;
31392 +
31393 +/*
31394 + * values chosen so all counter values fit in a single UDP packet
31395 + */
31396 +#define PROFILE_NODE_MAX_COUNTERS 32
31397 +
31398 +struct profile_counter {
31399 +       char name[PROFILE_COUNTER_NAME_LENGTH];
31400 +       unsigned int value;
31401 +};
31402 +
31403 +struct profilenode {
31404 +       struct devtree_node dn;
31405 +       volatile u32_t enabled;                 /* Is the profiler enabled to take samples? */
31406 +       volatile u32_t busy;                    /* set when the samples are being read by the driver */
31407 +       volatile u32_t rate;                    /* What is the sampling rate? */
31408 +       volatile u32_t enabled_threads;         /* which threads were enabled at the last sample time */
31409 +       volatile u32_t hrt;                     /* HRT threads */
31410 +       volatile u32_t profiler_thread;         /* thread running the profile sampler */
31411 +       volatile u32_t clocks;                  /* system clock timer at last sample */
31412 +       volatile u32_t clock_freq;              /* clock frequency in Hz */
31413 +       volatile u32_t ddr_freq;                /* memory frequency */
31414 +       volatile u32_t cpu_id;                  /* chip_id register */
31415 +       volatile u32_t inst_count[PROFILE_MAX_THREADS];         /* sampled instruction counts at most recent sample */
31416 +       volatile u32_t stats[4];                                /* contents of the cache statistics counters */
31417 +       volatile u16_t head;                    /* sample taker puts samples here */
31418 +       volatile u16_t tail;                    /* packet filler takes samples here */
31419 +       volatile u16_t count;                   /* number of valid samples */
31420 +       volatile u16_t max_samples;             /* how many samples can be in the samples array */
31421 +       struct profile_sample *samples;         /* samples array allocated by the linux driver */
31422 +       volatile u32_t num_counters;            /* how many registered performance counters */
31423 +       volatile struct profile_counter counters[PROFILE_NODE_MAX_COUNTERS];
31424 +
31425 +       /* unimplemented interface for future oprofile work */
31426 +       volatile u16_t oprofile_head;           /* sample taker puts samples here */
31427 +       volatile u16_t oprofile_tail;           /* packet filler takes samples here */
31428 +       volatile u16_t oprofile_count;          /* how many oprofile sampels are are in use */
31429 +       volatile u16_t oprofile_max_samples;    /* samples array size for oprofile samples */
31430 +       struct oprofile_sample *oprofile_samples;       /* oprofile sample buffer */
31431 +};
31432 +
31433 +#endif
31434 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/profpkt.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profpkt.h
31435 --- linux-2.6.30.10/arch/ubicom32/mach-common/profpkt.h 1970-01-01 02:00:00.000000000 +0200
31436 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profpkt.h     2009-12-11 11:45:11.000000000 +0200
31437 @@ -0,0 +1,158 @@
31438 +
31439 +/*
31440 + * arch/ubicom32/mach-common/profpkt.c
31441 + *   Ubicom32 Profiler packet formats for communication between the linux proc driver and the profiler display tool
31442 + *
31443 + * (C) Copyright 2009, Ubicom, Inc.
31444 + *
31445 + * This file is part of the Ubicom32 Linux Kernel Port.
31446 + *
31447 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31448 + * it and/or modify it under the terms of the GNU General Public License
31449 + * as published by the Free Software Foundation, either version 2 of the
31450 + * License, or (at your option) any later version.
31451 + *
31452 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31453 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31454 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31455 + * the GNU General Public License for more details.
31456 + *
31457 + * You should have received a copy of the GNU General Public License
31458 + * along with the Ubicom32 Linux Kernel Port.  If not,
31459 + * see <http://www.gnu.org/licenses/>.
31460 + */
31461 +
31462 +#define PROFILE_PORT 51080
31463 +#define PROFILE_POSIX_NAME_LENGTH 32
31464 +
31465 +/*
31466 + * profile UDP packet format for communicating between ip3k and host
31467 + *
31468 + * every packet starts with a header, followed by samples.
31469 + * samples are only taken for non-hrt threads that are
31470 + * active
31471 + */
31472 +#define PROF_MAGIC 0x3ea0
31473 +#define PROF_MAGIC_COUNTERS 0x9ea0
31474 +#define PROF_MAGIC_MAPS 0xaea0
31475 +
31476 +/*
31477 + * Versions (31 max):
31478 + * 1 to 4 were before 6.0 release,  development versions
31479 + * 5 was forward compatible version, shipped with 6.0 and 6.1
31480 + * 6 adds heap packets, and clock_freq to header, shipped with 6.2
31481 + * 7 adds a sequence numbers to check for dropped packets, shipped with 6.3.5
31482 + * 8 adds mqueue timing information, shipped with 6.3.5
31483 + * 9 adds sdram heap size information, shipped with 6.4
31484 + * 10 adds heapmem heap callers and long latency stack traces.  shipped with 6.4
31485 + * 11 adds support for Mars (IP5K).  shipped with 6.10
31486 + * 12 adds more support for Mars.  Shipped with 7.0
31487 + * 13 adds per sample latency measurement.  Shipped with 7.2
31488 + * 14 changes the heap format and adds a string packet.  Shipped with 7.4
31489 + * 15 adds dsr stats and posix.  shipped with 7.6
31490 + * 16 corrects maximum packet count for Ares.  ships with 7.9
31491 + * 17 adds a5 register value to sample
31492 + */
31493 +
31494 +#define PROFILE_VERSION 17
31495 +#define PROFILE_MAX_PACKET_SIZE 1440
31496 +
31497 +#define PROFILE_MAX_THREADS 16
31498 +
31499 +/*
31500 + * each packet starts with a profile_header, then sample_count samples
31501 + * samples are gprof samples of pc, the return address, condition codes, and
31502 + * active threads
31503 + */
31504 +struct profile_header {
31505 +       u16_t magic;                    /* magic number and version */
31506 +       u8_t header_size;               /* number of bytes in profile header */
31507 +       u8_t sample_count;              /* number of samples in the packet */
31508 +       u32_t clocks;                   /* clock counter value */
31509 +       u32_t instruction_count[PROFILE_MAX_THREADS];
31510 +                                       /* instructions executed per thread */
31511 +       u32_t profile_instructions;     /* instructions executed by profiler mainline */
31512 +       u16_t enabled;                  /* which threads are enabled */
31513 +       u16_t hrt;                      /* which threads are hrt */
31514 +       u16_t high;                     /* which threads are high priority */
31515 +       u16_t profiler_thread;          /* which thread runs the profiler */
31516 +       u32_t heap_free;                /* current free on-cihp heap space in bytes */
31517 +       u32_t heap_low_water;           /* on-chip heap low water mark */
31518 +       u32_t netpage_free;             /* number of free on-chip net pages */
31519 +       u32_t netpage_low_water;        /* low water mark on free on-chip netpages */
31520 +       u32_t min_sp[PROFILE_MAX_THREADS];
31521 +                                       /* stack pointer values per thread */
31522 +       u32_t clock_freq;               /* clock frequency (Hz) of system being analyzed */
31523 +       u32_t seq_num;                  /* to detect dropped profiler packets */
31524 +       u32_t timing_sequence;          /* sample number since boot */
31525 +       u32_t timing_interval;          /* second per sample timing interval */
31526 +       u32_t timing_worst_time;        /* duration of longest finction called, in core clocks */
31527 +       u32_t timing_function;          /* address of longest function */
31528 +       u32_t timing_average;           /* average time of all functions in last interval */
31529 +       u32_t timing_count;             /* number of functions called in last interval */
31530 +       u32_t extheap_free;             /* current free extmem heap space in bytes */
31531 +       u32_t extheap_low_water;        /* extmem heap low water mark */
31532 +       u32_t cpu_id;                   /* CHIP_ID register contents */
31533 +       u32_t perf_counters[4];         /* contents of the CPU performance counters */
31534 +       u8_t perf_config[4];            /* what is being counted */
31535 +       u32_t ddr_freq;                 /* DDR clock frequency */
31536 +       u32_t extnetpage_free;          /* number of free off chip net pages */
31537 +       u32_t extnetpage_low_water;     /* low water mark on off-chip free netpages */
31538 +       u32_t dsr_max_latency;          /* max time to process a dsr interrupt, in clocks, since last packet */
31539 +       u32_t dsr_ave_latency;          /* average dsr latency over last DSR_STATS_RECENT_COUNT interrupts */
31540 +       u32_t dsr_count;                /* number of dsr interrupts since last packet */
31541 +};
31542 +
31543 +struct profile_header_counters {
31544 +       u16_t magic;
31545 +       u16_t ultra_count;              /* how many ultra counters follow this */
31546 +       u32_t ultra_sample_time;        /* in chip clocks */
31547 +       u32_t linux_count;              /* how many linux counters follow this */
31548 +       u32_t linux_sample_time;
31549 +};
31550 +
31551 +/*
31552 + * values chosen so all counter values fit in a single 1400 byte UDP packet
31553 + */
31554 +#define PROFILE_COUNTER_NAME_LENGTH 20
31555 +#define PROFILE_MAX_COUNTERS ((PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_counters)) / (PROFILE_COUNTER_NAME_LENGTH + 4))
31556 +
31557 +struct profile_counter_pkt {
31558 +       char name[PROFILE_COUNTER_NAME_LENGTH];
31559 +       unsigned int value;
31560 +};
31561 +
31562 +/*
31563 + * send memory maps from linux to profiler tool
31564 + */
31565 +
31566 +struct profile_header_maps {
31567 +       u16_t magic;
31568 +       u16_t count;
31569 +       u32_t page_shift;
31570 +};
31571 +
31572 +#define PROFILE_MAP_NUM_TYPES 32
31573 +
31574 +/* types 0-15: size field is order.  True size is 2^order */
31575 +#define PROFILE_MAP_TYPE_UNKNOWN 0
31576 +#define PROFILE_MAP_TYPE_FREE 1
31577 +#define PROFILE_MAP_TYPE_SMALL 2
31578 +#define PROFILE_MAP_TYPE_FS 3
31579 +/* types 16-31: size field is pages.  True size is (1 << PAGE_SHIFT) * size */
31580 +#define PROFILE_MAP_SIZE_TYPE 16
31581 +#define PROFILE_MAP_TYPE_TEXT 16
31582 +#define PROFILE_MAP_TYPE_STACK 17
31583 +#define PROFILE_MAP_TYPE_APP_DATA 18
31584 +#define PROFILE_MAP_TYPE_CACHE 19
31585 +#define PROFILE_MAP_RESERVED 24
31586 +
31587 +#define PROFILE_MAP_TYPE_SHIFT 11
31588 +#define PROFILE_MAP_SIZE_MASK 0x7ff
31589 +
31590 +struct profile_map {
31591 +       u16_t start;            /* start page number of segment, relative to start of DRAM */
31592 +       u16_t type_size;        /* type (4 bits) of the segment and size in pages (12 bits) */
31593 +};
31594 +
31595 +#define PROFILE_MAX_MAPS (PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_maps)) / sizeof(struct profile_map)
31596 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ring_tio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ring_tio.c
31597 --- linux-2.6.30.10/arch/ubicom32/mach-common/ring_tio.c        1970-01-01 02:00:00.000000000 +0200
31598 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ring_tio.c    2009-12-11 11:45:11.000000000 +0200
31599 @@ -0,0 +1,123 @@
31600 +/*
31601 + * arch/ubicom32/mach-common/ring_tio.c
31602 + *   Generic initialization for UIO Ubicom32 Ring
31603 + *
31604 + * (C) Copyright 2009, Ubicom, Inc.
31605 + *
31606 + * This file is part of the Ubicom32 Linux Kernel Port.
31607 + *
31608 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31609 + * it and/or modify it under the terms of the GNU General Public License
31610 + * as published by the Free Software Foundation, either version 2 of the
31611 + * License, or (at your option) any later version.
31612 + *
31613 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31614 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31615 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31616 + * the GNU General Public License for more details.
31617 + *
31618 + * You should have received a copy of the GNU General Public License
31619 + * along with the Ubicom32 Linux Kernel Port.  If not,
31620 + * see <http://www.gnu.org/licenses/>.
31621 + */
31622 +
31623 +#include <linux/platform_device.h>
31624 +#include <linux/types.h>
31625 +
31626 +#include <asm/devtree.h>
31627 +#include <asm/ring_tio.h>
31628 +
31629 +static const char *ring_tio_driver_name = "uio_ubicom32ring";
31630 +
31631 +/*
31632 + * The number of ring_tio's currently allocated, used for .id
31633 + */
31634 +static int __initdata ring_tio_count;
31635 +
31636 +/*
31637 + * The maximum number of resources that the ring_tio will have.
31638 + * Currently 3, a register space, and up to 2 interrupts.
31639 + */
31640 +#define RING_TIO_MAX_RESOURCES 3
31641 +
31642 +/*
31643 + * ring_tio_init
31644 + *     Checks the device tree and instantiates the driver if found
31645 + */
31646 +void __init ring_tio_init(const char *node_name)
31647 +{
31648 +       struct platform_device *pdev;
31649 +       struct resource *res;
31650 +       int resource_idx = 0;
31651 +       struct ring_tio_node *ring_node;
31652 +
31653 +       /*
31654 +        * Check the device tree for the ring_tio
31655 +        */
31656 +       ring_node = (struct ring_tio_node *)devtree_find_node(node_name);
31657 +       if (!ring_node) {
31658 +               printk(KERN_WARNING "Ring TIO '%s' not found\n", node_name);
31659 +               return;
31660 +       }
31661 +
31662 +       if (ring_node->version != RING_TIO_NODE_VERSION) {
31663 +               printk(KERN_WARNING "ring_tio not compatible\n");
31664 +               return;
31665 +       }
31666 +
31667 +       /*
31668 +        * Dynamically create the platform_device structure and resources
31669 +        */
31670 +       pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
31671 +       if (!pdev) {
31672 +               printk(KERN_WARNING "ring_tio could not alloc pdev\n");
31673 +               return;
31674 +       }
31675 +
31676 +       res = kzalloc(sizeof(struct resource) * RING_TIO_MAX_RESOURCES,
31677 +                       GFP_KERNEL);
31678 +       if (!res) {
31679 +               kfree(pdev);
31680 +               printk(KERN_WARNING "ring_tio could not alloc res\n");
31681 +               return;
31682 +       }
31683 +
31684 +       pdev->name = ring_tio_driver_name;
31685 +       pdev->id = ring_tio_count++;
31686 +       pdev->resource = res;
31687 +
31688 +       /*
31689 +        * Fill in the resources and platform data from devtree information
31690 +        */
31691 +       res[resource_idx].start = (u32_t)(ring_node->regs);
31692 +       res[resource_idx].end = (u32_t)(ring_node->regs);
31693 +       res[resource_idx].flags = IORESOURCE_MEM;
31694 +       resource_idx++;
31695 +
31696 +       if (ring_node->dn.sendirq != 0xFF) {
31697 +               res[resource_idx].start = ring_node->dn.sendirq;
31698 +               res[resource_idx].flags = IORESOURCE_IRQ;
31699 +               resource_idx++;
31700 +       }
31701 +
31702 +       if (ring_node->dn.recvirq != 0xFF) {
31703 +               res[resource_idx].start = ring_node->dn.recvirq;
31704 +               res[resource_idx].flags = IORESOURCE_IRQ;
31705 +               resource_idx++;
31706 +       }
31707 +       pdev->num_resources = resource_idx;
31708 +
31709 +       printk(KERN_INFO "RingTIO.%d '%s' found irq=%d/%d regs=%p pdev=%p/%p\n",
31710 +               ring_tio_count - 1, node_name, ring_node->dn.sendirq,
31711 +               ring_node->dn.recvirq, ring_node->regs, pdev, res);
31712 +
31713 +       /*
31714 +        * Try to get the device registered
31715 +        */
31716 +       pdev->dev.platform_data = (void *)node_name;
31717 +       if (platform_device_register(pdev) < 0) {
31718 +               printk(KERN_WARNING "Ring failed to register\n");
31719 +               kfree(pdev);
31720 +               kfree(res);
31721 +       }
31722 +}
31723 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x.c
31724 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x.c  1970-01-01 02:00:00.000000000 +0200
31725 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x.c      2009-12-11 11:45:11.000000000 +0200
31726 @@ -0,0 +1,1195 @@
31727 +/*
31728 + * arch/ubicom32/mach-common/switch-bcm539x.c
31729 + *   BCM539X switch driver, SPI mode
31730 + *
31731 + * (C) Copyright 2009, Ubicom, Inc.
31732 + *
31733 + * This file is part of the Ubicom32 Linux Kernel Port.
31734 + *
31735 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31736 + * it and/or modify it under the terms of the GNU General Public License
31737 + * as published by the Free Software Foundation, either version 2 of the
31738 + * License, or (at your option) any later version.
31739 + *
31740 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31741 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31742 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31743 + * the GNU General Public License for more details.
31744 + *
31745 + * You should have received a copy of the GNU General Public License
31746 + * along with the Ubicom32 Linux Kernel Port.  If not,
31747 + * see <http://www.gnu.org/licenses/>.
31748 + *
31749 + * Ubicom32 implementation derived from (with many thanks):
31750 + *   arch/m68knommu
31751 + *   arch/blackfin
31752 + *   arch/parisc
31753 + */
31754 +
31755 +#include <linux/platform_device.h>
31756 +#include <linux/spi/spi.h>
31757 +#include <linux/gpio.h>
31758 +#include <linux/delay.h>
31759 +#include <linux/mii.h>
31760 +
31761 +#include <asm/switch-dev.h>
31762 +#include <asm/ubicom32-spi-gpio.h>
31763 +#include "switch-core.h"
31764 +#include "switch-bcm539x-reg.h"
31765 +
31766 +#define DRIVER_NAME "bcm539x-spi"
31767 +#define DRIVER_VERSION "1.0"
31768 +
31769 +#undef BCM539X_DEBUG
31770 +#define BCM539X_SPI_RETRIES    100
31771 +
31772 +struct bcm539x_data {
31773 +       struct switch_device                    *switch_dev;
31774 +
31775 +       /*
31776 +        * Our private data
31777 +        */
31778 +       struct spi_device                       *spi;
31779 +       struct switch_core_platform_data        *pdata;
31780 +
31781 +       /*
31782 +        * Last page we accessed
31783 +        */
31784 +       u8_t                                    last_page;
31785 +
31786 +       /*
31787 +        * 539x Device ID
31788 +        */
31789 +       u8_t                                    device_id;
31790 +};
31791 +
31792 +/*
31793 + * bcm539x_wait_status
31794 + *     Waits for the specified bit in the status register to be set/cleared.
31795 + */
31796 +static int bcm539x_wait_status(struct bcm539x_data *bd, u8_t mask, int set)
31797 +{
31798 +       u8_t txbuf[2];
31799 +       u8_t rxbuf;
31800 +       int i;
31801 +       int ret;
31802 +
31803 +       txbuf[0] = BCM539X_CMD_READ;
31804 +       txbuf[1] = BCM539X_GLOBAL_SPI_STATUS;
31805 +       for (i = 0; i < BCM539X_SPI_RETRIES; i++) {
31806 +               ret = spi_write_then_read(bd->spi, txbuf, 2, &rxbuf, 1);
31807 +               rxbuf &= mask;
31808 +               if ((set && rxbuf) || (!set && !rxbuf)) {
31809 +                       return 0;
31810 +               }
31811 +               udelay(1);
31812 +       }
31813 +
31814 +       return -EIO;
31815 +}
31816 +
31817 +/*
31818 + * bcm539x_set_page
31819 + *     Sets the register page for access (only if necessary)
31820 + */
31821 +static int bcm539x_set_page(struct bcm539x_data *bd, u8_t page)
31822 +{
31823 +       u8_t txbuf[3];
31824 +
31825 +       if (page == bd->last_page) {
31826 +               return 0;
31827 +       }
31828 +
31829 +       bd->last_page = page;
31830 +
31831 +       txbuf[0] = BCM539X_CMD_WRITE;
31832 +       txbuf[1] = BCM539X_GLOBAL_PAGE;
31833 +       txbuf[2] = page;
31834 +
31835 +       return spi_write(bd->spi, txbuf, 3);
31836 +}
31837 +
31838 +/*
31839 + * bcm539x_write_bytes
31840 + *     Writes a number of bytes to a given page and register
31841 + */
31842 +static int bcm539x_write_bytes(struct bcm539x_data *bd, u8_t page,
31843 +                              u8_t reg, void *buf, u8_t len)
31844 +{
31845 +       int ret;
31846 +       u8_t *txbuf;
31847 +
31848 +       txbuf = kmalloc(2 + len, GFP_KERNEL);
31849 +       if (!txbuf) {
31850 +               return -ENOMEM;
31851 +       }
31852 +
31853 +       /*
31854 +        * Make sure the chip has finished processing our previous request
31855 +        */
31856 +       ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31857 +       if (ret) {
31858 +               goto done;
31859 +       }
31860 +
31861 +       /*
31862 +        * Set the page
31863 +        */
31864 +       ret = bcm539x_set_page(bd, page);
31865 +       if (ret) {
31866 +               goto done;
31867 +       }
31868 +
31869 +       /*
31870 +        * Read the data
31871 +        */
31872 +       txbuf[0] = BCM539X_CMD_WRITE;
31873 +       txbuf[1] = reg;
31874 +       memcpy(&txbuf[2], buf, len);
31875 +
31876 +#ifdef BCM539X_DEBUG
31877 +       {
31878 +               int i;
31879 +               printk("write page %02x reg %02x len=%d buf=", page, reg, len);
31880 +               for (i = 0; i < len + 2; i++) {
31881 +                       printk("%02x ", txbuf[i]);
31882 +               }
31883 +               printk("\n");
31884 +       }
31885 +#endif
31886 +
31887 +       ret = spi_write(bd->spi, txbuf, 2 + len);
31888 +
31889 +done:
31890 +       kfree(txbuf);
31891 +       return ret;
31892 +}
31893 +
31894 +/*
31895 + * bcm539x_write_32
31896 + *     Writes 32 bits of data to the given page and register
31897 + */
31898 +static inline int bcm539x_write_32(struct bcm539x_data *bd, u8_t page,
31899 +                                  u8_t reg, u32_t data)
31900 +{
31901 +       data = cpu_to_le32(data);
31902 +       return bcm539x_write_bytes(bd, page, reg, &data, 4);
31903 +}
31904 +
31905 +/*
31906 + * bcm539x_write_16
31907 + *     Writes 16 bits of data to the given page and register
31908 + */
31909 +static inline int bcm539x_write_16(struct bcm539x_data *bd, u8_t page,
31910 +                                  u8_t reg, u16_t data)
31911 +{
31912 +       data = cpu_to_le16(data);
31913 +       return bcm539x_write_bytes(bd, page, reg, &data, 2);
31914 +}
31915 +
31916 +/*
31917 + * bcm539x_write_8
31918 + *     Writes 8 bits of data to the given page and register
31919 + */
31920 +static inline int bcm539x_write_8(struct bcm539x_data *bd, u8_t page,
31921 +                                 u8_t reg, u8_t data)
31922 +{
31923 +       return bcm539x_write_bytes(bd, page, reg, &data, 1);
31924 +}
31925 +
31926 +/*
31927 + * bcm539x_read_bytes
31928 + *     Reads a number of bytes from a given page and register
31929 + */
31930 +static int bcm539x_read_bytes(struct bcm539x_data *bd, u8_t page,
31931 +                             u8_t reg, void *buf, u8_t len)
31932 +{
31933 +       u8_t txbuf[2];
31934 +       int ret;
31935 +
31936 +       /*
31937 +        * (1) Make sure the chip has finished processing our previous request
31938 +        */
31939 +       ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31940 +       if (ret) {
31941 +               return ret;
31942 +       }
31943 +
31944 +       /*
31945 +        * (2) Set the page
31946 +        */
31947 +       ret = bcm539x_set_page(bd, page);
31948 +       if (ret) {
31949 +               return ret;
31950 +       }
31951 +
31952 +       /*
31953 +        * (3) Kick off the register read
31954 +        */
31955 +       txbuf[0] = BCM539X_CMD_READ;
31956 +       txbuf[1] = reg;
31957 +       ret = spi_write_then_read(bd->spi, txbuf, 2, txbuf, 1);
31958 +       if (ret) {
31959 +               return ret;
31960 +       }
31961 +
31962 +       /*
31963 +        * (4) Wait for RACK
31964 +        */
31965 +       ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_RACK, 1);
31966 +       if (ret) {
31967 +               return ret;
31968 +       }
31969 +
31970 +       /*
31971 +        * (5) Read the data
31972 +        */
31973 +       txbuf[0] = BCM539X_CMD_READ;
31974 +       txbuf[1] = BCM539X_GLOBAL_SPI_DATA0;
31975 +
31976 +       ret = spi_write_then_read(bd->spi, txbuf, 2, buf, len);
31977 +
31978 +#ifdef BCM539X_DEBUG
31979 +       {
31980 +               int i;
31981 +               printk("read page %02x reg %02x len=%d rxbuf=",
31982 +                      page, reg, len);
31983 +               for (i = 0; i < len; i++) {
31984 +                       printk("%02x ", ((u8_t *)buf)[i]);
31985 +               }
31986 +               printk("\n");
31987 +       }
31988 +#endif
31989 +
31990 +       return ret;
31991 +}
31992 +
31993 +/*
31994 + * bcm539x_read_32
31995 + *     Reads an 32 bit number from a given page and register
31996 + */
31997 +static int bcm539x_read_32(struct bcm539x_data *bd, u8_t page,
31998 +                          u8_t reg, u32_t *buf)
31999 +{
32000 +       int ret = bcm539x_read_bytes(bd, page, reg, buf, 4);
32001 +       *buf = le32_to_cpu(*buf);
32002 +       return ret;
32003 +}
32004 +
32005 +/*
32006 + * bcm539x_read_16
32007 + *     Reads an 16 bit number from a given page and register
32008 + */
32009 +static int bcm539x_read_16(struct bcm539x_data *bd, u8_t page,
32010 +                          u8_t reg, u16_t *buf)
32011 +{
32012 +       int ret = bcm539x_read_bytes(bd, page, reg, buf, 2);
32013 +       *buf = le16_to_cpu(*buf);
32014 +       return ret;
32015 +}
32016 +
32017 +/*
32018 + * bcm539x_read_8
32019 + *     Reads an 8 bit number from a given page and register
32020 + */
32021 +static int bcm539x_read_8(struct bcm539x_data *bd, u8_t page,
32022 +                         u8_t reg, u8_t *buf)
32023 +{
32024 +       return bcm539x_read_bytes(bd, page, reg, buf, 1);
32025 +}
32026 +
32027 +/*
32028 + * bcm539x_set_mode
32029 + */
32030 +static int bcm539x_set_mode(struct bcm539x_data *bd, int state)
32031 +{
32032 +       u8_t buf;
32033 +       int ret;
32034 +
32035 +       ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &buf);
32036 +       if (ret) {
32037 +               return ret;
32038 +       }
32039 +
32040 +       buf &= ~(1 << 1);
32041 +       buf |= state ? (1 << 1) : 0;
32042 +
32043 +       ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, buf);
32044 +       return ret;
32045 +}
32046 +
32047 +/*
32048 + * bcm539x_handle_reset
32049 + */
32050 +static int bcm539x_handle_reset(struct switch_device *dev, char *buf, int inst)
32051 +{
32052 +       struct bcm539x_data *bd =
32053 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32054 +       int ret;
32055 +
32056 +       ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST,
32057 +                             (1 << 7) | (1 << 4));
32058 +       if (ret) {
32059 +               return ret;
32060 +       }
32061 +
32062 +       udelay(20);
32063 +
32064 +       ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST, 0);
32065 +       return ret;
32066 +}
32067 +
32068 +/*
32069 + * bcm539x_handle_vlan_ports_read
32070 + */
32071 +static int bcm539x_handle_vlan_ports_read(struct switch_device *dev,
32072 +                                         char *buf, int inst)
32073 +{
32074 +       struct bcm539x_data *bd =
32075 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32076 +       int j;
32077 +       int len = 0;
32078 +       u8_t rxbuf8;
32079 +       u32_t rxbuf32;
32080 +       int ret;
32081 +
32082 +       ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
32083 +       if (ret) {
32084 +               return ret;
32085 +       }
32086 +
32087 +       ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32088 +                             (1 << 7) | 1);
32089 +       if (ret) {
32090 +               return ret;
32091 +       }
32092 +
32093 +       /*
32094 +        * Wait for completion
32095 +        */
32096 +       for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32097 +               ret = bcm539x_read_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32098 +                                    &rxbuf8);
32099 +               if (ret) {
32100 +                       return ret;
32101 +               }
32102 +               if (!(rxbuf8 & (1 << 7))) {
32103 +                       break;
32104 +               }
32105 +       }
32106 +
32107 +       if (j == BCM539X_SPI_RETRIES) {
32108 +               return -EIO;
32109 +       }
32110 +
32111 +       /*
32112 +        * Read the table entry
32113 +        */
32114 +       ret = bcm539x_read_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, &rxbuf32);
32115 +       if (ret) {
32116 +               return ret;
32117 +       }
32118 +
32119 +       for (j = 0; j < 9; j++) {
32120 +               if (rxbuf32 & (1 << j)) {
32121 +                       u16_t rxbuf16;
32122 +                       len += sprintf(buf + len, "%d", j);
32123 +                       if (rxbuf32 & (1 << (j + 9))) {
32124 +                               buf[len++] = 'u';
32125 +                       } else {
32126 +                               buf[len++] = 't';
32127 +                       }
32128 +                       ret = bcm539x_read_16(bd, PAGE_VLAN,
32129 +                                             REG_VLAN_PTAG0 + (j << 1),
32130 +                                             &rxbuf16);
32131 +                       if (ret) {
32132 +                               return ret;
32133 +                       }
32134 +                       if (rxbuf16 == inst) {
32135 +                               buf[len++] = '*';
32136 +                       }
32137 +                       buf[len++] = '\t';
32138 +               }
32139 +       }
32140 +
32141 +       len += sprintf(buf + len, "\n");
32142 +       buf[len] = '\0';
32143 +
32144 +       return len;
32145 +}
32146 +
32147 +/*
32148 + * bcm539x_handle_vlan_ports_write
32149 + */
32150 +static int bcm539x_handle_vlan_ports_write(struct switch_device *dev,
32151 +                                          char *buf, int inst)
32152 +{
32153 +       struct bcm539x_data *bd =
32154 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32155 +       int j;
32156 +       u32_t untag;
32157 +       u32_t ports;
32158 +       u32_t def;
32159 +
32160 +       u8_t rxbuf8;
32161 +       u16_t rxbuf16;
32162 +       int ret;
32163 +
32164 +       switch_parse_vlan_ports(dev, buf, &untag, &ports, &def);
32165 +
32166 +#ifdef BCM539X_DEBUG
32167 +       printk(KERN_DEBUG "'%s' inst=%d untag=%08x ports=%08x def=%08x\n",
32168 +               buf, inst, untag, ports, def);
32169 +#endif
32170 +
32171 +       if (!ports) {
32172 +               return 0;
32173 +       }
32174 +
32175 +       /*
32176 +        * Change default vlan tag
32177 +        */
32178 +       for (j = 0; j < 9; j++) {
32179 +               if ((untag | def) & (1 << j)) {
32180 +                       ret = bcm539x_write_16(bd, PAGE_VLAN,
32181 +                                              REG_VLAN_PTAG0 + (j << 1),
32182 +                                              inst);
32183 +                       if (ret) {
32184 +                               return ret;
32185 +                       }
32186 +                       continue;
32187 +               }
32188 +
32189 +               if (!(dev->port_mask[0] & (1 << j))) {
32190 +                       continue;
32191 +               }
32192 +
32193 +               /*
32194 +                * Remove any ports which are not listed anymore as members of
32195 +                * this vlan
32196 +                */
32197 +               ret = bcm539x_read_16(bd, PAGE_VLAN,
32198 +                                     REG_VLAN_PTAG0 + (j << 1), &rxbuf16);
32199 +               if (ret) {
32200 +                       return ret;
32201 +               }
32202 +               if (rxbuf16 == inst) {
32203 +                       ret = bcm539x_write_16(bd, PAGE_VLAN,
32204 +                                              REG_VLAN_PTAG0 + (j << 1), 0);
32205 +                       if (ret) {
32206 +                               return ret;
32207 +                       }
32208 +               }
32209 +       }
32210 +
32211 +       /*
32212 +        * Write the VLAN table
32213 +        */
32214 +       ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
32215 +       if (ret) {
32216 +               return ret;
32217 +       }
32218 +
32219 +       ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395,
32220 +                              (untag << 9) | ports);
32221 +       if (ret) {
32222 +               return ret;
32223 +       }
32224 +
32225 +       ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32226 +                             (1 << 7) | 0);
32227 +       if (ret) {
32228 +               return ret;
32229 +       }
32230 +
32231 +       /*
32232 +        * Wait for completion
32233 +        */
32234 +       for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32235 +               ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32236 +                                        &rxbuf8, 1);
32237 +               if (ret) {
32238 +                       return ret;
32239 +               }
32240 +               if (!(rxbuf8 & (1 << 7))) {
32241 +                       break;
32242 +               }
32243 +       }
32244 +
32245 +       return (j < BCM539X_SPI_RETRIES) ? 0 : -EIO;
32246 +}
32247 +
32248 +/*
32249 + * Handlers for <this_driver>/vlan/<vlan_id>
32250 + */
32251 +static const struct switch_handler bcm539x_switch_handlers_vlan_dir[] = {
32252 +       {
32253 +               .name   = "ports",
32254 +               .read   = bcm539x_handle_vlan_ports_read,
32255 +               .write  = bcm539x_handle_vlan_ports_write,
32256 +       },
32257 +       {
32258 +       },
32259 +};
32260 +
32261 +/*
32262 + * bcm539x_handle_vlan_delete_write
32263 + */
32264 +static int bcm539x_handle_vlan_delete_write(struct switch_device *dev,
32265 +                                           char *buf, int inst)
32266 +{
32267 +       struct bcm539x_data *bd =
32268 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32269 +       int vid;
32270 +       u8_t rxbuf8;
32271 +       u32_t txbuf;
32272 +       int j;
32273 +       int ret;
32274 +
32275 +       vid = simple_strtoul(buf, NULL, 0);
32276 +       if (!vid) {
32277 +               return -EINVAL;
32278 +       }
32279 +
32280 +       /*
32281 +        * Disable this VLAN
32282 +        *
32283 +        * Go through the port-based vlan registers and clear the appropriate
32284 +        * ones out
32285 +        */
32286 +       for (j = 0; j < 9; j++) {
32287 +               u16_t rxbuf16;
32288 +               ret = bcm539x_read_16(bd, PAGE_VLAN, REG_VLAN_PTAG0 + (j << 1),
32289 +                                     &rxbuf16);
32290 +               if (ret) {
32291 +                       return ret;
32292 +               }
32293 +               if (rxbuf16 == vid) {
32294 +                       txbuf = 0;
32295 +                       ret = bcm539x_write_16(bd, PAGE_VLAN,
32296 +                                              REG_VLAN_PTAG0 + (j << 1),
32297 +                                              txbuf);
32298 +                       if (ret) {
32299 +                               return ret;
32300 +                       }
32301 +               }
32302 +       }
32303 +
32304 +       /*
32305 +        * Write the VLAN table
32306 +        */
32307 +       txbuf = vid;
32308 +       ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, txbuf);
32309 +       if (ret) {
32310 +               return ret;
32311 +       }
32312 +
32313 +       txbuf = 0;
32314 +       ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, txbuf);
32315 +       if (ret) {
32316 +               return ret;
32317 +       }
32318 +
32319 +       txbuf = (1 << 7) | (0);
32320 +       ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395, txbuf);
32321 +       if (ret) {
32322 +               return ret;
32323 +       }
32324 +
32325 +       /*
32326 +        * Wait for completion
32327 +        */
32328 +       for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32329 +               ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32330 +                                        &rxbuf8, 1);
32331 +               if (ret) {
32332 +                       return ret;
32333 +               }
32334 +               if (!(rxbuf8 & (1 << 7))) {
32335 +                       break;
32336 +               }
32337 +       }
32338 +
32339 +       if (j == BCM539X_SPI_RETRIES) {
32340 +               return -EIO;
32341 +       }
32342 +
32343 +       return switch_remove_vlan_dir(dev, vid);
32344 +}
32345 +
32346 +/*
32347 + * bcm539x_handle_vlan_create_write
32348 + */
32349 +static int bcm539x_handle_vlan_create_write(struct switch_device *dev,
32350 +                                           char *buf, int inst)
32351 +{
32352 +       int vid;
32353 +
32354 +       vid = simple_strtoul(buf, NULL, 0);
32355 +       if (!vid) {
32356 +               return -EINVAL;
32357 +       }
32358 +
32359 +       return switch_create_vlan_dir(dev, vid,
32360 +                                     bcm539x_switch_handlers_vlan_dir);
32361 +}
32362 +
32363 +/*
32364 + * bcm539x_handle_enable_read
32365 + */
32366 +static int bcm539x_handle_enable_read(struct switch_device *dev,
32367 +                                     char *buf, int inst)
32368 +{
32369 +       struct bcm539x_data *bd =
32370 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32371 +       u8_t rxbuf;
32372 +       int ret;
32373 +
32374 +       ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &rxbuf);
32375 +       if (ret) {
32376 +               return ret;
32377 +       }
32378 +       rxbuf = (rxbuf & (1 << 1)) ? 1 : 0;
32379 +
32380 +       return sprintf(buf, "%d\n", rxbuf);
32381 +}
32382 +
32383 +/*
32384 + * bcm539x_handle_enable_write
32385 + */
32386 +static int bcm539x_handle_enable_write(struct switch_device *dev,
32387 +                                      char *buf, int inst)
32388 +{
32389 +       struct bcm539x_data *bd =
32390 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32391 +
32392 +       return bcm539x_set_mode(bd, buf[0] == '1');
32393 +}
32394 +
32395 +/*
32396 + * bcm539x_handle_enable_vlan_read
32397 + */
32398 +static int bcm539x_handle_enable_vlan_read(struct switch_device *dev,
32399 +                                          char *buf, int inst)
32400 +{
32401 +       struct bcm539x_data *bd =
32402 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32403 +       u8_t rxbuf;
32404 +       int ret;
32405 +
32406 +       ret = bcm539x_read_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, &rxbuf);
32407 +       if (ret) {
32408 +               return ret;
32409 +       }
32410 +       rxbuf = (rxbuf & (1 << 7)) ? 1 : 0;
32411 +
32412 +       return sprintf(buf, "%d\n", rxbuf);
32413 +}
32414 +
32415 +/*
32416 + * bcm539x_handle_enable_vlan_write
32417 + */
32418 +static int bcm539x_handle_enable_vlan_write(struct switch_device *dev,
32419 +                                           char *buf, int inst)
32420 +{
32421 +       struct bcm539x_data *bd =
32422 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32423 +       int ret;
32424 +
32425 +       /*
32426 +        * disable 802.1Q VLANs
32427 +        */
32428 +       if (buf[0] != '1') {
32429 +               ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, 0);
32430 +               return ret;
32431 +       }
32432 +
32433 +       /*
32434 +        * enable 802.1Q VLANs
32435 +        *
32436 +        * Enable 802.1Q | IVL learning
32437 +        */
32438 +       ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0,
32439 +                             (1 << 7) | (3 << 5));
32440 +       if (ret) {
32441 +               return ret;
32442 +       }
32443 +
32444 +       /*
32445 +        * RSV multicast fwd | RSV multicast chk
32446 +        */
32447 +       ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL1,
32448 +                             (1 << 2) | (1 << 3));
32449 +       if (ret) {
32450 +               return ret;
32451 +       }
32452 +#if 0
32453 +       /*
32454 +        * Drop invalid VID
32455 +        */
32456 +       ret = bcm539x_write_16(bd, PAGE_VLAN, REG_VLAN_CTRL3, 0x00FF);
32457 +       if (ret) {
32458 +               return ret;
32459 +       }
32460 +#endif
32461 +       return 0;
32462 +}
32463 +
32464 +/*
32465 + * bcm539x_handle_port_enable_read
32466 + */
32467 +static int bcm539x_handle_port_enable_read(struct switch_device *dev,
32468 +                                          char *buf, int inst)
32469 +{
32470 +       return sprintf(buf, "%d\n", 1);
32471 +}
32472 +
32473 +/*
32474 + * bcm539x_handle_port_enable_write
32475 + */
32476 +static int bcm539x_handle_port_enable_write(struct switch_device *dev,
32477 +                                           char *buf, int inst)
32478 +{
32479 +       /*
32480 +        * validate port
32481 +        */
32482 +       if (!(dev->port_mask[0] & (1 << inst))) {
32483 +               return -EIO;
32484 +       }
32485 +
32486 +       if (buf[0] != '1') {
32487 +               printk(KERN_WARNING "switch port[%d] disabling is not supported\n", inst);
32488 +       }
32489 +       return 0;
32490 +}
32491 +
32492 +/*
32493 + * bcm539x_handle_port_state_read
32494 + */
32495 +static int bcm539x_handle_port_state_read(struct switch_device *dev,
32496 +                                          char *buf, int inst)
32497 +{
32498 +       struct bcm539x_data *bd =
32499 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32500 +       int ret;
32501 +       u16_t link;
32502 +
32503 +       /*
32504 +        * validate port
32505 +        */
32506 +       if (!(dev->port_mask[0] & (1 << inst))) {
32507 +               return -EIO;
32508 +       }
32509 +
32510 +       /*
32511 +        * check PHY link state - CPU port (port 8) is always up
32512 +        */
32513 +       ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32514 +       if (ret) {
32515 +               return ret;
32516 +       }
32517 +       link |= (1 << 8);
32518 +
32519 +       return sprintf(buf, "%d\n", (link & (1 << inst)) ? 1 : 0);
32520 +}
32521 +
32522 +/*
32523 + * bcm539x_handle_port_media_read
32524 + */
32525 +static int bcm539x_handle_port_media_read(struct switch_device *dev,
32526 +                                          char *buf, int inst)
32527 +{
32528 +       struct bcm539x_data *bd =
32529 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32530 +       int ret;
32531 +       u16_t link, duplex;
32532 +       u32_t speed;
32533 +
32534 +       /*
32535 +        * validate port
32536 +        */
32537 +       if (!(dev->port_mask[0] & (1 << inst))) {
32538 +               return -EIO;
32539 +       }
32540 +
32541 +       /*
32542 +        * check PHY link state first - CPU port (port 8) is always up
32543 +        */
32544 +       ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32545 +       if (ret) {
32546 +               return ret;
32547 +       }
32548 +       link |= (1 << 8);
32549 +
32550 +       if (!(link & (1 << inst))) {
32551 +               return sprintf(buf, "UNKNOWN\n");
32552 +       }
32553 +
32554 +       /*
32555 +        * get link speeda dn duplex - CPU port (port 8) is 1000/full
32556 +        */
32557 +       ret = bcm539x_read_32(bd, PAGE_STATUS, 4, &speed);
32558 +       if (ret) {
32559 +               return ret;
32560 +       }
32561 +       speed |= (2 << 16);
32562 +       speed = (speed >> (2 * inst)) & 3;
32563 +
32564 +       ret = bcm539x_read_16(bd, PAGE_STATUS, 8, &duplex);
32565 +       if (ret) {
32566 +               return ret;
32567 +       }
32568 +       duplex |= (1 << 8);
32569 +       duplex = (duplex >> inst) & 1;
32570 +
32571 +       return sprintf(buf, "%d%cD\n",
32572 +               (speed == 0) ? 10 : ((speed == 1) ? 100 : 1000),
32573 +               duplex ? 'F' : 'H');
32574 +}
32575 +
32576 +/*
32577 + * bcm539x_handle_port_meida_write
32578 + */
32579 +static int bcm539x_handle_port_meida_write(struct switch_device *dev,
32580 +                                           char *buf, int inst)
32581 +{
32582 +       struct bcm539x_data *bd =
32583 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32584 +       int ret;
32585 +       u16_t ctrl_word, local_cap, local_giga_cap;
32586 +
32587 +       /*
32588 +        * validate port (not for CPU port)
32589 +        */
32590 +       if (!(dev->port_mask[0] & (1 << inst) & ~(1 << 8))) {
32591 +               return -EIO;
32592 +       }
32593 +
32594 +       /*
32595 +        * Get the maximum capability from status
32596 +        *      SPI reg[0x00] = PHY[0x0] --- MII control
32597 +        *      SPI reg[0x08] = PHY[0x4] --- MII local capability
32598 +        *      SPI reg[0x12] = PHY[0x9] --- GMII control
32599 +        */
32600 +       ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), &local_cap);
32601 +       if (ret) {
32602 +               return ret;
32603 +       }
32604 +       ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), &local_giga_cap);
32605 +       if (ret) {
32606 +               return ret;
32607 +       }
32608 +
32609 +       /* Configure to the requested speed */
32610 +       if (strncmp(buf, "1000FD", 6) == 0) {
32611 +               /* speed */
32612 +               local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32613 +               local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32614 +               local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32615 +               /* duplex */
32616 +       } else if (strncmp(buf, "100FD", 5) == 0) {
32617 +               /* speed */
32618 +               local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32619 +               local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32620 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32621 +               /* duplex */
32622 +               local_cap &= ~(ADVERTISE_100HALF);
32623 +       } else if (strncmp(buf, "100HD", 5) == 0) {
32624 +               /* speed */
32625 +               local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32626 +               local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32627 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32628 +               /* duplex */
32629 +               local_cap &= ~(ADVERTISE_100FULL);
32630 +       } else if (strncmp(buf, "10FD", 4) == 0) {
32631 +               /* speed */
32632 +               local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32633 +               local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32634 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32635 +               /* duplex */
32636 +               local_cap &= ~(ADVERTISE_10HALF);
32637 +       } else if (strncmp(buf, "10HD", 4) == 0) {
32638 +               /* speed */
32639 +               local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32640 +               local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32641 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32642 +               /* duplex */
32643 +               local_cap &= ~(ADVERTISE_10FULL);
32644 +       } else if (strncmp(buf, "AUTO", 4) == 0) {
32645 +               /* speed */
32646 +               local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32647 +               local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32648 +               local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32649 +       } else {
32650 +               return -EINVAL;
32651 +       }
32652 +
32653 +       /* Active PHY with the requested speed for auto-negotiation */
32654 +       ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), local_cap);
32655 +       if (ret) {
32656 +               return ret;
32657 +       }
32658 +       ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), local_giga_cap);
32659 +       if (ret) {
32660 +               return ret;
32661 +       }
32662 +
32663 +       ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), &ctrl_word);
32664 +       if (ret) {
32665 +               return ret;
32666 +       }
32667 +       ctrl_word |= (BMCR_ANENABLE | BMCR_ANRESTART);
32668 +       ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), ctrl_word);
32669 +       if (ret) {
32670 +               return ret;
32671 +       }
32672 +
32673 +       return 0;
32674 +}
32675 +
32676 +/*
32677 + * proc_fs entries for this switch
32678 + */
32679 +static const struct switch_handler bcm539x_switch_handlers[] = {
32680 +       {
32681 +               .name   = "enable",
32682 +               .read   = bcm539x_handle_enable_read,
32683 +               .write  = bcm539x_handle_enable_write,
32684 +       },
32685 +       {
32686 +               .name   = "enable_vlan",
32687 +               .read   = bcm539x_handle_enable_vlan_read,
32688 +               .write  = bcm539x_handle_enable_vlan_write,
32689 +       },
32690 +       {
32691 +               .name   = "reset",
32692 +               .write  = bcm539x_handle_reset,
32693 +       },
32694 +       {
32695 +       },
32696 +};
32697 +
32698 +/*
32699 + * Handlers for <this_driver>/vlan
32700 + */
32701 +static const struct switch_handler bcm539x_switch_handlers_vlan[] = {
32702 +       {
32703 +               .name   = "delete",
32704 +               .write  = bcm539x_handle_vlan_delete_write,
32705 +       },
32706 +       {
32707 +               .name   = "create",
32708 +               .write  = bcm539x_handle_vlan_create_write,
32709 +       },
32710 +       {
32711 +       },
32712 +};
32713 +
32714 +/*
32715 + * Handlers for <this_driver>/port/<port number>
32716 + */
32717 +static const struct switch_handler bcm539x_switch_handlers_port[] = {
32718 +       {
32719 +               .name   = "enable",
32720 +               .read   = bcm539x_handle_port_enable_read,
32721 +               .write  = bcm539x_handle_port_enable_write,
32722 +       },
32723 +       {
32724 +               .name   = "state",
32725 +               .read   = bcm539x_handle_port_state_read,
32726 +       },
32727 +       {
32728 +               .name   = "media",
32729 +               .read   = bcm539x_handle_port_media_read,
32730 +               .write  = bcm539x_handle_port_meida_write,
32731 +       },
32732 +       {
32733 +       },
32734 +};
32735 +
32736 +/*
32737 + * bcm539x_probe
32738 + */
32739 +static int __devinit bcm539x_probe(struct spi_device *spi)
32740 +{
32741 +       struct bcm539x_data *bd;
32742 +       struct switch_core_platform_data *pdata;
32743 +       struct switch_device *switch_dev = NULL;
32744 +       int i, ret;
32745 +       u8_t txbuf[2];
32746 +
32747 +       pdata = spi->dev.platform_data;
32748 +       if (!pdata) {
32749 +               return -EINVAL;
32750 +       }
32751 +
32752 +       ret = spi_setup(spi);
32753 +       if (ret < 0) {
32754 +               return ret;
32755 +       }
32756 +
32757 +       /*
32758 +        * Reset the chip if requested
32759 +        */
32760 +       if (pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32761 +               ret = gpio_request(pdata->pin_reset, "switch-bcm539x-reset");
32762 +               if (ret) {
32763 +                       printk(KERN_WARNING "Could not request reset\n");
32764 +                       return -EINVAL;
32765 +               }
32766 +
32767 +               gpio_direction_output(pdata->pin_reset, 0);
32768 +               udelay(10);
32769 +               gpio_set_value(pdata->pin_reset, 1);
32770 +               udelay(20);
32771 +       }
32772 +
32773 +       /*
32774 +        * Allocate our private data structure
32775 +        */
32776 +       bd = kzalloc(sizeof(struct bcm539x_data), GFP_KERNEL);
32777 +       if (!bd) {
32778 +               return -ENOMEM;
32779 +       }
32780 +
32781 +       dev_set_drvdata(&spi->dev, bd);
32782 +       bd->pdata = pdata;
32783 +       bd->spi = spi;
32784 +       bd->last_page = 0xFF;
32785 +
32786 +       /*
32787 +        * First perform SW reset if needed
32788 +        */
32789 +       if (pdata->flags & SWITCH_DEV_FLAG_SW_RESET) {
32790 +               txbuf[0] = (1 << 7) | (1 << 4);
32791 +               ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32792 +                                         REG_CTRL_SRST, txbuf, 1);
32793 +               if (ret) {
32794 +                       goto fail;
32795 +               }
32796 +
32797 +               udelay(20);
32798 +
32799 +               txbuf[0] = 0;
32800 +               ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32801 +                                         REG_CTRL_SRST, txbuf, 1);
32802 +               if (ret) {
32803 +                       goto fail;
32804 +               }
32805 +       }
32806 +
32807 +       /*
32808 +        * See if we can see the chip
32809 +        */
32810 +       for (i = 0; i < 10; i++) {
32811 +               ret = bcm539x_read_bytes(bd, PAGE_MMR, REG_DEVICE_ID,
32812 +                                        &bd->device_id, 1);
32813 +               if (!ret) {
32814 +                       break;
32815 +               }
32816 +       }
32817 +       if (ret) {
32818 +               goto fail;
32819 +       }
32820 +
32821 +       /*
32822 +        * We only support 5395, 5397, 5398
32823 +        */
32824 +       if ((bd->device_id != 0x95) && (bd->device_id != 0x97) &&
32825 +           (bd->device_id != 0x98)) {
32826 +               ret = -ENODEV;
32827 +               goto fail;
32828 +       }
32829 +
32830 +       /*
32831 +        *  Override CPU port config: fixed link @1000 with flow control
32832 +        */
32833 +       ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, txbuf);
32834 +       bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, 0xbb);        // Override IMP port config
32835 +       printk("Broadcom SW CPU port setting: 0x%x -> 0xbb\n", txbuf[0]);
32836 +
32837 +       /*
32838 +        * Setup the switch driver structure
32839 +        */
32840 +       switch_dev = switch_alloc();
32841 +       if (!switch_dev) {
32842 +               ret = -ENOMEM;
32843 +               goto fail;
32844 +       }
32845 +       switch_dev->name = pdata->name;
32846 +
32847 +       switch_dev->ports = (bd->device_id == 0x98) ? 9 : 6;
32848 +       switch_dev->port_mask[0] = (bd->device_id == 0x98) ? 0x1FF : 0x11F;
32849 +       switch_dev->driver_handlers = bcm539x_switch_handlers;
32850 +       switch_dev->reg_handlers = NULL;
32851 +       switch_dev->vlan_handlers = bcm539x_switch_handlers_vlan;
32852 +       switch_dev->port_handlers = bcm539x_switch_handlers_port;
32853 +
32854 +       bd->switch_dev = switch_dev;
32855 +       switch_set_drvdata(switch_dev, (void *)bd);
32856 +
32857 +       ret = switch_register(bd->switch_dev);
32858 +       if (ret < 0) {
32859 +               goto fail;
32860 +       }
32861 +
32862 +       printk(KERN_INFO "bcm53%02x switch chip initialized\n", bd->device_id);
32863 +
32864 +       return ret;
32865 +
32866 +fail:
32867 +       if (switch_dev) {
32868 +               switch_release(switch_dev);
32869 +       }
32870 +       dev_set_drvdata(&spi->dev, NULL);
32871 +       kfree(bd);
32872 +       return ret;
32873 +}
32874 +
32875 +static int __attribute__((unused)) bcm539x_remove(struct spi_device *spi)
32876 +{
32877 +       struct bcm539x_data *bd;
32878 +
32879 +       bd = dev_get_drvdata(&spi->dev);
32880 +
32881 +       if (bd->pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32882 +               gpio_free(bd->pdata->pin_reset);
32883 +       }
32884 +
32885 +       if (bd->switch_dev) {
32886 +               switch_unregister(bd->switch_dev);
32887 +               switch_release(bd->switch_dev);
32888 +       }
32889 +
32890 +       dev_set_drvdata(&spi->dev, NULL);
32891 +
32892 +       kfree(bd);
32893 +
32894 +       return 0;
32895 +}
32896 +
32897 +static struct spi_driver bcm539x_driver = {
32898 +       .driver = {
32899 +               .name           = DRIVER_NAME,
32900 +               .owner          = THIS_MODULE,
32901 +       },
32902 +       .probe          = bcm539x_probe,
32903 +       .remove         = __devexit_p(bcm539x_remove),
32904 +};
32905 +
32906 +static int __init bcm539x_init(void)
32907 +{
32908 +       return spi_register_driver(&bcm539x_driver);
32909 +}
32910 +
32911 +module_init(bcm539x_init);
32912 +
32913 +static void __exit bcm539x_exit(void)
32914 +{
32915 +       spi_unregister_driver(&bcm539x_driver);
32916 +}
32917 +module_exit(bcm539x_exit);
32918 +
32919 +MODULE_AUTHOR("Pat Tjin");
32920 +MODULE_LICENSE("GPL v2");
32921 +MODULE_DESCRIPTION("bcm539x SPI switch chip driver");
32922 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x-reg.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x-reg.h
32923 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x-reg.h      1970-01-01 02:00:00.000000000 +0200
32924 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x-reg.h  2009-12-11 11:45:11.000000000 +0200
32925 @@ -0,0 +1,221 @@
32926 +/*
32927 + * arch/ubicom32/mach-common/switch-bcm539x-reg.h
32928 + *   Broadcom switch definitions for Ubicom32 architecture.
32929 + *
32930 + * (C) Copyright 2009, Ubicom, Inc.
32931 + *
32932 + * This file is part of the Ubicom32 Linux Kernel Port.
32933 + *
32934 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
32935 + * it and/or modify it under the terms of the GNU General Public License
32936 + * as published by the Free Software Foundation, either version 2 of the
32937 + * License, or (at your option) any later version.
32938 + *
32939 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
32940 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
32941 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
32942 + * the GNU General Public License for more details.
32943 + *
32944 + * You should have received a copy of the GNU General Public License
32945 + * along with the Ubicom32 Linux Kernel Port.  If not,
32946 + * see <http://www.gnu.org/licenses/>.
32947 + *
32948 + * Ubicom32 implementation derived from (with many thanks):
32949 + *   arch/m68knommu
32950 + *   arch/blackfin
32951 + *   arch/parisc
32952 + */
32953 +
32954 +/*
32955 + * Broadcom 53xx RoboSwitch device driver.
32956 + *
32957 + * Copyright 2007, Broadcom Corporation
32958 + * All Rights Reserved.
32959 + *
32960 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32961 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
32962 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
32963 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32964 + *
32965 + * $Id$
32966 + */
32967 +
32968 +#ifndef _SWITCH_BCM539X_REG_H_
32969 +#define _SWITCH_BCM539X_REG_H_
32970 +
32971 +#define        BCM539X_CMD_READ                0x60
32972 +#define        BCM539X_CMD_WRITE               0x61
32973 +
32974 +#define        BCM539X_GLOBAL_SPI_DATA0        0xf0
32975 +
32976 +#define        BCM539X_GLOBAL_SPI_STATUS       0xfe
32977 +#define        BCM539X_GLOBAL_SPI_ST_SPIF      (1<<7)
32978 +#define        BCM539X_GLOBAL_SPI_ST_RACK      (1<<5)
32979 +
32980 +#define        BCM539X_GLOBAL_PAGE             0xff
32981 +
32982 +#define PAGE_PORT_TC                   0x00            // Port Traffic Control Register
32983 +
32984 +#define PAGE_QOS_CTL                   0x30            // QoS Global Control Register
32985 +#define PAGE_QOS_TAG                   0x34            // Default IEEE 802.1Q TAG Register
32986 +
32987 +#define PAGE_MII_CTL_PORT0             0x10            // Internal PHY MII Register
32988 +#define PAGE_MII_CTL_PORT1             0x11
32989 +#define PAGE_MII_CTL_PORT2             0x12
32990 +#define PAGE_MII_CTL_PORT3             0x13
32991 +#define PAGE_MII_CTL_PORT4             0x14
32992 +
32993 +#define PAGE_STATUS                    0x01            // Status Register Page
32994 +#define PAGE_RATE_CONTROL              0x41            // Broadcast Storm Suppression Register
32995 +
32996 +#define REG_GRATE_CONTROL              0x00
32997 +
32998 +#define REG_LED_POWER                  0x12
32999 +
33000 +// Ingress Rate Control
33001 +#define REG_IRATE_CONTROLP0            0x10
33002 +#define REG_IRATE_CONTROLP1            0x14
33003 +#define REG_IRATE_CONTROLP2            0x18
33004 +#define REG_IRATE_CONTROLP3            0x1C
33005 +#define REG_IRATE_CONTROLP4            0x20
33006 +#define REG_IRATE_CONTROLP7            0x2C
33007 +#define REG_IRATE_CONTROLPI            0x30
33008 +
33009 +// Egress Rate Control
33010 +#define REG_ERATE_CONTROLP0            0x80
33011 +#define REG_ERATE_CONTROLP1            0x82
33012 +#define REG_ERATE_CONTROLP2            0x84
33013 +#define REG_ERATE_CONTROLP3            0x86
33014 +#define REG_ERATE_CONTROLP4            0x88
33015 +#define REG_ERATE_CONTROLP5            0x8A
33016 +#define REG_ERATE_CONTROLP6            0x8C
33017 +#define REG_ERATE_CONTROLP7            0x8E
33018 +#define REG_ERATE_CONTROLPI            0x90
33019 +
33020 +#define REG_LINK_STATUS                        0x00
33021 +
33022 +#define REG_TC_PORT0                   0x00
33023 +#define REG_TC_PORT1                   0x01
33024 +#define REG_TC_PORT2                   0x02
33025 +#define REG_TC_PORT3                   0x03
33026 +#define REG_TC_PORT4                   0x04
33027 +#define REG_TC_PORT5                   0x05
33028 +
33029 +#define REG_SPEED_CTL                  0x00
33030 +#define REG_SPEED_ADV100               0x08
33031 +#define REG_SPEED_ADV1000              0x12
33032 +
33033 +#define REG_QOS_EN                     0x00
33034 +#define REG_QOS_TAG_PORT1              0x12            // Default IEEE 802.1Q TAG, PORT 1
33035 +#define REG_QOS_TAG_PORT2              0x14            // Default IEEE 802.1Q TAG, PORT 2
33036 +#define REG_QOS_TAG_PORT3              0x16            // Default IEEE 802.1Q TAG, PORT 3
33037 +#define REG_QOS_TAG_PORT4              0x18            // Default IEEE 802.1Q TAG, PORT 4
33038 +#define REG_QOS_PID_PORT1              0x52            // Ingress Port Priority ID MAP, PORT 1
33039 +#define REG_QOS_PID_PORT2              0x54            // Ingress Port Priority ID MAP, PORT 2
33040 +#define REG_QOS_PID_PORT3              0x56            // Ingress Port Priority ID MAP, PORT 3
33041 +#define REG_QOS_PID_PORT4              0x58            // Ingress Port Priority ID MAP, PORT 4
33042 +#define REG_QOS_TXQ_CTL                        0x80            // Tx Queue Control Register
33043 +#define REG_QOS_TXQ_WHTQ0              0x81            // Tx Queue Weight Register Queue 0
33044 +#define REG_QOS_TXQ_WHTQ1              0x82            // Tx Queue Weight Register Queue 1
33045 +#define REG_QOS_TXQ_WHTQ2              0x83            // Tx Queue Weight Register Queue 2
33046 +#define REG_QOS_TXQ_WHTQ3              0x84            // Tx Queue Weight Register Queue 3
33047 +
33048 +#define REG_CTRL_PPSEL                 0x24            /* 5397: Protected port select register */
33049 +
33050 +#define RATE_CONTROL_ENABLED           (1 << 22)
33051 +#define RATE_CONTROL_BSIZE             ((1 << 10) | (1 << 9) | (1 << 8))
33052 +
33053 +#define RATE_CONTROL_HIGH              ((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4))
33054 +#define RATE_CONTROL_HIGH_N            ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
33055 +
33056 +#define RATE_CONTROL_MEDIUM            ((1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
33057 +#define RATE_CONTROL_MEDIUM_N          ~((1 << 7))
33058 +
33059 +#define RATE_CONTROL_NORMAL            ((1 << 5) | (1 << 2) | (1 << 0))
33060 +#define RATE_CONTROL_NORMAL_N          ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1))
33061 +
33062 +#define RATE_CONTROL_LOW               ((1 << 4) | (1 << 3) | (1 << 0))
33063 +#define RATE_CONTROL_LOW_N             ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2) | (1 << 1))
33064 +
33065 +// --- Gemtek, Configure the switch to support Ethernet Port QoS
33066 +
33067 +/* MII access registers */
33068 +#define PSEUDO_PHYAD                   0x1E    /* MII Pseudo PHY address */
33069 +#define REG_MII_PAGE                   0x10    /* MII Page register */
33070 +#define REG_MII_ADDR                   0x11    /* MII Address register */
33071 +#define REG_MII_DATA0                  0x18    /* MII Data register 0 */
33072 +#define REG_MII_DATA1                  0x19    /* MII Data register 1 */
33073 +#define REG_MII_DATA2                  0x1a    /* MII Data register 2 */
33074 +#define REG_MII_DATA3                  0x1b    /* MII Data register 3 */
33075 +
33076 +/* Page numbers */
33077 +#define PAGE_CTRL                      0x00    /* Control page */
33078 +#define PAGE_MMR                       0x02    /* 5397 Management/Mirroring page */
33079 +#define PAGE_VTBL                      0x05    /* ARL/VLAN Table access page */
33080 +#define PAGE_VLAN                      0x34    /* VLAN page */
33081 +
33082 +/* Control page registers */
33083 +#define REG_CTRL_PORT0                 0x00    /* Port 0 traffic control register */
33084 +#define REG_CTRL_PORT1                 0x01    /* Port 1 traffic control register */
33085 +#define REG_CTRL_PORT2                 0x02    /* Port 2 traffic control register */
33086 +#define REG_CTRL_PORT3                 0x03    /* Port 3 traffic control register */
33087 +#define REG_CTRL_PORT4                 0x04    /* Port 4 traffic control register */
33088 +#define REG_CTRL_PORT5                 0x05    /* Port 5 traffic control register */
33089 +#define REG_CTRL_PORT6                 0x06    /* Port 6 traffic control register */
33090 +#define REG_CTRL_PORT7                 0x07    /* Port 7 traffic control register */
33091 +#define REG_CTRL_MODE                  0x0B    /* Switch Mode register */
33092 +#define REG_CTRL_MIIPO                 0x0E    /* 5325: MII Port Override register */
33093 +#define REG_CTRL_SRST                  0x79    /* Software reset control register */
33094 +
33095 +#define REG_DEVICE_ID                  0x30    /* 539x Device id: */
33096 +#define        DEVID5395                       0x95    /*  5395 */
33097 +#define        DEVID5397                       0x97    /*  5397 */
33098 +#define        DEVID5398                       0x98    /*  5398 */
33099 +#define REG_REVISION_ID                        0x40    /* 539x Revision id: */
33100 +
33101 +/* VLAN page registers */
33102 +#define REG_VLAN_CTRL0                 0x00    /* VLAN Control 0 register */
33103 +#define REG_VLAN_CTRL1                 0x01    /* VLAN Control 1 register */
33104 +#define REG_VLAN_CTRL2                 0x02    /* VLAN Control 2 register */
33105 +#define REG_VLAN_CTRL3                 0x03    /* VLAN Control 3 register */
33106 +#define REG_VLAN_CTRL4                 0x04    /* VLAN Control 4 register */
33107 +#define REG_VLAN_CTRL5                 0x05    /* VLAN Control 5 register */
33108 +#define REG_VLAN_ACCESS                        0x06    /* VLAN Table Access register */
33109 +#define REG_VLAN_WRITE                 0x08    /* VLAN Write register */
33110 +#define REG_VLAN_READ                  0x0C    /* VLAN Read register */
33111 +#define REG_VLAN_PTAG0                 0x10    /* VLAN Default Port Tag register - port 0 */
33112 +#define REG_VLAN_PTAG1                 0x12    /* VLAN Default Port Tag register - port 1 */
33113 +#define REG_VLAN_PTAG2                 0x14    /* VLAN Default Port Tag register - port 2 */
33114 +#define REG_VLAN_PTAG3                 0x16    /* VLAN Default Port Tag register - port 3 */
33115 +#define REG_VLAN_PTAG4                 0x18    /* VLAN Default Port Tag register - port 4 */
33116 +#define REG_VLAN_PTAG5                 0x1a    /* VLAN Default Port Tag register - port 5 */
33117 +#define REG_VLAN_PTAG6                 0x1c    /* VLAN Default Port Tag register - port 6 */
33118 +#define REG_VLAN_PTAG7                 0x1e    /* VLAN Default Port Tag register - port 7 */
33119 +#define REG_VLAN_PTAG8                 0x20    /* 539x: VLAN Default Port Tag register - IMP port */
33120 +#define REG_VLAN_PMAP                  0x20    /* 5325: VLAN Priority Re-map register */
33121 +
33122 +/* ARL/VLAN Table Access page registers */
33123 +#define REG_VTBL_CTRL                  0x00    /* ARL Read/Write Control */
33124 +#define REG_VTBL_MINDX                 0x02    /* MAC Address Index */
33125 +#define REG_VTBL_VINDX                 0x08    /* VID Table Index */
33126 +#define REG_VTBL_ARL_E0                        0x10    /* ARL Entry 0 */
33127 +#define REG_VTBL_ARL_E1                        0x18    /* ARL Entry 1 */
33128 +#define REG_VTBL_DAT_E0                        0x18    /* ARL Table Data Entry 0 */
33129 +#define REG_VTBL_SCTRL                 0x20    /* ARL Search Control */
33130 +#define REG_VTBL_SADDR                 0x22    /* ARL Search Address */
33131 +#define REG_VTBL_SRES                  0x24    /* ARL Search Result */
33132 +#define REG_VTBL_SREXT                 0x2c    /* ARL Search Result */
33133 +#define REG_VTBL_VID_E0                        0x30    /* VID Entry 0 */
33134 +#define REG_VTBL_VID_E1                        0x32    /* VID Entry 1 */
33135 +#define REG_VTBL_PREG                  0xFF    /* Page Register */
33136 +#define REG_VTBL_ACCESS                        0x60    /* VLAN table access register */
33137 +#define REG_VTBL_INDX                  0x61    /* VLAN table address index register */
33138 +#define REG_VTBL_ENTRY                 0x63    /* VLAN table entry register */
33139 +#define REG_VTBL_ACCESS_5395           0x80    /* VLAN table access register */
33140 +#define REG_VTBL_INDX_5395             0x81    /* VLAN table address index register */
33141 +#define REG_VTBL_ENTRY_5395            0x83    /* VLAN table entry register */
33142 +
33143 +/* SPI registers */
33144 +#define REG_SPI_PAGE                   0xff    /* SPI Page register */
33145 +
33146 +#endif
33147 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.c
33148 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.c     1970-01-01 02:00:00.000000000 +0200
33149 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.c 2009-12-11 11:45:11.000000000 +0200
33150 @@ -0,0 +1,737 @@
33151 +/*
33152 + * arch/ubicom32/mach-common/switch-core.c
33153 + *   Ubicom32 architecture switch and /proc/switch/... implementation.
33154 + *
33155 + * (C) Copyright 2009, Ubicom, Inc.
33156 + * Copyright (C) 2005 Felix Fietkau <openwrt@nbd.name>
33157 + *
33158 + * This file is part of the Ubicom32 Linux Kernel Port.
33159 + *
33160 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33161 + * it and/or modify it under the terms of the GNU General Public License
33162 + * as published by the Free Software Foundation, either version 2 of the
33163 + * License, or (at your option) any later version.
33164 + *
33165 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33166 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33167 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
33168 + * the GNU General Public License for more details.
33169 + *
33170 + * You should have received a copy of the GNU General Public License
33171 + * along with the Ubicom32 Linux Kernel Port.  If not,
33172 + * see <http://www.gnu.org/licenses/>.
33173 + *
33174 + * Ubicom32 implementation derived from (with many thanks):
33175 + *   arch/m68knommu
33176 + *   arch/blackfin
33177 + *   arch/parisc
33178 + *
33179 + * Basic doc of driver's /proc interface:
33180 + * /proc/switch/<interface>/
33181 + *   registers:              read-only
33182 + *   counters:               read-only
33183 + *   reset:                  write causes hardware reset
33184 + *   enable:                 "0", "1"
33185 + *   enable_vlan:            "0", "1"
33186 + *   port/<port-number>/
33187 + *     enabled:              "0", "1"
33188 + *     link state:           read-only
33189 + *     media:                "AUTO", "1000FD", "100FD", "100HD", "10FD", "10HD"
33190 + *   vlan/<port-number>/
33191 + *     ports: same syntax as for nvram's vlan*ports (eg. "1 2 3 4 5*")
33192 + */
33193 +
33194 +#include <linux/module.h>
33195 +#include <linux/init.h>
33196 +#include <linux/uaccess.h>
33197 +#include <linux/ctype.h>
33198 +#include <linux/proc_fs.h>
33199 +#include <linux/list.h>
33200 +#include <linux/rwsem.h>
33201 +#include <linux/device.h>
33202 +
33203 +#include "switch-core.h"
33204 +
33205 +/*
33206 + * Pointer to the root of our filesystem
33207 + */
33208 +static struct proc_dir_entry *switch_root;
33209 +
33210 +/*
33211 + * Lock used to manage access to the switch list
33212 + */
33213 +DECLARE_RWSEM(switch_list_lock);
33214 +EXPORT_SYMBOL_GPL(switch_list_lock);
33215 +
33216 +/*
33217 + * List of switches we are managing
33218 + */
33219 +LIST_HEAD(switch_list);
33220 +EXPORT_SYMBOL_GPL(switch_list);
33221 +
33222 +/*
33223 + * List of handlers we have
33224 + */
33225 +LIST_HEAD(switch_handler_list);
33226 +EXPORT_SYMBOL_GPL(switch_handler_list);
33227 +
33228 +/*
33229 + * Keep track of all the handlers we added
33230 + */
33231 +struct switch_handler_entry {
33232 +       struct list_head                node;
33233 +       struct proc_dir_entry           *parent;
33234 +       struct switch_device            *dev;
33235 +       const struct switch_handler     *handler;
33236 +       int                             inst;
33237 +};
33238 +
33239 +/*
33240 + * Keep track of all VLAN dirs we created
33241 + */
33242 +struct switch_vlan_entry {
33243 +       struct list_head                node;
33244 +       struct proc_dir_entry           *pde;
33245 +       int                             vlan_id;
33246 +       const struct switch_handler     *handlers;
33247 +};
33248 +
33249 +/*
33250 + * switch_parse_vlan_ports
33251 + *     Parse the vlan properties written to <driver>/vlan/<vlan_id>/ports
33252 + */
33253 +void switch_parse_vlan_ports(struct switch_device *switch_dev,
33254 +                            char *buf, u32_t *untag,
33255 +                            u32_t *ports, u32_t *def)
33256 +{
33257 +       u32_t tag = 0;
33258 +       *untag = 0;
33259 +       *ports = 0;
33260 +       *def = 0;
33261 +
33262 +
33263 +       /*
33264 +        * Skip any leading spaces
33265 +        */
33266 +       while (isspace(*buf)) {
33267 +               buf++;
33268 +       }
33269 +
33270 +       /*
33271 +        * Parse out the string
33272 +        */
33273 +       while (*buf) {
33274 +               u32_t port = simple_strtoul(buf, &buf, 10);
33275 +               u32_t mask = (1 << port);
33276 +
33277 +               /*
33278 +                * Parse out any flags
33279 +                */
33280 +               while (*buf && !isspace(*buf)) {
33281 +                       switch (*buf++) {
33282 +                       case 't':
33283 +                               tag |= mask;
33284 +                               break;
33285 +                       case '*':
33286 +                               *def |= mask;
33287 +                               break;
33288 +                       }
33289 +               }
33290 +               *ports |= mask;
33291 +
33292 +               /*
33293 +                * Skip any spaces
33294 +                */
33295 +               while (isspace(*buf)) {
33296 +                       buf++;
33297 +               }
33298 +       }
33299 +
33300 +       *untag = ~tag & *ports;
33301 +}
33302 +
33303 +/*
33304 + * switch_proc_read
33305 + *     Handle reads from the procfs, dispatches the driver specific handler
33306 + */
33307 +static ssize_t switch_proc_read(struct file *file, char *buf, size_t count,
33308 +                               loff_t *ppos)
33309 +{
33310 +       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33311 +       char *page;
33312 +       int len = 0;
33313 +
33314 +       page = kmalloc(SWITCH_MAX_BUFSZ, GFP_KERNEL);
33315 +       if (!page) {
33316 +               return -ENOBUFS;
33317 +       }
33318 +
33319 +       if (pde->data != NULL) {
33320 +               struct switch_handler_entry *she =
33321 +                       (struct switch_handler_entry *)pde->data;
33322 +               if (she->handler->read) {
33323 +                       len += she->handler->read(she->dev, page + len,
33324 +                                                 she->inst);
33325 +               }
33326 +       }
33327 +       len += 1;
33328 +
33329 +       if (*ppos < len) {
33330 +               len = min_t(int, len - *ppos, count);
33331 +               if (copy_to_user(buf, (page + *ppos), len)) {
33332 +                       kfree(page);
33333 +                       return -EFAULT;
33334 +               }
33335 +               *ppos += len;
33336 +       } else {
33337 +               len = 0;
33338 +       }
33339 +
33340 +       kfree(page);
33341 +
33342 +       return len;
33343 +}
33344 +
33345 +/*
33346 + * switch_proc_write
33347 + *     Handle writes from the procfs, dispatches the driver specific handler
33348 + */
33349 +static ssize_t switch_proc_write(struct file *file, const char *buf,
33350 +                                size_t count, loff_t *data)
33351 +{
33352 +       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33353 +       char *page;
33354 +       int ret = -EINVAL;
33355 +
33356 +       page = kmalloc(count + 1, GFP_KERNEL);
33357 +       if (page == NULL)
33358 +               return -ENOBUFS;
33359 +
33360 +       if (copy_from_user(page, buf, count)) {
33361 +               kfree(page);
33362 +               return -EINVAL;
33363 +       }
33364 +       page[count] = 0;
33365 +
33366 +       if (pde->data != NULL) {
33367 +               struct switch_handler_entry *she =
33368 +                       (struct switch_handler_entry *)pde->data;
33369 +               if (she->handler->write) {
33370 +                       ret = she->handler->write(she->dev, page, she->inst);
33371 +                       if (ret >= 0) {
33372 +                               ret = count;
33373 +                       }
33374 +               }
33375 +       }
33376 +
33377 +       kfree(page);
33378 +       return ret;
33379 +}
33380 +
33381 +/*
33382 + * File operations for the proc_fs, we must cast here since proc_fs' definitions
33383 + * differ from file_operations definitions.
33384 + */
33385 +static struct file_operations switch_proc_fops = {
33386 +       .read = (ssize_t (*) (struct file *, char __user *,
33387 +                             size_t, loff_t *))switch_proc_read,
33388 +       .write = (ssize_t (*) (struct file *, const char __user *,
33389 +                              size_t, loff_t *))switch_proc_write,
33390 +};
33391 +
33392 +/*
33393 + * switch_add_handler
33394 + */
33395 +static int switch_add_handler(struct switch_device *switch_dev,
33396 +                             struct proc_dir_entry *parent,
33397 +                             const struct switch_handler *handler,
33398 +                             int inst)
33399 +{
33400 +       struct switch_handler_entry *she;
33401 +       struct proc_dir_entry *pde;
33402 +       int mode;
33403 +
33404 +       she = (struct switch_handler_entry *)
33405 +               kzalloc(sizeof(struct switch_handler_entry), GFP_KERNEL);
33406 +       if (!she) {
33407 +               return -ENOMEM;
33408 +       }
33409 +
33410 +       INIT_LIST_HEAD(&she->node);
33411 +       she->parent = parent;
33412 +       she->dev = switch_dev;
33413 +       she->inst = inst;
33414 +       she->handler = handler;
33415 +       list_add(&she->node, &switch_dev->handlers);
33416 +
33417 +       mode = 0;
33418 +       if (handler->read != NULL) {
33419 +               mode |= S_IRUSR;
33420 +       }
33421 +       if (handler->write != NULL) {
33422 +               mode |= S_IWUSR;
33423 +       }
33424 +
33425 +       pde = create_proc_entry(handler->name, mode, parent);
33426 +       if (!pde) {
33427 +               kfree(she);
33428 +               printk("Failed to create node '%s' in parent %p\n",
33429 +                      handler->name, parent);
33430 +               return -ENOMEM;
33431 +       }
33432 +       pde->data = (void *)she;
33433 +       pde->proc_fops = &switch_proc_fops;
33434 +
33435 +       return 0;
33436 +}
33437 +
33438 +/*
33439 + * switch_add_handlers
33440 + */
33441 +static int switch_add_handlers(struct switch_device *switch_dev,
33442 +                              struct proc_dir_entry *parent,
33443 +                              const struct switch_handler *handlers,
33444 +                              int inst)
33445 +{
33446 +       while (handlers->name) {
33447 +               int ret = switch_add_handler(switch_dev,
33448 +                                            parent, handlers, inst);
33449 +               if (ret) {
33450 +                       return ret;
33451 +               }
33452 +               handlers++;
33453 +       }
33454 +
33455 +       return 0;
33456 +}
33457 +
33458 +/*
33459 + * switch_remove_vlan_dirs
33460 + *     Removes all vlan directories
33461 + *
33462 + * Assumes all vlan directories are empty, should be called after
33463 + * switch_remove_handlers
33464 + */
33465 +static void switch_remove_vlan_dirs(struct switch_device *switch_dev)
33466 +{
33467 +       struct list_head *pos;
33468 +       struct list_head *tmp;
33469 +       struct switch_vlan_entry *sve;
33470 +
33471 +       list_for_each_safe(pos, tmp, &switch_dev->vlan_dirs) {
33472 +               sve = list_entry(pos, struct switch_vlan_entry, node);
33473 +               list_del(pos);
33474 +               remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33475 +               kfree(sve);
33476 +       }
33477 +}
33478 +
33479 +/*
33480 + * switch_remove_handlers
33481 + *     Removes all handlers registered to the given switch_device
33482 + */
33483 +static void switch_remove_handlers(struct switch_device *switch_dev)
33484 +{
33485 +       struct list_head *pos;
33486 +       struct list_head *tmp;
33487 +       struct switch_handler_entry *she;
33488 +
33489 +       list_for_each_safe(pos, tmp, &switch_dev->handlers) {
33490 +               she = list_entry(pos, struct switch_handler_entry, node);
33491 +               list_del(pos);
33492 +               remove_proc_entry(she->handler->name, she->parent);
33493 +               kfree(she);
33494 +       }
33495 +}
33496 +
33497 +/*
33498 + * switch_unregister_proc_nodes
33499 + *     Unregisters all proc nodes related to switch_dev
33500 + */
33501 +void switch_unregister_proc_nodes(struct switch_device *switch_dev)
33502 +{
33503 +       switch_remove_handlers(switch_dev);
33504 +
33505 +       if (switch_dev->port_dirs) {
33506 +               int i;
33507 +
33508 +               for (i = 0; i < switch_dev->ports; i++) {
33509 +                       if (switch_dev->port_dirs[i]) {
33510 +                               remove_proc_entry(
33511 +                                       switch_dev->port_dirs[i]->name,
33512 +                                       switch_dev->port_dir);
33513 +                       }
33514 +               }
33515 +       }
33516 +
33517 +       if (switch_dev->port_dir) {
33518 +               remove_proc_entry("port", switch_dev->driver_dir);
33519 +               switch_dev->port_dir = NULL;
33520 +       }
33521 +
33522 +       if (switch_dev->reg_dir) {
33523 +               remove_proc_entry("reg", switch_dev->reg_dir);
33524 +               switch_dev->reg_dir = NULL;
33525 +       }
33526 +
33527 +       if (switch_dev->vlan_dir) {
33528 +               switch_remove_vlan_dirs(switch_dev);
33529 +               remove_proc_entry("vlan", switch_dev->driver_dir);
33530 +               switch_dev->vlan_dir = NULL;
33531 +       }
33532 +
33533 +       if (switch_dev->driver_dir) {
33534 +               remove_proc_entry(switch_dev->name, switch_root);
33535 +               switch_dev->driver_dir = NULL;
33536 +       }
33537 +}
33538 +
33539 +/*
33540 + * switch_remove_vlan_dir
33541 + *     Removes vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33542 + */
33543 +int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id)
33544 +{
33545 +       struct list_head *pos;
33546 +       struct switch_vlan_entry *sve = NULL;
33547 +
33548 +       list_for_each(pos, &switch_dev->vlan_dirs) {
33549 +               struct switch_vlan_entry *tmp =
33550 +                       list_entry(pos, struct switch_vlan_entry, node);
33551 +               if (tmp->vlan_id == vlan_id) {
33552 +                       sve = tmp;
33553 +                       break;
33554 +               }
33555 +       }
33556 +
33557 +       if (!sve) {
33558 +               return -ENOENT;
33559 +       }
33560 +
33561 +       /*
33562 +        * Remove it from the list
33563 +        */
33564 +       list_del(pos);
33565 +
33566 +       /*
33567 +        * Remove the handlers
33568 +        */
33569 +       while (sve->handlers->name) {
33570 +               remove_proc_entry(sve->handlers->name, sve->pde);
33571 +               sve->handlers++;
33572 +       }
33573 +
33574 +       /*
33575 +        * Remove the proc entry for the <vlan_id> dir
33576 +        */
33577 +       remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33578 +
33579 +       kfree(sve);
33580 +
33581 +       return 0;
33582 +}
33583 +
33584 +/*
33585 + * switch_create_vlan_dir
33586 + *     Creates vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33587 + */
33588 +int switch_create_vlan_dir(struct switch_device *switch_dev,
33589 +                          int vlan_id, const struct switch_handler *handlers)
33590 +{
33591 +       char s[14];
33592 +       struct proc_dir_entry *pde = NULL;
33593 +       struct switch_vlan_entry *sve = NULL;
33594 +       int ret;
33595 +       struct list_head *pos;
33596 +
33597 +       /*
33598 +        * Check to see if it exists already
33599 +        */
33600 +       list_for_each(pos, &switch_dev->vlan_dirs) {
33601 +               sve = list_entry(pos, struct switch_vlan_entry, node);
33602 +               if (sve->vlan_id == vlan_id) {
33603 +                       return -EEXIST;
33604 +               }
33605 +       }
33606 +       sve = NULL;
33607 +
33608 +       /*
33609 +        * Create the vlan directory if we didn't have it before
33610 +        */
33611 +       if (!switch_dev->vlan_dir) {
33612 +               switch_dev->vlan_dir = proc_mkdir("vlan",
33613 +                                                 switch_dev->driver_dir);
33614 +               if (!switch_dev->vlan_dir) {
33615 +                       goto fail;
33616 +               }
33617 +               if (switch_dev->vlan_handlers) {
33618 +                       ret = switch_add_handlers(switch_dev,
33619 +                                                 switch_dev->vlan_dir,
33620 +                                                 switch_dev->vlan_handlers, 0);
33621 +                       if (ret) {
33622 +                               goto fail;
33623 +                       }
33624 +               }
33625 +       }
33626 +
33627 +       /*
33628 +        * Create the vlan_id directory
33629 +        */
33630 +       snprintf(s, 14, "%d", vlan_id);
33631 +       pde = proc_mkdir(s, switch_dev->vlan_dir);
33632 +       if (!pde) {
33633 +               goto fail;
33634 +       }
33635 +
33636 +       /*
33637 +        * Create the handlers for this vlan
33638 +        */
33639 +       if (handlers) {
33640 +               ret = switch_add_handlers(switch_dev, pde, handlers, vlan_id);
33641 +               if (ret) {
33642 +                       goto fail;
33643 +               }
33644 +       }
33645 +
33646 +       /*
33647 +        * Keep track of all the switch vlan entries created
33648 +        */
33649 +       sve = (struct switch_vlan_entry *)
33650 +               kzalloc(sizeof(struct switch_vlan_entry), GFP_KERNEL);
33651 +       if (!sve) {
33652 +               goto fail;
33653 +       }
33654 +       INIT_LIST_HEAD(&sve->node);
33655 +       sve->handlers = handlers;
33656 +       sve->vlan_id = vlan_id;
33657 +       sve->pde = pde;
33658 +       list_add(&sve->node, &switch_dev->vlan_dirs);
33659 +
33660 +       return 0;
33661 +
33662 +fail:
33663 +       if (sve) {
33664 +               kfree(sve);
33665 +       }
33666 +
33667 +       if (pde) {
33668 +               /*
33669 +                * Remove any proc entries we might have created
33670 +                */
33671 +               while (handlers->name) {
33672 +                       remove_proc_entry(handlers->name, pde);
33673 +                       handlers++;
33674 +               }
33675 +
33676 +               remove_proc_entry(s, switch_dev->driver_dir);
33677 +       }
33678 +
33679 +       return -ENOMEM;
33680 +}
33681 +
33682 +/*
33683 + * switch_register_proc_nodes
33684 + */
33685 +int switch_register_proc_nodes(struct switch_device *switch_dev)
33686 +{
33687 +       int i;
33688 +       int n;
33689 +
33690 +       switch_dev->port_dirs = kzalloc(switch_dev->ports *
33691 +                                       sizeof(struct proc_dir_entry *),
33692 +                                       GFP_KERNEL);
33693 +       if (!switch_dev->port_dirs) {
33694 +               return -ENOMEM;
33695 +       }
33696 +
33697 +       /*
33698 +        * Create a new proc entry for this switch
33699 +        */
33700 +       switch_dev->driver_dir = proc_mkdir(switch_dev->name, switch_root);
33701 +       if (!switch_dev->driver_dir) {
33702 +               goto fail;
33703 +       }
33704 +       if (switch_dev->driver_handlers) {
33705 +               switch_add_handlers(switch_dev,
33706 +                                   switch_dev->driver_dir,
33707 +                                   switch_dev->driver_handlers,
33708 +                                   0);
33709 +       }
33710 +
33711 +       /*
33712 +        * Create the ports
33713 +        */
33714 +       switch_dev->port_dir = proc_mkdir("port", switch_dev->driver_dir);
33715 +       if (!switch_dev->port_dir) {
33716 +               goto fail;
33717 +       }
33718 +       for (n = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33719 +               if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33720 +                       char s[14];
33721 +
33722 +                       snprintf(s, 14, "%d", i);
33723 +                       switch_dev->port_dirs[n] =
33724 +                               proc_mkdir(s, switch_dev->port_dir);
33725 +                       if (!switch_dev->port_dirs[n]) {
33726 +                               goto fail;
33727 +                       }
33728 +                       if (switch_dev->port_handlers) {
33729 +                               switch_add_handlers(switch_dev,
33730 +                                                   switch_dev->port_dirs[n],
33731 +                                                   switch_dev->port_handlers,
33732 +                                                   i);
33733 +                       }
33734 +                       n++;
33735 +               }
33736 +       }
33737 +
33738 +       /*
33739 +        * Create the register directory for switch register access.
33740 +        */
33741 +       if (switch_dev->reg_handlers) {
33742 +               switch_dev->reg_dir = proc_mkdir("reg", switch_dev->driver_dir);
33743 +               if (!switch_dev->reg_dir) {
33744 +                       goto fail;
33745 +               }
33746 +
33747 +               switch_add_handlers(switch_dev,
33748 +                                   switch_dev->reg_dir,
33749 +                                   switch_dev->reg_handlers,
33750 +                                   0);
33751 +       }
33752 +
33753 +       /*
33754 +        * Create the vlan directory
33755 +        */
33756 +       if (switch_dev->vlan_handlers) {
33757 +               switch_dev->vlan_dir = proc_mkdir("vlan",
33758 +                                                 switch_dev->driver_dir);
33759 +               if (!switch_dev->vlan_dir) {
33760 +                       goto fail;
33761 +               }
33762 +               if (switch_dev->vlan_handlers) {
33763 +                       switch_add_handlers(switch_dev,
33764 +                                           switch_dev->vlan_dir,
33765 +                                           switch_dev->vlan_handlers,
33766 +                                           0);
33767 +               }
33768 +       }
33769 +
33770 +       return 0;
33771 +
33772 +fail:
33773 +       switch_unregister_proc_nodes(switch_dev);
33774 +       return -ENOMEM;
33775 +}
33776 +
33777 +/*
33778 + * switch_release
33779 + */
33780 +void switch_release(struct switch_device *switch_dev)
33781 +{
33782 +       kfree(switch_dev);
33783 +}
33784 +
33785 +/*
33786 + * switch_alloc
33787 + */
33788 +struct switch_device *switch_alloc(void)
33789 +{
33790 +       struct switch_device *switch_dev =
33791 +               kzalloc(sizeof(struct switch_device),
33792 +                                               GFP_KERNEL);
33793 +       INIT_LIST_HEAD(&switch_dev->node);
33794 +       INIT_LIST_HEAD(&switch_dev->vlan_dirs);
33795 +       INIT_LIST_HEAD(&switch_dev->handlers);
33796 +       return switch_dev;
33797 +}
33798 +
33799 +/*
33800 + * switch_register
33801 + */
33802 +int switch_register(struct switch_device *switch_dev)
33803 +{
33804 +       int ret;
33805 +       int i;
33806 +
33807 +       /*
33808 +        * Make sure that the number of ports and the port mask make sense
33809 +        */
33810 +       for (ret = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33811 +               if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33812 +                       ret++;
33813 +               }
33814 +       }
33815 +       if (ret > switch_dev->ports) {
33816 +               return -EINVAL;
33817 +       }
33818 +
33819 +       /*
33820 +        * Create the /proc entries
33821 +        */
33822 +       ret = switch_register_proc_nodes(switch_dev);
33823 +       if (ret) {
33824 +               return ret;
33825 +       }
33826 +
33827 +       /*
33828 +        * Add it to the list of switches
33829 +        */
33830 +       down_write(&switch_list_lock);
33831 +       list_add_tail(&switch_dev->node, &switch_list);
33832 +       up_write(&switch_list_lock);
33833 +
33834 +       printk(KERN_INFO "Registered switch device: %s\n", switch_dev->name);
33835 +
33836 +       return 0;
33837 +}
33838 +EXPORT_SYMBOL_GPL(switch_register);
33839 +
33840 +/*
33841 + * switch_unregister
33842 + *     Unregisters a previously registered switch_device object
33843 + */
33844 +void switch_unregister(struct switch_device *switch_dev)
33845 +{
33846 +       /*
33847 +        * remove the proc entries
33848 +        */
33849 +       switch_unregister_proc_nodes(switch_dev);
33850 +
33851 +       /*
33852 +        * Remove it from the list of switches
33853 +        */
33854 +       down_write(&switch_list_lock);
33855 +       list_del(&switch_dev->node);
33856 +       up_write(&switch_list_lock);
33857 +
33858 +       printk(KERN_INFO "Unregistered switch device: %s\n", switch_dev->name);
33859 +}
33860 +EXPORT_SYMBOL_GPL(switch_unregister);
33861 +
33862 +/*
33863 + * switch_init
33864 + */
33865 +static int __init switch_init(void)
33866 +{
33867 +       switch_root = proc_mkdir("switch", NULL);
33868 +       if (!switch_root) {
33869 +               printk(KERN_WARNING "Failed to make root switch node\n");
33870 +               return -ENODEV;
33871 +       }
33872 +       return 0;
33873 +}
33874 +module_init(switch_init);
33875 +
33876 +/*
33877 + * switch_exit
33878 + */
33879 +static void __exit switch_exit(void)
33880 +{
33881 +       remove_proc_entry("switch", NULL);
33882 +}
33883 +module_exit(switch_exit);
33884 +
33885 +MODULE_AUTHOR("Patrick Tjin");
33886 +MODULE_LICENSE("GPL");
33887 +MODULE_DESCRIPTION("Ethernet Switch Class Interface");
33888 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.h
33889 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.h     1970-01-01 02:00:00.000000000 +0200
33890 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.h 2009-12-11 11:45:11.000000000 +0200
33891 @@ -0,0 +1,92 @@
33892 +/*
33893 + * arch/ubicom32/mach-common/switch-core.h
33894 + *   Private data for the switch module
33895 + *
33896 + * (C) Copyright 2009, Ubicom, Inc.
33897 + *
33898 + * This file is part of the Ubicom32 Linux Kernel Port.
33899 + *
33900 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33901 + * it and/or modify it under the terms of the GNU General Public License
33902 + * as published by the Free Software Foundation, either version 2 of the
33903 + * License, or (at your option) any later version.
33904 + *
33905 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33906 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33907 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
33908 + * the GNU General Public License for more details.
33909 + *
33910 + * You should have received a copy of the GNU General Public License
33911 + * along with the Ubicom32 Linux Kernel Port.  If not,
33912 + * see <http://www.gnu.org/licenses/>.
33913 + *
33914 + * Ubicom32 implementation derived from (with many thanks):
33915 + *   arch/m68knommu
33916 + *   arch/blackfin
33917 + *   arch/parisc
33918 + */
33919 +#ifndef _SWITCH_CORE_H_
33920 +#define _SWITCH_CORE_H_
33921 +
33922 +struct switch_handler_entry;
33923 +struct switch_vlan_entry;
33924 +
33925 +#define SWITCH_PORT_MASK_SIZE  2
33926 +
33927 +struct switch_device {
33928 +       struct list_head                node;
33929 +
33930 +       const char                      *name;
33931 +       void                            *drvdata;
33932 +
33933 +       u8_t                            ports;
33934 +
33935 +       struct proc_dir_entry           *driver_dir;
33936 +       const struct switch_handler     *driver_handlers;
33937 +
33938 +       struct proc_dir_entry           *port_dir;
33939 +       struct proc_dir_entry           **port_dirs;
33940 +       const struct switch_handler     *port_handlers;
33941 +
33942 +       struct proc_dir_entry           *reg_dir;
33943 +       const struct switch_handler     *reg_handlers;
33944 +
33945 +       struct proc_dir_entry           *vlan_dir;
33946 +       const struct switch_handler     *vlan_handlers;
33947 +       struct list_head                vlan_dirs;
33948 +
33949 +       struct list_head                handlers;
33950 +
33951 +       u32_t                           port_mask[SWITCH_PORT_MASK_SIZE];
33952 +};
33953 +
33954 +typedef int (*switch_handler_fn)(struct switch_device *, char *buf, int nr);
33955 +struct switch_handler {
33956 +       const char              *name;
33957 +
33958 +       switch_handler_fn       read;
33959 +       switch_handler_fn       write;
33960 +};
33961 +
33962 +#define SWITCH_MAX_BUFSZ       4096
33963 +
33964 +static inline void switch_set_drvdata(struct switch_device *switch_dev, void *drvdata)
33965 +{
33966 +       switch_dev->drvdata = drvdata;
33967 +}
33968 +
33969 +static inline void *switch_get_drvdata(struct switch_device *switch_dev)
33970 +{
33971 +       return switch_dev->drvdata;
33972 +}
33973 +
33974 +extern int switch_create_vlan_dir(struct switch_device *switch_dev, int vlan_id, const struct switch_handler *handlers);
33975 +extern int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id);
33976 +extern void switch_parse_vlan_ports(struct switch_device *switch_dev, char *buf, u32_t *untag, u32_t *ports, u32_t *def);
33977 +
33978 +extern void switch_release(struct switch_device *switch_dev);
33979 +extern struct switch_device *switch_alloc(void);
33980 +extern int switch_register(struct switch_device *switch_dev);
33981 +extern void switch_unregister(struct switch_device *switch_dev);
33982 +
33983 +#endif
33984 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubi32-gpio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubi32-gpio.c
33985 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubi32-gpio.c      1970-01-01 02:00:00.000000000 +0200
33986 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubi32-gpio.c  2009-12-11 11:45:11.000000000 +0200
33987 @@ -0,0 +1,411 @@
33988 +/*
33989 + * arch/ubicom32/mach-common/ubi32-gpio.c
33990 + *   Ubicom gpio driver
33991 + *
33992 + * (C) Copyright 2009, Ubicom, Inc.
33993 + *
33994 + * This file is part of the Ubicom32 Linux Kernel Port.
33995 + *
33996 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33997 + * it and/or modify it under the terms of the GNU General Public License
33998 + * as published by the Free Software Foundation, either version 2 of the
33999 + * License, or (at your option) any later version.
34000 + *
34001 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34002 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34003 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
34004 + * the GNU General Public License for more details.
34005 + *
34006 + * You should have received a copy of the GNU General Public License
34007 + * along with the Ubicom32 Linux Kernel Port.  If not,
34008 + * see <http://www.gnu.org/licenses/>.
34009 + *
34010 + * Ubicom32 implementation derived from (with many thanks):
34011 + *   arch/m68knommu
34012 + *   arch/blackfin
34013 + *   arch/parisc
34014 + */
34015 +
34016 +#include <linux/module.h>
34017 +#include <linux/init.h>
34018 +#include <linux/errno.h>
34019 +#include <linux/kernel.h>
34020 +#include <linux/io.h>
34021 +#include <linux/gpio.h>
34022 +#include <linux/irq.h>
34023 +#include <linux/version.h>
34024 +
34025 +#if defined(CONFIG_PROC_FS)
34026 +#include <linux/proc_fs.h>
34027 +#endif
34028 +
34029 +#include <linux/io.h>
34030 +#include <asm/ip5000.h>
34031 +#include <linux/gpio.h>
34032 +
34033 +#define UBI_GPIO_CHECK_RANGE     0  /* !0 enables range checking */
34034 +
34035 +
34036 +/*
34037 + * Each I/O port can be configured to operate in one of several
34038 + * functional modes. One of these modes is GPIO, which causes the
34039 + * entire port to function as a GPIO port.  Since the various port
34040 + * registers serve the system with other important functions, such as
34041 + * ethernet, serial, USB, etc., it isn't advantageous to set any of
34042 + * the ports to be entirely dedicated for GPIO use.  The processor
34043 + * alternatively allows individual bits of a port to be assigned to be
34044 + * used as GPIO independently from the overall port function.  This
34045 + * bit-by-bit assignment is selected by setting the corresponding bit
34046 + * in the port's gpio_mask register.  When set, the selected bit is
34047 + * then enabled as a GPIO.  If the corresponding bit is set in the
34048 + * gpio_ctl register of the port, the bit is configured as a GPIO
34049 + * output.  Otherwise, it is an input.
34050 + *
34051 + * NOTE: This driver uses the bit-by-bit GPIO function assignment
34052 + * exclusively and *never* sets the port function registers to the
34053 + * GPIO function.
34054 + *
34055 + * GPIO is not the main function of any of the I/O ports.  The port
34056 + * bit widths are variable from one port to the next, determined by
34057 + * the more common I/O functions of the ports.  For simplicity, this
34058 + * driver assumes all the ports are 32 bits wide regardless of the
34059 + * real bit width of the port.  GPIO bits are numbered from zero to
34060 + * MAX_UBICOM_GPIOS.  Within a port, the least significant bit is
34061 + * numbered bit zero, the most significant is bit 31.  Since the ports
34062 + * are considered logically contiguous, GPIO #32 is the zeroth bit in
34063 + * port #1, and so on.  Due to the hardware definition, there are
34064 + * large gaps in the GPIO numbers representing real pins.
34065 + *
34066 + * NOTE: It is up to the programmer to refer to the processor data
34067 + * sheet to determine which bits in which ports can be accessed and
34068 + * used for GPIO.
34069 + *
34070 + */
34071 +
34072 +
34073 +/* There are 9 ports, A through I. Not all 32 bits in each
34074 + * port can be a GPIO, but we pretend they are.  Its up to the
34075 + * programmer to refer to the processor data sheet.
34076 + */
34077 +#define MAX_UBICOM_GPIOS   (9 * 32) /* ARCH_NR_GPIOS */
34078 +#define NUM_GPIO_PORTS     (gpio_bank(MAX_UBICOM_GPIOS))
34079 +
34080 +
34081 +/* GPIO reservation bit map array */
34082 +static int reserved_gpio_map[NUM_GPIO_PORTS];
34083 +
34084 +
34085 +/* Array of hardware io_port addresses */
34086 +static struct ubicom32_io_port *gpio_bank_addr[NUM_GPIO_PORTS] =
34087 +{
34088 +       UBICOM32_IO_PORT(RA),
34089 +       UBICOM32_IO_PORT(RB),
34090 +       UBICOM32_IO_PORT(RC),
34091 +       UBICOM32_IO_PORT(RD),
34092 +       UBICOM32_IO_PORT(RE),
34093 +       UBICOM32_IO_PORT(RF),
34094 +       UBICOM32_IO_PORT(RG),
34095 +       UBICOM32_IO_PORT(RH),
34096 +       UBICOM32_IO_PORT(RI)
34097 +};
34098 +
34099 +
34100 +struct ubi_gpio_chip {
34101 +       /*
34102 +        * Right now, nothing else lives here.
34103 +        */
34104 +       struct gpio_chip gpio_chip;
34105 +};
34106 +
34107 +
34108 +#if UBI_GPIO_CHECK_RANGE
34109 +inline int check_gpio(unsigned gpio)
34110 +{
34111 +       if (gpio >= MAX_UBICOM_GPIOS)
34112 +               return -EINVAL;
34113 +       return 0;
34114 +}
34115 +#else
34116 +#define check_gpio(n)   (0)
34117 +#endif
34118 +
34119 +/*
34120 + * ubi_gpio_get_port
34121 + *     Get the IO port associated with a certain gpio
34122 + */
34123 +struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio)
34124 +{
34125 +       if (gpio_bank(gpio) > NUM_GPIO_PORTS) {
34126 +               return NULL;
34127 +       }
34128 +       return gpio_bank_addr[gpio_bank(gpio)];
34129 +}
34130 +
34131 +/*
34132 + * ubi_gpio_error()
34133 + */
34134 +static void ubi_gpio_error(unsigned gpio)
34135 +{
34136 +       printk(KERN_ERR "ubicom-gpio: GPIO %d wasn't requested!\n", gpio);
34137 +}
34138 +
34139 +/*
34140 + * ubi_port_setup()
34141 + */
34142 +static void ubi_port_setup(unsigned gpio, unsigned short usage)
34143 +{
34144 +       if (!check_gpio(gpio)) {
34145 +               if (usage) {
34146 +                       UBICOM32_GPIO_ENABLE(gpio);
34147 +               } else {
34148 +                       UBICOM32_GPIO_DISABLE(gpio);
34149 +               }
34150 +       }
34151 +}
34152 +
34153 +/*
34154 + * ubi_gpio_request()
34155 + */
34156 +static int ubi_gpio_request(struct gpio_chip *chip, unsigned gpio)
34157 +{
34158 +       unsigned long flags;
34159 +
34160 +       if (check_gpio(gpio) < 0)
34161 +               return -EINVAL;
34162 +
34163 +       local_irq_save(flags);
34164 +
34165 +       if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34166 +               printk(KERN_ERR "ubi-gpio: GPIO %d is already reserved!\n",
34167 +                      gpio);
34168 +               local_irq_restore(flags);
34169 +               return -EBUSY;
34170 +       }
34171 +
34172 +       reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
34173 +
34174 +       ubi_port_setup(gpio, 1);
34175 +
34176 +       local_irq_restore(flags);
34177 +
34178 +       return 0;
34179 +}
34180 +
34181 +/*
34182 + * ubi_gpio_free()
34183 + */
34184 +static void ubi_gpio_free(struct gpio_chip *chip, unsigned gpio)
34185 +{
34186 +       unsigned long flags;
34187 +
34188 +       if (check_gpio(gpio) < 0)
34189 +               return;
34190 +
34191 +       local_irq_save(flags);
34192 +
34193 +       if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
34194 +               ubi_gpio_error(gpio);
34195 +               local_irq_restore(flags);
34196 +               return;
34197 +       }
34198 +
34199 +       /* Assert the pin is no longer claimed */
34200 +       reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
34201 +
34202 +       /* Revert port bit to use specified by port->function */
34203 +       ubi_port_setup(gpio, 0);
34204 +
34205 +       local_irq_restore(flags);
34206 +}
34207 +
34208 +/*
34209 + * ubi_gpio_direction_input()
34210 + */
34211 +static int ubi_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
34212 +{
34213 +       unsigned long flags;
34214 +
34215 +       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34216 +               ubi_gpio_error(gpio);
34217 +               return -EINVAL;
34218 +       }
34219 +
34220 +       local_irq_save(flags);
34221 +
34222 +       /* Configure pin as gpio */
34223 +       ubi_port_setup(gpio, 1);
34224 +
34225 +       /* Assert pin is an input */
34226 +       UBICOM32_GPIO_SET_PIN_INPUT(gpio);
34227 +
34228 +       local_irq_restore(flags);
34229 +
34230 +       return 0;
34231 +}
34232 +
34233 +
34234 +/*
34235 + * ubi_gpio_direction_output()
34236 + */
34237 +static int ubi_gpio_direction_output(struct gpio_chip *chip,
34238 +                                    unsigned gpio, int value)
34239 +{
34240 +       unsigned long flags;
34241 +
34242 +       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34243 +               ubi_gpio_error(gpio);
34244 +               return -EINVAL;
34245 +       }
34246 +
34247 +       local_irq_save(flags);
34248 +
34249 +       /* Configure pin as gpio and set initial value in gpio_out register
34250 +        * so that when we enable it as an output, it will have the correct
34251 +        * initial value.
34252 +        */
34253 +       ubi_port_setup(gpio, 1);
34254 +       if (value) {
34255 +               UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34256 +       } else {
34257 +               UBICOM32_GPIO_SET_PIN_LOW(gpio);
34258 +       }
34259 +
34260 +       /* Enable the pin as an output */
34261 +       UBICOM32_GPIO_SET_PIN_OUTPUT(gpio);
34262 +
34263 +       local_irq_restore(flags);
34264 +
34265 +       return 0;
34266 +}
34267 +
34268 +
34269 +/*
34270 + * ubi_gpio_get_value()
34271 + */
34272 +static int ubi_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
34273 +{
34274 +       return 0 != (gpio_bank_addr[gpio_bank(gpio)]->gpio_in & gpio_bit(gpio));
34275 +}
34276 +
34277 +
34278 +/*
34279 + * ubi_gpio_set_value()
34280 + */
34281 +static void ubi_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
34282 +                              int arg)
34283 +{
34284 +       unsigned long flags;
34285 +       local_irq_save(flags);
34286 +
34287 +       if (arg) {
34288 +               UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34289 +       } else {
34290 +               UBICOM32_GPIO_SET_PIN_LOW(gpio);
34291 +       }
34292 +
34293 +       local_irq_restore(flags);
34294 +}
34295 +
34296 +
34297 +/*
34298 + * ubi_gpio_to_irq()
34299 + */
34300 +static int ubi_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
34301 +{
34302 +       return gpio_to_irq(gpio);
34303 +}
34304 +
34305 +
34306 +/*
34307 + * ubi_gpio_init()
34308 + */
34309 +int __init ubi_gpio_init(void)
34310 +{
34311 +       int k;
34312 +       int status;
34313 +       struct ubi_gpio_chip *chip;
34314 +       struct gpio_chip *gc;
34315 +
34316 +       printk(KERN_INFO "Ubicom GPIO Controller\n");
34317 +
34318 +       chip = kzalloc(sizeof(struct ubi_gpio_chip), GFP_KERNEL);
34319 +       if (chip == NULL)
34320 +               return -ENOMEM;
34321 +
34322 +       gc = &chip->gpio_chip;
34323 +       gc->request          = ubi_gpio_request;
34324 +       gc->free             = ubi_gpio_free;
34325 +       gc->to_irq           = ubi_gpio_to_irq;
34326 +       gc->direction_input  = ubi_gpio_direction_input;
34327 +       gc->direction_output = ubi_gpio_direction_output;
34328 +       gc->get              = ubi_gpio_get_value;
34329 +       gc->set              = ubi_gpio_set_value;
34330 +       gc->can_sleep        = 0;
34331 +       gc->base             = 0;
34332 +       gc->ngpio            = MAX_UBICOM_GPIOS; /* ARCH_NR_GPIOS - 1 */
34333 +       gc->label            = "ubi_gpio";
34334 +
34335 +       status = gpiochip_add(gc);
34336 +       if (status != 0) {
34337 +               kfree(chip);
34338 +               return status;
34339 +       }
34340 +
34341 +       /* Assert all pins are free */
34342 +       for (k = 0; k < NUM_GPIO_PORTS; k++) {
34343 +               reserved_gpio_map[k] = 0;
34344 +       }
34345 +
34346 +       return 0;
34347 +}
34348 +
34349 +#if defined(CONFIG_PROC_FS)
34350 +/*
34351 + * ubi_get_gpio_dir()
34352 + */
34353 +static int ubi_get_gpio_dir(unsigned gpio)
34354 +{
34355 +       if (gpio_bank_addr[gpio_bank(gpio)]->gpio_ctl & gpio_bit(gpio))
34356 +               return 1;
34357 +       else
34358 +               return 0;
34359 +}
34360 +
34361 +/*
34362 + * gpio_proc_read()
34363 + */
34364 +static int ubi_gpio_proc_read(char *buf, char **start, off_t offset,
34365 +                         int len, int *unused_i, void *unused_v)
34366 +{
34367 +       int c, outlen = 0;
34368 +
34369 +       for (c = 0; c < MAX_UBICOM_GPIOS; c++) {
34370 +               if (!check_gpio(c) &&
34371 +                   (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) {
34372 +                       len = sprintf(buf, "GPIO_%d:\t\tGPIO %s\n", c,
34373 +                                     ubi_get_gpio_dir(c) ? "OUTPUT" : "INPUT");
34374 +               } else {
34375 +                       continue;
34376 +               }
34377 +
34378 +               buf += len;
34379 +               outlen += len;
34380 +       }
34381 +       return outlen;
34382 +}
34383 +
34384 +/*
34385 + * ubi_gpio_register_proc()
34386 + */
34387 +static __init int ubi_gpio_register_proc(void)
34388 +{
34389 +       struct proc_dir_entry *proc_gpio;
34390 +
34391 +       proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
34392 +       if (proc_gpio)
34393 +               proc_gpio->read_proc = ubi_gpio_proc_read;
34394 +
34395 +       return proc_gpio != NULL;
34396 +}
34397 +device_initcall(ubi_gpio_register_proc);
34398 +#endif
34399 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32hid.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32hid.c
34400 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32hid.c     1970-01-01 02:00:00.000000000 +0200
34401 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32hid.c 2009-12-11 11:45:11.000000000 +0200
34402 @@ -0,0 +1,557 @@
34403 +/*
34404 + * arch/ubicom32/mach-common/ubicom32hid.c
34405 + *   I2C driver for HID coprocessor found on some DPF implementations.
34406 + *
34407 + * (C) Copyright 2009, Ubicom, Inc.
34408 + *
34409 + * This file is part of the Ubicom32 Linux Kernel Port.
34410 + *
34411 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34412 + * it and/or modify it under the terms of the GNU General Public License
34413 + * as published by the Free Software Foundation, either version 2 of the
34414 + * License, or (at your option) any later version.
34415 + *
34416 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34417 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34418 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
34419 + * the GNU General Public License for more details.
34420 + *
34421 + * You should have received a copy of the GNU General Public License
34422 + * along with the Ubicom32 Linux Kernel Port.  If not,
34423 + * see <http://www.gnu.org/licenses/>.
34424 + *
34425 + * Ubicom32 implementation derived from (with many thanks):
34426 + *   arch/m68knommu
34427 + *   arch/blackfin
34428 + *   arch/parisc
34429 + */
34430 +
34431 +#include <linux/module.h>
34432 +#include <linux/init.h>
34433 +#include <linux/gpio.h>
34434 +#include <linux/delay.h>
34435 +#include <linux/platform_device.h>
34436 +#include <linux/i2c.h>
34437 +#include <linux/backlight.h>
34438 +#include <linux/fb.h>
34439 +#include <linux/input.h>
34440 +#include <linux/input-polldev.h>
34441 +
34442 +#include <asm/ubicom32hid.h>
34443 +
34444 +#define DRIVER_NAME "ubicom32hid"
34445 +
34446 +#ifdef DEBUG
34447 +static int ubicom32hid_debug;
34448 +#endif
34449 +
34450 +static const struct i2c_device_id ubicom32hid_id[] = {
34451 +       { DRIVER_NAME, },
34452 +       { }
34453 +};
34454 +MODULE_DEVICE_TABLE(i2c, ubicom32hid_id);
34455 +
34456 +/*
34457 + * Define this to make IR checking strict, in general, it's not needed
34458 + */
34459 +#undef UBICOM32HID_STRICT_IR_CHECK
34460 +
34461 +#define UBICOM32HID_CMD_SET_PWM                0x01
34462 +#define UBICOM32HID_CMD_SET_BL_EN      0x02
34463 +#define UBICOM32HID_BL_EN_LOW          0x00
34464 +#define UBICOM32HID_BL_EN_HIZ          0x01
34465 +#define UBICOM32HID_BL_EN_HI           0x02
34466 +#define UBICOM32HID_CMD_FLUSH          0x99
34467 +#define UBICOM32HID_CMD_RESET          0x99
34468 +#define UBICOM32HID_CMD_GET_IR_SWITCH  0xC0
34469 +#define UBICOM32HID_CMD_GET_REVISION   0xfd
34470 +#define UBICOM32HID_CMD_GET_DEVICE_ID  0xfe
34471 +#define UBICOM32HID_CMD_GET_VERSION    0xff
34472 +#define UBICOM32HID_DEVICE_ID          0x49
34473 +
34474 +#define UBICOM32HID_MAX_BRIGHTNESS_PWM 255
34475 +
34476 +/*
34477 + * Data structure returned by the HID device
34478 + */
34479 +struct ubicom32hid_input_data {
34480 +       uint32_t        ircmd;
34481 +       uint8_t         sw_state;
34482 +       uint8_t         sw_changed;
34483 +};
34484 +
34485 +/*
34486 + * Our private data
34487 + */
34488 +struct ubicom32hid_data {
34489 +       /*
34490 +        * Pointer to the platform data structure, we need the settings.
34491 +        */
34492 +       const struct ubicom32hid_platform_data  *pdata;
34493 +
34494 +       /*
34495 +        * Backlight device
34496 +        */
34497 +       struct backlight_device                 *bldev;
34498 +
34499 +       /*
34500 +        * I2C client, for sending messages to the HID device
34501 +        */
34502 +       struct i2c_client                       *client;
34503 +
34504 +       /*
34505 +        * Current intensity, used for get_intensity.
34506 +        */
34507 +       int                                     cur_intensity;
34508 +
34509 +       /*
34510 +        * Input subsystem
34511 +        *      We won't register an input subsystem if there are no mappings.
34512 +        */
34513 +       struct input_polled_dev                 *poll_dev;
34514 +};
34515 +
34516 +
34517 +/*
34518 + * ubicom32hid_set_intensity
34519 + */
34520 +static int ubicom32hid_set_intensity(struct backlight_device *bd)
34521 +{
34522 +       struct ubicom32hid_data *ud =
34523 +               (struct ubicom32hid_data *)bl_get_data(bd);
34524 +       int intensity = bd->props.brightness;
34525 +       int reg;
34526 +       u8_t val;
34527 +       int ret;
34528 +
34529 +       /*
34530 +        * If we're blanked the the intensity doesn't matter.
34531 +        */
34532 +       if ((bd->props.power != FB_BLANK_UNBLANK) ||
34533 +           (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
34534 +               intensity = 0;
34535 +       }
34536 +
34537 +       /*
34538 +        * Set the brightness based on the type of backlight
34539 +        */
34540 +       if (ud->pdata->type == UBICOM32HID_BL_TYPE_BINARY) {
34541 +               reg = UBICOM32HID_CMD_SET_BL_EN;
34542 +               if (intensity) {
34543 +                       val = ud->pdata->invert
34544 +                               ? UBICOM32HID_BL_EN_LOW : UBICOM32HID_BL_EN_HI;
34545 +               } else {
34546 +                       val = ud->pdata->invert
34547 +                               ? UBICOM32HID_BL_EN_HI : UBICOM32HID_BL_EN_LOW;
34548 +               }
34549 +       } else {
34550 +               reg = UBICOM32HID_CMD_SET_PWM;
34551 +               val = ud->pdata->invert
34552 +                       ? (UBICOM32HID_MAX_BRIGHTNESS_PWM - intensity) :
34553 +                       intensity;
34554 +       }
34555 +
34556 +       /*
34557 +        * Send the command
34558 +        */
34559 +       ret = i2c_smbus_write_byte_data(ud->client, reg, val);
34560 +       if (ret < 0) {
34561 +               dev_warn(&ud->client->dev, "Unable to write backlight err=%d\n",
34562 +                        ret);
34563 +               return ret;
34564 +       }
34565 +
34566 +       ud->cur_intensity = intensity;
34567 +
34568 +       return 0;
34569 +}
34570 +
34571 +/*
34572 + * ubicom32hid_get_intensity
34573 + *     Return the current intensity of the backlight.
34574 + */
34575 +static int ubicom32hid_get_intensity(struct backlight_device *bd)
34576 +{
34577 +       struct ubicom32hid_data *ud =
34578 +               (struct ubicom32hid_data *)bl_get_data(bd);
34579 +
34580 +       return ud->cur_intensity;
34581 +}
34582 +
34583 +/*
34584 + * ubicom32hid_verify_data
34585 + *     Verify the data to see if there is any action to be taken
34586 + *
34587 + * Returns 0 if no action is to be taken, non-zero otherwise
34588 + */
34589 +static int ubicom32hid_verify_data(struct ubicom32hid_data *ud,
34590 +                                  struct ubicom32hid_input_data *data)
34591 +{
34592 +       uint8_t *ircmd = (uint8_t *)&(data->ircmd);
34593 +
34594 +       /*
34595 +        * ircmd == DEADBEEF means ir queue is empty.  Since this is a
34596 +        * meaningful code, that means the rest of the message is most likely
34597 +        * correct, so only process the data if the switch state has changed.
34598 +        */
34599 +       if (data->ircmd == 0xDEADBEEF) {
34600 +               return data->sw_changed != 0;
34601 +       }
34602 +
34603 +       /*
34604 +        * We have an ircmd which is not empty:
34605 +        *      Data[1] should be the complement of Data[0]
34606 +        */
34607 +       if (ircmd[0] != (u8_t)~ircmd[1]) {
34608 +               return 0;
34609 +       }
34610 +
34611 +#ifdef UBICOM32HID_STRICT_IR_CHECK
34612 +       /*
34613 +        * It seems that some remote controls don't follow the NEC protocol
34614 +        * properly, so only do this check if the remote does indeed follow the
34615 +        * spec.  Data[3] should be the complement of Data[2]
34616 +        */
34617 +       if (ircmd[2] == (u8_t)~ircmd[3]) {
34618 +               return 1;
34619 +       }
34620 +
34621 +       /*
34622 +        * For non-compliant remotes, check the system code according to what
34623 +        * they send.
34624 +        */
34625 +       if ((ircmd[2] != UBICOM32HID_IR_SYSTEM_CODE_CHECK) ||
34626 +           (ircmd[3] != UBICOM32HID_IR_SYSTEM_CODE)) {
34627 +               return 0;
34628 +       }
34629 +#endif
34630 +
34631 +       /*
34632 +        * Data checks out, process
34633 +        */
34634 +       return 1;
34635 +}
34636 +
34637 +/*
34638 + * ubicom32hid_poll_input
34639 + *     Poll the input from the HID device.
34640 + */
34641 +static void ubicom32hid_poll_input(struct input_polled_dev *dev)
34642 +{
34643 +       struct ubicom32hid_data *ud = (struct ubicom32hid_data *)dev->private;
34644 +       const struct ubicom32hid_platform_data *pdata = ud->pdata;
34645 +       struct ubicom32hid_input_data data;
34646 +       struct input_dev *id = dev->input;
34647 +       int i;
34648 +       int sync_needed = 0;
34649 +       uint8_t cmd;
34650 +       int ret;
34651 +
34652 +       /*
34653 +        * Flush the queue
34654 +        */
34655 +       cmd = UBICOM32HID_CMD_FLUSH;
34656 +       ret = i2c_master_send(ud->client, &cmd, 1);
34657 +       if (ret < 0) {
34658 +               return;
34659 +       }
34660 +
34661 +       ret = i2c_smbus_read_i2c_block_data(
34662 +               ud->client, UBICOM32HID_CMD_GET_IR_SWITCH, 6, (void *)&data);
34663 +       if (ret < 0) {
34664 +               return;
34665 +       }
34666 +
34667 +       /*
34668 +        * Verify the data to see if there is any action to be taken
34669 +        */
34670 +       if (!ubicom32hid_verify_data(ud, &data)) {
34671 +               return;
34672 +       }
34673 +
34674 +#ifdef DEBUG
34675 +       if (ubicom32hid_debug) {
34676 +               printk("Polled ircmd=%8x swstate=%2x swchanged=%2x\n",
34677 +                      data.ircmd, data.sw_state, data.sw_changed);
34678 +       }
34679 +#endif
34680 +
34681 +       /*
34682 +        * Process changed switches
34683 +        */
34684 +       if (data.sw_changed) {
34685 +               const struct ubicom32hid_button *ub = pdata->buttons;
34686 +               for (i = 0; i < pdata->nbuttons; i++, ub++) {
34687 +                       uint8_t mask = (1 << ub->bit);
34688 +                       if (!(data.sw_changed & mask)) {
34689 +                               continue;
34690 +                       }
34691 +
34692 +                       sync_needed = 1;
34693 +                       input_event(id, ub->type, ub->code,
34694 +                                   (data.sw_state & mask) ? 1 : 0);
34695 +               }
34696 +       }
34697 +       if (sync_needed) {
34698 +               input_sync(id);
34699 +       }
34700 +
34701 +       /*
34702 +        * Process ir codes
34703 +        */
34704 +       if (data.ircmd != 0xDEADBEEF) {
34705 +               const struct ubicom32hid_ir *ui = pdata->ircodes;
34706 +               for (i = 0; i < pdata->nircodes; i++, ui++) {
34707 +                       if (ui->ir_code == data.ircmd) {
34708 +                               /*
34709 +                                * Simulate a up/down event
34710 +                                */
34711 +                               input_event(id, ui->type, ui->code, 1);
34712 +                               input_sync(id);
34713 +                               input_event(id, ui->type, ui->code, 0);
34714 +                               input_sync(id);
34715 +                       }
34716 +               }
34717 +       }
34718 +}
34719 +
34720 +
34721 +/*
34722 + * Backlight ops
34723 + */
34724 +static struct backlight_ops ubicom32hid_blops = {
34725 +       .get_brightness = ubicom32hid_get_intensity,
34726 +       .update_status  = ubicom32hid_set_intensity,
34727 +};
34728 +
34729 +/*
34730 + * ubicom32hid_probe
34731 + */
34732 +static int ubicom32hid_probe(struct i2c_client *client,
34733 +                            const struct i2c_device_id *id)
34734 +{
34735 +       struct ubicom32hid_platform_data *pdata;
34736 +       struct ubicom32hid_data *ud;
34737 +       int ret;
34738 +       int i;
34739 +       u8 version[2];
34740 +       char buf[1];
34741 +
34742 +       pdata = client->dev.platform_data;
34743 +       if (pdata == NULL) {
34744 +               return -ENODEV;
34745 +       }
34746 +
34747 +       /*
34748 +        * See if we even have a device available before allocating memory.
34749 +        *
34750 +        * Hard reset the device
34751 +        */
34752 +       ret = gpio_request(pdata->gpio_reset, "ubicom32hid-reset");
34753 +       if (ret < 0) {
34754 +               return ret;
34755 +       }
34756 +       gpio_direction_output(pdata->gpio_reset, pdata->gpio_reset_polarity);
34757 +       udelay(100);
34758 +       gpio_set_value(pdata->gpio_reset, !pdata->gpio_reset_polarity);
34759 +       udelay(100);
34760 +
34761 +       /*
34762 +        * soft reset the device.  It sometimes takes a while to do this.
34763 +        */
34764 +       for (i = 0; i < 50; i++) {
34765 +               buf[0] = UBICOM32HID_CMD_RESET;
34766 +               ret = i2c_master_send(client, buf, 1);
34767 +               if (ret > 0) {
34768 +                       break;
34769 +               }
34770 +               udelay(10000);
34771 +       }
34772 +       if (i == 50) {
34773 +               dev_warn(&client->dev, "Unable to reset device\n");
34774 +               goto fail;
34775 +       }
34776 +
34777 +       ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_DEVICE_ID);
34778 +       if (ret != UBICOM32HID_DEVICE_ID) {
34779 +               dev_warn(&client->dev, "Incorrect device id %02x\n", buf[0]);
34780 +               ret = -ENODEV;
34781 +               goto fail;
34782 +       }
34783 +
34784 +       ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_VERSION);
34785 +       if (ret < 0) {
34786 +               dev_warn(&client->dev, "Unable to get version\n");
34787 +               goto fail;
34788 +       }
34789 +       version[0] = ret;
34790 +
34791 +       ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_REVISION);
34792 +       if (ret < 0) {
34793 +               dev_warn(&client->dev, "Unable to get revision\n");
34794 +               goto fail;
34795 +       }
34796 +       version[1] = ret;
34797 +
34798 +       /*
34799 +        * Allocate our private data
34800 +        */
34801 +       ud = kzalloc(sizeof(struct ubicom32hid_data), GFP_KERNEL);
34802 +       if (!ud) {
34803 +               ret = -ENOMEM;
34804 +               goto fail;
34805 +       }
34806 +       ud->pdata = pdata;
34807 +       ud->client = client;
34808 +
34809 +       /*
34810 +        * Register our backlight device
34811 +        */
34812 +       ud->bldev = backlight_device_register(DRIVER_NAME, &client->dev,
34813 +                                             ud, &ubicom32hid_blops);
34814 +       if (IS_ERR(ud->bldev)) {
34815 +               ret = PTR_ERR(ud->bldev);
34816 +               goto fail2;
34817 +       }
34818 +       platform_set_drvdata(client, ud);
34819 +
34820 +       /*
34821 +        * Start up the backlight with the requested intensity
34822 +        */
34823 +       ud->bldev->props.power = FB_BLANK_UNBLANK;
34824 +       ud->bldev->props.max_brightness =
34825 +               (pdata->type == UBICOM32HID_BL_TYPE_PWM) ?
34826 +               UBICOM32HID_MAX_BRIGHTNESS_PWM : 1;
34827 +       if (pdata->default_intensity < ud->bldev->props.max_brightness) {
34828 +               ud->bldev->props.brightness = pdata->default_intensity;
34829 +       } else {
34830 +               dev_warn(&client->dev, "Default brightness out of range, "
34831 +                        "setting to max\n");
34832 +               ud->bldev->props.brightness = ud->bldev->props.max_brightness;
34833 +       }
34834 +
34835 +       ubicom32hid_set_intensity(ud->bldev);
34836 +
34837 +       /*
34838 +        * Check to see if we have any inputs
34839 +        */
34840 +       if (!pdata->nbuttons && !pdata->nircodes) {
34841 +               goto done;
34842 +       }
34843 +
34844 +       /*
34845 +        * We have buttons or codes, we must register an input device
34846 +        */
34847 +       ud->poll_dev = input_allocate_polled_device();
34848 +       if (!ud->poll_dev) {
34849 +               ret = -ENOMEM;
34850 +               goto fail3;
34851 +       }
34852 +
34853 +       /*
34854 +        * Setup the polling to default to 100ms
34855 +        */
34856 +       ud->poll_dev->poll = ubicom32hid_poll_input;
34857 +       ud->poll_dev->poll_interval =
34858 +               pdata->poll_interval ? pdata->poll_interval : 100;
34859 +       ud->poll_dev->private = ud;
34860 +
34861 +       ud->poll_dev->input->name =
34862 +               pdata->input_name ? pdata->input_name : "Ubicom32HID";
34863 +       ud->poll_dev->input->phys = "ubicom32hid/input0";
34864 +       ud->poll_dev->input->dev.parent = &client->dev;
34865 +       ud->poll_dev->input->id.bustype = BUS_I2C;
34866 +
34867 +       /*
34868 +        * Set the capabilities by running through the buttons and ir codes
34869 +        */
34870 +       for (i = 0; i < pdata->nbuttons; i++) {
34871 +               const struct ubicom32hid_button *ub = &pdata->buttons[i];
34872 +
34873 +               input_set_capability(ud->poll_dev->input,
34874 +                                    ub->type ? ub->type : EV_KEY, ub->code);
34875 +       }
34876 +
34877 +       for (i = 0; i < pdata->nircodes; i++) {
34878 +               const struct ubicom32hid_ir *ui = &pdata->ircodes[i];
34879 +
34880 +               input_set_capability(ud->poll_dev->input,
34881 +                                    ui->type ? ui->type : EV_KEY, ui->code);
34882 +       }
34883 +
34884 +       ret = input_register_polled_device(ud->poll_dev);
34885 +       if (ret) {
34886 +               goto fail3;
34887 +       }
34888 +
34889 +done:
34890 +       printk(KERN_INFO DRIVER_NAME ": enabled, version=%02x.%02x\n",
34891 +              version[0], version[1]);
34892 +
34893 +       return 0;
34894 +
34895 +fail3:
34896 +       gpio_free(ud->pdata->gpio_reset);
34897 +       backlight_device_unregister(ud->bldev);
34898 +fail2:
34899 +       kfree(ud);
34900 +fail:
34901 +       gpio_free(pdata->gpio_reset);
34902 +       return ret;
34903 +}
34904 +
34905 +/*
34906 + * ubicom32hid_remove
34907 + */
34908 +static int ubicom32hid_remove(struct i2c_client *client)
34909 +{
34910 +       struct ubicom32hid_data *ud =
34911 +               (struct ubicom32hid_data *)platform_get_drvdata(client);
34912 +
34913 +       gpio_free(ud->pdata->gpio_reset);
34914 +
34915 +       backlight_device_unregister(ud->bldev);
34916 +
34917 +       if (ud->poll_dev) {
34918 +               input_unregister_polled_device(ud->poll_dev);
34919 +               input_free_polled_device(ud->poll_dev);
34920 +       }
34921 +
34922 +       platform_set_drvdata(client, NULL);
34923 +
34924 +       kfree(ud);
34925 +
34926 +       return 0;
34927 +}
34928 +
34929 +static struct i2c_driver ubicom32hid_driver = {
34930 +       .driver = {
34931 +               .name   = DRIVER_NAME,
34932 +               .owner  = THIS_MODULE,
34933 +       },
34934 +       .probe          = ubicom32hid_probe,
34935 +       .remove         = __exit_p(ubicom32hid_remove),
34936 +       .id_table       = ubicom32hid_id,
34937 +};
34938 +
34939 +/*
34940 + * ubicom32hid_init
34941 + */
34942 +static int __init ubicom32hid_init(void)
34943 +{
34944 +       return i2c_add_driver(&ubicom32hid_driver);
34945 +}
34946 +module_init(ubicom32hid_init);
34947 +
34948 +/*
34949 + * ubicom32hid_exit
34950 + */
34951 +static void __exit ubicom32hid_exit(void)
34952 +{
34953 +       i2c_del_driver(&ubicom32hid_driver);
34954 +}
34955 +module_exit(ubicom32hid_exit);
34956 +
34957 +MODULE_AUTHOR("Pat Tjin <@ubicom.com>")
34958 +MODULE_DESCRIPTION("Ubicom HID driver");
34959 +MODULE_LICENSE("GPL");
34960 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input.c
34961 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input.c   1970-01-01 02:00:00.000000000 +0200
34962 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input.c       2009-12-11 11:45:11.000000000 +0200
34963 @@ -0,0 +1,265 @@
34964 +/*
34965 + * arch/ubicom32/mach-common/ubicom32input.c
34966 + *   Ubicom32 Input driver
34967 + *
34968 + *   based on gpio-keys
34969 + *
34970 + * (C) Copyright 2009, Ubicom, Inc.
34971 + *
34972 + * This file is part of the Ubicom32 Linux Kernel Port.
34973 + *
34974 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34975 + * it and/or modify it under the terms of the GNU General Public License
34976 + * as published by the Free Software Foundation, either version 2 of the
34977 + * License, or (at your option) any later version.
34978 + *
34979 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34980 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34981 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
34982 + * the GNU General Public License for more details.
34983 + *
34984 + * You should have received a copy of the GNU General Public License
34985 + * along with the Ubicom32 Linux Kernel Port.  If not,
34986 + * see <http://www.gnu.org/licenses/>.
34987 + *
34988 + * Ubicom32 implementation derived from (with many thanks):
34989 + *   arch/m68knommu
34990 + *   arch/blackfin
34991 + *   arch/parisc
34992 + *
34993 + *
34994 + * TODO: add groups for inputs which can be sampled together (i.e. I2C)
34995 + */
34996 +
34997 +#include <linux/kernel.h>
34998 +#include <linux/module.h>
34999 +#include <linux/platform_device.h>
35000 +#include <linux/input.h>
35001 +#include <linux/input-polldev.h>
35002 +#include <linux/delay.h>
35003 +#include <linux/gpio.h>
35004 +
35005 +#include <asm/ubicom32input.h>
35006 +
35007 +struct ubicom32input_data {
35008 +       struct ubicom32input_platform_data      *pdata;
35009 +
35010 +       struct input_polled_dev                 *poll_dev;
35011 +
35012 +       /*
35013 +        * collection of previous states for buttons
35014 +        */
35015 +       u8                                      prev_state[0];
35016 +};
35017 +
35018 +/*
35019 + * ubicom32input_poll
35020 + */
35021 +static void ubicom32input_poll(struct input_polled_dev *dev)
35022 +{
35023 +       struct ubicom32input_data *ud =
35024 +               (struct ubicom32input_data *)dev->private;
35025 +       struct ubicom32input_platform_data *pdata = ud->pdata;
35026 +       struct input_dev *id = dev->input;
35027 +       int i;
35028 +       int sync_needed = 0;
35029 +
35030 +       for (i = 0; i < pdata->nbuttons; i++) {
35031 +               const struct ubicom32input_button *ub = &pdata->buttons[i];
35032 +               int state = 0;
35033 +
35034 +               int val = gpio_get_value(ub->gpio);
35035 +
35036 +               /*
35037 +                * Check to see if the state changed from the last time we
35038 +                * looked
35039 +                */
35040 +               if (val == ud->prev_state[i]) {
35041 +                       continue;
35042 +               }
35043 +
35044 +               /*
35045 +                * The state has changed, determine if we are "up" or "down"
35046 +                */
35047 +               ud->prev_state[i] = val;
35048 +
35049 +               if ((!val && ub->active_low) || (val && !ub->active_low)) {
35050 +                       state = 1;
35051 +               }
35052 +
35053 +               input_event(id, ub->type, ub->code, state);
35054 +               sync_needed = 1;
35055 +       }
35056 +
35057 +       if (sync_needed) {
35058 +               input_sync(id);
35059 +       }
35060 +}
35061 +
35062 +/*
35063 + * ubicom32input_probe
35064 + */
35065 +static int __devinit ubicom32input_probe(struct platform_device *pdev)
35066 +{
35067 +       int i;
35068 +       struct ubicom32input_data *ud;
35069 +       struct input_polled_dev *poll_dev;
35070 +       struct input_dev *input_dev;
35071 +       struct ubicom32input_platform_data *pdata;
35072 +       int ret;
35073 +
35074 +       pdata = pdev->dev.platform_data;
35075 +       if (!pdata) {
35076 +               return -EINVAL;
35077 +       }
35078 +
35079 +       ud = kzalloc(sizeof(struct ubicom32input_data) +
35080 +                    pdata->nbuttons, GFP_KERNEL);
35081 +       if (!ud) {
35082 +               return -ENOMEM;
35083 +       }
35084 +       ud->pdata = pdata;
35085 +
35086 +       poll_dev = input_allocate_polled_device();
35087 +       if (!poll_dev) {
35088 +               ret = -ENOMEM;
35089 +               goto fail;
35090 +       }
35091 +
35092 +       platform_set_drvdata(pdev, ud);
35093 +
35094 +       ud->poll_dev = poll_dev;
35095 +       poll_dev->private = ud;
35096 +       poll_dev->poll = ubicom32input_poll;
35097 +
35098 +       /*
35099 +        * Set the poll interval requested, default to 50 msec
35100 +        */
35101 +       if (pdata->poll_interval) {
35102 +               poll_dev->poll_interval = pdata->poll_interval;
35103 +       } else {
35104 +               poll_dev->poll_interval = 50;
35105 +       }
35106 +
35107 +       /*
35108 +        * Setup the input device
35109 +        */
35110 +       input_dev = poll_dev->input;
35111 +       input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input";
35112 +       input_dev->phys = "ubicom32input/input0";
35113 +       input_dev->dev.parent = &pdev->dev;
35114 +       input_dev->id.bustype = BUS_HOST;
35115 +
35116 +       /*
35117 +        * Reserve the GPIOs
35118 +        */
35119 +       for (i = 0; i < pdata->nbuttons; i++) {
35120 +               const struct ubicom32input_button *ub = &pdata->buttons[i];
35121 +
35122 +               ret = gpio_request(ub->gpio,
35123 +                                  ub->desc ? ub->desc : "ubicom32input");
35124 +               if (ret < 0) {
35125 +                       pr_err("ubicom32input: failed to request "
35126 +                              "GPIO %d ret=%d\n", ub->gpio, ret);
35127 +                       goto fail2;
35128 +               }
35129 +
35130 +               ret = gpio_direction_input(ub->gpio);
35131 +               if (ret < 0) {
35132 +                       pr_err("ubicom32input: failed to set "
35133 +                              "GPIO %d to input ret=%d\n", ub->gpio, ret);
35134 +                       goto fail2;
35135 +               }
35136 +
35137 +               /*
35138 +                * Set the previous state to the non-active stae
35139 +                */
35140 +               ud->prev_state[i] = ub->active_low;
35141 +
35142 +               input_set_capability(input_dev,
35143 +                                    ub->type ? ub->type : EV_KEY, ub->code);
35144 +       }
35145 +
35146 +       /*
35147 +        * Register
35148 +        */
35149 +       ret = input_register_polled_device(ud->poll_dev);
35150 +       if (ret) {
35151 +               goto fail2;
35152 +       }
35153 +
35154 +       return 0;
35155 +
35156 +fail2:
35157 +       /*
35158 +        * release the GPIOs we have already requested.
35159 +        */
35160 +       while (--i >= 0) {
35161 +               gpio_free(pdata->buttons[i].gpio);
35162 +       }
35163 +
35164 +fail:
35165 +       printk(KERN_ERR "Ubicom32Input: Failed to register driver %d", ret);
35166 +       platform_set_drvdata(pdev, NULL);
35167 +       input_free_polled_device(poll_dev);
35168 +       kfree(ud);
35169 +       return ret;
35170 +}
35171 +
35172 +/*
35173 + * ubicom32input_remove
35174 + */
35175 +static int __devexit ubicom32input_remove(struct platform_device *dev)
35176 +{
35177 +       struct ubicom32input_data *ud =
35178 +               (struct ubicom32input_data *)platform_get_drvdata(dev);
35179 +       int i;
35180 +
35181 +       /*
35182 +        * Free the GPIOs
35183 +        */
35184 +       for (i = 0; i < ud->pdata->nbuttons; i++) {
35185 +               gpio_free(ud->pdata->buttons[i].gpio);
35186 +       }
35187 +
35188 +       platform_set_drvdata(dev, NULL);
35189 +       input_unregister_polled_device(ud->poll_dev);
35190 +       input_free_polled_device(ud->poll_dev);
35191 +
35192 +       kfree(ud);
35193 +
35194 +       return 0;
35195 +}
35196 +
35197 +static struct platform_driver ubicom32input_driver = {
35198 +       .driver         = {
35199 +               .name   = "ubicom32input",
35200 +               .owner  = THIS_MODULE,
35201 +       },
35202 +       .probe          = ubicom32input_probe,
35203 +       .remove         = __devexit_p(ubicom32input_remove),
35204 +};
35205 +
35206 +/*
35207 + * ubicom32input_init
35208 + */
35209 +static int __devinit ubicom32input_init(void)
35210 +{
35211 +       return platform_driver_register(&ubicom32input_driver);
35212 +}
35213 +
35214 +/*
35215 + * ubicom32input_exit
35216 + */
35217 +static void __exit ubicom32input_exit(void)
35218 +{
35219 +       platform_driver_unregister(&ubicom32input_driver);
35220 +}
35221 +
35222 +module_init(ubicom32input_init);
35223 +module_exit(ubicom32input_exit);
35224 +
35225 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35226 +MODULE_DESCRIPTION("Ubicom32 Input Driver");
35227 +MODULE_LICENSE("GPL");
35228 +MODULE_ALIAS("platform:ubicom32-input");
35229 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input_i2c.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input_i2c.c
35230 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input_i2c.c       1970-01-01 02:00:00.000000000 +0200
35231 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input_i2c.c   2009-12-11 11:45:11.000000000 +0200
35232 @@ -0,0 +1,325 @@
35233 +/*
35234 + * arch/ubicom32/mach-common/ubicom32input_i2c.c
35235 + *   Ubicom32 Input driver for I2C
35236 + *       Supports PCA953x and family
35237 + *
35238 + *   We hog the I2C device, turning it all to input.
35239 + *
35240 + *   Based on gpio-keys, pca953x
35241 + *
35242 + * (C) Copyright 2009, Ubicom, Inc.
35243 + *
35244 + * This file is part of the Ubicom32 Linux Kernel Port.
35245 + *
35246 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35247 + * it and/or modify it under the terms of the GNU General Public License
35248 + * as published by the Free Software Foundation, either version 2 of the
35249 + * License, or (at your option) any later version.
35250 + *
35251 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35252 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35253 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
35254 + * the GNU General Public License for more details.
35255 + *
35256 + * You should have received a copy of the GNU General Public License
35257 + * along with the Ubicom32 Linux Kernel Port.  If not,
35258 + * see <http://www.gnu.org/licenses/>.
35259 + *
35260 + * Ubicom32 implementation derived from (with many thanks):
35261 + *   arch/m68knommu
35262 + *   arch/blackfin
35263 + *   arch/parisc
35264 + */
35265 +#include <linux/kernel.h>
35266 +#include <linux/module.h>
35267 +#include <linux/platform_device.h>
35268 +#include <linux/input.h>
35269 +#include <linux/input-polldev.h>
35270 +#include <linux/i2c.h>
35271 +
35272 +#include <asm/ubicom32input_i2c.h>
35273 +
35274 +#define UBICOM32INPUT_I2C_REG_INPUT    0
35275 +#define UBICOM32INPUT_I2C_REG_OUTPUT   1
35276 +#define UBICOM32INPUT_I2C_REG_INVERT   2
35277 +#define UBICOM32INPUT_I2C_REG_DIRECTION        3
35278 +
35279 +static const struct i2c_device_id ubicom32input_i2c_id[] = {
35280 +       { "ubicom32in_pca9534", 8, },
35281 +       { "ubicom32in_pca9535", 16, },
35282 +       { "ubicom32in_pca9536", 4, },
35283 +       { "ubicom32in_pca9537", 4, },
35284 +       { "ubicom32in_pca9538", 8, },
35285 +       { "ubicom32in_pca9539", 16, },
35286 +       { "ubicom32in_pca9554", 8, },
35287 +       { "ubicom32in_pca9555", 16, },
35288 +       { "ubicom32in_pca9557", 8, },
35289 +       { "ubicom32in_max7310", 8, },
35290 +       { }
35291 +};
35292 +MODULE_DEVICE_TABLE(i2c, ubicom32input_i2c_id);
35293 +
35294 +struct ubicom32input_i2c_data {
35295 +       struct ubicom32input_i2c_platform_data  *pdata;
35296 +
35297 +       struct i2c_client                       *client;
35298 +
35299 +       struct input_polled_dev                 *poll_dev;
35300 +
35301 +       /*
35302 +        * collection of previous states for buttons
35303 +        */
35304 +       uint16_t                                prev_state;
35305 +
35306 +       uint8_t                                 ngpios;
35307 +};
35308 +
35309 +/*
35310 + * ubicom32input_i2c_write_reg
35311 + *     writes a register to the I2C device.
35312 + */
35313 +static int ubicom32input_i2c_write_reg(struct ubicom32input_i2c_data *ud,
35314 +                                      int reg, uint16_t val)
35315 +{
35316 +       int ret;
35317 +
35318 +       if (ud->ngpios <= 8) {
35319 +               ret = i2c_smbus_write_byte_data(ud->client, reg, val);
35320 +       } else {
35321 +               ret = i2c_smbus_write_word_data(ud->client, reg << 1, val);
35322 +       }
35323 +
35324 +       if (ret < 0) {
35325 +               return ret;
35326 +       }
35327 +
35328 +       return 0;
35329 +}
35330 +
35331 +/*
35332 + * ubicom32input_i2c_read_reg
35333 + *     reads a register from the I2C device.
35334 + */
35335 +static int ubicom32input_i2c_read_reg(struct ubicom32input_i2c_data *ud,
35336 +                                     int reg, uint16_t *val)
35337 +{
35338 +       int ret;
35339 +
35340 +       if (ud->ngpios <= 8) {
35341 +               ret = i2c_smbus_read_byte_data(ud->client, reg);
35342 +       } else {
35343 +               ret = i2c_smbus_read_word_data(ud->client, reg);
35344 +       }
35345 +
35346 +       if (ret < 0) {
35347 +               return ret;
35348 +       }
35349 +
35350 +       *val = (uint16_t)ret;
35351 +
35352 +       return 0;
35353 +}
35354 +
35355 +/*
35356 + * ubicom32input_i2c_poll
35357 + */
35358 +static void ubicom32input_i2c_poll(struct input_polled_dev *dev)
35359 +{
35360 +       struct ubicom32input_i2c_data *ud =
35361 +               (struct ubicom32input_i2c_data *)dev->private;
35362 +       struct ubicom32input_i2c_platform_data *pdata = ud->pdata;
35363 +       struct input_dev *id = dev->input;
35364 +       int i;
35365 +       int sync_needed = 0;
35366 +       uint16_t val;
35367 +       uint16_t change_mask;
35368 +
35369 +       /*
35370 +        * Try to get the input status, if we fail, bail out, maybe we can do it
35371 +        * next time.
35372 +        */
35373 +       if (ubicom32input_i2c_read_reg(ud, UBICOM32INPUT_I2C_REG_INPUT, &val)) {
35374 +               return;
35375 +       }
35376 +
35377 +       /*
35378 +        * see if anything changed by using XOR
35379 +        */
35380 +       change_mask = ud->prev_state ^ val;
35381 +       ud->prev_state = val;
35382 +
35383 +       for (i = 0; i < pdata->nbuttons; i++) {
35384 +               const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35385 +               uint16_t mask = 1 << ub->bit;
35386 +               int state = val & mask;
35387 +
35388 +               /*
35389 +                * Check to see if the state changed from the last time we
35390 +                * looked
35391 +                */
35392 +               if (!(change_mask & mask)) {
35393 +                       continue;
35394 +               }
35395 +               input_event(id, ub->type, ub->code, state);
35396 +               sync_needed = 1;
35397 +       }
35398 +
35399 +       if (sync_needed) {
35400 +               input_sync(id);
35401 +       }
35402 +}
35403 +
35404 +/*
35405 + * ubicom32input_i2c_probe
35406 + */
35407 +static int __devinit ubicom32input_i2c_probe(struct i2c_client *client,
35408 +                                            const struct i2c_device_id *id)
35409 +{
35410 +       int i;
35411 +       struct ubicom32input_i2c_data *ud;
35412 +       struct input_polled_dev *poll_dev;
35413 +       struct input_dev *input_dev;
35414 +       struct ubicom32input_i2c_platform_data *pdata;
35415 +       int ret;
35416 +       uint16_t invert_mask = 0;
35417 +
35418 +       pdata = client->dev.platform_data;
35419 +       if (!pdata) {
35420 +               return -EINVAL;
35421 +       }
35422 +
35423 +       ud = kzalloc(sizeof(struct ubicom32input_i2c_data), GFP_KERNEL);
35424 +       if (!ud) {
35425 +               return -ENOMEM;
35426 +       }
35427 +       ud->pdata = pdata;
35428 +       ud->client = client;
35429 +       ud->ngpios = id->driver_data;
35430 +
35431 +       poll_dev = input_allocate_polled_device();
35432 +       if (!poll_dev) {
35433 +               ret = -ENOMEM;
35434 +               goto fail;
35435 +       }
35436 +
35437 +       ud->poll_dev = poll_dev;
35438 +       poll_dev->private = ud;
35439 +       poll_dev->poll = ubicom32input_i2c_poll;
35440 +
35441 +       /*
35442 +        * Set the poll interval requested, default to 100 msec
35443 +        */
35444 +       if (pdata->poll_interval) {
35445 +               poll_dev->poll_interval = pdata->poll_interval;
35446 +       } else {
35447 +               poll_dev->poll_interval = 100;
35448 +       }
35449 +
35450 +       /*
35451 +        * Setup the input device
35452 +        */
35453 +       input_dev = poll_dev->input;
35454 +       input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input I2C";
35455 +       input_dev->phys = "ubicom32input_i2c/input0";
35456 +       input_dev->dev.parent = &client->dev;
35457 +       input_dev->id.bustype = BUS_I2C;
35458 +
35459 +       /*
35460 +        * Set the capabilities
35461 +        */
35462 +       for (i = 0; i < pdata->nbuttons; i++) {
35463 +               const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35464 +
35465 +               if (ub->active_low) {
35466 +                       invert_mask |= (1 << ub->bit);
35467 +               }
35468 +
35469 +               input_set_capability(input_dev,
35470 +                                    ub->type ? ub->type : EV_KEY, ub->code);
35471 +       }
35472 +
35473 +       /*
35474 +        * Setup the device (all inputs)
35475 +        */
35476 +       ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_DIRECTION,
35477 +                                         0xFFFF);
35478 +       if (ret < 0) {
35479 +               goto fail;
35480 +       }
35481 +
35482 +       ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_INVERT,
35483 +                                         invert_mask);
35484 +       if (ret < 0) {
35485 +               goto fail;
35486 +       }
35487 +
35488 +       /*
35489 +        * Register
35490 +        */
35491 +       ret = input_register_polled_device(ud->poll_dev);
35492 +       if (ret) {
35493 +               goto fail;
35494 +       }
35495 +
35496 +       i2c_set_clientdata(client, ud);
35497 +
35498 +       return 0;
35499 +
35500 +fail:
35501 +       printk(KERN_ERR "ubicom32input_i2c: Failed to register driver %d\n",
35502 +              ret);
35503 +       input_free_polled_device(poll_dev);
35504 +       kfree(ud);
35505 +       return ret;
35506 +}
35507 +
35508 +/*
35509 + * ubicom32input_i2c_remove
35510 + */
35511 +static int __devexit ubicom32input_i2c_remove(struct i2c_client *client)
35512 +{
35513 +       struct ubicom32input_i2c_data *ud =
35514 +               (struct ubicom32input_i2c_data *)i2c_get_clientdata(client);
35515 +
35516 +       i2c_set_clientdata(client, NULL);
35517 +       input_unregister_polled_device(ud->poll_dev);
35518 +       input_free_polled_device(ud->poll_dev);
35519 +
35520 +       kfree(ud);
35521 +
35522 +       return 0;
35523 +}
35524 +
35525 +static struct i2c_driver ubicom32input_i2c_driver = {
35526 +       .driver         = {
35527 +               .name   = "ubicom32input_i2c",
35528 +               .owner  = THIS_MODULE,
35529 +       },
35530 +       .remove         = __devexit_p(ubicom32input_i2c_remove),
35531 +       .id_table       = ubicom32input_i2c_id,
35532 +       .probe          = ubicom32input_i2c_probe,
35533 +};
35534 +
35535 +/*
35536 + * ubicom32input_i2c_init
35537 + */
35538 +static int __devinit ubicom32input_i2c_init(void)
35539 +{
35540 +       return i2c_add_driver(&ubicom32input_i2c_driver);
35541 +}
35542 +
35543 +/*
35544 + * ubicom32input_i2c_exit
35545 + */
35546 +static void __exit ubicom32input_i2c_exit(void)
35547 +{
35548 +       i2c_del_driver(&ubicom32input_i2c_driver);
35549 +}
35550 +
35551 +module_init(ubicom32input_i2c_init);
35552 +module_exit(ubicom32input_i2c_exit);
35553 +
35554 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35555 +MODULE_DESCRIPTION("Ubicom32 Input Driver I2C");
35556 +MODULE_LICENSE("GPL");
35557 +MODULE_ALIAS("platform:ubicom32-input");
35558 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/usb.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb.c
35559 --- linux-2.6.30.10/arch/ubicom32/mach-common/usb.c     1970-01-01 02:00:00.000000000 +0200
35560 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb.c 2009-12-11 11:45:11.000000000 +0200
35561 @@ -0,0 +1,132 @@
35562 +/*
35563 + * arch/ubicom32/mach-common/ip5k_usb.c
35564 + *   Ubicom32 architecture usb support.
35565 + *
35566 + * (C) Copyright 2009, Ubicom, Inc.
35567 + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
35568 + * Author: Kevin Hilman
35569 + *
35570 + * This file is part of the Ubicom32 Linux Kernel Port.
35571 + *
35572 + * The Ubicom32 Linux Kernel Port is free software: you can
35573 + * redistribute it and/or modify it under the terms of the GNU General
35574 + * Public License as published by the Free Software Foundation, either
35575 + * version 2 of the License, or (at your option) any later version.
35576 + *
35577 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35578 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35579 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
35580 + * See the GNU General Public License for more details.
35581 + *
35582 + * You should have received a copy of the GNU General Public License
35583 + * along with the Ubicom32 Linux Kernel Port.  If not,
35584 + * see <http://www.gnu.org/licenses/>.
35585 + *
35586 + * Ubicom32 implementation derived from (with many thanks):
35587 + *   arch/m68knommu
35588 + *   arch/blackfin
35589 + *   arch/parisc
35590 + */
35591 +
35592 +#include <linux/types.h>
35593 +#include <linux/errno.h>
35594 +#include <linux/delay.h>
35595 +#include <linux/platform_device.h>
35596 +#include <linux/dma-mapping.h>
35597 +#include <linux/usb/musb.h>
35598 +#include <asm/devtree.h>
35599 +#include <asm/ip5000.h>
35600 +#include "usb_tio.h"
35601 +
35602 +struct usbtionode *unode = NULL;
35603 +
35604 +static struct resource usb_resources[] = {
35605 +       [0] = {
35606 +               .start  = RJ + 0x800,
35607 +               .end    = RJ + 0x1000,
35608 +               .flags  = IORESOURCE_MEM,
35609 +       },
35610 +       [1] = { /* general IRQ */
35611 +               .start  = 1, /* this is a dummy value, the real irq number is passed from kernel_setup_param */
35612 +               .flags  = IORESOURCE_IRQ,
35613 +       },
35614 +};
35615 +
35616 +
35617 +static struct musb_hdrc_eps_bits musb_eps[] = {
35618 +       { "ep1_tx", 4, },
35619 +       { "ep1_rx", 4, },
35620 +       { "ep2_tx", 10, },
35621 +       { "ep2_rx", 10, },
35622 +       { "ep3_tx", 9, },
35623 +       { "ep3_rx", 9, },
35624 +       { "ep4_tx", 9, },
35625 +       { "ep4_rx", 9, },
35626 +       { "ep5_tx", 6, },
35627 +       { "ep5_rx", 6, },
35628 +};
35629 +
35630 +static struct musb_hdrc_config musb_config = {
35631 +       .multipoint     = true,
35632 +       .dyn_fifo       = false,
35633 +       .soft_con       = true,
35634 +       .dma            = false,
35635 +
35636 +       .num_eps        = 6,
35637 +       .dma_channels   = 0,
35638 +       .ram_bits       = 0,
35639 +       .eps_bits       = musb_eps,
35640 +};
35641 +
35642 +static struct musb_hdrc_platform_data usb_data = {
35643 +#ifdef CONFIG_USB_MUSB_OTG
35644 +       .mode           = MUSB_OTG,
35645 +#else
35646 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
35647 +       .mode           = MUSB_HOST,
35648 +#else
35649 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
35650 +       .mode           = MUSB_PERIPHERAL,
35651 +#endif
35652 +#endif
35653 +#endif
35654 +       .clock          = NULL,
35655 +       .set_clock      = NULL,
35656 +       .config         = &musb_config,
35657 +};
35658 +
35659 +static struct platform_device musb_device = {
35660 +       .name           = "musb_hdrc",
35661 +       .id             = 0,
35662 +       .dev = {
35663 +               .platform_data          = &usb_data,
35664 +               .dma_mask               = NULL,
35665 +               .coherent_dma_mask      = 0,
35666 +       },
35667 +       .resource       = usb_resources,
35668 +       .num_resources  = ARRAY_SIZE(usb_resources),
35669 +};
35670 +
35671 +struct usbtio_node *usb_node = NULL;
35672 +void ubi32_usb_init(void)
35673 +{
35674 +       /*
35675 +        * See if the usbtio is in the device tree.
35676 +        */
35677 +       usb_node = (struct usbtio_node *)devtree_find_node("usbtio");
35678 +       if (!usb_node) {
35679 +               printk(KERN_WARNING "usb init failed\n");
35680 +               return;
35681 +       }
35682 +
35683 +       usb_resources[1].start = usb_node->dn.recvirq;
35684 +       if (platform_device_register(&musb_device) < 0) {
35685 +               printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
35686 +               return;
35687 +       }
35688 +}
35689 +
35690 +void ubi32_usb_int_clr(void)
35691 +{
35692 +        UBICOM32_IO_PORT(RJ)->int_clr = (1 << 3);
35693 +}
35694 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.c
35695 --- linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.c 1970-01-01 02:00:00.000000000 +0200
35696 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.c     2009-12-11 11:45:11.000000000 +0200
35697 @@ -0,0 +1,356 @@
35698 +/*
35699 + * arch/ubicom32/mach-common/usb_tio.c
35700 + *  Linux side Ubicom USB TIO driver
35701 + *
35702 + * (C) Copyright 2009, Ubicom, Inc.
35703 + *
35704 + * This file is part of the Ubicom32 Linux Kernel Port.
35705 + *
35706 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35707 + * it and/or modify it under the terms of the GNU General Public License
35708 + * as published by the Free Software Foundation, either version 2 of the
35709 + * License, or (at your option) any later version.
35710 + *
35711 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35712 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35713 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
35714 + * the GNU General Public License for more details.
35715 + *
35716 + * You should have received a copy of the GNU General Public License
35717 + * along with the Ubicom32 Linux Kernel Port.  If not,
35718 + * see <http://www.gnu.org/licenses/>.
35719 + *
35720 + * Ubicom32 implementation derived from (with many thanks):
35721 + *   arch/m68knommu
35722 + *   arch/blackfin
35723 + *   arch/parisc
35724 + */
35725 +#include <linux/module.h>
35726 +#include <linux/spinlock.h>
35727 +#include <linux/slab.h>
35728 +#include <asm/devtree.h>
35729 +#include "usb_tio.h"
35730 +
35731 +#ifdef CONFIG_SMP
35732 +static DEFINE_SPINLOCK(tio_lock);
35733 +#define USB_TIO_LOCK(lock, flag) spin_lock_irqsave(lock, flag)
35734 +#define USB_TIO_UNLOCK(lock, flag) spin_unlock_irqrestore(lock, flag)
35735 +#define USB_TIO_LOCK_ISLOCKED(lock) spin_try_lock(lock)
35736 +#else
35737 +#define USB_TIO_LOCK(lock, flag) local_irq_save(flag)
35738 +#define USB_TIO_UNLOCK(lock, flag) local_irq_restore(flag)
35739 +#endif
35740 +
35741 +spinlock_t usb_tio_lock;
35742 +
35743 +/*
35744 + * usb_tio_set_hrt_interrupt()
35745 + */
35746 +static inline void usb_tio_set_hrt_interrupt(void)
35747 +{
35748 +       ubicom32_set_interrupt(usb_node->dn.sendirq);
35749 +}
35750 +
35751 +static inline void usb_tio_wait_hrt(void)
35752 +{
35753 +       while (unlikely(usb_node->pdesc));
35754 +}
35755 +
35756 +#if defined(USB_TIO_DEBUG)
35757 +static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req)
35758 +{
35759 +       BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2);
35760 +}
35761 +
35762 +static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req)
35763 +{
35764 +       req->magic = 0;
35765 +}
35766 +#endif
35767 +
35768 +static void usb_tio_request_set_magic(volatile struct usb_tio_request *req)
35769 +{
35770 +       req->magic = USB_TIO_REQUEST_MAGIC1;
35771 +}
35772 +
35773 +/*
35774 + * usb_tio_commit_request()
35775 + */
35776 +static inline void usb_tio_commit_request(volatile struct usb_tio_request *request)
35777 +{
35778 +       wmb();
35779 +       usb_node->pdesc = request;
35780 +
35781 +       /*
35782 +        * next thing to do is alway checking if (usb_node->pdesc == NULL)
35783 +        * to see if the request is done, so add a mb() here
35784 +        */
35785 +       mb();
35786 +       usb_tio_set_hrt_interrupt();
35787 +}
35788 +
35789 +/*
35790 + * usb_tio_read_u16()
35791 + *     Synchronously read 16 bits.
35792 + */
35793 +u8_t usb_tio_read_u16(u32_t address, u16_t *data)
35794 +{
35795 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35796 +       unsigned long flag;
35797 +
35798 +       /*
35799 +        * Wait for any previous request to complete and then make this request.
35800 +        */
35801 +       USB_TIO_LOCK(&tio_lock, flag);
35802 +       usb_tio_wait_hrt();
35803 +
35804 +       /*
35805 +        * Fill in the request.
35806 +        */
35807 +       tio_req->address = address;
35808 +       tio_req->cmd = USB_TIO_READ16_SYNC;
35809 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35810 +       usb_tio_commit_request(tio_req);
35811 +
35812 +       /*
35813 +        * Wait for the result to show up.
35814 +        */
35815 +       usb_tio_wait_hrt();
35816 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35817 +       *data = (u16_t)tio_req->data;
35818 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35819 +       USB_TIO_UNLOCK(&tio_lock, flag);
35820 +       return USB_TIO_OK;
35821 +}
35822 +
35823 +/*
35824 + * usb_tio_read_u8()
35825 + *     Synchronously read 16 bits.
35826 + */
35827 +u8_t usb_tio_read_u8(u32_t address, u8_t *data)
35828 +{
35829 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35830 +       unsigned long flag;
35831 +
35832 +       /*
35833 +        * Wait for any previous request to complete and then make this request.
35834 +        */
35835 +       USB_TIO_LOCK(&tio_lock, flag);
35836 +       usb_tio_wait_hrt();
35837 +
35838 +       /*
35839 +        * Fill in the request.
35840 +        */
35841 +       tio_req->address = address;
35842 +       tio_req->cmd = USB_TIO_READ8_SYNC;
35843 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35844 +
35845 +       /*
35846 +        * commit the request
35847 +        */
35848 +       usb_tio_commit_request(tio_req);
35849 +
35850 +       /*
35851 +        * Wait for the result to show up.
35852 +        */
35853 +       usb_tio_wait_hrt();
35854 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35855 +       *data = (u8_t)tio_req->data;
35856 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35857 +       USB_TIO_UNLOCK(&tio_lock, flag);
35858 +       return USB_TIO_OK;
35859 +}
35860 +
35861 +/*
35862 + * usb_tio_write_u16()
35863 + *     Asynchronously  write 16 bits.
35864 + */
35865 +u8_t usb_tio_write_u16(u32_t address, u16_t data)
35866 +{
35867 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35868 +       unsigned long flag;
35869 +
35870 +       /*
35871 +        * Wait for any previous write or pending read to complete.
35872 +        */
35873 +       USB_TIO_LOCK(&tio_lock, flag);
35874 +       usb_tio_wait_hrt();
35875 +
35876 +       tio_req->address = address;
35877 +       tio_req->data = data;
35878 +       tio_req->cmd = USB_TIO_WRITE16_ASYNC;
35879 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35880 +
35881 +       /*
35882 +        * commit the request
35883 +        */
35884 +       usb_tio_commit_request(tio_req);
35885 +       USB_TIO_UNLOCK(&tio_lock, flag);
35886 +       return USB_TIO_OK;
35887 +}
35888 +
35889 +/*
35890 + * usb_tio_write_u8()
35891 + *     Asynchronously  write 8 bits.
35892 + */
35893 +u8_t usb_tio_write_u8(u32_t address, u8_t data)
35894 +{
35895 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35896 +       unsigned long flag;
35897 +
35898 +       /*
35899 +        * Wait for any previous write or pending read to complete.
35900 +        */
35901 +       USB_TIO_LOCK(&tio_lock, flag);
35902 +       usb_tio_wait_hrt();
35903 +
35904 +       tio_req->address = address;
35905 +       tio_req->data = data;
35906 +       tio_req->cmd = USB_TIO_WRITE8_ASYNC;
35907 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35908 +
35909 +       /*
35910 +        * commit the request
35911 +        */
35912 +       usb_tio_commit_request(tio_req);
35913 +       USB_TIO_UNLOCK(&tio_lock, flag);
35914 +       return USB_TIO_OK;
35915 +}
35916 +
35917 +/*
35918 + * usb_tio_read_fifo()
35919 + *     Synchronously read FIFO.
35920 + */
35921 +u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes)
35922 +{
35923 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35924 +       unsigned long flag;
35925 +
35926 +       /*
35927 +        * Wait for any previous request to complete and then make this request.
35928 +        */
35929 +       USB_TIO_LOCK(&tio_lock, flag);
35930 +       usb_tio_wait_hrt();
35931 +
35932 +       /*
35933 +        * Fill in the request.
35934 +        */
35935 +       tio_req->address = address;
35936 +       tio_req->cmd = USB_TIO_READ_FIFO_SYNC;
35937 +       tio_req->buffer = buffer;
35938 +       tio_req->transfer_length = bytes;
35939 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35940 +
35941 +       /*
35942 +        * commit the request
35943 +        */
35944 +       usb_tio_commit_request(tio_req);
35945 +
35946 +        /*
35947 +        * Wait for the result to show up.
35948 +        */
35949 +       usb_tio_wait_hrt();
35950 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35951 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35952 +       USB_TIO_UNLOCK(&tio_lock, flag);
35953 +       return USB_TIO_OK;
35954 +}
35955 +
35956 +/*
35957 + * usb_tio_write_fifo()
35958 + *     Synchronously  write 32 bits.
35959 + */
35960 +u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes)
35961 +{
35962 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35963 +       unsigned long flag;
35964 +
35965 +       USB_TIO_LOCK(&tio_lock, flag);
35966 +       usb_tio_wait_hrt();
35967 +
35968 +       tio_req->address = address;
35969 +       tio_req->buffer = buffer;
35970 +       tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
35971 +       tio_req->transfer_length = bytes;
35972 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35973 +       /*
35974 +        * commit the request
35975 +        */
35976 +       usb_tio_commit_request(tio_req);
35977 +
35978 +       /*
35979 +        * Wait for the result to show up.
35980 +        */
35981 +       usb_tio_wait_hrt();
35982 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35983 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35984 +       USB_TIO_UNLOCK(&tio_lock, flag);
35985 +       return USB_TIO_OK;
35986 +}
35987 +
35988 +/*
35989 + * usb_tio_write_fifo_async()
35990 + *     Asynchronously write 32 bits.
35991 + */
35992 +u8_t usb_tio_write_fifo_async(u32_t address, u32_t buffer, u32_t bytes)
35993 +{
35994 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35995 +       unsigned long flag;
35996 +
35997 +       USB_TIO_LOCK(&tio_lock, flag);
35998 +       usb_tio_wait_hrt();
35999 +
36000 +       tio_req->address = address;
36001 +
36002 +       /*
36003 +        * Is it necessary to make a local copy of the buffer? Any chance the URB is aborted before TIO finished the FIFO write?
36004 +        */
36005 +       tio_req->buffer = buffer;
36006 +       tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
36007 +       tio_req->transfer_length = bytes;
36008 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
36009 +       /*
36010 +        * commit the request
36011 +        */
36012 +       usb_tio_commit_request(tio_req);
36013 +       USB_TIO_UNLOCK(&tio_lock, flag);
36014 +       return USB_TIO_OK;
36015 +}
36016 +
36017 +/*
36018 + * usb_tio_read_int_status()
36019 + *     read and clear the interrupt status registers
36020 + */
36021 +void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
36022 +{
36023 +
36024 +       /*
36025 +        * clear the interrupt must be syncronized with the TIO thread to prevent the racing condiiton
36026 +        * that TIO thread try to set it at same time
36027 +        */
36028 +       asm volatile (
36029 +       "1:     bset (%0), (%0), #0     \n\t" \
36030 +       "       jmpne.f 1b              \n\t" \
36031 +               :
36032 +               : "a" (&usb_node->usb_vp_control)
36033 +               : "memory", "cc"
36034 +       );
36035 +
36036 +       *int_usb = usb_node->usb_vp_hw_int_usb;
36037 +       *int_tx  = cpu_to_le16(usb_node->usb_vp_hw_int_tx);
36038 +       *int_rx  = cpu_to_le16(usb_node->usb_vp_hw_int_rx);
36039 +
36040 +       //printk(KERN_INFO "int read %x, %x, %x\n", *int_usb, *int_tx, *int_rx);
36041 +
36042 +       /*
36043 +        * The interrupt status register is read-clean, so clear it now
36044 +        */
36045 +       usb_node->usb_vp_hw_int_usb = 0;
36046 +       usb_node->usb_vp_hw_int_tx = 0;
36047 +       usb_node->usb_vp_hw_int_rx = 0;
36048 +
36049 +       /*
36050 +        * release the lock bit
36051 +        */
36052 +       usb_node->usb_vp_control &= 0xfffe;
36053 +}
36054 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.h
36055 --- linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.h 1970-01-01 02:00:00.000000000 +0200
36056 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.h     2009-12-11 11:45:11.000000000 +0200
36057 @@ -0,0 +1,111 @@
36058 +/*
36059 + * arch/ubicom32/mach-common/usb_tio.h
36060 + *   Definitions for usb_tio.c
36061 + *
36062 + * (C) Copyright 2009, Ubicom, Inc.
36063 + *
36064 + * This file is part of the Ubicom32 Linux Kernel Port.
36065 + *
36066 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36067 + * it and/or modify it under the terms of the GNU General Public License
36068 + * as published by the Free Software Foundation, either version 2 of the
36069 + * License, or (at your option) any later version.
36070 + *
36071 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36072 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36073 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36074 + * the GNU General Public License for more details.
36075 + *
36076 + * You should have received a copy of the GNU General Public License
36077 + * along with the Ubicom32 Linux Kernel Port.  If not,
36078 + * see <http://www.gnu.org/licenses/>.
36079 + *
36080 + * Ubicom32 implementation derived from (with many thanks):
36081 + *   arch/m68knommu
36082 + *   arch/blackfin
36083 + *   arch/parisc
36084 + */
36085 +
36086 +#include <linux/version.h>
36087 +#include <linux/kernel.h>
36088 +#include <linux/types.h>
36089 +#include <linux/errno.h>
36090 +#include <linux/err.h>
36091 +#include <asm/devtree.h>
36092 +#include <asm/ip5000.h>
36093 +
36094 +#ifndef _USB_TIO_H
36095 +#define _USB_TIO_H
36096 +
36097 +#undef  USB_TIO_DEBUG
36098 +
36099 +#define USB_TIO_REQUEST_MAGIC1 0x2307
36100 +#define USB_TIO_REQUEST_MAGIC2 0x0789
36101 +#if defined(USB_TIO_DEBUG)
36102 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req)      usb_tio_request_verify_magic(req)
36103 +#define USB_TIO_REQUEST_SET_MAGIC(req)          usb_tio_request_set_magic(req)
36104 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req)       usb_tio_request_clear_magic(req)
36105 +#else
36106 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req)
36107 +#define USB_TIO_REQUEST_SET_MAGIC(req)          usb_tio_request_set_magic(req)
36108 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req)
36109 +#endif
36110 +
36111 +enum USB_TIO_status {
36112 +       USB_TIO_OK,
36113 +       USB_TIO_ERROR,
36114 +       USB_TIO_ERROR_COMMIT,
36115 +};
36116 +
36117 +enum USB_TIO_cmds {
36118 +       USB_TIO_READ16_SYNC,
36119 +       USB_TIO_READ8_SYNC,
36120 +       USB_TIO_READ_FIFO_SYNC,
36121 +
36122 +       USB_TIO_WRITE16_ASYNC,
36123 +       USB_TIO_WRITE8_ASYNC,
36124 +       USB_TIO_WRITE_FIFO_ASYNC,
36125 +
36126 +       USB_TIO_WRITE16_SYNC,
36127 +       USB_TIO_WRITE8_SYNC,
36128 +       USB_TIO_WRITE_FIFO_SYNC,
36129 +
36130 +};
36131 +
36132 +enum USB_TIO_state {
36133 +       USB_TIO_NORMAL,
36134 +       USB_TIO_DMA_SETUP,
36135 +};
36136 +
36137 +struct usb_tio_request {
36138 +       volatile u32_t address;
36139 +       union {
36140 +               volatile u32_t data;
36141 +               volatile u32_t buffer;
36142 +       };
36143 +       volatile u16_t cmd;
36144 +       const volatile u16_t status;
36145 +       volatile u32_t transfer_length;
36146 +       volatile u32_t thread_mask;
36147 +       volatile u16_t magic;
36148 +};
36149 +
36150 +struct usbtio_node {
36151 +       struct devtree_node dn;
36152 +       volatile struct usb_tio_request * volatile pdesc;
36153 +       struct usb_tio_request  request;
36154 +       volatile u32_t usb_vp_config;
36155 +       volatile u32_t usb_vp_control;
36156 +       const volatile u32_t usb_vp_status;
36157 +       volatile u16_t usb_vp_hw_int_tx;
36158 +       volatile u16_t usb_vp_hw_int_rx;
36159 +       volatile u8_t  usb_vp_hw_int_usb;
36160 +       volatile u8_t usb_vp_hw_int_mask_usb;
36161 +        volatile u16_t usb_vp_hw_int_mask_tx;
36162 +        volatile u16_t usb_vp_hw_int_mask_rx;
36163 +
36164 +};
36165 +
36166 +extern struct usbtio_node *usb_node;
36167 +extern void ubi32_usb_init(void);
36168 +#endif
36169 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/vdc_tio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/vdc_tio.c
36170 --- linux-2.6.30.10/arch/ubicom32/mach-common/vdc_tio.c 1970-01-01 02:00:00.000000000 +0200
36171 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/vdc_tio.c     2009-12-11 11:45:11.000000000 +0200
36172 @@ -0,0 +1,111 @@
36173 +/*
36174 + * arch/ubicom32/mach-common/vdc_tio.c
36175 + *   Generic initialization for VDC
36176 + *
36177 + * (C) Copyright 2009, Ubicom, Inc.
36178 + *
36179 + * This file is part of the Ubicom32 Linux Kernel Port.
36180 + *
36181 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36182 + * it and/or modify it under the terms of the GNU General Public License
36183 + * as published by the Free Software Foundation, either version 2 of the
36184 + * License, or (at your option) any later version.
36185 + *
36186 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36187 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36188 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36189 + * the GNU General Public License for more details.
36190 + *
36191 + * You should have received a copy of the GNU General Public License
36192 + * along with the Ubicom32 Linux Kernel Port.  If not,
36193 + * see <http://www.gnu.org/licenses/>.
36194 + *
36195 + * Ubicom32 implementation derived from (with many thanks):
36196 + *   arch/m68knommu
36197 + *   arch/blackfin
36198 + *   arch/parisc
36199 + */
36200 +
36201 +#include <linux/platform_device.h>
36202 +#include <linux/types.h>
36203 +
36204 +#include <asm/devtree.h>
36205 +#include <asm/vdc_tio.h>
36206 +
36207 +/*
36208 + * Resources that this driver uses
36209 + */
36210 +static struct resource vdc_tio_resources[] = {
36211 +       /*
36212 +        * Send IRQ
36213 +        */
36214 +       [0] = {
36215 +               /*
36216 +                * The init routine will query the devtree and fill this in
36217 +                */
36218 +               .flags  = IORESOURCE_IRQ,
36219 +       },
36220 +
36221 +       /*
36222 +        * Receive IRQ (optional)
36223 +        */
36224 +       [1] = {
36225 +               /*
36226 +                * The init routine will query the devtree and fill this in
36227 +                */
36228 +               .flags  = IORESOURCE_IRQ,
36229 +       },
36230 +
36231 +       /*
36232 +        * Memory Mapped Registers
36233 +        */
36234 +       [2] = {
36235 +               /*
36236 +                * The init routine will query the devtree and fill this in
36237 +                */
36238 +               .flags  = IORESOURCE_MEM,
36239 +       },
36240 +};
36241 +
36242 +/*
36243 + * The platform_device structure which is passed to the driver
36244 + */
36245 +static struct platform_device vdc_tio_platform_device = {
36246 +       .name           = "ubicom32fb",
36247 +       .id             = -1,
36248 +       .resource       = vdc_tio_resources,
36249 +       .num_resources  = ARRAY_SIZE(vdc_tio_resources),
36250 +};
36251 +
36252 +/*
36253 + * vdc_tio_init
36254 + *     Checks the device tree and instantiates the driver if found
36255 + */
36256 +void __init vdc_tio_init(void)
36257 +{
36258 +       /*
36259 +        * Check the device tree for the vdc_tio
36260 +        */
36261 +       struct vdc_tio_node *vdc_node =
36262 +               (struct vdc_tio_node *)devtree_find_node("vdctio");
36263 +       if (!vdc_node) {
36264 +               printk(KERN_WARNING "No vdc_tio found\n");
36265 +               return;
36266 +       }
36267 +
36268 +       /*
36269 +        * Fill in the resources and platform data from devtree information
36270 +        */
36271 +       vdc_tio_resources[0].start = vdc_node->dn.sendirq;
36272 +       vdc_tio_resources[1].start = vdc_node->dn.recvirq;
36273 +       vdc_tio_resources[2].start = (u32_t)vdc_node->regs;
36274 +       vdc_tio_resources[2].end = (u32_t)vdc_node->regs +
36275 +               sizeof(struct vdc_tio_vp_regs);
36276 +
36277 +       /*
36278 +        * Try to get the device registered
36279 +        */
36280 +       if (platform_device_register(&vdc_tio_platform_device) < 0) {
36281 +               printk(KERN_WARNING "VDC failed to register\n");
36282 +       }
36283 +}
36284 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160dev.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160dev.c
36285 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160dev.c   1970-01-01 02:00:00.000000000 +0200
36286 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160dev.c       2009-12-11 11:45:11.000000000 +0200
36287 @@ -0,0 +1,109 @@
36288 +/*
36289 + * arch/ubicom32/mach-ip5k/board-ip5160dev.c
36290 + *   Platform initialization for ip5160dev board.
36291 + *
36292 + * (C) Copyright 2009, Ubicom, Inc.
36293 + *
36294 + * This file is part of the Ubicom32 Linux Kernel Port.
36295 + *
36296 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36297 + * it and/or modify it under the terms of the GNU General Public License
36298 + * as published by the Free Software Foundation, either version 2 of the
36299 + * License, or (at your option) any later version.
36300 + *
36301 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36302 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36303 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36304 + * the GNU General Public License for more details.
36305 + *
36306 + * You should have received a copy of the GNU General Public License
36307 + * along with the Ubicom32 Linux Kernel Port.  If not,
36308 + * see <http://www.gnu.org/licenses/>.
36309 + *
36310 + * Ubicom32 implementation derived from (with many thanks):
36311 + *   arch/m68knommu
36312 + *   arch/blackfin
36313 + *   arch/parisc
36314 + */
36315 +#include <linux/device.h>
36316 +#include <linux/platform_device.h>
36317 +#include <linux/gpio.h>
36318 +
36319 +#include <asm/board.h>
36320 +#include <asm/machdep.h>
36321 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36322 +#include <asm/ubicom32suart.h>
36323 +#endif
36324 +
36325 +/*
36326 + * Factory Default Button on the board at PXn
36327 + * TODO: This is just a placeholder and it needs to include proper header files
36328 + */
36329 +struct ubicom32fdb_platform_data {
36330 +       int             fdb_gpio;
36331 +       bool            fdb_polarity;
36332 +};
36333 +
36334 +static struct ubicom32fdb_platform_data ip5160dev_fdb_data = {
36335 +       .fdb_gpio               = 0,
36336 +       .fdb_polarity           = true,
36337 +};
36338 +
36339 +static struct platform_device ip5160dev_fdb_device = {
36340 +       .name   = "ubicom32fdb",
36341 +       .id     = -1,
36342 +       .dev    = {
36343 +               .platform_data = &ip5160dev_fdb_data,
36344 +       },
36345 +};
36346 +
36347 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36348 +static struct resource ip5160dev_ubicom32_suart_resources[] = {
36349 +        {
36350 +               .start  = RD,
36351 +               .end    = RD,
36352 +               .flags  = IORESOURCE_MEM,
36353 +        },
36354 +        {
36355 +               .start  = PORT_OTHER_INT(RD),
36356 +               .end    = PORT_OTHER_INT(RD),
36357 +               .flags  = IORESOURCE_IRQ,
36358 +        },
36359 +        {
36360 +               .start  = 240000000,
36361 +               .end    = 240000000,
36362 +               .flags  = UBICOM32_SUART_IORESOURCE_CLOCK,
36363 +        },
36364 +};
36365 +
36366 +static struct platform_device ip5160dev_ubicom32_suart_device = {
36367 +       .name           = "ubicom32suart",
36368 +       .id             = -1,
36369 +        .num_resources  = ARRAY_SIZE(ip5160dev_ubicom32_suart_resources),
36370 +        .resource       = ip5160dev_ubicom32_suart_resources,
36371 +};
36372 +#endif
36373 +
36374 +/*
36375 + * List of all devices in our system
36376 + */
36377 +static struct platform_device *ip5160dev_devices[] __initdata = {
36378 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36379 +       &ip5160dev_ubicom32_suart_device,
36380 +#endif
36381 +       &ip5160dev_fdb_device,
36382 +};
36383 +
36384 +/*
36385 + * ip5160dev_init
36386 + *     Called to add the devices which we have on this board
36387 + */
36388 +static int __init ip5160dev_init(void)
36389 +{
36390 +       ubi_gpio_init();
36391 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36392 +       platform_add_devices(ip5160dev_devices, ARRAY_SIZE(ip5160dev_devices));
36393 +       return 0;
36394 +}
36395 +
36396 +arch_initcall(ip5160dev_init);
36397 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160rgw.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36398 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160rgw.c   1970-01-01 02:00:00.000000000 +0200
36399 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160rgw.c       2009-12-11 11:45:11.000000000 +0200
36400 @@ -0,0 +1,75 @@
36401 +/*
36402 + * arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36403 + *   Platform initialization for ip5160rgw board.
36404 + *
36405 + * (C) Copyright 2009, Ubicom, Inc.
36406 + *
36407 + * This file is part of the Ubicom32 Linux Kernel Port.
36408 + *
36409 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36410 + * it and/or modify it under the terms of the GNU General Public License
36411 + * as published by the Free Software Foundation, either version 2 of the
36412 + * License, or (at your option) any later version.
36413 + *
36414 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36415 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36416 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36417 + * the GNU General Public License for more details.
36418 + *
36419 + * You should have received a copy of the GNU General Public License
36420 + * along with the Ubicom32 Linux Kernel Port.  If not,
36421 + * see <http://www.gnu.org/licenses/>.
36422 + *
36423 + * Ubicom32 implementation derived from (with many thanks):
36424 + *   arch/m68knommu
36425 + *   arch/blackfin
36426 + *   arch/parisc
36427 + */
36428 +#include <linux/device.h>
36429 +#include <linux/platform_device.h>
36430 +#include <linux/gpio.h>
36431 +#include <asm/board.h>
36432 +#include <asm/machdep.h>
36433 +
36434 +/*
36435 + * Factory Default Button on the board at PXn
36436 + * TODO: This is just a placeholder and it needs to include proper header files
36437 + */
36438 +struct ubicom32fdb_platform_data {
36439 +       int             fdb_gpio;
36440 +       bool            fdb_polarity;
36441 +};
36442 +
36443 +static struct ubicom32fdb_platform_data ip5160rgw_fdb_data = {
36444 +       .fdb_gpio               = 0,
36445 +       .fdb_polarity           = true,
36446 +};
36447 +
36448 +static struct platform_device ip5160rgw_fdb_device = {
36449 +       .name   = "ubicom32fdb",
36450 +       .id     = -1,
36451 +       .dev    = {
36452 +               .platform_data = &ip5160rgw_fdb_data,
36453 +       },
36454 +};
36455 +
36456 +/*
36457 + * List of all devices in our system
36458 + */
36459 +static struct platform_device *ip5160rgw_devices[] __initdata = {
36460 +       &ip5160rgw_fdb_device,
36461 +};
36462 +
36463 +/*
36464 + * ip5160rgw_init
36465 + *     Called to add the devices which we have on this board
36466 + */
36467 +static int __init ip5160rgw_init(void)
36468 +{
36469 +       ubi_gpio_init();
36470 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36471 +       platform_add_devices(ip5160rgw_devices, ARRAY_SIZE(ip5160rgw_devices));
36472 +       return 0;
36473 +}
36474 +
36475 +arch_initcall(ip5160rgw_init);
36476 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5170dpf.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36477 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5170dpf.c   1970-01-01 02:00:00.000000000 +0200
36478 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5170dpf.c       2009-12-11 11:45:11.000000000 +0200
36479 @@ -0,0 +1,279 @@
36480 +/*
36481 + * arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36482 + *   Platform initialization for ip5160dpf board.
36483 + *
36484 + * (C) Copyright 2009, Ubicom, Inc.
36485 + *
36486 + * This file is part of the Ubicom32 Linux Kernel Port.
36487 + *
36488 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36489 + * it and/or modify it under the terms of the GNU General Public License
36490 + * as published by the Free Software Foundation, either version 2 of the
36491 + * License, or (at your option) any later version.
36492 + *
36493 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36494 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36495 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36496 + * the GNU General Public License for more details.
36497 + *
36498 + * You should have received a copy of the GNU General Public License
36499 + * along with the Ubicom32 Linux Kernel Port.  If not,
36500 + * see <http://www.gnu.org/licenses/>.
36501 + *
36502 + * Ubicom32 implementation derived from (with many thanks):
36503 + *   arch/m68knommu
36504 + *   arch/blackfin
36505 + *   arch/parisc
36506 + */
36507 +#include <linux/device.h>
36508 +#include <linux/platform_device.h>
36509 +#include <linux/gpio.h>
36510 +#include <linux/leds.h>
36511 +
36512 +#include <linux/i2c.h>
36513 +#include <linux/i2c-gpio.h>
36514 +
36515 +#include <linux/input.h>
36516 +#include <asm/board.h>
36517 +#include <asm/machdep.h>
36518 +#include <asm/ubicom32hid.h>
36519 +#include <asm/vdc_tio.h>
36520 +
36521 +/*
36522 + * LEDs
36523 + *
36524 + * WLAN                        PD9     (Note this is shared with MISO, but we don't use it)
36525 + * WPS                 PD8
36526 + *
36527 + * TODO: check triggers, are they generic?
36528 + */
36529 +static struct gpio_led ip5170dpf_gpio_leds[] = {
36530 +       {
36531 +               .name                   = "d31:green:WLAN1",
36532 +               .default_trigger        = "WLAN1",
36533 +               .gpio                   = GPIO_RD_9,
36534 +               .active_low             = 1,
36535 +       },
36536 +       {
36537 +               .name                   = "d30:green:WPS",
36538 +               .default_trigger        = "WPS",
36539 +               .gpio                   = GPIO_RD_8,
36540 +               .active_low             = 1,
36541 +       },
36542 +};
36543 +
36544 +static struct gpio_led_platform_data ip5170dpf_gpio_led_platform_data = {
36545 +       .num_leds       = 2,
36546 +       .leds           = ip5170dpf_gpio_leds,
36547 +};
36548 +
36549 +static struct platform_device ip5170dpf_gpio_leds_device = {
36550 +       .name           = "leds-gpio",
36551 +       .id             = -1,
36552 +       .dev = {
36553 +               .platform_data = &ip5170dpf_gpio_led_platform_data,
36554 +       },
36555 +};
36556 +
36557 +/*
36558 + * Backlight on the board PD0, hardware PWM
36559 + */
36560 +static const struct ubicom32hid_button ip5170dpf_ubicom32hid_buttons[] = {
36561 +       {
36562 +               .type   = EV_KEY,
36563 +               .code   = KEY_UP,
36564 +               .bit    = 0,
36565 +       },
36566 +       {
36567 +               .type   = EV_KEY,
36568 +               .code   = KEY_LEFT,
36569 +               .bit    = 1,
36570 +       },
36571 +       {
36572 +               .type   = EV_KEY,
36573 +               .code   = KEY_RIGHT,
36574 +               .bit    = 2,
36575 +       },
36576 +       {
36577 +               .type   = EV_KEY,
36578 +               .code   = KEY_DOWN,
36579 +               .bit    = 3,
36580 +       },
36581 +       {
36582 +               .type   = EV_KEY,
36583 +               .code   = KEY_ENTER,
36584 +               .bit    = 4,
36585 +       },
36586 +       {
36587 +               .type   = EV_KEY,
36588 +               .code   = KEY_MENU,
36589 +               .bit    = 5,
36590 +       },
36591 +       {
36592 +               .type   = EV_KEY,
36593 +               .code   = KEY_ESC,
36594 +               .bit    = 7,
36595 +       },
36596 +};
36597 +
36598 +static const struct ubicom32hid_ir ip5170dpf_ubicom32hid_ircodes[] = {
36599 +       {
36600 +               .type           = EV_KEY,
36601 +               .code           = KEY_UP,
36602 +               .ir_code        = 0xF807916E
36603 +       },
36604 +       {
36605 +               .type           = EV_KEY,
36606 +               .code           = KEY_DOWN,
36607 +               .ir_code        = 0xF20D916E
36608 +       },
36609 +       {
36610 +               .type           = EV_KEY,
36611 +               .code           = KEY_LEFT,
36612 +               .ir_code        = 0xF609916E
36613 +       },
36614 +       {
36615 +               .type           = EV_KEY,
36616 +               .code           = KEY_RIGHT,
36617 +               .ir_code        = 0xF40B916E
36618 +       },
36619 +       {
36620 +               .type           = EV_KEY,
36621 +               .code           = KEY_ENTER,
36622 +               .ir_code        = 0xF50A916E
36623 +       },
36624 +       {       /* rotate */
36625 +               .type           = EV_KEY,
36626 +               .code           = KEY_FN_F1,
36627 +               .ir_code        = 0xF906916E
36628 +       },
36629 +       {
36630 +               .type           = EV_KEY,
36631 +               .code           = KEY_MENU,
36632 +               .ir_code        = 0xF708916E
36633 +       },
36634 +       {       /* font size */
36635 +               .type           = EV_KEY,
36636 +               .code           = KEY_FN_F2,
36637 +               .ir_code        = 0xF30C916E
36638 +       },
36639 +       {
36640 +               .type           = EV_KEY,
36641 +               .code           = KEY_ESC,
36642 +               .ir_code        = 0xF10E916E
36643 +       },
36644 +       {
36645 +               .type           = EV_KEY,
36646 +               .code           = KEY_VOLUMEUP,
36647 +               .ir_code        = 0xF00F916E
36648 +       },
36649 +       {
36650 +               .type           = EV_KEY,
36651 +               .code           = KEY_VOLUMEDOWN,
36652 +               .ir_code        = 0xED12916E
36653 +       },
36654 +       {
36655 +               .type           = EV_KEY,
36656 +               .code           = KEY_MUTE,
36657 +               .ir_code        = 0xEA15916E
36658 +       },
36659 +       {
36660 +               .type           = EV_KEY,
36661 +               .code           = KEY_INFO,
36662 +               .ir_code        = 0xEF10916E
36663 +       },
36664 +       {       /* Like */
36665 +               .type           = EV_KEY,
36666 +               .code           = KEY_FN_F3,
36667 +               .ir_code        = 0xEE11916E
36668 +       },
36669 +       {       /* Dislike */
36670 +               .type           = EV_KEY,
36671 +               .code           = KEY_FN_F4,
36672 +               .ir_code        = 0xEB14916E
36673 +       },
36674 +       {
36675 +               .type           = EV_KEY,
36676 +               .code           = KEY_POWER,
36677 +               .ir_code        = 0xFD02916E
36678 +       },
36679 +};
36680 +
36681 +static struct ubicom32hid_platform_data ip5170dpf_ubicom32hid_platform_data = {
36682 +       .gpio_reset             = GPIO_RA_4,
36683 +       .gpio_reset_polarity    = 0,
36684 +       .type                   = UBICOM32HID_BL_TYPE_BINARY,
36685 +       .invert                 = 0,
36686 +       .default_intensity      = 1,
36687 +       .buttons                = ip5170dpf_ubicom32hid_buttons,
36688 +       .nbuttons               = ARRAY_SIZE(ip5170dpf_ubicom32hid_buttons),
36689 +       .ircodes                = ip5170dpf_ubicom32hid_ircodes,
36690 +       .nircodes               = ARRAY_SIZE(ip5170dpf_ubicom32hid_ircodes),
36691 +};
36692 +
36693 +/*
36694 + * Devices on the I2C bus
36695 + */
36696 +static struct i2c_board_info __initdata ip5170dpf_i2c_board_info[] = {
36697 +       /*
36698 +        * U24, ubicom32hid
36699 +        */
36700 +       {
36701 +               .type           = "ubicom32hid",
36702 +               .addr           = 0x08,
36703 +               .platform_data  = &ip5170dpf_ubicom32hid_platform_data,
36704 +       },
36705 +
36706 +       /*
36707 +        * U14, CS4350 DAC, address 0x4B
36708 +        */
36709 +};
36710 +
36711 +/*
36712 + * I2C bus on the board, SDA PF13, SCL PF14
36713 + */
36714 +static struct i2c_gpio_platform_data ip5170dpf_i2c_data = {
36715 +       .sda_pin                = GPIO_RF_13,
36716 +       .scl_pin                = GPIO_RF_14,
36717 +       .sda_is_open_drain      = 0,
36718 +       .scl_is_open_drain      = 0,
36719 +       .scl_is_output_only     = 1,
36720 +       .udelay                 = 5,
36721 +};
36722 +
36723 +static struct platform_device ip5170dpf_i2c_device = {
36724 +       .name   = "i2c-gpio",
36725 +       .id     = 0,
36726 +       .dev    = {
36727 +               .platform_data = &ip5170dpf_i2c_data,
36728 +       },
36729 +};
36730 +
36731 +/*
36732 + * List of all devices in our system
36733 + */
36734 +static struct platform_device *ip5170dpf_devices[] __initdata = {
36735 +       &ip5170dpf_i2c_device,
36736 +       &ip5170dpf_gpio_leds_device,
36737 +};
36738 +
36739 +/*
36740 + * ip5170dpf_init
36741 + *     Called to add the devices which we have on this board
36742 + */
36743 +static int __init ip5170dpf_init(void)
36744 +{
36745 +       ubi_gpio_init();
36746 +
36747 +       vdc_tio_init();
36748 +
36749 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36750 +       platform_add_devices(ip5170dpf_devices, ARRAY_SIZE(ip5170dpf_devices));
36751 +
36752 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
36753 +       i2c_register_board_info(0, ip5170dpf_i2c_board_info, ARRAY_SIZE(ip5170dpf_i2c_board_info));
36754 +
36755 +       return 0;
36756 +}
36757 +
36758 +arch_initcall(ip5170dpf_init);
36759 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/Kconfig linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Kconfig
36760 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/Kconfig     1970-01-01 02:00:00.000000000 +0200
36761 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Kconfig 2009-12-11 11:45:11.000000000 +0200
36762 @@ -0,0 +1,28 @@
36763 +
36764 +config IP5170DPF
36765 +       bool "IP5170DPF"
36766 +       select UBICOM32_V3
36767 +       select I2C
36768 +       select I2C_GPIO
36769 +       select FB
36770 +       select FB_UBICOM32
36771 +       select BACKLIGHT_LCD_SUPPORT
36772 +       select BACKLIGHT_CLASS_DEVICE
36773 +       select UBICOM_HID
36774 +       select NEW_LEDS
36775 +       select LEDS_CLASS
36776 +       select LEDS_GPIO
36777 +       help
36778 +               IP5170 Digital Picture Frame board, 8005-1113, IP5K-BEV-0011-13 v1.3
36779 +
36780 +config IP5160DEV
36781 +       bool "IP5160Dev_Ver1Dot1"
36782 +       select UBICOM32_V3
36783 +       help
36784 +               Ubicom StreamEngine 5000 Development Board, IP5K-BDV-0004-11 v1.1
36785 +
36786 +config IP5160EVAL
36787 +       bool "IP5160RGWEval_Ver2Rev2"
36788 +       select UBICOM32_V3
36789 +       help
36790 +               Ubicom StreamEngine 5000 RGW Evaluation Board, IP5K-RGW-0004-11 v2.2
36791 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Makefile
36792 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/Makefile    1970-01-01 02:00:00.000000000 +0200
36793 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Makefile        2009-12-11 11:45:11.000000000 +0200
36794 @@ -0,0 +1,31 @@
36795 +#
36796 +# arch/ubicom32/mach-ip5k/Makefile
36797 +#      Makefile for boards which have an ip5k on them.
36798 +#
36799 +# (C) Copyright 2009, Ubicom, Inc.
36800 +#
36801 +# This file is part of the Ubicom32 Linux Kernel Port.
36802 +#
36803 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
36804 +# it and/or modify it under the terms of the GNU General Public License
36805 +# as published by the Free Software Foundation, either version 2 of the
36806 +# License, or (at your option) any later version.
36807 +#
36808 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
36809 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
36810 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36811 +# the GNU General Public License for more details.
36812 +#
36813 +# You should have received a copy of the GNU General Public License
36814 +# along with the Ubicom32 Linux Kernel Port.  If not,
36815 +# see <http://www.gnu.org/licenses/>.
36816 +#
36817 +# Ubicom32 implementation derived from (with many thanks):
36818 +#   arch/m68knommu
36819 +#   arch/blackfin
36820 +#   arch/parisc
36821 +#
36822 +
36823 +obj-$(CONFIG_IP5170DPF)                += board-ip5170dpf.o
36824 +obj-$(CONFIG_IP5160DEV)                += board-ip5160dev.o
36825 +obj-$(CONFIG_IP5160EVAL)       += board-ip5160rgw.o
36826 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7145dpf.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36827 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7145dpf.c   1970-01-01 02:00:00.000000000 +0200
36828 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7145dpf.c       2009-12-11 11:45:11.000000000 +0200
36829 @@ -0,0 +1,715 @@
36830 +/*
36831 + * arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36832 + *   Board file for IP7145DPF, rev 1.0, P/N 8007-0410
36833 + *
36834 + * (C) Copyright 2009, Ubicom, Inc.
36835 + *
36836 + * This file is part of the Ubicom32 Linux Kernel Port.
36837 + *
36838 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36839 + * it and/or modify it under the terms of the GNU General Public License
36840 + * as published by the Free Software Foundation, either version 2 of the
36841 + * License, or (at your option) any later version.
36842 + *
36843 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36844 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36845 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36846 + * the GNU General Public License for more details.
36847 + *
36848 + * You should have received a copy of the GNU General Public License
36849 + * along with the Ubicom32 Linux Kernel Port.  If not,
36850 + * see <http://www.gnu.org/licenses/>.
36851 + *
36852 + * Ubicom32 implementation derived from (with many thanks):
36853 + *   arch/m68knommu
36854 + *   arch/blackfin
36855 + *   arch/parisc
36856 + */
36857 +#include <linux/device.h>
36858 +#include <linux/platform_device.h>
36859 +#include <linux/gpio.h>
36860 +
36861 +#include <linux/input.h>
36862 +
36863 +#include <linux/i2c.h>
36864 +#include <linux/i2c-gpio.h>
36865 +#include <linux/i2c/pca953x.h>
36866 +
36867 +#include <asm/board.h>
36868 +#include <asm/machdep.h>
36869 +#include <asm/ubicom32input.h>
36870 +#include <asm/ubicom32input_i2c.h>
36871 +#include <asm/ubicom32bl.h>
36872 +#include <asm/ubicom32lcdpower.h>
36873 +#include <asm/vdc_tio.h>
36874 +
36875 +#include <asm/ubicom32sd.h>
36876 +#include <asm/sd_tio.h>
36877 +#include <asm/devtree.h>
36878 +#include <asm/audio.h>
36879 +
36880 +#include <asm/ring_tio.h>
36881 +
36882 +/******************************************************************************
36883 + * SD/IO Port F (Slot 1) platform data
36884 + */
36885 +static struct resource ip7145dpf_portf_sd_resources[] = {
36886 +       /*
36887 +        * Send IRQ
36888 +        */
36889 +       [0] = {
36890 +               /*
36891 +                * The init routine will query the devtree and fill this in
36892 +                */
36893 +               .flags  = IORESOURCE_IRQ,
36894 +       },
36895 +
36896 +       /*
36897 +        * Receive IRQ
36898 +        */
36899 +       [1] = {
36900 +               /*
36901 +                * The init routine will query the devtree and fill this in
36902 +                */
36903 +               .flags  = IORESOURCE_IRQ,
36904 +       },
36905 +
36906 +       /*
36907 +        * Memory Mapped Registers
36908 +        */
36909 +       [2] = {
36910 +               /*
36911 +                * The init routine will query the devtree and fill this in
36912 +                */
36913 +               .flags  = IORESOURCE_MEM,
36914 +       },
36915 +};
36916 +
36917 +static struct ubicom32sd_card ip7145dpf_portf_sd_cards[] = {
36918 +       [0] = {
36919 +               .pin_wp         = IP7145DPF_IOB0,
36920 +               .wp_polarity    = 1,
36921 +               .pin_pwr        = IP7145DPF_IOB4,
36922 +               .pin_cd         = GPIO_RA_4,
36923 +       },
36924 +       [1] = {
36925 +               .pin_wp         = IP7145DPF_IOB1,
36926 +               .wp_polarity    = 1,
36927 +               .pin_pwr        = IP7145DPF_IOB5,
36928 +               .pin_cd         = GPIO_RA_6,
36929 +       },
36930 +};
36931 +
36932 +static struct ubicom32sd_platform_data ip7145dpf_portf_sd_platform_data = {
36933 +       .ncards         = 2,
36934 +       .cards          = ip7145dpf_portf_sd_cards,
36935 +};
36936 +
36937 +static struct platform_device ip7145dpf_portf_sd_device = {
36938 +       .name           = "ubicom32sd",
36939 +       .id             = 0,
36940 +       .resource       = ip7145dpf_portf_sd_resources,
36941 +       .num_resources  = ARRAY_SIZE(ip7145dpf_portf_sd_resources),
36942 +       .dev            = {
36943 +                       .platform_data = &ip7145dpf_portf_sd_platform_data,
36944 +       },
36945 +
36946 +};
36947 +
36948 +/*
36949 + * ip7145dpf_portf_sd_init
36950 + */
36951 +static void ip7145dpf_portf_sd_init(void)
36952 +{
36953 +       /*
36954 +        * Check the device tree for the sd_tio
36955 +        */
36956 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
36957 +       if (!sd_node) {
36958 +               printk(KERN_INFO "PortF SDTIO not found\n");
36959 +               return;
36960 +       }
36961 +
36962 +       /*
36963 +        * Fill in the resources and platform data from devtree information
36964 +        */
36965 +       ip7145dpf_portf_sd_resources[0].start = sd_node->dn.sendirq;
36966 +       ip7145dpf_portf_sd_resources[1].start = sd_node->dn.recvirq;
36967 +       ip7145dpf_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
36968 +       ip7145dpf_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
36969 +
36970 +       platform_device_register(&ip7145dpf_portf_sd_device);
36971 +}
36972 +
36973 +/******************************************************************************
36974 + * SD/IO Port B (Slot 2) platform data
36975 + */
36976 +static struct resource ip7145dpf_portb_sd_resources[] = {
36977 +       /*
36978 +        * Send IRQ
36979 +        */
36980 +       [0] = {
36981 +               /*
36982 +                * The init routine will query the devtree and fill this in
36983 +                */
36984 +               .flags  = IORESOURCE_IRQ,
36985 +       },
36986 +
36987 +       /*
36988 +        * Receive IRQ
36989 +        */
36990 +       [1] = {
36991 +               /*
36992 +                * The init routine will query the devtree and fill this in
36993 +                */
36994 +               .flags  = IORESOURCE_IRQ,
36995 +       },
36996 +
36997 +       /*
36998 +        * Memory Mapped Registers
36999 +        */
37000 +       [2] = {
37001 +               /*
37002 +                * The init routine will query the devtree and fill this in
37003 +                */
37004 +               .flags  = IORESOURCE_MEM,
37005 +       },
37006 +};
37007 +
37008 +static struct ubicom32sd_card ip7145dpf_portb_sd_cards[] = {
37009 +       [0] = {
37010 +               .pin_wp         = IP7145DPF_IOB2,
37011 +               .wp_polarity    = 1,
37012 +               .pin_pwr        = IP7145DPF_IOB6,
37013 +               .pin_cd         = IP7145DPF_IOB3,
37014 +       },
37015 +};
37016 +
37017 +static struct ubicom32sd_platform_data ip7145dpf_portb_sd_platform_data = {
37018 +       .ncards         = 1,
37019 +       .cards          = ip7145dpf_portb_sd_cards,
37020 +};
37021 +
37022 +static struct platform_device ip7145dpf_portb_sd_device = {
37023 +       .name           = "ubicom32sd",
37024 +       .id             = 1,
37025 +       .resource       = ip7145dpf_portb_sd_resources,
37026 +       .num_resources  = ARRAY_SIZE(ip7145dpf_portb_sd_resources),
37027 +       .dev            = {
37028 +                       .platform_data = &ip7145dpf_portb_sd_platform_data,
37029 +       },
37030 +
37031 +};
37032 +
37033 +/*
37034 + * ip7145dpf_portb_sd_init
37035 + */
37036 +static void ip7145dpf_portb_sd_init(void)
37037 +{
37038 +       /*
37039 +        * Check the device tree for the sd_tio
37040 +        */
37041 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
37042 +       if (!sd_node) {
37043 +               printk(KERN_INFO "PortB SDTIO not found\n");
37044 +               return;
37045 +       }
37046 +
37047 +       /*
37048 +        * Fill in the resources and platform data from devtree information
37049 +        */
37050 +       ip7145dpf_portb_sd_resources[0].start = sd_node->dn.sendirq;
37051 +       ip7145dpf_portb_sd_resources[1].start = sd_node->dn.recvirq;
37052 +       ip7145dpf_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
37053 +       ip7145dpf_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
37054 +
37055 +       platform_device_register(&ip7145dpf_portb_sd_device);
37056 +}
37057 +
37058 +
37059 +#ifdef IP7145DPF_USE_MMC_SPI
37060 +/******************************************************************************
37061 + * SPI over GPIO (MMC_SPI)
37062 + */
37063 +#include <linux/spi/spi.h>
37064 +#include <linux/spi/mmc_spi.h>
37065 +#include <linux/mmc/host.h>
37066 +#include <asm/ubicom32-spi-gpio.h>
37067 +
37068 +#define MMC_CS GPIO_RF_5       // PF5 D3
37069 +#define MMC_CD GPIO_RA_4       // PA4 CD
37070 +#define MMC_WP IP7145DPF_IOB0  // IOB0 WP
37071 +#define MMC_PWR        IP7145DPF_IOB4  // IOB4 PWR
37072 +
37073 +/*
37074 + * SPI bus over GPIO (for SD card)
37075 + */
37076 +static struct ubicom32_spi_gpio_platform_data ip7145dpf_spi_gpio_data = {
37077 +       .pin_mosi       = GPIO_RF_0,    // PF0 CMD
37078 +       .pin_miso       = GPIO_RF_2,    // PF2 D0
37079 +       .pin_clk        = GPIO_RF_1,    // PF1 CLK
37080 +       .bus_num        = 0,            // We'll call this SPI bus 0
37081 +       .num_chipselect = 1,            // only one device on this SPI bus
37082 +};
37083 +
37084 +static struct platform_device ip7145dpf_spi_gpio_device = {
37085 +       .name   = "ubicom32-spi-gpio",
37086 +       .id     = 0,
37087 +       .dev    = {
37088 +               .platform_data = &ip7145dpf_spi_gpio_data,
37089 +       },
37090 +};
37091 +
37092 +/*
37093 + * ip7145dpf_mmc_spi_setpower_slot_a
37094 + *     Set the power state for slot A
37095 + */
37096 +static void ip7145dpf_mmc_spi_setpower_slot_a(struct device *dev, unsigned int vdd)
37097 +{
37098 +       struct mmc_spi_platform_data *pd = dev->platform_data;
37099 +
37100 +       /*
37101 +        * Power is inverted, we could tell the IOB to do it, but it's cleaner this way.
37102 +        */
37103 +       if ((1 << vdd) & pd->ocr_mask) {
37104 +               gpio_set_value(MMC_PWR, 0);
37105 +               return;
37106 +       }
37107 +       gpio_set_value(MMC_PWR, 1);
37108 +}
37109 +
37110 +/*
37111 + * ip7145dpf_mmc_spi_get_cd_slot_a
37112 + *     Get the CD bit for slot A
37113 + */
37114 +static int ip7145dpf_mmc_spi_get_cd_slot_a(struct device *dev)
37115 +{
37116 +       /*
37117 +        * Note that the sense of the GPIO is inverted
37118 +        */
37119 +       return !gpio_get_value(MMC_CD);
37120 +}
37121 +
37122 +/*
37123 + * ip7145dpf_mmc_spi_get_ro_slot_a
37124 + *     Get the WP bit for slot A
37125 + */
37126 +static int ip7145dpf_mmc_spi_get_ro_slot_a(struct device *dev)
37127 +{
37128 +       /*
37129 +        * Note that the sense of the GPIO is inverted, we could tell the IOB to do it, but
37130 +        * it's clearer this way.
37131 +        */
37132 +       return !gpio_get_value(MMC_WP);
37133 +}
37134 +
37135 +/*
37136 + * ip7145dpf_mmc_spi_exit_slot_a
37137 + *     Free the appropriate GPIOs for slot A SD slot.
37138 + */
37139 +static void ip7145dpf_mmc_spi_exit_slot_a(struct device *dev, void *appdata)
37140 +{
37141 +       gpio_free(MMC_CD);
37142 +       gpio_free(MMC_CS);
37143 +       gpio_free(MMC_WP);
37144 +       gpio_free(MMC_PWR);
37145 +       platform_device_unregister(&ip7145dpf_spi_gpio_device);
37146 +}
37147 +
37148 +/*
37149 + * ip7145dpf_mmc_spi_init_slot_a
37150 + *     Allocate the appropriate GPIOs for slot A SD slot.
37151 + *     WP is on IOB0, CD is PA4, CS is on PF5
37152 + *     TODO: make CD an interrupt
37153 + */
37154 +static int ip7145dpf_mmc_spi_init_slot_a(void)
37155 +{
37156 +       int ret = gpio_request(MMC_CD, "mmc-a-cd");
37157 +       if (ret) {
37158 +               printk(KERN_ERR "%s: could not request mmc-a-cd pin\n", __FUNCTION__);
37159 +               return -ENOSYS;
37160 +       }
37161 +       gpio_direction_input(MMC_CD);
37162 +
37163 +       ret = gpio_request(MMC_CS, "mmc-a-cs");
37164 +       if (ret) {
37165 +               printk(KERN_ERR "%s: could not request mmc-a-cs pin\n", __FUNCTION__);
37166 +               goto no_cs;
37167 +       }
37168 +       gpio_direction_output(MMC_CS, 0);
37169 +
37170 +       ret = gpio_request(MMC_WP, "mmc-a-wp");
37171 +       if (ret) {
37172 +               printk(KERN_ERR "%s: could not request mmc-a-wp pin\n", __FUNCTION__);
37173 +               goto no_wp;
37174 +       }
37175 +       gpio_direction_input(MMC_WP);
37176 +
37177 +       /*
37178 +        * Start off with power off
37179 +        */
37180 +       ret = gpio_request(MMC_PWR, "mmc-a-pwr");
37181 +       if (ret) {
37182 +               printk(KERN_ERR "%s: could not request mmc-a-pwr pin\n", __FUNCTION__);
37183 +               goto no_pwr;
37184 +       }
37185 +       ret = gpio_direction_output(MMC_PWR, 1);
37186 +
37187 +       return 0;
37188 +
37189 +no_pwr:
37190 +       gpio_free(MMC_WP);
37191 +
37192 +no_wp:
37193 +       gpio_free(MMC_CS);
37194 +
37195 +no_cs:
37196 +       gpio_free(MMC_CD);
37197 +       return -ENOSYS;
37198 +}
37199 +
37200 +/*
37201 + * MMC_SPI driver (currently bitbang)
37202 + */
37203 +static struct mmc_spi_platform_data ip7145dpf_mmc_platform_data = {
37204 +       .ocr_mask       = MMC_VDD_33_34,
37205 +       .exit           = ip7145dpf_mmc_spi_exit_slot_a,
37206 +       .get_ro         = ip7145dpf_mmc_spi_get_ro_slot_a,
37207 +       .get_cd         = ip7145dpf_mmc_spi_get_cd_slot_a,
37208 +
37209 +       .setpower       = ip7145dpf_mmc_spi_setpower_slot_a,
37210 +       .powerup_msecs  = 500,
37211 +
37212 +       .detect_delay   = 100,
37213 +
37214 +       .caps           = MMC_CAP_NEEDS_POLL,
37215 +};
37216 +
37217 +static struct ubicom32_spi_gpio_controller_data ip7145dpf_mmc_controller_data = {
37218 +       .pin_cs =  MMC_CS,
37219 +};
37220 +
37221 +static struct spi_board_info ip7145dpf_spi_board_info[] = {
37222 +       {
37223 +               .modalias = "mmc_spi",
37224 +               .bus_num = 0,
37225 +               .chip_select = 0,
37226 +               .max_speed_hz = 2000000,
37227 +               .platform_data = &ip7145dpf_mmc_platform_data,
37228 +               .controller_data = &ip7145dpf_mmc_controller_data,
37229 +       }
37230 +};
37231 +#endif /* IP7145DPF_USE_MMC_SPI */
37232 +
37233 +/*
37234 + * ip7145dpf_u72_setup
37235 + *     Called by I2C to tell us that u72 is setup.
37236 + *
37237 + * This function is called by I2C to tell us that u72 has been setup.  All
37238 + * devices which rely on this chip being initialized (or even present) need to
37239 + * be initialized in this function otherwise they may get initialized too early.
37240 + *
37241 + * Currently the only device depending on u72 is the SPI
37242 + */
37243 +static int __init ip7145dpf_u72_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
37244 +{
37245 +#ifdef IP7145DPF_USE_MMC_SPI
37246 +       if (ip7145dpf_mmc_spi_init_slot_a()) {
37247 +               printk(KERN_ERR "%s: could not request mmc resources\n", __FUNCTION__);
37248 +       } else {
37249 +               printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
37250 +               spi_register_board_info(ip7145dpf_spi_board_info, ARRAY_SIZE(ip7145dpf_spi_board_info));
37251 +               platform_device_register(&ip7145dpf_spi_gpio_device);
37252 +       }
37253 +#else
37254 +       /*
37255 +        * Initialize the Port F/Port B SD slots
37256 +        */
37257 +       ip7145dpf_portf_sd_init();
37258 +       ip7145dpf_portb_sd_init();
37259 +#endif
37260 +       return 0;
37261 +}
37262 +
37263 +/******************************************************************************
37264 + * LCD VGH on the board at PE6
37265 + */
37266 +static struct ubicom32lcdpower_platform_data ip7145dpf_lcdpower_data = {
37267 +       .vgh_gpio               = GPIO_RE_6,
37268 +       .vgh_polarity           = true,
37269 +};
37270 +
37271 +static struct platform_device ip7145dpf_lcdpower_device = {
37272 +       .name   = "ubicom32lcdpower",
37273 +       .id     = -1,
37274 +       .dev    = {
37275 +               .platform_data = &ip7145dpf_lcdpower_data,
37276 +       },
37277 +};
37278 +
37279 +/******************************************************************************
37280 + * Backlight on the board PD0, hardware PWM
37281 + */
37282 +static struct ubicom32bl_platform_data ip7145dpf_backlight_data = {
37283 +       .type                   = UBICOM32BL_TYPE_PWM,
37284 +       .pwm_channel            = 2,
37285 +       .pwm_prescale           = 15,
37286 +       .pwm_period             = 60,
37287 +       .default_intensity      = 0x80,
37288 +};
37289 +
37290 +static struct platform_device ip7145dpf_backlight_device = {
37291 +       .name   = "ubicom32bl",
37292 +       .id     = -1,
37293 +       .dev    = {
37294 +               .platform_data = &ip7145dpf_backlight_data,
37295 +       },
37296 +};
37297 +
37298 +/******************************************************************************
37299 + * Ubicom32Input on I2C, U48 MAX7310, address 0x18, 8 bits
37300 + */
37301 +static struct ubicom32input_i2c_button ip7145dpf_ubicom32input_i2c_u48_buttons[] = {
37302 +       {
37303 +               .type           = EV_KEY,
37304 +               .code           = KEY_UP,
37305 +               .bit            = 0,
37306 +               .active_low     = 1,
37307 +       },
37308 +       {
37309 +               .type           = EV_KEY,
37310 +               .code           = KEY_LEFT,
37311 +               .bit            = 1,
37312 +               .active_low     = 1,
37313 +       },
37314 +       {
37315 +               .type           = EV_KEY,
37316 +               .code           = KEY_RIGHT,
37317 +               .bit            = 2,
37318 +               .active_low     = 1,
37319 +       },
37320 +       {
37321 +               .type           = EV_KEY,
37322 +               .code           = KEY_DOWN,
37323 +               .bit            = 3,
37324 +               .active_low     = 1,
37325 +       },
37326 +       {
37327 +               .type           = EV_KEY,
37328 +               .code           = KEY_ENTER,
37329 +               .bit            = 4,
37330 +               .active_low     = 1,
37331 +       },
37332 +       {
37333 +               .type           = EV_KEY,
37334 +               .code           = KEY_MENU,
37335 +               .bit            = 5,
37336 +               .active_low     = 1,
37337 +       },
37338 +       {
37339 +               .type           = EV_KEY,
37340 +               .code           = KEY_ESC,
37341 +               .bit            = 6,
37342 +               .active_low     = 1,
37343 +       },
37344 +};
37345 +
37346 +static struct ubicom32input_i2c_platform_data ip7145dpf_ubicom32input_i2c_u48_platform_data = {
37347 +       .buttons        = ip7145dpf_ubicom32input_i2c_u48_buttons,
37348 +       .nbuttons       = ARRAY_SIZE(ip7145dpf_ubicom32input_i2c_u48_buttons),
37349 +       .name           = "Ubicom32 Input I2C U48",
37350 +};
37351 +
37352 +/******************************************************************************
37353 + * Additional GPIO chips
37354 + */
37355 +static struct pca953x_platform_data ip7145dpf_gpio_u72_platform_data = {
37356 +       .gpio_base = IP7145DPF_U72_BASE,
37357 +       .setup = ip7145dpf_u72_setup,
37358 +};
37359 +
37360 +/******************************************************************************
37361 + * Devices on the I2C bus
37362 + */
37363 +static struct i2c_board_info __initdata ip7145dpf_i2c_board_info[] = {
37364 +       /*
37365 +        * U51, S35390A RTC, address 0x30
37366 +        */
37367 +       {
37368 +               .type           = "s35390a",
37369 +               .addr           = 0x30,
37370 +       },
37371 +
37372 +       /*
37373 +        * U48, MAX7310 IO expander, 8 bits, address 0x18
37374 +        */
37375 +       {
37376 +               .type           = "ubicom32in_max7310",
37377 +               .addr           = 0x18,
37378 +               .platform_data  = &ip7145dpf_ubicom32input_i2c_u48_platform_data,
37379 +       },
37380 +
37381 +       /*
37382 +        * U72, MAX7310 IOB expander, 8 bits, address 0x19
37383 +        */
37384 +       {
37385 +               .type           = "max7310",
37386 +               .addr           = 0x19,
37387 +               .platform_data  = &ip7145dpf_gpio_u72_platform_data,
37388 +       },
37389 +};
37390 +
37391 +/*
37392 + * I2C bus on the board, SDA PE1, SCL PE2
37393 + */
37394 +static struct i2c_gpio_platform_data ip7145dpf_i2c_data = {
37395 +       .sda_pin                = GPIO_RE_1,
37396 +       .scl_pin                = GPIO_RE_2,
37397 +       .sda_is_open_drain      = 0,
37398 +       .scl_is_open_drain      = 0,
37399 +};
37400 +
37401 +static struct platform_device ip7145dpf_i2c_device = {
37402 +       .name   = "i2c-gpio",
37403 +       .id     = 0,
37404 +       .dev    = {
37405 +               .platform_data = &ip7145dpf_i2c_data,
37406 +       },
37407 +};
37408 +
37409 +/******************************************************************************
37410 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37411 + *
37412 + * WPS                 PF12
37413 + * FACT_DEFAULT                PF13
37414 + * POWER               PE4
37415 + *
37416 + * Not sutable for the keypad buttons since those run on I2C GPIO.  The polling
37417 + * of ubicom32input would seem to be excessive for this.
37418 + *
37419 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37420 + */
37421 +static struct ubicom32input_button ip7145dpf_ubicom32input_buttons[] = {
37422 +       {
37423 +               .type           = EV_KEY,
37424 +               .code           = KEY_FN_F1,
37425 +               .gpio           = GPIO_RF_12,
37426 +               .desc           = "WPS",
37427 +               .active_low     = 1,
37428 +       },
37429 +       {
37430 +               .type           = EV_KEY,
37431 +               .code           = KEY_FN_F2,
37432 +               .gpio           = GPIO_RF_13,
37433 +               .desc           = "Factory Default",
37434 +               .active_low     = 1,
37435 +       },
37436 +       {
37437 +               .type           = EV_KEY,
37438 +               .code           = KEY_POWER,
37439 +               .gpio           = GPIO_RE_4,
37440 +               .desc           = "Power",
37441 +               .active_low     = 1,
37442 +       },
37443 +};
37444 +
37445 +static struct ubicom32input_platform_data ip7145dpf_ubicom32input_data = {
37446 +       .buttons        = ip7145dpf_ubicom32input_buttons,
37447 +       .nbuttons       = ARRAY_SIZE(ip7145dpf_ubicom32input_buttons),
37448 +};
37449 +
37450 +static struct platform_device ip7145dpf_ubicom32input_device = {
37451 +       .name   = "ubicom32input",
37452 +       .id     = -1,
37453 +       .dev    = {
37454 +               .platform_data = &ip7145dpf_ubicom32input_data,
37455 +       },
37456 +};
37457 +
37458 +/*
37459 + * List of all devices in our system
37460 + */
37461 +static struct platform_device *ip7145dpf_devices[] __initdata = {
37462 +       &ip7145dpf_i2c_device,
37463 +       &ip7145dpf_lcdpower_device,
37464 +       &ip7145dpf_backlight_device,
37465 +       &ip7145dpf_ubicom32input_device,
37466 +};
37467 +
37468 +/*
37469 + * ip7145dpf_power_off
37470 + *     Called to turn the power off for this board
37471 + */
37472 +static void ip7145dpf_power_off(void)
37473 +{
37474 +       gpio_set_value(GPIO_RE_5, 0);
37475 +}
37476 +
37477 +/*
37478 + * ip7145dpf_init
37479 + *     Called to add the devices which we have on this board
37480 + */
37481 +static int __init ip7145dpf_init(void)
37482 +{
37483 +       int ret;
37484 +       struct platform_device *audio_dev;
37485 +
37486 +       ubi_gpio_init();
37487 +
37488 +#ifdef CONFIG_UIO_UBICOM32RING
37489 +       ring_tio_init("decoder_ring");
37490 +#endif
37491 +
37492 +       /*
37493 +        * Start up the video driver first
37494 +        */
37495 +       vdc_tio_init();
37496 +
37497 +       /*
37498 +        * Take over holding of the power from the system
37499 +        */
37500 +       ret = gpio_request(GPIO_RE_5, "power_hold");
37501 +       if (ret) {
37502 +               printk(KERN_ERR "%s: could not request power hold GPIO\n", __FUNCTION__);
37503 +       }
37504 +       gpio_direction_output(GPIO_RE_5, 1);
37505 +       mach_power_off = ip7145dpf_power_off;
37506 +
37507 +       /*
37508 +        * USB SEL_HOST_USB line
37509 +        */
37510 +       ret = gpio_request(GPIO_RF_11, "SEL_HOST_USB");
37511 +       if (ret) {
37512 +               printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37513 +       }
37514 +       gpio_direction_output(GPIO_RF_11, 0);
37515 +
37516 +       /*
37517 +        * Setup audio
37518 +        */
37519 +       audio_dev = audio_device_alloc("snd-ubi32-generic", "audio", "audio-i2sout", 0);
37520 +       if (audio_dev) {
37521 +               platform_device_register(audio_dev);
37522 +       }
37523 +
37524 +       /*
37525 +        * Register all of the devices we have on this board
37526 +        */
37527 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37528 +       platform_add_devices(ip7145dpf_devices, ARRAY_SIZE(ip7145dpf_devices));
37529 +
37530 +       /*
37531 +        * Register all of the devices which sit on the I2C bus
37532 +        */
37533 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
37534 +       i2c_register_board_info(0, ip7145dpf_i2c_board_info, ARRAY_SIZE(ip7145dpf_i2c_board_info));
37535 +
37536 +       /*
37537 +        * We have to initialize the SPI after the I2C IOB gets setup. SPI is initialized in
37538 +        * ip7145dpf_u72_setup
37539 +        */
37540 +
37541 +       return 0;
37542 +}
37543 +
37544 +arch_initcall(ip7145dpf_init);
37545 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160bringup.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37546 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160bringup.c       1970-01-01 02:00:00.000000000 +0200
37547 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160bringup.c   2009-12-11 11:45:11.000000000 +0200
37548 @@ -0,0 +1,134 @@
37549 +/*
37550 + * arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37551 + *   Support for the IP7160 bringup board.
37552 + *
37553 + * (C) Copyright 2009, Ubicom, Inc.
37554 + *
37555 + * This file is part of the Ubicom32 Linux Kernel Port.
37556 + *
37557 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37558 + * it and/or modify it under the terms of the GNU General Public License
37559 + * as published by the Free Software Foundation, either version 2 of the
37560 + * License, or (at your option) any later version.
37561 + *
37562 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37563 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37564 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
37565 + * the GNU General Public License for more details.
37566 + *
37567 + * You should have received a copy of the GNU General Public License
37568 + * along with the Ubicom32 Linux Kernel Port.  If not,
37569 + * see <http://www.gnu.org/licenses/>.
37570 + *
37571 + * Ubicom32 implementation derived from (with many thanks):
37572 + *   arch/m68knommu
37573 + *   arch/blackfin
37574 + *   arch/parisc
37575 + */
37576 +#include <linux/device.h>
37577 +#include <linux/platform_device.h>
37578 +#include <linux/gpio.h>
37579 +#include <linux/leds.h>
37580 +#include <linux/delay.h>
37581 +#include <linux/input.h>
37582 +
37583 +#include <asm/board.h>
37584 +#include <asm/machdep.h>
37585 +#include <asm/ubicom32input.h>
37586 +
37587 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37588 +#include <asm/ubicom32suart.h>
37589 +#endif
37590 +
37591 +/*
37592 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37593 + *
37594 + * WPS                 PD5
37595 + * FACT_DEFAULT                PD6
37596 + *
37597 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37598 + */
37599 +static struct ubicom32input_button ip7160bringup_ubicom32input_buttons[] = {
37600 +       {
37601 +               .type           = EV_KEY,
37602 +               .code           = KEY_FN_F1,
37603 +               .gpio           = GPIO_RD_5,
37604 +               .desc           = "WPS",
37605 +               .active_low     = 1,
37606 +       },
37607 +       {
37608 +               .type           = EV_KEY,
37609 +               .code           = KEY_FN_F2,
37610 +               .gpio           = GPIO_RD_6,
37611 +               .desc           = "Factory Default",
37612 +               .active_low     = 1,
37613 +       },
37614 +};
37615 +
37616 +static struct ubicom32input_platform_data ip7160bringup_ubicom32input_data = {
37617 +       .buttons        = ip7160bringup_ubicom32input_buttons,
37618 +       .nbuttons       = ARRAY_SIZE(ip7160bringup_ubicom32input_buttons),
37619 +};
37620 +
37621 +static struct platform_device ip7160bringup_ubicom32input_device = {
37622 +       .name   = "ubicom32input",
37623 +       .id     = -1,
37624 +       .dev    = {
37625 +               .platform_data = &ip7160bringup_ubicom32input_data,
37626 +       },
37627 +};
37628 +
37629 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37630 +static struct resource ip7160bringup_ubicom32_suart_resources[] = {
37631 +       {
37632 +               .start  = RE,
37633 +               .end    = RE,
37634 +               .flags  = IORESOURCE_MEM,
37635 +       },
37636 +       {
37637 +               .start  = PORT_OTHER_INT(RE),
37638 +               .end    = PORT_OTHER_INT(RE),
37639 +               .flags  = IORESOURCE_IRQ,
37640 +       },
37641 +       {
37642 +               .start  = 250000000,
37643 +               .end    = 250000000,
37644 +               .flags  = UBICOM32_SUART_IORESOURCE_CLOCK,
37645 +       },
37646 +};
37647 +
37648 +static struct platform_device ip7160bringup_ubicom32_suart_device = {
37649 +       .name           = "ubicom32suart",
37650 +       .id             = -1,
37651 +       .num_resources  = ARRAY_SIZE(ip7160bringup_ubicom32_suart_resources),
37652 +       .resource       = ip7160bringup_ubicom32_suart_resources,
37653 +};
37654 +#endif
37655 +
37656 +/*
37657 + * List of all devices in our system
37658 + */
37659 +static struct platform_device *ip7160bringup_devices[] __initdata = {
37660 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37661 +       &ip7160bringup_ubicom32_suart_device,
37662 +#endif
37663 +       &ip7160bringup_ubicom32input_device,
37664 +};
37665 +
37666 +/*
37667 + * ip7160bringup_init
37668 + *     Called to add the devices which we have on this board
37669 + */
37670 +static int __init ip7160bringup_init(void)
37671 +{
37672 +       board_init();
37673 +
37674 +       ubi_gpio_init();
37675 +
37676 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37677 +       platform_add_devices(ip7160bringup_devices, ARRAY_SIZE(ip7160bringup_devices));
37678 +
37679 +       return 0;
37680 +}
37681 +
37682 +arch_initcall(ip7160bringup_init);
37683 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160dpf.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37684 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160dpf.c   1970-01-01 02:00:00.000000000 +0200
37685 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160dpf.c       2009-12-11 11:45:11.000000000 +0200
37686 @@ -0,0 +1,326 @@
37687 +/*
37688 + * arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37689 + *   Platform initialization for ip7160dpf board.
37690 + *
37691 + * (C) Copyright 2009, Ubicom, Inc.
37692 + *
37693 + * This file is part of the Ubicom32 Linux Kernel Port.
37694 + *
37695 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37696 + * it and/or modify it under the terms of the GNU General Public License
37697 + * as published by the Free Software Foundation, either version 2 of the
37698 + * License, or (at your option) any later version.
37699 + *
37700 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37701 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37702 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
37703 + * the GNU General Public License for more details.
37704 + *
37705 + * You should have received a copy of the GNU General Public License
37706 + * along with the Ubicom32 Linux Kernel Port.  If not,
37707 + * see <http://www.gnu.org/licenses/>.
37708 + *
37709 + * Ubicom32 implementation derived from (with many thanks):
37710 + *   arch/m68knommu
37711 + *   arch/blackfin
37712 + *   arch/parisc
37713 + */
37714 +#include <linux/device.h>
37715 +#include <linux/platform_device.h>
37716 +#include <linux/delay.h>
37717 +#include <linux/gpio.h>
37718 +
37719 +#include <linux/i2c.h>
37720 +#include <linux/i2c-gpio.h>
37721 +
37722 +#include <linux/input.h>
37723 +
37724 +#include <asm/board.h>
37725 +#include <asm/machdep.h>
37726 +#include <asm/ubicom32hid.h>
37727 +#include <asm/vdc_tio.h>
37728 +#include <asm/audio.h>
37729 +
37730 +/*
37731 + * Backlight on the board PD0, hardware PWM
37732 + */
37733 +static const struct ubicom32hid_button ip7160dpf_ubicom32hid_buttons[] = {
37734 +       {
37735 +               .type   = EV_KEY,
37736 +               .code   = KEY_UP,
37737 +               .bit    = 0,
37738 +       },
37739 +       {
37740 +               .type   = EV_KEY,
37741 +               .code   = KEY_LEFT,
37742 +               .bit    = 1,
37743 +       },
37744 +       {
37745 +               .type   = EV_KEY,
37746 +               .code   = KEY_RIGHT,
37747 +               .bit    = 2,
37748 +       },
37749 +       {
37750 +               .type   = EV_KEY,
37751 +               .code   = KEY_DOWN,
37752 +               .bit    = 3,
37753 +       },
37754 +       {
37755 +               .type   = EV_KEY,
37756 +               .code   = KEY_ENTER,
37757 +               .bit    = 4,
37758 +       },
37759 +       {
37760 +               .type   = EV_KEY,
37761 +               .code   = KEY_MENU,
37762 +               .bit    = 5,
37763 +       },
37764 +       {
37765 +               .type   = EV_KEY,
37766 +               .code   = KEY_ESC,
37767 +               .bit    = 7,
37768 +       },
37769 +};
37770 +
37771 +static const struct ubicom32hid_ir ip7160dpf_ubicom32hid_ircodes[] = {
37772 +       {
37773 +               .type           = EV_KEY,
37774 +               .code           = KEY_UP,
37775 +               .ir_code        = 0xF807916E
37776 +       },
37777 +       {
37778 +               .type           = EV_KEY,
37779 +               .code           = KEY_DOWN,
37780 +               .ir_code        = 0xF20D916E
37781 +       },
37782 +       {
37783 +               .type           = EV_KEY,
37784 +               .code           = KEY_LEFT,
37785 +               .ir_code        = 0xF609916E
37786 +       },
37787 +       {
37788 +               .type           = EV_KEY,
37789 +               .code           = KEY_RIGHT,
37790 +               .ir_code        = 0xF40B916E
37791 +       },
37792 +       {
37793 +               .type           = EV_KEY,
37794 +               .code           = KEY_ENTER,
37795 +               .ir_code        = 0xF50A916E
37796 +       },
37797 +       {       /* rotate */
37798 +               .type           = EV_KEY,
37799 +               .code           = KEY_FN_F1,
37800 +               .ir_code        = 0xF906916E
37801 +       },
37802 +       {
37803 +               .type           = EV_KEY,
37804 +               .code           = KEY_MENU,
37805 +               .ir_code        = 0xF708916E
37806 +       },
37807 +       {       /* font size */
37808 +               .type           = EV_KEY,
37809 +               .code           = KEY_FN_F2,
37810 +               .ir_code        = 0xF30C916E
37811 +       },
37812 +       {
37813 +               .type           = EV_KEY,
37814 +               .code           = KEY_ESC,
37815 +               .ir_code        = 0xF10E916E
37816 +       },
37817 +       {
37818 +               .type           = EV_KEY,
37819 +               .code           = KEY_VOLUMEUP,
37820 +               .ir_code        = 0xF00F916E
37821 +       },
37822 +       {
37823 +               .type           = EV_KEY,
37824 +               .code           = KEY_VOLUMEDOWN,
37825 +               .ir_code        = 0xED12916E
37826 +       },
37827 +       {
37828 +               .type           = EV_KEY,
37829 +               .code           = KEY_MUTE,
37830 +               .ir_code        = 0xEA15916E
37831 +       },
37832 +       {
37833 +               .type           = EV_KEY,
37834 +               .code           = KEY_INFO,
37835 +               .ir_code        = 0xEF10916E
37836 +       },
37837 +       {       /* Like */
37838 +               .type           = EV_KEY,
37839 +               .code           = KEY_FN_F3,
37840 +               .ir_code        = 0xEE11916E
37841 +       },
37842 +       {       /* Dislike */
37843 +               .type           = EV_KEY,
37844 +               .code           = KEY_FN_F4,
37845 +               .ir_code        = 0xEB14916E
37846 +       },
37847 +       {
37848 +               .type           = EV_KEY,
37849 +               .code           = KEY_POWER,
37850 +               .ir_code        = 0xFD02916E
37851 +       },
37852 +};
37853 +
37854 +static struct ubicom32hid_platform_data ip7160dpf_ubicom32hid_platform_data = {
37855 +       .gpio_reset             = GPIO_RI_5,
37856 +       .gpio_reset_polarity    = 0,
37857 +       .type                   = UBICOM32HID_BL_TYPE_PWM,
37858 +       .invert                 = 0,
37859 +       .default_intensity      = 128,
37860 +       .buttons                = ip7160dpf_ubicom32hid_buttons,
37861 +       .nbuttons               = ARRAY_SIZE(ip7160dpf_ubicom32hid_buttons),
37862 +       .ircodes                = ip7160dpf_ubicom32hid_ircodes,
37863 +       .nircodes               = ARRAY_SIZE(ip7160dpf_ubicom32hid_ircodes),
37864 +};
37865 +
37866 +/*
37867 + * Devices on the I2C bus
37868 + *     This board has a "bus 2" which is isolated from the main bus by U47
37869 + *     and pin RI0.  It should be safe to always enable bus 2 by setting
37870 + *     RI0 to low, however, it should be noted that on all existing configurations
37871 + *     of this board, U49 and U51 are not populated.
37872 + */
37873 +static struct i2c_board_info __initdata ip7160dpf_i2c_board_info[] = {
37874 +       /*
37875 +        * U37, CS4350 DAC, address 0x4B, bus 2
37876 +        *      THIS ENTRY MUST BE FIRST
37877 +        */
37878 +       {
37879 +               .type           = "cs4350",
37880 +               .addr           = 0x4B,
37881 +       }
37882 +
37883 +       /*
37884 +        * U24, ubicom32hid
37885 +        */
37886 +       {
37887 +               .type           = "ubicom32hid",
37888 +               .addr           = 0x08,
37889 +               .platform_data  = &ip7160dpf_ubicom32hid_platform_data,
37890 +       },
37891 +
37892 +       /*
37893 +        * U49, ISL29001 Ambient Light Sensor, address 0x44, bus 2 (may not be stuffed)
37894 +        */
37895 +
37896 +       /*
37897 +        * U51, S35390A RTC, address 0x30, bus 2 (may not be stuffed)
37898 +        */
37899 +#ifdef CONFIG_RTC_DRV_S35390A
37900 +       {
37901 +               .type           = "s35390a",
37902 +               .addr           = 0x30,
37903 +       },
37904 +#endif
37905 +};
37906 +
37907 +/*
37908 + * I2C bus on the board, SDA PI1, SCL PI2
37909 + */
37910 +static struct i2c_gpio_platform_data ip7160dpf_i2c_data = {
37911 +       .sda_pin                = GPIO_RI_1,
37912 +       .scl_pin                = GPIO_RI_2,
37913 +       .sda_is_open_drain      = 0,
37914 +       .scl_is_open_drain      = 0,
37915 +       .scl_is_output_only     = 1,
37916 +       .udelay                 = 6,
37917 +};
37918 +
37919 +static struct platform_device ip7160dpf_i2c_device = {
37920 +       .name   = "i2c-gpio",
37921 +       .id     = 0,
37922 +       .dev    = {
37923 +               .platform_data = &ip7160dpf_i2c_data,
37924 +       },
37925 +};
37926 +
37927 +/*
37928 + * List of all devices in our system
37929 + */
37930 +static struct platform_device *ip7160dpf_devices[] __initdata = {
37931 +       &ip7160dpf_i2c_device,
37932 +};
37933 +
37934 +/*
37935 + * ip7160dpf_power_off
37936 + *     Called to turn the power off for this board
37937 + */
37938 +static void ip7160dpf_power_off(void)
37939 +{
37940 +       gpio_set_value(GPIO_RF_14, 0);
37941 +}
37942 +
37943 +/*
37944 + * ip7160dpf_init
37945 + *     Called to add the devices which we have on this board
37946 + */
37947 +static int __init ip7160dpf_init(void)
37948 +{
37949 +       int ret;
37950 +       struct platform_device *audio_dev;
37951 +
37952 +       ubi_gpio_init();
37953 +
37954 +       /*
37955 +        * Hold the POWER_HOLD line
37956 +        */
37957 +       ret = gpio_request(GPIO_RF_14, "POWER_HOLD");
37958 +       if (ret) {
37959 +               printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
37960 +       }
37961 +       gpio_direction_output(GPIO_RF_14, 1);
37962 +       mach_power_off = ip7160dpf_power_off;
37963 +
37964 +       /*
37965 +        * USB SEL_HOST_USB line
37966 +        */
37967 +       ret = gpio_request(GPIO_RI_13, "SEL_HOST_USB");
37968 +       if (ret) {
37969 +               printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37970 +       }
37971 +       gpio_direction_output(GPIO_RI_13, 0);
37972 +
37973 +       /*
37974 +        * USB/DAC nRESET line
37975 +        */
37976 +       ret = gpio_request(GPIO_RI_3, "USB_DAC_nRESET");
37977 +       if (ret) {
37978 +               printk(KERN_ERR "%s: could not request USB_DAC_nRESET GPIO\n", __FUNCTION__);
37979 +       }
37980 +       gpio_direction_output(GPIO_RI_3, 0);
37981 +       udelay(1);
37982 +       gpio_direction_output(GPIO_RI_3, 1);
37983 +
37984 +       /*
37985 +        * I2C BUS2 Disable line
37986 +        */
37987 +       ret = gpio_request(GPIO_RI_0, "DISABLE_BUS2");
37988 +       if (ret) {
37989 +               printk(KERN_ERR "%s: could not request DISABLE_BUS2 GPIO\n", __FUNCTION__);
37990 +       }
37991 +       gpio_direction_output(GPIO_RI_0, 0);
37992 +
37993 +       vdc_tio_init();
37994 +
37995 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37996 +       platform_add_devices(ip7160dpf_devices, ARRAY_SIZE(ip7160dpf_devices));
37997 +
37998 +       /*
37999 +        * Allocate the audio driver if we can
38000 +        */
38001 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio-i2sout", 0);
38002 +       if (audio_dev) {
38003 +               ip7160dpf_i2c_board_info[0].platform_data = audio_dev;
38004 +       }
38005 +
38006 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38007 +       i2c_register_board_info(0, ip7160dpf_i2c_board_info, ARRAY_SIZE(ip7160dpf_i2c_board_info));
38008 +
38009 +       return 0;
38010 +}
38011 +
38012 +arch_initcall(ip7160dpf_init);
38013 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160rgw.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160rgw.c
38014 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160rgw.c   1970-01-01 02:00:00.000000000 +0200
38015 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160rgw.c       2009-12-11 11:45:11.000000000 +0200
38016 @@ -0,0 +1,355 @@
38017 +/*
38018 + * arch/ubicom32/mach-ip7k/board-ip7160rgw.c
38019 + *   Platform initialization for ip7160rgw board.
38020 + *
38021 + * (C) Copyright 2009, Ubicom, Inc.
38022 + *
38023 + * This file is part of the Ubicom32 Linux Kernel Port.
38024 + *
38025 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38026 + * it and/or modify it under the terms of the GNU General Public License
38027 + * as published by the Free Software Foundation, either version 2 of the
38028 + * License, or (at your option) any later version.
38029 + *
38030 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38031 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38032 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
38033 + * the GNU General Public License for more details.
38034 + *
38035 + * You should have received a copy of the GNU General Public License
38036 + * along with the Ubicom32 Linux Kernel Port.  If not,
38037 + * see <http://www.gnu.org/licenses/>.
38038 + *
38039 + * Ubicom32 implementation derived from (with many thanks):
38040 + *   arch/m68knommu
38041 + *   arch/blackfin
38042 + *   arch/parisc
38043 + */
38044 +#include <linux/device.h>
38045 +#include <linux/platform_device.h>
38046 +#include <linux/gpio.h>
38047 +#include <linux/leds.h>
38048 +#include <linux/delay.h>
38049 +#include <linux/input.h>
38050 +#include <linux/spi/spi.h>
38051 +
38052 +#include <asm/board.h>
38053 +#include <asm/machdep.h>
38054 +#include <asm/ubicom32input.h>
38055 +
38056 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38057 +#include <asm/ubicom32suart.h>
38058 +#endif
38059 +
38060 +#include <asm/ubicom32-spi-gpio.h>
38061 +#include <asm/switch-dev.h>
38062 +
38063 +#ifdef CONFIG_IP7160RGWLCD
38064 +#include <linux/i2c.h>
38065 +#include <linux/i2c-gpio.h>
38066 +/*
38067 + * LCD Adapter board 8007-092x support
38068 + *
38069 + * Touch controller
38070 + *
38071 + * Connected via I2C bus, interrupt on PA6
38072 + */
38073 +#include <linux/i2c/tsc2007.h>
38074 +
38075 +/*
38076 + * ip7160rgwlcd_tsc2007_exit_platform_hw
38077 + */
38078 +static void ip7160rgwlcd_tsc2007_exit_platform_hw(void)
38079 +{
38080 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
38081 +       gpio_free(GPIO_RA_5);
38082 +}
38083 +
38084 +/*
38085 + * ip7160rgwlcd_tsc2007_init_platform_hw
38086 + */
38087 +static int ip7160rgwlcd_tsc2007_init_platform_hw(void)
38088 +{
38089 +       int res = gpio_request(GPIO_RA_5, "TSC2007_IRQ");
38090 +       if (res) {
38091 +               return res;
38092 +       }
38093 +
38094 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
38095 +       UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 17);
38096 +       return 0;
38097 +}
38098 +
38099 +/*
38100 + * ip7160rgwlcd_tsc2007_get_pendown_state
38101 + */
38102 +static int ip7160rgwlcd_tsc2007_get_pendown_state(void)
38103 +{
38104 +       return !gpio_get_value(GPIO_RA_5);
38105 +}
38106 +
38107 +static struct tsc2007_platform_data ip7160rgwlcd_tsc2007_data = {
38108 +       .model                  = 2007,
38109 +       .x_plate_ohms           = 350,
38110 +       .get_pendown_state      = ip7160rgwlcd_tsc2007_get_pendown_state,
38111 +       .init_platform_hw       = ip7160rgwlcd_tsc2007_init_platform_hw,
38112 +       .exit_platform_hw       = ip7160rgwlcd_tsc2007_exit_platform_hw,
38113 +};
38114 +
38115 +/******************************************************************************
38116 + * I2C bus on the board, SDA PI14, SCL PI13
38117 + */
38118 +static struct i2c_gpio_platform_data ip7160rgwlcd_i2c_data = {
38119 +       .sda_pin                = GPIO_RI_14,
38120 +       .scl_pin                = GPIO_RI_13,
38121 +       .sda_is_open_drain      = 0,
38122 +       .scl_is_open_drain      = 0,
38123 +       .udelay                 = 50,
38124 +};
38125 +
38126 +static struct platform_device ip7160rgwlcd_i2c_device = {
38127 +       .name   = "i2c-gpio",
38128 +       .id     = 0,
38129 +       .dev    = {
38130 +               .platform_data = &ip7160rgwlcd_i2c_data,
38131 +       },
38132 +};
38133 +
38134 +static struct i2c_board_info __initdata ip7160rgwlcd_i2c_board_info[] = {
38135 +       {
38136 +               .type = "tsc2007",
38137 +               .addr = 0x48,
38138 +               .irq = 45, // RA5
38139 +               .platform_data = &ip7160rgwlcd_tsc2007_data,
38140 +       },
38141 +};
38142 +
38143 +#endif
38144 +
38145 +/*
38146 + * SPI bus over GPIO for Gigabit Ethernet Switch
38147 + *     U58:
38148 + *             MOSI    PE0
38149 + *             MISO    PE1
38150 + *             CLK     PE3
38151 + *             CS      PE2
38152 + */
38153 +static struct ubicom32_spi_gpio_platform_data ip7160rgw_spi_gpio_data = {
38154 +       .pin_mosi       = GPIO_RE_0,
38155 +       .pin_miso       = GPIO_RE_1,
38156 +       .pin_clk        = GPIO_RE_3,
38157 +       .bus_num        = 0,            // We'll call this SPI bus 0
38158 +       .num_chipselect = 1,            // only one device on this SPI bus
38159 +       .clk_default    = 1,
38160 +};
38161 +
38162 +static struct platform_device ip7160rgw_spi_gpio_device = {
38163 +       .name   = "ubicom32-spi-gpio",
38164 +       .id     = 0,
38165 +       .dev    = {
38166 +               .platform_data = &ip7160rgw_spi_gpio_data,
38167 +       },
38168 +};
38169 +
38170 +static struct ubicom32_spi_gpio_controller_data ip7160rgw_bcm539x_controller_data = {
38171 +       .pin_cs = GPIO_RE_2,
38172 +};
38173 +
38174 +static struct switch_core_platform_data ip7160rgw_bcm539x_platform_data = {
38175 +       .flags          = SWITCH_DEV_FLAG_HW_RESET,
38176 +       .pin_reset      = GPIO_RE_4,
38177 +       .name           = "bcm539x",
38178 +};
38179 +
38180 +static struct spi_board_info ip7160rgw_spi_board_info[] = {
38181 +       {
38182 +               .modalias               = "bcm539x-spi",
38183 +               .bus_num                = 0,
38184 +               .chip_select            = 0,
38185 +               .max_speed_hz           = 2000000,
38186 +               .platform_data          = &ip7160rgw_bcm539x_platform_data,
38187 +               .controller_data        = &ip7160rgw_bcm539x_controller_data,
38188 +               .mode                   = SPI_MODE_3,
38189 +       }
38190 +};
38191 +
38192 +/*
38193 + * LEDs
38194 + *
38195 + * WLAN1               PD0     (PWM capable)
38196 + * WLAN2               PD1
38197 + * USB2.0              PD2
38198 + * Status              PD3
38199 + * WPS                 PD4
38200 + *
38201 + * TODO: check triggers, are they generic?
38202 + */
38203 +static struct gpio_led ip7160rgw_gpio_leds[] = {
38204 +       {
38205 +               .name                   = "d53:green:WLAN1",
38206 +               .default_trigger        = "WLAN1",
38207 +               .gpio                   = GPIO_RD_0,
38208 +               .active_low             = 1,
38209 +       },
38210 +       {
38211 +               .name                   = "d54:green:WLAN2",
38212 +               .default_trigger        = "WLAN2",
38213 +               .gpio                   = GPIO_RD_1,
38214 +               .active_low             = 1,
38215 +       },
38216 +       {
38217 +               .name                   = "d55:green:USB",
38218 +               .default_trigger        = "USB",
38219 +               .gpio                   = GPIO_RD_2,
38220 +               .active_low             = 1,
38221 +       },
38222 +       {
38223 +               .name                   = "d56:green:Status",
38224 +               .default_trigger        = "Status",
38225 +               .gpio                   = GPIO_RD_3,
38226 +               .active_low             = 1,
38227 +       },
38228 +       {
38229 +               .name                   = "d57:green:WPS",
38230 +               .default_trigger        = "WPS",
38231 +               .gpio                   = GPIO_RD_4,
38232 +               .active_low             = 1,
38233 +       },
38234 +};
38235 +
38236 +static struct gpio_led_platform_data ip7160rgw_gpio_led_platform_data = {
38237 +       .num_leds       = 5,
38238 +       .leds           = ip7160rgw_gpio_leds,
38239 +};
38240 +
38241 +static struct platform_device ip7160rgw_gpio_leds_device = {
38242 +       .name           = "leds-gpio",
38243 +       .id             = -1,
38244 +       .dev = {
38245 +               .platform_data = &ip7160rgw_gpio_led_platform_data,
38246 +       },
38247 +};
38248 +
38249 +/*
38250 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
38251 + *
38252 + * WPS                 PD5
38253 + * FACT_DEFAULT                PD6
38254 + *
38255 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
38256 + */
38257 +static struct ubicom32input_button ip7160rgw_ubicom32input_buttons[] = {
38258 +       {
38259 +               .type           = EV_KEY,
38260 +               .code           = KEY_FN_F1,
38261 +               .gpio           = GPIO_RD_5,
38262 +               .desc           = "WPS",
38263 +               .active_low     = 1,
38264 +       },
38265 +       {
38266 +               .type           = EV_KEY,
38267 +               .code           = KEY_FN_F2,
38268 +               .gpio           = GPIO_RD_6,
38269 +               .desc           = "Factory Default",
38270 +               .active_low     = 1,
38271 +       },
38272 +};
38273 +
38274 +static struct ubicom32input_platform_data ip7160rgw_ubicom32input_data = {
38275 +       .buttons        = ip7160rgw_ubicom32input_buttons,
38276 +       .nbuttons       = ARRAY_SIZE(ip7160rgw_ubicom32input_buttons),
38277 +};
38278 +
38279 +static struct platform_device ip7160rgw_ubicom32input_device = {
38280 +       .name   = "ubicom32input",
38281 +       .id     = -1,
38282 +       .dev    = {
38283 +               .platform_data = &ip7160rgw_ubicom32input_data,
38284 +       },
38285 +};
38286 +
38287 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38288 +static struct resource ip7160rgw_ubicom32_suart_resources[] = {
38289 +       {
38290 +               .start  = RE,
38291 +               .end    = RE,
38292 +               .flags  = IORESOURCE_MEM,
38293 +       },
38294 +       {
38295 +               .start  = PORT_OTHER_INT(RE),
38296 +               .end    = PORT_OTHER_INT(RE),
38297 +               .flags  = IORESOURCE_IRQ,
38298 +       },
38299 +       {
38300 +               .start  = 250000000,
38301 +               .end    = 250000000,
38302 +               .flags  = UBICOM32_SUART_IORESOURCE_CLOCK,
38303 +       },
38304 +};
38305 +
38306 +static struct platform_device ip7160rgw_ubicom32_suart_device = {
38307 +       .name           = "ubicom32suart",
38308 +       .id             = -1,
38309 +       .num_resources  = ARRAY_SIZE(ip7160rgw_ubicom32_suart_resources),
38310 +       .resource       = ip7160rgw_ubicom32_suart_resources,
38311 +};
38312 +#endif
38313 +
38314 +/*
38315 + * List of all devices in our system
38316 + */
38317 +static struct platform_device *ip7160rgw_devices[] __initdata = {
38318 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38319 +       &ip7160rgw_ubicom32_suart_device,
38320 +#endif
38321 +       &ip7160rgw_ubicom32input_device,
38322 +       &ip7160rgw_gpio_leds_device,
38323 +       &ip7160rgw_spi_gpio_device,
38324 +#ifdef CONFIG_IP7160RGWLCD
38325 +       &ip7160rgwlcd_i2c_device,
38326 +#endif
38327 +};
38328 +
38329 +/*
38330 + * ip7160rgw_init
38331 + *     Called to add the devices which we have on this board
38332 + */
38333 +static int __init ip7160rgw_init(void)
38334 +{
38335 +       board_init();
38336 +
38337 +       /*
38338 +        * Rev 1.2 boards have spi in a different place than 1.1/1.0
38339 +        */
38340 +       if (strcmp(board_get_revision(), "1.2") == 0) {
38341 +               ip7160rgw_spi_gpio_data.pin_mosi = GPIO_RD_7;
38342 +       }
38343 +
38344 +       ubi_gpio_init();
38345 +
38346 +       /*
38347 +        * Reserve switch SPI CS on behalf on switch driver
38348 +        */
38349 +       if (gpio_request(ip7160rgw_bcm539x_controller_data.pin_cs, "switch-bcm539x-cs")) {
38350 +               printk(KERN_WARNING "Could not request cs of switch SPI I/F\n");
38351 +               return -EIO;
38352 +       }
38353 +       gpio_direction_output(ip7160rgw_bcm539x_controller_data.pin_cs, 1);
38354 +
38355 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38356 +       platform_add_devices(ip7160rgw_devices, ARRAY_SIZE(ip7160rgw_devices));
38357 +
38358 +       printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
38359 +       spi_register_board_info(ip7160rgw_spi_board_info, ARRAY_SIZE(ip7160rgw_spi_board_info));
38360 +
38361 +#ifdef CONFIG_IP7160RGWLCD
38362 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38363 +       i2c_register_board_info(0, ip7160rgwlcd_i2c_board_info, ARRAY_SIZE(ip7160rgwlcd_i2c_board_info));
38364 +       printk(KERN_INFO "IP7160 RGW + LCD\n");
38365 +#else
38366 +       printk(KERN_INFO "IP7160 RGW\n");
38367 +#endif
38368 +       return 0;
38369 +}
38370 +
38371 +arch_initcall(ip7160rgw_init);
38372 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500av.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500av.c
38373 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500av.c    1970-01-01 02:00:00.000000000 +0200
38374 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500av.c        2009-12-11 11:45:11.000000000 +0200
38375 @@ -0,0 +1,273 @@
38376 +/*
38377 + * arch/ubicom32/mach-ip7k/board-ip7500av.c
38378 + *   Support for IP7500 Audio Video Board + CPU module board.
38379 + *
38380 + * This file supports the IP7500 Audio Video Board:
38381 + *     8007-0810  Rev 1.0
38382 + * with one of the following CPU module boards:
38383 + *     8007-0510  Rev 1.0
38384 + *     8007-0510A Rev 1.0 (with ethernet)
38385 + *
38386 + * DIP Switch SW2 configuration: (*) default
38387 + *     POS 1: on(*) = PCI enabled, off = PCI disabled
38388 + *     POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
38389 + *     POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
38390 + *     POS 4: unused
38391 + *
38392 + * (C) Copyright 2009, Ubicom, Inc.
38393 + *
38394 + * This file is part of the Ubicom32 Linux Kernel Port.
38395 + *
38396 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38397 + * it and/or modify it under the terms of the GNU General Public License
38398 + * as published by the Free Software Foundation, either version 2 of the
38399 + * License, or (at your option) any later version.
38400 + *
38401 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38402 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38403 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
38404 + * the GNU General Public License for more details.
38405 + *
38406 + * You should have received a copy of the GNU General Public License
38407 + * along with the Ubicom32 Linux Kernel Port.  If not,
38408 + * see <http://www.gnu.org/licenses/>.
38409 + */
38410 +
38411 +#include <linux/platform_device.h>
38412 +#include <linux/device.h>
38413 +#include <linux/gpio.h>
38414 +#include <linux/i2c.h>
38415 +#include <linux/i2c-gpio.h>
38416 +#include <linux/delay.h>
38417 +#include <asm/board.h>
38418 +#include <asm/machdep.h>
38419 +#include <asm/ring_tio.h>
38420 +#include <asm/vdc_tio.h>
38421 +#include <asm/audio.h>
38422 +#include <asm/ubi32-pcm.h>
38423 +#include <asm/ubi32-cs4384.h>
38424 +
38425 +/******************************************************************************
38426 + * Devices on the I2C bus
38427 + *
38428 + * BEWARE of changing the order of things in this array as we depend on
38429 + * certain things to be in certain places.
38430 + */
38431 +static struct i2c_board_info __initdata ip7500av_i2c_board_info[] = {
38432 +       /*
38433 +        * U6, CS4384 DAC, address 0x19
38434 +        */
38435 +       {
38436 +               .type           = "cs4384",
38437 +               .addr           = 0x19,
38438 +       },
38439 +};
38440 +
38441 +/*
38442 + * I2C bus on the board, SDA PD1, SCL PD2
38443 + */
38444 +static struct i2c_gpio_platform_data ip7500av_i2c_data = {
38445 +       .sda_pin                = GPIO_RD_6,
38446 +       .scl_pin                = GPIO_RD_3,
38447 +       .sda_is_open_drain      = 0,
38448 +       .scl_is_open_drain      = 0,
38449 +       .udelay                 = 50,
38450 +};
38451 +
38452 +static struct platform_device ip7500av_i2c_device = {
38453 +       .name   = "i2c-gpio",
38454 +       .id     = 0,
38455 +       .dev    = {
38456 +               .platform_data = &ip7500av_i2c_data,
38457 +       },
38458 +};
38459 +
38460 +/*
38461 + * List of possible mclks we can generate.  This depends on the CPU frequency.
38462 + */
38463 +static struct ubi32_cs4384_mclk_entry ip7500av_cs4384_mclk_entries[] = {
38464 +       {
38465 +               .rate   =       12288000,
38466 +               .div    =       44,
38467 +       },
38468 +       {
38469 +               .rate   =       11289600,
38470 +               .div    =       48,
38471 +       },
38472 +};
38473 +
38474 +/*
38475 + * List of all devices in our system
38476 + */
38477 +static struct platform_device *ip7500av_devices[] __initdata = {
38478 +       &ip7500av_i2c_device,
38479 +};
38480 +
38481 +/*
38482 + * ip7500av_vdac_write
38483 + */
38484 +static int __init ip7500av_vdac_write(int reg, int val)
38485 +{
38486 +       struct i2c_adapter *adap;
38487 +       struct i2c_msg msg[1];
38488 +       unsigned char data[2];
38489 +       int err;
38490 +
38491 +       adap = i2c_get_adapter(0);
38492 +       if (!adap) {
38493 +               printk(KERN_WARNING "%s: failed to get i2c adapter\n", __FUNCTION__);
38494 +               return -ENODEV;
38495 +       }
38496 +       msg->addr = 0x2B;
38497 +       msg->flags = 0;
38498 +       msg->len = 2;
38499 +       msg->buf = data;
38500 +       data[0] = reg;
38501 +       data[1] = val;
38502 +       err = i2c_transfer(adap, msg, 1);
38503 +       i2c_put_adapter(adap);
38504 +       if (err >= 0) {
38505 +               return 0;
38506 +       }
38507 +       return err;
38508 +}
38509 +
38510 +/*
38511 + * ip7500av_vdac_init
38512 + *     Initializes the video DAC via I2C
38513 + *
38514 + * Equivalent mode line: 720x480p = 27 Mhz, 720 736 800 858 480 484 492 525
38515 + */
38516 +static int __init ip7500av_vdac_init(void)
38517 +{
38518 +       int err;
38519 +
38520 +       printk(KERN_INFO "Initializing ADV7393 DAC\n");
38521 +
38522 +       /*
38523 +        * Reset the VDAC
38524 +        */
38525 +       if (gpio_request(GPIO_RF_6, "VDAC Reset")) {
38526 +               printk(KERN_WARNING "%s: failed to allocate VDAC Reset\n", __FUNCTION__);
38527 +               return -EBUSY;
38528 +       }
38529 +       gpio_direction_output(GPIO_RF_6, 0);
38530 +       udelay(1);
38531 +       gpio_set_value(GPIO_RF_6, 1);
38532 +
38533 +       /*
38534 +        * See table 100 of ADV7393 data sheet: 16-bit 525p YCrCb In, YPbPr Out
38535 +        */
38536 +       err = ip7500av_vdac_write(0x17, 0x02);
38537 +       if (err) {
38538 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38539 +               return err;
38540 +       }
38541 +       err = ip7500av_vdac_write(0x00, 0x1c);
38542 +       if (err) {
38543 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38544 +               return err;
38545 +       }
38546 +       err = ip7500av_vdac_write(0x01, 0x10);
38547 +       if (err) {
38548 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38549 +               return err;
38550 +       }
38551 +       err = ip7500av_vdac_write(0x31, 0x01);
38552 +       if (err) {
38553 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38554 +               return err;
38555 +       }
38556 +#ifdef IP7500AV_VDAC_SWAP_PBPR
38557 +       err = ip7500av_vdac_write(0x35, 0x08);
38558 +       if (err) {
38559 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38560 +               return err;
38561 +       }
38562 +#endif
38563 +#ifdef IP7500AV_VDAC_FULL_RANGE
38564 +       err = ip7500av_vdac_write(0x30, 0x02);
38565 +       if (err) {
38566 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38567 +               return err;
38568 +       }
38569 +#endif
38570 +       return 0;
38571 +}
38572 +late_initcall(ip7500av_vdac_init);
38573 +
38574 +/*
38575 + * ip7500av_init
38576 + *     Called to add the devices which we have on this board
38577 + */
38578 +static int __init ip7500av_init(void)
38579 +{
38580 +       struct platform_device *audio_dev;
38581 +       struct platform_device *audio_dev2;
38582 +       struct ubi32_cs4384_platform_data *cs4384_pd;
38583 +
38584 +       board_init();
38585 +
38586 +       ubi_gpio_init();
38587 +
38588 +       vdc_tio_init();
38589 +
38590 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38591 +       platform_add_devices(ip7500av_devices, ARRAY_SIZE(ip7500av_devices));
38592 +
38593 +       /*
38594 +        * CS4384 DAC
38595 +        */
38596 +       audio_dev = audio_device_alloc("snd-ubi32-cs4384", "audio", "audio-i2sout",
38597 +                       sizeof(struct ubi32_cs4384_platform_data));
38598 +       if (audio_dev) {
38599 +               /*
38600 +                * Attempt to figure out a good divisor.  This will only work
38601 +                * assuming the core frequency is compatible.
38602 +                */
38603 +               int i;
38604 +               unsigned int freq = processor_frequency();
38605 +               for (i = 0; i < ARRAY_SIZE(ip7500av_cs4384_mclk_entries); i++) {
38606 +                       unsigned int div;
38607 +                       unsigned int rate = ip7500av_cs4384_mclk_entries[i].rate / 1000;
38608 +                       div = ((freq / rate) + 500) / 1000;
38609 +                       ip7500av_cs4384_mclk_entries[i].div = div;
38610 +                       printk("CS4384 mclk %d rate %u000Hz div %u act %u\n", i, rate, div, freq / div);
38611 +               }
38612 +
38613 +               cs4384_pd = audio_device_priv(audio_dev);
38614 +               cs4384_pd->mclk_src = UBI32_CS4384_MCLK_PWM_0;
38615 +               cs4384_pd->n_mclk = ARRAY_SIZE(ip7500av_cs4384_mclk_entries);
38616 +               cs4384_pd->mclk_entries = ip7500av_cs4384_mclk_entries;
38617 +               ip7500av_i2c_board_info[0].platform_data = audio_dev;
38618 +
38619 +               /*
38620 +                * Reset the DAC
38621 +                */
38622 +               if (gpio_request(GPIO_RF_4, "DAC Reset") == 0) {
38623 +                       gpio_direction_output(GPIO_RF_4, 0);
38624 +                       udelay(1);
38625 +                       gpio_direction_output(GPIO_RF_4, 1);
38626 +               } else {
38627 +                       printk("Unable to request DAC reset GPIO\n");
38628 +               }
38629 +       }
38630 +
38631 +       /*
38632 +        * SPDIF port
38633 +        */
38634 +       audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
38635 +       if (audio_dev2) {
38636 +               platform_device_register(audio_dev2);
38637 +       }
38638 +
38639 +       /*
38640 +        * Register all of the devices which sit on the I2C bus
38641 +        */
38642 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38643 +       i2c_register_board_info(0, ip7500av_i2c_board_info, ARRAY_SIZE(ip7500av_i2c_board_info));
38644 +
38645 +       printk(KERN_INFO "IP7500 Audio/Video Board\n");
38646 +       return 0;
38647 +}
38648 +arch_initcall(ip7500av_init);
38649 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500iap.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500iap.c
38650 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500iap.c   1970-01-01 02:00:00.000000000 +0200
38651 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500iap.c       2009-12-11 11:45:11.000000000 +0200
38652 @@ -0,0 +1,414 @@
38653 +/*
38654 + * arch/ubicom32/mach-ip7k/board-ip7500iap.c
38655 + *   Support for IP7500 Internet Audio Player
38656 + *
38657 + * This file supports the IP7500 Internet Audio Player:
38658 + *     8007-1110  Rev 1.0
38659 + *
38660 + * (C) Copyright 2009, Ubicom, Inc.
38661 + *
38662 + * This file is part of the Ubicom32 Linux Kernel Port.
38663 + *
38664 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38665 + * it and/or modify it under the terms of the GNU General Public License
38666 + * as published by the Free Software Foundation, either version 2 of the
38667 + * License, or (at your option) any later version.
38668 + *
38669 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38670 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38671 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
38672 + * the GNU General Public License for more details.
38673 + *
38674 + * You should have received a copy of the GNU General Public License
38675 + * along with the Ubicom32 Linux Kernel Port.  If not,
38676 + * see <http://www.gnu.org/licenses/>.
38677 + */
38678 +#include <linux/device.h>
38679 +#include <linux/gpio.h>
38680 +#include <asm/board.h>
38681 +
38682 +#include <linux/delay.h>
38683 +
38684 +#include <linux/platform_device.h>
38685 +#include <asm/audio.h>
38686 +#include <linux/i2c.h>
38687 +#include <linux/i2c-gpio.h>
38688 +
38689 +#include <asm/ubicom32sd.h>
38690 +#include <asm/sd_tio.h>
38691 +
38692 +#include <asm/ubicom32bl.h>
38693 +
38694 +#include <asm/machdep.h>
38695 +
38696 +/******************************************************************************
38697 + * SD/IO Port F (Slot 1) platform data
38698 + */
38699 +static struct resource ip7500iap_portf_sd_resources[] = {
38700 +       /*
38701 +        * Send IRQ
38702 +        */
38703 +       [0] = {
38704 +               /*
38705 +                * The init routine will query the devtree and fill this in
38706 +                */
38707 +               .flags  = IORESOURCE_IRQ,
38708 +       },
38709 +
38710 +       /*
38711 +        * Receive IRQ
38712 +        */
38713 +       [1] = {
38714 +               /*
38715 +                * The init routine will query the devtree and fill this in
38716 +                */
38717 +               .flags  = IORESOURCE_IRQ,
38718 +       },
38719 +
38720 +       /*
38721 +        * Memory Mapped Registers
38722 +        */
38723 +       [2] = {
38724 +               /*
38725 +                * The init routine will query the devtree and fill this in
38726 +                */
38727 +               .flags  = IORESOURCE_MEM,
38728 +       },
38729 +};
38730 +
38731 +static struct ubicom32sd_card ip7500iap_portf_sd_cards[] = {
38732 +       [0] = {
38733 +               .pin_wp         = GPIO_RF_7,
38734 +               .wp_polarity    = 1,
38735 +               .pin_pwr        = GPIO_RF_8,
38736 +               .pin_cd         = GPIO_RF_6,
38737 +       },
38738 +};
38739 +
38740 +static struct ubicom32sd_platform_data ip7500iap_portf_sd_platform_data = {
38741 +       .ncards         = 1,
38742 +       .cards          = ip7500iap_portf_sd_cards,
38743 +};
38744 +
38745 +static struct platform_device ip7500iap_portf_sd_device = {
38746 +       .name           = "ubicom32sd",
38747 +       .id             = 0,
38748 +       .resource       = ip7500iap_portf_sd_resources,
38749 +       .num_resources  = ARRAY_SIZE(ip7500iap_portf_sd_resources),
38750 +       .dev            = {
38751 +                       .platform_data = &ip7500iap_portf_sd_platform_data,
38752 +       },
38753 +
38754 +};
38755 +
38756 +/*
38757 + * ip7500iap_portf_sd_init
38758 + */
38759 +static void ip7500iap_portf_sd_init(void)
38760 +{
38761 +       /*
38762 +        * Check the device tree for the sd_tio
38763 +        */
38764 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
38765 +       if (!sd_node) {
38766 +               printk(KERN_INFO "PortF SDTIO not found\n");
38767 +               return;
38768 +       }
38769 +
38770 +       /*
38771 +        * Fill in the resources and platform data from devtree information
38772 +        */
38773 +       ip7500iap_portf_sd_resources[0].start = sd_node->dn.sendirq;
38774 +       ip7500iap_portf_sd_resources[1].start = sd_node->dn.recvirq;
38775 +       ip7500iap_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
38776 +       ip7500iap_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38777 +
38778 +       platform_device_register(&ip7500iap_portf_sd_device);
38779 +}
38780 +
38781 +/******************************************************************************
38782 + * SD/IO Port B (Slot 2) platform data
38783 + */
38784 +static struct resource ip7500iap_portb_sd_resources[] = {
38785 +       /*
38786 +        * Send IRQ
38787 +        */
38788 +       [0] = {
38789 +               /*
38790 +                * The init routine will query the devtree and fill this in
38791 +                */
38792 +               .flags  = IORESOURCE_IRQ,
38793 +       },
38794 +
38795 +       /*
38796 +        * Receive IRQ
38797 +        */
38798 +       [1] = {
38799 +               /*
38800 +                * The init routine will query the devtree and fill this in
38801 +                */
38802 +               .flags  = IORESOURCE_IRQ,
38803 +       },
38804 +
38805 +       /*
38806 +        * Memory Mapped Registers
38807 +        */
38808 +       [2] = {
38809 +               /*
38810 +                * The init routine will query the devtree and fill this in
38811 +                */
38812 +               .flags  = IORESOURCE_MEM,
38813 +       },
38814 +};
38815 +
38816 +static struct ubicom32sd_card ip7500iap_portb_sd_cards[] = {
38817 +       [0] = {
38818 +               .pin_wp         = GPIO_RB_13,
38819 +               .wp_polarity    = 1,
38820 +               .pin_pwr        = GPIO_RB_11,
38821 +               .pin_cd         = GPIO_RB_12,
38822 +       },
38823 +};
38824 +
38825 +static struct ubicom32sd_platform_data ip7500iap_portb_sd_platform_data = {
38826 +       .ncards         = 1,
38827 +       .cards          = ip7500iap_portb_sd_cards,
38828 +};
38829 +
38830 +static struct platform_device ip7500iap_portb_sd_device = {
38831 +       .name           = "ubicom32sd",
38832 +       .id             = 1,
38833 +       .resource       = ip7500iap_portb_sd_resources,
38834 +       .num_resources  = ARRAY_SIZE(ip7500iap_portb_sd_resources),
38835 +       .dev            = {
38836 +                       .platform_data = &ip7500iap_portb_sd_platform_data,
38837 +       },
38838 +
38839 +};
38840 +
38841 +/*
38842 + * ip7500iap_portb_sd_init
38843 + */
38844 +static void ip7500iap_portb_sd_init(void)
38845 +{
38846 +       /*
38847 +        * Check the device tree for the sd_tio
38848 +        */
38849 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
38850 +       if (!sd_node) {
38851 +               printk(KERN_INFO "PortB SDTIO not found\n");
38852 +               return;
38853 +       }
38854 +
38855 +       /*
38856 +        * Fill in the resources and platform data from devtree information
38857 +        */
38858 +       ip7500iap_portb_sd_resources[0].start = sd_node->dn.sendirq;
38859 +       ip7500iap_portb_sd_resources[1].start = sd_node->dn.recvirq;
38860 +       ip7500iap_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
38861 +       ip7500iap_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38862 +
38863 +       platform_device_register(&ip7500iap_portb_sd_device);
38864 +}
38865 +
38866 +/******************************************************************************
38867 + * Touch controller
38868 + *
38869 + * Connected via I2C bus, interrupt on PA6
38870 + */
38871 +#include <linux/i2c/tsc2007.h>
38872 +
38873 +/*
38874 + * ip7500iap_tsc2007_exit_platform_hw
38875 + */
38876 +static void ip7500iap_tsc2007_exit_platform_hw(void)
38877 +{
38878 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38879 +       gpio_free(GPIO_RA_6);
38880 +}
38881 +
38882 +/*
38883 + * ip7500iap_tsc2007_init_platform_hw
38884 + */
38885 +static int ip7500iap_tsc2007_init_platform_hw(void)
38886 +{
38887 +       int res = gpio_request(GPIO_RA_6, "TSC2007_IRQ");
38888 +       if (res) {
38889 +               return res;
38890 +       }
38891 +
38892 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38893 +       UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 19);
38894 +       return 0;
38895 +}
38896 +
38897 +/*
38898 + * ip7500iap_tsc2007_get_pendown_state
38899 + */
38900 +static int ip7500iap_tsc2007_get_pendown_state(void)
38901 +{
38902 +       return !gpio_get_value(GPIO_RA_6);
38903 +}
38904 +
38905 +static struct tsc2007_platform_data ip7500iap_tsc2007_data = {
38906 +       .model                  = 2007,
38907 +       .x_plate_ohms           = 350,
38908 +       .get_pendown_state      = ip7500iap_tsc2007_get_pendown_state,
38909 +       .init_platform_hw       = ip7500iap_tsc2007_init_platform_hw,
38910 +       .exit_platform_hw       = ip7500iap_tsc2007_exit_platform_hw,
38911 +};
38912 +
38913 +/******************************************************************************
38914 + * i2c devices
38915 + *
38916 + * DO NOT CHANGE THE ORDER HERE unless you know how this works.  There
38917 + * are hardcoded indicies which refer to the order of drivers listed here.
38918 + */
38919 +static struct i2c_board_info __initdata ip7500iap_i2c_board_info[] = {
38920 +       /*
38921 +        * U6, CS4350 DAC, address 0x4B
38922 +        */
38923 +       {
38924 +               .type           = "cs4350",
38925 +               .addr           = 0x4B,
38926 +       },
38927 +
38928 +       /*
38929 +        * U20, S35390A RTC, address 0x30
38930 +        */
38931 +       {
38932 +               .type           = "s35390a",
38933 +               .addr           = 0x30,
38934 +       },
38935 +
38936 +       /*
38937 +        * U9, TSC2007 Touch screen controller, address 0x49, irq RA6
38938 +        */
38939 +       {
38940 +               .type           = "tsc2007",
38941 +               .addr           = 0x49,
38942 +               .irq            = 46,
38943 +               .platform_data  = &ip7500iap_tsc2007_data,
38944 +       },
38945 +};
38946 +
38947 +/*
38948 + * I2C bus on the board, SDA PE4, SCL PE5
38949 + */
38950 +static struct i2c_gpio_platform_data ip7500iap_i2c_data = {
38951 +       .sda_pin                = GPIO_RF_14,
38952 +       .scl_pin                = GPIO_RF_13,
38953 +       .sda_is_open_drain      = 0,
38954 +       .scl_is_open_drain      = 0,
38955 +       .udelay                 = 50,
38956 +};
38957 +
38958 +static struct platform_device ip7500iap_i2c_device = {
38959 +       .name   = "i2c-gpio",
38960 +       .id     = 0,
38961 +       .dev    = {
38962 +               .platform_data = &ip7500iap_i2c_data,
38963 +       },
38964 +};
38965 +
38966 +/******************************************************************************
38967 + * Backlight on the board PD0, hardware PWM
38968 + */
38969 +static struct ubicom32bl_platform_data ip7500iap_backlight_data = {
38970 +       .type                   = UBICOM32BL_TYPE_PWM,
38971 +       .pwm_channel            = 2,
38972 +       .pwm_prescale           = 15,
38973 +       .pwm_period             = 60,
38974 +       .default_intensity      = 0x80,
38975 +};
38976 +
38977 +static struct platform_device ip7500iap_backlight_device = {
38978 +       .name   = "ubicom32bl",
38979 +       .id     = -1,
38980 +       .dev    = {
38981 +               .platform_data = &ip7500iap_backlight_data,
38982 +       },
38983 +};
38984 +
38985 +/******************************************************************************
38986 + * Devices on this board
38987 + */
38988 +static struct platform_device *ip7500iap_devices[] __initdata = {
38989 +       &ip7500iap_i2c_device,
38990 +       &ip7500iap_backlight_device,
38991 +};
38992 +
38993 +/*
38994 + * ip7500iap_power_off
38995 + *     Called to turn the power off for this board
38996 + */
38997 +static void ip7500iap_power_off(void)
38998 +{
38999 +       gpio_set_value(GPIO_RF_11, 0);
39000 +}
39001 +
39002 +/*
39003 + * ip7500iap_init
39004 + *     Called to add the devices which we have on this board
39005 + */
39006 +static int __init ip7500iap_init(void)
39007 +{
39008 +       struct platform_device *audio_dev;
39009 +       struct platform_device *audio_dev2;
39010 +       int ret;
39011 +
39012 +       board_init();
39013 +
39014 +       ubi_gpio_init();
39015 +
39016 +       /*
39017 +        * Hold the POWER_HOLD line
39018 +        */
39019 +       ret = gpio_request(GPIO_RF_11, "POWER_HOLD");
39020 +       if (ret) {
39021 +               printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
39022 +       }
39023 +       gpio_direction_output(GPIO_RF_11, 1);
39024 +       mach_power_off = ip7500iap_power_off;
39025 +
39026 +       /*
39027 +        * DAC nRESET line
39028 +        */
39029 +       ret = gpio_request(GPIO_RE_7, "DAC_nRESET");
39030 +       if (ret) {
39031 +               printk(KERN_ERR "%s: could not request DAC_nRESET GPIO\n", __FUNCTION__);
39032 +       }
39033 +       gpio_direction_output(GPIO_RE_7, 0);
39034 +       udelay(1);
39035 +       gpio_set_value(GPIO_RE_7, 1);
39036 +
39037 +       /*
39038 +        * Bring up any SDIO slots
39039 +        */
39040 +       ip7500iap_portb_sd_init();
39041 +       ip7500iap_portf_sd_init();
39042 +
39043 +       /*
39044 +        * Bring up audio devices
39045 +        */
39046 +       platform_add_devices(ip7500iap_devices, ARRAY_SIZE(ip7500iap_devices));
39047 +
39048 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39049 +       if (audio_dev) {
39050 +               ip7500iap_i2c_board_info[0].platform_data = audio_dev;
39051 +       }
39052 +
39053 +       audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39054 +       if (audio_dev2) {
39055 +               platform_device_register(audio_dev2);
39056 +       }
39057 +
39058 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39059 +       i2c_register_board_info(0, ip7500iap_i2c_board_info, ARRAY_SIZE(ip7500iap_i2c_board_info));
39060 +
39061 +       printk(KERN_INFO "IP7500 Internet Audio Player\n");
39062 +
39063 +       return 0;
39064 +}
39065 +
39066 +arch_initcall(ip7500iap_init);
39067 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500media.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500media.c
39068 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500media.c 1970-01-01 02:00:00.000000000 +0200
39069 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500media.c     2009-12-11 11:45:11.000000000 +0200
39070 @@ -0,0 +1,732 @@
39071 +/*
39072 + * arch/ubicom32/mach-ip7k/board-ip7500media.c
39073 + *   Board file for IP7500 media board.
39074 + *
39075 + * Supports the following configuration
39076 + *     CPU Module:
39077 + *             P/N 8007-0510 rev 1.0 NOPHY
39078 + *             P/N 8007-0511 rev 1.1 NOPHY
39079 + *                     DIP Switch SW2 configuration:
39080 + *                             POS 1: on  = PCI enabled
39081 + *                             POS 2: off = TTYX => PF12
39082 + *                             POS 3: off = TTYY => PF15
39083 + *                             POS 4: unused
39084 + *     Media Board:
39085 + *             P/N 8007-0610 rev 1.0
39086 + *
39087 + *     LCD Adapter Board: (optional)
39088 + *             P/N 8007-0920 rev 2.0
39089 + *             P/N 8007-0921 rev 2.1
39090 + *
39091 + * (C) Copyright 2009, Ubicom, Inc.
39092 + *
39093 + * This file is part of the Ubicom32 Linux Kernel Port.
39094 + *
39095 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39096 + * it and/or modify it under the terms of the GNU General Public License
39097 + * as published by the Free Software Foundation, either version 2 of the
39098 + * License, or (at your option) any later version.
39099 + *
39100 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39101 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39102 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39103 + * the GNU General Public License for more details.
39104 + *
39105 + * You should have received a copy of the GNU General Public License
39106 + * along with the Ubicom32 Linux Kernel Port.  If not,
39107 + * see <http://www.gnu.org/licenses/>.
39108 + *
39109 + * Ubicom32 implementation derived from (with many thanks):
39110 + *   arch/m68knommu
39111 + *   arch/blackfin
39112 + *   arch/parisc
39113 + */
39114 +#include <linux/device.h>
39115 +#include <linux/platform_device.h>
39116 +#include <linux/gpio.h>
39117 +
39118 +#include <linux/input.h>
39119 +
39120 +#include <linux/i2c.h>
39121 +#include <linux/i2c-gpio.h>
39122 +#include <linux/i2c/pca953x.h>
39123 +
39124 +#include <asm/board.h>
39125 +#include <asm/machdep.h>
39126 +#include <asm/ubicom32input_i2c.h>
39127 +#include <asm/ubicom32bl.h>
39128 +#include <asm/ubicom32lcdpower.h>
39129 +#include <asm/vdc_tio.h>
39130 +
39131 +#include <asm/ubicom32sd.h>
39132 +#include <asm/sd_tio.h>
39133 +#include <asm/devtree.h>
39134 +#include <asm/audio.h>
39135 +
39136 +#include <asm/ring_tio.h>
39137 +
39138 +/******************************************************************************
39139 + * SD/IO Port F (Slot 1) platform data
39140 + */
39141 +static struct resource ip7500media_portf_sd_resources[] = {
39142 +       /*
39143 +        * Send IRQ
39144 +        */
39145 +       [0] = {
39146 +               /*
39147 +                * The init routine will query the devtree and fill this in
39148 +                */
39149 +               .flags  = IORESOURCE_IRQ,
39150 +       },
39151 +
39152 +       /*
39153 +        * Receive IRQ
39154 +        */
39155 +       [1] = {
39156 +               /*
39157 +                * The init routine will query the devtree and fill this in
39158 +                */
39159 +               .flags  = IORESOURCE_IRQ,
39160 +       },
39161 +
39162 +       /*
39163 +        * Memory Mapped Registers
39164 +        */
39165 +       [2] = {
39166 +               /*
39167 +                * The init routine will query the devtree and fill this in
39168 +                */
39169 +               .flags  = IORESOURCE_MEM,
39170 +       },
39171 +};
39172 +
39173 +static struct ubicom32sd_card ip7500media_portf_sd_cards[] = {
39174 +       [0] = {
39175 +               .pin_wp         = IP7500MEDIA_IO16,
39176 +               .wp_polarity    = 1,
39177 +               .pin_pwr        = IP7500MEDIA_IO20,
39178 +               .pin_cd         = IP7500MEDIA_IO23,
39179 +       },
39180 +       [1] = {
39181 +               .pin_wp         = IP7500MEDIA_IO17,
39182 +               .wp_polarity    = 1,
39183 +               .pin_pwr        = IP7500MEDIA_IO21,
39184 +               .pin_cd         = IP7500MEDIA_IO24,
39185 +       },
39186 +};
39187 +
39188 +static struct ubicom32sd_platform_data ip7500media_portf_sd_platform_data = {
39189 +       .ncards         = 2,
39190 +       .cards          = ip7500media_portf_sd_cards,
39191 +};
39192 +
39193 +static struct platform_device ip7500media_portf_sd_device = {
39194 +       .name           = "ubicom32sd",
39195 +       .id             = 0,
39196 +       .resource       = ip7500media_portf_sd_resources,
39197 +       .num_resources  = ARRAY_SIZE(ip7500media_portf_sd_resources),
39198 +       .dev            = {
39199 +                       .platform_data = &ip7500media_portf_sd_platform_data,
39200 +       },
39201 +
39202 +};
39203 +
39204 +/*
39205 + * ip7500media_portf_sd_init
39206 + */
39207 +static void ip7500media_portf_sd_init(void)
39208 +{
39209 +       /*
39210 +        * Check the device tree for the sd_tio
39211 +        */
39212 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
39213 +       if (!sd_node) {
39214 +               printk(KERN_INFO "PortF SDTIO not found\n");
39215 +               return;
39216 +       }
39217 +
39218 +       /*
39219 +        * Fill in the resources and platform data from devtree information
39220 +        */
39221 +       ip7500media_portf_sd_resources[0].start = sd_node->dn.sendirq;
39222 +       ip7500media_portf_sd_resources[1].start = sd_node->dn.recvirq;
39223 +       ip7500media_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
39224 +       ip7500media_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
39225 +
39226 +       platform_device_register(&ip7500media_portf_sd_device);
39227 +}
39228 +
39229 +/******************************************************************************
39230 + * SD/IO Port B (Slot 2) platform data
39231 + */
39232 +static struct resource ip7500media_portb_sd_resources[] = {
39233 +       /*
39234 +        * Send IRQ
39235 +        */
39236 +       [0] = {
39237 +               /*
39238 +                * The init routine will query the devtree and fill this in
39239 +                */
39240 +               .flags  = IORESOURCE_IRQ,
39241 +       },
39242 +
39243 +       /*
39244 +        * Receive IRQ
39245 +        */
39246 +       [1] = {
39247 +               /*
39248 +                * The init routine will query the devtree and fill this in
39249 +                */
39250 +               .flags  = IORESOURCE_IRQ,
39251 +       },
39252 +
39253 +       /*
39254 +        * Memory Mapped Registers
39255 +        */
39256 +       [2] = {
39257 +               /*
39258 +                * The init routine will query the devtree and fill this in
39259 +                */
39260 +               .flags  = IORESOURCE_MEM,
39261 +       },
39262 +};
39263 +
39264 +static struct ubicom32sd_card ip7500media_portb_sd_cards[] = {
39265 +       [0] = {
39266 +               .pin_wp         = IP7500MEDIA_IO19,
39267 +               .wp_polarity    = 1,
39268 +               .pin_pwr        = IP7500MEDIA_IO22,
39269 +               .pin_cd         = IP7500MEDIA_IO18,
39270 +       },
39271 +};
39272 +
39273 +static struct ubicom32sd_platform_data ip7500media_portb_sd_platform_data = {
39274 +       .ncards         = 1,
39275 +       .cards          = ip7500media_portb_sd_cards,
39276 +};
39277 +
39278 +static struct platform_device ip7500media_portb_sd_device = {
39279 +       .name           = "ubicom32sd",
39280 +       .id             = 1,
39281 +       .resource       = ip7500media_portb_sd_resources,
39282 +       .num_resources  = ARRAY_SIZE(ip7500media_portb_sd_resources),
39283 +       .dev            = {
39284 +                       .platform_data = &ip7500media_portb_sd_platform_data,
39285 +       },
39286 +
39287 +};
39288 +
39289 +/*
39290 + * ip7500media_portb_sd_init
39291 + */
39292 +static void ip7500media_portb_sd_init(void)
39293 +{
39294 +       /*
39295 +        * Check the device tree for the sd_tio
39296 +        */
39297 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
39298 +       if (!sd_node) {
39299 +               printk(KERN_INFO "PortB SDTIO not found\n");
39300 +               return;
39301 +       }
39302 +
39303 +       /*
39304 +        * Fill in the resources and platform data from devtree information
39305 +        */
39306 +       ip7500media_portb_sd_resources[0].start = sd_node->dn.sendirq;
39307 +       ip7500media_portb_sd_resources[1].start = sd_node->dn.recvirq;
39308 +       ip7500media_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
39309 +       ip7500media_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
39310 +
39311 +       platform_device_register(&ip7500media_portb_sd_device);
39312 +}
39313 +
39314 +/*
39315 + * ip7500media_u17_setup
39316 + *     Called by I2C to tell us that u17 is setup.
39317 + *
39318 + * This function is called by I2C to tell us that u17 has been setup.  All
39319 + * devices which rely on this chip being initialized (or even present) need to
39320 + * be initialized in this function otherwise they may get initialized too early.
39321 + *
39322 + * Currently the only device depending on u17 is the SDIO
39323 + */
39324 +static int __init ip7500media_u17_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
39325 +{
39326 +       /*
39327 +        * Initialize the Port F/Port B SD slots (only the enabled ports will init)
39328 +        */
39329 +       ip7500media_portf_sd_init();
39330 +       ip7500media_portb_sd_init();
39331 +
39332 +       return 0;
39333 +}
39334 +
39335 +/******************************************************************************
39336 + * LCD VGH on the board at PE6
39337 + */
39338 +static struct ubicom32lcdpower_platform_data ip7500media_lcdpower_data = {
39339 +       .vgh_gpio               = GPIO_RE_7,
39340 +       .vgh_polarity           = true,
39341 +};
39342 +
39343 +static struct platform_device ip7500media_lcdpower_device = {
39344 +       .name   = "ubicom32lcdpower",
39345 +       .id     = -1,
39346 +       .dev    = {
39347 +               .platform_data = &ip7500media_lcdpower_data,
39348 +       },
39349 +};
39350 +
39351 +/******************************************************************************
39352 + * Backlight on the board PD0, hardware PWM
39353 + */
39354 +static struct ubicom32bl_platform_data ip7500media_backlight_data = {
39355 +       .type                   = UBICOM32BL_TYPE_PWM,
39356 +       .pwm_channel            = 2,
39357 +       .pwm_prescale           = 15,
39358 +       .pwm_period             = 60,
39359 +       .default_intensity      = 0x80,
39360 +};
39361 +
39362 +static struct platform_device ip7500media_backlight_device = {
39363 +       .name   = "ubicom32bl",
39364 +       .id     = -1,
39365 +       .dev    = {
39366 +               .platform_data = &ip7500media_backlight_data,
39367 +       },
39368 +};
39369 +
39370 +/******************************************************************************
39371 + * Ubicom32Input on I2C, U15 MAX7310, address 0x18, 8 bits
39372 + */
39373 +static struct ubicom32input_i2c_button ip7500media_ubicom32input_i2c_u15_buttons[] = {
39374 +       {
39375 +               .type           = EV_KEY,
39376 +               .code           = KEY_LEFT,
39377 +               .bit            = 0,
39378 +               .active_low     = 1,
39379 +       },
39380 +       {
39381 +               .type           = EV_KEY,
39382 +               .code           = KEY_RIGHT,
39383 +               .bit            = 1,
39384 +               .active_low     = 1,
39385 +       },
39386 +       {
39387 +               .type           = EV_KEY,
39388 +               .code           = KEY_UP,
39389 +               .bit            = 2,
39390 +               .active_low     = 1,
39391 +       },
39392 +       {
39393 +               .type           = EV_KEY,
39394 +               .code           = KEY_DOWN,
39395 +               .bit            = 3,
39396 +               .active_low     = 1,
39397 +       },
39398 +       {
39399 +               .type           = EV_KEY,
39400 +               .code           = KEY_ENTER,
39401 +               .bit            = 4,
39402 +               .active_low     = 1,
39403 +       },
39404 +       {
39405 +               .type           = EV_KEY,
39406 +               .code           = KEY_MENU,
39407 +               .bit            = 5,
39408 +               .active_low     = 1,
39409 +       },
39410 +       {
39411 +               .type           = EV_KEY,
39412 +               .code           = KEY_ESC,
39413 +               .bit            = 6,
39414 +               .active_low     = 1,
39415 +       },
39416 +};
39417 +
39418 +static struct ubicom32input_i2c_platform_data ip7500media_ubicom32input_i2c_u15_platform_data = {
39419 +       .buttons        = ip7500media_ubicom32input_i2c_u15_buttons,
39420 +       .nbuttons       = ARRAY_SIZE(ip7500media_ubicom32input_i2c_u15_buttons),
39421 +       .name           = "Ubicom32 Input I2C U15",
39422 +};
39423 +
39424 +/******************************************************************************
39425 + * Additional GPIO chips
39426 + */
39427 +static struct pca953x_platform_data ip7500media_gpio_u16_platform_data = {
39428 +       .gpio_base = IP7500MEDIA_U16_BASE,
39429 +};
39430 +
39431 +static struct pca953x_platform_data ip7500media_gpio_u17_platform_data = {
39432 +       .gpio_base = IP7500MEDIA_U17_BASE,
39433 +       .setup = ip7500media_u17_setup,
39434 +};
39435 +
39436 +static struct pca953x_platform_data ip7500media_gpio_u18_platform_data = {
39437 +       .gpio_base = IP7500MEDIA_U18_BASE,
39438 +};
39439 +
39440 +
39441 +/******************************************************************************
39442 + * Touch controller present on LCD Adapter board
39443 + *
39444 + * Connected via I2C bus, interrupt on PD1
39445 + */
39446 +#include <linux/i2c/tsc2007.h>
39447 +
39448 +/*
39449 + * ip7500media_tsc2007_exit_platform_hw
39450 + */
39451 +static void ip7500media_tsc2007_exit_platform_hw(void)
39452 +{
39453 +       UBICOM32_IO_PORT(RD)->int_mask &= ~(1 << 11);
39454 +       UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39455 +       gpio_free(GPIO_RD_1);
39456 +}
39457 +
39458 +/*
39459 + * ip7500media_tsc2007_init_platform_hw
39460 + */
39461 +static int ip7500media_tsc2007_init_platform_hw(void)
39462 +{
39463 +       int res = gpio_request(GPIO_RD_1, "TSC2007_IRQ");
39464 +       if (res) {
39465 +               return res;
39466 +       }
39467 +       UBICOM32_IO_PORT(RD)->function = 0;
39468 +       UBICOM32_IO_PORT(RD)->int_mask = (1 << 11);
39469 +       UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39470 +       UBICOM32_IO_PORT(RD)->ctl2 |= (0x02 << 16);
39471 +
39472 +       return 0;
39473 +}
39474 +
39475 +/*
39476 + * ip7500media_tsc2007_clear_penirq
39477 + */
39478 +static void ip7500media_tsc2007_clear_penirq(void)
39479 +{
39480 +       UBICOM32_IO_PORT(RD)->int_clr = (1 << 11);
39481 +}
39482 +
39483 +/*
39484 + * ip7500media_tsc2007_get_pendown_state
39485 + */
39486 +static int ip7500media_tsc2007_get_pendown_state(void)
39487 +{
39488 +       return !gpio_get_value(GPIO_RD_1);
39489 +}
39490 +
39491 +static struct tsc2007_platform_data ip7500media_tsc2007_data = {
39492 +       .model                  = 2007,
39493 +       .x_plate_ohms           = 350,
39494 +       .get_pendown_state      = ip7500media_tsc2007_get_pendown_state,
39495 +       .init_platform_hw       = ip7500media_tsc2007_init_platform_hw,
39496 +       .exit_platform_hw       = ip7500media_tsc2007_exit_platform_hw,
39497 +       .clear_penirq           = ip7500media_tsc2007_clear_penirq,
39498 +};
39499 +
39500 +/******************************************************************************
39501 + * Devices on the I2C bus
39502 + *
39503 + * BEWARE of changing the order of things in this array as we depend on
39504 + * certain things to be in certain places.
39505 + */
39506 +static struct i2c_board_info __initdata ip7500media_i2c_board_info[] = {
39507 +       /*
39508 +        * U6, CS4350 DAC, address 0x4B
39509 +        */
39510 +       {
39511 +               .type           = "cs4350",
39512 +               .addr           = 0x4B,
39513 +       },
39514 +
39515 +       /*
39516 +        * U14, S35390A RTC, address 0x30
39517 +        */
39518 +       {
39519 +               .type           = "s35390a",
39520 +               .addr           = 0x30,
39521 +       },
39522 +
39523 +       /*
39524 +        * U15, MAX7310 IO expander, 8 bits, address 0x18
39525 +        *      IO0: User I/O (J16-1) (Left)    IO4: User I/O (J16-5) (Enter)
39526 +        *      IO1: User I/O (J16-2) (Right)   IO5: User I/O (J16-6) (Menu)
39527 +        *      IO2: User I/O (J16-3) (Up)      IO6: User I/O (J16-7) (Back)
39528 +        *      IO3: User I/O (J16-4) (Down)    IO7: User I/O (J16-8)
39529 +        */
39530 +       {
39531 +               .type           = "ubicom32in_max7310",
39532 +               .addr           = 0x18,
39533 +               .platform_data  = &ip7500media_ubicom32input_i2c_u15_platform_data,
39534 +       },
39535 +
39536 +       /*
39537 +        * U16, MAX7310 IO expander, 8 bits, address 0x1C
39538 +        *      IO8 : User I/O (J16-9)          IO12: User I/O (J16-17)
39539 +        *      IO9 : User I/O (J16-10)         IO13: User I/O (J16-18)
39540 +        *      IO10: User I/O (J16-15)         IO14: User I/O (J16-19)
39541 +        *      IO11: User I/O (J16-16)         IO15: User I/O (J16-20)
39542 +        */
39543 +       {
39544 +               .type           = "max7310",
39545 +               .addr           = 0x1C,
39546 +               .platform_data  = &ip7500media_gpio_u16_platform_data,
39547 +       },
39548 +
39549 +       /*
39550 +        * U17, MAX7310 IO expander, 8 bits, address 0x1A
39551 +        *      IO16: SDIO1A_WP                 IO20: SD1A_PWREN
39552 +        *      IO17: SDIO1B_WP                 IO21: SD1B_PWREN
39553 +        *      IO18: SDIO2_CD                  IO22: SD2_PWREN
39554 +        *      IO19: SDIO2_WP                  IO23: SDIO1A_CD
39555 +        *
39556 +        */
39557 +       {
39558 +               .type           = "max7310",
39559 +               .addr           = 0x1A,
39560 +               .platform_data  = &ip7500media_gpio_u17_platform_data,
39561 +       },
39562 +
39563 +       /*
39564 +        * U18, MAX7310 IOB expander, 8 bits, address 0x1E
39565 +        *      IO24: SDIO1B_CD                 IO28: User I/O TP6
39566 +        *      IO25: User I/O TP9              IO29: User I/O TP5
39567 +        *      IO26: User I/O TP8              IO30: User I/O TP4
39568 +        *      IO27: User I/O TP7              IO31: User I/O TP3
39569 +        */
39570 +       {
39571 +               .type           = "max7310",
39572 +               .addr           = 0x1E,
39573 +               .platform_data  = &ip7500media_gpio_u18_platform_data,
39574 +       },
39575 +};
39576 +
39577 +/*
39578 + * Additional I2C devices to add when a LCD adapter board is present
39579 + */
39580 +static struct i2c_board_info __initdata ip7500media_lcd_adapter_i2c_board_info[] = {
39581 +       {
39582 +               I2C_BOARD_INFO("tsc2007", 0x48),
39583 +               .irq = PORT_OTHER_INT(RD),
39584 +               .platform_data = &ip7500media_tsc2007_data,
39585 +       },
39586 +};
39587 +
39588 +/*
39589 + * I2C bus on the board, SDA PE4, SCL PE5
39590 + */
39591 +static struct i2c_gpio_platform_data ip7500media_i2c_data = {
39592 +       .sda_pin                = GPIO_RE_4,
39593 +       .scl_pin                = GPIO_RE_5,
39594 +       .sda_is_open_drain      = 0,
39595 +       .scl_is_open_drain      = 0,
39596 +       .udelay                 = 50,
39597 +};
39598 +
39599 +static struct platform_device ip7500media_i2c_device = {
39600 +       .name   = "i2c-gpio",
39601 +       .id     = 0,
39602 +       .dev    = {
39603 +               .platform_data = &ip7500media_i2c_data,
39604 +       },
39605 +};
39606 +
39607 +/*
39608 + * Virtual Frame Buffer device for use with LCD Adapter
39609 + */
39610 +static struct platform_device ip7500media_vfb_device = {
39611 +       .name   = "ubicom32vfb",
39612 +       .id     = -1,
39613 +};
39614 +
39615 +/*
39616 + * vdc_override:
39617 + *     0: no override (auto-detect)
39618 + *     1: force vdc usage
39619 + *     2: force lcd adapter usage
39620 + */
39621 +static int __initdata vdc_override = 0;
39622 +
39623 +/*
39624 + * ip7500media_set_forcevdc
39625 + *     Called when forcevdc is present on the kernel boot line
39626 + */
39627 +static int __init ip7500media_set_forcevdc(char *str)
39628 +{
39629 +       if (str[0] == '1') {
39630 +               vdc_override = 1;
39631 +       } else {
39632 +               vdc_override = 2;
39633 +       }
39634 +       return 1;
39635 +}
39636 +
39637 +/*
39638 + * ip7500media_video_init
39639 + *     Called late to determine what kind of video we have on this board
39640 + */
39641 +static int __init ip7500media_video_init(void)
39642 +{
39643 +       struct i2c_adapter *adap;
39644 +       struct i2c_msg msg[1];
39645 +       unsigned char *data;
39646 +       unsigned char checksum;
39647 +       int err;
39648 +       int i;
39649 +
39650 +       if (vdc_override == 1) {
39651 +               printk(KERN_INFO "Force VDCTIO mode\n");
39652 +               goto no_adapter;
39653 +       }
39654 +       if (vdc_override == 2) {
39655 +               printk(KERN_INFO "Force LCD Adapter Board mode\n");
39656 +               return 0;
39657 +       }
39658 +
39659 +       /*
39660 +        * Check to see if there is an EEPROM out there.  If we see an
39661 +        * EEPROM then we will assume a LCD Adapter Board (8007-092x)
39662 +        * exists.
39663 +        */
39664 +       data = kmalloc(256, GFP_KERNEL);
39665 +       if (!data) {
39666 +               printk(KERN_WARNING "%s: Failed to allocate memory\n", __FUNCTION__);
39667 +               return -ENOMEM;
39668 +       }
39669 +
39670 +       adap = i2c_get_adapter(0);
39671 +       if (!adap) {
39672 +               printk(KERN_WARNING "%s: Failed to get i2c adapter\n", __FUNCTION__);
39673 +               kfree(data);
39674 +               return -ENODEV;
39675 +       }
39676 +       data[0] = 0;
39677 +       msg->addr = 0x50;
39678 +       msg->flags = 0;
39679 +       msg->len = 1;
39680 +       msg->buf = data;
39681 +       err = i2c_transfer(adap, msg, 1);
39682 +       if (err < 0) {
39683 +               goto no_adapter;
39684 +       }
39685 +
39686 +       msg->addr = 0x50;
39687 +       msg->flags = I2C_M_RD;
39688 +       msg->len = 256;
39689 +       msg->buf = data;
39690 +       err = i2c_transfer(adap, msg, 1);
39691 +       if (err < 0) {
39692 +               goto no_adapter;
39693 +       }
39694 +
39695 +       i2c_put_adapter(adap);
39696 +
39697 +       /*
39698 +        * Verify the checksum
39699 +        */
39700 +       checksum = 0xff;
39701 +       for (i = 0; i < 255; i++) {
39702 +               checksum ^= data[i];
39703 +       }
39704 +       if (checksum != data[255]) {
39705 +               printk(KERN_WARNING "%s: Checksum mismatch\n", __FUNCTION__);
39706 +       }
39707 +
39708 +       kfree(data);
39709 +
39710 +       /*
39711 +        * Bring up VFB
39712 +        */
39713 +       platform_device_register(&ip7500media_vfb_device);
39714 +
39715 +       /*
39716 +        * Add the i2c devices on the LCD Adapter board.  (We have to use i2c_new_device
39717 +        * since it's late in the boot process.)
39718 +        */
39719 +       printk(KERN_INFO "%s: registering LCD Adapter board i2c resources\n", __FUNCTION__);
39720 +       for (i = 0; i < ARRAY_SIZE(ip7500media_lcd_adapter_i2c_board_info); i++) {
39721 +               i2c_new_device(adap, &ip7500media_lcd_adapter_i2c_board_info[i]);
39722 +       }
39723 +
39724 +       i2c_put_adapter(adap);
39725 +
39726 +       return 0;
39727 +
39728 +       /*
39729 +        * No LCD Adapter board, bring up VDC
39730 +        */
39731 +no_adapter:
39732 +       vdc_tio_init();
39733 +       return 0;
39734 +}
39735 +late_initcall(ip7500media_video_init);
39736 +__setup("forcevdc=", ip7500media_set_forcevdc);
39737 +
39738 +/*
39739 + * ip7500media_init
39740 + *     Called to add the devices which we have on this board
39741 + */
39742 +static int __init ip7500media_init(void)
39743 +{
39744 +       struct platform_device *audio_dev;
39745 +       int have_ethernet = (devtree_find_node("eth_lan") != 0);
39746 +
39747 +       board_init();
39748 +
39749 +       ubi_gpio_init();
39750 +
39751 +#ifdef CONFIG_UIO_UBICOM32RING
39752 +       ring_tio_init("decoder_ring");
39753 +#endif
39754 +
39755 +       /*
39756 +        * Register all of the devices we have on this board
39757 +        */
39758 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
39759 +       platform_device_register(&ip7500media_i2c_device);
39760 +       platform_device_register(&ip7500media_backlight_device);
39761 +
39762 +       /*
39763 +        * If ethernet doesn't exist then we can init the lcdpower
39764 +        */
39765 +       if (!have_ethernet) {
39766 +               platform_device_register(&ip7500media_lcdpower_device);
39767 +       }
39768 +
39769 +       /*
39770 +        * Allocate the audio drivers.  SPDIF not supported on boards with ethernet.
39771 +        */
39772 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39773 +       if (audio_dev) {
39774 +               ip7500media_i2c_board_info[0].platform_data = audio_dev;
39775 +       }
39776 +
39777 +       if (!have_ethernet) {
39778 +               struct platform_device *audio_dev2;
39779 +
39780 +               audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39781 +               if (audio_dev2) {
39782 +                       platform_device_register(audio_dev2);
39783 +               }
39784 +       }
39785 +
39786 +       /*
39787 +        * Register all of the devices which sit on the I2C bus
39788 +        */
39789 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39790 +       i2c_register_board_info(0, ip7500media_i2c_board_info, ARRAY_SIZE(ip7500media_i2c_board_info));
39791 +
39792 +       /*
39793 +        * We have to initialize the SDIO after the I2C IOB gets setup.  SDIO is initialized in
39794 +        * ip7500media_u17_setup
39795 +        */
39796 +
39797 +       printk("IP7500 Media Board\n");
39798 +
39799 +       return 0;
39800 +}
39801 +
39802 +arch_initcall(ip7500media_init);
39803 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500module.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500module.c
39804 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500module.c        1970-01-01 02:00:00.000000000 +0200
39805 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500module.c    2009-12-11 11:45:11.000000000 +0200
39806 @@ -0,0 +1,55 @@
39807 +/*
39808 + * arch/ubicom32/mach-ip7k/board-ip7500module.c
39809 + *   Support for IP7500 CPU module board.
39810 + *
39811 + * This file supports the IP7500 CPU module board:
39812 + *     8007-0510  Rev 1.0
39813 + *     8007-0510A Rev 1.0 (with ethernet)
39814 + *
39815 + * DIP Switch SW2 configuration: (*) default
39816 + *     POS 1: on(*) = PCI enabled, off = PCI disabled
39817 + *     POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
39818 + *     POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
39819 + *     POS 4: unused
39820 + *
39821 + * (C) Copyright 2009, Ubicom, Inc.
39822 + *
39823 + * This file is part of the Ubicom32 Linux Kernel Port.
39824 + *
39825 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39826 + * it and/or modify it under the terms of the GNU General Public License
39827 + * as published by the Free Software Foundation, either version 2 of the
39828 + * License, or (at your option) any later version.
39829 + *
39830 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39831 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39832 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39833 + * the GNU General Public License for more details.
39834 + *
39835 + * You should have received a copy of the GNU General Public License
39836 + * along with the Ubicom32 Linux Kernel Port.  If not,
39837 + * see <http://www.gnu.org/licenses/>.
39838 + *
39839 + * Ubicom32 implementation derived from (with many thanks):
39840 + *   arch/m68knommu
39841 + *   arch/blackfin
39842 + *   arch/parisc
39843 + */
39844 +#include <linux/device.h>
39845 +#include <linux/gpio.h>
39846 +#include <asm/board.h>
39847 +
39848 +/*
39849 + * ip7500module_init
39850 + *     Called to add the devices which we have on this board
39851 + */
39852 +static int __init ip7500module_init(void)
39853 +{
39854 +       board_init();
39855 +
39856 +       ubi_gpio_init();
39857 +
39858 +       return 0;
39859 +}
39860 +
39861 +arch_initcall(ip7500module_init);
39862 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39863 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c 1970-01-01 02:00:00.000000000 +0200
39864 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c     2009-12-11 11:45:11.000000000 +0200
39865 @@ -0,0 +1,101 @@
39866 +/*
39867 + * arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39868 + *   Support for IP7500 Wireless Speaker board.
39869 + *
39870 + * This file supports the IP7500 Wireless Speaker board:
39871 + *     8007-1210  Rev 1.0
39872 + *
39873 + * (C) Copyright 2009, Ubicom, Inc.
39874 + *
39875 + * This file is part of the Ubicom32 Linux Kernel Port.
39876 + *
39877 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39878 + * it and/or modify it under the terms of the GNU General Public License
39879 + * as published by the Free Software Foundation, either version 2 of the
39880 + * License, or (at your option) any later version.
39881 + *
39882 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39883 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39884 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39885 + * the GNU General Public License for more details.
39886 + *
39887 + * You should have received a copy of the GNU General Public License
39888 + * along with the Ubicom32 Linux Kernel Port.  If not,
39889 + * see <http://www.gnu.org/licenses/>.
39890 + */
39891 +#include <linux/device.h>
39892 +#include <linux/gpio.h>
39893 +#include <asm/board.h>
39894 +
39895 +#include <linux/platform_device.h>
39896 +#include <asm/audio.h>
39897 +#include <linux/i2c.h>
39898 +#include <linux/i2c-gpio.h>
39899 +
39900 +static struct i2c_board_info __initdata ip7500wspkr_i2c_board_info[] = {
39901 +       /*
39902 +        * U6, CS4350 DAC, address 0x4B
39903 +        */
39904 +       {
39905 +               .type           = "cs4350",
39906 +               .addr           = 0x4B,
39907 +       },
39908 +};
39909 +
39910 +/*
39911 + * I2C bus on the board, SDA PE4, SCL PE5
39912 + */
39913 +static struct i2c_gpio_platform_data ip7500wspkr_i2c_data = {
39914 +       .sda_pin                = GPIO_RD_5,
39915 +       .scl_pin                = GPIO_RD_6,
39916 +       .sda_is_open_drain      = 0,
39917 +       .scl_is_open_drain      = 0,
39918 +       .udelay                 = 50,
39919 +};
39920 +
39921 +static struct platform_device ip7500wspkr_i2c_device = {
39922 +       .name   = "i2c-gpio",
39923 +       .id     = 0,
39924 +       .dev    = {
39925 +               .platform_data = &ip7500wspkr_i2c_data,
39926 +       },
39927 +};
39928 +
39929 +static struct platform_device *ip7500wspkr_devices[] __initdata = {
39930 +       &ip7500wspkr_i2c_device,
39931 +};
39932 +
39933 +/*
39934 + * ip7500wspkr_init
39935 + *     Called to add the devices which we have on this board
39936 + */
39937 +static int __init ip7500wspkr_init(void)
39938 +{
39939 +       struct platform_device *audio_dev;
39940 +       struct platform_device *audio_dev2;
39941 +
39942 +       board_init();
39943 +
39944 +       ubi_gpio_init();
39945 +
39946 +       platform_add_devices(ip7500wspkr_devices, ARRAY_SIZE(ip7500wspkr_devices));
39947 +
39948 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39949 +       if (audio_dev) {
39950 +               ip7500wspkr_i2c_board_info[0].platform_data = audio_dev;
39951 +       }
39952 +
39953 +       audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39954 +       if (audio_dev2) {
39955 +               platform_device_register(audio_dev2);
39956 +       }
39957 +
39958 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39959 +       i2c_register_board_info(0, ip7500wspkr_i2c_board_info, ARRAY_SIZE(ip7500wspkr_i2c_board_info));
39960 +
39961 +       printk(KERN_INFO "IP7500 Wireless Speaker Board\n");
39962 +
39963 +       return 0;
39964 +}
39965 +
39966 +arch_initcall(ip7500wspkr_init);
39967 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/Kconfig linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Kconfig
39968 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/Kconfig     1970-01-01 02:00:00.000000000 +0200
39969 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Kconfig 2009-12-11 11:45:11.000000000 +0200
39970 @@ -0,0 +1,205 @@
39971 +config IP7145DPF
39972 +       bool "IP7145DPF"
39973 +       select UBICOM32_V4
39974 +       select UBICOM_INPUT
39975 +       select UBICOM_INPUT_I2C
39976 +       select RTC_CLASS
39977 +       select RTC_DRV_S35390A
39978 +       select I2C
39979 +       select I2C_GPIO
39980 +       select GPIO_PCA953X
39981 +       select FB
39982 +       select FB_UBICOM32
39983 +       select LCD_CLASS_DEVICE
39984 +       select LCD_UBICOM32POWER
39985 +       select BACKLIGHT_LCD_SUPPORT
39986 +       select BACKLIGHT_CLASS_DEVICE
39987 +       select BACKLIGHT_UBICOM32
39988 +       select SND_UBI32
39989 +       select MMC_UBICOM32
39990 +       select MMC
39991 +       select MMC_BLOCK
39992 +       help
39993 +               IP7145 Digital Picture Frame reference design, supports:
39994 +                       8007-0410 v1.0
39995 +
39996 +config IP7160RGW
39997 +       bool "IP7160RGW"
39998 +       select UBICOM32_V4
39999 +       select UBICOM_INPUT
40000 +       select NEW_LEDS
40001 +       select LEDS_CLASS
40002 +       select LEDS_GPIO
40003 +       select SPI
40004 +       select SPI_UBICOM32_GPIO
40005 +       select VLAN_8021Q
40006 +       select UBICOM_SWITCH
40007 +       select UBICOM_SWITCH_BCM539X
40008 +       help
40009 +               Ubicom IP7160 RGW Eval, supports:
40010 +                       8007-0110 v1.0
40011 +                       8007-0111 v1.1
40012 +                       8007-0112 v1.2
40013 +
40014 +config IP7160RGWLCD
40015 +       bool "IP7160RGWLCD"
40016 +       select UBICOM32_V4
40017 +       select UBICOM_INPUT
40018 +       select NEW_LEDS
40019 +       select LEDS_CLASS
40020 +       select LEDS_GPIO
40021 +       select SPI
40022 +       select SPI_UBICOM32_GPIO
40023 +       select VLAN_8021Q
40024 +       select UBICOM_SWITCH
40025 +       select UBICOM_SWITCH_BCM539X
40026 +       select INPUT_TOUCHSCREEN
40027 +       select TOUCHSCREEN_TSC2007
40028 +       select FB
40029 +       select FB_UBICOM32_VIRTUAL
40030 +       select I2C
40031 +       select I2C_GPIO
40032 +       help
40033 +               Ubicom IP7160 RGW Eval, supports:
40034 +                       8007-0112 v1.2 + 8007-1410 v1.0
40035 +
40036 +               With Ubicom LCD Adapter
40037 +                       8007-0920 v2.0
40038 +                       8007-0921 v2.1
40039 +
40040 +
40041 +config IP7160BRINGUP
40042 +       bool "IP7160BRINGUP"
40043 +       select UBICOM32_V4
40044 +       select NEW_LEDS
40045 +       select LEDS_CLASS
40046 +       select LEDS_GPIO
40047 +       help
40048 +               Ubicom IP7160 Bringup, supports:
40049 +                       8007-0010 v1.0
40050 +
40051 +config IP7160DPF
40052 +       bool "IP7160DPF"
40053 +       select UBICOM32_V4
40054 +       select I2C
40055 +       select I2C_GPIO
40056 +       select FB
40057 +       select FB_UBICOM32
40058 +       select BACKLIGHT_LCD_SUPPORT
40059 +       select BACKLIGHT_CLASS_DEVICE
40060 +       select SND_UBI32
40061 +       select SND_UBI32_AUDIO_CS4350
40062 +       select UBICOM_HID
40063 +       help
40064 +               IP7160 Digital Picture Frame board, supports:
40065 +                       8007-0211 Rev 1.1
40066 +
40067 +config IP7500MODULE
40068 +       bool "IP7500MODULE"
40069 +       select UBICOM32_V4
40070 +       help
40071 +               Ubicom IP7500 CPU Module board, supports:
40072 +                       8007-0510  v1.0
40073 +                       8007-0510A v1.0
40074 +
40075 +               Please see ip7500module.c for more details.
40076 +
40077 +config IP7500AV
40078 +       bool "IP7500AV"
40079 +       select UBICOM32_V4
40080 +       select I2C
40081 +       select I2C_GPIO
40082 +       select SND_UBI32
40083 +       select SND_UBI32_AUDIO_CS4384
40084 +       select FB
40085 +       select FB_UBICOM32
40086 +       help
40087 +               Ubicom IP7500 Audio Video board, supports:
40088 +                       8007-0810  v1.0
40089 +
40090 +               With Ubicom IP7500 CPU Module board:
40091 +                       8007-0510  v1.0 -or-
40092 +                       8007-0510A v1.0
40093 +
40094 +               Please see ip7500av.c for more details.
40095 +
40096 +config IP7500MEDIA
40097 +       bool "IP7500MEDIA"
40098 +       select UBICOM32_V4
40099 +       select UBICOM_INPUT_I2C
40100 +       select RTC_CLASS
40101 +       select RTC_DRV_S35390A
40102 +       select I2C
40103 +       select I2C_GPIO
40104 +       select GPIO_PCA953X
40105 +       select FB
40106 +       select FB_UBICOM32
40107 +       select FB_UBICOM32_VIRTUAL
40108 +       select FB_UBICOM32_VIRTUAL_NOAUTO
40109 +       select LCD_CLASS_DEVICE
40110 +       select LCD_UBICOM32POWER
40111 +       select BACKLIGHT_LCD_SUPPORT
40112 +       select BACKLIGHT_CLASS_DEVICE
40113 +       select BACKLIGHT_UBICOM32
40114 +       select INPUT_TOUCHSCREEN
40115 +       select TOUCHSCREEN_TSC2007
40116 +       select SOUND
40117 +       select SND
40118 +       select SND_UBI32
40119 +       select SND_UBI32_AUDIO_CS4350
40120 +       select MMC_UBICOM32
40121 +       select MMC
40122 +       select MMC_BLOCK
40123 +       help
40124 +               IP7500 Media Board w/ IP7500 CPU Module board, supports:
40125 +                       8007-0610 v1.0 w/ 8007-0510 v1.0
40126 +                       8007-0610 v1.0 w/ 8007-0510 v1.0 NOPHY
40127 +                       8007-0610 v1.0 w/ 8007-0511 v1.1 NOPHY
40128 +
40129 +               Also supports optional LCD Adapter board:
40130 +                       8006-0920 v2.0
40131 +                       8006-0921 v2.1
40132 +
40133 +               Please see ip7500media.c for more details.
40134 +
40135 +config IP7500WSPKR
40136 +       bool "IP7500WSPKR"
40137 +       select UBICOM32_V4
40138 +       select I2C
40139 +       select I2C_GPIO
40140 +       select SOUND
40141 +       select SND
40142 +       select SND_UBI32
40143 +       select SND_UBI32_AUDIO_CS4350
40144 +       help
40145 +               IP7500 Wireless Speaker Board, supports:
40146 +                       8007-1210 v1.0
40147 +
40148 +               Please see ip7500wspkr.c for more details.
40149 +
40150 +config IP7500IAP
40151 +       bool "IP7500IAP"
40152 +       select UBICOM32_V4
40153 +       select I2C
40154 +       select I2C_GPIO
40155 +       select FB
40156 +       select FB_UBICOM32_VIRTUAL
40157 +       select SOUND
40158 +       select SND
40159 +       select SND_UBI32
40160 +       select SND_UBI32_AUDIO_CS4350
40161 +       select RTC_CLASS
40162 +       select RTC_DRV_S35390A
40163 +       select INPUT_TOUCHSCREEN
40164 +       select TOUCHSCREEN_TSC2007
40165 +       select BACKLIGHT_LCD_SUPPORT
40166 +       select BACKLIGHT_CLASS_DEVICE
40167 +       select BACKLIGHT_UBICOM32
40168 +       help
40169 +               IP7500 Internet Audio Player, supports:
40170 +                       8007-1110 v1.0
40171 +
40172 +               Please see ip7500iap.c for more details.
40173 +
40174 +
40175 +               Please see ip7500media.c for more details.
40176 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Makefile
40177 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/Makefile    1970-01-01 02:00:00.000000000 +0200
40178 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Makefile        2009-12-11 11:45:11.000000000 +0200
40179 @@ -0,0 +1,38 @@
40180 +#
40181 +# arch/ubicom32/mach-ip7k/Makefile
40182 +#      Makefile for ip7k based boards.
40183 +#
40184 +# (C) Copyright 2009, Ubicom, Inc.
40185 +#
40186 +# This file is part of the Ubicom32 Linux Kernel Port.
40187 +#
40188 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40189 +# it and/or modify it under the terms of the GNU General Public License
40190 +# as published by the Free Software Foundation, either version 2 of the
40191 +# License, or (at your option) any later version.
40192 +#
40193 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40194 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40195 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40196 +# the GNU General Public License for more details.
40197 +#
40198 +# You should have received a copy of the GNU General Public License
40199 +# along with the Ubicom32 Linux Kernel Port.  If not,
40200 +# see <http://www.gnu.org/licenses/>.
40201 +#
40202 +# Ubicom32 implementation derived from (with many thanks):
40203 +#   arch/m68knommu
40204 +#   arch/blackfin
40205 +#   arch/parisc
40206 +#
40207 +
40208 +obj-$(CONFIG_IP7145DPF)                += board-ip7145dpf.o
40209 +obj-$(CONFIG_IP7160RGW)                += board-ip7160rgw.o
40210 +obj-$(CONFIG_IP7160RGWLCD)     += board-ip7160rgw.o
40211 +obj-$(CONFIG_IP7160BRINGUP)    += board-ip7160bringup.o
40212 +obj-$(CONFIG_IP7160DPF)                += board-ip7160dpf.o
40213 +obj-$(CONFIG_IP7500MODULE)     += board-ip7500module.o
40214 +obj-$(CONFIG_IP7500MEDIA)      += board-ip7500media.o
40215 +obj-$(CONFIG_IP7500AV)         += board-ip7500av.o
40216 +obj-$(CONFIG_IP7500WSPKR)      += board-ip7500wspkr.o
40217 +obj-$(CONFIG_IP7500IAP)                += board-ip7500iap.o
40218 diff -ruN linux-2.6.30.10/arch/ubicom32/Makefile linux-2.6.30.10-ubi/arch/ubicom32/Makefile
40219 --- linux-2.6.30.10/arch/ubicom32/Makefile      1970-01-01 02:00:00.000000000 +0200
40220 +++ linux-2.6.30.10-ubi/arch/ubicom32/Makefile  2009-12-11 11:45:11.000000000 +0200
40221 @@ -0,0 +1,104 @@
40222 +#
40223 +# arch/ubicom32/Makefile
40224 +#      <TODO: Replace with short file description>
40225 +#
40226 +# (C) Copyright 2009, Ubicom, Inc.
40227 +#
40228 +# This file is part of the Ubicom32 Linux Kernel Port.
40229 +#
40230 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40231 +# it and/or modify it under the terms of the GNU General Public License
40232 +# as published by the Free Software Foundation, either version 2 of the
40233 +# License, or (at your option) any later version.
40234 +#
40235 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40236 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40237 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40238 +# the GNU General Public License for more details.
40239 +#
40240 +# You should have received a copy of the GNU General Public License
40241 +# along with the Ubicom32 Linux Kernel Port.  If not,
40242 +# see <http://www.gnu.org/licenses/>.
40243 +#
40244 +# Ubicom32 implementation derived from (with many thanks):
40245 +#   arch/m68knommu
40246 +#   arch/blackfin
40247 +#   arch/parisc
40248 +#
40249 +
40250 +KBUILD_DEFCONFIG :=
40251 +
40252 +# setup the machine name and machine dependent settings
40253 +machine-$(CONFIG_UBICOM32_V3)  := ip5k
40254 +machine-$(CONFIG_UBICOM32_V4)  := ip7k
40255 +MACHINE := $(machine-y)
40256 +export MACHINE
40257 +
40258 +model-$(CONFIG_RAMKERNEL)      := ram
40259 +model-$(CONFIG_ROMKERNEL)      := rom
40260 +MODEL := $(model-y)
40261 +export MODEL
40262 +
40263 +CPUCLASS := $(cpuclass-y)
40264 +
40265 +export CPUCLASS
40266 +
40267 +#
40268 +# We want the core kernel built using the fastcall ABI but modules need
40269 +# to be built using the slower calling convention because they could be
40270 +# loaded out of range for fast calls.
40271 +#
40272 +CFLAGS_KERNEL    += -mfastcall
40273 +CFLAGS_MODULE    += -mno-fastcall
40274 +
40275 +#
40276 +# Some CFLAG additions based on specific CPU type.
40277 +#
40278 +cflags-$(CONFIG_UBICOM32_V3)           := -march=ubicom32v3 -DIP5000
40279 +cflags-$(CONFIG_UBICOM32_V4)           := -march=ubicom32v4 -DIP7000
40280 +
40281 +ldflags-$(CONFIG_LINKER_RELAXATION)    := --relax
40282 +LDFLAGS_vmlinux := $(ldflags-y)
40283 +
40284 +GCCLIBDIR := $(dir $(shell $(CC) $(cflags-y) -print-libgcc-file-name))
40285 +GCC_LIBS := $(GCCLIBDIR)/libgcc.a
40286 +
40287 +KBUILD_CFLAGS += $(cflags-y) -ffunction-sections
40288 +KBUILD_AFLAGS += $(cflags-y)
40289 +
40290 +KBUILD_CFLAGS += -D__linux__ -Dlinux
40291 +KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
40292 +
40293 +# include any machine specific directory
40294 +ifneq ($(machine-y),)
40295 +core-y += arch/$(ARCH)/mach-$(MACHINE)/
40296 +endif
40297 +
40298 +head-y := arch/$(ARCH)/kernel/head.o
40299 +
40300 +core-y += arch/$(ARCH)/kernel/ \
40301 +          arch/$(ARCH)/mm/ \
40302 +          arch/$(ARCH)/crypto/ \
40303 +          arch/$(ARCH)/mach-common/
40304 +
40305 +drivers-$(CONFIG_OPROFILE)     += arch/ubicom32/oprofile/
40306 +
40307 +libs-y += arch/$(ARCH)/lib/
40308 +libs-y += $(GCC_LIBS)
40309 +
40310 +archclean:
40311 +
40312 +# make sure developer has selected a valid board
40313 +ifeq ($(CONFIG_NOBOARD),y)
40314 +# $(error have to select a valid board file $(CONFIG_NOBOARD), please run kernel config again)
40315 +_all: config_board_error
40316 +endif
40317 +
40318 +config_board_error:
40319 +       @echo "*************************************************"
40320 +       @echo "You have not selected a proper board."
40321 +       @echo "Please run menuconfig (or config) against your"
40322 +       @echo "kernel and choose your board under Processor"
40323 +       @echo "options"
40324 +       @echo "*************************************************"
40325 +       @exit 1
40326 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/fault.c linux-2.6.30.10-ubi/arch/ubicom32/mm/fault.c
40327 --- linux-2.6.30.10/arch/ubicom32/mm/fault.c    1970-01-01 02:00:00.000000000 +0200
40328 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/fault.c        2009-12-11 11:45:11.000000000 +0200
40329 @@ -0,0 +1,80 @@
40330 +/*
40331 + * arch/ubicom32/mm/fault.c
40332 + *   Ubicom32 architecture page fault implementation.
40333 + *
40334 + * (C) Copyright 2009, Ubicom, Inc.
40335 + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
40336 + *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com)
40337 + *
40338 + *  Based on:
40339 + *
40340 + *  linux/arch/m68k/mm/fault.c
40341 + *
40342 + *  Copyright (C) 1995  Hamish Macdonald
40343 + *
40344 + * This file is part of the Ubicom32 Linux Kernel Port.
40345 + *
40346 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40347 + * it and/or modify it under the terms of the GNU General Public License
40348 + * as published by the Free Software Foundation, either version 2 of the
40349 + * License, or (at your option) any later version.
40350 + *
40351 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40352 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40353 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40354 + * the GNU General Public License for more details.
40355 + *
40356 + * You should have received a copy of the GNU General Public License
40357 + * along with the Ubicom32 Linux Kernel Port.  If not,
40358 + * see <http://www.gnu.org/licenses/>.
40359 + *
40360 + * Ubicom32 implementation derived from (with many thanks):
40361 + *   arch/m68knommu
40362 + *   arch/blackfin
40363 + *   arch/parisc
40364 + */
40365 +
40366 +#include <linux/module.h>
40367 +#include <linux/mman.h>
40368 +#include <linux/mm.h>
40369 +#include <linux/kernel.h>
40370 +#include <linux/ptrace.h>
40371 +
40372 +#include <asm/system.h>
40373 +#include <asm/pgtable.h>
40374 +
40375 +extern void die_if_kernel(char *, struct pt_regs *, long);
40376 +
40377 +/*
40378 + * This routine handles page faults.  It determines the problem, and
40379 + * then passes it off to one of the appropriate routines.
40380 + *
40381 + * error_code:
40382 + *     bit 0 == 0 means no page found, 1 means protection fault
40383 + *     bit 1 == 0 means read, 1 means write
40384 + *
40385 + * If this routine detects a bad access, it returns 1, otherwise it
40386 + * returns 0.
40387 + */
40388 +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
40389 +                             unsigned long error_code)
40390 +{
40391 +#ifdef DEBUG
40392 +       printk (KERN_DEBUG "regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
40393 +               regs->sr, regs->pc, address, error_code);
40394 +#endif
40395 +
40396 +       /*
40397 +        * Oops. The kernel tried to access some bad page. We'll have to
40398 +        * terminate things with extreme prejudice.
40399 +        */
40400 +       if ((unsigned long) address < PAGE_SIZE) {
40401 +               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
40402 +       } else
40403 +               printk(KERN_ALERT "Unable to handle kernel access");
40404 +       printk(KERN_ALERT " at virtual address %08lx\n",address);
40405 +       die_if_kernel("Oops", regs, error_code);
40406 +       do_exit(SIGKILL);
40407 +
40408 +       return 1;
40409 +}
40410 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/init.c linux-2.6.30.10-ubi/arch/ubicom32/mm/init.c
40411 --- linux-2.6.30.10/arch/ubicom32/mm/init.c     1970-01-01 02:00:00.000000000 +0200
40412 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/init.c 2009-12-11 11:45:11.000000000 +0200
40413 @@ -0,0 +1,262 @@
40414 +/*
40415 + * arch/ubicom32/mm/init.c
40416 + *   Ubicom32 architecture virtual memory initialization.
40417 + *
40418 + * (C) Copyright 2009, Ubicom, Inc.
40419 + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
40420 + *                      Kenneth Albanowski <kjahds@kjahds.com>,
40421 + *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com)
40422 + *
40423 + *  Based on:
40424 + *
40425 + *  linux/arch/m68k/mm/init.c
40426 + *
40427 + *  Copyright (C) 1995  Hamish Macdonald
40428 + *
40429 + *  JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
40430 + *  DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
40431 + *
40432 + * This file is part of the Ubicom32 Linux Kernel Port.
40433 + *
40434 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40435 + * it and/or modify it under the terms of the GNU General Public License
40436 + * as published by the Free Software Foundation, either version 2 of the
40437 + * License, or (at your option) any later version.
40438 + *
40439 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40440 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40441 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40442 + * the GNU General Public License for more details.
40443 + *
40444 + * You should have received a copy of the GNU General Public License
40445 + * along with the Ubicom32 Linux Kernel Port.  If not,
40446 + * see <http://www.gnu.org/licenses/>.
40447 + *
40448 + * Ubicom32 implementation derived from (with many thanks):
40449 + *   arch/m68knommu
40450 + *   arch/blackfin
40451 + *   arch/parisc
40452 + */
40453 +
40454 +#include <linux/signal.h>
40455 +#include <linux/sched.h>
40456 +#include <linux/kernel.h>
40457 +#include <linux/errno.h>
40458 +#include <linux/string.h>
40459 +#include <linux/types.h>
40460 +#include <linux/ptrace.h>
40461 +#include <linux/mman.h>
40462 +#include <linux/mm.h>
40463 +#include <linux/swap.h>
40464 +#include <linux/init.h>
40465 +#include <linux/highmem.h>
40466 +#include <linux/pagemap.h>
40467 +#include <linux/bootmem.h>
40468 +#include <linux/slab.h>
40469 +
40470 +#include <asm/setup.h>
40471 +#include <asm/segment.h>
40472 +#include <asm/page.h>
40473 +#include <asm/pgtable.h>
40474 +#include <asm/system.h>
40475 +#include <asm/machdep.h>
40476 +#include <asm/ocm-alloc.h>
40477 +#include <asm/processor.h>
40478 +
40479 +#undef DEBUG
40480 +
40481 +extern void die_if_kernel(char *,struct pt_regs *,long);
40482 +extern void free_initmem(void);
40483 +
40484 +/*
40485 + * BAD_PAGE is the page that is used for page faults when linux
40486 + * is out-of-memory. Older versions of linux just did a
40487 + * do_exit(), but using this instead means there is less risk
40488 + * for a process dying in kernel mode, possibly leaving a inode
40489 + * unused etc..
40490 + *
40491 + * BAD_PAGETABLE is the accompanying page-table: it is initialized
40492 + * to point to BAD_PAGE entries.
40493 + *
40494 + * ZERO_PAGE is a special page that is used for zero-initialized
40495 + * data and COW.
40496 + */
40497 +static unsigned long empty_bad_page_table;
40498 +
40499 +static unsigned long empty_bad_page;
40500 +
40501 +unsigned long empty_zero_page;
40502 +
40503 +void show_mem(void)
40504 +{
40505 +    unsigned long i;
40506 +    int free = 0, total = 0, reserved = 0, shared = 0;
40507 +    int cached = 0;
40508 +
40509 +    printk(KERN_INFO "\nMem-info:\n");
40510 +    show_free_areas();
40511 +    i = max_mapnr;
40512 +    while (i-- > 0) {
40513 +       total++;
40514 +       if (PageReserved(mem_map+i))
40515 +           reserved++;
40516 +       else if (PageSwapCache(mem_map+i))
40517 +           cached++;
40518 +       else if (!page_count(mem_map+i))
40519 +           free++;
40520 +       else
40521 +           shared += page_count(mem_map+i) - 1;
40522 +    }
40523 +    printk(KERN_INFO "%d pages of RAM\n",total);
40524 +    printk(KERN_INFO "%d free pages\n",free);
40525 +    printk(KERN_INFO "%d reserved pages\n",reserved);
40526 +    printk(KERN_INFO "%d pages shared\n",shared);
40527 +    printk(KERN_INFO "%d pages swap cached\n",cached);
40528 +}
40529 +
40530 +extern unsigned long memory_start;
40531 +extern unsigned long memory_end;
40532 +extern char __ocm_free_begin;
40533 +extern char __ocm_free_end;
40534 +
40535 +/*
40536 + * paging_init() continues the virtual memory environment setup which
40537 + * was begun by the code in arch/head.S.
40538 + * The parameters are pointers to where to stick the starting and ending
40539 + * addresses of available kernel virtual memory.
40540 + */
40541 +void __init paging_init(void)
40542 +{
40543 +       /*
40544 +        * Make sure start_mem is page aligned, otherwise bootmem and
40545 +        * page_alloc get different views of the world.
40546 +        */
40547 +#ifdef DEBUG
40548 +       unsigned long start_mem = PAGE_ALIGN(memory_start);
40549 +#endif
40550 +       unsigned long end_mem   = memory_end & PAGE_MASK;
40551 +
40552 +#ifdef DEBUG
40553 +       printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
40554 +               start_mem, end_mem);
40555 +#endif
40556 +
40557 +       /*
40558 +        * Initialize the bad page table and bad page to point
40559 +        * to a couple of allocated pages.
40560 +        */
40561 +       empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40562 +       empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40563 +       empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40564 +       memset((void *)empty_zero_page, 0, PAGE_SIZE);
40565 +
40566 +       /*
40567 +        * TODO: enable setting up for user memory management interface.
40568 +        */
40569 +
40570 +#ifdef DEBUG
40571 +       printk (KERN_DEBUG "before free_area_init\n");
40572 +
40573 +       printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
40574 +               start_mem, end_mem);
40575 +#endif
40576 +
40577 +       {
40578 +               unsigned long zones_size[MAX_NR_ZONES] = {0, };
40579 +#ifdef CONFIG_ZONE_DMA
40580 +               zones_size[ZONE_DMA] = OCMSIZE >> PAGE_SHIFT;
40581 +#endif
40582 +               zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
40583 +#ifdef CONFIG_HIGHMEM
40584 +               zones_size[ZONE_HIGHMEM] = 0;
40585 +#endif
40586 +               free_area_init(zones_size);
40587 +       }
40588 +}
40589 +
40590 +void __init mem_init(void)
40591 +{
40592 +       int codek = 0, datak = 0, initk = 0;
40593 +       unsigned long tmp, ram_start, ram_end, len;
40594 +       extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
40595 +
40596 +       unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
40597 +       unsigned long end_mem   = memory_end; /* DAVIDM - this must not include kernel stack at top */
40598 +       processor_dram(&ram_start, &ram_end);
40599 +       len = (ram_end - ram_start) + OCMSIZE;
40600 +#ifdef DEBUG
40601 +       printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
40602 +#endif
40603 +
40604 +       end_mem &= PAGE_MASK;
40605 +       high_memory = (void *) end_mem;
40606 +
40607 +       start_mem = PAGE_ALIGN(start_mem);
40608 +       max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
40609 +
40610 +       /* this will put all memory onto the freelists */
40611 +#ifdef CONFIG_ZONE_DMA
40612 +       {
40613 +               unsigned long ocm_free_begin = (unsigned long)&__ocm_free_begin;
40614 +               unsigned long ocm_free_end = (unsigned long)&__ocm_free_end;
40615 +               unsigned long zone_dma_begin = (ocm_free_begin + PAGE_SIZE - 1) & PAGE_MASK;
40616 +               unsigned long zone_dma_end = ocm_free_end & PAGE_MASK;
40617 +               if (zone_dma_end > zone_dma_begin)
40618 +                       free_bootmem(zone_dma_begin, zone_dma_end-zone_dma_begin);
40619 +       }
40620 +#endif
40621 +       totalram_pages = free_all_bootmem();
40622 +
40623 +       codek = (&_etext - &_stext) >> 10;
40624 +       datak = (&_ebss - &_sdata) >> 10;
40625 +       initk = (&__init_begin - &__init_end) >> 10;
40626 +
40627 +       tmp = nr_free_pages() << PAGE_SHIFT;
40628 +       printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
40629 +              tmp >> 10,
40630 +              len >> 10,
40631 +              codek,
40632 +              datak
40633 +              );
40634 +
40635 +}
40636 +
40637 +#ifdef CONFIG_BLK_DEV_INITRD
40638 +void free_initrd_mem(unsigned long start, unsigned long end)
40639 +{
40640 +       int pages = 0;
40641 +       for (; start < end; start += PAGE_SIZE) {
40642 +               ClearPageReserved(virt_to_page(start));
40643 +               init_page_count(virt_to_page(start));
40644 +               free_page(start);
40645 +               totalram_pages++;
40646 +               pages++;
40647 +       }
40648 +       printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
40649 +}
40650 +#endif
40651 +
40652 +void
40653 +free_initmem()
40654 +{
40655 +#ifdef CONFIG_RAMKERNEL
40656 +       unsigned long addr;
40657 +       extern char __init_begin, __init_end;
40658 +       /*
40659 +        * The following code should be cool even if these sections
40660 +        * are not page aligned.
40661 +        */
40662 +       addr = PAGE_ALIGN((unsigned long)(&__init_begin));
40663 +       /* next to check that the page we free is not a partial page */
40664 +       for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
40665 +               ClearPageReserved(virt_to_page(addr));
40666 +               init_page_count(virt_to_page(addr));
40667 +               free_page(addr);
40668 +               totalram_pages++;
40669 +       }
40670 +       printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
40671 +                       (addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
40672 +                       (int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
40673 +                       (int)(addr - PAGE_SIZE));
40674 +#endif
40675 +}
40676 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/kmap.c linux-2.6.30.10-ubi/arch/ubicom32/mm/kmap.c
40677 --- linux-2.6.30.10/arch/ubicom32/mm/kmap.c     1970-01-01 02:00:00.000000000 +0200
40678 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/kmap.c 2009-12-11 11:45:11.000000000 +0200
40679 @@ -0,0 +1,79 @@
40680 +/*
40681 + * arch/ubicom32/mm/kmap.c
40682 + *   Ubicom32 architecture non-mmu ioremap and friends implementation.
40683 + *
40684 + * (C) Copyright 2009, Ubicom, Inc.
40685 + * Copyright (C) 2000 Lineo, <davidm@snapgear.com>
40686 + * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
40687 + *
40688 + * This file is part of the Ubicom32 Linux Kernel Port.
40689 + *
40690 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40691 + * it and/or modify it under the terms of the GNU General Public License
40692 + * as published by the Free Software Foundation, either version 2 of the
40693 + * License, or (at your option) any later version.
40694 + *
40695 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40696 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40697 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40698 + * the GNU General Public License for more details.
40699 + *
40700 + * You should have received a copy of the GNU General Public License
40701 + * along with the Ubicom32 Linux Kernel Port.  If not,
40702 + * see <http://www.gnu.org/licenses/>.
40703 + *
40704 + * Ubicom32 implementation derived from (with many thanks):
40705 + *   arch/m68knommu
40706 + *   arch/blackfin
40707 + *   arch/parisc
40708 + */
40709 +
40710 +#include <linux/module.h>
40711 +#include <linux/mm.h>
40712 +#include <linux/kernel.h>
40713 +#include <linux/string.h>
40714 +#include <linux/types.h>
40715 +#include <linux/slab.h>
40716 +#include <linux/vmalloc.h>
40717 +
40718 +#include <asm/setup.h>
40719 +#include <asm/segment.h>
40720 +#include <asm/page.h>
40721 +#include <asm/pgalloc.h>
40722 +#include <asm/io.h>
40723 +#include <asm/system.h>
40724 +
40725 +#undef DEBUG
40726 +
40727 +/*
40728 + * Map some physical address range into the kernel address space.
40729 + */
40730 +void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
40731 +{
40732 +       return (void *)physaddr;
40733 +}
40734 +
40735 +/*
40736 + * Unmap a ioremap()ed region again.
40737 + */
40738 +void iounmap(void *addr)
40739 +{
40740 +}
40741 +
40742 +/*
40743 + * __iounmap unmaps nearly everything, so be careful
40744 + * it doesn't free currently pointer/page tables anymore but it
40745 + * wans't used anyway and might be added later.
40746 + */
40747 +void __iounmap(void *addr, unsigned long size)
40748 +{
40749 +}
40750 +
40751 +/*
40752 + * Set new cache mode for some kernel address space.
40753 + * The caller must push data for that range itself, if such data may already
40754 + * be in the cache.
40755 + */
40756 +void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
40757 +{
40758 +}
40759 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mm/Makefile
40760 --- linux-2.6.30.10/arch/ubicom32/mm/Makefile   1970-01-01 02:00:00.000000000 +0200
40761 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/Makefile       2009-12-11 11:45:11.000000000 +0200
40762 @@ -0,0 +1,32 @@
40763 +#
40764 +# arch/ubicom32/mm/Makefile
40765 +#      <TODO: Replace with short file description>
40766 +#
40767 +# (C) Copyright 2009, Ubicom, Inc.
40768 +#
40769 +# This file is part of the Ubicom32 Linux Kernel Port.
40770 +#
40771 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40772 +# it and/or modify it under the terms of the GNU General Public License
40773 +# as published by the Free Software Foundation, either version 2 of the
40774 +# License, or (at your option) any later version.
40775 +#
40776 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40777 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40778 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40779 +# the GNU General Public License for more details.
40780 +#
40781 +# You should have received a copy of the GNU General Public License
40782 +# along with the Ubicom32 Linux Kernel Port.  If not,
40783 +# see <http://www.gnu.org/licenses/>.
40784 +#
40785 +# Ubicom32 implementation derived from (with many thanks):
40786 +#   arch/m68knommu
40787 +#   arch/blackfin
40788 +#   arch/parisc
40789 +#
40790 +#
40791 +# Makefile for the linux m68knommu specific parts of the memory manager.
40792 +#
40793 +
40794 +obj-y += init.o fault.o memory.o kmap.o ocm-alloc.o
40795 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/memory.c linux-2.6.30.10-ubi/arch/ubicom32/mm/memory.c
40796 --- linux-2.6.30.10/arch/ubicom32/mm/memory.c   1970-01-01 02:00:00.000000000 +0200
40797 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/memory.c       2009-12-11 11:45:11.000000000 +0200
40798 @@ -0,0 +1,58 @@
40799 +/*
40800 + * arch/ubicom32/mm/memory.c
40801 + *   Ubicom32 architecture kernel_map() implementation.
40802 + *
40803 + * (C) Copyright 2009, Ubicom, Inc.
40804 + *  Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
40805 + *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
40806 + *
40807 + *  Based on:
40808 + *
40809 + *  linux/arch/m68k/mm/memory.c
40810 + *
40811 + *  Copyright (C) 1995  Hamish Macdonald
40812 + *
40813 + * This file is part of the Ubicom32 Linux Kernel Port.
40814 + *
40815 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40816 + * it and/or modify it under the terms of the GNU General Public License
40817 + * as published by the Free Software Foundation, either version 2 of the
40818 + * License, or (at your option) any later version.
40819 + *
40820 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40821 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40822 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40823 + * the GNU General Public License for more details.
40824 + *
40825 + * You should have received a copy of the GNU General Public License
40826 + * along with the Ubicom32 Linux Kernel Port.  If not,
40827 + * see <http://www.gnu.org/licenses/>.
40828 + *
40829 + * Ubicom32 implementation derived from (with many thanks):
40830 + *   arch/m68knommu
40831 + *   arch/blackfin
40832 + *   arch/parisc
40833 + */
40834 +
40835 +#include <linux/module.h>
40836 +#include <linux/mm.h>
40837 +#include <linux/kernel.h>
40838 +#include <linux/string.h>
40839 +#include <linux/types.h>
40840 +#include <linux/slab.h>
40841 +
40842 +#include <asm/segment.h>
40843 +#include <asm/page.h>
40844 +#include <asm/pgtable.h>
40845 +#include <asm/system.h>
40846 +
40847 +/*
40848 + * Map some physical address range into the kernel address space.
40849 + * The code is copied and adapted from map_chunk().
40850 + */
40851 +
40852 +unsigned long kernel_map(unsigned long paddr, unsigned long size,
40853 +                        int nocacheflag, unsigned long *memavailp )
40854 +{
40855 +       return paddr;
40856 +}
40857 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/ocm-alloc.c linux-2.6.30.10-ubi/arch/ubicom32/mm/ocm-alloc.c
40858 --- linux-2.6.30.10/arch/ubicom32/mm/ocm-alloc.c        1970-01-01 02:00:00.000000000 +0200
40859 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/ocm-alloc.c    2009-12-11 11:45:11.000000000 +0200
40860 @@ -0,0 +1,487 @@
40861 +/*
40862 + * arch/ubicom32/mm/ocm-alloc.c
40863 + *     OCM allocator for Uibcom32 On-Chip memory
40864 + *
40865 + * (C) Copyright 2009, Ubicom, Inc.
40866 + *  Copyright 2004-2008 Analog Devices Inc.
40867 + *
40868 + *  Based on:
40869 + *
40870 + *  arch/blackfin/mm/sram-alloc.c
40871 + *
40872 + *
40873 + * This file is part of the Ubicom32 Linux Kernel Port.
40874 + *
40875 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40876 + * it and/or modify it under the terms of the GNU General Public License
40877 + * as published by the Free Software Foundation, either version 2 of the
40878 + * License, or (at your option) any later version.
40879 + *
40880 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40881 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40882 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40883 + * the GNU General Public License for more details.
40884 + *
40885 + * You should have received a copy of the GNU General Public License
40886 + * along with the Ubicom32 Linux Kernel Port.  If not,
40887 + * see <http://www.gnu.org/licenses/>.
40888 + *
40889 + * Ubicom32 implementation derived from (with many thanks):
40890 + *   arch/m68knommu
40891 + *   arch/blackfin
40892 + *   arch/parisc
40893 + */
40894 +
40895 +#include <linux/module.h>
40896 +#include <linux/kernel.h>
40897 +#include <linux/types.h>
40898 +#include <linux/miscdevice.h>
40899 +#include <linux/ioport.h>
40900 +#include <linux/fcntl.h>
40901 +#include <linux/init.h>
40902 +#include <linux/poll.h>
40903 +#include <linux/proc_fs.h>
40904 +#include <linux/mutex.h>
40905 +#include <linux/rtc.h>
40906 +#include <asm/ocm-alloc.h>
40907 +
40908 +#if 0
40909 +#define DEBUGP printk
40910 +#else
40911 +#define DEBUGP(fmt, a...)
40912 +#endif
40913 +/*
40914 + * the data structure for OCM heap pieces
40915 + */
40916 +struct ocm_piece {
40917 +       void *paddr;
40918 +       int size;
40919 +       pid_t pid;
40920 +       struct ocm_piece *next;
40921 +};
40922 +
40923 +/*
40924 + * struct ocm_heap
40925 + */
40926 +struct ocm_heap {
40927 +       struct ocm_piece free_head;
40928 +       struct ocm_piece used_head;
40929 +       struct mutex lock;
40930 +};
40931 +
40932 +static struct ocm_heap ocm_inst_heap;
40933 +int ubi32_ocm_skbuf_max = 21, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
40934 +
40935 +/*
40936 + * OCM area for storing code
40937 + */
40938 +extern asmlinkage void *__ocm_free_begin;
40939 +extern asmlinkage void *__ocm_free_end;
40940 +extern asmlinkage void *__ocm_inst_heap_begin;
40941 +extern asmlinkage void *__ocm_inst_heap_end;
40942 +#define OCM_INST_HEAP_BEGIN ((unsigned int)&__ocm_inst_heap_begin)
40943 +#define OCM_INST_HEAP_END ((unsigned int)&__ocm_inst_heap_end)
40944 +#define OCM_INST_HEAP_LENGTH (OCM_INST_HEAP_END - OCM_INST_HEAP_BEGIN)
40945 +
40946 +static struct kmem_cache *ocm_piece_cache;
40947 +
40948 +/*
40949 + * _ocm_heap_init()
40950 + */
40951 +static int __init _ocm_heap_init(struct ocm_heap *ocmh,
40952 +                                 unsigned int start,
40953 +                                 unsigned int size)
40954 +{
40955 +       ocmh->free_head.next = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
40956 +
40957 +       if (!ocmh->free_head.next)
40958 +               return -1;
40959 +
40960 +       ocmh->free_head.next->paddr = (void *)start;
40961 +       ocmh->free_head.next->size = size;
40962 +       ocmh->free_head.next->pid = 0;
40963 +       ocmh->free_head.next->next = 0;
40964 +
40965 +       ocmh->used_head.next = NULL;
40966 +
40967 +       /* mutex initialize */
40968 +       mutex_init(&ocmh->lock);
40969 +
40970 +       return 0;
40971 +}
40972 +
40973 +/*
40974 + * _ocm_alloc_init()
40975 + *
40976 + * starts the ocm heap(s)
40977 + */
40978 +static int __init _ocm_alloc_init(void)
40979 +{
40980 +       if (OCM_INST_HEAP_LENGTH) {
40981 +               ocm_piece_cache = kmem_cache_create("ocm_piece_cache",
40982 +                                                   sizeof(struct ocm_piece),
40983 +                                                   0, SLAB_PANIC, NULL);
40984 +
40985 +               if (_ocm_heap_init(&ocm_inst_heap,
40986 +                                  OCM_INST_HEAP_BEGIN,
40987 +                                  OCM_INST_HEAP_LENGTH) == 0)
40988 +                       printk(KERN_INFO "OCM Instruction Heap %d KB\n",
40989 +                              OCM_INST_HEAP_LENGTH >> 10);
40990 +               else
40991 +                       printk(KERN_INFO "Failed to initialize OCM "
40992 +                              "Instruction Heap\n");
40993 +
40994 +       } else
40995 +               printk(KERN_INFO "No space available for OCM "
40996 +                      "Instruction Heap\n");
40997 +
40998 +       return 0;
40999 +}
41000 +pure_initcall(_ocm_alloc_init);
41001 +
41002 +/*
41003 + * _ocm_alloc()
41004 + *     generic alloc a block in the ocm heap, if successful
41005 + *     returns the pointer.
41006 + */
41007 +static void *_ocm_alloc(size_t size, pid_t pid, struct ocm_heap *ocmheap)
41008 +{
41009 +       struct ocm_piece *pslot, *plast, *pavail;
41010 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
41011 +       struct ocm_piece *pused_head = &ocmheap->used_head;
41012 +
41013 +       if (size <= 0 || !pfree_head || !pused_head)
41014 +               return NULL;
41015 +
41016 +       /* Align the size */
41017 +       size = (size + 3) & ~3;
41018 +
41019 +       pslot = pfree_head->next;
41020 +       plast = pfree_head;
41021 +
41022 +       /*
41023 +        * search an available piece slot
41024 +        */
41025 +       while (pslot != NULL && size > pslot->size) {
41026 +               plast = pslot;
41027 +               pslot = pslot->next;
41028 +       }
41029 +
41030 +       if (!pslot)
41031 +               return NULL;
41032 +
41033 +       if (pslot->size == size) {
41034 +               /*
41035 +                * Unlink this block from the list
41036 +                */
41037 +               plast->next = pslot->next;
41038 +               pavail = pslot;
41039 +       } else {
41040 +               /*
41041 +                * Split this block in two.
41042 +                */
41043 +               pavail = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
41044 +
41045 +               if (!pavail)
41046 +                       return NULL;
41047 +
41048 +               pavail->paddr = pslot->paddr;
41049 +               pavail->size = size;
41050 +               pslot->paddr += size;
41051 +               pslot->size -= size;
41052 +       }
41053 +
41054 +       pavail->pid = pid;
41055 +
41056 +       pslot = pused_head->next;
41057 +       plast = pused_head;
41058 +
41059 +       /*
41060 +        * insert new piece into used piece list !!!
41061 +        */
41062 +       while (pslot != NULL && pavail->paddr < pslot->paddr) {
41063 +               plast = pslot;
41064 +               pslot = pslot->next;
41065 +       }
41066 +
41067 +       pavail->next = pslot;
41068 +       plast->next = pavail;
41069 +
41070 +       DEBUGP("_ocm_alloc %d bytes at %p from in %p",
41071 +              size, pavail->paddr, ocmheap);
41072 +
41073 +       return pavail->paddr;
41074 +}
41075 +
41076 +#if 0
41077 +/* Allocate the largest available block.  */
41078 +static void *_ocm_alloc_max(struct ocm_heap *ocmheap,
41079 +                            unsigned long *psize)
41080 +{
41081 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
41082 +       struct ocm_piece *pslot, *pmax;
41083 +
41084 +       pmax = pslot = pfree_head->next;
41085 +
41086 +       /* search an available piece slot */
41087 +       while (pslot != NULL) {
41088 +               if (pslot->size > pmax->size)
41089 +                       pmax = pslot;
41090 +               pslot = pslot->next;
41091 +       }
41092 +
41093 +       if (!pmax)
41094 +               return NULL;
41095 +
41096 +       *psize = pmax->size;
41097 +
41098 +       return _ocm_alloc(*psize, ocmheap);
41099 +}
41100 +#endif
41101 +
41102 +/*
41103 + * _ocm_free()
41104 + *     generic free a block in the ocm heap, if successful
41105 + */
41106 +static int _ocm_free(const void *addr,
41107 +                    struct ocm_heap *ocmheap)
41108 +{
41109 +       struct ocm_piece *pslot, *plast, *pavail;
41110 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
41111 +       struct ocm_piece *pused_head = &ocmheap->used_head;
41112 +
41113 +       /* search the relevant memory slot */
41114 +       pslot = pused_head->next;
41115 +       plast = pused_head;
41116 +
41117 +       /* search an available piece slot */
41118 +       while (pslot != NULL && pslot->paddr != addr) {
41119 +               plast = pslot;
41120 +               pslot = pslot->next;
41121 +       }
41122 +
41123 +       if (!pslot) {
41124 +               DEBUGP("_ocm_free %p  not found in %p", addr, ocmheap);
41125 +               return -1;
41126 +       }
41127 +       DEBUGP("_ocm_free %p from in %p", addr, ocmheap);
41128 +
41129 +       plast->next = pslot->next;
41130 +       pavail = pslot;
41131 +       pavail->pid = 0;
41132 +
41133 +       /* insert free pieces back to the free list */
41134 +       pslot = pfree_head->next;
41135 +       plast = pfree_head;
41136 +
41137 +       while (pslot != NULL && addr > pslot->paddr) {
41138 +               plast = pslot;
41139 +               pslot = pslot->next;
41140 +       }
41141 +
41142 +       if (plast != pfree_head &&
41143 +           plast->paddr + plast->size == pavail->paddr) {
41144 +               plast->size += pavail->size;
41145 +               kmem_cache_free(ocm_piece_cache, pavail);
41146 +       } else {
41147 +               pavail->next = plast->next;
41148 +               plast->next = pavail;
41149 +               plast = pavail;
41150 +       }
41151 +
41152 +       if (pslot && plast->paddr + plast->size == pslot->paddr) {
41153 +               plast->size += pslot->size;
41154 +               plast->next = pslot->next;
41155 +               kmem_cache_free(ocm_piece_cache, pslot);
41156 +       }
41157 +
41158 +       return 0;
41159 +}
41160 +
41161 +/*
41162 + * ocm_inst_alloc()
41163 + *
41164 + *     allocates a block of size in the ocm instrction heap, if
41165 + *     successful returns address allocated.
41166 + */
41167 +void *ocm_inst_alloc(size_t size, pid_t pid)
41168 +{
41169 +       void *addr;
41170 +
41171 +       if (!OCM_INST_HEAP_LENGTH)
41172 +               return NULL;
41173 +
41174 +
41175 +       mutex_lock(&ocm_inst_heap.lock);
41176 +
41177 +       addr = _ocm_alloc(size, pid, &ocm_inst_heap);
41178 +
41179 +       mutex_unlock(&ocm_inst_heap.lock);
41180 +
41181 +       return addr;
41182 +}
41183 +EXPORT_SYMBOL(ocm_inst_alloc);
41184 +
41185 +/*
41186 + * ocm_inst_free()
41187 + *     free a block in the ocm instrction heap, returns 0 if successful.
41188 + */
41189 +int ocm_inst_free(const void *addr)
41190 +{
41191 +       int ret;
41192 +
41193 +       if (!OCM_INST_HEAP_LENGTH)
41194 +               return -1;
41195 +
41196 +       mutex_lock(&ocm_inst_heap.lock);
41197 +
41198 +       ret = _ocm_free(addr, &ocm_inst_heap);
41199 +
41200 +       mutex_unlock(&ocm_inst_heap.lock);
41201 +
41202 +       return ret;
41203 +}
41204 +EXPORT_SYMBOL(ocm_inst_free);
41205 +
41206 +/*
41207 + * ocm_free()
41208 + *     free a block in one of the ocm heaps, returns 0 if successful.
41209 + */
41210 +int ocm_free(const void *addr)
41211 +{
41212 +       if (addr >= (void *)OCM_INST_HEAP_BEGIN
41213 +                && addr < (void *)(OCM_INST_HEAP_END))
41214 +               return ocm_inst_free(addr);
41215 +       else
41216 +               return -1;
41217 +}
41218 +EXPORT_SYMBOL(ocm_free);
41219 +
41220 +
41221 +#ifdef CONFIG_PROC_FS
41222 +/* Need to keep line of output the same.  Currently, that is 46 bytes
41223 + * (including newline).
41224 + */
41225 +static int _ocm_proc_read(char *buf, int *len, int count, const char *desc,
41226 +                          struct ocm_heap *ocmheap)
41227 +{
41228 +       struct ocm_piece *pslot;
41229 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
41230 +       struct ocm_piece *pused_head = &ocmheap->used_head;
41231 +
41232 +       /* The format is the following
41233 +        * --- OCM 123456789012345 Size   PID State     \n
41234 +        * 12345678-12345678 1234567890 12345 1234567890\n
41235 +        */
41236 +       int l;
41237 +       l = sprintf(&buf[*len], "--- OCM %-15s Size   PID State     \n",
41238 +                   desc);
41239 +
41240 +       *len += l;
41241 +       count -= l;
41242 +
41243 +       mutex_lock(&ocm_inst_heap.lock);
41244 +
41245 +       /*
41246 +        * search the relevant memory slot
41247 +        */
41248 +       pslot = pused_head->next;
41249 +
41250 +       while (pslot != NULL && count > 46) {
41251 +               l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41252 +                            pslot->paddr, pslot->paddr + pslot->size,
41253 +                            pslot->size, pslot->pid, "ALLOCATED");
41254 +
41255 +               *len += l;
41256 +               count -= l;
41257 +               pslot = pslot->next;
41258 +       }
41259 +
41260 +       pslot = pfree_head->next;
41261 +
41262 +       while (pslot != NULL && count > 46) {
41263 +               l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41264 +                           pslot->paddr, pslot->paddr + pslot->size,
41265 +                           pslot->size, pslot->pid, "FREE");
41266 +
41267 +               *len += l;
41268 +               count -= l;
41269 +               pslot = pslot->next;
41270 +       }
41271 +
41272 +       mutex_unlock(&ocm_inst_heap.lock);
41273 +
41274 +       return 0;
41275 +}
41276 +
41277 +static int ocm_proc_read(char *buf, char **start, off_t offset, int count,
41278 +               int *eof, void *data)
41279 +{
41280 +       int len = 0;
41281 +
41282 +       len = sprintf(&buf[len], "--- OCM SKB usage (max RX buf %d)\n"
41283 +                       "(SKB in OCM) %d - (SKB in DDR) %d\n",
41284 +                       ubi32_ocm_skbuf_max,
41285 +                       ubi32_ocm_skbuf,
41286 +                       ubi32_ddr_skbuf);
41287 +
41288 +       len += sprintf(&buf[len], "--- OCM Data Heap       Size\n"
41289 +                       "%p-%p %10i\n",
41290 +                       ((void *)&__ocm_free_begin),
41291 +                       ((void *)&__ocm_free_end),
41292 +                       ((unsigned int)&__ocm_free_end) -
41293 +                       ((unsigned int)&__ocm_free_begin));
41294 +
41295 +       if (_ocm_proc_read(buf, &len, count - len, "Inst Heap",
41296 +                           &ocm_inst_heap))
41297 +               goto not_done;
41298 +       *eof = 1;
41299 + not_done:
41300 +       return len;
41301 +}
41302 +
41303 +static int ocm_proc_write(struct file *file, const char __user *buffer,
41304 +                           unsigned long count, void *data)
41305 +{
41306 +       int n, v;
41307 +       char in[8];
41308 +
41309 +       if (count > sizeof(in))
41310 +               return -EINVAL;
41311 +
41312 +       if (copy_from_user(in, buffer, count))
41313 +               return -EFAULT;
41314 +       in[count-1] = 0;
41315 +
41316 +       printk(KERN_INFO "OCM skb alloc max = %s\n", in);
41317 +
41318 +       n = 0;
41319 +       v = 0;
41320 +       while ((in[n] >= '0') && (in[n] <= '9')) {
41321 +               v = v * 10 + (int)(in[n] - '0');
41322 +               n++;
41323 +       }
41324 +
41325 +       if (v == 0)
41326 +               return -EINVAL;
41327 +
41328 +       ubi32_ocm_skbuf_max = v;
41329 +       ubi32_ocm_skbuf = ubi32_ddr_skbuf = 0;
41330 +
41331 +       return count;
41332 +}
41333 +
41334 +static int __init sram_proc_init(void)
41335 +{
41336 +       struct proc_dir_entry *ptr;
41337 +       ptr = create_proc_entry("ocm", S_IFREG | S_IRUGO, NULL);
41338 +       if (!ptr) {
41339 +               printk(KERN_WARNING "unable to create /proc/ocm\n");
41340 +               return -1;
41341 +       }
41342 +       ptr->read_proc = ocm_proc_read;
41343 +       ptr->write_proc = ocm_proc_write;
41344 +       return 0;
41345 +}
41346 +late_initcall(sram_proc_init);
41347 +#endif
41348 diff -ruN linux-2.6.30.10/arch/ubicom32/oprofile/ipProf.h linux-2.6.30.10-ubi/arch/ubicom32/oprofile/ipProf.h
41349 --- linux-2.6.30.10/arch/ubicom32/oprofile/ipProf.h     1970-01-01 02:00:00.000000000 +0200
41350 +++ linux-2.6.30.10-ubi/arch/ubicom32/oprofile/ipProf.h 2009-12-11 11:45:11.000000000 +0200
41351 @@ -0,0 +1,39 @@
41352 +#ifndef __IP_PROF_H__
41353 +#define __IP_PROF_H__
41354 +
41355 +/* This number MUST match what is used in the ultra configuration! */
41356 +#define IPPROFILETIO_MAX_SAMPLES       600
41357 +
41358 +/* Move to .h file used in both; avoid special types  */
41359 +struct profile_sample {
41360 +       unsigned int    pc;             /* PC value */
41361 +       unsigned int    parent;         /* a5 contents, to find the caller */
41362 +       unsigned char   cond_codes;     /* for branch prediction */
41363 +       unsigned char   thread;         /* I-blocked, D-blocked,
41364 +                                          4-bit thread number */
41365 +       unsigned short  active;         /* which threads are active -
41366 +                                          for accurate counting */
41367 +       unsigned short  blocked;        /* which threads are blocked due to
41368 +                                          I or D cache misses */
41369 +       unsigned int    latency;        /* CPU clocks since the last message
41370 +                                          dispatch in this thread
41371 +                                          (thread 0 only for now) */
41372 +};
41373 +
41374 +
41375 +struct profilenode {
41376 +       struct devtree_node dn;
41377 +       volatile unsigned char enabled; /* Is the tio enabled to
41378 +                                          take samples? */
41379 +       volatile unsigned char busy;    /* set when the samples
41380 +                                          are being read */
41381 +       volatile unsigned int mask;     /* Threads that change the MT_EN flag */
41382 +       volatile unsigned short rate;   /* What is the sampling rate? */
41383 +       volatile unsigned short head;   /* sample taker puts samples here */
41384 +       volatile unsigned short tail;   /* packet filler takes samples here */
41385 +       volatile unsigned short count;  /* number of valid samples */
41386 +       volatile unsigned short total;  /* Total samples */
41387 +       struct profile_sample samples[IPPROFILETIO_MAX_SAMPLES];
41388 +};
41389 +
41390 +#endif
41391 diff -ruN linux-2.6.30.10/arch/ubicom32/oprofile/Makefile linux-2.6.30.10-ubi/arch/ubicom32/oprofile/Makefile
41392 --- linux-2.6.30.10/arch/ubicom32/oprofile/Makefile     1970-01-01 02:00:00.000000000 +0200
41393 +++ linux-2.6.30.10-ubi/arch/ubicom32/oprofile/Makefile 2009-12-11 11:45:11.000000000 +0200
41394 @@ -0,0 +1,37 @@
41395 +#
41396 +# arch/ubicom32/Makefile
41397 +#       Makefile for Oprofile support on Ubicom32
41398 +#
41399 +# (C) Copyright 2009, Ubicom, Inc.
41400 +#
41401 +# This file is part of the Ubicom32 Linux Kernel Port.
41402 +#
41403 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
41404 +# it and/or modify it under the terms of the GNU General Public License
41405 +# as published by the Free Software Foundation, either version 2 of the
41406 +# License, or (at your option) any later version.
41407 +#
41408 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
41409 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
41410 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
41411 +# the GNU General Public License for more details.
41412 +#
41413 +# You should have received a copy of the GNU General Public License
41414 +# along with the Ubicom32 Linux Kernel Port.  If not,
41415 +# see <http://www.gnu.org/licenses/>.
41416 +#
41417 +# Ubicom32 implementation derived from (with many thanks):
41418 +#   arch/m68knommu
41419 +#   arch/blackfin
41420 +#   arch/parisc
41421 +#
41422 +
41423 +obj-$(CONFIG_OPROFILE) += oprofile.o
41424 +
41425 +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
41426 +               oprof.o cpu_buffer.o buffer_sync.o \
41427 +               event_buffer.o oprofile_files.o \
41428 +               oprofilefs.o oprofile_stats.o \
41429 +               timer_int.o )
41430 +
41431 +oprofile-y     := $(DRIVER_OBJS) profile.o
41432 diff -ruN linux-2.6.30.10/arch/ubicom32/oprofile/profile.c linux-2.6.30.10-ubi/arch/ubicom32/oprofile/profile.c
41433 --- linux-2.6.30.10/arch/ubicom32/oprofile/profile.c    1970-01-01 02:00:00.000000000 +0200
41434 +++ linux-2.6.30.10-ubi/arch/ubicom32/oprofile/profile.c        2009-12-11 11:45:11.000000000 +0200
41435 @@ -0,0 +1,221 @@
41436 +/*
41437 + * arch/ubicom32/oprofile/profile.c
41438 + *     Oprofile support for arch Ubicom32
41439 + *
41440 + * (C) Copyright 2009, Ubicom, Inc.
41441 + *
41442 + * This file is part of the Ubicom32 Linux Kernel Port.
41443 + *
41444 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41445 + * it and/or modify it under the terms of the GNU General Public License
41446 + * as published by the Free Software Foundation, either version 2 of the
41447 + * License, or (at your option)
41448 + * any later version.
41449 + *
41450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it will
41451 + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41452 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41453 + * General Public License for more details.
41454 + *
41455 + * You should have received a copy of the GNU General Public License
41456 + * along with the Ubicom32 Linux Kernel Port.  If not, see
41457 + * <http://www.gnu.org/licenses/>.
41458 + *
41459 + * Ubicom32 implementation derived from (with many thanks):
41460 + *   arch/m68knommu
41461 + *   arch/blackfin
41462 + *   arch/parisc
41463 + */
41464 +
41465 +/**
41466 + * @file profile.c
41467 + *
41468 + * @remark Copyright 2002 OProfile authors
41469 + * @remark Read the file COPYING
41470 + *
41471 + * @author Hunyue Yau <hy@hy-research.com>
41472 + */
41473 +
41474 +#include <linux/oprofile.h>
41475 +#include <linux/init.h>
41476 +#include <linux/errno.h>
41477 +#include <linux/interrupt.h>
41478 +#include <linux/module.h>
41479 +#include <linux/kernel.h>
41480 +
41481 +#include <asm/devtree.h>
41482 +#include <asm/thread.h>
41483 +
41484 +/* For identifying userland vs kernel address */
41485 +#include <asm/stacktrace.h>
41486 +#include "ipProf.h"
41487 +
41488 +/* For communications with the backend */
41489 +static struct profilenode *profile_node;
41490 +
41491 +/* Bitmask containing all Linux threads - as seen by the ROSR reg */
41492 +static unsigned long th_all_mask;
41493 +
41494 +/* Lookup table to translate a hardware thread into a CPU identifier
41495 + * Table is indexed by the ROSR value which is assumed to be
41496 + * relatively small (0...15).
41497 + */
41498 +unsigned int cpu_map[THREAD_ARCHITECTURAL_MAX];
41499 +
41500 +static struct pt_regs regs;
41501 +
41502 +/*
41503 + * For each sample returned, checked to see if they are relevant to
41504 + * us. This is necessary as the ubicom32 architecture has other software
41505 + * running outside of Linux. Only then, put the sample into the relevant
41506 + * cpu bins.
41507 + *
41508 + * To minimize overhead, a global mask with all possible threads of in
41509 + * interest to us is used as a first check. Then a second mask identifying
41510 + * the thread is used to obtain an identifier for that "CPU".
41511 + */
41512 +
41513 +/*
41514 + * ubicom32_build_cpu_th_mask()
41515 + *
41516 + * Build a lookup table for translation between hardware thread
41517 + * "ROSR" values and Linux CPU ids
41518 + *
41519 + * *** This gets executed on all CPUs at once! ***
41520 + */
41521 +static void ubicom32_build_cpu_th_mask(void *mask)
41522 +{
41523 +       thread_t self = thread_get_self();
41524 +       unsigned long *th_m = mask;
41525 +
41526 +       BUG_ON(self <= 0 || self >= THREAD_ARCHITECTURAL_MAX);
41527 +       cpu_map[self] = smp_processor_id();
41528 +
41529 +       set_bit(self, th_m);
41530 +}
41531 +
41532 +/*
41533 + * profile_interrupt()
41534 + *
41535 + * Process samples returned from the profiler backend. The backend
41536 + * may return samples that are irrelevant to us or may even return
41537 + * multiple samples for the same CPU. Note that the sames may be
41538 + * for ANY cpu. At this time, this is unique and to support this requires
41539 + * Oprofile to expose an interface to accept the CPU that the same came
41540 + * frome.
41541 + */
41542 +static irqreturn_t profile_interrupt(int irq, void *arg)
41543 +{
41544 +       int i, buf_entry;
41545 +       int is_kernel;
41546 +       unsigned int bit_th;
41547 +       unsigned int th;
41548 +
41549 +       if (!(profile_node->enabled) || profile_node->count < 0) {
41550 +               printk(KERN_WARNING
41551 +                       "Unexpected interrupt, no samples or not enabled!\n");
41552 +               return IRQ_HANDLED;
41553 +       }
41554 +
41555 +       profile_node->busy = 1;         /* Keep backend out */
41556 +
41557 +       for (i = 0; i < profile_node->count; i++) {
41558 +               buf_entry = profile_node->tail;
41559 +               profile_node->tail++;
41560 +               profile_node->tail %= IPPROFILETIO_MAX_SAMPLES;
41561 +
41562 +               /* Note - the "thread" ID is only the lower 4 bits */
41563 +               th = (0x0f & profile_node->samples[buf_entry].thread);
41564 +               bit_th = (1 << th);
41565 +
41566 +               if ((bit_th & th_all_mask) == 0)
41567 +                       continue;
41568 +
41569 +               regs.pc = profile_node->samples[buf_entry].pc;
41570 +
41571 +               is_kernel = ubicom32_is_kernel(regs.pc);
41572 +
41573 +               oprofile_add_ext_sample_cpu(regs.pc, &regs, 0, is_kernel,
41574 +                                           cpu_map[th]);
41575 +       }
41576 +       profile_node->count = 0;
41577 +       profile_node->busy = 0;
41578 +
41579 +       return IRQ_HANDLED;
41580 +}
41581 +
41582 +/*
41583 + * profile_start()
41584 + *
41585 + * Notification from oprofile to start the profiler
41586 + */
41587 +static int profile_start(void)
41588 +{
41589 +       if (!profile_node)
41590 +               return -1;
41591 +
41592 +       profile_node->enabled = 1;
41593 +
41594 +       return 0;
41595 +}
41596 +
41597 +/*
41598 + * profile_stop()
41599 + *
41600 + * Notification from oprofile to stop the profiler
41601 + */
41602 +static void profile_stop(void)
41603 +{
41604 +       if (profile_node)
41605 +               profile_node->enabled = 0;
41606 +}
41607 +
41608 +/*
41609 + * oprofile_arch_init()
41610 + *
41611 + * Attach to Oprofile after qualify the availability of the backend
41612 + * profiler support.
41613 + */
41614 +int __init oprofile_arch_init(struct oprofile_operations *ops)
41615 +{
41616 +       int r = -ENODEV;
41617 +
41618 +       profile_node = (struct profilenode *)devtree_find_node("profiler");
41619 +
41620 +       if (profile_node == NULL) {
41621 +               printk(KERN_WARNING "Cannot find profiler node\n");
41622 +               return r;
41623 +       }
41624 +
41625 +       r = request_irq(profile_node->dn.recvirq, profile_interrupt,
41626 +                       IRQF_DISABLED, "profiler", NULL);
41627 +
41628 +       if (r < 0) {
41629 +               profile_node = NULL;
41630 +               printk(KERN_WARNING "Cannot get profiler IRQ\n");
41631 +               return r;
41632 +       }
41633 +
41634 +       ops->start = profile_start;
41635 +       ops->stop = profile_stop;
41636 +       ops->cpu_type = "timer";
41637 +
41638 +       memset(cpu_map, 0, sizeof(cpu_map));
41639 +
41640 +       on_each_cpu(ubicom32_build_cpu_th_mask, &th_all_mask, 1);
41641 +
41642 +       memset(&regs, 0, sizeof(regs));
41643 +
41644 +       return r;
41645 +}
41646 +
41647 +/*
41648 + * oprofile_arch_exit()
41649 + *
41650 + * External call to take outselves out.
41651 + * Make sure backend is not running.
41652 + */
41653 +void oprofile_arch_exit(void)
41654 +{
41655 +       BUG_ON(profile_node->enabled);
41656 +}
41657 diff -ruN linux-2.6.30.10/drivers/char/hw_random/Kconfig linux-2.6.30.10-ubi/drivers/char/hw_random/Kconfig
41658 --- linux-2.6.30.10/drivers/char/hw_random/Kconfig      2009-12-04 08:00:07.000000000 +0200
41659 +++ linux-2.6.30.10-ubi/drivers/char/hw_random/Kconfig  2009-12-11 11:45:13.000000000 +0200
41660 @@ -148,3 +148,16 @@
41661  
41662           To compile this driver as a module, choose M here: the
41663           module will be called virtio-rng.  If unsure, say N.
41664 +
41665 +config HW_RANDOM_UBICOM32
41666 +       tristate "Ubicom32 HW Random Number Generator support"
41667 +       depends on HW_RANDOM && UBICOM32
41668 +       default HW_RANDOM
41669 +       ---help---
41670 +         This driver provides kernel-side support for the Random Number
41671 +         Generator hardware found on Ubicom32 processors.
41672 +
41673 +         To compile this driver as a module, choose M here: the
41674 +         module will be called pasemi-rng.
41675 +
41676 +         If unsure, say Y.
41677 diff -ruN linux-2.6.30.10/drivers/char/hw_random/Makefile linux-2.6.30.10-ubi/drivers/char/hw_random/Makefile
41678 --- linux-2.6.30.10/drivers/char/hw_random/Makefile     2009-12-04 08:00:07.000000000 +0200
41679 +++ linux-2.6.30.10-ubi/drivers/char/hw_random/Makefile 2009-12-11 11:45:13.000000000 +0200
41680 @@ -15,3 +15,4 @@
41681  obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
41682  obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
41683  obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
41684 +obj-$(CONFIG_HW_RANDOM_UBICOM32) += ubicom32-rng.o
41685 diff -ruN linux-2.6.30.10/drivers/char/hw_random/ubicom32-rng.c linux-2.6.30.10-ubi/drivers/char/hw_random/ubicom32-rng.c
41686 --- linux-2.6.30.10/drivers/char/hw_random/ubicom32-rng.c       1970-01-01 02:00:00.000000000 +0200
41687 +++ linux-2.6.30.10-ubi/drivers/char/hw_random/ubicom32-rng.c   2009-12-11 11:45:13.000000000 +0200
41688 @@ -0,0 +1,105 @@
41689 +/*
41690 + * drivers/net/ubi32-eth.c
41691 + *   Ubicom32 hardware random number generator driver.
41692 + *
41693 + * (C) Copyright 2009, Ubicom, Inc.
41694 + *
41695 + * This file is part of the Ubicom32 Linux Kernel Port.
41696 + *
41697 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41698 + * it and/or modify it under the terms of the GNU General Public License
41699 + * as published by the Free Software Foundation, either version 2 of the
41700 + * License, or (at your option) any later version.
41701 + *
41702 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41703 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41704 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
41705 + * the GNU General Public License for more details.
41706 + *
41707 + * You should have received a copy of the GNU General Public License
41708 + * along with the Ubicom32 Linux Kernel Port.  If not,
41709 + * see <http://www.gnu.org/licenses/>.
41710 + *
41711 + * Ubicom32 implementation derived from (with many thanks):
41712 + *   arch/m68knommu
41713 + *   arch/blackfin
41714 + *   arch/parisc
41715 + */
41716 +
41717 +#include <linux/kernel.h>
41718 +#include <linux/module.h>
41719 +#include <linux/hw_random.h>
41720 +#include <linux/delay.h>
41721 +#include <asm/io.h>
41722 +#include <asm/ip5000.h>
41723 +
41724 +#define MODULE_NAME "ubicom32_rng"
41725 +
41726 +static int ubicom32_rng_data_present(struct hwrng *rng, int wait)
41727 +{
41728 +       int data, i;
41729 +
41730 +       for (i = 0; i < 20; i++) {
41731 +               data = *(int *)(TIMER_BASE + TIMER_TRN);
41732 +               if (data || !wait)
41733 +                       break;
41734 +               udelay(10);
41735 +       }
41736 +       return data;
41737 +}
41738 +
41739 +static int ubicom32_rng_data_read(struct hwrng *rng, u32 *data)
41740 +{
41741 +       *data = *(int *)(TIMER_BASE + TIMER_TRN);
41742 +       return 4;
41743 +}
41744 +
41745 +static int ubicom32_rng_init(struct hwrng *rng)
41746 +{
41747 +       printk(KERN_INFO "ubicom32 rng init\n");
41748 +       *(int *)(TIMER_BASE + TIMER_TRN_CFG) = TIMER_TRN_CFG_ENABLE_OSC;
41749 +       return 0;
41750 +}
41751 +
41752 +static void ubicom32_rng_cleanup(struct hwrng *rng)
41753 +{
41754 +       printk(KERN_INFO "ubicom32 rng cleanup\n");
41755 +       *(int *)(TIMER_BASE + TIMER_TRN_CFG) = 0;
41756 +}
41757 +
41758 +static struct hwrng ubicom32_rng = {
41759 +       .name           = MODULE_NAME,
41760 +       .init           = ubicom32_rng_init,
41761 +       .cleanup        = ubicom32_rng_cleanup,
41762 +       .data_present   = ubicom32_rng_data_present,
41763 +       .data_read      = ubicom32_rng_data_read,
41764 +       .priv           = 0,
41765 +};
41766 +
41767 +static int __init mod_init(void)
41768 +{
41769 +       int err;
41770 +
41771 +       printk(KERN_INFO "ubicom32 rng started\n");
41772 +       err = hwrng_register(&ubicom32_rng);
41773 +       if (err) {
41774 +               printk(KERN_ERR "ubicom32 rng register failed (%d)\n",
41775 +                       err);
41776 +       }
41777 +
41778 +       return err;
41779 +}
41780 +
41781 +static void __exit mod_exit(void)
41782 +{
41783 +       printk(KERN_INFO "ubicom32 rng stopped\n");
41784 +       hwrng_unregister(&ubicom32_rng);
41785 +}
41786 +
41787 +module_init(mod_init);
41788 +module_exit(mod_exit);
41789 +
41790 +MODULE_LICENSE("GPL");
41791 +MODULE_AUTHOR("Ubicom, Inc.");
41792 +MODULE_DESCRIPTION("H/W rng driver for ubicom32 processor");
41793 +MODULE_VERSION("1:1.0.a");
41794 diff -ruN linux-2.6.30.10/drivers/crypto/Kconfig linux-2.6.30.10-ubi/drivers/crypto/Kconfig
41795 --- linux-2.6.30.10/drivers/crypto/Kconfig      2009-12-04 08:00:07.000000000 +0200
41796 +++ linux-2.6.30.10-ubi/drivers/crypto/Kconfig  2009-12-11 11:45:13.000000000 +0200
41797 @@ -61,6 +61,40 @@
41798           To compile this driver as a module, choose M here: the module
41799           will be called geode-aes.
41800  
41801 +config CRYPTO_UBICOM32
41802 +        bool "Ubicom32 Security Module"
41803 +        depends on UBICOM32
41804 +        help
41805 +          This is the ubicom32 hardware acceleration common code.
41806 +
41807 +config CRYPTO_AES_UBICOM32
41808 +        tristate "Ubicom32 AES implementation"
41809 +        depends on CRYPTO_UBICOM32
41810 +        select CRYPTO_ALGAPI
41811 +        help
41812 +          This is the ubicom32 hardware AES implementation.
41813 +
41814 +config CRYPTO_DES_UBICOM32
41815 +        tristate "Ubicom32 DES implementation"
41816 +        depends on CRYPTO_UBICOM32
41817 +        select CRYPTO_ALGAPI
41818 +        help
41819 +          This is the ubicom32 hardware DES and 3DES implementation.
41820 +
41821 +config CRYPTO_SHA1_UBICOM32
41822 +        tristate "Ubicom32 SHA1 implementation"
41823 +        depends on CRYPTO_UBICOM32
41824 +        select CRYPTO_ALGAPI
41825 +        help
41826 +          This is the ubicom32 hardware SHA1 implementation.
41827 +
41828 +config CRYPTO_MD5_UBICOM32
41829 +        tristate "Ubicom32 MD5 implementation"
41830 +        depends on CRYPTO_UBICOM32
41831 +        select CRYPTO_ALGAPI
41832 +        help
41833 +          This is the ubicom32 hardware MD5 implementation.
41834 +
41835  config ZCRYPT
41836         tristate "Support for PCI-attached cryptographic adapters"
41837         depends on S390
41838 diff -ruN linux-2.6.30.10/drivers/mmc/host/Kconfig linux-2.6.30.10-ubi/drivers/mmc/host/Kconfig
41839 --- linux-2.6.30.10/drivers/mmc/host/Kconfig    2009-12-14 11:15:33.000000000 +0200
41840 +++ linux-2.6.30.10-ubi/drivers/mmc/host/Kconfig        2009-12-14 11:15:31.000000000 +0200
41841 @@ -266,3 +266,10 @@
41842         help
41843           This option automatically enables configfs support for gpiommc
41844           if configfs is available.
41845 +
41846 +config MMC_UBICOM32
41847 +       tristate "Ubicom32 MMC/SD host controller"
41848 +       depends on UBICOM32
41849 +       help
41850 +         This provides support for the SD/MMC hardware found on Ubicom32
41851 +         IP7K processors
41852 diff -ruN linux-2.6.30.10/drivers/mmc/host/Makefile linux-2.6.30.10-ubi/drivers/mmc/host/Makefile
41853 --- linux-2.6.30.10/drivers/mmc/host/Makefile   2009-12-14 11:37:36.000000000 +0200
41854 +++ linux-2.6.30.10-ubi/drivers/mmc/host/Makefile       2009-12-14 11:37:35.000000000 +0200
41855 @@ -30,4 +30,5 @@
41856  obj-$(CONFIG_MMC_SDRICOH_CS)   += sdricoh_cs.o
41857  obj-$(CONFIG_MMC_TMIO)         += tmio_mmc.o
41858  obj-$(CONFIG_GPIOMMC)          += gpiommc.o
41859 +obj-$(CONFIG_MMC_UBICOM32)     += ubicom32sd.o
41860  
41861 diff -ruN linux-2.6.30.10/drivers/mmc/host/ubicom32sd.c linux-2.6.30.10-ubi/drivers/mmc/host/ubicom32sd.c
41862 --- linux-2.6.30.10/drivers/mmc/host/ubicom32sd.c       1970-01-01 02:00:00.000000000 +0200
41863 +++ linux-2.6.30.10-ubi/drivers/mmc/host/ubicom32sd.c   2009-12-11 11:45:16.000000000 +0200
41864 @@ -0,0 +1,773 @@
41865 +/*
41866 + * drivers/mmc/host/ubicom32sd.c
41867 + *     Ubicom32 Secure Digital Host Controller Interface driver
41868 + *
41869 + * (C) Copyright 2009, Ubicom, Inc.
41870 + *
41871 + * This file is part of the Ubicom32 Linux Kernel Port.
41872 + *
41873 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41874 + * it and/or modify it under the terms of the GNU General Public License
41875 + * as published by the Free Software Foundation, either version 2 of the
41876 + * License, or (at your option) any later version.
41877 + *
41878 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41879 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41880 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
41881 + * the GNU General Public License for more details.
41882 + *
41883 + * You should have received a copy of the GNU General Public License
41884 + * along with the Ubicom32 Linux Kernel Port.  If not,
41885 + * see <http://www.gnu.org/licenses/>.
41886 + */
41887 +
41888 +#include <linux/module.h>
41889 +#include <linux/platform_device.h>
41890 +#include <linux/delay.h>
41891 +#include <linux/scatterlist.h>
41892 +#include <linux/leds.h>
41893 +#include <linux/gpio.h>
41894 +#include <linux/mmc/host.h>
41895 +
41896 +#include <asm/ubicom32sd.h>
41897 +
41898 +#define DRIVER_NAME "ubicom32sd"
41899 +
41900 +#define sd_printk(...)
41901 +//#define sd_printk printk
41902 +
41903 +#define SDTIO_VP_VERSION       3
41904 +
41905 +#define SDTIO_MAX_SG_BLOCKS    16
41906 +
41907 +enum sdtio_commands {
41908 +       SDTIO_COMMAND_NOP,
41909 +       SDTIO_COMMAND_SETUP,
41910 +       SDTIO_COMMAND_SETUP_SDIO,
41911 +       SDTIO_COMMAND_EXECUTE,
41912 +       SDTIO_COMMAND_RESET,
41913 +};
41914 +
41915 +#define SDTIO_COMMAND_SHIFT                    24
41916 +#define SDTIO_COMMAND_FLAG_STOP_RSP_CRC                (1 << 10)
41917 +#define SDTIO_COMMAND_FLAG_STOP_RSP_136                (1 << 9)
41918 +#define SDTIO_COMMAND_FLAG_STOP_RSP            (1 << 8)
41919 +#define SDTIO_COMMAND_FLAG_STOP_CMD            (1 << 7)
41920 +#define SDTIO_COMMAND_FLAG_DATA_STREAM         (1 << 6)
41921 +#define SDTIO_COMMAND_FLAG_DATA_RD             (1 << 5)
41922 +#define SDTIO_COMMAND_FLAG_DATA_WR             (1 << 4)
41923 +#define SDTIO_COMMAND_FLAG_CMD_RSP_CRC         (1 << 3)
41924 +#define SDTIO_COMMAND_FLAG_CMD_RSP_136         (1 << 2)
41925 +#define SDTIO_COMMAND_FLAG_CMD_RSP             (1 << 1)
41926 +#define SDTIO_COMMAND_FLAG_CMD                 (1 << 0)
41927 +
41928 +/*
41929 + * SDTIO_COMMAND_SETUP_SDIO
41930 + */
41931 +#define SDTIO_COMMAND_FLAG_SDIO_INT_EN         (1 << 0)
41932 +
41933 +/*
41934 + * SDTIO_COMMAND_SETUP
41935 + *      clock speed in arg
41936 + */
41937 +#define SDTIO_COMMAND_FLAG_4BIT                 (1 << 3)
41938 +#define SDTIO_COMMAND_FLAG_1BIT                 (1 << 2)
41939 +#define SDTIO_COMMAND_FLAG_SET_CLOCK            (1 << 1)
41940 +#define SDTIO_COMMAND_FLAG_SET_WIDTH            (1 << 0)
41941 +
41942 +#define SDTIO_COMMAND_FLAG_CMD_RSP_MASK                (SDTIO_COMMAND_FLAG_CMD_RSP | SDTIO_COMMAND_FLAG_CMD_RSP_136)
41943 +#define SDTIO_COMMAND_FLAG_STOP_RSP_MASK       (SDTIO_COMMAND_FLAG_STOP_RSP | SDTIO_COMMAND_FLAG_STOP_RSP_136)
41944 +#define SDTIO_COMMAND_FLAG_RSP_MASK            (SDTIO_COMMAND_FLAG_CMD_RSP_MASK | SDTIO_COMMAND_FLAG_STOP_RSP_MASK)
41945 +
41946 +struct sdtio_vp_sg {
41947 +       volatile void           *addr;
41948 +       volatile u32_t          len;
41949 +};
41950 +
41951 +#define SDTIO_VP_INT_STATUS_DONE               (1 << 31)
41952 +#define SDTIO_VP_INT_STATUS_SDIO_INT           (1 << 10)
41953 +#define SDTIO_VP_INT_STATUS_DATA_CRC_ERR       (1 << 9)
41954 +#define SDTIO_VP_INT_STATUS_DATA_PROG_ERR      (1 << 8)
41955 +#define SDTIO_VP_INT_STATUS_DATA_TIMEOUT       (1 << 7)
41956 +#define SDTIO_VP_INT_STATUS_STOP_RSP_CRC       (1 << 6)
41957 +#define SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT   (1 << 5)
41958 +#define SDTIO_VP_INT_STATUS_CMD_RSP_CRC                (1 << 4)
41959 +#define SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT    (1 << 3)
41960 +#define SDTIO_VP_INT_STATUS_CMD_TIMEOUT                (1 << 2)
41961 +#define SDTIO_VP_INT_STATUS_CARD1_INSERT       (1 << 1)
41962 +#define SDTIO_VP_INT_STATUS_CARD0_INSERT       (1 << 0)
41963 +
41964 +struct sdtio_vp_regs {
41965 +       u32_t                           version;
41966 +       u32_t                           f_max;
41967 +       u32_t                           f_min;
41968 +
41969 +       volatile u32_t                  int_status;
41970 +
41971 +       volatile u32_t                  command;
41972 +       volatile u32_t                  arg;
41973 +
41974 +       volatile u32_t                  cmd_opcode;
41975 +       volatile u32_t                  cmd_arg;
41976 +       volatile u32_t                  cmd_rsp0;
41977 +       volatile u32_t                  cmd_rsp1;
41978 +       volatile u32_t                  cmd_rsp2;
41979 +       volatile u32_t                  cmd_rsp3;
41980 +
41981 +       volatile u32_t                  stop_opcode;
41982 +       volatile u32_t                  stop_arg;
41983 +       volatile u32_t                  stop_rsp0;
41984 +       volatile u32_t                  stop_rsp1;
41985 +       volatile u32_t                  stop_rsp2;
41986 +       volatile u32_t                  stop_rsp3;
41987 +
41988 +       volatile u32_t                  data_timeout_ns;
41989 +       volatile u16_t                  data_blksz;
41990 +       volatile u16_t                  data_blkct;
41991 +       volatile u32_t                  data_bytes_transferred;
41992 +       volatile u32_t                  sg_len;
41993 +       struct sdtio_vp_sg              sg[SDTIO_MAX_SG_BLOCKS];
41994 +};
41995 +
41996 +struct ubicom32sd_data {
41997 +       const struct ubicom32sd_platform_data   *pdata;
41998 +
41999 +       struct mmc_host                         *mmc;
42000 +
42001 +       /*
42002 +        * Lock used to protect the data structure
42003 +       spinlock_t                              lock;
42004 +        */
42005 +       int     int_en;
42006 +       int     int_pend;
42007 +
42008 +       /*
42009 +        * Receive and transmit interrupts used for communicating
42010 +        * with hardware
42011 +        */
42012 +       int                                     irq_tx;
42013 +       int                                     irq_rx;
42014 +
42015 +       /*
42016 +        * Current outstanding mmc request
42017 +        */
42018 +       struct mmc_request                      *mrq;
42019 +
42020 +       /*
42021 +        * Hardware registers
42022 +        */
42023 +       struct sdtio_vp_regs                    *regs;
42024 +};
42025 +
42026 +/*****************************************************************************\
42027 + *                                                                           *
42028 + * Suspend/resume                                                            *
42029 + *                                                                           *
42030 +\*****************************************************************************/
42031 +
42032 +#if 0//def CONFIG_PM
42033 +
42034 +int ubicom32sd_suspend_host(struct ubicom32sd_host *host, pm_message_t state)
42035 +{
42036 +       int ret;
42037 +
42038 +       ret = mmc_suspend_host(host->mmc, state);
42039 +       if (ret)
42040 +               return ret;
42041 +
42042 +       free_irq(host->irq, host);
42043 +
42044 +       return 0;
42045 +}
42046 +
42047 +EXPORT_SYMBOL_GPL(ubicom32sd_suspend_host);
42048 +
42049 +int ubicom32sd_resume_host(struct ubicom32sd_host *host)
42050 +{
42051 +       int ret;
42052 +
42053 +       if (host->flags & UBICOM32SD_USE_DMA) {
42054 +               if (host->ops->enable_dma)
42055 +                       host->ops->enable_dma(host);
42056 +       }
42057 +
42058 +       ret = request_irq(host->irq, ubicom32sd_irq, IRQF_SHARED,
42059 +                         mmc_hostname(host->mmc), host);
42060 +       if (ret)
42061 +               return ret;
42062 +
42063 +       ubicom32sd_init(host);
42064 +       mmiowb();
42065 +
42066 +       ret = mmc_resume_host(host->mmc);
42067 +       if (ret)
42068 +               return ret;
42069 +
42070 +       return 0;
42071 +}
42072 +
42073 +EXPORT_SYMBOL_GPL(ubicom32sd_resume_host);
42074 +
42075 +#endif /* CONFIG_PM */
42076 +
42077 +/*
42078 + * ubicom32sd_send_command_sync
42079 + */
42080 +static void ubicom32sd_send_command_sync(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
42081 +{
42082 +       ud->regs->command = command;
42083 +       ud->regs->arg = arg;
42084 +       ubicom32_set_interrupt(ud->irq_tx);
42085 +       while (ud->regs->command) {
42086 +               ndelay(100);
42087 +       }
42088 +}
42089 +
42090 +/*
42091 + * ubicom32sd_send_command
42092 + */
42093 +static void ubicom32sd_send_command(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
42094 +{
42095 +       ud->regs->command = command;
42096 +       ud->regs->arg = arg;
42097 +       ubicom32_set_interrupt(ud->irq_tx);
42098 +}
42099 +
42100 +/*
42101 + * ubicom32sd_reset
42102 + */
42103 +static void ubicom32sd_reset(struct ubicom32sd_data *ud)
42104 +{
42105 +       ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_RESET << SDTIO_COMMAND_SHIFT, 0);
42106 +       ud->regs->int_status = 0;
42107 +}
42108 +
42109 +/*
42110 + * ubicom32sd_mmc_request
42111 + */
42112 +static void ubicom32sd_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
42113 +{
42114 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42115 +       u32_t command = SDTIO_COMMAND_EXECUTE << SDTIO_COMMAND_SHIFT;
42116 +       int ret = 0;
42117 +
42118 +       WARN(ud->mrq != NULL, "ud->mrq still set to %p\n", ud->mrq);
42119 +       //pr_debug("send cmd %08x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags);
42120 +
42121 +       if (mrq->cmd) {
42122 +               struct mmc_command *cmd = mrq->cmd;
42123 +
42124 +               sd_printk("%s:\t\t\tsetup cmd %02d arg %08x flags %08x\n", mmc_hostname(mmc), cmd->opcode, cmd->arg, cmd->flags);
42125 +
42126 +               ud->regs->cmd_opcode = cmd->opcode;
42127 +               ud->regs->cmd_arg = cmd->arg;
42128 +
42129 +               command |= SDTIO_COMMAND_FLAG_CMD;
42130 +
42131 +               if (cmd->flags & MMC_RSP_PRESENT) {
42132 +                       command |= SDTIO_COMMAND_FLAG_CMD_RSP;
42133 +               }
42134 +
42135 +               if (cmd->flags & MMC_RSP_136) {
42136 +                       command |= SDTIO_COMMAND_FLAG_CMD_RSP_136;
42137 +               }
42138 +
42139 +               if (cmd->flags & MMC_RSP_CRC) {
42140 +                       command |= SDTIO_COMMAND_FLAG_CMD_RSP_CRC;
42141 +               }
42142 +       }
42143 +
42144 +       if (mrq->data) {
42145 +               struct mmc_data *data = mrq->data;
42146 +               struct scatterlist *sg = data->sg;
42147 +               int i;
42148 +
42149 +printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n", mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len, data->flags, data->timeout_ns);
42150 +
42151 +               sd_printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n",
42152 +                         mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len,
42153 +                         data->flags, data->timeout_ns);
42154 +
42155 +               if (data->sg_len > SDTIO_MAX_SG_BLOCKS) {
42156 +                       ret = -EINVAL;
42157 +                       data->error = -EINVAL;
42158 +                       goto fail;
42159 +               }
42160 +
42161 +               ud->regs->data_timeout_ns = data->timeout_ns;
42162 +               ud->regs->data_blksz = data->blksz;
42163 +               ud->regs->data_blkct = data->blocks;
42164 +               ud->regs->sg_len = data->sg_len;
42165 +
42166 +               /*
42167 +                * Load all of our sg list into the driver sg buffer
42168 +                */
42169 +               for (i = 0; i < data->sg_len; i++) {
42170 +                       sd_printk("%s: sg %d = %p %d\n", mmc_hostname(mmc), i, sg_virt(sg), sg->length);
42171 +                       ud->regs->sg[i].addr = sg_virt(sg);
42172 +                       ud->regs->sg[i].len = sg->length;
42173 +                       if (((u32_t)ud->regs->sg[i].addr & 0x03) || (sg->length & 0x03)) {
42174 +                               sd_printk("%s: Need aligned buffers\n", mmc_hostname(mmc));
42175 +                               ret = -EINVAL;
42176 +                               data->error = -EINVAL;
42177 +                               goto fail;
42178 +                       }
42179 +                       sg++;
42180 +               }
42181 +               if (data->flags & MMC_DATA_READ) {
42182 +                       command |= SDTIO_COMMAND_FLAG_DATA_RD;
42183 +               } else if (data->flags & MMC_DATA_WRITE) {
42184 +                       command |= SDTIO_COMMAND_FLAG_DATA_WR;
42185 +               } else if (data->flags & MMC_DATA_STREAM) {
42186 +                       command |= SDTIO_COMMAND_FLAG_DATA_STREAM;
42187 +               }
42188 +       }
42189 +
42190 +       if (mrq->stop) {
42191 +               struct mmc_command *stop = mrq->stop;
42192 +               sd_printk("%s: \t\t\tsetup stop %02d arg %08x flags %08x\n", mmc_hostname(mmc), stop->opcode, stop->arg, stop->flags);
42193 +
42194 +               ud->regs->stop_opcode = stop->opcode;
42195 +               ud->regs->stop_arg = stop->arg;
42196 +
42197 +               command |= SDTIO_COMMAND_FLAG_STOP_CMD;
42198 +
42199 +               if (stop->flags & MMC_RSP_PRESENT) {
42200 +                       command |= SDTIO_COMMAND_FLAG_STOP_RSP;
42201 +               }
42202 +
42203 +               if (stop->flags & MMC_RSP_136) {
42204 +                       command |= SDTIO_COMMAND_FLAG_STOP_RSP_136;
42205 +               }
42206 +
42207 +               if (stop->flags & MMC_RSP_CRC) {
42208 +                       command |= SDTIO_COMMAND_FLAG_STOP_RSP_CRC;
42209 +               }
42210 +       }
42211 +
42212 +       ud->mrq = mrq;
42213 +
42214 +       sd_printk("%s: Sending command %08x\n", mmc_hostname(mmc), command);
42215 +
42216 +       ubicom32sd_send_command(ud, command, 0);
42217 +
42218 +       return;
42219 +fail:
42220 +       sd_printk("%s: mmcreq ret = %d\n", mmc_hostname(mmc), ret);
42221 +       mrq->cmd->error = ret;
42222 +       mmc_request_done(mmc, mrq);
42223 +}
42224 +
42225 +/*
42226 + * ubicom32sd_mmc_set_ios
42227 + */
42228 +static void ubicom32sd_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
42229 +{
42230 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42231 +       u32_t command = SDTIO_COMMAND_SETUP << SDTIO_COMMAND_SHIFT;
42232 +       u32_t arg = 0;
42233 +       sd_printk("%s: ios call bw:%u pm:%u clk:%u\n", mmc_hostname(mmc), 1 << ios->bus_width, ios->power_mode, ios->clock);
42234 +
42235 +       switch (ios->bus_width) {
42236 +       case MMC_BUS_WIDTH_1:
42237 +               command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_1BIT;
42238 +               break;
42239 +
42240 +       case MMC_BUS_WIDTH_4:
42241 +               command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_4BIT;
42242 +               break;
42243 +       }
42244 +
42245 +       if (ios->clock) {
42246 +               arg = ios->clock;
42247 +               command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
42248 +       }
42249 +
42250 +       switch (ios->power_mode) {
42251 +
42252 +       /*
42253 +        * Turn off the SD bus (power + clock)
42254 +        */
42255 +       case MMC_POWER_OFF:
42256 +               gpio_set_value(ud->pdata->cards[0].pin_pwr, !ud->pdata->cards[0].pwr_polarity);
42257 +               command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
42258 +               break;
42259 +
42260 +       /*
42261 +        * Turn on the power to the SD bus
42262 +        */
42263 +       case MMC_POWER_ON:
42264 +               gpio_set_value(ud->pdata->cards[0].pin_pwr, ud->pdata->cards[0].pwr_polarity);
42265 +               break;
42266 +
42267 +       /*
42268 +        * Turn on the clock to the SD bus
42269 +        */
42270 +       case MMC_POWER_UP:
42271 +               /*
42272 +                * Done above
42273 +                */
42274 +               break;
42275 +       }
42276 +
42277 +       ubicom32sd_send_command_sync(ud, command, arg);
42278 +
42279 +       /*
42280 +        * Let the power settle down
42281 +        */
42282 +       udelay(500);
42283 +}
42284 +
42285 +/*
42286 + * ubicom32sd_mmc_get_cd
42287 + */
42288 +static int ubicom32sd_mmc_get_cd(struct mmc_host *mmc)
42289 +{
42290 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42291 +       sd_printk("%s: get cd %u %u\n", mmc_hostname(mmc), ud->pdata->cards[0].pin_cd, gpio_get_value(ud->pdata->cards[0].pin_cd));
42292 +
42293 +       return gpio_get_value(ud->pdata->cards[0].pin_cd) ?
42294 +                               ud->pdata->cards[0].cd_polarity :
42295 +                               !ud->pdata->cards[0].cd_polarity;
42296 +}
42297 +
42298 +/*
42299 + * ubicom32sd_mmc_get_ro
42300 + */
42301 +static int ubicom32sd_mmc_get_ro(struct mmc_host *mmc)
42302 +{
42303 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42304 +       sd_printk("%s: get ro %u %u\n", mmc_hostname(mmc), ud->pdata->cards[0].pin_wp, gpio_get_value(ud->pdata->cards[0].pin_wp));
42305 +
42306 +       return gpio_get_value(ud->pdata->cards[0].pin_wp) ?
42307 +                               ud->pdata->cards[0].wp_polarity :
42308 +                               !ud->pdata->cards[0].wp_polarity;
42309 +}
42310 +
42311 +/*
42312 + * ubicom32sd_mmc_enable_sdio_irq
42313 + */
42314 +static void ubicom32sd_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
42315 +{
42316 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42317 +
42318 +       ud->int_en = enable;
42319 +       if (enable && ud->int_pend) {
42320 +               ud->int_pend = 0;
42321 +               mmc_signal_sdio_irq(mmc);
42322 +       }
42323 +}
42324 +
42325 +/*
42326 + * ubicom32sd_interrupt
42327 + */
42328 +static irqreturn_t ubicom32sd_interrupt(int irq, void *dev)
42329 +{
42330 +       struct mmc_host *mmc = (struct mmc_host *)dev;
42331 +       struct mmc_request *mrq;
42332 +       struct ubicom32sd_data *ud;
42333 +       u32_t int_status;
42334 +
42335 +       if (!mmc) {
42336 +               return IRQ_HANDLED;
42337 +       }
42338 +
42339 +       ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42340 +       if (!ud) {
42341 +               return IRQ_HANDLED;
42342 +       }
42343 +
42344 +       int_status = ud->regs->int_status;
42345 +       ud->regs->int_status &= ~int_status;
42346 +
42347 +       if (int_status & SDTIO_VP_INT_STATUS_SDIO_INT) {
42348 +               if (ud->int_en) {
42349 +                       ud->int_pend = 0;
42350 +                       mmc_signal_sdio_irq(mmc);
42351 +               } else {
42352 +                       ud->int_pend++;
42353 +               }
42354 +       }
42355 +
42356 +       if (!(int_status & SDTIO_VP_INT_STATUS_DONE)) {
42357 +               return IRQ_HANDLED;
42358 +       }
42359 +
42360 +       mrq = ud->mrq;
42361 +       if (!mrq) {
42362 +               sd_printk("%s: Spurious interrupt", mmc_hostname(mmc));
42363 +               return IRQ_HANDLED;
42364 +       }
42365 +       ud->mrq = NULL;
42366 +
42367 +       /*
42368 +        * SDTIO_VP_INT_DONE
42369 +        */
42370 +       if (mrq->cmd->flags & MMC_RSP_PRESENT) {
42371 +               struct mmc_command *cmd = mrq->cmd;
42372 +               cmd->error = 0;
42373 +
42374 +               if ((cmd->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_CRC)) {
42375 +                       cmd->error = -EILSEQ;
42376 +               } else if (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT) {
42377 +                       cmd->error = -ETIMEDOUT;
42378 +                       goto done;
42379 +               } else if (cmd->flags & MMC_RSP_136) {
42380 +                       cmd->resp[0] = ud->regs->cmd_rsp0;
42381 +                       cmd->resp[1] = ud->regs->cmd_rsp1;
42382 +                       cmd->resp[2] = ud->regs->cmd_rsp2;
42383 +                       cmd->resp[3] = ud->regs->cmd_rsp3;
42384 +               } else {
42385 +                       cmd->resp[0] = ud->regs->cmd_rsp0;
42386 +               }
42387 +               sd_printk("%s:\t\t\tResponse %08x %08x %08x %08x err=%d\n", mmc_hostname(mmc), cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
42388 +       }
42389 +
42390 +       if (mrq->data) {
42391 +               struct mmc_data *data = mrq->data;
42392 +
42393 +               if (int_status & SDTIO_VP_INT_STATUS_DATA_TIMEOUT) {
42394 +                       data->error = -ETIMEDOUT;
42395 +                       sd_printk("%s:\t\t\tData Timeout\n", mmc_hostname(mmc));
42396 +                       goto done;
42397 +               } else if (int_status & SDTIO_VP_INT_STATUS_DATA_CRC_ERR) {
42398 +                       data->error = -EILSEQ;
42399 +                       sd_printk("%s:\t\t\tData CRC\n", mmc_hostname(mmc));
42400 +                       goto done;
42401 +               } else if (int_status & SDTIO_VP_INT_STATUS_DATA_PROG_ERR) {
42402 +                       data->error = -EILSEQ;
42403 +                       sd_printk("%s:\t\t\tData Program Error\n", mmc_hostname(mmc));
42404 +                       goto done;
42405 +               } else {
42406 +                       data->error = 0;
42407 +                       data->bytes_xfered = ud->regs->data_bytes_transferred;
42408 +               }
42409 +       }
42410 +
42411 +       if (mrq->stop && (mrq->stop->flags & MMC_RSP_PRESENT)) {
42412 +               struct mmc_command *stop = mrq->stop;
42413 +               stop->error = 0;
42414 +
42415 +               if ((stop->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_CRC)) {
42416 +                       stop->error = -EILSEQ;
42417 +               } else if (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT) {
42418 +                       stop->error = -ETIMEDOUT;
42419 +                       goto done;
42420 +               } else if (stop->flags & MMC_RSP_136) {
42421 +                       stop->resp[0] = ud->regs->stop_rsp0;
42422 +                       stop->resp[1] = ud->regs->stop_rsp1;
42423 +                       stop->resp[2] = ud->regs->stop_rsp2;
42424 +                       stop->resp[3] = ud->regs->stop_rsp3;
42425 +               } else {
42426 +                       stop->resp[0] = ud->regs->stop_rsp0;
42427 +               }
42428 +               sd_printk("%s:\t\t\tStop Response %08x %08x %08x %08x err=%d\n", mmc_hostname(mmc), stop->resp[0], stop->resp[1], stop->resp[2], stop->resp[3], stop->error);
42429 +       }
42430 +
42431 +done:
42432 +       mmc_request_done(mmc, mrq);
42433 +
42434 +       return IRQ_HANDLED;
42435 +}
42436 +
42437 +static struct mmc_host_ops ubicom32sd_ops = {
42438 +       .request                = ubicom32sd_mmc_request,
42439 +       .set_ios                = ubicom32sd_mmc_set_ios,
42440 +       .get_ro                 = ubicom32sd_mmc_get_ro,
42441 +       .get_cd                 = ubicom32sd_mmc_get_cd,
42442 +       .enable_sdio_irq        = ubicom32sd_mmc_enable_sdio_irq,
42443 +};
42444 +
42445 +/*
42446 + * ubicom32sd_probe
42447 + */
42448 +static int __devinit ubicom32sd_probe(struct platform_device *pdev)
42449 +{
42450 +       struct ubicom32sd_platform_data *pdata = (struct ubicom32sd_platform_data *)pdev->dev.platform_data;
42451 +       struct mmc_host *mmc;
42452 +       struct ubicom32sd_data *ud;
42453 +       struct resource *res_regs;
42454 +       struct resource *res_irq_tx;
42455 +       struct resource *res_irq_rx;
42456 +       int ret;
42457 +
42458 +       /*
42459 +        * Get our resources, regs is the hardware driver base address
42460 +        * and the tx and rx irqs are used to communicate with the
42461 +        * hardware driver.
42462 +        */
42463 +       res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42464 +       res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
42465 +       res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
42466 +       if (!res_regs || !res_irq_tx || !res_irq_rx) {
42467 +               ret = -EINVAL;
42468 +               goto fail;
42469 +       }
42470 +
42471 +       /*
42472 +        * Reserve any gpios we need
42473 +        */
42474 +       ret = gpio_request(pdata->cards[0].pin_wp, "sd-wp");
42475 +       if (ret) {
42476 +               goto fail;
42477 +       }
42478 +       gpio_direction_input(pdata->cards[0].pin_wp);
42479 +
42480 +       ret = gpio_request(pdata->cards[0].pin_cd, "sd-cd");
42481 +       if (ret) {
42482 +               goto fail_cd;
42483 +       }
42484 +       gpio_direction_input(pdata->cards[0].pin_cd);
42485 +
42486 +       /*
42487 +        * HACK: for the dual port controller on port F, we don't support the second port right now
42488 +        */
42489 +       if (pdata->ncards > 1) {
42490 +               ret = gpio_request(pdata->cards[1].pin_pwr, "sd-pwr");
42491 +               gpio_direction_output(pdata->cards[1].pin_pwr, !pdata->cards[1].pwr_polarity);
42492 +               gpio_direction_output(pdata->cards[1].pin_pwr, pdata->cards[1].pwr_polarity);
42493 +       }
42494 +
42495 +       ret = gpio_request(pdata->cards[0].pin_pwr, "sd-pwr");
42496 +       if (ret) {
42497 +               goto fail_pwr;
42498 +       }
42499 +       gpio_direction_output(pdata->cards[0].pin_pwr, !pdata->cards[0].pwr_polarity);
42500 +
42501 +       /*
42502 +        * Allocate the MMC driver, it includes memory for our data.
42503 +        */
42504 +       mmc = mmc_alloc_host(sizeof(struct ubicom32sd_data), &pdev->dev);
42505 +       if (!mmc) {
42506 +               ret = -ENOMEM;
42507 +               goto fail_mmc;
42508 +       }
42509 +       ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42510 +       ud->mmc = mmc;
42511 +       ud->pdata = pdata;
42512 +       ud->regs = (struct sdtio_vp_regs *)res_regs->start;
42513 +       ud->irq_tx = res_irq_tx->start;
42514 +       ud->irq_rx = res_irq_rx->start;
42515 +       platform_set_drvdata(pdev, mmc);
42516 +
42517 +       ret = request_irq(ud->irq_rx, ubicom32sd_interrupt, IRQF_DISABLED, mmc_hostname(mmc), mmc);
42518 +       if (ret) {
42519 +               goto fail_mmc;
42520 +       }
42521 +
42522 +       /*
42523 +        * Fill in the mmc structure
42524 +        */
42525 +       mmc->ops = &ubicom32sd_ops;
42526 +       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ |
42527 +                   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
42528 +
42529 +       mmc->f_min = ud->regs->f_min;
42530 +       mmc->f_max = ud->regs->f_max;
42531 +       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
42532 +
42533 +       /*
42534 +        * Setup some restrictions on transfers
42535 +        *
42536 +        * We allow up to SDTIO_MAX_SG_BLOCKS of data to DMA into, there are
42537 +        * not really any "max_seg_size", "max_req_size", or "max_blk_count"
42538 +        * restrictions (must be less than U32_MAX though), pick
42539 +        * something large?!...
42540 +        *
42541 +        * The hardware can do up to 4095 bytes per block, since the spec
42542 +        * only requires 2048, we'll set it to that and not worry about
42543 +        * potential weird blk lengths.
42544 +        */
42545 +       mmc->max_hw_segs = SDTIO_MAX_SG_BLOCKS;
42546 +       mmc->max_phys_segs = SDTIO_MAX_SG_BLOCKS;
42547 +       mmc->max_seg_size = 1024 * 1024;
42548 +       mmc->max_req_size = 1024 * 1024;
42549 +       mmc->max_blk_count = 1024;
42550 +
42551 +       mmc->max_blk_size = 2048;
42552 +
42553 +       ubicom32sd_reset(ud);
42554 +
42555 +       /*
42556 +        * enable interrupts
42557 +        */
42558 +       ud->int_en = 0;
42559 +       ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_SETUP_SDIO << SDTIO_COMMAND_SHIFT | SDTIO_COMMAND_FLAG_SDIO_INT_EN, 0);
42560 +
42561 +       mmc_add_host(mmc);
42562 +
42563 +       printk(KERN_INFO "%s at %p, irq %d/%d\n", mmc_hostname(mmc),
42564 +                       ud->regs, ud->irq_tx, ud->irq_rx);
42565 +       return 0;
42566 +
42567 +fail_mmc:
42568 +       gpio_free(pdata->cards[0].pin_pwr);
42569 +fail_pwr:
42570 +       gpio_free(pdata->cards[0].pin_cd);
42571 +fail_cd:
42572 +       gpio_free(pdata->cards[0].pin_wp);
42573 +fail:
42574 +       return ret;
42575 +}
42576 +
42577 +/*
42578 + * ubicom32sd_remove
42579 + */
42580 +static int __devexit ubicom32sd_remove(struct platform_device *pdev)
42581 +{
42582 +       struct mmc_host *mmc = platform_get_drvdata(pdev);
42583 +
42584 +       platform_set_drvdata(pdev, NULL);
42585 +
42586 +       if (mmc) {
42587 +               struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42588 +
42589 +               gpio_free(ud->pdata->cards[0].pin_pwr);
42590 +               gpio_free(ud->pdata->cards[0].pin_cd);
42591 +               gpio_free(ud->pdata->cards[0].pin_wp);
42592 +
42593 +               mmc_remove_host(mmc);
42594 +               mmc_free_host(mmc);
42595 +       }
42596 +
42597 +       /*
42598 +        * Note that our data is allocated as part of the mmc structure
42599 +        * so we don't need to free it.
42600 +        */
42601 +       return 0;
42602 +}
42603 +
42604 +static struct platform_driver ubicom32sd_driver = {
42605 +       .driver = {
42606 +               .name = DRIVER_NAME,
42607 +               .owner = THIS_MODULE,
42608 +       },
42609 +       .probe = ubicom32sd_probe,
42610 +       .remove = __devexit_p(ubicom32sd_remove),
42611 +#if 0
42612 +       .suspend = ubicom32sd_suspend,
42613 +       .resume = ubicom32sd_resume,
42614 +#endif
42615 +};
42616 +
42617 +/*
42618 + * ubicom32sd_init
42619 + */
42620 +static int __init ubicom32sd_init(void)
42621 +{
42622 +       return platform_driver_register(&ubicom32sd_driver);
42623 +}
42624 +module_init(ubicom32sd_init);
42625 +
42626 +/*
42627 + * ubicom32sd_exit
42628 + */
42629 +static void __exit ubicom32sd_exit(void)
42630 +{
42631 +    platform_driver_unregister(&ubicom32sd_driver);
42632 +}
42633 +module_exit(ubicom32sd_exit);
42634 +
42635 +MODULE_AUTHOR("Patrick Tjin");
42636 +MODULE_DESCRIPTION("Ubicom32 Secure Digital Host Controller Interface driver");
42637 +MODULE_LICENSE("GPL");
42638 diff -ruN linux-2.6.30.10/drivers/mtd/devices/Kconfig linux-2.6.30.10-ubi/drivers/mtd/devices/Kconfig
42639 --- linux-2.6.30.10/drivers/mtd/devices/Kconfig 2009-12-04 08:00:07.000000000 +0200
42640 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/Kconfig     2009-12-11 11:45:16.000000000 +0200
42641 @@ -104,6 +104,31 @@
42642         help
42643           This option enables FAST_READ access supported by ST M25Pxx.
42644  
42645 +config MTD_UBI32_NAND_SPI_ER
42646 +       tristate "UBI32_NAND SPI-ER support"
42647 +       help
42648 +         This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42649 +         using the built in flash controller on the Ubicom32 architecture.
42650 +         Partial page writes are not supported by this driver.
42651 +
42652 +config MTD_NAND_SPI_ER
42653 +       tristate "NAND SPI-ER support"
42654 +       help
42655 +         This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42656 +         using a generic SPI bus.  Partial page writes are supported
42657 +         by this driver.
42658 +
42659 +config MTD_UBI32_M25P80
42660 +       tristate "Ubicom processor support for most SPI Flash chips (AT26DF, M25P, W25X, ...)"
42661 +       depends on UBICOM32
42662 +       default y
42663 +       help
42664 +         This enables access to most modern SPI flash chips, used for
42665 +         program and data storage.   Series supported include Atmel AT26DF,
42666 +         Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X.  Other chips
42667 +         are supported as well.  See the driver source for the current list,
42668 +         or to add other chips.
42669 +
42670  config MTD_SLRAM
42671         tristate "Uncached system RAM"
42672         help
42673 diff -ruN linux-2.6.30.10/drivers/mtd/devices/Makefile linux-2.6.30.10-ubi/drivers/mtd/devices/Makefile
42674 --- linux-2.6.30.10/drivers/mtd/devices/Makefile        2009-12-04 08:00:07.000000000 +0200
42675 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/Makefile    2009-12-11 11:45:16.000000000 +0200
42676 @@ -16,3 +16,6 @@
42677  obj-$(CONFIG_MTD_BLOCK2MTD)    += block2mtd.o
42678  obj-$(CONFIG_MTD_DATAFLASH)    += mtd_dataflash.o
42679  obj-$(CONFIG_MTD_M25P80)       += m25p80.o
42680 +obj-$(CONFIG_MTD_UBI32_M25P80) += ubi32-m25p80.o
42681 +obj-$(CONFIG_MTD_NAND_SPI_ER)  += nand-spi-er.o
42682 +obj-$(CONFIG_MTD_UBI32_NAND_SPI_ER)    += ubi32-nand-spi-er.o
42683 diff -ruN linux-2.6.30.10/drivers/mtd/devices/nand-spi-er.c linux-2.6.30.10-ubi/drivers/mtd/devices/nand-spi-er.c
42684 --- linux-2.6.30.10/drivers/mtd/devices/nand-spi-er.c   1970-01-01 02:00:00.000000000 +0200
42685 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/nand-spi-er.c       2009-12-11 11:45:16.000000000 +0200
42686 @@ -0,0 +1,1017 @@
42687 +/*
42688 + * Micron SPI-ER NAND Flash Memory
42689 + *
42690 + * (C) Copyright 2009, Ubicom, Inc.
42691 + *
42692 + * This file is part of the Ubicom32 Linux Kernel Port.
42693 + *
42694 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
42695 + * it and/or modify it under the terms of the GNU General Public License
42696 + * as published by the Free Software Foundation, either version 2 of the
42697 + * License, or (at your option) any later version.
42698 + *
42699 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
42700 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
42701 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
42702 + * the GNU General Public License for more details.
42703 + *
42704 + * You should have received a copy of the GNU General Public License
42705 + * along with the Ubicom32 Linux Kernel Port.  If not,
42706 + * see <http://www.gnu.org/licenses/>.
42707 +*/
42708 +#include <linux/module.h>
42709 +#include <linux/init.h>
42710 +#include <linux/slab.h>
42711 +#include <linux/delay.h>
42712 +#include <linux/device.h>
42713 +#include <linux/mutex.h>
42714 +#include <linux/err.h>
42715 +
42716 +#include <linux/spi/spi.h>
42717 +#include <linux/spi/flash.h>
42718 +
42719 +#include <linux/mtd/mtd.h>
42720 +#include <linux/mtd/partitions.h>
42721 +
42722 +#define NAND_SPI_ER_BLOCK_FROM_ROW(row)                (row >> 6)
42723 +
42724 +#define NAND_SPI_ER_STATUS_P_FAIL              (1 << 3)
42725 +#define NAND_SPI_ER_STATUS_E_FAIL              (1 << 2)
42726 +#define NAND_SPI_ER_STATUS_OIP                 (1 << 0)
42727 +
42728 +#define NAND_SPI_ER_LAST_ROW_INVALID           0xFFFFFFFF
42729 +#define        NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET       0x08
42730 +
42731 +struct nand_spi_er_device {
42732 +       const char              *name;
42733 +
42734 +       uint8_t                 id0;
42735 +       uint8_t                 id1;
42736 +
42737 +       unsigned int            blocks;
42738 +       unsigned int            pages_per_block;
42739 +       unsigned int            page_size;
42740 +       unsigned int            write_size;
42741 +       unsigned int            erase_size;
42742 +};
42743 +
42744 +struct nand_spi_er {
42745 +       char                            name[24];
42746 +
42747 +       const struct nand_spi_er_device *device;
42748 +
42749 +       struct mutex                    lock;
42750 +       struct spi_device               *spi;
42751 +
42752 +       struct mtd_info                 mtd;
42753 +
42754 +       unsigned int                    last_row;       /* the last row we fetched */
42755 +
42756 +       /*
42757 +        * Bad block table (MUST be last in strcuture)
42758 +        */
42759 +       unsigned long                   nbb;
42760 +       unsigned long                   bbt[0];
42761 +};
42762 +
42763 +const struct nand_spi_er_device nand_spi_er_devices[] = {
42764 +       {
42765 +               name:                   "MT29F1G01ZDC",
42766 +               id0:                    0x2C,
42767 +               id1:                    0x12,
42768 +               blocks:                 1024,
42769 +               pages_per_block:        64,
42770 +               page_size:              2048,
42771 +               write_size:             512,
42772 +               erase_size:             64 * 2048,
42773 +       },
42774 +       {
42775 +               name:                   "MT29F1G01ZDC",
42776 +               id0:                    0x2C,
42777 +               id1:                    0x13,
42778 +               blocks:                 1024,
42779 +               pages_per_block:        64,
42780 +               page_size:              2048,
42781 +               write_size:             512,
42782 +               erase_size:             64 * 2048,
42783 +       },
42784 +};
42785 +
42786 +static int read_only = 0;
42787 +module_param(read_only, int, 0);
42788 +MODULE_PARM_DESC(read_only, "Leave device locked");
42789 +
42790 +/*
42791 + * nand_spi_er_get_feature
42792 + *     Get Feature register
42793 + */
42794 +static int nand_spi_er_get_feature(struct nand_spi_er *chip, int reg, uint8_t *data)
42795 +{
42796 +       uint8_t txbuf[2];
42797 +       uint8_t rxbuf[1];
42798 +       int res;
42799 +
42800 +       txbuf[0] = 0x0F;
42801 +       txbuf[1] = reg;
42802 +       res = spi_write_then_read(chip->spi, txbuf, 2, rxbuf, 1);
42803 +       if (res) {
42804 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed get feature res=%d\n", chip->name, res);
42805 +               return res;
42806 +       }
42807 +       *data = rxbuf[0];
42808 +       return 0;
42809 +}
42810 +
42811 +/*
42812 + * nand_spi_er_busywait
42813 + *     Wait until the chip is not busy
42814 + */
42815 +static int nand_spi_er_busywait(struct nand_spi_er *chip, uint8_t *data)
42816 +{
42817 +       int i;
42818 +
42819 +       for (i = 0; i < 100; i++) {
42820 +               int res = nand_spi_er_get_feature(chip, 0xC0, data);
42821 +               if (res) {
42822 +                       return res;
42823 +               }
42824 +               if (!(*data & NAND_SPI_ER_STATUS_OIP)) {
42825 +                       break;
42826 +               }
42827 +       }
42828 +
42829 +       return 0;
42830 +}
42831 +
42832 +/*
42833 + * nand_spi_er_erase
42834 + *     Erase a block, parameters must be block aligned
42835 + */
42836 +static int nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
42837 +{
42838 +       struct nand_spi_er *chip = mtd->priv;
42839 +       struct spi_device *spi = chip->spi;
42840 +       uint8_t txbuf[4];
42841 +       int res;
42842 +
42843 +       DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
42844 +
42845 +       if ((instr->addr + instr->len) > mtd->size) {
42846 +               return -EINVAL;
42847 +       }
42848 +
42849 +       if (instr->addr & (chip->device->erase_size - 1)) {
42850 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
42851 +               return -EINVAL;
42852 +       }
42853 +
42854 +       if (instr->len & (chip->device->erase_size - 1)) {
42855 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
42856 +               return -EINVAL;
42857 +       }
42858 +
42859 +       mutex_lock(&chip->lock);
42860 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42861 +
42862 +       while (instr->len) {
42863 +               uint32_t block = instr->addr >> 17;
42864 +               uint32_t row = block << 6;
42865 +               uint8_t stat;
42866 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
42867 +
42868 +               /*
42869 +                * Write enable
42870 +                */
42871 +               txbuf[0] = 0x06;
42872 +               res = spi_write(spi, txbuf, 1);
42873 +               if (res) {
42874 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
42875 +                       mutex_unlock(&chip->lock);
42876 +                       return res;
42877 +               }
42878 +
42879 +               /*
42880 +                * Test for bad block
42881 +                */
42882 +               if (test_bit(block, chip->bbt)) {
42883 +                       instr->fail_addr = block << 17;
42884 +                       instr->state = MTD_ERASE_FAILED;
42885 +                       res = -EBADMSG;
42886 +                       goto done;
42887 +               }
42888 +
42889 +               /*
42890 +                * Block erase
42891 +                */
42892 +               txbuf[0] = 0xD8;
42893 +               txbuf[1] = 0x00;
42894 +               txbuf[2] = row >> 8;
42895 +               txbuf[3] = row & 0xFF;
42896 +               res = spi_write(spi, txbuf, 4);
42897 +               if (res) {
42898 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed block erase res=%d\n", chip->name, res);
42899 +                       instr->fail_addr = block << 17;
42900 +                       instr->state = MTD_ERASE_FAILED;
42901 +                       goto done;
42902 +               }
42903 +
42904 +               /*
42905 +                * Wait
42906 +                */
42907 +               res = nand_spi_er_busywait(chip, &stat);
42908 +               if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42909 +                       instr->fail_addr = block << 17;
42910 +                       instr->state = MTD_ERASE_FAILED;
42911 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42912 +                       if (res) {
42913 +                               goto done;
42914 +                       }
42915 +
42916 +                       /*
42917 +                        * Chip is stuck?
42918 +                        */
42919 +                       res = -EIO;
42920 +                       goto done;
42921 +               }
42922 +
42923 +               /*
42924 +                * Check the status register
42925 +                */
42926 +               if (stat & NAND_SPI_ER_STATUS_E_FAIL) {
42927 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
42928 +                       instr->fail_addr = block << 17;
42929 +                       instr->state = MTD_ERASE_FAILED;
42930 +                       goto done;
42931 +               }
42932 +
42933 +               /*
42934 +                * Next
42935 +                */
42936 +               block++;
42937 +               instr->len -= chip->device->erase_size;
42938 +               instr->addr += chip->device->erase_size;
42939 +       }
42940 +
42941 +       instr->state = MTD_ERASE_DONE;
42942 +
42943 +       mutex_unlock(&chip->lock);
42944 +       return 0;
42945 +
42946 +done:
42947 +       /*
42948 +        * Write disable
42949 +        */
42950 +       txbuf[0] = 0x04;
42951 +       res = spi_write(spi, txbuf, 1);
42952 +       if (res) {
42953 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
42954 +       }
42955 +
42956 +       mutex_unlock(&chip->lock);
42957 +
42958 +       mtd_erase_callback(instr);
42959 +       return 0;
42960 +}
42961 +
42962 +/*
42963 + * nand_spi_er_read
42964 + *
42965 + * return -EUCLEAN: ecc error recovered
42966 + * return -EBADMSG: ecc error not recovered
42967 +*/
42968 +static int nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
42969 +                              size_t *retlen, u_char *buf)
42970 +{
42971 +       struct nand_spi_er *chip = mtd->priv;
42972 +       struct spi_device *spi = chip->spi;
42973 +
42974 +       uint32_t row;
42975 +       uint32_t column;
42976 +       int retval = 0;
42977 +
42978 +       *retlen = 0;
42979 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
42980 +
42981 +       /*
42982 +        * Zero length reads, nothing to do
42983 +        */
42984 +       if (len == 0) {
42985 +               return 0;
42986 +       }
42987 +
42988 +       /*
42989 +        * Reject reads which go over the end of the flash
42990 +        */
42991 +       if ((from + len) > mtd->size) {
42992 +               return -EINVAL;
42993 +       }
42994 +
42995 +       /*
42996 +        * Get the row and column address to start at
42997 +        */
42998 +       row = from >> 11;
42999 +       column = from & 0x7FF;
43000 +       DEBUG(MTD_DEBUG_LEVEL3, "%s: row=%x %d column=%x %d last_row=%x %d\n", chip->name, row, row, column, column, chip->last_row, chip->last_row);
43001 +
43002 +       /*
43003 +        * Read the data from the chip
43004 +        */
43005 +       mutex_lock(&chip->lock);
43006 +       while (len) {
43007 +               uint8_t stat;
43008 +               uint8_t txbuf[4];
43009 +               struct spi_message message;
43010 +               struct spi_transfer x[2];
43011 +               int res;
43012 +               size_t toread;
43013 +
43014 +               /*
43015 +                * Figure out how much to read
43016 +                *
43017 +                * If we are reading from the middle of a page then the most we
43018 +                * can read is to the end of the page
43019 +                */
43020 +               toread = len;
43021 +               if (toread > (chip->device->page_size - column)) {
43022 +                       toread = chip->device->page_size - column;
43023 +               }
43024 +
43025 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: buf=%p toread=%x row=%x column=%x last_row=%x\n", chip->name, buf, toread, row, column, chip->last_row);
43026 +
43027 +               if (chip->last_row != row) {
43028 +                       /*
43029 +                        * Check if the block is bad
43030 +                        */
43031 +                       if (test_bit(NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
43032 +                               mutex_unlock(&chip->lock);
43033 +                               return -EBADMSG;
43034 +                       }
43035 +
43036 +                       /*
43037 +                        * Load the appropriate page
43038 +                        */
43039 +                       txbuf[0] = 0x13;
43040 +                       txbuf[1] = 0x00;
43041 +                       txbuf[2] = row >> 8;
43042 +                       txbuf[3] = row & 0xFF;
43043 +                       res = spi_write(spi, txbuf, 4);
43044 +                       if (res) {
43045 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed page load res=%d\n", chip->name, res);
43046 +                               mutex_unlock(&chip->lock);
43047 +                               return res;
43048 +                       }
43049 +
43050 +                       /*
43051 +                        * Wait
43052 +                        */
43053 +                       res = nand_spi_er_busywait(chip, &stat);
43054 +                       if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43055 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43056 +                               if (res) {
43057 +                                       mutex_unlock(&chip->lock);
43058 +                                       return res;
43059 +                               }
43060 +
43061 +                               /*
43062 +                                * Chip is stuck?
43063 +                                */
43064 +                               mutex_unlock(&chip->lock);
43065 +                               return -EIO;
43066 +                       }
43067 +
43068 +                       /*
43069 +                        * Check the ECC bits
43070 +                        */
43071 +                       stat >>= 4;
43072 +                       if (stat == 1) {
43073 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
43074 +                               retval = -EUCLEAN;
43075 +                       }
43076 +                       if (stat == 2) {
43077 +                               DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
43078 +                               chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43079 +                               mutex_unlock(&chip->lock);
43080 +                               return -EBADMSG;
43081 +                       }
43082 +
43083 +               }
43084 +
43085 +               chip->last_row = row;
43086 +
43087 +               /*
43088 +                * Read out the data
43089 +                */
43090 +               spi_message_init(&message);
43091 +               memset(x, 0, sizeof(x));
43092 +
43093 +               txbuf[0] = 0x03;
43094 +               txbuf[1] = column >> 8;
43095 +               txbuf[2] = column & 0xFF;
43096 +               txbuf[3] = 0;
43097 +               x[0].tx_buf = txbuf;
43098 +               x[0].len = 4;
43099 +               spi_message_add_tail(&x[0], &message);
43100 +
43101 +               x[1].rx_buf = buf;
43102 +               x[1].len = toread;
43103 +               spi_message_add_tail(&x[1], &message);
43104 +
43105 +               res = spi_sync(spi, &message);
43106 +               if (res) {
43107 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed data read res=%d\n", chip->name, res);
43108 +                       mutex_unlock(&chip->lock);
43109 +                       return res;
43110 +               }
43111 +               buf += toread;
43112 +               len -= toread;
43113 +               *retlen += toread;
43114 +
43115 +               /*
43116 +                * For the next page, increment the row and always start at column 0
43117 +                */
43118 +               column = 0;
43119 +               row++;
43120 +       }
43121 +
43122 +       mutex_unlock(&chip->lock);
43123 +       return retval;
43124 +}
43125 +
43126 +/*
43127 + * nand_spi_er_write
43128 + */
43129 +#define NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
43130 +static int nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
43131 +                               size_t *retlen, const u_char *buf)
43132 +{
43133 +       struct nand_spi_er *chip = mtd->priv;
43134 +       struct spi_device *spi = chip->spi;
43135 +       const struct nand_spi_er_device *device = chip->device;
43136 +       uint32_t row;
43137 +       uint32_t col;
43138 +       uint8_t txbuf[4];
43139 +       int res;
43140 +       size_t towrite;
43141 +
43142 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
43143 +
43144 +       *retlen = 0;
43145 +
43146 +       /*
43147 +        * nothing to write
43148 +        */
43149 +       if (!len) {
43150 +               return 0;
43151 +       }
43152 +
43153 +       /*
43154 +        * Reject writes which go over the end of the flash
43155 +        */
43156 +       if ((to + len) > mtd->size) {
43157 +               return -EINVAL;
43158 +       }
43159 +
43160 +       /*
43161 +        * Check to see if everything is page aligned
43162 +        */
43163 +       if (NOT_ALIGNED(to) || NOT_ALIGNED(len)) {
43164 +               printk(KERN_NOTICE "nand_spi_er_write: Attempt to write non page aligned data\n");
43165 +               return -EINVAL;
43166 +       }
43167 +
43168 +       mutex_lock(&chip->lock);
43169 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43170 +
43171 +       /*
43172 +        * If the first write is a partial write then write at most the number of
43173 +        * bytes to get us page aligned and then the remainder will be
43174 +        * page aligned.  The last bit may be a partial page as well.
43175 +        */
43176 +       col = to & (device->page_size - 1);
43177 +       towrite = device->page_size - col;
43178 +       if (towrite > len) {
43179 +               towrite = len;
43180 +       }
43181 +
43182 +       /*
43183 +        * Write the data
43184 +        */
43185 +       row = to >> 11;
43186 +       while (len) {
43187 +               struct spi_message message;
43188 +               struct spi_transfer x[2];
43189 +               uint8_t stat;
43190 +
43191 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
43192 +
43193 +               /*
43194 +                * Write enable
43195 +                */
43196 +               txbuf[0] = 0x06;
43197 +               res = spi_write(spi, txbuf, 1);
43198 +               if (res) {
43199 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
43200 +                       mutex_unlock(&chip->lock);
43201 +                       return res;
43202 +               }
43203 +
43204 +               /*
43205 +                * Write the data into the cache
43206 +                */
43207 +               spi_message_init(&message);
43208 +               memset(x, 0, sizeof(x));
43209 +               txbuf[0] = 0x02;
43210 +               txbuf[1] = col >> 8;
43211 +               txbuf[2] = col & 0xFF;
43212 +               x[0].tx_buf = txbuf;
43213 +               x[0].len = 3;
43214 +               spi_message_add_tail(&x[0], &message);
43215 +               x[1].tx_buf = buf;
43216 +               x[1].len = towrite;
43217 +               spi_message_add_tail(&x[1], &message);
43218 +               res = spi_sync(spi, &message);
43219 +               if (res) {
43220 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed cache write res=%d\n", chip->name, res);
43221 +                       goto done;
43222 +               }
43223 +
43224 +               /*
43225 +                * Program execute
43226 +                */
43227 +               txbuf[0] = 0x10;
43228 +               txbuf[1] = 0x00;
43229 +               txbuf[2] = row >> 8;
43230 +               txbuf[3] = row & 0xFF;
43231 +               res = spi_write(spi, txbuf, 4);
43232 +               if (res) {
43233 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed prog execute res=%d\n", chip->name, res);
43234 +                       goto done;
43235 +               }
43236 +
43237 +               /*
43238 +                * Wait
43239 +                */
43240 +               res = nand_spi_er_busywait(chip, &stat);
43241 +               if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43242 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43243 +                       if (res) {
43244 +                               goto done;
43245 +                       }
43246 +
43247 +                       /*
43248 +                        * Chip is stuck?
43249 +                        */
43250 +                       res = -EIO;
43251 +                       goto done;
43252 +               }
43253 +
43254 +               if (stat & (1 << 3)) {
43255 +                       res = -EBADMSG;
43256 +                       goto done;
43257 +               }
43258 +
43259 +               row++;
43260 +               buf += towrite;
43261 +               len -= towrite;
43262 +               *retlen += towrite;
43263 +
43264 +               /*
43265 +                * At this point, we are always page aligned so start at column 0.
43266 +                * Note we may not have a full page to write at the end, hence the
43267 +                * check if towrite > len.
43268 +                */
43269 +               col = 0;
43270 +               towrite = device->page_size;
43271 +               if (towrite > len) {
43272 +                       towrite = len;
43273 +               }
43274 +       }
43275 +
43276 +       mutex_unlock(&chip->lock);
43277 +       return res;
43278 +
43279 +done:
43280 +       /*
43281 +        * Write disable
43282 +        */
43283 +       txbuf[0] = 0x04;
43284 +       res = spi_write(spi, txbuf, 1);
43285 +       if (res) {
43286 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43287 +       }
43288 +
43289 +       mutex_unlock(&chip->lock);
43290 +
43291 +       return res;
43292 +}
43293 +
43294 +/*
43295 + * nand_spi_er_isbad
43296 + */
43297 +static int nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
43298 +{
43299 +       struct nand_spi_er *chip = mtd->priv;
43300 +       uint32_t block;
43301 +
43302 +       if (ofs & (chip->device->erase_size - 1)) {
43303 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43304 +               return -EINVAL;
43305 +       }
43306 +
43307 +       block = ofs >> 17;
43308 +
43309 +       return test_bit(block, chip->bbt);
43310 +}
43311 +
43312 +/*
43313 + * nand_spi_er_markbad
43314 + */
43315 +static int nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
43316 +{
43317 +       struct nand_spi_er *chip = mtd->priv;
43318 +       struct spi_device *spi = chip->spi;
43319 +       uint32_t block;
43320 +       uint32_t row;
43321 +       uint8_t txbuf[7];
43322 +       int res;
43323 +       uint8_t stat;
43324 +
43325 +       if (ofs & (chip->device->erase_size - 1)) {
43326 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43327 +               return -EINVAL;
43328 +       }
43329 +
43330 +       block = ofs >> 17;
43331 +
43332 +       /*
43333 +        * If it's already marked bad, no need to mark it
43334 +        */
43335 +       if (test_bit(block, chip->bbt)) {
43336 +               return 0;
43337 +       }
43338 +
43339 +       /*
43340 +        * Mark it in our cache
43341 +        */
43342 +       __set_bit(block, chip->bbt);
43343 +
43344 +       /*
43345 +        * Write the user bad block mark.  If it fails, then we really
43346 +        * can't do anything about it.
43347 +        */
43348 +       mutex_lock(&chip->lock);
43349 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43350 +
43351 +       /*
43352 +        * Write enable
43353 +        */
43354 +       txbuf[0] = 0x06;
43355 +       res = spi_write(spi, txbuf, 1);
43356 +       if (res) {
43357 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
43358 +               mutex_unlock(&chip->lock);
43359 +               return res;
43360 +       }
43361 +
43362 +       /*
43363 +        * Write the mark
43364 +        */
43365 +       txbuf[0] = 0x84;
43366 +       txbuf[1] = 0x08;
43367 +       txbuf[2] = NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET;
43368 +       txbuf[3] = 0xde;
43369 +       txbuf[4] = 0xad;
43370 +       txbuf[5] = 0xbe;
43371 +       txbuf[6] = 0xef;
43372 +       res = spi_write(spi, txbuf, 7);
43373 +       if (res) {
43374 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write mark res=%d\n", chip->name, res);
43375 +               goto done;
43376 +       }
43377 +
43378 +       /*
43379 +        * Program execute
43380 +        */
43381 +       row = ofs >> 11;
43382 +       txbuf[0] = 0x10;
43383 +       txbuf[1] = 0x00;
43384 +       txbuf[2] = row >> 8;
43385 +       txbuf[3] = row & 0xFF;
43386 +       res = spi_write(spi, txbuf, 4);
43387 +       if (res) {
43388 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed program execute res=%d\n", chip->name, res);
43389 +               goto done;
43390 +       }
43391 +
43392 +       /*
43393 +        * Wait
43394 +        */
43395 +       res = nand_spi_er_busywait(chip, &stat);
43396 +       if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43397 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43398 +               if (res) {
43399 +                       goto done;
43400 +               }
43401 +
43402 +               /*
43403 +                * Chip is stuck?
43404 +                */
43405 +               res = -EIO;
43406 +               goto done;
43407 +       }
43408 +
43409 +       if (stat & (1 << 3)) {
43410 +               res = -EBADMSG;
43411 +       }
43412 +
43413 +done:
43414 +       /*
43415 +        * Write disable
43416 +        */
43417 +       txbuf[0] = 0x04;
43418 +       res = spi_write(spi, txbuf, 1);
43419 +       if (res) {
43420 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43421 +       }
43422 +
43423 +       mutex_unlock(&chip->lock);
43424 +
43425 +       return res;
43426 +}
43427 +
43428 +/*
43429 + * nand_spi_er_read_bbt
43430 + */
43431 +static int nand_spi_er_read_bbt(struct nand_spi_er *chip)
43432 +{
43433 +       int j;
43434 +       for (j = 0; j < chip->device->blocks; j++) {
43435 +               uint8_t txbuf[4];
43436 +               uint8_t rxbuf[16];
43437 +               uint32_t bbmark;
43438 +               int res;
43439 +               unsigned short row = j << 6;
43440 +               uint8_t stat;
43441 +
43442 +               /*
43443 +                * Read Page
43444 +                */
43445 +               txbuf[0] = 0x13;
43446 +               txbuf[1] = 0x00;
43447 +               txbuf[2] = row >> 8;
43448 +               txbuf[3] = row & 0xFF;
43449 +               res = spi_write(chip->spi, txbuf, 4);
43450 +               if (res) {
43451 +                       return res;
43452 +               }
43453 +
43454 +               /*
43455 +                * Wait
43456 +                */
43457 +               res = nand_spi_er_busywait(chip, &stat);
43458 +               if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43459 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43460 +                       if (res) {
43461 +                               return res;
43462 +                       }
43463 +
43464 +                       /*
43465 +                        * Chip is stuck?
43466 +                        */
43467 +                       return -EIO;
43468 +               }
43469 +
43470 +               /*
43471 +                * Check factory bad block mark
43472 +                */
43473 +               txbuf[0] = 0x03;
43474 +               txbuf[1] = 0x08;
43475 +               txbuf[2] = 0x00;
43476 +               txbuf[3] = 0x00;
43477 +               res = spi_write_then_read(chip->spi, txbuf, 4, rxbuf, 16);
43478 +               if (res) {
43479 +                       return res;
43480 +               }
43481 +               if (rxbuf[0] != 0xFF) {
43482 +                       chip->nbb++;
43483 +                       __set_bit(j, chip->bbt);
43484 +                       continue;
43485 +               }
43486 +
43487 +               memcpy(&bbmark, &rxbuf[8], 4);
43488 +               if (bbmark == 0xdeadbeef) {
43489 +                       chip->nbb++;
43490 +                       __set_bit(j, chip->bbt);
43491 +               }
43492 +       }
43493 +
43494 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
43495 +       printk("%s: Bad Block Table:", chip->name);
43496 +       for (j = 0; j < chip->device->blocks; j++) {
43497 +               if ((j % 64) == 0) {
43498 +                       printk("\n%s: block %03x: ", chip->name, j);
43499 +               }
43500 +               printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
43501 +       }
43502 +       printk("\n%s: Bad Block Numbers: ", chip->name);
43503 +       for (j = 0; j < chip->device->blocks; j++) {
43504 +               if (test_bit(j, chip->bbt)) {
43505 +                       printk("%x ", j);
43506 +               }
43507 +       }
43508 +       printk("\n");
43509 +#endif
43510 +
43511 +       return 0;
43512 +}
43513 +
43514 +#ifndef MODULE
43515 +/*
43516 + * Called at boot time:
43517 + *
43518 + * nand_spi_er=read_only
43519 + *     if read_only specified then do not unlock device
43520 + */
43521 +static int __init nand_spi_er_setup(char *str)
43522 +{
43523 +       if (str && (strncasecmp(str, "read_only", 9) == 0)) {
43524 +               read_only = 1;
43525 +       }
43526 +       return 0;
43527 +}
43528 +
43529 +__setup("nand_spi_er=", nand_spi_er_setup);
43530 +#endif
43531 +
43532 +/*
43533 + * nand_spi_er_probe
43534 + *     Detect and initialize nand_spi_er device.
43535 + */
43536 +static int __devinit nand_spi_er_probe(struct spi_device *spi)
43537 +{
43538 +       uint8_t txbuf[3];
43539 +       uint8_t rxbuf[2];
43540 +       int i;
43541 +       int res;
43542 +       size_t bbt_bytes;
43543 +       struct nand_spi_er *chip;
43544 +       const struct nand_spi_er_device *device;
43545 +
43546 +       res = spi_setup(spi);
43547 +       if (res) {
43548 +               return res;
43549 +       }
43550 +
43551 +       /*
43552 +        * Reset
43553 +        */
43554 +       for (i = 0; i < 2; i++) {
43555 +               txbuf[0] = 0xFF;
43556 +               res = spi_write(spi, txbuf, 1);
43557 +               if (res) {
43558 +                       return res;
43559 +               }
43560 +               udelay(250);
43561 +       }
43562 +       udelay(1000);
43563 +
43564 +       /*
43565 +        * Read ID
43566 +        */
43567 +       txbuf[0] = 0x9F;
43568 +       txbuf[1] = 0x00;
43569 +       res = spi_write_then_read(spi, txbuf, 2, rxbuf, 2);
43570 +       if (res) {
43571 +               return res;
43572 +       }
43573 +
43574 +       device = nand_spi_er_devices;
43575 +       for (i = 0; i < ARRAY_SIZE(nand_spi_er_devices); i++) {
43576 +               if ((device->id0 == rxbuf[0]) && (device->id1 == rxbuf[1])) {
43577 +                       break;
43578 +               }
43579 +               device++;
43580 +       }
43581 +       if (i == ARRAY_SIZE(nand_spi_er_devices)) {
43582 +               return -ENODEV;
43583 +       }
43584 +
43585 +       /*
43586 +        * Initialize our chip structure
43587 +        */
43588 +       bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
43589 +       chip = kzalloc(sizeof(struct nand_spi_er) + bbt_bytes, GFP_KERNEL);
43590 +       if (!chip) {
43591 +               return -ENOMEM;
43592 +       }
43593 +       snprintf(chip->name, sizeof(chip->name), "%s.%d.%d", device->name, spi->master->bus_num, spi->chip_select);
43594 +
43595 +       chip->spi = spi;
43596 +       chip->device = device;
43597 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43598 +
43599 +       mutex_init(&chip->lock);
43600 +
43601 +       chip->mtd.type = MTD_NANDFLASH;
43602 +       chip->mtd.flags = MTD_WRITEABLE;
43603 +
43604 +       /*
43605 +        * #blocks * block size * n blocks
43606 +        */
43607 +       chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
43608 +       chip->mtd.erasesize = device->erase_size;
43609 +
43610 +       /*
43611 +        * 1 page, optionally we can support partial write (512)
43612 +        */
43613 +       chip->mtd.writesize = device->write_size;
43614 +       chip->mtd.name = device->name;
43615 +       chip->mtd.erase = nand_spi_er_erase;
43616 +       chip->mtd.read = nand_spi_er_read;
43617 +       chip->mtd.write = nand_spi_er_write;
43618 +       chip->mtd.block_isbad = nand_spi_er_isbad;
43619 +       chip->mtd.block_markbad = nand_spi_er_markbad;
43620 +       chip->mtd.priv = chip;
43621 +
43622 +       /*
43623 +        * Cache the bad block table
43624 +        */
43625 +       res = nand_spi_er_read_bbt(chip);
43626 +       if (res) {
43627 +               kfree(chip);
43628 +               return res;
43629 +       }
43630 +
43631 +       /*
43632 +        * Un/lock the chip
43633 +        */
43634 +       txbuf[0] = 0x1F;
43635 +       txbuf[1] = 0xA0;
43636 +       if (read_only) {
43637 +               txbuf[2] = 0x38;
43638 +       } else {
43639 +               txbuf[2] = 0x00;
43640 +       }
43641 +       res = spi_write(spi, txbuf, 3);
43642 +       if (res) {
43643 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed lock operation res=%d\n", chip->name, res);
43644 +               mutex_unlock(&chip->lock);
43645 +               return res;
43646 +       }
43647 +
43648 +       spi_set_drvdata(spi, chip);
43649 +
43650 +       printk(KERN_INFO "%s: added device %s size: %u KBytes %u bad blocks %s\n", spi->dev.bus_id, chip->mtd.name, DIV_ROUND_UP(chip->mtd.size, 1024), chip->nbb, read_only ? "[read only]" : "");
43651 +       return add_mtd_device(&chip->mtd);
43652 +}
43653 +
43654 +/*
43655 + * nand_spi_er_remove
43656 + */
43657 +static int __devexit nand_spi_er_remove(struct spi_device *spi)
43658 +{
43659 +       struct nand_spi_er *chip = spi_get_drvdata(spi);
43660 +       int status = 0;
43661 +
43662 +       DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
43663 +       status = del_mtd_device(&chip->mtd);
43664 +       if (status == 0)
43665 +               kfree(chip);
43666 +       return status;
43667 +}
43668 +
43669 +static struct spi_driver nand_spi_er_driver = {
43670 +       .driver = {
43671 +               .name           = "nand-spi-er",
43672 +               .bus            = &spi_bus_type,
43673 +               .owner          = THIS_MODULE,
43674 +       },
43675 +
43676 +       .probe          = nand_spi_er_probe,
43677 +       .remove         = __devexit_p(nand_spi_er_remove),
43678 +
43679 +       /* FIXME:  investigate suspend and resume... */
43680 +};
43681 +
43682 +/*
43683 + * nand_spi_er_init
43684 + */
43685 +static int __init nand_spi_er_init(void)
43686 +{
43687 +       return spi_register_driver(&nand_spi_er_driver);
43688 +}
43689 +module_init(nand_spi_er_init);
43690 +
43691 +/*
43692 + * nand_spi_er_exit
43693 + */
43694 +static void __exit nand_spi_er_exit(void)
43695 +{
43696 +       spi_unregister_driver(&nand_spi_er_driver);
43697 +}
43698 +module_exit(nand_spi_er_exit);
43699 +
43700 +
43701 +MODULE_LICENSE("GPL");
43702 +MODULE_AUTHOR("Patrick Tjin");
43703 +MODULE_DESCRIPTION("MTD nand_spi_er driver");
43704 diff -ruN linux-2.6.30.10/drivers/mtd/devices/ubi32-m25p80.c linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-m25p80.c
43705 --- linux-2.6.30.10/drivers/mtd/devices/ubi32-m25p80.c  1970-01-01 02:00:00.000000000 +0200
43706 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-m25p80.c      2009-12-11 11:45:16.000000000 +0200
43707 @@ -0,0 +1,1066 @@
43708 +/*
43709 + * drivers/mtd/devices/ubi32-m25p80.c
43710 + *   NOR flash driver, Ubicom processor internal SPI flash interface.
43711 + *
43712 + *   This code instantiates the serial flash that contains the
43713 + *   original bootcode.  The serial flash start at address 0x60000000
43714 + *   in both Ubicom32V3 and Ubicom32V4 ISAs.
43715 + *
43716 + *   This piece of flash is made to appear as a Memory Technology
43717 + *   Device (MTD) with this driver to allow Read/Write/Erase operations.
43718 + *
43719 + * (C) Copyright 2009, Ubicom, Inc.
43720 + *
43721 + * This file is part of the Ubicom32 Linux Kernel Port.
43722 + *
43723 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
43724 + * it and/or modify it under the terms of the GNU General Public License
43725 + * as published by the Free Software Foundation, either version 2 of the
43726 + * License, or (at your option) any later version.
43727 + *
43728 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
43729 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
43730 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
43731 + * the GNU General Public License for more details.
43732 + *
43733 + * You should have received a copy of the GNU General Public License
43734 + * along with the Ubicom32 Linux Kernel Port.  If not,
43735 + * see <http://www.gnu.org/licenses/>.
43736 + *
43737 + * Ubicom32 implementation derived from (with many thanks):
43738 + *   arch/m68knommu
43739 + *   arch/blackfin
43740 + *   arch/parisc
43741 + */
43742 +#include <linux/types.h>
43743 +#include <linux/device.h>
43744 +#include <linux/platform_device.h>
43745 +#include <linux/mtd/mtd.h>
43746 +#include <linux/mtd/partitions.h>
43747 +#include <linux/mtd/physmap.h>
43748 +#include <linux/spi/spi.h>
43749 +#include <linux/spi/flash.h>
43750 +
43751 +#include <linux/init.h>
43752 +#include <linux/module.h>
43753 +#include <linux/interrupt.h>
43754 +#include <linux/mutex.h>
43755 +
43756 +#include <asm/ip5000.h>
43757 +#include <asm/devtree.h>
43758 +
43759 +#define UBICOM32_FLASH_BASE    0x60000000
43760 +#define UBICOM32_FLASH_MAX_SIZE 0x01000000
43761 +#define UBICOM32_FLASH_START   0x00000000
43762 +#define UBICOM32_KERNEL_OFFSET 0x00010000 /* The kernel starts after Ubicom
43763 +                                           * .protect section. */
43764 +
43765 +static struct mtd_partition ubicom32_flash_partitions[] = {
43766 +       {
43767 +               .name   = "Bootloader",         /* Protected Section
43768 +                                                * Partition */
43769 +               .size   = 0x10000,
43770 +               .offset = UBICOM32_FLASH_START,
43771 +//             .mask_flags = MTD_WRITEABLE     /* Mark Read-only */
43772 +       },
43773 +       {
43774 +               .name   = "Kernel",             /* Kernel Partition. */
43775 +               .size   = 0,                    /* this will be set up during
43776 +                                                * probe stage. At that time we
43777 +                                                * will know end of linux image
43778 +                                                * in flash. */
43779 +               .offset = MTDPART_OFS_APPEND,   /* Starts right after Protected
43780 +                                                * section. */
43781 +//             .mask_flags = MTD_WRITEABLE     /* Mark Read-only */
43782 +       },
43783 +       {
43784 +               .name   = "Rest",               /* Rest of the flash. */
43785 +               .size   = 0x200000,             /* Use up what remains in the
43786 +                                                * flash. */
43787 +               .offset = MTDPART_OFS_NXTBLK,   /* Starts right after Protected
43788 +                                                * section. */
43789 +       }
43790 +};
43791 +
43792 +static struct flash_platform_data ubicom32_flash_data = {
43793 +       .name = "ubicom32_boot_flash",
43794 +       .parts = ubicom32_flash_partitions,
43795 +       .nr_parts = ARRAY_SIZE(ubicom32_flash_partitions),
43796 +};
43797 +
43798 +static struct resource ubicom32_flash_resource[] = {
43799 +       {
43800 +               .start  = UBICOM32_FLASH_BASE,
43801 +               .end    = UBICOM32_FLASH_BASE +
43802 +               UBICOM32_FLASH_MAX_SIZE - 1,
43803 +               .flags  = IORESOURCE_MEM,
43804 +       },
43805 +};
43806 +
43807 +static struct platform_device ubicom32_flash_device = {
43808 +       .name = "ubicom32flashdriver",
43809 +       .id = 0, /* Bus number */
43810 +       .num_resources = ARRAY_SIZE(ubicom32_flash_resource),
43811 +       .resource = ubicom32_flash_resource,
43812 +       .dev = {
43813 +               .platform_data = &ubicom32_flash_data,
43814 +       },
43815 +};
43816 +
43817 +static struct platform_device *ubicom32_flash_devices[] = {
43818 +       &ubicom32_flash_device,
43819 +};
43820 +
43821 +static int __init ubicom32_flash_init(void)
43822 +{
43823 +       printk(KERN_INFO "%s(): registering device resources\n",
43824 +              __FUNCTION__);
43825 +       platform_add_devices(ubicom32_flash_devices,
43826 +                            ARRAY_SIZE(ubicom32_flash_devices));
43827 +       return 0;
43828 +}
43829 +
43830 +arch_initcall(ubicom32_flash_init);
43831 +
43832 +/*
43833 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips through
43834 + * Ubicom32 SPI controller.
43835 + *
43836 + * Author: Mike Lavender, mike@steroidmicros.com
43837 + *
43838 + * Copyright (c) 2005, Intec Automation Inc.
43839 + *
43840 + * Some parts are based on lart.c by Abraham Van Der Merwe
43841 + *
43842 + * Cleaned up and generalized based on mtd_dataflash.c
43843 + *
43844 + * This code is free software; you can redistribute it and/or modify
43845 + * it under the terms of the GNU General Public License version 2 as
43846 + * published by the Free Software Foundation.
43847 + *
43848 + */
43849 +
43850 +#define FLASH_PAGESIZE         256
43851 +
43852 +/* Flash opcodes. */
43853 +#define        OPCODE_WREN             0x06    /* Write enable */
43854 +#define        OPCODE_RDSR             0x05    /* Read status register */
43855 +#define        OPCODE_READ             0x03    /* Read data bytes (low frequency) */
43856 +#define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
43857 +#define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
43858 +#define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
43859 +#define        OPCODE_BE_32K           0x52    /* Erase 32KiB block */
43860 +#define        OPCODE_SE               0xd8    /* Sector erase (usually 64KiB) */
43861 +#define        OPCODE_RDID             0x9f    /* Read JEDEC ID */
43862 +
43863 +/* Status Register bits. */
43864 +#define        SR_WIP                  1       /* Write in progress */
43865 +#define        SR_WEL                  2       /* Write enable latch */
43866 +/* meaning of other SR_* bits may differ between vendors */
43867 +#define        SR_BP0                  4       /* Block protect 0 */
43868 +#define        SR_BP1                  8       /* Block protect 1 */
43869 +#define        SR_BP2                  0x10    /* Block protect 2 */
43870 +#define        SR_SRWD                 0x80    /* SR write protect */
43871 +
43872 +/* Define max times to check status register before we give up. */
43873 +#define        MAX_READY_WAIT_COUNT    100000
43874 +
43875 +
43876 +#ifdef CONFIG_MTD_PARTITIONS
43877 +#define        mtd_has_partitions()    (1)
43878 +#else
43879 +#define        mtd_has_partitions()    (0)
43880 +#endif
43881 +
43882 +/*
43883 + * Ubicom32 FLASH Command Set
43884 + */
43885 +#define FLASH_FC_INST_CMD      0x00    /* for SPI command only transaction */
43886 +#define FLASH_FC_INST_WR       0x01    /* for SPI write transaction */
43887 +#define FLASH_FC_INST_RD       0x02    /* for SPI read transaction */
43888 +
43889 +#define ALIGN_DOWN(v, a) ((v) & ~((a) - 1))
43890 +#define ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1))
43891 +
43892 +#define        FLASH_COMMAND_KICK_OFF(io)                                                      \
43893 +       asm volatile(                                                                   \
43894 +       "       bset    "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)")   \n\t"   \
43895 +       "       jmpt.t  .+4                                                     \n\t"   \
43896 +       "       bset    "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)")  \n\t"   \
43897 +               :                                                                       \
43898 +               : "a" (io)                                                              \
43899 +               : "memory", "cc"                                                        \
43900 +       );
43901 +
43902 +#define        FLASH_COMMAND_WAIT_FOR_COMPLETION(io)                                           \
43903 +       asm volatile(                                                                   \
43904 +       "       btst    "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)")    \n\t"   \
43905 +       "       jmpeq.f .-4                                                     \n\t"   \
43906 +               :                                                                       \
43907 +               : "a" (io)                                                              \
43908 +               : "memory", "cc"                                                                        \
43909 +       );
43910 +
43911 +#define        FLASH_COMMAND_EXEC(io)                                                          \
43912 +       FLASH_COMMAND_KICK_OFF(io)                                                      \
43913 +       FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
43914 +
43915 +
43916 +#define OSC1_FREQ 12000000
43917 +#define TEN_MICRO_SECONDS (OSC1_FREQ * 10 / 1000000)
43918 +
43919 +/*
43920 + * We will have to eventually replace this null definition with the real thing.
43921 + */
43922 +#define WATCHDOG_RESET()
43923 +
43924 +#define EXTFLASH_WRITE_FIFO_SIZE 32
43925 +#define EXTFLASH_WRITE_BLOCK_SIZE EXTFLASH_WRITE_FIFO_SIZE /* limit the size to
43926 +                                                           * FIFO capacity, so
43927 +                                                           * the thread can be
43928 +                                                           * suspended. */
43929 +
43930 +#define JFFS2_FILESYSTEM_SIZE 0x100000
43931 +
43932 +/****************************************************************************/
43933 +
43934 +struct m25p {
43935 +       struct platform_device  *plt_dev;
43936 +       struct mutex            lock;
43937 +       struct mtd_info         mtd;
43938 +       unsigned                partitioned:1;
43939 +       u8                      erase_opcode;
43940 +       u8                      command[4];
43941 +};
43942 +
43943 +static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
43944 +{
43945 +       return container_of(mtd, struct m25p, mtd);
43946 +}
43947 +
43948 +/****************************************************************************/
43949 +
43950 +/*
43951 + * Internal helper functions
43952 + */
43953 +
43954 +/*
43955 + * Read the status register, returning its value in the location
43956 + * Return the status register value.
43957 + * Returns negative if error occurred.
43958 + */
43959 +static int read_sr(struct m25p *flash)
43960 +{
43961 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43962 +
43963 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
43964 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43965 +               IO_XFL_CTL1_FC_DATA(1);
43966 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
43967 +       FLASH_COMMAND_EXEC(io);
43968 +
43969 +       return io->status1 & 0xff;
43970 +}
43971 +
43972 +/*
43973 + * mem_flash_io_read_u32()
43974 + */
43975 +static u32 mem_flash_io_read_u32(u32 addr)
43976 +{
43977 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43978 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
43979 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43980 +               IO_XFL_CTL1_FC_DATA(4) | IO_XFL_CTL1_FC_DUMMY(1) |
43981 +               IO_XFL_CTL1_FC_ADDR;
43982 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_FAST_READ) |
43983 +               IO_XFL_CTL2_FC_ADDR(addr);
43984 +       FLASH_COMMAND_EXEC(io);
43985 +       return io->status1;
43986 +}
43987 +
43988 +/*
43989 + * mem_flash_read_u8()
43990 + */
43991 +static u8 mem_flash_read_u8(u32 addr)
43992 +{
43993 +       u32 tmp_addr = ALIGN_DOWN(addr, 4);
43994 +       u32 tmp_data = mem_flash_io_read_u32(tmp_addr);
43995 +       u8 *ptr = (u8 *)&tmp_data;
43996 +       return ptr[addr & 0x3];
43997 +}
43998 +
43999 +/*
44000 + * mem_flash_read()
44001 + *     No need to lock as read is implemented with ireads (same as normal flash
44002 + *     execution).
44003 + */
44004 +static void mem_flash_read(u32 addr, void *dst, size_t length)
44005 +{
44006 +       /*
44007 +        * Range check
44008 +        */
44009 +       /*
44010 +        * Fix source alignment.
44011 +        */
44012 +       while (addr & 0x03) {
44013 +               if (length == 0) {
44014 +                       return;
44015 +               }
44016 +               *((u8 *)dst) = mem_flash_read_u8(addr++);
44017 +               dst++;
44018 +               length--;
44019 +       }
44020 +
44021 +       while (length >= 4) {
44022 +               u32 tmp_data = mem_flash_io_read_u32(addr);
44023 +               addr += 4;
44024 +               length -= 4;
44025 +
44026 +               /*
44027 +                * Send the data to the destination.
44028 +                */
44029 +               memcpy((void *)dst, (void *)&tmp_data, 4);
44030 +               dst += 4;
44031 +       }
44032 +
44033 +       while (length--) {
44034 +               *((u8 *)dst) = mem_flash_read_u8(addr++);
44035 +               dst++;
44036 +       }
44037 +}
44038 +
44039 +/*
44040 + * mem_flash_wait_until_complete()
44041 + */
44042 +static void mem_flash_wait_until_complete(void)
44043 +{
44044 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44045 +
44046 +       do {
44047 +               /*
44048 +                * Put a delay here to deal with flash programming problem.
44049 +                */
44050 +               u32 mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
44051 +               while (UBICOM32_IO_TIMER->mptval < mptval)
44052 +                       ;
44053 +
44054 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
44055 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
44056 +                       IO_XFL_CTL1_FC_DATA(1);
44057 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
44058 +               FLASH_COMMAND_EXEC(io);
44059 +       } while (io->status1 & SR_WIP);
44060 +}
44061 +
44062 +/*
44063 + * mem_flash_write_next()
44064 + */
44065 +static size_t mem_flash_write_next(u32 addr, u8 *buf, size_t length)
44066 +{
44067 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44068 +       u32 data_start = addr;
44069 +       u32 data_end = addr + length;
44070 +       size_t count;
44071 +       u32 i, j;
44072 +
44073 +       /*
44074 +        * Top limit address.
44075 +        */
44076 +       u32 block_start = ALIGN_DOWN(data_start, 4);
44077 +       u32 block_end = block_start + EXTFLASH_WRITE_BLOCK_SIZE;
44078 +
44079 +       union {
44080 +               u8 byte[EXTFLASH_WRITE_BLOCK_SIZE];
44081 +               u32 word[EXTFLASH_WRITE_BLOCK_SIZE / 4];
44082 +       } write_buf;
44083 +
44084 +       u32 *flash_addr = (u32 *)block_start;
44085 +
44086 +       /*
44087 +        * The write block must be limited by FLASH internal buffer.
44088 +        */
44089 +       u32 block_end_align = ALIGN_DOWN(block_end, 256);
44090 +       bool write_needed;
44091 +
44092 +       block_end = (block_end_align > block_start)
44093 +               ? block_end_align : block_end;
44094 +       data_end = (data_end <= block_end) ? data_end : block_end;
44095 +       block_end = ALIGN_UP(data_end, 4);
44096 +       count = data_end - data_start;
44097 +
44098 +       /*
44099 +        * Transfer data to a buffer.
44100 +        */
44101 +       for (i = 0; i < (block_end - block_start) / 4; i++) {
44102 +               /*
44103 +                * The FLASH read can hold D-cache for a long time.
44104 +                * Use I/O operation to read FLASH to avoid starving other
44105 +                * threads, especially HRT.  (Do this for application only)
44106 +                */
44107 +               write_buf.word[i] = mem_flash_io_read_u32(
44108 +                       (u32)(&flash_addr[i]));
44109 +       }
44110 +
44111 +       write_needed = false;
44112 +       for (i = 0, j = (data_start - block_start);
44113 +            i < (data_end - data_start); i++, j++) {
44114 +               write_needed = write_needed || (write_buf.byte[j] != buf[i]);
44115 +               write_buf.byte[j] &= buf[i];
44116 +       }
44117 +
44118 +
44119 +       /*
44120 +        * If the data in FLASH is identical to what to be written. Then skip
44121 +        * it.
44122 +        */
44123 +       if (write_needed) {
44124 +               /*
44125 +                * Write to flash.
44126 +                */
44127 +               void *tmp __attribute__((unused));
44128 +               s32 extra_words;
44129 +
44130 +               asm volatile(
44131 +               "       move.4  %0, %2                                                                  \n\t"
44132 +               "       bset    "D(IO_INT_SET)"(%1), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")        \n\t"
44133 +               "       pipe_flush 0                                                                    \n\t"
44134 +               "       .rept   "D(EXTFLASH_WRITE_FIFO_SIZE / 4)"                                       \n\t"
44135 +               "       move.4  "D(IO_TX_FIFO)"(%1), (%0)4++                                            \n\t"
44136 +               "       .endr                                                                           \n\t"
44137 +                       : "=&a" (tmp)
44138 +                       : "a" (io), "r" (&write_buf.word[0])
44139 +                       : "memory", "cc"
44140 +               );
44141 +
44142 +               /* Lock FLASH for write access. */
44143 +               io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
44144 +
44145 +               /* Command: WREN */
44146 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
44147 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44148 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
44149 +               FLASH_COMMAND_EXEC(io);
44150 +
44151 +               /* Command: BYTE PROGRAM */
44152 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
44153 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) |
44154 +                       IO_XFL_CTL1_FC_DATA(block_end - block_start) |
44155 +                       IO_XFL_CTL1_FC_ADDR;
44156 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_PP) |
44157 +                       IO_XFL_CTL2_FC_ADDR(block_start);
44158 +               FLASH_COMMAND_KICK_OFF(io);
44159 +
44160 +               extra_words = (s32)(block_end - block_start -
44161 +                                   EXTFLASH_WRITE_FIFO_SIZE) / 4;
44162 +               if (extra_words > 0) {
44163 +                       asm volatile(
44164 +                       "       move.4          %0, %3                          \n\t"
44165 +                       "1:     cmpi            "D(IO_FIFO_LEVEL)"(%1), #4      \n\t"
44166 +                       "       jmpgt.s.t       1b                              \n\t"
44167 +                       "       move.4          "D(IO_TX_FIFO)"(%1), (%0)4++    \n\t"
44168 +                       "       add.4           %2, #-1, %2                     \n\t"
44169 +                       "       jmpgt.t         1b                              \n\t"
44170 +                               : "=&a" (tmp)
44171 +                               : "a" (io), "d" (extra_words),
44172 +                                 "r" (&write_buf.word[EXTFLASH_WRITE_FIFO_SIZE / 4])
44173 +                               : "memory", "cc"
44174 +                       );
44175 +               }
44176 +               FLASH_COMMAND_WAIT_FOR_COMPLETION(io);
44177 +
44178 +               mem_flash_wait_until_complete();
44179 +
44180 +
44181 +               /* Unlock FLASH for cache access. */
44182 +               io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
44183 +       }
44184 +
44185 +       /*
44186 +        * Complete.
44187 +        */
44188 +       return count;
44189 +}
44190 +
44191 +/*
44192 + * mem_flash_write()
44193 + */
44194 +static void mem_flash_write(u32 addr, const void *src, size_t length)
44195 +{
44196 +       /*
44197 +        * Write data
44198 +        */
44199 +       u8_t *ptr = (u8_t *)src;
44200 +       while (length) {
44201 +               size_t count = mem_flash_write_next(addr, ptr, length);
44202 +               addr += count;
44203 +               ptr += count;
44204 +               length -= count;
44205 +       }
44206 +}
44207 +
44208 +/*
44209 + * Service routine to read status register until ready, or timeout occurs.
44210 + * Returns non-zero if error.
44211 + */
44212 +static int wait_till_ready(struct m25p *flash)
44213 +{
44214 +       int count;
44215 +       int sr;
44216 +
44217 +       /* one chip guarantees max 5 msec wait here after page writes,
44218 +        * but potentially three seconds (!) after page erase.
44219 +        */
44220 +       for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
44221 +               u32 mptval;
44222 +               sr = read_sr(flash);
44223 +               if (sr < 0)
44224 +                       break;
44225 +               else if (!(sr & SR_WIP))
44226 +                       return 0;
44227 +
44228 +               /*
44229 +                * Put a 10us delay here to deal with flash programming problem.
44230 +                */
44231 +               mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
44232 +               while ((s32)(mptval - UBICOM32_IO_TIMER->mptval) > 0) {
44233 +                       WATCHDOG_RESET();
44234 +               }
44235 +               /* REVISIT sometimes sleeping would be best */
44236 +       }
44237 +
44238 +       return 1;
44239 +}
44240 +
44241 +/*
44242 + * mem_flash_erase_page()
44243 + */
44244 +static void mem_flash_erase_page(u32 addr)
44245 +{
44246 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44247 +
44248 +       /* Lock FLASH for write access. */
44249 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
44250 +
44251 +       /* Command: WREN */
44252 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44253 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44254 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
44255 +       FLASH_COMMAND_EXEC(io);
44256 +
44257 +       /* Command: ERASE */
44258 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44259 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) |
44260 +               IO_XFL_CTL1_FC_ADDR;
44261 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_SE) |
44262 +               IO_XFL_CTL2_FC_ADDR(addr);
44263 +       FLASH_COMMAND_EXEC(io);
44264 +
44265 +       mem_flash_wait_until_complete();
44266 +
44267 +       /* Unlock FLASH for cache access. */
44268 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
44269 +}
44270 +
44271 +/*
44272 + * mem_flash_erase()
44273 + */
44274 +static u32 mem_flash_erase(u32 addr, u32 length)
44275 +{
44276 +       /*
44277 +        * Calculate the endaddress to be the first address of the page
44278 +        * just beyond this erase section of pages.
44279 +        */
44280 +       u32 endaddr = addr + length;
44281 +
44282 +       /*
44283 +        * Erase.
44284 +        */
44285 +       while (addr < endaddr) {
44286 +               u32 test_addr = addr;
44287 +               mem_flash_erase_page(addr);
44288 +
44289 +               /*
44290 +                * Test how much was erased as actual flash page at this address
44291 +                * may be smaller than the expected page size.
44292 +                */
44293 +               while (test_addr < endaddr) {
44294 +                       /*
44295 +                        * The FLASH read can hold D-cache for a long time.  Use
44296 +                        * I/O operation to read FLASH to avoid starving other
44297 +                        * threads, especially HRT.  (Do this for application
44298 +                        * only)
44299 +                        */
44300 +                       if (mem_flash_io_read_u32(test_addr) != 0xFFFFFFFF) {
44301 +                               break;
44302 +                       }
44303 +                       test_addr += 4;
44304 +               }
44305 +               if (test_addr == addr) {
44306 +                       printk("erase failed at address 0x%x, skipping",
44307 +                              test_addr);
44308 +                       test_addr += 4;
44309 +                       return 1;
44310 +               }
44311 +               addr = test_addr;
44312 +       }
44313 +       return 0;
44314 +}
44315 +
44316 +
44317 +/****************************************************************************/
44318 +
44319 +/*
44320 + * MTD implementation
44321 + */
44322 +
44323 +/*
44324 + * Erase an address range on the flash chip.  The address range may extend
44325 + * one or more erase sectors.  Return an error is there is a problem erasing.
44326 + */
44327 +static int ubicom32_flash_driver_erase(struct mtd_info *mtd,
44328 +                                      struct erase_info *instr)
44329 +{
44330 +       struct m25p *flash = mtd_to_m25p(mtd);
44331 +       u32 addr, len;
44332 +
44333 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %lld\n",
44334 +             dev_name(&flash->plt_dev->dev), __FUNCTION__, "at",
44335 +             (u32)instr->addr, instr->len);
44336 +
44337 +       /* sanity checks */
44338 +       if (instr->addr + instr->len > flash->mtd.size)
44339 +               return -EINVAL;
44340 +       if ((instr->addr % mtd->erasesize) != 0
44341 +                       || (instr->len % mtd->erasesize) != 0) {
44342 +               return -EINVAL;
44343 +       }
44344 +
44345 +       addr = instr->addr + UBICOM32_FLASH_BASE;
44346 +       len = instr->len;
44347 +
44348 +       mutex_lock(&flash->lock);
44349 +
44350 +       /* REVISIT in some cases we could speed up erasing large regions
44351 +        * by using OPCODE_SE instead of OPCODE_BE_4K
44352 +        */
44353 +
44354 +       /* now erase those sectors */
44355 +       if (mem_flash_erase(addr, len)) {
44356 +               instr->state = MTD_ERASE_FAILED;
44357 +               mutex_unlock(&flash->lock);
44358 +               return -EIO;
44359 +       }
44360 +
44361 +       mutex_unlock(&flash->lock);
44362 +       instr->state = MTD_ERASE_DONE;
44363 +       mtd_erase_callback(instr);
44364 +       return 0;
44365 +}
44366 +
44367 +/*
44368 + * Read an address range from the flash chip.  The address range
44369 + * may be any size provided it is within the physical boundaries.
44370 + */
44371 +static int ubicom32_flash_driver_read(struct mtd_info *mtd, loff_t from,
44372 +                                     size_t len, size_t *retlen, u_char *buf)
44373 +{
44374 +       struct m25p *flash = mtd_to_m25p(mtd);
44375 +       u32 base_addr = UBICOM32_FLASH_BASE + from;
44376 +
44377 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44378 +             dev_name(&flash->plt_dev->dev), __FUNCTION__, "from",
44379 +             (u32)from, len);
44380 +
44381 +       /* sanity checks */
44382 +       if (!len)
44383 +               return 0;
44384 +
44385 +       if (from + len > flash->mtd.size)
44386 +               return -EINVAL;
44387 +
44388 +       /* Byte count starts at zero. */
44389 +       if (retlen)
44390 +               *retlen = 0;
44391 +
44392 +       mutex_lock(&flash->lock);
44393 +
44394 +       /* Wait till previous write/erase is done. */
44395 +       if (wait_till_ready(flash)) {
44396 +               /* REVISIT status return?? */
44397 +               mutex_unlock(&flash->lock);
44398 +               return 1;
44399 +       }
44400 +
44401 +       mem_flash_read(base_addr, (void *)buf, len);
44402 +
44403 +       if (retlen)
44404 +               *retlen = len;
44405 +
44406 +       mutex_unlock(&flash->lock);
44407 +
44408 +       return 0;
44409 +}
44410 +
44411 +/*
44412 + * Write an address range to the flash chip.  Data must be written in
44413 + * FLASH_PAGESIZE chunks.  The address range may be any size provided
44414 + * it is within the physical boundaries.
44415 + */
44416 +static int ubicom32_flash_driver_write(struct mtd_info *mtd, loff_t to,
44417 +                                      size_t len, size_t *retlen,
44418 +                                      const u_char *buf)
44419 +{
44420 +       struct m25p *flash = mtd_to_m25p(mtd);
44421 +       u32 base_addr = UBICOM32_FLASH_BASE + to;
44422 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44423 +             dev_name(&flash->plt_dev->dev), __FUNCTION__, "to",
44424 +             (u32)to, len);
44425 +
44426 +       if (retlen)
44427 +               *retlen = 0;
44428 +
44429 +       /* sanity checks */
44430 +       if (!len)
44431 +               return 0;
44432 +
44433 +       if (to + len > flash->mtd.size)
44434 +               return -EINVAL;
44435 +
44436 +       mutex_lock(&flash->lock);
44437 +
44438 +       mem_flash_write(base_addr, (void *) buf, len);
44439 +
44440 +       /* Wait until finished previous write command. */
44441 +       if (wait_till_ready(flash)) {
44442 +               mutex_unlock(&flash->lock);
44443 +               return 1;
44444 +       }
44445 +
44446 +       if (retlen)
44447 +               *retlen = len;
44448 +
44449 +       mutex_unlock(&flash->lock);
44450 +       return 0;
44451 +}
44452 +
44453 +
44454 +/****************************************************************************/
44455 +
44456 +/*
44457 + * SPI device driver setup and teardown
44458 + */
44459 +
44460 +struct flash_info {
44461 +       char            *name;
44462 +
44463 +       /* JEDEC id zero means "no ID" (most older chips); otherwise it has
44464 +        * a high byte of zero plus three data bytes: the manufacturer id,
44465 +        * then a two byte device id.
44466 +        */
44467 +       u32             jedec_id;
44468 +
44469 +       /* The size listed here is what works with OPCODE_SE, which isn't
44470 +        * necessarily called a "sector" by the vendor.
44471 +        */
44472 +       unsigned        sector_size;
44473 +       u16             n_sectors;
44474 +
44475 +       u16             flags;
44476 +#define        SECT_4K         0x01            /* OPCODE_BE_4K works uniformly */
44477 +};
44478 +
44479 +
44480 +/* NOTE: double check command sets and memory organization when you add
44481 + * more flash chips.  This current list focusses on newer chips, which
44482 + * have been converging on command sets which including JEDEC ID.
44483 + */
44484 +static struct flash_info __devinitdata m25p_data[] = {
44485 +
44486 +       /* Atmel -- some are (confusingly) marketed as "DataFlash" */
44487 +       { "at25fs010",  0x1f6601, 32 * 1024, 4, SECT_4K, },
44488 +       { "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },
44489 +
44490 +       { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
44491 +
44492 +       { "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
44493 +       { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
44494 +       { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
44495 +       { "at26df321",  0x1f4701, 64 * 1024, 64, SECT_4K, },
44496 +
44497 +       /* Spansion -- single (large) sector size only, at least
44498 +        * for the chips listed here (without boot sectors).
44499 +        */
44500 +       { "s25sl004a", 0x010212, 64 * 1024, 8, },
44501 +       { "s25sl008a", 0x010213, 64 * 1024, 16, },
44502 +       { "s25sl016a", 0x010214, 64 * 1024, 32, },
44503 +       { "s25sl032a", 0x010215, 64 * 1024, 64, },
44504 +       { "s25sl064a", 0x010216, 64 * 1024, 128, },
44505 +
44506 +       /* SST -- large erase sizes are "overlays", "sectors" are 4K */
44507 +       { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
44508 +       { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
44509 +       { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
44510 +       { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
44511 +
44512 +       /* ST Microelectronics -- newer production may have feature updates */
44513 +       { "m25p05",  0x202010,  32 * 1024, 2, },
44514 +       { "m25p10",  0x202011,  32 * 1024, 4, },
44515 +       { "m25p20",  0x202012,  64 * 1024, 4, },
44516 +       { "m25p40",  0x202013,  64 * 1024, 8, },
44517 +       { "m25p80",         0,  64 * 1024, 16, },
44518 +       { "m25p16",  0x202015,  64 * 1024, 32, },
44519 +       { "m25p32",  0x202016,  64 * 1024, 64, },
44520 +       { "m25p64",  0x202017,  64 * 1024, 128, },
44521 +       { "m25p128", 0x202018, 256 * 1024, 64, },
44522 +
44523 +       { "m45pe80", 0x204014,  64 * 1024, 16, },
44524 +       { "m45pe16", 0x204015,  64 * 1024, 32, },
44525 +
44526 +       { "m25pe80", 0x208014,  64 * 1024, 16, },
44527 +       { "m25pe16", 0x208015,  64 * 1024, 32, SECT_4K, },
44528 +
44529 +       /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
44530 +       { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
44531 +       { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
44532 +       { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
44533 +       { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
44534 +       { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
44535 +       { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
44536 +       { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
44537 +
44538 +       /* Macronix -- mx25lxxx */
44539 +       { "mx25l32",  0xc22016, 64 * 1024,  64, },
44540 +       { "mx25l64",  0xc22017, 64 * 1024, 128, },
44541 +       { "mx25l128", 0xc22018, 64 * 1024, 256, },
44542 +
44543 +};
44544 +
44545 +struct flash_info *__devinit jedec_probe(struct platform_device *spi)
44546 +{
44547 +       int                     tmp;
44548 +       u32                     jedec;
44549 +       struct flash_info       *info;
44550 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44551 +
44552 +       /*
44553 +        * Setup and run RDID command on the flash.
44554 +        */
44555 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44556 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
44557 +               IO_XFL_CTL1_FC_DATA(3);
44558 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDID);
44559 +       FLASH_COMMAND_EXEC(io);
44560 +
44561 +       jedec = io->status1 & 0x00ffffff;
44562 +
44563 +       for (tmp = 0, info = m25p_data;
44564 +                       tmp < ARRAY_SIZE(m25p_data);
44565 +                       tmp++, info++) {
44566 +               if (info->jedec_id == jedec)
44567 +                       return info;
44568 +       }
44569 +       dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
44570 +       return NULL;
44571 +}
44572 +
44573 +
44574 +/*
44575 + * board specific setup should have ensured the SPI clock used here
44576 + * matches what the READ command supports, at least until this driver
44577 + * understands FAST_READ (for clocks over 25 MHz).
44578 + */
44579 +static int __devinit ubicom32_flash_probe(struct platform_device *spi)
44580 +{
44581 +       struct flash_platform_data      *data;
44582 +       struct m25p                     *flash;
44583 +       struct flash_info               *info;
44584 +       unsigned                        i;
44585 +
44586 +       /* Platform data helps sort out which chip type we have, as
44587 +        * well as how this board partitions it.  If we don't have
44588 +        * a chip ID, try the JEDEC id commands; they'll work for most
44589 +        * newer chips, even if we don't recognize the particular chip.
44590 +        */
44591 +       data = spi->dev.platform_data;
44592 +       if (data && data->type) {
44593 +               for (i = 0, info = m25p_data;
44594 +                               i < ARRAY_SIZE(m25p_data);
44595 +                               i++, info++) {
44596 +                       if (strcmp(data->type, info->name) == 0)
44597 +                               break;
44598 +               }
44599 +
44600 +               /* unrecognized chip? */
44601 +               if (i == ARRAY_SIZE(m25p_data)) {
44602 +                       DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
44603 +                             dev_name(&spi->dev), data->type);
44604 +                       info = NULL;
44605 +
44606 +               /* recognized; is that chip really what's there? */
44607 +               } else if (info->jedec_id) {
44608 +                       struct flash_info       *chip = jedec_probe(spi);
44609 +
44610 +                       if (!chip || chip != info) {
44611 +                               dev_warn(&spi->dev, "found %s, expected %s\n",
44612 +                                               chip ? chip->name : "UNKNOWN",
44613 +                                               info->name);
44614 +                               info = NULL;
44615 +                       }
44616 +               }
44617 +       } else
44618 +               info = jedec_probe(spi);
44619 +
44620 +       if (!info)
44621 +               return -ENODEV;
44622 +
44623 +       flash = kzalloc(sizeof *flash, GFP_KERNEL);
44624 +       if (!flash)
44625 +               return -ENOMEM;
44626 +
44627 +       flash->plt_dev = spi;
44628 +       mutex_init(&flash->lock);
44629 +       dev_set_drvdata(&spi->dev, flash);
44630 +
44631 +       if (data && data->name)
44632 +               flash->mtd.name = data->name;
44633 +       else
44634 +               flash->mtd.name = dev_name(&spi->dev);
44635 +
44636 +       flash->mtd.type = MTD_NORFLASH;
44637 +       flash->mtd.writesize = 1;
44638 +       flash->mtd.flags = MTD_CAP_NORFLASH;
44639 +       flash->mtd.size = info->sector_size * info->n_sectors;
44640 +       flash->mtd.erase = ubicom32_flash_driver_erase;
44641 +       flash->mtd.read = ubicom32_flash_driver_read;
44642 +       flash->mtd.write = ubicom32_flash_driver_write;
44643 +
44644 +       /* prefer "small sector" erase if possible */
44645 +       /*
44646 +        * The Ubicom erase code does not use the opcode for smaller sectors,
44647 +        * so disable that functionality and keep erasesize == sector_size
44648 +        * so that the test in ubicom32_flash_driver_erase works properly.
44649 +        *
44650 +        * This was: `if (info->flags & SECT_4K) {' instead of `if (0) {'
44651 +        */
44652 +       if (0) {
44653 +               flash->erase_opcode = OPCODE_BE_4K;
44654 +               flash->mtd.erasesize = 4096;
44655 +       } else {
44656 +               flash->erase_opcode = OPCODE_SE;
44657 +               flash->mtd.erasesize = info->sector_size;
44658 +       }
44659 +
44660 +       dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
44661 +                flash->mtd.size / 1024);
44662 +
44663 +       DEBUG(MTD_DEBUG_LEVEL2,
44664 +               "mtd .name = %s, .size = 0x%.8llx (%lluMiB) "
44665 +                       ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
44666 +               flash->mtd.name,
44667 +               flash->mtd.size, flash->mtd.size / (1024*1024),
44668 +               flash->mtd.erasesize, flash->mtd.erasesize / 1024,
44669 +               flash->mtd.numeraseregions);
44670 +
44671 +       if (flash->mtd.numeraseregions)
44672 +               for (i = 0; i < flash->mtd.numeraseregions; i++)
44673 +                       DEBUG(MTD_DEBUG_LEVEL2,
44674 +                               "mtd.eraseregions[%d] = { .offset = 0x%.8llx, "
44675 +                               ".erasesize = 0x%.8x (%uKiB), "
44676 +                               ".numblocks = %d }\n",
44677 +                               i, flash->mtd.eraseregions[i].offset,
44678 +                               flash->mtd.eraseregions[i].erasesize,
44679 +                               flash->mtd.eraseregions[i].erasesize / 1024,
44680 +                               flash->mtd.eraseregions[i].numblocks);
44681 +
44682 +
44683 +       /* partitions should match sector boundaries; and it may be good to
44684 +        * use readonly partitions for writeprotected sectors (BP2..BP0).
44685 +        */
44686 +       if (mtd_has_partitions()) {
44687 +               struct mtd_partition    *parts = NULL;
44688 +               int                     nr_parts = 0;
44689 +
44690 +#ifdef CONFIG_MTD_CMDLINE_PARTS
44691 +               static const char *part_probes[] = { "cmdlinepart", NULL, };
44692 +
44693 +               nr_parts = parse_mtd_partitions(&flash->mtd,
44694 +                               part_probes, &parts, 0);
44695 +#endif
44696 +
44697 +               if (nr_parts <= 0 && data && data->parts) {
44698 +                       parts = data->parts;
44699 +                       nr_parts = data->nr_parts;
44700 +                       if (nr_parts >= 2) {
44701 +                               /*
44702 +                                * Set last partition size to be 1M.
44703 +                                */
44704 +                               parts[1].size = flash->mtd.size -
44705 +                                       parts[0].size - JFFS2_FILESYSTEM_SIZE;
44706 +                               parts[2].size = JFFS2_FILESYSTEM_SIZE;
44707 +                       }
44708 +               }
44709 +
44710 +               if (nr_parts > 0) {
44711 +                       for (i = 0; i < nr_parts; i++) {
44712 +                               DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
44713 +                                       "{.name = %s, .offset = 0x%.8llx, "
44714 +                                               ".size = 0x%.8llx (%lluKiB) }\n",
44715 +                                       i, parts[i].name,
44716 +                                       parts[i].offset,
44717 +                                       parts[i].size,
44718 +                                       parts[i].size / 1024);
44719 +                       }
44720 +                       flash->partitioned = 1;
44721 +                       return add_mtd_partitions(&flash->mtd, parts, nr_parts);
44722 +               }
44723 +       } else if (data->nr_parts)
44724 +               dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
44725 +                               data->nr_parts, data->name);
44726 +
44727 +       return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
44728 +}
44729 +
44730 +
44731 +static int __devexit ubicom32_flash_remove(struct spi_device *spi)
44732 +{
44733 +       struct m25p     *flash = dev_get_drvdata(&spi->dev);
44734 +       int             status;
44735 +
44736 +       /* Clean up MTD stuff. */
44737 +       if (mtd_has_partitions() && flash->partitioned)
44738 +               status = del_mtd_partitions(&flash->mtd);
44739 +       else
44740 +               status = del_mtd_device(&flash->mtd);
44741 +       if (status == 0)
44742 +               kfree(flash);
44743 +       return 0;
44744 +}
44745 +
44746 +static struct platform_driver ubicom32_flash_driver = {
44747 +       .driver = {
44748 +               .name   = "ubicom32flashdriver",
44749 +               .bus    = &platform_bus_type,
44750 +               .owner  = THIS_MODULE,
44751 +       },
44752 +       .probe  = ubicom32_flash_probe,
44753 +       .remove = NULL,
44754 +};
44755 +
44756 +static int ubicom32_flash_driver_init(void)
44757 +{
44758 +       return platform_driver_register(&ubicom32_flash_driver);
44759 +}
44760 +
44761 +
44762 +static void ubicom32_flash_driver_exit(void)
44763 +{
44764 +       platform_driver_unregister(&ubicom32_flash_driver);
44765 +}
44766 +
44767 +
44768 +module_init(ubicom32_flash_driver_init);
44769 +module_exit(ubicom32_flash_driver_exit);
44770 +
44771 +MODULE_LICENSE("GPL");
44772 +MODULE_AUTHOR("Mike Lavender");
44773 +MODULE_DESCRIPTION("Ubicom32 MTD SPI driver for ST M25Pxx flash chips");
44774 diff -ruN linux-2.6.30.10/drivers/mtd/devices/ubi32-nand-spi-er.c linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-nand-spi-er.c
44775 --- linux-2.6.30.10/drivers/mtd/devices/ubi32-nand-spi-er.c     1970-01-01 02:00:00.000000000 +0200
44776 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-nand-spi-er.c 2009-12-11 11:45:16.000000000 +0200
44777 @@ -0,0 +1,1188 @@
44778 +/*
44779 + * Micron SPI-ER NAND Flash Memory
44780 + *     This code uses the built in Ubicom flash controller
44781 + *
44782 + * (C) Copyright 2009, Ubicom, Inc.
44783 + *
44784 + * This file is part of the Ubicom32 Linux Kernel Port.
44785 + *
44786 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
44787 + * it and/or modify it under the terms of the GNU General Public License
44788 + * as published by the Free Software Foundation, either version 2 of the
44789 + * License, or (at your option) any later version.
44790 + *
44791 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
44792 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
44793 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
44794 + * the GNU General Public License for more details.
44795 + *
44796 + * You should have received a copy of the GNU General Public License
44797 + * along with the Ubicom32 Linux Kernel Port.  If not,
44798 + * see <http://www.gnu.org/licenses/>.
44799 +*/
44800 +#include <linux/module.h>
44801 +#include <linux/init.h>
44802 +#include <linux/slab.h>
44803 +#include <linux/delay.h>
44804 +#include <linux/device.h>
44805 +#include <linux/platform_device.h>
44806 +#include <linux/mutex.h>
44807 +#include <linux/err.h>
44808 +
44809 +#include <linux/mtd/mtd.h>
44810 +#include <linux/mtd/partitions.h>
44811 +
44812 +#define DRIVER_NAME                            "ubi32-nand-spi-er"
44813 +#define UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row)  (row >> 6)
44814 +
44815 +#define UBI32_NAND_SPI_ER_STATUS_P_FAIL                (1 << 3)
44816 +#define UBI32_NAND_SPI_ER_STATUS_E_FAIL                (1 << 2)
44817 +#define UBI32_NAND_SPI_ER_STATUS_OIP           (1 << 0)
44818 +
44819 +#define UBI32_NAND_SPI_ER_LAST_ROW_INVALID     0xFFFFFFFF
44820 +#define        UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET 0x08
44821 +
44822 +struct ubi32_nand_spi_er_device {
44823 +       const char              *name;
44824 +
44825 +       uint16_t                id;
44826 +
44827 +       unsigned int            blocks;
44828 +       unsigned int            pages_per_block;
44829 +       unsigned int            page_size;
44830 +       unsigned int            write_size;
44831 +       unsigned int            erase_size;
44832 +};
44833 +
44834 +struct ubi32_nand_spi_er {
44835 +       char                            name[24];
44836 +
44837 +       const struct ubi32_nand_spi_er_device   *device;
44838 +
44839 +       struct mutex                    lock;
44840 +       struct platform_device          *pdev;
44841 +
44842 +       struct mtd_info                 mtd;
44843 +
44844 +       unsigned int                    last_row;       /* the last row we fetched */
44845 +
44846 +       /*
44847 +        * Bad block table (MUST be last in strcuture)
44848 +        */
44849 +       unsigned long                   nbb;
44850 +       unsigned long                   bbt[0];
44851 +};
44852 +
44853 +/*
44854 + * Chip supports a write_size of 512, but we cannot do partial
44855 + * page with command 0x84.
44856 + *
44857 + * We need to use command 0x84 because we cannot fill the FIFO fast
44858 + * enough to transfer the whole 512 bytes at a time. (maybe through
44859 + * OCM?)
44860 + */
44861 +const struct ubi32_nand_spi_er_device ubi32_nand_spi_er_devices[] = {
44862 +       {
44863 +               name:                   "MT29F1G01ZDC",
44864 +               id:                     0x2C12,
44865 +               blocks:                 1024,
44866 +               pages_per_block:        64,
44867 +               page_size:              2048,
44868 +               write_size:             2048,
44869 +               erase_size:             64 * 2048,
44870 +       },
44871 +       {
44872 +               name:                   "MT29F1G01ZDC",
44873 +               id:                     0x2C13,
44874 +               blocks:                 1024,
44875 +               pages_per_block:        64,
44876 +               page_size:              2048,
44877 +               write_size:             2048,
44878 +               erase_size:             64 * 2048,
44879 +       },
44880 +};
44881 +
44882 +static int read_only = 0;
44883 +module_param(read_only, int, 0);
44884 +MODULE_PARM_DESC(read_only, "Leave device locked");
44885 +
44886 +/*
44887 + * Ubicom32 FLASH Command Set
44888 + */
44889 +#define FLASH_PORT             RA
44890 +
44891 +#define FLASH_FC_INST_CMD      0x00    /* for SPI command only transaction */
44892 +#define FLASH_FC_INST_WR       0x01    /* for SPI write transaction */
44893 +#define FLASH_FC_INST_RD       0x02    /* for SPI read transaction */
44894 +
44895 +#define FLASH_COMMAND_KICK_OFF(io)                                                             \
44896 +       asm volatile(                                                                           \
44897 +               "       bset    "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)")   \n\t"   \
44898 +               "       jmpt.t  .+4                                                     \n\t"   \
44899 +               "       bset    "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)")  \n\t"   \
44900 +               :                                                                               \
44901 +               : "a" (io)                                                                      \
44902 +               : "cc"                                                                          \
44903 +               );
44904 +
44905 +#define FLASH_COMMAND_WAIT_FOR_COMPLETION(io)                                                  \
44906 +       asm volatile(                                                                           \
44907 +               "       btst    "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)")    \n\t"   \
44908 +               "       jmpeq.f .-4                                                     \n\t"   \
44909 +               :                                                                               \
44910 +               : "a" (io)                                                                      \
44911 +               : "cc"                                                                          \
44912 +       );
44913 +
44914 +#define FLASH_COMMAND_EXEC(io)                         \
44915 +               FLASH_COMMAND_KICK_OFF(io)              \
44916 +               FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
44917 +
44918 +/*
44919 + * ubi32_nand_spi_er_get_feature
44920 + *     Get Feature register
44921 + */
44922 +static uint8_t ubi32_nand_spi_er_get_feature(uint32_t reg)
44923 +{
44924 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44925 +
44926 +       /*
44927 +        * Note that this will produce the sequence:
44928 +        *      SI [0F][REG][00][00]
44929 +        *      SO ---------[SR][SR][SR]
44930 +        * Since the flash controller can only output 24 bits of address, this is
44931 +        * ok for this command since the data will just repeat as long as the CS
44932 +        * is asserted and the clock is running.
44933 +        */
44934 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44935 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(1) |
44936 +                   IO_XFL_CTL1_FC_ADDR;
44937 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x0F) | IO_XFL_CTL2_FC_ADDR(reg << 16);
44938 +       FLASH_COMMAND_EXEC(io);
44939 +
44940 +       return io->status1 & 0xFF;
44941 +}
44942 +
44943 +/*
44944 + * ubi32_nand_spi_er_write_buf
44945 + *     writes a buffer to the bus
44946 + *
44947 + * Writes 511 + 1 bytes to the bus, we have to stuff one data byte into the address.
44948 + */
44949 +static void ubi32_nand_spi_er_write_buf(const uint8_t *buf, uint32_t col)
44950 +{
44951 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44952 +       uint32_t tmp;
44953 +
44954 +       asm volatile (
44955 +               "       bset            "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")   \n\t"
44956 +               "       pipe_flush      0                                                                       \n\t"
44957 +               :
44958 +               : [port] "a" (FLASH_PORT)
44959 +               : "cc"
44960 +       );
44961 +
44962 +       /*
44963 +        * Write the data into the cache
44964 +        */
44965 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44966 +#ifdef SUPPORT_512_FIFO
44967 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(511) |
44968 +#endif
44969 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(31) |
44970 +                   IO_XFL_CTL1_FC_ADDR;
44971 +
44972 +       /*
44973 +        * Construct the address with the first byte of data
44974 +        */
44975 +       tmp = (col << 8) | *buf++;
44976 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84) | IO_XFL_CTL2_FC_ADDR(tmp);
44977 +
44978 +       asm volatile (
44979 +
44980 +               /*
44981 +                * Move 32 bytes
44982 +                *
44983 +                * The first word needs to be [11][22][33][33] to work around a flash
44984 +                * controller bug.
44985 +                */
44986 +               "       move.2          %[tmp], (%[data])2++                                                    \n\t"
44987 +               "       shmrg.1         %[tmp], (%[data]), %[tmp]                                               \n\t"
44988 +               "       shmrg.1         %[tmp], (%[data])1++, %[tmp]                                            \n\t"
44989 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[tmp]                                        \n\t"
44990 +
44991 +               /*
44992 +                * We're aligned again!
44993 +                */
44994 +               "       .rept 7                                                                                 \n\t"
44995 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
44996 +               "       .endr                                                                                   \n\t"
44997 +
44998 +               /*
44999 +                * Kick off the flash command
45000 +                */
45001 +               "       bset    "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)")                      \n\t"
45002 +               "       jmpt.t  .+4                                                                             \n\t"
45003 +               "       bset    "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)")                     \n\t"
45004 +
45005 +#ifdef SUPPORT_512_FIFO
45006 +               /*
45007 +                * Fill the remaining 120 words as space becomes available
45008 +                */
45009 +               "1:                                                                                             \n\t"
45010 +               "       cmpi            "D(IO_FIFO_LEVEL)"(%[port]), #4                                         \n\t"
45011 +               "       jmpgt.s.t       1b                                                                      \n\t"
45012 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
45013 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
45014 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
45015 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
45016 +               "       add.4           %[cnt], #-4, %[cnt]                                                     \n\t"
45017 +               "       jmpgt.t         1b                                                                      \n\t"
45018 +#endif
45019 +               /*
45020 +                * Wait for the transaction to finish
45021 +                */
45022 +               "       btst    "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)")                       \n\t"
45023 +               "       jmpeq.f .-4                                                                             \n\t"
45024 +
45025 +               : [tmp] "=&d" (tmp),
45026 +                 [data] "+&a" (buf)
45027 +               : [column] "d" (col),
45028 +                 [port] "a" (FLASH_PORT),
45029 +                 [cnt] "d" (120)               // see above comment
45030 +               : "cc"
45031 +       );
45032 +}
45033 +
45034 +/*
45035 + * ubi32_nand_spi_er_send_rd_addr
45036 + *     perform FC_RD: CMD + address
45037 + */
45038 +static void ubi32_nand_spi_er_send_rd_addr(uint8_t command, uint32_t address)
45039 +{
45040 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45041 +
45042 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45043 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(4) |
45044 +                   IO_XFL_CTL1_FC_ADDR;
45045 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
45046 +       FLASH_COMMAND_EXEC(io);
45047 +}
45048 +
45049 +/*
45050 + * ubi32_nand_spi_er_send_cmd_addr
45051 + *     perform FC_(xxx): CMD + address
45052 + */
45053 +static void ubi32_nand_spi_er_send_cmd_addr(uint8_t command, uint32_t address)
45054 +{
45055 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45056 +
45057 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45058 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) | IO_XFL_CTL1_FC_ADDR;
45059 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
45060 +       FLASH_COMMAND_EXEC(io);
45061 +}
45062 +
45063 +/*
45064 + * ubi32_nand_spi_er_write_disable
45065 + *     clear the write enable bit
45066 + */
45067 +static void ubi32_nand_spi_er_write_disable(void)
45068 +{
45069 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45070 +
45071 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45072 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45073 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x04);
45074 +       FLASH_COMMAND_EXEC(io);
45075 +}
45076 +
45077 +/*
45078 + * ubi32_nand_spi_er_write_enable
45079 + *     set the write enable bit
45080 + */
45081 +static void ubi32_nand_spi_er_write_enable(void)
45082 +{
45083 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45084 +
45085 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45086 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45087 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x06);
45088 +       FLASH_COMMAND_EXEC(io);
45089 +}
45090 +
45091 +/*
45092 + * ubi32_nand_spi_er_busywait
45093 + *     Wait until the chip is not busy
45094 + */
45095 +static uint8_t ubi32_nand_spi_er_busywait(void)
45096 +{
45097 +       int i;
45098 +       uint8_t data;
45099 +
45100 +       /*
45101 +        * tRD is 100us, so don't delay too long, however, tERS is
45102 +        * 10ms so you'd better loop enough.
45103 +        */
45104 +       for (i = 0; i < 200; i++) {
45105 +               data = ubi32_nand_spi_er_get_feature(0xC0);
45106 +               if (!(data & UBI32_NAND_SPI_ER_STATUS_OIP)) {
45107 +                       break;
45108 +               }
45109 +
45110 +               udelay(50);
45111 +       }
45112 +
45113 +       return data;
45114 +}
45115 +
45116 +/*
45117 + * ubi32_nand_spi_er_erase
45118 + *     Erase a block, parameters must be block aligned
45119 + */
45120 +static int ubi32_nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
45121 +{
45122 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45123 +       int res;
45124 +
45125 +       DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
45126 +
45127 +       if ((instr->addr + instr->len) > mtd->size) {
45128 +               return -EINVAL;
45129 +       }
45130 +
45131 +       if (instr->addr & (chip->device->erase_size - 1)) {
45132 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
45133 +               return -EINVAL;
45134 +       }
45135 +
45136 +       if (instr->len & (chip->device->erase_size - 1)) {
45137 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
45138 +               return -EINVAL;
45139 +       }
45140 +
45141 +       mutex_lock(&chip->lock);
45142 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45143 +
45144 +       while (instr->len) {
45145 +               uint32_t block = instr->addr >> 17;
45146 +               uint32_t row = block << 6;
45147 +               uint8_t stat;
45148 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
45149 +
45150 +               /*
45151 +                * Test for bad block
45152 +                */
45153 +               if (test_bit(block, chip->bbt)) {
45154 +                       instr->fail_addr = block << 17;
45155 +                       instr->state = MTD_ERASE_FAILED;
45156 +                       res = -EBADMSG;
45157 +                       goto done;
45158 +               }
45159 +
45160 +               ubi32_nand_spi_er_write_enable();
45161 +
45162 +               /*
45163 +                * Block erase
45164 +                */
45165 +               ubi32_nand_spi_er_send_cmd_addr(0xD8, row);
45166 +
45167 +               /*
45168 +                * Wait
45169 +                */
45170 +               stat = ubi32_nand_spi_er_busywait();
45171 +               if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45172 +                       instr->fail_addr = block << 17;
45173 +                       instr->state = MTD_ERASE_FAILED;
45174 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45175 +
45176 +                       /*
45177 +                        * Chip is stuck?
45178 +                        */
45179 +                       res = -EIO;
45180 +                       goto done;
45181 +               }
45182 +
45183 +               /*
45184 +                * Check the status register
45185 +                */
45186 +               if (stat & UBI32_NAND_SPI_ER_STATUS_E_FAIL) {
45187 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
45188 +                       instr->fail_addr = block << 17;
45189 +                       instr->state = MTD_ERASE_FAILED;
45190 +                       goto done;
45191 +               }
45192 +
45193 +               /*
45194 +                * Next
45195 +                */
45196 +               block++;
45197 +               instr->len -= chip->device->erase_size;
45198 +               instr->addr += chip->device->erase_size;
45199 +       }
45200 +
45201 +       instr->state = MTD_ERASE_DONE;
45202 +
45203 +       mutex_unlock(&chip->lock);
45204 +       return 0;
45205 +
45206 +done:
45207 +       ubi32_nand_spi_er_write_disable();
45208 +
45209 +       mutex_unlock(&chip->lock);
45210 +
45211 +       mtd_erase_callback(instr);
45212 +       return 0;
45213 +}
45214 +
45215 +/*
45216 + * ubi32_nand_spi_er_read
45217 + *
45218 + * return -EUCLEAN: ecc error recovered
45219 + * return -EBADMSG: ecc error not recovered
45220 +*/
45221 +static int ubi32_nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
45222 +                                 size_t *retlen, u_char *buf)
45223 +{
45224 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45225 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45226 +
45227 +       uint32_t row;
45228 +       uint32_t column;
45229 +       int retval = 0;
45230 +       uint32_t *pbuf = (uint32_t *)buf;
45231 +
45232 +       *retlen = 0;
45233 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
45234 +
45235 +       /*
45236 +        * buf should be aligned
45237 +        */
45238 +       if ((uint32_t)buf & 0x03) {
45239 +               return -EINVAL;
45240 +       }
45241 +
45242 +       /*
45243 +        * Zero length reads, nothing to do
45244 +        */
45245 +       if (len == 0) {
45246 +               return 0;
45247 +       }
45248 +
45249 +       /*
45250 +        * Reject reads which go over the end of the flash
45251 +        */
45252 +       if ((from + len) > mtd->size) {
45253 +               return -EINVAL;
45254 +       }
45255 +
45256 +       /*
45257 +        * Get the row and column address to start at
45258 +        */
45259 +       row = from >> 11;
45260 +       column = from & 0x7FF;
45261 +       DEBUG(MTD_DEBUG_LEVEL3, "%s: row=%x %d column=%x %d last_row=%x %d\n", chip->name, row, row, column, column, chip->last_row, chip->last_row);
45262 +
45263 +       /*
45264 +        * Read the data from the chip
45265 +        */
45266 +       mutex_lock(&chip->lock);
45267 +       while (len) {
45268 +               uint8_t stat;
45269 +               size_t toread;
45270 +               int i;
45271 +               int tmp;
45272 +
45273 +               /*
45274 +                * Figure out how much to read
45275 +                *
45276 +                * If we are reading from the middle of a page then the most we
45277 +                * can read is to the end of the page
45278 +                */
45279 +               toread = len;
45280 +               if (toread > (chip->device->page_size - column)) {
45281 +                       toread = chip->device->page_size - column;
45282 +               }
45283 +
45284 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: buf=%p toread=%x row=%x column=%x last_row=%x\n", chip->name, pbuf, toread, row, column, chip->last_row);
45285 +
45286 +               if (chip->last_row != row) {
45287 +                       /*
45288 +                        * Check if the block is bad
45289 +                        */
45290 +                       if (test_bit(UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
45291 +                               mutex_unlock(&chip->lock);
45292 +                               return -EBADMSG;
45293 +                       }
45294 +
45295 +                       /*
45296 +                        * Load the appropriate page
45297 +                        */
45298 +                       ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45299 +
45300 +                       /*
45301 +                        * Wait
45302 +                        */
45303 +                       stat = ubi32_nand_spi_er_busywait();
45304 +                       if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45305 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45306 +
45307 +                               /*
45308 +                                * Chip is stuck?
45309 +                                */
45310 +                               mutex_unlock(&chip->lock);
45311 +                               return -EIO;
45312 +                       }
45313 +
45314 +                       /*
45315 +                        * Check the ECC bits
45316 +                        */
45317 +                       stat >>= 4;
45318 +                       if (stat == 1) {
45319 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
45320 +                               retval = -EUCLEAN;
45321 +                       }
45322 +                       if (stat == 2) {
45323 +                               DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
45324 +                               chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45325 +                               mutex_unlock(&chip->lock);
45326 +                               return -EBADMSG;
45327 +                       }
45328 +
45329 +               }
45330 +
45331 +               chip->last_row = row;
45332 +
45333 +               /*
45334 +                * Read out the data:
45335 +                *      We can always read a little too much since there is the
45336 +                *      OOB after byte addr 2047.  The most we'll overread is 3 bytes.
45337 +                */
45338 +               if (((uint32_t)pbuf & 0x03) == 0) {
45339 +                       /*
45340 +                        * Aligned read
45341 +                        */
45342 +                       tmp = toread & (~0x03);
45343 +                       for (i = 0; i < tmp; i += 4) {
45344 +                               ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45345 +                               *pbuf++ = io->status1;
45346 +                               column += 4;
45347 +                       }
45348 +               } else {
45349 +                       /*
45350 +                        * Unaligned read
45351 +                        */
45352 +                       tmp = toread & (~0x03);
45353 +                       for (i = 0; i < tmp; i += 4) {
45354 +                               ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45355 +                               memcpy(pbuf, &io->status1, 4);
45356 +                               column += 4;
45357 +                       }
45358 +               }
45359 +
45360 +               /*
45361 +                * Fill in any single bytes
45362 +                */
45363 +               tmp = toread & 0x03;
45364 +               if (tmp) {
45365 +                       uint8_t *bbuf = pbuf;
45366 +                       uint32_t val;
45367 +                       ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45368 +                       val = io->status1;
45369 +                       for (i = 0; i < tmp; i++) {
45370 +                               *bbuf++ = val >> 24;
45371 +                               val <<= 8;
45372 +                       }
45373 +               }
45374 +
45375 +               len -= toread;
45376 +               *retlen += toread;
45377 +
45378 +               /*
45379 +                * For the next page, increment the row and always start at column 0
45380 +                */
45381 +               column = 0;
45382 +               row++;
45383 +       }
45384 +
45385 +       mutex_unlock(&chip->lock);
45386 +       return retval;
45387 +}
45388 +
45389 +/*
45390 + * ubi32_nand_spi_er_write
45391 + */
45392 +#define WRITE_NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
45393 +static int ubi32_nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
45394 +                                  size_t *retlen, const u_char *buf)
45395 +{
45396 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45397 +       const struct ubi32_nand_spi_er_device *device = chip->device;
45398 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45399 +       uint32_t row;
45400 +       uint32_t col;
45401 +       int res = 0;
45402 +       size_t towrite;
45403 +
45404 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
45405 +
45406 +       *retlen = 0;
45407 +
45408 +       /*
45409 +        * nothing to write
45410 +        */
45411 +       if (!len) {
45412 +               return 0;
45413 +       }
45414 +
45415 +       /*
45416 +        * Reject writes which go over the end of the flash
45417 +        */
45418 +       if ((to + len) > mtd->size) {
45419 +               return -EINVAL;
45420 +       }
45421 +
45422 +       /*
45423 +        * buf should be aligned to 16 bits
45424 +        */
45425 +       if ((uint32_t)buf & 0x01) {
45426 +               return -EINVAL;
45427 +       }
45428 +
45429 +       /*
45430 +        * Check to see if everything is page aligned
45431 +        */
45432 +       if (WRITE_NOT_ALIGNED(to) || WRITE_NOT_ALIGNED(len)) {
45433 +               printk(KERN_NOTICE "ubi32_nand_spi_er_write: Attempt to write non page aligned data\n");
45434 +               return -EINVAL;
45435 +       }
45436 +
45437 +       mutex_lock(&chip->lock);
45438 +
45439 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45440 +
45441 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45442 +
45443 +       /*
45444 +        * If the first write is a partial write then write at most the number of
45445 +        * bytes to get us page aligned and then the remainder will be
45446 +        * page aligned.  The last bit may be a partial page as well.
45447 +        */
45448 +       col = to & (device->page_size - 1);
45449 +       towrite = device->page_size - col;
45450 +       if (towrite > len) {
45451 +               towrite = len;
45452 +       }
45453 +
45454 +       /*
45455 +        * Write the data
45456 +        */
45457 +       row = to >> 11;
45458 +       while (len) {
45459 +               uint8_t stat;
45460 +               uint32_t my_towrite;
45461 +
45462 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
45463 +
45464 +               ubi32_nand_spi_er_write_enable();
45465 +
45466 +               /*
45467 +                * Move the data into the cache
45468 +                */
45469 +               my_towrite = towrite;
45470 +               while (my_towrite) {
45471 +                       uint32_t len = my_towrite;
45472 +                       if (len > 32) {
45473 +                               len = 32;
45474 +                       }
45475 +
45476 +                       ubi32_nand_spi_er_write_buf(buf, col);
45477 +                       buf += len;
45478 +                       col += len;
45479 +                       my_towrite -= len;
45480 +               }
45481 +
45482 +               /*
45483 +                * Program execute
45484 +                */
45485 +               ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45486 +
45487 +               /*
45488 +                * Wait
45489 +                */
45490 +               stat = ubi32_nand_spi_er_busywait();
45491 +               if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45492 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45493 +
45494 +                       /*
45495 +                        * Chip is stuck?
45496 +                        */
45497 +                       res = -EIO;
45498 +                       goto done;
45499 +               }
45500 +
45501 +               if (stat & (1 << 3)) {
45502 +                       res = -EBADMSG;
45503 +                       goto done;
45504 +               }
45505 +
45506 +               row++;
45507 +               len -= towrite;
45508 +               *retlen += towrite;
45509 +
45510 +               /*
45511 +                * At this point, we are always page aligned so start at column 0.
45512 +                * Note we may not have a full page to write at the end, hence the
45513 +                * check if towrite > len.
45514 +                */
45515 +               col = 0;
45516 +               towrite = device->page_size;
45517 +               if (towrite > len) {
45518 +                       towrite = len;
45519 +               }
45520 +       }
45521 +
45522 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45523 +
45524 +       mutex_unlock(&chip->lock);
45525 +       return res;
45526 +
45527 +done:
45528 +       ubi32_nand_spi_er_write_disable();
45529 +
45530 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45531 +
45532 +       mutex_unlock(&chip->lock);
45533 +
45534 +       return res;
45535 +}
45536 +
45537 +/*
45538 + * ubi32_nand_spi_er_isbad
45539 + */
45540 +static int ubi32_nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
45541 +{
45542 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45543 +       uint32_t block;
45544 +
45545 +       if (ofs & (chip->device->erase_size - 1)) {
45546 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45547 +               return -EINVAL;
45548 +       }
45549 +
45550 +       block = ofs >> 17;
45551 +
45552 +       return test_bit(block, chip->bbt);
45553 +}
45554 +
45555 +/*
45556 + * ubi32_nand_spi_er_markbad
45557 + */
45558 +static int ubi32_nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
45559 +{
45560 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45561 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45562 +       uint32_t block;
45563 +       uint32_t row;
45564 +       int res = 0;
45565 +       uint8_t stat;
45566 +
45567 +       if (ofs & (chip->device->erase_size - 1)) {
45568 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45569 +               return -EINVAL;
45570 +       }
45571 +
45572 +       block = ofs >> 17;
45573 +
45574 +       /*
45575 +        * If it's already marked bad, no need to mark it
45576 +        */
45577 +       if (test_bit(block, chip->bbt)) {
45578 +               return 0;
45579 +       }
45580 +
45581 +       /*
45582 +        * Mark it in our cache
45583 +        */
45584 +       __set_bit(block, chip->bbt);
45585 +
45586 +       /*
45587 +        * Write the user bad block mark.  If it fails, then we really
45588 +        * can't do anything about it.
45589 +        */
45590 +       mutex_lock(&chip->lock);
45591 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45592 +
45593 +       ubi32_nand_spi_er_write_enable();
45594 +
45595 +       /*
45596 +        * Write the mark
45597 +        */
45598 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45599 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45600 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(6);
45601 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84);
45602 +
45603 +       asm volatile (
45604 +               "       bset            "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")   \n\t"
45605 +               "       pipe_flush      0                                                                       \n\t"
45606 +
45607 +               /*
45608 +                * Move the data into the FIFO
45609 +                */
45610 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[word1]                                      \n\t"
45611 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[word2]                                      \n\t"
45612 +
45613 +               /*
45614 +                * Kick off the flash command
45615 +                */
45616 +               "       bset    "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)")                      \n\t"
45617 +               "       jmpt.t  .+4                                                                             \n\t"
45618 +               "       bset    "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)")                     \n\t"
45619 +
45620 +               /*
45621 +                * Wait for the transaction to finish
45622 +                */
45623 +               "       btst    "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)")                       \n\t"
45624 +               "       jmpeq.f .-4                                                                             \n\t"
45625 +
45626 +               :
45627 +               : [word1] "d" (0x0800dead | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 16)),
45628 +                 [word2] "d" (0xbeef0000),
45629 +                 [port] "a" (FLASH_PORT)
45630 +               : "cc"
45631 +       );
45632 +
45633 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45634 +
45635 +       /*
45636 +        * Program execute
45637 +        */
45638 +       row = block << 6;
45639 +       ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45640 +
45641 +       /*
45642 +        * Wait
45643 +        */
45644 +       stat = ubi32_nand_spi_er_busywait();
45645 +       if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45646 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45647 +
45648 +               /*
45649 +                * Chip is stuck?
45650 +                */
45651 +               res = -EIO;
45652 +               goto done;
45653 +       }
45654 +
45655 +       if (stat & (1 << 3)) {
45656 +               res = -EBADMSG;
45657 +       }
45658 +
45659 +done:
45660 +       ubi32_nand_spi_er_write_disable();
45661 +
45662 +       mutex_unlock(&chip->lock);
45663 +
45664 +       return res;
45665 +}
45666 +
45667 +/*
45668 + * ubi32_nand_spi_er_read_bbt
45669 + */
45670 +static int ubi32_nand_spi_er_read_bbt(struct ubi32_nand_spi_er *chip)
45671 +{
45672 +       int j;
45673 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45674 +
45675 +       for (j = 0; j < chip->device->blocks; j++) {
45676 +               unsigned short row = j << 6;
45677 +               uint8_t stat;
45678 +
45679 +               /*
45680 +                * Read Page
45681 +                */
45682 +               ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45683 +
45684 +               /*
45685 +                * Wait
45686 +                */
45687 +               stat = ubi32_nand_spi_er_busywait();
45688 +               if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45689 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45690 +
45691 +                       /*
45692 +                        * Chip is stuck?
45693 +                        */
45694 +                       return -EIO;
45695 +               }
45696 +
45697 +               /*
45698 +                * Check factory bad block mark
45699 +                */
45700 +               ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000);
45701 +
45702 +               if ((io->status1 >> 24) != 0xFF) {
45703 +                       chip->nbb++;
45704 +                       __set_bit(j, chip->bbt);
45705 +                       continue;
45706 +               }
45707 +
45708 +               ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000 | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 8));
45709 +               if (io->status1 == 0xdeadbeef) {
45710 +                       chip->nbb++;
45711 +                       __set_bit(j, chip->bbt);
45712 +               }
45713 +       }
45714 +
45715 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
45716 +       printk("%s: Bad Block Table:", chip->name);
45717 +       for (j = 0; j < chip->device->blocks; j++) {
45718 +               if ((j % 64) == 0) {
45719 +                       printk("\n%s: block %03x: ", chip->name, j);
45720 +               }
45721 +               printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
45722 +       }
45723 +       printk("\n%s: Bad Block Numbers: ", chip->name);
45724 +       for (j = 0; j < chip->device->blocks; j++) {
45725 +               if (test_bit(j, chip->bbt)) {
45726 +                       printk("%x ", j);
45727 +               }
45728 +       }
45729 +       printk("\n");
45730 +#endif
45731 +
45732 +       return 0;
45733 +}
45734 +
45735 +#ifndef MODULE
45736 +/*
45737 + * Called at boot time:
45738 + *
45739 + * ubi32_nand_spi_er=read_only
45740 + *     if read_only specified then do not unlock device
45741 + */
45742 +static int __init ubi32_nand_spi_er_setup(char *str)
45743 +{
45744 +       if (str && (strncasecmp(str, "read_only", 9) == 0)) {
45745 +               read_only = 1;
45746 +       }
45747 +       return 0;
45748 +}
45749 +
45750 +__setup("ubi32_nand_spi_er=", ubi32_nand_spi_er_setup);
45751 +#endif
45752 +
45753 +/*
45754 + * ubi32_nand_spi_er_probe
45755 + *     Detect and initialize ubi32_nand_spi_er device.
45756 + */
45757 +static int __devinit ubi32_nand_spi_er_probe(struct platform_device *pdev)
45758 +{
45759 +       uint32_t i;
45760 +       uint32_t id;
45761 +       int res;
45762 +       size_t bbt_bytes;
45763 +       struct ubi32_nand_spi_er *chip;
45764 +       const struct ubi32_nand_spi_er_device *device;
45765 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45766 +
45767 +       /*
45768 +        * Reset
45769 +        */
45770 +       for (i = 0; i < 2; i++) {
45771 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
45772 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45773 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(0xFF);
45774 +               FLASH_COMMAND_EXEC(io);
45775 +               udelay(250);
45776 +       }
45777 +       udelay(1000);
45778 +
45779 +       /*
45780 +        * Read out ID
45781 +        */
45782 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45783 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(2) |
45784 +                   IO_XFL_CTL1_FC_ADDR;
45785 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x9F);
45786 +       FLASH_COMMAND_EXEC(io);
45787 +
45788 +       id = io->status1 >> 16;
45789 +       device = ubi32_nand_spi_er_devices;
45790 +       for (i = 0; i < ARRAY_SIZE(ubi32_nand_spi_er_devices); i++) {
45791 +               if (device->id == id) {
45792 +                       break;
45793 +               }
45794 +               device++;
45795 +       }
45796 +       if (i == ARRAY_SIZE(ubi32_nand_spi_er_devices)) {
45797 +               return -ENODEV;
45798 +       }
45799 +
45800 +       /*
45801 +        * Initialize our chip structure
45802 +        */
45803 +       bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
45804 +       chip = kzalloc(sizeof(struct ubi32_nand_spi_er) + bbt_bytes, GFP_KERNEL);
45805 +       if (!chip) {
45806 +               return -ENOMEM;
45807 +       }
45808 +       snprintf(chip->name, sizeof(chip->name), "%s", device->name);
45809 +
45810 +       chip->device = device;
45811 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45812 +
45813 +       mutex_init(&chip->lock);
45814 +
45815 +       chip->mtd.type = MTD_NANDFLASH;
45816 +       chip->mtd.flags = MTD_WRITEABLE;
45817 +
45818 +       /*
45819 +        * #blocks * block size * n blocks
45820 +        */
45821 +       chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
45822 +       chip->mtd.erasesize = device->erase_size;
45823 +
45824 +       /*
45825 +        * 1 page, optionally we can support partial write (512)
45826 +        */
45827 +       chip->mtd.writesize = device->write_size;
45828 +       chip->mtd.name = device->name;
45829 +       chip->mtd.erase = ubi32_nand_spi_er_erase;
45830 +       chip->mtd.read = ubi32_nand_spi_er_read;
45831 +       chip->mtd.write = ubi32_nand_spi_er_write;
45832 +       chip->mtd.block_isbad = ubi32_nand_spi_er_isbad;
45833 +       chip->mtd.block_markbad = ubi32_nand_spi_er_markbad;
45834 +       chip->mtd.priv = chip;
45835 +
45836 +       /*
45837 +        * Cache the bad block table
45838 +        */
45839 +       res = ubi32_nand_spi_er_read_bbt(chip);
45840 +       if (res) {
45841 +               kfree(chip);
45842 +               return res;
45843 +       }
45844 +
45845 +       /*
45846 +        * Un/lock the chip
45847 +        */
45848 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45849 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45850 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(2);
45851 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x1F);
45852 +
45853 +       if (read_only) {
45854 +               i = 0xa0380000;
45855 +       } else {
45856 +               i = 0xa0000000;
45857 +       }
45858 +       asm volatile (
45859 +               "       bset            "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")   \n\t"
45860 +               "       pipe_flush      0                                                                       \n\t"
45861 +
45862 +               /*
45863 +                * Move the data into the FIFO
45864 +                */
45865 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[word1]                                      \n\t"
45866 +
45867 +               /*
45868 +                * Kick off the flash command
45869 +                */
45870 +               "       bset    "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)")                      \n\t"
45871 +               "       jmpt.t  .+4                                                                             \n\t"
45872 +               "       bset    "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)")                     \n\t"
45873 +
45874 +               /*
45875 +                * Wait for the transaction to finish
45876 +                */
45877 +               "       btst    "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)")                       \n\t"
45878 +               "       jmpeq.f .-4                                                                             \n\t"
45879 +
45880 +               :
45881 +               : [word1] "d" (i),
45882 +                 [port] "a" (FLASH_PORT)
45883 +               : "cc"
45884 +       );
45885 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45886 +
45887 +       dev_set_drvdata(&pdev->dev, chip);
45888 +
45889 +       printk(KERN_INFO "%s: added device size: %u KBytes %lu bad blocks %s\n", chip->mtd.name, DIV_ROUND_UP(chip->mtd.size, 1024), chip->nbb, read_only ? "[read only]" : "");
45890 +       return add_mtd_device(&chip->mtd);
45891 +}
45892 +
45893 +/*
45894 + * ubi32_nand_spi_er_remove
45895 + */
45896 +static int __devexit ubi32_nand_spi_er_remove(struct platform_device *pdev)
45897 +{
45898 +       struct ubi32_nand_spi_er *chip = dev_get_drvdata(&pdev->dev);
45899 +       int status;
45900 +
45901 +       DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", chip->name);
45902 +
45903 +       status = del_mtd_device(&chip->mtd);
45904 +       if (status == 0) {
45905 +               kfree(chip);
45906 +       }
45907 +
45908 +       dev_set_drvdata(&pdev->dev, NULL);
45909 +       return status;
45910 +}
45911 +
45912 +static struct platform_device *ubi32_nand_spi_er_device;
45913 +
45914 +static struct platform_driver ubi32_nand_spi_er_driver = {
45915 +       .driver = {
45916 +               .name           = DRIVER_NAME,
45917 +               .owner          = THIS_MODULE,
45918 +       },
45919 +
45920 +       .probe          = ubi32_nand_spi_er_probe,
45921 +       .remove         = ubi32_nand_spi_er_remove,
45922 +};
45923 +
45924 +/*
45925 + * ubi32_nand_spi_er_init
45926 + */
45927 +static int __init ubi32_nand_spi_er_init(void)
45928 +{
45929 +       int ret;
45930 +
45931 +       ret = platform_driver_register(&ubi32_nand_spi_er_driver);
45932 +
45933 +       if (ret) {
45934 +               return ret;
45935 +       }
45936 +
45937 +       ubi32_nand_spi_er_device = platform_device_alloc(DRIVER_NAME, 0);
45938 +       if (!ubi32_nand_spi_er_device) {
45939 +               return -ENOMEM;
45940 +       }
45941 +
45942 +       ret = platform_device_add(ubi32_nand_spi_er_device);
45943 +       if (ret) {
45944 +               platform_device_put(ubi32_nand_spi_er_device);
45945 +               platform_driver_unregister(&ubi32_nand_spi_er_driver);
45946 +       }
45947 +
45948 +       return ret;
45949 +}
45950 +module_init(ubi32_nand_spi_er_init);
45951 +
45952 +/*
45953 + * ubi32_nand_spi_er_exit
45954 + */
45955 +static void __exit ubi32_nand_spi_er_exit(void)
45956 +{
45957 +       platform_device_unregister(ubi32_nand_spi_er_device);
45958 +       platform_driver_unregister(&ubi32_nand_spi_er_driver);
45959 +}
45960 +module_exit(ubi32_nand_spi_er_exit);
45961 +
45962 +
45963 +MODULE_LICENSE("GPL");
45964 +MODULE_AUTHOR("Patrick Tjin");
45965 +MODULE_DESCRIPTION("MTD ubi32_nand_spi_er driver for ubicom32 SPI flash controller.");
45966 diff -ruN linux-2.6.30.10/drivers/net/Kconfig linux-2.6.30.10-ubi/drivers/net/Kconfig
45967 --- linux-2.6.30.10/drivers/net/Kconfig 2009-12-14 11:47:19.000000000 +0200
45968 +++ linux-2.6.30.10-ubi/drivers/net/Kconfig     2009-12-14 11:47:17.000000000 +0200
45969 @@ -2540,6 +2540,19 @@
45970           To compile this driver as a module, choose M here. The module
45971           will be called jme.
45972  
45973 +config UBICOM32_GMAC
45974 +       tristate "Ubicom Gigabit Ethernet support"
45975 +       depends on UBICOM32
45976 +       help
45977 +         Gigabit Ethernet support for ubicom32 processors
45978 +
45979 +config UBICOM32_OCM_FOR_SKB
45980 +        bool  "USE OCM for SKB (EXPERIMENTAL)"
45981 +        depends on UBICOM32_GMAC
45982 +       default n
45983 +        help
45984 +          Allocate skb from OCM for Ethernet Receive when possible
45985 +
45986  endif # NETDEV_1000
45987  
45988  #
45989 diff -ruN linux-2.6.30.10/drivers/net/Makefile linux-2.6.30.10-ubi/drivers/net/Makefile
45990 --- linux-2.6.30.10/drivers/net/Makefile        2009-12-14 11:48:38.000000000 +0200
45991 +++ linux-2.6.30.10-ubi/drivers/net/Makefile    2009-12-14 11:48:40.000000000 +0200
45992 @@ -272,3 +272,5 @@
45993  obj-$(CONFIG_SFC) += sfc/
45994  
45995  obj-$(CONFIG_WIMAX) += wimax/
45996 +
45997 +obj-$(CONFIG_UBICOM32_GMAC) += ubi32-eth.o
45998 diff -ruN linux-2.6.30.10/drivers/net/ubi32-eth.c linux-2.6.30.10-ubi/drivers/net/ubi32-eth.c
45999 --- linux-2.6.30.10/drivers/net/ubi32-eth.c     1970-01-01 02:00:00.000000000 +0200
46000 +++ linux-2.6.30.10-ubi/drivers/net/ubi32-eth.c 2009-12-11 11:45:18.000000000 +0200
46001 @@ -0,0 +1,760 @@
46002 +/*
46003 + * drivers/net/ubi32-eth.c
46004 + *   Ubicom32 ethernet TIO interface driver.
46005 + *
46006 + * (C) Copyright 2009, Ubicom, Inc.
46007 + *
46008 + * This file is part of the Ubicom32 Linux Kernel Port.
46009 + *
46010 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46011 + * it and/or modify it under the terms of the GNU General Public License
46012 + * as published by the Free Software Foundation, either version 2 of the
46013 + * License, or (at your option) any later version.
46014 + *
46015 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46016 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46017 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
46018 + * the GNU General Public License for more details.
46019 + *
46020 + * You should have received a copy of the GNU General Public License
46021 + * along with the Ubicom32 Linux Kernel Port.  If not,
46022 + * see <http://www.gnu.org/licenses/>.
46023 + *
46024 + * Ubicom32 implementation derived from (with many thanks):
46025 + *   arch/m68knommu
46026 + *   arch/blackfin
46027 + *   arch/parisc
46028 + */
46029 +/*
46030 + * ubi32_eth.c
46031 + * Ethernet driver for Ip5k/Ip7K
46032 + */
46033 +
46034 +#include <linux/module.h>
46035 +#include <linux/init.h>
46036 +#include <linux/moduleparam.h>
46037 +
46038 +#include <linux/sched.h>
46039 +#include <linux/kernel.h>
46040 +#include <linux/errno.h>
46041 +#include <linux/types.h>
46042 +#include <linux/interrupt.h>
46043 +
46044 +#include <linux/in.h>
46045 +#include <linux/netdevice.h>
46046 +#include <linux/etherdevice.h>
46047 +#include <linux/mii.h>
46048 +#include <linux/if_vlan.h>
46049 +#include <linux/ip.h>
46050 +#include <linux/tcp.h>
46051 +#include <linux/skbuff.h>
46052 +#include <asm/checksum.h>
46053 +#include <asm/ip5000.h>
46054 +#include <asm/devtree.h>
46055 +#include <asm/system.h>
46056 +
46057 +#define UBICOM32_USE_NAPI      /* define this to use NAPI instead of tasklet */
46058 +//#define UBICOM32_USE_POLLING /* define this to use polling instead of interrupt */
46059 +#include "ubi32-eth.h"
46060 +
46061 +/*
46062 + * TODO:
46063 + * mac address from flash
46064 + * multicast filter
46065 + * ethtool support
46066 + * sysfs support
46067 + * skb->nrfrag support
46068 + * ioctl
46069 + * monitor phy status
46070 + */
46071 +
46072 +extern int ubi32_ocm_skbuf_max, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
46073 +static const char *eth_if_name[UBI32_ETH_NUM_OF_DEVICES] =
46074 +       {"eth_lan", "eth_wan"};
46075 +static struct net_device *ubi32_eth_devices[UBI32_ETH_NUM_OF_DEVICES] =
46076 +       {NULL, NULL};
46077 +static u8_t mac_addr[UBI32_ETH_NUM_OF_DEVICES][ETH_ALEN] = {
46078 +       {0x00, 0x03, 0x64, 'l', 'a', 'n'},
46079 +       {0x00, 0x03, 0x64, 'w', 'a', 'n'}};
46080 +
46081 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
46082 +static inline struct sk_buff *ubi32_alloc_skb_ocm(struct net_device *dev, unsigned int length)
46083 +{
46084 +       return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
46085 +}
46086 +#endif
46087 +
46088 +static inline struct sk_buff *ubi32_alloc_skb(struct net_device *dev, unsigned int length)
46089 +{
46090 +       return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN);
46091 +}
46092 +
46093 +static void ubi32_eth_vp_rxtx_enable(struct net_device *dev)
46094 +{
46095 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46096 +       priv->regs->command = UBI32_ETH_VP_CMD_RX_ENABLE | UBI32_ETH_VP_CMD_TX_ENABLE;
46097 +       priv->regs->int_mask = (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46098 +       ubicom32_set_interrupt(priv->vp_int_bit);
46099 +}
46100 +
46101 +static void ubi32_eth_vp_rxtx_stop(struct net_device *dev)
46102 +{
46103 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46104 +       priv->regs->command = 0;
46105 +       priv->regs->int_mask = 0;
46106 +       ubicom32_set_interrupt(priv->vp_int_bit);
46107 +
46108 +       /* Wait for graceful shutdown */
46109 +       while (priv->regs->status & (UBI32_ETH_VP_STATUS_RX_STATE | UBI32_ETH_VP_STATUS_TX_STATE));
46110 +}
46111 +
46112 +/*
46113 + * ubi32_eth_tx_done()
46114 + */
46115 +static int ubi32_eth_tx_done(struct net_device *dev)
46116 +{
46117 +       struct ubi32_eth_private *priv;
46118 +       struct sk_buff *skb;
46119 +       volatile void *pdata;
46120 +       struct ubi32_eth_dma_desc *desc;
46121 +       u32_t   count = 0;
46122 +
46123 +       priv = netdev_priv(dev);
46124 +
46125 +       priv->regs->int_status &= ~UBI32_ETH_VP_INT_TX;
46126 +       while (priv->tx_tail != priv->regs->tx_out) {
46127 +               pdata = priv->regs->tx_dma_ring[priv->tx_tail];
46128 +               BUG_ON(pdata == NULL);
46129 +
46130 +               skb = container_of((void *)pdata, struct sk_buff, cb);
46131 +               desc = (struct ubi32_eth_dma_desc *)pdata;
46132 +               if (unlikely(!(desc->status & UBI32_ETH_VP_TX_OK))) {
46133 +                       dev->stats.tx_errors++;
46134 +               } else {
46135 +                       dev->stats.tx_packets++;
46136 +                       dev->stats.tx_bytes += skb->len;
46137 +               }
46138 +               dev_kfree_skb_any(skb);
46139 +               priv->regs->tx_dma_ring[priv->tx_tail] = NULL;
46140 +               priv->tx_tail = (priv->tx_tail + 1) & TX_DMA_RING_MASK;
46141 +               count++;
46142 +       }
46143 +
46144 +       if (unlikely(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46145 +               spin_lock(&priv->lock);
46146 +               if (priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL) {
46147 +                       priv->regs->status &= ~UBI32_ETH_VP_STATUS_TX_Q_FULL;
46148 +                       netif_wake_queue(dev);
46149 +               }
46150 +               spin_unlock(&priv->lock);
46151 +       }
46152 +       return count;
46153 +}
46154 +
46155 +/*
46156 + * ubi32_eth_receive()
46157 + *     To avoid locking overhead, this is called only
46158 + *     by tasklet when not using NAPI, or
46159 + *     by NAPI poll when using NAPI.
46160 + *     return number of frames processed
46161 + */
46162 +static int ubi32_eth_receive(struct net_device *dev, int quota)
46163 +{
46164 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46165 +       unsigned short rx_in = priv->regs->rx_in;
46166 +       struct sk_buff *skb;
46167 +       struct ubi32_eth_dma_desc *desc = NULL;
46168 +       volatile void *pdata;
46169 +
46170 +       int extra_reserve_adj;
46171 +       int extra_alloc = UBI32_ETH_RESERVE_SPACE + UBI32_ETH_TRASHED_MEMORY;
46172 +       int replenish_cnt, count = 0;
46173 +       int replenish_max = RX_DMA_MAX_QUEUE_SIZE;
46174 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
46175 +       if (likely(dev == ubi32_eth_devices[0]))
46176 +               replenish_max = min(ubi32_ocm_skbuf_max, RX_DMA_MAX_QUEUE_SIZE);;
46177 +#endif
46178 +
46179 +       if (unlikely(rx_in == priv->regs->rx_out))
46180 +               priv->vp_stats.rx_q_full_cnt++;
46181 +
46182 +       priv->regs->int_status &= ~UBI32_ETH_VP_INT_RX;
46183 +       while (priv->rx_tail != priv->regs->rx_out) {
46184 +               if (unlikely(count == quota)) {
46185 +                       /* There is still frame pending to be processed */
46186 +                       priv->vp_stats.rx_throttle++;
46187 +                       break;
46188 +               }
46189 +
46190 +               pdata = priv->regs->rx_dma_ring[priv->rx_tail];
46191 +               BUG_ON(pdata == NULL);
46192 +
46193 +               desc = (struct ubi32_eth_dma_desc *)pdata;
46194 +               skb = container_of((void *)pdata, struct sk_buff, cb);
46195 +               count++;
46196 +               priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
46197 +               priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
46198 +
46199 +               /*
46200 +                * Check only RX_OK bit here.
46201 +                * The rest of status word is used as timestamp
46202 +                */
46203 +               if (unlikely(!(desc->status & UBI32_ETH_VP_RX_OK))) {
46204 +                       dev->stats.rx_errors++;
46205 +                       dev_kfree_skb_any(skb);
46206 +                       continue;
46207 +               }
46208 +
46209 +               skb_put(skb, desc->data_len);
46210 +               skb->dev = dev;
46211 +               skb->protocol = eth_type_trans(skb, dev);
46212 +               skb->ip_summed = CHECKSUM_NONE;
46213 +               dev->stats.rx_bytes += skb->len;
46214 +               dev->stats.rx_packets++;
46215 +#ifndef UBICOM32_USE_NAPI
46216 +               netif_rx(skb);
46217 +#else
46218 +               netif_receive_skb(skb);
46219 +#endif
46220 +       }
46221 +
46222 +       /* fill in more descripor for VP*/
46223 +       replenish_cnt =  replenish_max -
46224 +               ((RX_DMA_RING_SIZE + rx_in - priv->rx_tail) & RX_DMA_RING_MASK);
46225 +       if (replenish_cnt > 0) {
46226 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
46227 +               /*
46228 +                * black magic for perforamnce:
46229 +                *   Try to allocate skb from OCM only for first Ethernet I/F.
46230 +                *   Also limit number of RX buffers to 21 due to limited OCM.
46231 +                */
46232 +               if (likely(dev == ubi32_eth_devices[0])) {
46233 +                       do {
46234 +                               skb = ubi32_alloc_skb_ocm(dev, RX_BUF_SIZE + extra_alloc);
46235 +                               if (!skb) {
46236 +                                       break;
46237 +                               }
46238 +                               /* set up dma descriptor */
46239 +                               ubi32_ocm_skbuf++;
46240 +                               desc = (struct ubi32_eth_dma_desc *)skb->cb;
46241 +                               extra_reserve_adj =
46242 +                                       ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
46243 +                                       (CACHE_LINE_SIZE - 1);
46244 +                               skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
46245 +                               desc->data_pointer = skb->data;
46246 +                               desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
46247 +                               desc->data_len = 0;
46248 +                               desc->status = 0;
46249 +                               priv->regs->rx_dma_ring[rx_in] = desc;
46250 +                               rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
46251 +                       } while (--replenish_cnt > 0);
46252 +               }
46253 +#endif
46254 +
46255 +               while (replenish_cnt-- > 0) {
46256 +                       skb = ubi32_alloc_skb(dev, RX_BUF_SIZE + extra_alloc);
46257 +                       if (!skb) {
46258 +                               priv->vp_stats.rx_alloc_err++;
46259 +                               break;
46260 +                       }
46261 +                       /* set up dma descriptor */
46262 +                       ubi32_ddr_skbuf++;
46263 +                       desc = (struct ubi32_eth_dma_desc *)skb->cb;
46264 +                       extra_reserve_adj =
46265 +                               ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
46266 +                               (CACHE_LINE_SIZE - 1);
46267 +                       skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
46268 +                       desc->data_pointer = skb->data;
46269 +                       desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
46270 +                       desc->data_len = 0;
46271 +                       desc->status = 0;
46272 +                       priv->regs->rx_dma_ring[rx_in] = desc;
46273 +                       rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
46274 +               }
46275 +
46276 +               wmb();
46277 +               priv->regs->rx_in = rx_in;
46278 +               ubicom32_set_interrupt(priv->vp_int_bit);
46279 +       }
46280 +
46281 +       if (likely(count > 0)) {
46282 +               dev->last_rx = jiffies;
46283 +       }
46284 +       return count;
46285 +}
46286 +
46287 +#ifdef UBICOM32_USE_NAPI
46288 +static int ubi32_eth_napi_poll(struct napi_struct *napi, int budget)
46289 +{
46290 +       struct ubi32_eth_private *priv = container_of(napi, struct ubi32_eth_private, napi);
46291 +       struct net_device *dev = priv->dev;
46292 +       u32_t count;
46293 +
46294 +       if (priv->tx_tail != priv->regs->tx_out) {
46295 +                ubi32_eth_tx_done(dev);
46296 +        }
46297 +
46298 +       count = ubi32_eth_receive(dev, budget);
46299 +
46300 +       if (count < budget) {
46301 +               napi_complete(napi);
46302 +               priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46303 +               if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46304 +                       if (napi_reschedule(napi)) {
46305 +                               priv->regs->int_mask = 0;
46306 +                       }
46307 +               }
46308 +       }
46309 +       return count;
46310 +}
46311 +
46312 +#else
46313 +static void ubi32_eth_do_tasklet(unsigned long arg)
46314 +{
46315 +       struct net_device *dev = (struct net_device *)arg;
46316 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46317 +
46318 +       if (priv->tx_tail != priv->regs->tx_out) {
46319 +               ubi32_eth_tx_done(dev);
46320 +       }
46321 +
46322 +       /* always call receive to process new RX frame as well as replenish RX buffers */
46323 +       ubi32_eth_receive(dev, UBI32_RX_BOUND);
46324 +
46325 +       priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46326 +       if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46327 +               priv->regs->int_mask = 0;
46328 +               tasklet_schedule(&priv->tsk);
46329 +       }
46330 +}
46331 +#endif
46332 +
46333 +#if defined(UBICOM32_USE_POLLING)
46334 +static struct timer_list eth_poll_timer;
46335 +
46336 +static void ubi32_eth_poll(unsigned long arg)
46337 +{
46338 +       struct net_device *dev;
46339 +       struct ubi32_eth_private *priv;
46340 +       int i;
46341 +
46342 +       for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46343 +               dev = ubi32_eth_devices[i];
46344 +               if (dev && (dev->flags & IFF_UP)) {
46345 +                       priv = netdev_priv(dev);
46346 +#ifdef UBICOM32_USE_NAPI
46347 +                       napi_schedule(&priv->napi);
46348 +#else
46349 +                       tasklet_schedule(&priv->tsk);
46350 +#endif
46351 +               }
46352 +       }
46353 +
46354 +       eth_poll_timer.expires = jiffies + 2;
46355 +       add_timer(&eth_poll_timer);
46356 +}
46357 +
46358 +#else
46359 +static irqreturn_t ubi32_eth_interrupt(int irq, void *dev_id)
46360 +{
46361 +       struct ubi32_eth_private *priv;
46362 +
46363 +       struct net_device *dev = (struct net_device *)dev_id;
46364 +       BUG_ON(irq != dev->irq);
46365 +
46366 +       priv = netdev_priv(dev);
46367 +       if (unlikely(!(priv->regs->int_status & priv->regs->int_mask))) {
46368 +               return IRQ_NONE;
46369 +       }
46370 +
46371 +       /*
46372 +        * Disable port interrupt
46373 +        */
46374 +#ifdef UBICOM32_USE_NAPI
46375 +       if (napi_schedule_prep(&priv->napi)) {
46376 +               priv->regs->int_mask = 0;
46377 +               __napi_schedule(&priv->napi);
46378 +       }
46379 +#else
46380 +       priv->regs->int_mask = 0;
46381 +       tasklet_schedule(&priv->tsk);
46382 +#endif
46383 +       return IRQ_HANDLED;
46384 +}
46385 +#endif
46386 +
46387 +/*
46388 + * ubi32_eth_open
46389 + */
46390 +static int ubi32_eth_open(struct net_device *dev)
46391 +{
46392 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46393 +       int err;
46394 +
46395 +       printk(KERN_INFO "eth open %s\n",dev->name);
46396 +#ifndef UBICOM32_USE_POLLING
46397 +       /* request_region() */
46398 +       err = request_irq(dev->irq, ubi32_eth_interrupt, IRQF_DISABLED, dev->name, dev);
46399 +       if (err) {
46400 +               printk(KERN_WARNING "fail to request_irq %d\n",err);
46401 +                return -ENODEV;
46402 +       }
46403 +#endif
46404 +#ifdef  UBICOM32_USE_NAPI
46405 +       napi_enable(&priv->napi);
46406 +#else
46407 +       tasklet_init(&priv->tsk, ubi32_eth_do_tasklet, (unsigned long)dev);
46408 +#endif
46409 +
46410 +       /* call receive to supply RX buffers */
46411 +       ubi32_eth_receive(dev, RX_DMA_MAX_QUEUE_SIZE);
46412 +
46413 +       /* check phy status and call netif_carrier_on */
46414 +       ubi32_eth_vp_rxtx_enable(dev);
46415 +       netif_start_queue(dev);
46416 +       return 0;
46417 +}
46418 +
46419 +static int ubi32_eth_close(struct net_device *dev)
46420 +{
46421 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46422 +       volatile void *pdata;
46423 +       struct sk_buff *skb;
46424 +
46425 +#ifndef UBICOM32_USE_POLLING
46426 +       free_irq(dev->irq, dev);
46427 +#endif
46428 +       netif_stop_queue(dev); /* can't transmit any more */
46429 +#ifdef UBICOM32_USE_NAPI
46430 +       napi_disable(&priv->napi);
46431 +#else
46432 +       tasklet_kill(&priv->tsk);
46433 +#endif
46434 +       ubi32_eth_vp_rxtx_stop(dev);
46435 +
46436 +       /*
46437 +        * RX clean up
46438 +        */
46439 +       while (priv->rx_tail != priv->regs->rx_in) {
46440 +               pdata = priv->regs->rx_dma_ring[priv->rx_tail];
46441 +               skb = container_of((void *)pdata, struct sk_buff, cb);
46442 +               priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
46443 +               dev_kfree_skb_any(skb);
46444 +               priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
46445 +       }
46446 +       priv->regs->rx_in = 0;
46447 +       priv->regs->rx_out = priv->regs->rx_in;
46448 +       priv->rx_tail = priv->regs->rx_in;
46449 +
46450 +       /*
46451 +        * TX clean up
46452 +        */
46453 +       BUG_ON(priv->regs->tx_out != priv->regs->tx_in);
46454 +       ubi32_eth_tx_done(dev);
46455 +       BUG_ON(priv->tx_tail != priv->regs->tx_in);
46456 +       priv->regs->tx_in = 0;
46457 +       priv->regs->tx_out = priv->regs->tx_in;
46458 +       priv->tx_tail = priv->regs->tx_in;
46459 +
46460 +       return 0;
46461 +}
46462 +
46463 +/*
46464 + * ubi32_eth_set_config
46465 + */
46466 +static int ubi32_eth_set_config(struct net_device *dev, struct ifmap *map)
46467 +{
46468 +       /* if must to down to config it */
46469 +       printk(KERN_INFO "set_config %x\n", dev->flags);
46470 +       if (dev->flags & IFF_UP)
46471 +               return -EBUSY;
46472 +
46473 +       /* I/O and IRQ can not be changed */
46474 +       if (map->base_addr != dev->base_addr) {
46475 +               printk(KERN_WARNING "%s: Can't change I/O address\n", dev->name);
46476 +               return -EOPNOTSUPP;
46477 +       }
46478 +
46479 +#ifndef UBICOM32_USE_POLLING
46480 +       if (map->irq != dev->irq) {
46481 +               printk(KERN_WARNING "%s: Can't change IRQ\n", dev->name);
46482 +               return -EOPNOTSUPP;
46483 +       }
46484 +#endif
46485 +
46486 +       /* ignore other fields */
46487 +       return 0;
46488 +}
46489 +
46490 +static int ubi32_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
46491 +{
46492 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46493 +       struct ubi32_eth_dma_desc *desc = NULL;
46494 +       unsigned short space, tx_in;
46495 +
46496 +       tx_in = priv->regs->tx_in;
46497 +
46498 +       dev->trans_start = jiffies; /* save the timestamp */
46499 +       space = TX_DMA_RING_MASK - ((TX_DMA_RING_SIZE + tx_in - priv->tx_tail) & TX_DMA_RING_MASK);
46500 +
46501 +       if (unlikely(space == 0)) {
46502 +               if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46503 +                       spin_lock(&priv->lock);
46504 +                       if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46505 +                               priv->regs->status |= UBI32_ETH_VP_STATUS_TX_Q_FULL;
46506 +                               priv->vp_stats.tx_q_full_cnt++;
46507 +                               netif_stop_queue(dev);
46508 +                       }
46509 +                       spin_unlock(&priv->lock);
46510 +               }
46511 +
46512 +               /* give both HW and this driver an extra trigger */
46513 +               priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46514 +#ifndef UBICOM32_USE_POLLING
46515 +               ubicom32_set_interrupt(dev->irq);
46516 +#endif
46517 +               ubicom32_set_interrupt(priv->vp_int_bit);
46518 +
46519 +               return NETDEV_TX_BUSY;
46520 +       }
46521 +
46522 +       /*still have room */
46523 +       desc = (struct ubi32_eth_dma_desc *)skb->cb;
46524 +       desc->data_pointer = skb->data;
46525 +       desc->data_len = skb->len;
46526 +       priv->regs->tx_dma_ring[tx_in] = desc;
46527 +       tx_in = ((tx_in + 1) & TX_DMA_RING_MASK);
46528 +       wmb();
46529 +       priv->regs->tx_in = tx_in;
46530 +       /* kick the HRT */
46531 +       ubicom32_set_interrupt(priv->vp_int_bit);
46532 +
46533 +       return NETDEV_TX_OK;
46534 +}
46535 +
46536 +/*
46537 + * Deal with a transmit timeout.
46538 + */
46539 +static void ubi32_eth_tx_timeout (struct net_device *dev)
46540 +{
46541 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46542 +       dev->stats.tx_errors++;
46543 +       priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46544 +#ifndef UBICOM32_USE_POLLING
46545 +       ubicom32_set_interrupt(dev->irq);
46546 +#endif
46547 +       ubicom32_set_interrupt(priv->vp_int_bit);
46548 +}
46549 +
46550 +static int ubi32_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
46551 +{
46552 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46553 +       struct mii_ioctl_data *data = if_mii(rq);
46554 +
46555 +       printk(KERN_INFO "ioctl %s, %d\n", dev->name, cmd);
46556 +       switch (cmd) {
46557 +       case SIOCGMIIPHY:
46558 +               data->phy_id = 0;
46559 +               break;
46560 +
46561 +       case SIOCGMIIREG:
46562 +               if ((data->reg_num & 0x1F) == MII_BMCR) {
46563 +                       /* Make up MII control register value from what we know */
46564 +                       data->val_out = 0x0000
46565 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_DUPLEX)
46566 +                                       ? BMCR_FULLDPLX : 0)
46567 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED100)
46568 +                                       ? BMCR_SPEED100 : 0)
46569 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED1000)
46570 +                                       ? BMCR_SPEED1000 : 0);
46571 +               } else if ((data->reg_num & 0x1F) == MII_BMSR) {
46572 +                       /* Make up MII status register value from what we know */
46573 +                       data->val_out =
46574 +                       (BMSR_100FULL|BMSR_100HALF|BMSR_10FULL|BMSR_10HALF)
46575 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_LINK)
46576 +                                       ? BMSR_LSTATUS : 0);
46577 +               } else {
46578 +                       return -EIO;
46579 +               }
46580 +               break;
46581 +
46582 +       case SIOCSMIIREG:
46583 +               return -EOPNOTSUPP;
46584 +               break;
46585 +
46586 +       default:
46587 +               return -EOPNOTSUPP;
46588 +       }
46589 +
46590 +       return 0;
46591 +}
46592 +
46593 +/*
46594 + * Return statistics to the caller
46595 + */
46596 +static struct net_device_stats *ubi32_eth_get_stats(struct net_device *dev)
46597 +{
46598 +       return &dev->stats;
46599 +}
46600 +
46601 +
46602 +static int ubi32_eth_change_mtu(struct net_device *dev, int new_mtu)
46603 +{
46604 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46605 +       unsigned long flags;
46606 +
46607 +       if ((new_mtu < 68) || (new_mtu > 1500))
46608 +               return -EINVAL;
46609 +
46610 +       spin_lock_irqsave(&priv->lock, flags);
46611 +       dev->mtu = new_mtu;
46612 +       spin_unlock_irqrestore(&priv->lock, flags);
46613 +       printk(KERN_INFO "set mtu to %d", new_mtu);
46614 +       return 0;
46615 +}
46616 +
46617 +/*
46618 + * ubi32_eth_cleanup: unload the module
46619 + */
46620 +void ubi32_eth_cleanup(void)
46621 +{
46622 +       struct ubi32_eth_private *priv;
46623 +       struct net_device *dev;
46624 +       int i;
46625 +
46626 +       for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46627 +               dev = ubi32_eth_devices[i];
46628 +               if (dev) {
46629 +                       priv = netdev_priv(dev);
46630 +                       kfree(priv->regs->tx_dma_ring);
46631 +                       unregister_netdev(dev);
46632 +                       free_netdev(dev);
46633 +                       ubi32_eth_devices[i] = NULL;
46634 +               }
46635 +       }
46636 +}
46637 +
46638 +int ubi32_eth_init_module(void)
46639 +{
46640 +       struct ethtionode *eth_node;
46641 +       struct net_device *dev;
46642 +       struct ubi32_eth_private *priv;
46643 +       int i, err;
46644 +
46645 +       /*
46646 +        * Device allocation.
46647 +        */
46648 +       err = 0;
46649 +       for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46650 +               /*
46651 +                * See if the eth_vp is in the device tree.
46652 +                */
46653 +               eth_node = (struct ethtionode *)devtree_find_node(eth_if_name[i]);
46654 +               if (!eth_node) {
46655 +                       printk(KERN_INFO "%s does not exist\n", eth_if_name[i]);
46656 +                       continue;
46657 +               }
46658 +
46659 +               eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46660 +                               sizeof(struct ubi32_eth_dma_desc *) *
46661 +                               (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE),
46662 +                               GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
46663 +
46664 +               if (eth_node->tx_dma_ring == NULL) {
46665 +                       eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46666 +                               sizeof(struct ubi32_eth_dma_desc *) *
46667 +                               (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE), GFP_KERNEL);
46668 +                       printk(KERN_INFO "fail to allocate from OCM\n");
46669 +               }
46670 +
46671 +               if (!eth_node->tx_dma_ring) {
46672 +                       err = -ENOMEM;
46673 +                       break;
46674 +               }
46675 +               eth_node->rx_dma_ring = eth_node->tx_dma_ring + TX_DMA_RING_SIZE;
46676 +               eth_node->tx_sz = TX_DMA_RING_SIZE - 1;
46677 +               eth_node->rx_sz = RX_DMA_RING_SIZE - 1;
46678 +
46679 +               dev = alloc_etherdev(sizeof(struct ubi32_eth_private));
46680 +               if (!dev) {
46681 +                       kfree(eth_node->tx_dma_ring);
46682 +                       err = -ENOMEM;
46683 +                       break;
46684 +               }
46685 +               priv = netdev_priv(dev);
46686 +               priv->dev = dev;
46687 +
46688 +               /*
46689 +                * This just fill in some default Ubicom MAC address
46690 +                */
46691 +               memcpy(dev->dev_addr, mac_addr[i], ETH_ALEN);
46692 +               memset(dev->broadcast, 0xff, ETH_ALEN);
46693 +
46694 +               priv->regs = eth_node;
46695 +               priv->regs->command = 0;
46696 +               priv->regs->int_mask = 0;
46697 +               priv->regs->int_status = 0;
46698 +               priv->regs->tx_out = 0;
46699 +               priv->regs->rx_out = 0;
46700 +               priv->regs->tx_in = 0;
46701 +               priv->regs->rx_in = 0;
46702 +               priv->rx_tail = 0;
46703 +               priv->tx_tail = 0;
46704 +
46705 +               priv->vp_int_bit = eth_node->dn.sendirq;
46706 +               dev->irq = eth_node->dn.recvirq;
46707 +
46708 +               spin_lock_init(&priv->lock);
46709 +
46710 +               dev->open               = ubi32_eth_open;
46711 +               dev->stop               = ubi32_eth_close;
46712 +               dev->hard_start_xmit    = ubi32_eth_start_xmit;
46713 +               dev->tx_timeout         = ubi32_eth_tx_timeout;
46714 +               dev->watchdog_timeo     = UBI32_ETH_VP_TX_TIMEOUT;
46715 +
46716 +               dev->set_config         = ubi32_eth_set_config;
46717 +               dev->do_ioctl           = ubi32_eth_ioctl;
46718 +               dev->get_stats          = ubi32_eth_get_stats;
46719 +               dev->change_mtu         = ubi32_eth_change_mtu;
46720 +#ifdef UBICOM32_USE_NAPI
46721 +               netif_napi_add(dev, &priv->napi, ubi32_eth_napi_poll, UBI32_ETH_NAPI_WEIGHT);
46722 +#endif
46723 +               err = register_netdev(dev);
46724 +               if (err) {
46725 +                       printk(KERN_WARNING "Failed to register netdev %s\n", eth_if_name[i]);
46726 +                       //release_region();
46727 +                       free_netdev(dev);
46728 +                       kfree(eth_node->tx_dma_ring);
46729 +                       break;
46730 +               }
46731 +
46732 +               ubi32_eth_devices[i] = dev;
46733 +               printk(KERN_INFO "%s vp_base:0x%p, tio_int:%d irq:%d feature:0x%lx\n",
46734 +                       dev->name, priv->regs, eth_node->dn.sendirq, dev->irq, dev->features);
46735 +       }
46736 +
46737 +       if (err) {
46738 +               ubi32_eth_cleanup();
46739 +               return err;
46740 +       }
46741 +
46742 +       if (!ubi32_eth_devices[0] && !ubi32_eth_devices[1]) {
46743 +               return -ENODEV;
46744 +       }
46745 +
46746 +#if defined(UBICOM32_USE_POLLING)
46747 +       init_timer(&eth_poll_timer);
46748 +       eth_poll_timer.function = ubi32_eth_poll;
46749 +       eth_poll_timer.data = (unsigned long)0;
46750 +       eth_poll_timer.expires = jiffies + 2;
46751 +       add_timer(&eth_poll_timer);
46752 +#endif
46753 +
46754 +       return 0;
46755 +}
46756 +
46757 +module_init(ubi32_eth_init_module);
46758 +module_exit(ubi32_eth_cleanup);
46759 +
46760 +MODULE_AUTHOR("Kan Yan, Greg Ren");
46761 +MODULE_LICENSE("GPL");
46762 diff -ruN linux-2.6.30.10/drivers/net/ubi32-eth.h linux-2.6.30.10-ubi/drivers/net/ubi32-eth.h
46763 --- linux-2.6.30.10/drivers/net/ubi32-eth.h     1970-01-01 02:00:00.000000000 +0200
46764 +++ linux-2.6.30.10-ubi/drivers/net/ubi32-eth.h 2009-12-11 11:45:18.000000000 +0200
46765 @@ -0,0 +1,132 @@
46766 +/*
46767 + * drivers/net/ubi32-eth.h
46768 + *   Ubicom32 ethernet TIO interface driver definitions.
46769 + *
46770 + * (C) Copyright 2009, Ubicom, Inc.
46771 + *
46772 + * This file is part of the Ubicom32 Linux Kernel Port.
46773 + *
46774 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46775 + * it and/or modify it under the terms of the GNU General Public License
46776 + * as published by the Free Software Foundation, either version 2 of the
46777 + * License, or (at your option) any later version.
46778 + *
46779 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46780 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46781 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
46782 + * the GNU General Public License for more details.
46783 + *
46784 + * You should have received a copy of the GNU General Public License
46785 + * along with the Ubicom32 Linux Kernel Port.  If not,
46786 + * see <http://www.gnu.org/licenses/>.
46787 + *
46788 + * Ubicom32 implementation derived from (with many thanks):
46789 + *   arch/m68knommu
46790 + *   arch/blackfin
46791 + *   arch/parisc
46792 + */
46793 +#ifndef _UBI32_ETH_H
46794 +#define _UBI32_ETH_H
46795 +
46796 +#include <asm/devtree.h>
46797 +
46798 +#define UBI32_ETH_NUM_OF_DEVICES 2
46799 +
46800 +/*
46801 + * Number of bytes trashed beyond the packet data.
46802 + */
46803 +#define UBI32_ETH_TRASHED_MEMORY       (CACHE_LINE_SIZE + ETH_HLEN - 1)
46804 +
46805 +/*
46806 + * Linux already reserves NET_SKB_PAD bytes of headroom in each sk_buff.
46807 + * We want to be able to reserve at least one cache line to align Ethernet
46808 + * and IP header to cache line.
46809 + * Note that the TIO expects a CACHE_LINE_SIZE - ETH_HLEN aligned Ethernet
46810 + * header, while satisfies NET_IP_ALIGN (= 2) automatically.
46811 + * (NET_SKB_PAD is 16, NET_IP_ALIGN is 2, CACHE_LINE_SIZE is 32).
46812 + * You can add more space by making UBI32_ETH_RESERVE_EXTRA != 0.
46813 + */
46814 +#define UBI32_ETH_RESERVE_EXTRA (1 * CACHE_LINE_SIZE)
46815 +#define UBI32_ETH_RESERVE_SPACE        (UBI32_ETH_RESERVE_EXTRA + CACHE_LINE_SIZE)
46816 +
46817 +struct ubi32_eth_dma_desc {
46818 +       volatile void   *data_pointer;  /* pointer to the buffer */
46819 +       volatile u16    buffer_len;     /* the buffer size */
46820 +       volatile u16    data_len;       /* actual frame length */
46821 +       volatile u32    status;         /* bit0: status to be update by VP; bit[31:1] time stamp */
46822 +};
46823 +
46824 +#define TX_DMA_RING_SIZE (1<<8)
46825 +#define TX_DMA_RING_MASK (TX_DMA_RING_SIZE - 1)
46826 +#define RX_DMA_RING_SIZE (1<<8)
46827 +#define RX_DMA_RING_MASK (RX_DMA_RING_SIZE - 1)
46828 +
46829 +#define RX_DMA_MAX_QUEUE_SIZE (RX_DMA_RING_SIZE - 1)   /* no more than (RX_DMA_RING_SIZE - 1) */
46830 +#define RX_MAX_PKT_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN)
46831 +#define RX_MIN_PKT_SIZE        ETH_ZLEN
46832 +#define RX_BUF_SIZE (RX_MAX_PKT_SIZE + VLAN_HLEN)      /* allow double VLAN tag */
46833 +
46834 +#define UBI32_ETH_VP_TX_TIMEOUT (10*HZ)
46835 +
46836 +struct ubi32_eth_vp_stats {
46837 +       u32     rx_alloc_err;
46838 +       u32     tx_q_full_cnt;
46839 +       u32     rx_q_full_cnt;
46840 +       u32     rx_throttle;
46841 +};
46842 +
46843 +struct ubi32_eth_private {
46844 +       struct net_device *dev;
46845 +       struct ubi32_eth_vp_stats vp_stats;
46846 +       spinlock_t lock;
46847 +#ifdef UBICOM32_USE_NAPI
46848 +       struct napi_struct napi;
46849 +#else
46850 +       struct tasklet_struct tsk;
46851 +#endif
46852 +       struct ethtionode *regs;
46853 +       u16     rx_tail;
46854 +       u16     tx_tail;
46855 +       u32     vp_int_bit;
46856 +};
46857 +
46858 +struct ethtionode {
46859 +       struct devtree_node dn;
46860 +       volatile u16    command;
46861 +       volatile u16    status;
46862 +       volatile u16    int_mask;       /* interrupt mask */
46863 +       volatile u16    int_status;     /* interrupt mask */
46864 +       volatile u16    tx_in;          /* owned by driver */
46865 +       volatile u16    tx_out;         /* owned by vp */
46866 +       volatile u16    rx_in;          /* owned by driver */
46867 +       volatile u16    rx_out;         /* owned by vp */
46868 +       u16             tx_sz;          /* owned by driver */
46869 +       u16             rx_sz;          /* owned by driver */
46870 +       struct ubi32_eth_dma_desc **tx_dma_ring;
46871 +       struct ubi32_eth_dma_desc **rx_dma_ring;
46872 +};
46873 +
46874 +#define UBI32_ETH_VP_STATUS_LINK       (1<<0)
46875 +#define UBI32_ETH_VP_STATUS_SPEED100   (0x1<<1)
46876 +#define UBI32_ETH_VP_STATUS_SPEED1000  (0x1<<2)
46877 +#define UBI32_ETH_VP_STATUS_DUPLEX     (0x1<<3)
46878 +#define UBI32_ETH_VP_STATUS_FLOW_CTRL  (0x1<<4)
46879 +
46880 +#define UBI32_ETH_VP_STATUS_RX_STATE   (0x1<<5)
46881 +#define UBI32_ETH_VP_STATUS_TX_STATE   (0x1<<6)
46882 +
46883 +#define UBI32_ETH_VP_STATUS_TX_Q_FULL  (1<<8)
46884 +
46885 +#define UBI32_ETH_VP_INT_RX    (1<<0)
46886 +#define UBI32_ETH_VP_INT_TX    (1<<1)
46887 +
46888 +#define UBI32_ETH_VP_CMD_RX_ENABLE     (1<<0)
46889 +#define UBI32_ETH_VP_CMD_TX_ENABLE     (1<<1)
46890 +
46891 +#define UBI32_ETH_VP_RX_OK             (1<<0)
46892 +#define UBI32_ETH_VP_TX_OK             (1<<1)
46893 +
46894 +#define UBI32_TX_BOUND         TX_DMA_RING_SIZE
46895 +#define UBI32_RX_BOUND         64
46896 +#define UBI32_ETH_NAPI_WEIGHT  64              /* for GigE */
46897 +#endif
46898 diff -ruN linux-2.6.30.10/drivers/net/usb/asix.c linux-2.6.30.10-ubi/drivers/net/usb/asix.c
46899 --- linux-2.6.30.10/drivers/net/usb/asix.c      2009-12-04 08:00:07.000000000 +0200
46900 +++ linux-2.6.30.10-ubi/drivers/net/usb/asix.c  2009-12-11 11:45:18.000000000 +0200
46901 @@ -319,14 +319,33 @@
46902                 /* get the packet length */
46903                 size = (u16) (header & 0x0000ffff);
46904  
46905 -               if ((skb->len) - ((size + 1) & 0xfffe) == 0)
46906 +               if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
46907 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46908 +                       if (((u32)packet & 0x02) == 0) {
46909 +                               memmove(packet - 2, packet, size);
46910 +                               skb->data -= 2;
46911 +                               skb->tail -= 2;
46912 +                       }
46913 +#endif
46914                         return 2;
46915 +               }
46916 +
46917                 if (size > ETH_FRAME_LEN) {
46918                         deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
46919                         return 0;
46920                 }
46921                 ax_skb = skb_clone(skb, GFP_ATOMIC);
46922                 if (ax_skb) {
46923 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46924 +                       if (((u32)packet & 0x02) == 0) {
46925 +                               memmove(packet - 2, packet, size);
46926 +                               ax_skb->data = packet - 2;
46927 +                       } else {
46928 +                               ax_skb->data = packet;
46929 +                       }
46930 +#else
46931 +                       ax_skb->data = packet;
46932 +#endif
46933                         ax_skb->len = size;
46934                         ax_skb->data = packet;
46935                         skb_set_tail_pointer(ax_skb, size);
46936 @@ -1125,13 +1144,19 @@
46937         mode = AX88178_MEDIUM_DEFAULT;
46938  
46939         if (ecmd.speed == SPEED_1000)
46940 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46941                 mode |= AX_MEDIUM_GM;
46942 +#else
46943 +               mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
46944 +#endif
46945         else if (ecmd.speed == SPEED_100)
46946                 mode |= AX_MEDIUM_PS;
46947         else
46948                 mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
46949  
46950 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46951         mode |= AX_MEDIUM_ENCK;
46952 +#endif
46953  
46954         if (ecmd.duplex == DUPLEX_FULL)
46955                 mode |= AX_MEDIUM_FD;
46956 diff -ruN linux-2.6.30.10/drivers/oprofile/cpu_buffer.c linux-2.6.30.10-ubi/drivers/oprofile/cpu_buffer.c
46957 --- linux-2.6.30.10/drivers/oprofile/cpu_buffer.c       2009-12-04 08:00:07.000000000 +0200
46958 +++ linux-2.6.30.10-ubi/drivers/oprofile/cpu_buffer.c   2009-12-11 11:45:18.000000000 +0200
46959 @@ -328,10 +328,10 @@
46960  }
46961  
46962  static inline void
46963 -__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46964 -                         unsigned long event, int is_kernel)
46965 +__oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
46966 +                             unsigned long event, int is_kernel, int cpu)
46967  {
46968 -       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
46969 +       struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
46970         unsigned long backtrace = oprofile_backtrace_depth;
46971  
46972         /*
46973 @@ -353,7 +353,8 @@
46974  void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46975                              unsigned long event, int is_kernel)
46976  {
46977 -       __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46978 +       __oprofile_add_ext_sample_cpu(pc, regs, event,
46979 +                                     is_kernel, smp_processor_id());
46980  }
46981  
46982  void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
46983 @@ -361,7 +362,8 @@
46984         int is_kernel = !user_mode(regs);
46985         unsigned long pc = profile_pc(regs);
46986  
46987 -       __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46988 +       __oprofile_add_ext_sample_cpu(pc, regs, event,
46989 +                                     is_kernel, smp_processor_id());
46990  }
46991  
46992  /*
46993 diff -ruN linux-2.6.30.10/drivers/pci/Makefile linux-2.6.30.10-ubi/drivers/pci/Makefile
46994 --- linux-2.6.30.10/drivers/pci/Makefile        2009-12-04 08:00:07.000000000 +0200
46995 +++ linux-2.6.30.10-ubi/drivers/pci/Makefile    2009-12-11 11:45:18.000000000 +0200
46996 @@ -44,8 +44,8 @@
46997  obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
46998  obj-$(CONFIG_X86_VISWS) += setup-irq.o
46999  obj-$(CONFIG_MN10300) += setup-bus.o
47000 +obj-$(CONFIG_UBICOM32) += setup-bus.o setup-irq.o
47001  
47002 -#
47003  # ACPI Related PCI FW Functions
47004  #
47005  obj-$(CONFIG_ACPI)    += pci-acpi.o
47006 diff -ruN linux-2.6.30.10/drivers/serial/Kconfig linux-2.6.30.10-ubi/drivers/serial/Kconfig
47007 --- linux-2.6.30.10/drivers/serial/Kconfig      2009-12-04 08:00:07.000000000 +0200
47008 +++ linux-2.6.30.10-ubi/drivers/serial/Kconfig  2009-12-11 11:45:19.000000000 +0200
47009 @@ -871,6 +871,57 @@
47010           console (the system console is the device which receives all kernel
47011           messages and warnings and which allows logins in single user mode).
47012  
47013 +config SERIAL_UBI32_UARTTIO
47014 +        tristate "Ubicom UARTTIO support"
47015 +        depends on UBICOM32=y
47016 +        select SERIAL_CORE
47017 +       default y
47018 +        help
47019 +          Add support for the Ubicom virtual peripherial serial interface.
47020 +
47021 +config SERIAL_UBI32_UARTTIO_NR_UARTS
47022 +       int "Maximum number of UARTTIO virtual serial ports"
47023 +       depends on SERIAL_UBI32_UARTTIO
47024 +       default "4"
47025 +       help
47026 +         Set this to the maximum number of serial ports you want the driver to support.
47027 +
47028 +config SERIAL_UBI32_UARTTIO_CONSOLE
47029 +        tristate "Ubicom UARTTIO console support"
47030 +        depends on SERIAL_UBI32_UARTTIO=y
47031 +        select SERIAL_CORE_CONSOLE
47032 +       default y
47033 +        help
47034 +          Add support for console on the Ubicom virtual peripherial serial interface.
47035 +
47036 +config SERIAL_UBI32_SERDES
47037 +        bool "Ubicom serial port support"
47038 +        depends on UBICOM32=y
47039 +        select SERIAL_CORE
47040 +       default y
47041 +        help
47042 +          Add support for the Ubicom serial interface.
47043 +
47044 +config SERIAL_UBI32_SERDES_CONSOLE
47045 +        bool "Ubicom serial console support"
47046 +        depends on SERIAL_UBI32_SERDES=y
47047 +        select SERIAL_CORE_CONSOLE
47048 +       default y
47049 +
47050 +config SERIAL_UBI32_MAILBOX
47051 +        bool "Ubicom mailbox support"
47052 +        depends on UBICOM32=y
47053 +        select SERIAL_CORE
47054 +       default n
47055 +        help
47056 +          Add support for the Ubicom mailbox interface.
47057 +
47058 +config SERIAL_UBI32_MAILBOX_CONSOLE
47059 +        bool "Ubicom mailbox console support"
47060 +        depends on SERIAL_UBI32_MAILBOX=y
47061 +        select SERIAL_CORE_CONSOLE
47062 +       default y
47063 +
47064  config SERIAL_SUNCORE
47065         bool
47066         depends on SPARC
47067 diff -ruN linux-2.6.30.10/drivers/serial/Makefile linux-2.6.30.10-ubi/drivers/serial/Makefile
47068 --- linux-2.6.30.10/drivers/serial/Makefile     2009-12-04 08:00:07.000000000 +0200
47069 +++ linux-2.6.30.10-ubi/drivers/serial/Makefile 2009-12-11 11:45:19.000000000 +0200
47070 @@ -77,3 +77,6 @@
47071  obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
47072  obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
47073  obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
47074 +obj-$(CONFIG_SERIAL_UBI32_SERDES) += ubi32_serdes.o
47075 +obj-$(CONFIG_SERIAL_UBI32_UARTTIO) += ubi32_uarttio.o
47076 +obj-$(CONFIG_SERIAL_UBI32_MAILBOX) += ubi32_mailbox.o
47077 diff -ruN linux-2.6.30.10/drivers/serial/ubi32_mailbox.c linux-2.6.30.10-ubi/drivers/serial/ubi32_mailbox.c
47078 --- linux-2.6.30.10/drivers/serial/ubi32_mailbox.c      1970-01-01 02:00:00.000000000 +0200
47079 +++ linux-2.6.30.10-ubi/drivers/serial/ubi32_mailbox.c  2009-12-11 11:45:19.000000000 +0200
47080 @@ -0,0 +1,928 @@
47081 +/*
47082 + * drivers/serial/ubi32_mailbox.c
47083 + *   Ubicom32 On-Chip Mailbox Driver
47084 + *
47085 + * (C) Copyright 2009, Ubicom, Inc.
47086 + *
47087 + * This file is part of the Ubicom32 Linux Kernel Port.
47088 + *
47089 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
47090 + * it and/or modify it under the terms of the GNU General Public License
47091 + * as published by the Free Software Foundation, either version 2 of the
47092 + * License, or (at your option) any later version.
47093 + *
47094 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
47095 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
47096 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
47097 + * the GNU General Public License for more details.
47098 + *
47099 + * You should have received a copy of the GNU General Public License
47100 + * along with the Ubicom32 Linux Kernel Port.  If not,
47101 + * see <http://www.gnu.org/licenses/>.
47102 + *
47103 + * Ubicom32 implementation derived from (with many thanks):
47104 + *   arch/m68knommu
47105 + *   arch/blackfin
47106 + *   arch/parisc
47107 + */
47108 +#include <linux/module.h>
47109 +#include <linux/ioport.h>
47110 +#include <linux/init.h>
47111 +#include <linux/console.h>
47112 +#include <linux/sysrq.h>
47113 +#include <linux/platform_device.h>
47114 +#include <linux/tty.h>
47115 +#include <linux/tty_flip.h>
47116 +#include <linux/serial_core.h>
47117 +
47118 +#include <asm/ip5000.h>
47119 +
47120 +#define SERIAL_UBICOM_BAUDRATE 115200
47121 +#define SERIAL_UBICOM_DATA_BIT 8       /* Fixed parameter - do not change */
47122 +#define SERIAL_UBICOM_PAR_BIT  0       /* Fixed parameter - do not change */
47123 +#define SERIAL_UBICOM_STOP_BIT 1       /* Fixed parameter - do not change */
47124 +
47125 +/* UART name and device definitions */
47126 +#define UBI32_MAILBOX_NAME     "ttyUM" // XXX
47127 +#define UBI32_MAILBOX_MAJOR    207 // XXX
47128 +#define UBI32_MAILBOX_MINOR    64
47129 +
47130 +#define PORT_UBI32_MAILBOX     1235
47131 +#define NR_PORTS 1
47132 +
47133 +#define get_sclk() 0
47134 +
47135 +struct ubi32_mailbox_port {
47136 +       struct uart_port port;
47137 +       /*
47138 +        * NOTE (rkeller):
47139 +        * the uart port is wrapped in another structure in case we need to hold more state than
47140 +        * what we can hold in the uart_port.
47141 +        * Not sure if we need this, I took over the concept from the blackfin driver.
47142 +        */
47143 +} ubi32_mailbox_ports[NR_PORTS];
47144 +
47145 +struct ubi32_mailbox_resource {
47146 +       int uart_base_addr;
47147 +       int uart_irq;
47148 +} ubi32_mailbox_resource[NR_PORTS] = {
47149 +       /*
47150 +        * uart_base_addr has to be non-NULL because it is put in the uart_port membase.
47151 +        * If membase if null the kernel skips the configuration and our port_type never gets set.
47152 +        */
47153 +       {ISD_MAILBOX_BASE, ISD_MAILBOX_INT}
47154 +};
47155 +
47156 +static volatile struct ubicom32_isd_mailbox {
47157 +       volatile u32_t in;
47158 +       volatile u32_t out;
47159 +       volatile u32_t status;
47160 +} *ubi32_mailbox = (struct ubicom32_isd_mailbox *)ISD_MAILBOX_BASE;
47161 +
47162 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart);
47163 +
47164 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart);
47165 +
47166 +#define TRUE 1
47167 +#define FALSE 0
47168 +
47169 +static int mailbox_console_flg = TRUE;
47170 +static int num_timeouts = 0;
47171 +
47172 +/*
47173 + * dummy functions and defined to be able to compile the Blackfin code
47174 + */
47175 +#define UART_GET_LSR(port) (1)
47176 +#define UART_PUT_LSR(port, bits)
47177 +#define UART_CLEAR_LSR(port) (1)
47178 +#define TEMT 1
47179 +#define TFI 1
47180 +#define BI 1
47181 +#define PE 1
47182 +#define OE 1
47183 +#define FE 1
47184 +#define THRE 1
47185 +#define DR 1
47186 +#define UART_GET_LCR(port) (1)
47187 +#define UART_PUT_LCR(port, bits)
47188 +#define SB 1
47189 +#define STB 1
47190 +#define PEN 1
47191 +#define EPS 1
47192 +#define STP 1
47193 +#define WLS(n) 0
47194 +#define UART_GET_IER(port) (1)
47195 +#define UART_SET_IER(port, bits)
47196 +#define UART_CLEAR_IER(port, bits)
47197 +#define ETBEI 0
47198 +#define ERBFI 0
47199 +#define UART_GET_CHAR(port) ubi32_mailbox_get_char()
47200 +#define UART_PUT_CHAR(port, ch) ubi32_mailbox_put_char(ch)
47201 +#define SSYNC()
47202 +#define UART_GET_DLL(port) 0
47203 +#define UART_PUT_DLL(port, ch)
47204 +#define UART_GET_DLH(port) 0
47205 +#define UART_PUT_DLH(port, ch)
47206 +#define UART_GET_GCTL(port) (0)
47207 +#define UART_PUT_GCTL(port, ch)
47208 +#define UCEN 1
47209 +
47210 +/*
47211 + * ubi32_mailbox_get_char_avail()
47212 + */
47213 +static int ubi32_mailbox_get_char_avail(void)
47214 +{
47215 +       return !(ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
47216 +}
47217 +
47218 +/*
47219 + * ubi32_mailbox_get_char()
47220 + */
47221 +static u32_t ubi32_mailbox_get_char(void)
47222 +{
47223 +       if (mailbox_console_flg == TRUE) {
47224 +               /*
47225 +                * Mailbox console is connected.
47226 +                */
47227 +               while (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
47228 +               return ubi32_mailbox->in & 0xff;
47229 +       }
47230 +
47231 +       /*
47232 +        * Mailbox console was not connected.
47233 +        */
47234 +       if (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY) {
47235 +               return 0xff;
47236 +       }
47237 +
47238 +       /*
47239 +        * Mailbox console is connecting.
47240 +        */
47241 +       mailbox_console_flg = TRUE;
47242 +       num_timeouts = 0;
47243 +       return ubi32_mailbox->in & 0xff;
47244 +}
47245 +
47246 +#define MAILBOX_MAX_ATTEMPTS 1000000
47247 +#define MAILBOX_MAX_TIMEOUTS 5
47248 +/*
47249 + * ubi32_mailbox_put_char()
47250 + */
47251 +static void ubi32_mailbox_put_char(u32_t v)
47252 +{
47253 +       /*
47254 +        * Wait to be able to output.
47255 +        */
47256 +       u32_t num_attempts = 0;
47257 +
47258 +       if(mailbox_console_flg == TRUE) {
47259 +               while(num_attempts++ < MAILBOX_MAX_ATTEMPTS) {
47260 +                       if(ubi32_mailbox->status & ISD_MAILBOX_STATUS_OUT_EMPTY) {
47261 +                               break;
47262 +                       }
47263 +               }
47264 +
47265 +               /*
47266 +                * If timed out more than 5 times on send, mailbox console is disconnected now.
47267 +                */
47268 +               if (num_attempts > MAILBOX_MAX_ATTEMPTS) {
47269 +                       if (num_timeouts++ > MAILBOX_MAX_TIMEOUTS) {
47270 +                               mailbox_console_flg = FALSE;
47271 +                       }
47272 +               }
47273 +       }
47274 +
47275 +       asm volatile(
47276 +               "pipe_flush 0   \n\t"
47277 +               "pipe_flush 0   \n\t"
47278 +               "pipe_flush 0   \n\t"
47279 +               "pipe_flush 0   \n\t"
47280 +               "pipe_flush 0   \n\t"
47281 +               "pipe_flush 0   \n\t"
47282 +               "pipe_flush 0   \n\t"
47283 +       );
47284 +
47285 +       ubi32_mailbox->out = v & 0xff;
47286 +}
47287 +
47288 +static void ubi32_mailbox_hw_init(struct ubi32_mailbox_port *uart)
47289 +{
47290 +// NOTE: It does not do any good to do these here because we are running on the linux hardware thread,
47291 +//     and these have to be called on the ldsr thread.
47292 +//     ubicom32_clear_interrupt(ISD_MAILBOX_INT);
47293 +//     ubicom32_enable_interrupt(ISD_MAILBOX_INT);
47294 +}
47295 +
47296 +/*
47297 + * interrupts are disabled on entry
47298 + */
47299 +static void ubi32_mailbox_stop_tx(struct uart_port *port)
47300 +{
47301 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47302 +//     struct circ_buf *xmit = &uart->port.info->xmit;
47303 +
47304 +       while (!(UART_GET_LSR(uart) & TEMT))
47305 +               cpu_relax();
47306 +
47307 +       /* Clear TFI bit */
47308 +       UART_PUT_LSR(uart, TFI);
47309 +       UART_CLEAR_IER(uart, ETBEI);
47310 +}
47311 +
47312 +/*
47313 + * port is locked and interrupts are disabled
47314 + */
47315 +static void ubi32_mailbox_start_tx(struct uart_port *port)
47316 +{
47317 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47318 +
47319 +       UART_SET_IER(uart, ETBEI);
47320 +
47321 +       ubi32_mailbox_tx_chars(uart);
47322 +}
47323 +
47324 +/*
47325 + * Interrupts are enabled
47326 + */
47327 +static void ubi32_mailbox_stop_rx(struct uart_port *port)
47328 +{
47329 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47330 +       UART_CLEAR_IER(uart, ERBFI);
47331 +}
47332 +
47333 +/*
47334 + * Set the modem control timer to fire immediately.
47335 + */
47336 +static void ubi32_mailbox_enable_ms(struct uart_port *port)
47337 +{
47338 +}
47339 +
47340 +static void ubi32_mailbox_rx_chars(struct ubi32_mailbox_port *uart)
47341 +{
47342 +       struct uart_info *info = uart->port.info;
47343 +       struct tty_struct *tty = info->port.tty;
47344 +       unsigned int status, ch, flg;
47345 +
47346 +       status = 0; // XXX? UART_GET_LSR(uart);
47347 +       UART_CLEAR_LSR(uart);
47348 +
47349 +       ch = UART_GET_CHAR(uart);
47350 +
47351 +       if(ch == 0xff)
47352 +               return;
47353 +
47354 +       uart->port.icount.rx++;
47355 +
47356 +       if (status & BI) {
47357 +               uart->port.icount.brk++;
47358 +               if (uart_handle_break(&uart->port))
47359 +                       goto ignore_char;
47360 +               status &= ~(PE | FE);
47361 +       }
47362 +       if (status & PE)
47363 +               uart->port.icount.parity++;
47364 +       if (status & OE)
47365 +               uart->port.icount.overrun++;
47366 +       if (status & FE)
47367 +               uart->port.icount.frame++;
47368 +
47369 +       status &= uart->port.read_status_mask;
47370 +
47371 +       if (status & BI)
47372 +               flg = TTY_BREAK;
47373 +       else if (status & PE)
47374 +               flg = TTY_PARITY;
47375 +       else if (status & FE)
47376 +               flg = TTY_FRAME;
47377 +       else
47378 +               flg = TTY_NORMAL;
47379 +
47380 +       if (uart_handle_sysrq_char(&uart->port, ch))
47381 +               goto ignore_char;
47382 +
47383 +       uart_insert_char(&uart->port, status, OE, ch, flg);
47384 +
47385 + ignore_char:
47386 +       tty_flip_buffer_push(tty);
47387 +}
47388 +
47389 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart)
47390 +{
47391 +       struct circ_buf *xmit = &uart->port.info->xmit;
47392 +
47393 +       if (uart->port.x_char) {
47394 +               UART_PUT_CHAR(uart, uart->port.x_char);
47395 +               uart->port.icount.tx++;
47396 +               uart->port.x_char = 0;
47397 +       }
47398 +       /*
47399 +        * Check the modem control lines before
47400 +        * transmitting anything.
47401 +        */
47402 +       ubi32_mailbox_mctrl_check(uart);
47403 +
47404 +       if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
47405 +               ubi32_mailbox_stop_tx(&uart->port);
47406 +               return;
47407 +       }
47408 +
47409 +       while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
47410 +               UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
47411 +               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
47412 +               uart->port.icount.tx++;
47413 +               SSYNC();
47414 +       }
47415 +
47416 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
47417 +               uart_write_wakeup(&uart->port);
47418 +
47419 +       if (uart_circ_empty(xmit))
47420 +               ubi32_mailbox_stop_tx(&uart->port);
47421 +}
47422 +
47423 +static irqreturn_t ubi32_mailbox_isr(int irq, void *dev_id)
47424 +{
47425 +       struct ubi32_mailbox_port *uart = dev_id;
47426 +
47427 +       spin_lock(&uart->port.lock);
47428 +
47429 +       //XXX?while (UART_GET_LSR(uart) & DR)
47430 +
47431 +       /*
47432 +        * RX process
47433 +        */
47434 +       while (ubi32_mailbox_get_char_avail()) {
47435 +               ubi32_mailbox_rx_chars(uart);
47436 +       }
47437 +
47438 +#if 0
47439 +       /*
47440 +        * TX process
47441 +        */
47442 +       if (this_uart.tx_in == this_uart.tx_out) {
47443 +               UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask &= ~IO_PORTX_INT_SERDES_TXBE;
47444 +       } else if (UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_status & IO_PORTX_INT_SERDES_TXBE) {
47445 +               uart_ubicom32_send(this_uart.tx_buf[this_uart.tx_out & (SERIAL_UBICOM_BUF_SIZE - 1)]);
47446 +               this_uart.tx_out++;
47447 +               UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask |= IO_PORTX_INT_SERDES_TXBE;
47448 +       }
47449 +#endif
47450 +
47451 +       spin_unlock(&uart->port.lock);
47452 +
47453 +       return IRQ_HANDLED;
47454 +}
47455 +#if 0
47456 +static irqreturn_t ubi32_mailbox_tx_int(int irq, void *dev_id)
47457 +{
47458 +       struct ubi32_mailbox_port *uart = dev_id;
47459 +
47460 +       spin_lock(&uart->port.lock);
47461 +       if (UART_GET_LSR(uart) & THRE)
47462 +               ubi32_mailbox_tx_chars(uart);
47463 +       spin_unlock(&uart->port.lock);
47464 +
47465 +       return IRQ_HANDLED;
47466 +}
47467 +#endif
47468 +
47469 +/*
47470 + * Return TIOCSER_TEMT when transmitter is not busy.
47471 + */
47472 +static unsigned int ubi32_mailbox_tx_empty(struct uart_port *port)
47473 +{
47474 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47475 +       unsigned short lsr;
47476 +
47477 +       lsr = UART_GET_LSR(uart);
47478 +       if (lsr & TEMT)
47479 +               return TIOCSER_TEMT;
47480 +       else
47481 +               return 0;
47482 +}
47483 +
47484 +static unsigned int ubi32_mailbox_get_mctrl(struct uart_port *port)
47485 +{
47486 +               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
47487 +}
47488 +
47489 +static void ubi32_mailbox_set_mctrl(struct uart_port *port, unsigned int mctrl)
47490 +{
47491 +}
47492 +
47493 +/*
47494 + * Handle any change of modem status signal since we were last called.
47495 + */
47496 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart)
47497 +{
47498 +}
47499 +
47500 +/*
47501 + * Interrupts are always disabled.
47502 + */
47503 +static void ubi32_mailbox_break_ctl(struct uart_port *port, int break_state)
47504 +{
47505 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47506 +       u16 lcr = UART_GET_LCR(uart);
47507 +       if (break_state)
47508 +               lcr |= SB;
47509 +       else
47510 +               lcr &= ~SB;
47511 +       UART_PUT_LCR(uart, lcr);
47512 +       SSYNC();
47513 +}
47514 +
47515 +static int ubi32_mailbox_startup(struct uart_port *port)
47516 +{
47517 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47518 +
47519 +       if (request_irq(uart->port.irq, ubi32_mailbox_isr, IRQF_DISABLED,
47520 +            "UBI32_MAILBOX", uart)) {
47521 +               printk(KERN_NOTICE "Unable to attach Ubicom32 SERDES interrupt\n");
47522 +               return -EBUSY;
47523 +       }
47524 +
47525 +       UART_SET_IER(uart, ERBFI);
47526 +       return 0;
47527 +}
47528 +
47529 +static void ubi32_mailbox_shutdown(struct uart_port *port)
47530 +{
47531 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47532 +
47533 +       free_irq(uart->port.irq, uart);
47534 +}
47535 +
47536 +static void
47537 +ubi32_mailbox_set_termios(struct uart_port *port, struct ktermios *termios,
47538 +                  struct ktermios *old)
47539 +{
47540 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47541 +       unsigned long flags;
47542 +       unsigned int baud, quot;
47543 +       unsigned short val, ier, lsr, lcr = 0;
47544 +
47545 +       switch (termios->c_cflag & CSIZE) {
47546 +       case CS8:
47547 +               lcr = WLS(8);
47548 +               break;
47549 +       case CS7:
47550 +               lcr = WLS(7);
47551 +               break;
47552 +       case CS6:
47553 +               lcr = WLS(6);
47554 +               break;
47555 +       case CS5:
47556 +               lcr = WLS(5);
47557 +               break;
47558 +       default:
47559 +               printk(KERN_ERR "%s: word lengh not supported\n",
47560 +                       __FUNCTION__);
47561 +       }
47562 +
47563 +       if (termios->c_cflag & CSTOPB)
47564 +               lcr |= STB;
47565 +       if (termios->c_cflag & PARENB)
47566 +               lcr |= PEN;
47567 +       if (!(termios->c_cflag & PARODD))
47568 +               lcr |= EPS;
47569 +       if (termios->c_cflag & CMSPAR)
47570 +               lcr |= STP;
47571 +
47572 +       port->read_status_mask = OE;
47573 +       if (termios->c_iflag & INPCK)
47574 +               port->read_status_mask |= (FE | PE);
47575 +       if (termios->c_iflag & (BRKINT | PARMRK))
47576 +               port->read_status_mask |= BI;
47577 +
47578 +       /*
47579 +        * Characters to ignore
47580 +        */
47581 +       port->ignore_status_mask = 0;
47582 +       if (termios->c_iflag & IGNPAR)
47583 +               port->ignore_status_mask |= FE | PE;
47584 +       if (termios->c_iflag & IGNBRK) {
47585 +               port->ignore_status_mask |= BI;
47586 +               /*
47587 +                * If we're ignoring parity and break indicators,
47588 +                * ignore overruns too (for real raw support).
47589 +                */
47590 +               if (termios->c_iflag & IGNPAR)
47591 +                       port->ignore_status_mask |= OE;
47592 +       }
47593 +
47594 +       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
47595 +       quot = uart_get_divisor(port, baud);
47596 +       spin_lock_irqsave(&uart->port.lock, flags);
47597 +
47598 +       do {
47599 +               lsr = UART_GET_LSR(uart);
47600 +       } while (!(lsr & TEMT));
47601 +
47602 +       /* Disable UART */
47603 +       ier = UART_GET_IER(uart);
47604 +       UART_CLEAR_IER(uart, 0xF);
47605 +
47606 +       UART_PUT_DLL(uart, quot & 0xFF);
47607 +       SSYNC();
47608 +       UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
47609 +       SSYNC();
47610 +
47611 +       UART_PUT_LCR(uart, lcr);
47612 +
47613 +       /* Enable UART */
47614 +       UART_SET_IER(uart, ier);
47615 +
47616 +       val = UART_GET_GCTL(uart);
47617 +       val |= UCEN;
47618 +       UART_PUT_GCTL(uart, val);
47619 +
47620 +       spin_unlock_irqrestore(&uart->port.lock, flags);
47621 +}
47622 +
47623 +static const char *ubi32_mailbox_type(struct uart_port *port)
47624 +{
47625 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47626 +
47627 +       return uart->port.type == PORT_UBI32_MAILBOX ? "UBI32_MAILBOX" : NULL;
47628 +}
47629 +
47630 +/*
47631 + * Release the memory region(s) being used by 'port'.
47632 + */
47633 +static void ubi32_mailbox_release_port(struct uart_port *port)
47634 +{
47635 +}
47636 +
47637 +/*
47638 + * Request the memory region(s) being used by 'port'.
47639 + */
47640 +static int ubi32_mailbox_request_port(struct uart_port *port)
47641 +{
47642 +       return 0;
47643 +}
47644 +
47645 +/*
47646 + * Configure/autoconfigure the port.
47647 + */
47648 +static void ubi32_mailbox_config_port(struct uart_port *port, int flags)
47649 +{
47650 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47651 +
47652 +       if (flags & UART_CONFIG_TYPE && ubi32_mailbox_request_port(&uart->port) == 0)
47653 +               uart->port.type = PORT_UBI32_MAILBOX;
47654 +}
47655 +
47656 +/*
47657 + * Verify the new serial_struct (for TIOCSSERIAL).
47658 + * The only change we allow are to the flags and type, and
47659 + * even then only between PORT_UBI32_MAILBOX and PORT_UNKNOWN
47660 + */
47661 +static int
47662 +ubi32_mailbox_verify_port(struct uart_port *port, struct serial_struct *ser)
47663 +{
47664 +       return 0;
47665 +}
47666 +
47667 +static struct uart_ops ubi32_mailbox_pops = {
47668 +       .tx_empty       = ubi32_mailbox_tx_empty,
47669 +       .set_mctrl      = ubi32_mailbox_set_mctrl,
47670 +       .get_mctrl      = ubi32_mailbox_get_mctrl,
47671 +       .stop_tx        = ubi32_mailbox_stop_tx,
47672 +       .start_tx       = ubi32_mailbox_start_tx,
47673 +       .stop_rx        = ubi32_mailbox_stop_rx,
47674 +       .enable_ms      = ubi32_mailbox_enable_ms,
47675 +       .break_ctl      = ubi32_mailbox_break_ctl,
47676 +       .startup        = ubi32_mailbox_startup,
47677 +       .shutdown       = ubi32_mailbox_shutdown,
47678 +       .set_termios    = ubi32_mailbox_set_termios,
47679 +       .type           = ubi32_mailbox_type,
47680 +       .release_port   = ubi32_mailbox_release_port,
47681 +       .request_port   = ubi32_mailbox_request_port,
47682 +       .config_port    = ubi32_mailbox_config_port,
47683 +       .verify_port    = ubi32_mailbox_verify_port,
47684 +};
47685 +
47686 +static void __init ubi32_mailbox_init_ports(void)
47687 +{
47688 +       static int first = 1;
47689 +       int i;
47690 +
47691 +       if (!first)
47692 +               return;
47693 +       first = 0;
47694 +
47695 +       for (i = 0; i < NR_PORTS; i++) {
47696 +               ubi32_mailbox_ports[i].port.uartclk   = get_sclk();
47697 +               ubi32_mailbox_ports[i].port.ops       = &ubi32_mailbox_pops;
47698 +               ubi32_mailbox_ports[i].port.line      = i;
47699 +               ubi32_mailbox_ports[i].port.iotype    = UPIO_MEM;
47700 +               ubi32_mailbox_ports[i].port.membase   =
47701 +                       (void __iomem *)ubi32_mailbox_resource[i].uart_base_addr;
47702 +               ubi32_mailbox_ports[i].port.mapbase   =
47703 +                       ubi32_mailbox_resource[i].uart_base_addr;
47704 +               ubi32_mailbox_ports[i].port.irq       =
47705 +                       ubi32_mailbox_resource[i].uart_irq;
47706 +               ubi32_mailbox_ports[i].port.flags     = UPF_BOOT_AUTOCONF;
47707 +               spin_lock_init(&ubi32_mailbox_ports[i].port.lock);
47708 +
47709 +               ubi32_mailbox_hw_init(&ubi32_mailbox_ports[i]);
47710 +       }
47711 +
47712 +}
47713 +
47714 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47715 +/*
47716 + * If the port was already initialised (eg, by a boot loader),
47717 + * try to determine the current setup.
47718 + */
47719 +static void __init
47720 +ubi32_mailbox_console_get_options(struct ubi32_mailbox_port *uart, int *baud,
47721 +                          int *parity, int *bits)
47722 +{
47723 +       unsigned short status;
47724 +
47725 +       status = UART_GET_IER(uart) & (ERBFI | ETBEI);
47726 +       if (status == (ERBFI | ETBEI)) {
47727 +               /* ok, the port was enabled */
47728 +               unsigned short lcr;
47729 +               unsigned short dlh, dll;
47730 +
47731 +               lcr = UART_GET_LCR(uart);
47732 +
47733 +               *parity = 'n';
47734 +               if (lcr & PEN) {
47735 +                       if (lcr & EPS)
47736 +                               *parity = 'e';
47737 +                       else
47738 +                               *parity = 'o';
47739 +               }
47740 +               switch (lcr & 0x03) {
47741 +                       case 0: *bits = 5; break;
47742 +                       case 1: *bits = 6; break;
47743 +                       case 2: *bits = 7; break;
47744 +                       case 3: *bits = 8; break;
47745 +               }
47746 +
47747 +               dll = UART_GET_DLL(uart);
47748 +               dlh = UART_GET_DLH(uart);
47749 +
47750 +               *baud = get_sclk() / (16*(dll | dlh << 8));
47751 +       }
47752 +       pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
47753 +}
47754 +#endif
47755 +
47756 +#if defined(CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
47757 +static struct uart_driver ubi32_mailbox_reg;
47758 +
47759 +static int __init
47760 +ubi32_mailbox_console_setup(struct console *co, char *options)
47761 +{
47762 +       struct ubi32_mailbox_port *uart;
47763 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47764 +       int baud = SERIAL_UBICOM_BAUDRATE;
47765 +       int bits = 8;
47766 +       int parity = 'n';
47767 +       int flow = 'n';
47768 +# endif
47769 +
47770 +       /*
47771 +        * Check whether an invalid uart number has been specified, and
47772 +        * if so, search for the first available port that does have
47773 +        * console support.
47774 +        */
47775 +       if (co->index == -1 || co->index >= NR_PORTS)
47776 +               co->index = 0;
47777 +       uart = &ubi32_mailbox_ports[co->index];
47778 +
47779 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47780 +       if (options)
47781 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
47782 +       else
47783 +               ubi32_mailbox_console_get_options(uart, &baud, &parity, &bits);
47784 +
47785 +       //JB return uart_set_options(&uart->port, co, baud, parity, bits, flow);
47786 +       return 0;
47787 +# else
47788 +       return 0;
47789 +# endif
47790 +}
47791 +#endif /* defined (CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) ||
47792 +                                defined (CONFIG_EARLY_PRINTK) */
47793 +
47794 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47795 +static void ubi32_mailbox_console_putchar(struct uart_port *port, int ch)
47796 +{
47797 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47798 +       while (!(UART_GET_LSR(uart) & THRE))
47799 +               barrier();
47800 +       UART_PUT_CHAR(uart, ch);
47801 +       SSYNC();
47802 +}
47803 +
47804 +/*
47805 + * Interrupts are disabled on entering
47806 + */
47807 +static void
47808 +ubi32_mailbox_console_write(struct console *co, const char *s, unsigned int count)
47809 +{
47810 +       struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[co->index];
47811 +       unsigned long flags = 0;
47812 +
47813 +       spin_lock_irqsave(&uart->port.lock, flags);
47814 +       uart_console_write(&uart->port, s, count, ubi32_mailbox_console_putchar);
47815 +       spin_unlock_irqrestore(&uart->port.lock, flags);
47816 +
47817 +}
47818 +
47819 +static struct console ubi32_mailbox_console = {
47820 +       .name           = UBI32_MAILBOX_NAME,
47821 +       .write          = ubi32_mailbox_console_write,
47822 +       .device         = uart_console_device,
47823 +       .setup          = ubi32_mailbox_console_setup,
47824 +       .flags          = CON_PRINTBUFFER,
47825 +       .index          = -1,
47826 +       .data           = &ubi32_mailbox_reg,
47827 +};
47828 +
47829 +static int __init ubi32_mailbox_console_init(void)
47830 +{
47831 +       ubi32_mailbox_init_ports();
47832 +       register_console(&ubi32_mailbox_console);
47833 +       return 0;
47834 +}
47835 +console_initcall(ubi32_mailbox_console_init);
47836 +
47837 +#define UBI32_MAILBOX_CONSOLE  &ubi32_mailbox_console
47838 +#else
47839 +#define UBI32_MAILBOX_CONSOLE  NULL
47840 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47841 +
47842 +
47843 +#ifdef CONFIG_EARLY_PRINTK
47844 +static __init void ubi32_mailbox_early_putc(struct uart_port *port, int ch)
47845 +{
47846 +       UART_PUT_CHAR(uart, ch);
47847 +}
47848 +
47849 +static __init void ubi32_mailbox_early_write(struct console *con, const char *s,
47850 +                                       unsigned int n)
47851 +{
47852 +       struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[con->index];
47853 +       unsigned int i;
47854 +
47855 +       for (i = 0; i < n; i++, s++) {
47856 +               if (*s == '\n')
47857 +                       ubi32_mailbox_early_putc(&uart->port, '\r');
47858 +               ubi32_mailbox_early_putc(&uart->port, *s);
47859 +       }
47860 +}
47861 +
47862 +static struct __init console ubi32_mailbox_early_console = {
47863 +       .name = "early_UM",
47864 +       .write = ubi32_mailbox_early_write,
47865 +       .device = uart_console_device,
47866 +       .flags = CON_PRINTBUFFER,
47867 +       .setup = ubi32_mailbox_console_setup,
47868 +       .index = -1,
47869 +       .data  = &ubi32_mailbox_reg,
47870 +};
47871 +
47872 +/*
47873 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
47874 + */
47875 +struct console __init *ubi32_mailbox_early_init(unsigned int port,
47876 +                                               unsigned int cflag)
47877 +{
47878 +       struct ubi32_mailbox_port *uart;
47879 +       struct ktermios t;
47880 +
47881 +       if (port == -1 || port >= NR_PORTS)
47882 +               port = 0;
47883 +       ubi32_mailbox_init_ports();
47884 +       ubi32_mailbox_early_console.index = port;
47885 +       uart = &ubi32_mailbox_ports[port];
47886 +       t.c_cflag = cflag;
47887 +       t.c_iflag = 0;
47888 +       t.c_oflag = 0;
47889 +       t.c_lflag = ICANON;
47890 +       t.c_line = port;
47891 +       ubi32_mailbox_set_termios(&uart->port, &t, &t);
47892 +       return &ubi32_mailbox_early_console;
47893 +}
47894 +
47895 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47896 +
47897 +static struct uart_driver ubi32_mailbox_reg = {
47898 +       .owner                  = THIS_MODULE,
47899 +       .driver_name            = "ubi32_mailbox",
47900 +       .dev_name               = UBI32_MAILBOX_NAME,
47901 +       .major                  = UBI32_MAILBOX_MAJOR,
47902 +       .minor                  = UBI32_MAILBOX_MINOR,
47903 +       .nr                     = NR_PORTS,
47904 +       .cons                   = UBI32_MAILBOX_CONSOLE,
47905 +};
47906 +
47907 +static int ubi32_mailbox_suspend(struct platform_device *dev, pm_message_t state)
47908 +{
47909 +       struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47910 +
47911 +       if (uart)
47912 +               uart_suspend_port(&ubi32_mailbox_reg, &uart->port);
47913 +
47914 +       return 0;
47915 +}
47916 +
47917 +static int ubi32_mailbox_resume(struct platform_device *dev)
47918 +{
47919 +       struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47920 +
47921 +       if (uart)
47922 +               uart_resume_port(&ubi32_mailbox_reg, &uart->port);
47923 +
47924 +       return 0;
47925 +}
47926 +
47927 +static int ubi32_mailbox_probe(struct platform_device *dev)
47928 +{
47929 +       struct resource *res = dev->resource;
47930 +       int i;
47931 +
47932 +       for (i = 0; i < dev->num_resources; i++, res++)
47933 +               if (res->flags & IORESOURCE_MEM)
47934 +                       break;
47935 +
47936 +       if (i < dev->num_resources) {
47937 +               for (i = 0; i < NR_PORTS; i++, res++) {
47938 +                       if (ubi32_mailbox_ports[i].port.mapbase != res->start)
47939 +                               continue;
47940 +                       ubi32_mailbox_ports[i].port.dev = &dev->dev;
47941 +                       uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[i].port);
47942 +                       platform_set_drvdata(dev, &ubi32_mailbox_ports[i]);
47943 +               }
47944 +       }
47945 +
47946 +       return 0;
47947 +}
47948 +
47949 +static int ubi32_mailbox_remove(struct platform_device *pdev)
47950 +{
47951 +       struct ubi32_mailbox_port *uart = platform_get_drvdata(pdev);
47952 +
47953 +       platform_set_drvdata(pdev, NULL);
47954 +
47955 +       if (uart)
47956 +               uart_remove_one_port(&ubi32_mailbox_reg, &uart->port);
47957 +
47958 +       return 0;
47959 +}
47960 +
47961 +static struct platform_driver ubi32_mailbox_driver = {
47962 +       .probe          = ubi32_mailbox_probe,
47963 +       .remove         = ubi32_mailbox_remove,
47964 +       .suspend        = ubi32_mailbox_suspend,
47965 +       .resume         = ubi32_mailbox_resume,
47966 +       .driver         = {
47967 +               .name   = "ubi32-mbox",
47968 +               .owner  = THIS_MODULE,
47969 +       },
47970 +};
47971 +
47972 +static int __init ubi32_mailbox_init(void)
47973 +{
47974 +       int ret;
47975 +
47976 +       pr_info("Serial: Ubicom32 mailbox serial driver.\n");
47977 +
47978 +       mailbox_console_flg = TRUE;
47979 +       num_timeouts = 0;
47980 +       ubi32_mailbox_init_ports();
47981 +
47982 +       ret = uart_register_driver(&ubi32_mailbox_reg);
47983 +       if (ret == 0) {
47984 +               ret = platform_driver_register(&ubi32_mailbox_driver);
47985 +               if (ret) {
47986 +                       pr_debug("uart register failed\n");
47987 +                       uart_unregister_driver(&ubi32_mailbox_reg);
47988 +               }
47989 +       }
47990 +
47991 +       /*
47992 +        * XXX HACK: currently probe does not get called, but the port needs to be added to work.
47993 +        */
47994 +       uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[0].port);
47995 +       return ret;
47996 +}
47997 +
47998 +static void __exit ubi32_mailbox_exit(void)
47999 +{
48000 +       platform_driver_unregister(&ubi32_mailbox_driver);
48001 +       uart_unregister_driver(&ubi32_mailbox_reg);
48002 +}
48003 +
48004 +module_init(ubi32_mailbox_init);
48005 +module_exit(ubi32_mailbox_exit);
48006 +
48007 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_MAILBOX_MAJOR);
48008 +MODULE_ALIAS("platform:ubi32_mailbox");
48009 diff -ruN linux-2.6.30.10/drivers/serial/ubi32_serdes.c linux-2.6.30.10-ubi/drivers/serial/ubi32_serdes.c
48010 --- linux-2.6.30.10/drivers/serial/ubi32_serdes.c       1970-01-01 02:00:00.000000000 +0200
48011 +++ linux-2.6.30.10-ubi/drivers/serial/ubi32_serdes.c   2009-12-11 11:45:19.000000000 +0200
48012 @@ -0,0 +1,817 @@
48013 +/*
48014 + * drivers/serial/ubi32_serdes.c
48015 + *   Ubicom32 On-Chip Serial Driver
48016 + *
48017 + * (C) Copyright 2009, Ubicom, Inc.
48018 + *
48019 + * This file is part of the Ubicom32 Linux Kernel Port.
48020 + *
48021 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
48022 + * it and/or modify it under the terms of the GNU General Public License
48023 + * as published by the Free Software Foundation, either version 2 of the
48024 + * License, or (at your option) any later version.
48025 + *
48026 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
48027 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
48028 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
48029 + * the GNU General Public License for more details.
48030 + *
48031 + * You should have received a copy of the GNU General Public License
48032 + * along with the Ubicom32 Linux Kernel Port.  If not,
48033 + * see <http://www.gnu.org/licenses/>.
48034 + *
48035 + * Ubicom32 implementation derived from (with many thanks):
48036 + *   arch/m68knommu
48037 + *   arch/blackfin
48038 + *   arch/parisc
48039 + */
48040 +#include <linux/module.h>
48041 +#include <linux/ioport.h>
48042 +#include <linux/init.h>
48043 +#include <linux/console.h>
48044 +#include <linux/sysrq.h>
48045 +#include <linux/platform_device.h>
48046 +#include <linux/tty.h>
48047 +#include <linux/tty_flip.h>
48048 +#include <linux/serial_core.h>
48049 +
48050 +#include <asm/ip5000.h>
48051 +#include <asm/ubicom32suart.h>
48052 +
48053 +
48054 +#define SERIAL_UBICOM_PIN_RXD  (1 << 0)
48055 +#define SERIAL_UBICOM_PIN_TXD  (1 << 6)
48056 +#define SERIAL_UBICOM_CTL0     0x8b300000
48057 +#define SERIAL_UBICOM_CTL1     0x00000009
48058 +
48059 +#define SERIAL_UBICOM_DATA_BIT 8       /* Fixed parameter - do not change */
48060 +#define SERIAL_UBICOM_PAR_BIT  0       /* Fixed parameter - do not change */
48061 +#define SERIAL_UBICOM_STOP_BIT 1       /* Fixed parameter - do not change */
48062 +
48063 +/* UART name and device definitions */
48064 +#define UBI32_SERDES_NAME      "ttyUS" // XXX
48065 +#define UBI32_SERDES_MAJOR     206 // XXX
48066 +#define UBI32_SERDES_MINOR     64 // XXX
48067 +
48068 +#define PORT_UBI32_SERDES      1234
48069 +#define NR_PORTS 1
48070 +
48071 +struct uart_port ubi32_serdes_ports[NR_PORTS];
48072 +
48073 +struct ubi32_serdes_resource {
48074 +       void *uart_base_addr;
48075 +       int uart_irq;
48076 +       int uart_clock;
48077 +} ubi32_serdes_resource[NR_PORTS] = {
48078 +       /*
48079 +        * Get params from kernel command line (required for early printk)
48080 +        * or from platform resources.
48081 +        */
48082 +       {0, 0, 0}
48083 +};
48084 +
48085 +/*
48086 + * Can get overridden by 'serdes=' kernel command line.
48087 + */
48088 +static int ubi32_serdes_default_baud_rate = 115200;
48089 +
48090 +
48091 +#define IO_PORT(port) ((struct ubicom32_io_port *)port->membase)
48092 +#define IO_PORT_INT_STATUS(port) (IO_PORT(port)->int_status)
48093 +#define IO_PORT_INT_MASK(port) (IO_PORT(port)->int_mask)
48094 +#define IO_PORT_INT_CLR(port) (IO_PORT(port)->int_clr)
48095 +
48096 +
48097 +/*
48098 + * ubi32_serdes_get_char()
48099 + */
48100 +static u8_t ubi32_serdes_get_char(struct ubicom32_io_port *io_port)
48101 +{
48102 +       /*
48103 +        * Read from hardware (forced 32-bit atomic read).
48104 +        */
48105 +       u32_t data = 0;
48106 +
48107 +       if ( io_port ) {
48108 +               io_port->int_clr = IO_PORTX_INT_SERDES_RXBF;
48109 +               asm volatile (
48110 +                       "move.4         %0, %1          \n\t"
48111 +                       : "=r" (data)
48112 +                       : "m" (*(u32_t *)&(io_port->rx_fifo))
48113 +                       );
48114 +       }
48115 +
48116 +       return (u8_t)(data & 0x000000ff);
48117 +}
48118 +
48119 +/*
48120 + * ubi32_serdes_put_char()
48121 + */
48122 +static void ubi32_serdes_put_char(struct ubicom32_io_port *io_port, u8_t c)
48123 +{
48124 +       u32_t data = 0x0000fe00 | (c << 1);
48125 +
48126 +       if ( io_port ) {
48127 +               /*
48128 +                * Fixed data format:
48129 +                * [LSB]1 start bit - 8 data bits - no parity - 1 stop bit[MSB]
48130 +                */
48131 +               io_port->int_clr = IO_PORTX_INT_SERDES_TXBE;
48132 +               io_port->ctl2 = data;
48133 +               io_port->int_set = IO_PORTX_INT_SERDES_TXBUF_VALID;
48134 +       }
48135 +}
48136 +
48137 +static void ubi32_serdes_hw_init(struct uart_port *port, int baud)
48138 +{
48139 +       struct ubicom32_io_port *io_port = IO_PORT(port);
48140 +
48141 +       if ( io_port ) {
48142 +               /*
48143 +                * Put port functions 1-4 into reset state.
48144 +                * Function 0 (GPIO) does not need or have a reset bit.
48145 +                *
48146 +                * Select SERDES function for restart below.
48147 +                */
48148 +               io_port->function =
48149 +                       IO_FUNC_FUNCTION_RESET(1) | IO_FUNC_FUNCTION_RESET(2) |
48150 +                       IO_FUNC_FUNCTION_RESET(3) | IO_FUNC_FUNCTION_RESET(4) |
48151 +                       IO_PORTX_FUNC_SERDES;
48152 +
48153 +               /*
48154 +                * Configure SERDES baudrate
48155 +                */
48156 +               if ( baud == 0 ) {
48157 +                       baud = ubi32_serdes_default_baud_rate;
48158 +               }
48159 +
48160 +               io_port->ctl0 =
48161 +                       SERIAL_UBICOM_CTL0 |
48162 +                       ((port->uartclk / (16 * baud)) - 1);
48163 +
48164 +               io_port->ctl1 =
48165 +                       SERIAL_UBICOM_CTL1;
48166 +
48167 +               /*
48168 +                * don't interrupt until startup and start_tx
48169 +                */
48170 +               io_port->int_mask = 0;
48171 +
48172 +               /*
48173 +                * Set TXD pin output, RXD input and prevent GPIO
48174 +                * override on the TXD & RXD pins
48175 +                */
48176 +               io_port->gpio_ctl &= ~SERIAL_UBICOM_PIN_RXD;
48177 +               io_port->gpio_ctl |= SERIAL_UBICOM_PIN_TXD;
48178 +               io_port->gpio_mask &= ~(SERIAL_UBICOM_PIN_RXD | SERIAL_UBICOM_PIN_TXD);
48179 +
48180 +               /*
48181 +                * Restart (un-reset) the port's SERDES function.
48182 +                */
48183 +               io_port->function &= ~(IO_FUNC_FUNCTION_RESET(IO_PORTX_FUNC_SERDES));
48184 +       }
48185 +}
48186 +
48187 +#define ULITE_STATUS_RXVALID IO_PORTX_INT_SERDES_RXBF
48188 +#define ULITE_STATUS_OVERRUN 0
48189 +#define ULITE_STATUS_FRAME 0
48190 +#define ULITE_STATUS_PARITY 0
48191 +#define ULITE_STATUS_TXEMPTY IO_PORTX_INT_SERDES_TXBE
48192 +#define ULITE_STATUS_TXFULL 0
48193 +
48194 +static int ubi32_serdes_receive(struct uart_port *port, int stat)
48195 +{
48196 +       struct tty_struct *tty = port->info->port.tty;
48197 +       unsigned char ch = 0;
48198 +       char flag = TTY_NORMAL;
48199 +
48200 +       if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
48201 +                    | ULITE_STATUS_FRAME)) == 0)
48202 +               return 0;
48203 +
48204 +       /* stats */
48205 +       if (stat & ULITE_STATUS_RXVALID) {
48206 +               port->icount.rx++;
48207 +               ch = ubi32_serdes_get_char((struct ubicom32_io_port *)port->membase);
48208 +
48209 +               if (stat & ULITE_STATUS_PARITY)
48210 +                       port->icount.parity++;
48211 +       }
48212 +
48213 +       if (stat & ULITE_STATUS_OVERRUN)
48214 +               port->icount.overrun++;
48215 +
48216 +       if (stat & ULITE_STATUS_FRAME)
48217 +               port->icount.frame++;
48218 +
48219 +
48220 +       /* drop byte with parity error if IGNPAR specificed */
48221 +       if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
48222 +               stat &= ~ULITE_STATUS_RXVALID;
48223 +
48224 +       stat &= port->read_status_mask;
48225 +
48226 +       if (stat & ULITE_STATUS_PARITY)
48227 +               flag = TTY_PARITY;
48228 +
48229 +       stat &= ~port->ignore_status_mask;
48230 +
48231 +       if (stat & ULITE_STATUS_RXVALID)
48232 +               tty_insert_flip_char(tty, ch, flag);
48233 +
48234 +       if (stat & ULITE_STATUS_FRAME)
48235 +               tty_insert_flip_char(tty, 0, TTY_FRAME);
48236 +
48237 +       if (stat & ULITE_STATUS_OVERRUN)
48238 +               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
48239 +
48240 +       return 1;
48241 +}
48242 +
48243 +/*
48244 + * interrupts are disabled on entry
48245 + */
48246 +static void ubi32_serdes_stop_tx(struct uart_port *port)
48247 +{
48248 +       IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) & ~IO_PORTX_INT_SERDES_TXBE;
48249 +}
48250 +
48251 +static int ubi32_serdes_transmit(struct uart_port *port, int stat)
48252 +{
48253 +       struct circ_buf *xmit  = &port->info->xmit;
48254 +
48255 +       if (!(stat & IO_PORTX_INT_SERDES_TXBE))
48256 +               return 0;
48257 +
48258 +       if (port->x_char) {
48259 +               ubi32_serdes_put_char(IO_PORT(port), port->x_char);
48260 +               port->x_char = 0;
48261 +               port->icount.tx++;
48262 +               return 1;
48263 +       }
48264 +
48265 +       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
48266 +               ubi32_serdes_stop_tx(port);
48267 +               return 0;
48268 +       }
48269 +
48270 +       ubi32_serdes_put_char(IO_PORT(port), xmit->buf[xmit->tail]);
48271 +       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
48272 +       port->icount.tx++;
48273 +
48274 +       /* wake up */
48275 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
48276 +               uart_write_wakeup(port);
48277 +
48278 +       if (uart_circ_empty(xmit))
48279 +               ubi32_serdes_stop_tx(port);
48280 +
48281 +       return 1;
48282 +}
48283 +
48284 +/*
48285 + * port is locked and interrupts are disabled
48286 + */
48287 +static void ubi32_serdes_start_tx(struct uart_port *port)
48288 +{
48289 +       IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) | IO_PORTX_INT_SERDES_TXBE;
48290 +       ubi32_serdes_transmit(port, IO_PORT_INT_STATUS(port));
48291 +}
48292 +
48293 +/*
48294 + * Interrupts are enabled
48295 + */
48296 +static void ubi32_serdes_stop_rx(struct uart_port *port)
48297 +{
48298 +       /* don't forward any more data (like !CREAD) */
48299 +       port->ignore_status_mask = IO_PORTX_INT_SERDES_RXBF;
48300 +}
48301 +
48302 +/*
48303 + * Set the modem control timer to fire immediately.
48304 + */
48305 +static void ubi32_serdes_enable_ms(struct uart_port *port)
48306 +{
48307 +       /* N/A */
48308 +}
48309 +
48310 +static irqreturn_t ubi32_serdes_isr(int irq, void *dev_id)
48311 +{
48312 +       struct uart_port *port = dev_id;
48313 +       int busy;
48314 +
48315 +       spin_lock(&port->lock);
48316 +
48317 +       do {
48318 +               int stat = IO_PORT_INT_STATUS(port);
48319 +               busy  = ubi32_serdes_receive(port, stat);
48320 +               busy |= ubi32_serdes_transmit(port, stat);
48321 +       } while (busy);
48322 +
48323 +       tty_flip_buffer_push(port->info->port.tty);
48324 +
48325 +       spin_unlock(&port->lock);
48326 +
48327 +       return IRQ_HANDLED;
48328 +}
48329 +
48330 +/*
48331 + * Return TIOCSER_TEMT when transmitter is not busy.
48332 + */
48333 +static unsigned int ubi32_serdes_tx_empty(struct uart_port *port)
48334 +{
48335 +       unsigned long flags;
48336 +       unsigned int ret;
48337 +
48338 +       spin_lock_irqsave(&port->lock, flags);
48339 +       ret = IO_PORT_INT_STATUS(port);
48340 +       spin_unlock_irqrestore(&port->lock, flags);
48341 +
48342 +       return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
48343 +}
48344 +
48345 +static unsigned int ubi32_serdes_get_mctrl(struct uart_port *port)
48346 +{
48347 +       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
48348 +}
48349 +
48350 +static void ubi32_serdes_set_mctrl(struct uart_port *port, unsigned int mctrl)
48351 +{
48352 +       /* N/A */
48353 +}
48354 +
48355 +/*
48356 + * Interrupts are always disabled.
48357 + */
48358 +static void ubi32_serdes_break_ctl(struct uart_port *port, int break_state)
48359 +{
48360 +       /* N/A */
48361 +}
48362 +
48363 +static int ubi32_serdes_startup(struct uart_port *port)
48364 +{
48365 +       if (request_irq(port->irq, ubi32_serdes_isr, IRQF_DISABLED,
48366 +            "UBI32_SERDES", port)) {
48367 +               printk(KERN_NOTICE "Unable to attach port interrupt\n");
48368 +               return -EBUSY;
48369 +       }
48370 +
48371 +       IO_PORT_INT_CLR(port) = IO_PORTX_INT_SERDES_RXBF;
48372 +       IO_PORT_INT_MASK(port) = IO_PORTX_INT_SERDES_RXBF;
48373 +       return 0;
48374 +}
48375 +
48376 +static void ubi32_serdes_shutdown(struct uart_port *port)
48377 +{
48378 +       struct ubi32_serdes_port *uart = (struct ubi32_serdes_port *)port;
48379 +
48380 +       IO_PORT_INT_MASK(port) = 0;
48381 +       free_irq(port->irq, uart);
48382 +}
48383 +
48384 +static void
48385 +ubi32_serdes_set_termios(struct uart_port *port, struct ktermios *termios,
48386 +                  struct ktermios *old)
48387 +{
48388 +       unsigned long flags;
48389 +       unsigned int baud;
48390 +
48391 +       spin_lock_irqsave(&port->lock, flags);
48392 +
48393 +       port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
48394 +               | ULITE_STATUS_TXFULL;
48395 +
48396 +       if (termios->c_iflag & INPCK)
48397 +               port->read_status_mask |=
48398 +                       ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
48399 +
48400 +       port->ignore_status_mask = 0;
48401 +       if (termios->c_iflag & IGNPAR)
48402 +               port->ignore_status_mask |= ULITE_STATUS_PARITY
48403 +                       | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48404 +
48405 +       /* ignore all characters if CREAD is not set */
48406 +       if ((termios->c_cflag & CREAD) == 0)
48407 +               port->ignore_status_mask |=
48408 +                       ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
48409 +                       | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48410 +
48411 +       /* update timeout */
48412 +       baud = uart_get_baud_rate(port, termios, old, 0, 460800);
48413 +       uart_update_timeout(port, termios->c_cflag, baud);
48414 +
48415 +       IO_PORT(port)->ctl0 = SERIAL_UBICOM_CTL0 |
48416 +                       ((port->uartclk / (16 * baud)) - 1);
48417 +
48418 +       spin_unlock_irqrestore(&port->lock, flags);
48419 +}
48420 +
48421 +static const char *ubi32_serdes_type(struct uart_port *port)
48422 +{
48423 +       return port->type == PORT_UBI32_SERDES ? "UBI32_SERDES" : NULL;
48424 +}
48425 +
48426 +/*
48427 + * Release the memory region(s) being used by 'port'.
48428 + */
48429 +static void ubi32_serdes_release_port(struct uart_port *port)
48430 +{
48431 +}
48432 +
48433 +/*
48434 + * Request the memory region(s) being used by 'port'.
48435 + */
48436 +static int ubi32_serdes_request_port(struct uart_port *port)
48437 +{
48438 +       return 0;
48439 +}
48440 +
48441 +/*
48442 + * Configure/autoconfigure the port.
48443 + */
48444 +static void ubi32_serdes_config_port(struct uart_port *port, int flags)
48445 +{
48446 +       if (flags & UART_CONFIG_TYPE &&
48447 +           ubi32_serdes_request_port(port) == 0)
48448 +               port->type = PORT_UBI32_SERDES;
48449 +}
48450 +
48451 +/*
48452 + * Verify the new serial_struct (for TIOCSSERIAL).
48453 + * The only change we allow are to the flags and type, and
48454 + * even then only between PORT_UBI32_SERDES and PORT_UNKNOWN
48455 + */
48456 +static int
48457 +ubi32_serdes_verify_port(struct uart_port *port, struct serial_struct *ser)
48458 +{
48459 +       return 0;
48460 +}
48461 +
48462 +static struct uart_ops ubi32_serdes_pops = {
48463 +       .tx_empty       = ubi32_serdes_tx_empty,
48464 +       .set_mctrl      = ubi32_serdes_set_mctrl,
48465 +       .get_mctrl      = ubi32_serdes_get_mctrl,
48466 +       .stop_tx        = ubi32_serdes_stop_tx,
48467 +       .start_tx       = ubi32_serdes_start_tx,
48468 +       .stop_rx        = ubi32_serdes_stop_rx,
48469 +       .enable_ms      = ubi32_serdes_enable_ms,
48470 +       .break_ctl      = ubi32_serdes_break_ctl,
48471 +       .startup        = ubi32_serdes_startup,
48472 +       .shutdown       = ubi32_serdes_shutdown,
48473 +       .set_termios    = ubi32_serdes_set_termios,
48474 +       .type           = ubi32_serdes_type,
48475 +       .release_port   = ubi32_serdes_release_port,
48476 +       .request_port   = ubi32_serdes_request_port,
48477 +       .config_port    = ubi32_serdes_config_port,
48478 +       .verify_port    = ubi32_serdes_verify_port,
48479 +};
48480 +
48481 +static void __init ubi32_serdes_init_ports(void)
48482 +{
48483 +       int i;
48484 +
48485 +       for (i = 0; i < NR_PORTS; i++) {
48486 +               ubi32_serdes_ports[i].uartclk   = ubi32_serdes_resource[i].uart_clock;
48487 +               ubi32_serdes_ports[i].ops       = &ubi32_serdes_pops;
48488 +               ubi32_serdes_ports[i].line      = i;
48489 +               ubi32_serdes_ports[i].iotype    = UPIO_MEM;
48490 +               ubi32_serdes_ports[i].membase   =
48491 +                       (void __iomem *)ubi32_serdes_resource[i].uart_base_addr;
48492 +               ubi32_serdes_ports[i].mapbase   =
48493 +                       (resource_size_t)ubi32_serdes_resource[i].uart_base_addr;
48494 +               ubi32_serdes_ports[i].irq       =
48495 +                       ubi32_serdes_resource[i].uart_irq;
48496 +               ubi32_serdes_ports[i].flags     = UPF_BOOT_AUTOCONF;
48497 +
48498 +               ubi32_serdes_hw_init(&ubi32_serdes_ports[i], 0);
48499 +       }
48500 +
48501 +}
48502 +
48503 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48504 +/*
48505 + * If the port was already initialised (eg, by a boot loader),
48506 + * try to determine the current setup.
48507 + */
48508 +static void __init
48509 +ubi32_serdes_console_get_options(struct uart_port *port, int *baud)
48510 +{
48511 +       u32 round_to = 1200;
48512 +       u32 real_baud;
48513 +
48514 +       /*
48515 +        * We might get called before platform init and with no
48516 +        * kernel command line options, so port might be NULL.
48517 +        */
48518 +       *baud = ubi32_serdes_default_baud_rate;;
48519 +       if ( IO_PORT(port) == 0 )
48520 +               return;
48521 +
48522 +       real_baud = port->uartclk
48523 +               / (16 * ((IO_PORT(port)->ctl0 & ~SERIAL_UBICOM_CTL0) + 1));
48524 +
48525 +       *baud = ((real_baud + round_to - 1) / round_to) * round_to;
48526 +
48527 +       pr_debug("%s:baud = %d, real_baud = %d\n", __FUNCTION__, *baud, real_baud);
48528 +}
48529 +#endif
48530 +
48531 +#if defined(CONFIG_SERIAL_UBI32_SERDES_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
48532 +static struct uart_driver ubi32_serdes_reg;
48533 +
48534 +static int __init
48535 +ubi32_serdes_console_setup(struct console *co, char *options)
48536 +{
48537 +       struct uart_port *port;
48538 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48539 +       int baud = ubi32_serdes_default_baud_rate;
48540 +       int bits = 8;
48541 +       int parity = 'n';
48542 +       int flow = 'n';
48543 +#endif
48544 +
48545 +       /*
48546 +        * Check whether an invalid uart number has been specified, and
48547 +        * if so, search for the first available port that does have
48548 +        * console support.
48549 +        */
48550 +       if (co->index == -1 || co->index >= NR_PORTS)
48551 +               co->index = 0;
48552 +       port = &ubi32_serdes_ports[co->index];
48553 +
48554 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48555 +       if (options) {
48556 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
48557 +               ubi32_serdes_hw_init(port, baud);
48558 +       }
48559 +       else
48560 +               ubi32_serdes_console_get_options(port, &baud);
48561 +
48562 +       return uart_set_options(port, co, baud, parity, bits, flow);
48563 +#else
48564 +       return 0;
48565 +#endif
48566 +}
48567 +#endif /* defined (CONFIG_SERIAL_UBI32_SERDES_CONSOLE) ||
48568 +                                defined (CONFIG_EARLY_PRINTK) */
48569 +
48570 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48571 +static void
48572 +ubi32_serdes_console_putchar(struct uart_port *port, int ch)
48573 +{
48574 +       if ( IO_PORT(port) ) {
48575 +               while (!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE))
48576 +                       barrier();
48577 +               ubi32_serdes_put_char(IO_PORT(port), ch);
48578 +       }
48579 +}
48580 +
48581 +/*
48582 + * Interrupts are disabled on entering
48583 + */
48584 +static void
48585 +ubi32_serdes_console_write(struct console *co, const char *s, unsigned int count)
48586 +{
48587 +       struct uart_port *port = &ubi32_serdes_ports[co->index];
48588 +       unsigned long flags = 0;
48589 +
48590 +       spin_lock_irqsave(&port->lock, flags);
48591 +       uart_console_write(port, s, count, ubi32_serdes_console_putchar);
48592 +       spin_unlock_irqrestore(&port->lock, flags);
48593 +
48594 +}
48595 +
48596 +static struct console ubi32_serdes_console = {
48597 +       .name           = UBI32_SERDES_NAME,
48598 +       .write          = ubi32_serdes_console_write,
48599 +       .device         = uart_console_device,
48600 +       .setup          = ubi32_serdes_console_setup,
48601 +       .flags          = CON_PRINTBUFFER,
48602 +       .index          = -1,
48603 +       .data           = &ubi32_serdes_reg,
48604 +};
48605 +
48606 +static int __init ubi32_serdes_console_init(void)
48607 +{
48608 +       ubi32_serdes_init_ports();
48609 +       register_console(&ubi32_serdes_console);
48610 +       return 0;
48611 +}
48612 +console_initcall(ubi32_serdes_console_init);
48613 +
48614 +#define UBI32_SERDES_CONSOLE   &ubi32_serdes_console
48615 +#else
48616 +#define UBI32_SERDES_CONSOLE   NULL
48617 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48618 +
48619 +
48620 +#ifdef CONFIG_EARLY_PRINTK
48621 +static __init void ubi32_serdes_early_putc(struct uart_port *port, int ch)
48622 +{
48623 +       unsigned timeout = 0xffff;
48624 +
48625 +       while ((!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE)) && --timeout)
48626 +               cpu_relax();
48627 +       ubi32_serdes_put_char(IO_PORT(port), ch);
48628 +}
48629 +
48630 +static __init void ubi32_serdes_early_write(struct console *con, const char *s,
48631 +                                       unsigned int n)
48632 +{
48633 +       struct uart_port *port = &ubi32_serdes_ports[con->index];
48634 +       unsigned int i;
48635 +
48636 +       for (i = 0; i < n; i++, s++) {
48637 +               if (*s == '\n')
48638 +                       ubi32_serdes_early_putc(port, '\r');
48639 +               ubi32_serdes_early_putc(port, *s);
48640 +       }
48641 +}
48642 +
48643 +static struct __init console ubi32_serdes_early_console = {
48644 +       .name = "early_US",
48645 +       .write = ubi32_serdes_early_write,
48646 +       .device = uart_console_device,
48647 +       .flags = CON_PRINTBUFFER,
48648 +       .setup = ubi32_serdes_console_setup,
48649 +       .index = -1,
48650 +       .data  = &ubi32_serdes_reg,
48651 +};
48652 +
48653 +/*
48654 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
48655 + */
48656 +struct console __init *ubi32_serdes_early_init(unsigned int port_index,
48657 +                                               unsigned int cflag)
48658 +{
48659 +       struct uart_port *uart;
48660 +       struct ktermios t;
48661 +
48662 +       if (port_index == -1 || port_index >= NR_PORTS)
48663 +               port_index = 0;
48664 +       ubi32_serdes_init_ports();
48665 +       ubi32_serdes_early_console.index = port_index;
48666 +       uart = &ubi32_serdes_ports[port_index];
48667 +       t.c_cflag = cflag;
48668 +       t.c_iflag = 0;
48669 +       t.c_oflag = 0;
48670 +       t.c_lflag = ICANON;
48671 +       t.c_line = port_index;
48672 +       ubi32_serdes_set_termios(uart, &t, &t);
48673 +       return &ubi32_serdes_early_console;
48674 +}
48675 +
48676 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48677 +
48678 +static struct uart_driver ubi32_serdes_reg = {
48679 +       .owner                  = THIS_MODULE,
48680 +       .driver_name            = "ubi32_serdes",
48681 +       .dev_name               = UBI32_SERDES_NAME,
48682 +       .major                  = UBI32_SERDES_MAJOR,
48683 +       .minor                  = UBI32_SERDES_MINOR,
48684 +       .nr                     = NR_PORTS,
48685 +       .cons                   = UBI32_SERDES_CONSOLE,
48686 +};
48687 +
48688 +static int ubi32_serdes_suspend(struct platform_device *dev, pm_message_t state)
48689 +{
48690 +       struct uart_port *port = platform_get_drvdata(dev);
48691 +
48692 +       if (port)
48693 +               uart_suspend_port(&ubi32_serdes_reg, port);
48694 +
48695 +       return 0;
48696 +}
48697 +
48698 +static int ubi32_serdes_resume(struct platform_device *dev)
48699 +{
48700 +       struct uart_port *port = platform_get_drvdata(dev);
48701 +
48702 +       if (port)
48703 +               uart_resume_port(&ubi32_serdes_reg, port);
48704 +
48705 +       return 0;
48706 +}
48707 +
48708 +static int ubi32_serdes_probe(struct platform_device *dev)
48709 +{
48710 +       struct resource *res = dev->resource;
48711 +       int i;
48712 +
48713 +       for (i = 0; i < dev->num_resources; i++, res++) {
48714 +               if (res->flags & IORESOURCE_MEM) {
48715 +                       ubi32_serdes_resource[0].uart_base_addr = (void *) res->start;
48716 +               }
48717 +               else if (res->flags & IORESOURCE_IRQ) {
48718 +                       ubi32_serdes_resource[0].uart_irq = res->start;
48719 +               }
48720 +               else if (res->flags & UBICOM32_SUART_IORESOURCE_CLOCK) {
48721 +                       ubi32_serdes_resource[0].uart_clock = res->start;
48722 +               }
48723 +       }
48724 +
48725 +       ubi32_serdes_init_ports();
48726 +
48727 +       return 0;
48728 +}
48729 +
48730 +static int ubi32_serdes_remove(struct platform_device *pdev)
48731 +{
48732 +       struct uart_port *port = platform_get_drvdata(pdev);
48733 +
48734 +       platform_set_drvdata(pdev, NULL);
48735 +
48736 +       if (port)
48737 +               uart_remove_one_port(&ubi32_serdes_reg, port);
48738 +
48739 +       return 0;
48740 +}
48741 +
48742 +static struct platform_driver ubi32_serdes_driver = {
48743 +       .remove         = ubi32_serdes_remove,
48744 +       .suspend        = ubi32_serdes_suspend,
48745 +       .resume         = ubi32_serdes_resume,
48746 +       .driver         = {
48747 +               .name   = "ubicom32suart",
48748 +               .owner  = THIS_MODULE,
48749 +       },
48750 +};
48751 +
48752 +
48753 +#ifndef MODULE
48754 +/*
48755 + * Called at boot time.
48756 + *
48757 + * You can specify IO base, IRQ, and clock for the serdes serial port
48758 + * using kernel command line "serdes=0xiobase,irq,clock".  Values
48759 + * specified will be overwritten by platform device data, if present.
48760 + */
48761 +static int __init ubi32_serdes_setup(char *str)
48762 +{
48763 +#define N_PARMS   (4+1)
48764 +       int ints[N_PARMS];
48765 +       int i;
48766 +
48767 +       str = get_options(str, ARRAY_SIZE(ints), ints);
48768 +
48769 +       for (i = 0; i < N_PARMS; i++) {
48770 +               if (i < ints[0]) {
48771 +                       if (i == 0) {
48772 +                               ubi32_serdes_resource[0].uart_base_addr = (void *) ints[i+1];
48773 +                       }
48774 +                       else if (i == 1) {
48775 +                               ubi32_serdes_resource[0].uart_irq = ints[i+1];
48776 +                       }
48777 +                       else if (i == 2) {
48778 +                               ubi32_serdes_resource[0].uart_clock = ints[i+1];
48779 +                       }
48780 +                       else if (i == 3) {
48781 +                               ubi32_serdes_default_baud_rate = ints[i+1];
48782 +                       }
48783 +               }
48784 +       }
48785 +       return 1;
48786 +}
48787 +
48788 +__setup("serdes=", ubi32_serdes_setup);
48789 +#endif
48790 +
48791 +static int __init ubi32_serdes_init(void)
48792 +{
48793 +       int ret;
48794 +
48795 +       pr_info("Serial: Ubicom32 serdes uart serial driver\n");
48796 +
48797 +       ret = platform_driver_probe(&ubi32_serdes_driver, ubi32_serdes_probe);
48798 +       if (ret != 0) {
48799 +               printk(KERN_INFO "serdes platform_driver_probe() failed: %d\n", ret);
48800 +               return ret;
48801 +       }
48802 +
48803 +       ubi32_serdes_init_ports();
48804 +
48805 +       ret = uart_register_driver(&ubi32_serdes_reg);
48806 +       if ( ret == 0 ) {
48807 +               ret = uart_add_one_port(&ubi32_serdes_reg, &ubi32_serdes_ports[0]);
48808 +               if ( ret != 0 ) {
48809 +                       uart_unregister_driver(&ubi32_serdes_reg);
48810 +               }
48811 +       }
48812 +
48813 +       return ret;
48814 +}
48815 +
48816 +static void __exit ubi32_serdes_exit(void)
48817 +{
48818 +       platform_driver_unregister(&ubi32_serdes_driver);
48819 +       uart_unregister_driver(&ubi32_serdes_reg);
48820 +}
48821 +
48822 +module_init(ubi32_serdes_init);
48823 +module_exit(ubi32_serdes_exit);
48824 +
48825 +MODULE_AUTHOR("Rainer Keller <rkeller@ubicom.com>");
48826 +MODULE_DESCRIPTION("Ubicom generic serial port driver");
48827 +MODULE_LICENSE("GPL");
48828 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_SERDES_MAJOR);
48829 +MODULE_ALIAS("platform:ubi32_serdes");
48830 diff -ruN linux-2.6.30.10/drivers/serial/ubi32_uarttio.c linux-2.6.30.10-ubi/drivers/serial/ubi32_uarttio.c
48831 --- linux-2.6.30.10/drivers/serial/ubi32_uarttio.c      1970-01-01 02:00:00.000000000 +0200
48832 +++ linux-2.6.30.10-ubi/drivers/serial/ubi32_uarttio.c  2009-12-11 11:45:19.000000000 +0200
48833 @@ -0,0 +1,1172 @@
48834 +/*
48835 + * drivers/serial/ubi32_uarttio.c
48836 + *   Ubicom32 Serial Virtual Peripherial Driver
48837 + *
48838 + * (C) Copyright 2009, Ubicom, Inc.
48839 + *
48840 + * This file is part of the Ubicom32 Linux Kernel Port.
48841 + *
48842 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
48843 + * it and/or modify it under the terms of the GNU General Public License
48844 + * as published by the Free Software Foundation, either version 2 of the
48845 + * License, or (at your option) any later version.
48846 + *
48847 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
48848 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
48849 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
48850 + * the GNU General Public License for more details.
48851 + *
48852 + * You should have received a copy of the GNU General Public License
48853 + * along with the Ubicom32 Linux Kernel Port.  If not,
48854 + * see <http://www.gnu.org/licenses/>.
48855 + */
48856 +
48857 +#include <linux/module.h>
48858 +#include <linux/ioport.h>
48859 +#include <linux/init.h>
48860 +#include <linux/console.h>
48861 +#include <linux/sysrq.h>
48862 +#include <linux/platform_device.h>
48863 +#include <linux/tty.h>
48864 +#include <linux/tty_flip.h>
48865 +#include <linux/serial_core.h>
48866 +
48867 +#include <asm/ip5000.h>
48868 +#include <asm/gpio.h>
48869 +#include <asm/thread.h>
48870 +#include <asm/uart_tio.h>
48871 +
48872 +#define DRIVER_NAME    "ubi32_uarttio"
48873 +
48874 +/*
48875 + * For storing the module parameters.
48876 + */
48877 +#define UBI32_UARTTIO_MAX_PARAM_LEN    80
48878 +static char utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN];
48879 +
48880 +/*
48881 + * UART name and device definitions
48882 + */
48883 +#define UBI32_UARTTIO_NAME     "ttyUV" // XXX
48884 +#define UBI32_UARTTIO_MAJOR    206 // XXX
48885 +#define UBI32_UARTTIO_MINOR    64 // XXX
48886 +
48887 +/*
48888 + * The following structures are allocated statically because the
48889 + * memory allocation subsystem is not initialized this early on
48890 + */
48891 +
48892 +/*
48893 + * Per port structure
48894 + */
48895 +struct ubi32_uarttio_port {
48896 +       struct uarttio_uart             *uart;
48897 +       unsigned int                    tx_pin;
48898 +       unsigned int                    rx_pin;
48899 +
48900 +       struct uart_port                port;
48901 +
48902 +       u8_t                            added;
48903 +
48904 +       /*
48905 +        * If this value is set, the port has had its direction set already
48906 +        */
48907 +       u8_t                            port_init;
48908 +};
48909 +static struct ubi32_uarttio_port uarttio_ports[CONFIG_SERIAL_UBI32_UARTTIO_NR_UARTS];
48910 +
48911 +/*
48912 + * Number of ports currently initialized
48913 + */
48914 +static int uarttio_nports;
48915 +
48916 +/*
48917 + * Per device structure
48918 + */
48919 +struct ubi32_uarttio_instance {
48920 +       struct uarttio_regs             *regs;
48921 +       struct ubi32_uarttio_port       *ports;
48922 +
48923 +       u8_t                            irq_requested;
48924 +       u8_t                            driver_registered;
48925 +       u8_t                            irq;
48926 +};
48927 +static struct ubi32_uarttio_instance uarttio_inst;
48928 +
48929 +#ifdef CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE
48930 +static struct console ubi32_uarttio_console;
48931 +#define UBI32_UARTTIO_CONSOLE  &ubi32_uarttio_console
48932 +#else
48933 +#define UBI32_UARTTIO_CONSOLE  NULL
48934 +#endif
48935 +
48936 +static struct uart_driver ubi32_uarttio_uart_driver = {
48937 +       .owner                  = THIS_MODULE,
48938 +       .driver_name            = DRIVER_NAME,
48939 +       .dev_name               = UBI32_UARTTIO_NAME,
48940 +       .major                  = UBI32_UARTTIO_MAJOR,
48941 +       .minor                  = UBI32_UARTTIO_MINOR,
48942 +       .cons                   = UBI32_UARTTIO_CONSOLE,
48943 +};
48944 +
48945 +#ifdef UBI32_UARTTIO_UNUSED
48946 +/*
48947 + * ubi32_uarttio_get_send_space
48948 + */
48949 +static int ubi32_uarttio_get_send_space(struct uarttio_uart *uart)
48950 +{
48951 +       int count = uart->tx_fifo_head - uart->tx_fifo_tail;
48952 +       if (count < 0) {
48953 +               count += uart->tx_fifo_size;
48954 +       }
48955 +       return uart->tx_fifo_size - count;
48956 +}
48957 +#endif
48958 +
48959 +/*
48960 + * ubi32_uarttio_get_recv_ready
48961 + */
48962 +static int ubi32_uarttio_get_recv_ready(struct uarttio_uart *uart)
48963 +{
48964 +       int count = uart->rx_fifo_head - uart->rx_fifo_tail;
48965 +       if (count < 0) {
48966 +               count += uart->rx_fifo_size;
48967 +       }
48968 +       return count;
48969 +}
48970 +
48971 +/*
48972 + * ubi32_uarttio_get_char()
48973 + */
48974 +static u8_t ubi32_uarttio_get_char(struct uarttio_uart *uart)
48975 +{
48976 +       /*
48977 +        * Retrieve byte
48978 +        */
48979 +       u32_t tail = uart->rx_fifo_tail;
48980 +       u8_t data = uart->rx_fifo[tail];
48981 +
48982 +       if (++tail == uart->rx_fifo_size) {
48983 +               tail = 0;
48984 +       }
48985 +       uart->rx_fifo_tail = tail;
48986 +
48987 +       return data;
48988 +}
48989 +
48990 +/*
48991 + * ubi32_uarttio_put_char()
48992 + */
48993 +static int ubi32_uarttio_put_char(struct uarttio_uart *uart, u8_t c)
48994 +{
48995 +       u32_t head = uart->tx_fifo_head;
48996 +       u32_t prev = head;
48997 +
48998 +       /*
48999 +        * Wrap
49000 +        */
49001 +       if (++head == uart->tx_fifo_size) {
49002 +               head = 0;
49003 +       }
49004 +
49005 +       /*
49006 +        * If there isn't any space, return EBUSY
49007 +        */
49008 +       if (head == uart->tx_fifo_tail) {
49009 +               return -EBUSY;
49010 +       }
49011 +
49012 +       /*
49013 +        * Put the character in the queue
49014 +        */
49015 +       uart->tx_fifo[prev] = c;
49016 +       uart->tx_fifo_head = head;
49017 +
49018 +       return 0;
49019 +}
49020 +
49021 +/*
49022 + * ubi32_uarttio_set_baud
49023 + */
49024 +static int ubi32_uarttio_set_baud(struct ubi32_uarttio_port *uup, unsigned int baud)
49025 +{
49026 +       if (uup->uart->current_baud_rate == baud) {
49027 +               return 0;
49028 +       }
49029 +
49030 +       uup->uart->baud_rate = baud;
49031 +       uup->uart->flags |= UARTTIO_UART_FLAG_SET_RATE;
49032 +       while (uup->uart->flags & UARTTIO_UART_FLAG_SET_RATE) {
49033 +               cpu_relax();
49034 +       }
49035 +
49036 +       if (uup->uart->current_baud_rate != baud) {
49037 +               /*
49038 +                * Failed to set baud rate
49039 +                */
49040 +               printk(KERN_WARNING "Invalid baud rate %u, running at %u\n", baud, uup->uart->current_baud_rate);
49041 +               return -EINVAL;
49042 +       }
49043 +
49044 +       return 0;
49045 +}
49046 +
49047 +/*
49048 + * ubi32_uarttio_handle_receive
49049 + */
49050 +static void ubi32_uarttio_handle_receive(struct ubi32_uarttio_port *uup, int stat)
49051 +{
49052 +       struct uarttio_uart *uart = uup->uart;
49053 +       struct uart_port *port = &uup->port;
49054 +       struct tty_struct *tty = port->info->port.tty;
49055 +       unsigned char ch = 0;
49056 +       char flag = TTY_NORMAL;
49057 +       int count;
49058 +
49059 +       if ((stat & (UARTTIO_UART_INT_RX | UARTTIO_UART_INT_RXFRAME | UARTTIO_UART_INT_RXOVF)) == 0) {
49060 +               return;
49061 +       }
49062 +
49063 +       if (stat & UARTTIO_UART_INT_RX) {
49064 +               count = ubi32_uarttio_get_recv_ready(uart);
49065 +               port->icount.rx += count;
49066 +       }
49067 +
49068 +       if (stat & UARTTIO_UART_INT_RXOVF) {
49069 +               port->icount.overrun++;
49070 +       }
49071 +
49072 +       if (stat & UARTTIO_UART_INT_RXFRAME) {
49073 +               port->icount.frame++;
49074 +       }
49075 +
49076 +       stat &= ~port->ignore_status_mask;
49077 +
49078 +       if (stat & UARTTIO_UART_INT_RX) {
49079 +               int i;
49080 +               for (i = 0; i < count; i++) {
49081 +                       ch = ubi32_uarttio_get_char(uart);
49082 +                       tty_insert_flip_char(tty, ch, flag);
49083 +               }
49084 +       }
49085 +
49086 +       if (stat & UARTTIO_UART_INT_RXFRAME) {
49087 +               tty_insert_flip_char(tty, 0, TTY_FRAME);
49088 +       }
49089 +
49090 +       if (stat & UARTTIO_UART_INT_RXOVF) {
49091 +               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
49092 +       }
49093 +}
49094 +
49095 +/*
49096 + * ubi32_uarttio_stop_tx
49097 + *     interrupts are disabled on entry
49098 + */
49099 +static void ubi32_uarttio_stop_tx(struct uart_port *port)
49100 +{
49101 +       struct ubi32_uarttio_port *uup = port->private_data;
49102 +
49103 +       uup->uart->int_mask &= ~UARTTIO_UART_INT_TXBE;
49104 +}
49105 +
49106 +/*
49107 + * ubi32_uarttio_handle_transmit
49108 + */
49109 +static void ubi32_uarttio_handle_transmit(struct ubi32_uarttio_port *uup, int stat)
49110 +{
49111 +       struct uarttio_uart *uart = uup->uart;
49112 +       struct uart_port *port = &uup->port;
49113 +       struct circ_buf *xmit  = &port->info->xmit;
49114 +
49115 +       if (!(stat & UARTTIO_UART_INT_TXBE)) {
49116 +               return;
49117 +       }
49118 +
49119 +       if (port->x_char) {
49120 +               if (ubi32_uarttio_put_char(uart, port->x_char)) {
49121 +                       return;
49122 +               }
49123 +               port->x_char = 0;
49124 +               port->icount.tx++;
49125 +               return;
49126 +       }
49127 +
49128 +       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
49129 +               ubi32_uarttio_stop_tx(port);
49130 +               return;
49131 +       }
49132 +
49133 +       /*
49134 +        * Send as many characters as we can
49135 +        */
49136 +       while (ubi32_uarttio_put_char(uart, xmit->buf[xmit->tail]) == 0) {
49137 +               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
49138 +               port->icount.tx++;
49139 +               if (uart_circ_empty(xmit)) {
49140 +                       break;
49141 +               }
49142 +       }
49143 +
49144 +       /* wake up */
49145 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
49146 +               uart_write_wakeup(port);
49147 +       }
49148 +
49149 +       if (uart_circ_empty(xmit)) {
49150 +               ubi32_uarttio_stop_tx(port);
49151 +       }
49152 +}
49153 +
49154 +/*
49155 + * ubi32_uarttio_start_tx
49156 + *     port is locked and interrupts are disabled
49157 + */
49158 +static void ubi32_uarttio_start_tx(struct uart_port *port)
49159 +{
49160 +       struct ubi32_uarttio_port *uup = port->private_data;
49161 +       struct uarttio_uart *uart = uup->uart;
49162 +
49163 +       uart->int_mask |= UARTTIO_UART_INT_TXBE;
49164 +}
49165 +
49166 +/*
49167 + * ubi32_uarttio_stop_rx
49168 + *     Interrupts are enabled
49169 + */
49170 +static void ubi32_uarttio_stop_rx(struct uart_port *port)
49171 +{
49172 +       struct ubi32_uarttio_port *uup = port->private_data;
49173 +       struct uarttio_uart *uart = uup->uart;
49174 +
49175 +       /*
49176 +        * don't forward any more data (like !CREAD)
49177 +        */
49178 +       uart->int_mask &= ~UARTTIO_UART_INT_RX;
49179 +       port->ignore_status_mask = UARTTIO_UART_INT_RX;
49180 +}
49181 +
49182 +/*
49183 + * ubi32_uarttio_enable_ms
49184 + *     Set the modem control timer to fire immediately.
49185 + */
49186 +static void ubi32_uarttio_enable_ms(struct uart_port *port)
49187 +{
49188 +       /* N/A */
49189 +}
49190 +
49191 +/*
49192 + * ubi32_uarttio_isr
49193 + */
49194 +static irqreturn_t ubi32_uarttio_isr(int irq, void *appdata)
49195 +{
49196 +       struct ubi32_uarttio_port *uup = uarttio_ports;
49197 +       int i;
49198 +
49199 +       /*
49200 +        * Service all of the ports
49201 +        */
49202 +       for (i = 0; i < uarttio_nports; i++) {
49203 +               unsigned int flags;
49204 +
49205 +               if (!(uup->uart->flags & UARTTIO_UART_FLAG_ENABLED)) {
49206 +                       uup++;
49207 +                       continue;
49208 +               }
49209 +
49210 +               spin_lock(&uup->port.lock);
49211 +
49212 +               flags = uup->uart->int_flags;
49213 +
49214 +               uup->uart->int_flags = 0;
49215 +
49216 +               ubi32_uarttio_handle_receive(uup, flags);
49217 +               ubi32_uarttio_handle_transmit(uup, flags);
49218 +
49219 +               tty_flip_buffer_push(uup->port.info->port.tty);
49220 +
49221 +               spin_unlock(&uup->port.lock);
49222 +
49223 +               uup++;
49224 +       }
49225 +
49226 +       return IRQ_HANDLED;
49227 +}
49228 +
49229 +/*
49230 + * ubi32_uarttio_tx_empty
49231 + *     Return TIOCSER_TEMT when transmitter is not busy.
49232 + */
49233 +static unsigned int ubi32_uarttio_tx_empty(struct uart_port *port)
49234 +{
49235 +       struct ubi32_uarttio_port *uup = port->private_data;
49236 +
49237 +       if (uup->uart->tx_fifo_head == uup->uart->tx_fifo_tail) {
49238 +               return TIOCSER_TEMT;
49239 +       }
49240 +
49241 +       return 0;
49242 +}
49243 +
49244 +/*
49245 + * ubi32_uarttio_get_mctrl
49246 + */
49247 +static unsigned int ubi32_uarttio_get_mctrl(struct uart_port *port)
49248 +{
49249 +       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
49250 +}
49251 +
49252 +/*
49253 + * ubi32_uarttio_set_mctrl
49254 + */
49255 +static void ubi32_uarttio_set_mctrl(struct uart_port *port, unsigned int mctrl)
49256 +{
49257 +       /* N/A */
49258 +}
49259 +
49260 +/*
49261 + * ubi32_uarttio_break_ctl
49262 + */
49263 +static void ubi32_uarttio_break_ctl(struct uart_port *port, int break_state)
49264 +{
49265 +       /* N/A */
49266 +}
49267 +
49268 +/*
49269 + * ubi32_uarttio_startup
49270 + */
49271 +static int ubi32_uarttio_startup(struct uart_port *port)
49272 +{
49273 +       struct ubi32_uarttio_port *uup = port->private_data;
49274 +       struct uarttio_uart *uart = uup->uart;
49275 +
49276 +       uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49277 +
49278 +       uart->int_mask |= UARTTIO_UART_INT_TXBE | UARTTIO_UART_INT_RX;
49279 +
49280 +       return 0;
49281 +}
49282 +
49283 +/*
49284 + * ubi32_uarttio_shutdown
49285 + */
49286 +static void ubi32_uarttio_shutdown(struct uart_port *port)
49287 +{
49288 +       struct ubi32_uarttio_port *uup = port->private_data;
49289 +       struct uarttio_uart *uart = uup->uart;
49290 +
49291 +       uart->int_mask = 0;
49292 +       uart->flags &= ~UARTTIO_UART_FLAG_ENABLED;
49293 +}
49294 +
49295 +/*
49296 + * ubi32_uarttio_set_termios
49297 + */
49298 +static void ubi32_uarttio_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
49299 +{
49300 +       struct ubi32_uarttio_port *uup = port->private_data;
49301 +       unsigned long flags;
49302 +       unsigned int baud;
49303 +
49304 +       spin_lock_irqsave(&port->lock, flags);
49305 +
49306 +#if 0
49307 +       port->read_status_mask = UBI32_UARTTIO_RX | UBI32_UARTTIO_RXOVF | UBI32_UARTTIO_TXOVF;
49308 +
49309 +       if (termios->c_iflag & INPCK) {
49310 +               port->read_status_mask |= UBI32_UARTTIO_RXFRAME;
49311 +       }
49312 +#endif
49313 +
49314 +       port->ignore_status_mask = 0;
49315 +       if (termios->c_iflag & IGNPAR) {
49316 +               port->ignore_status_mask |= UARTTIO_UART_INT_RXFRAME |
49317 +                                           UARTTIO_UART_INT_RXOVF;
49318 +       }
49319 +
49320 +       /*
49321 +        * ignore all characters if CREAD is not set
49322 +        */
49323 +       if ((termios->c_cflag & CREAD) == 0) {
49324 +               port->ignore_status_mask |= UARTTIO_UART_INT_RX |
49325 +                                           UARTTIO_UART_INT_RXFRAME |
49326 +                                           UARTTIO_UART_INT_RXOVF;
49327 +       }
49328 +
49329 +       /* update timeout */
49330 +       baud = uart_get_baud_rate(port, termios, old, 0, 460800);
49331 +       uart_update_timeout(port, termios->c_cflag, baud);
49332 +
49333 +       ubi32_uarttio_set_baud(uup, baud);
49334 +       spin_unlock_irqrestore(&port->lock, flags);
49335 +}
49336 +
49337 +/*
49338 + * ubi32_uarttio_type
49339 + */
49340 +static const char *ubi32_uarttio_type(struct uart_port *port)
49341 +{
49342 +       return (port->type == PORT_UBI32_UARTTIO) ? "UBI32_UARTTIO" : NULL;
49343 +}
49344 +
49345 +/*
49346 + * ubi32_uarttio_release_port
49347 + *     Release the memory region(s) being used by 'port'.
49348 + */
49349 +static void ubi32_uarttio_release_port(struct uart_port *port)
49350 +{
49351 +}
49352 +
49353 +/*
49354 + * ubi32_uarttio_request_port
49355 + *     Request the memory region(s) being used by 'port'.
49356 + */
49357 +static int ubi32_uarttio_request_port(struct uart_port *port)
49358 +{
49359 +       return 0;
49360 +}
49361 +
49362 +/*
49363 + * ubi32_uarttio_config_port
49364 + *     Configure/autoconfigure the port.
49365 + */
49366 +static void ubi32_uarttio_config_port(struct uart_port *port, int flags)
49367 +{
49368 +       if ((flags & UART_CONFIG_TYPE) && (ubi32_uarttio_request_port(port) == 0)) {
49369 +               port->type = PORT_UBI32_UARTTIO;
49370 +       }
49371 +}
49372 +
49373 +/*
49374 + * ubi32_uarttio_verify_port
49375 + *     Verify the new serial_struct (for TIOCSSERIAL).
49376 + *
49377 + * The only change we allow are to the flags and type, and
49378 + * even then only between PORT_UBI32_UARTTIO and PORT_UNKNOWN
49379 + */
49380 +static int ubi32_uarttio_verify_port(struct uart_port *port, struct serial_struct *ser)
49381 +{
49382 +       return 0;
49383 +}
49384 +
49385 +static struct uart_ops ubi32_uarttio_pops = {
49386 +       .tx_empty       = ubi32_uarttio_tx_empty,
49387 +       .set_mctrl      = ubi32_uarttio_set_mctrl,
49388 +       .get_mctrl      = ubi32_uarttio_get_mctrl,
49389 +       .stop_tx        = ubi32_uarttio_stop_tx,
49390 +       .start_tx       = ubi32_uarttio_start_tx,
49391 +       .stop_rx        = ubi32_uarttio_stop_rx,
49392 +       .enable_ms      = ubi32_uarttio_enable_ms,
49393 +       .break_ctl      = ubi32_uarttio_break_ctl,
49394 +       .startup        = ubi32_uarttio_startup,
49395 +       .shutdown       = ubi32_uarttio_shutdown,
49396 +       .set_termios    = ubi32_uarttio_set_termios,
49397 +       .type           = ubi32_uarttio_type,
49398 +       .release_port   = ubi32_uarttio_release_port,
49399 +       .request_port   = ubi32_uarttio_request_port,
49400 +       .config_port    = ubi32_uarttio_config_port,
49401 +       .verify_port    = ubi32_uarttio_verify_port,
49402 +};
49403 +
49404 +/*
49405 + * ubi32_uarttio_add_ports
49406 + */
49407 +static int __init ubi32_uarttio_add_ports(void)
49408 +{
49409 +       int res = 0;
49410 +       struct ubi32_uarttio_port *uup = uarttio_ports;
49411 +       int i = 0;
49412 +
49413 +       for (i = 0; i < uarttio_nports; i++) {
49414 +               /*
49415 +                * Setup the GPIOs
49416 +                */
49417 +               res = gpio_request(uup->tx_pin, "ubi32_uarttio_tx");
49418 +               if (res) {
49419 +                       printk(KERN_WARNING "Failed to request GPIO %d\n", uup->tx_pin);
49420 +                       res = -EBUSY;
49421 +                       goto next;
49422 +               }
49423 +
49424 +               res = gpio_request(uup->rx_pin, "ubi32_uarttio_rx");
49425 +               if (res) {
49426 +                       gpio_free(uup->tx_pin);
49427 +                       printk(KERN_WARNING "Failed to request GPIO %d\n", uup->rx_pin);
49428 +                       res = -EBUSY;
49429 +                       goto next;
49430 +               }
49431 +
49432 +               res = uart_add_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49433 +               if (res) {
49434 +                       gpio_free(uup->rx_pin);
49435 +                       gpio_free(uup->tx_pin);
49436 +                       res = -ENODEV;
49437 +                       printk(KERN_WARNING "Failed to add port %d,%d\n", uup->tx_pin, uup->rx_pin);
49438 +                       goto next;
49439 +               }
49440 +               uup->added = 1;
49441 +
49442 +               /*
49443 +                * Set the direction of the ports now, after we're sure that everything is ok
49444 +                */
49445 +               if (!uup->port_init) {
49446 +                       gpio_direction_output(uup->tx_pin, 1);
49447 +                       gpio_direction_input(uup->rx_pin);
49448 +               }
49449 +
49450 +next:
49451 +               uup++;
49452 +       }
49453 +       return res;
49454 +}
49455 +
49456 +/*
49457 + * ubi32_uarttio_cleanup
49458 + */
49459 +static void ubi32_uarttio_cleanup(void)
49460 +{
49461 +       struct ubi32_uarttio_port *uup;
49462 +       int i;
49463 +
49464 +       /*
49465 +        * Stop the hardware thread
49466 +        */
49467 +       if (uarttio_inst.regs) {
49468 +               thread_disable(uarttio_inst.regs->thread);
49469 +       }
49470 +       if (uarttio_inst.irq_requested) {
49471 +               free_irq(uarttio_inst.irq, NULL);
49472 +       }
49473 +
49474 +       /*
49475 +        * Get rid of the ports
49476 +        */
49477 +       uup = uarttio_inst.ports;
49478 +       for (i = 0; i < uarttio_nports; i++) {
49479 +               gpio_free(uup->tx_pin);
49480 +               gpio_free(uup->rx_pin);
49481 +               if (uup->added) {
49482 +                       uart_remove_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49483 +               }
49484 +               uup++;
49485 +       }
49486 +
49487 +       if (uarttio_inst.driver_registered) {
49488 +               uart_unregister_driver(&ubi32_uarttio_uart_driver);
49489 +       }
49490 +}
49491 +
49492 +/*
49493 + * ubi32_uarttio_setup_port
49494 + *     Setup a port in the TIO registers
49495 + */
49496 +static int ubi32_uarttio_setup_port(int index,
49497 +                                   struct uarttio_uart *uart,
49498 +                                   unsigned int baud, unsigned int tx_pin,
49499 +                                   unsigned int rx_pin)
49500 +{
49501 +       struct ubi32_uarttio_port *uup = &uarttio_ports[index];
49502 +       void *tx_port = ubi_gpio_get_port(tx_pin);
49503 +       void *rx_port = ubi_gpio_get_port(rx_pin);
49504 +
49505 +       /*
49506 +        * Verify the ports are on chip
49507 +        */
49508 +       if (!tx_port || !rx_port) {
49509 +               printk(KERN_WARNING "Invalid port(s) specified: %u or %u\n", tx_pin, rx_pin);
49510 +               return -EINVAL;
49511 +       }
49512 +
49513 +       uup->tx_pin = tx_pin;
49514 +       uup->rx_pin = rx_pin;
49515 +       uup->uart = uart;
49516 +
49517 +       /*
49518 +        * Setup the port structure
49519 +        */
49520 +       uup->port.ops           = &ubi32_uarttio_pops;
49521 +       uup->port.line          = index;
49522 +       uup->port.iotype        = UPIO_MEM;
49523 +       uup->port.flags         = UPF_BOOT_AUTOCONF;
49524 +       uup->port.fifosize      = uup->uart->tx_fifo_size;
49525 +       uup->port.private_data  = uup;
49526 +
49527 +       /*
49528 +        * We share this IRQ across all ports
49529 +        */
49530 +       uup->port.irq           = uarttio_inst.irq;
49531 +
49532 +       /*
49533 +        * We really don't have a mem/map base but without these variables
49534 +        * set, the serial_core won't startup.
49535 +        */
49536 +       uup->port.membase       = (void __iomem *)uup;
49537 +       uup->port.mapbase       = (resource_size_t)uup;
49538 +       spin_lock_init(&uup->port.lock);
49539 +
49540 +       /*
49541 +        * Set up the hardware
49542 +        */
49543 +       uart->flags = UARTTIO_UART_FLAG_SET_RATE | UARTTIO_UART_FLAG_RESET;
49544 +
49545 +       uart->tx_port = (unsigned int)tx_port;
49546 +       uart->tx_pin = gpio_pin_index(tx_pin);
49547 +       uart->tx_bits = 8;
49548 +       uart->tx_stop_bits = 1;
49549 +
49550 +       uart->rx_port = (unsigned int)rx_port;
49551 +       uart->rx_pin = gpio_pin_index(rx_pin);
49552 +       uart->rx_bits = 8;
49553 +       uart->rx_stop_bits = 1;
49554 +
49555 +       uart->baud_rate = baud;
49556 +
49557 +       return 0;
49558 +}
49559 +
49560 +enum ubi32_uarttio_parse_states {
49561 +       UBI32_UARTTIO_PARSE_STATE_BAUD,
49562 +       UBI32_UARTTIO_PARSE_STATE_TX_PIN,
49563 +       UBI32_UARTTIO_PARSE_STATE_RX_PIN,
49564 +       UBI32_UARTTIO_PARSE_STATE_HS,
49565 +       UBI32_UARTTIO_PARSE_STATE_CTS_PIN,
49566 +       UBI32_UARTTIO_PARSE_STATE_RTS_PIN,
49567 +};
49568 +
49569 +/*
49570 + * ubi32_uarttio_parse_param
49571 + */
49572 +static int ubi32_uarttio_parse_param(char *str)
49573 +{
49574 +       int res;
49575 +       int i;
49576 +       int baud = 0;
49577 +       int tx_pin = 0;
49578 +       int rx_pin = 0;
49579 +       int hs = 0;
49580 +       int cts_pin = 0;
49581 +       int rts_pin = 0;
49582 +       int nfound = 0;
49583 +       enum ubi32_uarttio_parse_states state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49584 +       struct uarttio_uart *uart = uarttio_inst.regs->uarts;
49585 +
49586 +       /*
49587 +        * Run though the options and generate the proper structures
49588 +        */
49589 +       res = get_option(&str, &i);
49590 +       while ((res == 2) || (res == 1)) {
49591 +               switch (state) {
49592 +               case UBI32_UARTTIO_PARSE_STATE_BAUD:
49593 +                       /*
49594 +                        * If we are here and nfound > 0 then create the port
49595 +                        * based on the previous input
49596 +                        */
49597 +                       if (nfound) {
49598 +                               /*
49599 +                                * Create the port
49600 +                                */
49601 +                               if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49602 +                                       /*
49603 +                                        * Port was invalid
49604 +                                        */
49605 +                                       goto fail;
49606 +                               } else {
49607 +                                       printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49608 +                                       uart++;
49609 +                               }
49610 +                       }
49611 +
49612 +                       /*
49613 +                        * Reset the variables and go to the next state
49614 +                        */
49615 +                       hs = 0;
49616 +                       baud = i;
49617 +                       state = UBI32_UARTTIO_PARSE_STATE_TX_PIN;
49618 +                       break;
49619 +
49620 +               case UBI32_UARTTIO_PARSE_STATE_TX_PIN:
49621 +                       tx_pin = i;
49622 +                       state = UBI32_UARTTIO_PARSE_STATE_RX_PIN;
49623 +                       break;
49624 +
49625 +               case UBI32_UARTTIO_PARSE_STATE_RX_PIN:
49626 +                       rx_pin = i;
49627 +                       state = UBI32_UARTTIO_PARSE_STATE_HS;
49628 +                       break;
49629 +
49630 +               case UBI32_UARTTIO_PARSE_STATE_HS:
49631 +                       hs = i;
49632 +                       if (hs) {
49633 +                               state = UBI32_UARTTIO_PARSE_STATE_CTS_PIN;
49634 +                               break;
49635 +                       }
49636 +
49637 +                       if (nfound == uarttio_inst.regs->max_uarts) {
49638 +                               printk(KERN_WARNING "Maximum number of serial ports reached\n");
49639 +                               goto done;
49640 +                       }
49641 +                       nfound++;
49642 +                       state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49643 +                       break;
49644 +
49645 +               case UBI32_UARTTIO_PARSE_STATE_CTS_PIN:
49646 +                       cts_pin = i;
49647 +                       state = UBI32_UARTTIO_PARSE_STATE_RTS_PIN;
49648 +                       break;
49649 +
49650 +               case UBI32_UARTTIO_PARSE_STATE_RTS_PIN:
49651 +                       rts_pin = i;
49652 +
49653 +                       if (nfound == uarttio_inst.regs->max_uarts) {
49654 +                               printk(KERN_WARNING "Maximum number of serial ports reached\n");
49655 +                               goto done;
49656 +                       }
49657 +                       nfound++;
49658 +                       state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49659 +                       break;
49660 +               }
49661 +               res = get_option(&str, &i);
49662 +       }
49663 +
49664 +       if ((res > 2) || state != UBI32_UARTTIO_PARSE_STATE_BAUD) {
49665 +               printk(KERN_WARNING "Parameter syntax error.\n");
49666 +               res = -EINVAL;
49667 +               goto fail;
49668 +       }
49669 +
49670 +       /*
49671 +        * Create the final port
49672 +        */
49673 +       if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49674 +               goto fail;
49675 +       }
49676 +       printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49677 +
49678 +done:
49679 +       uarttio_nports = nfound;
49680 +
49681 +       return nfound ? 0 : -ENODEV;
49682 +
49683 +fail:
49684 +       /*
49685 +        * Reset the ports
49686 +        */
49687 +       uart = uarttio_inst.regs->uarts;
49688 +       for (i = 0; i < uarttio_inst.regs->max_uarts; i++) {
49689 +               uart->flags = 0;
49690 +               uart++;
49691 +       }
49692 +
49693 +       return res;
49694 +}
49695 +
49696 +/*
49697 + * ubi32_uarttio_probe
49698 + */
49699 +static int ubi32_uarttio_probe(void)
49700 +{
49701 +       int ret;
49702 +       struct uarttio_node *uart_node;
49703 +       char *str = utio_ports_param;
49704 +       static int probed;
49705 +       static int probe_result;
49706 +
49707 +       /*
49708 +        * We only want to be probed once, we could be probed twice
49709 +        * for example if we are used as a console
49710 +        */
49711 +       if (probed) {
49712 +               return probe_result;
49713 +       }
49714 +       probed = 1;
49715 +
49716 +       /*
49717 +        * Extract the TIO name from the setup string
49718 +        */
49719 +       while (*str) {
49720 +               if (*str == ',') {
49721 +                       *str++ = 0;
49722 +                       break;
49723 +               }
49724 +               str++;
49725 +       }
49726 +
49727 +       if (!*str) {
49728 +               probe_result = -EINVAL;
49729 +               return -EINVAL;
49730 +       }
49731 +
49732 +       uart_node = (struct uarttio_node *)devtree_find_node(utio_ports_param);
49733 +       if (!uart_node) {
49734 +               probe_result = -ENODEV;
49735 +               return -ENODEV;
49736 +       }
49737 +
49738 +       uarttio_inst.irq = uart_node->dn.recvirq;
49739 +       uarttio_inst.regs = uart_node->regs;
49740 +
49741 +       /*
49742 +        * Parse module parameters.
49743 +        */
49744 +       ret = ubi32_uarttio_parse_param(str);
49745 +       if (ret != 0) {
49746 +               ubi32_uarttio_cleanup();
49747 +               probe_result = ret;
49748 +               return ret;
49749 +       }
49750 +
49751 +       ubi32_uarttio_uart_driver.nr = uarttio_nports;
49752 +
49753 +       return 0;
49754 +}
49755 +
49756 +#if defined(CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE)
49757 +/*
49758 + * ubi32_uarttio_console_setup
49759 + */
49760 +static int __init ubi32_uarttio_console_setup(struct console *co, char *options)
49761 +{
49762 +       int baud;
49763 +       int bits = 8;
49764 +       int parity = 'n';
49765 +       int flow = 'n';
49766 +       struct ubi32_uarttio_port *uup;
49767 +
49768 +       /*
49769 +        * Check whether an invalid uart number has been specified, and
49770 +        * if so, search for the first available port that does have
49771 +        * console support.
49772 +        */
49773 +       if (co->index == -1 || co->index >= uarttio_nports) {
49774 +               co->index = 0;
49775 +       }
49776 +       uup = &uarttio_ports[co->index];
49777 +       baud = uup->uart->baud_rate;
49778 +       uup->uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49779 +
49780 +       /*
49781 +        * Setup the GPIOs
49782 +        *      We have to use the direct interface because the gpio
49783 +        *      subsystem is not available at this point.
49784 +        */
49785 +       uup->port_init = 1;
49786 +       UBICOM32_GPIO_SET_PIN_HIGH(uup->tx_pin);
49787 +       UBICOM32_GPIO_SET_PIN_OUTPUT(uup->tx_pin);
49788 +       UBICOM32_GPIO_SET_PIN_INPUT(uup->rx_pin);
49789 +
49790 +       /*
49791 +        * Start the thread
49792 +        */
49793 +       thread_enable(uarttio_inst.regs->thread);
49794 +
49795 +       /*
49796 +        * Process options
49797 +        */
49798 +       if (options) {
49799 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
49800 +               if (ubi32_uarttio_set_baud(uup, baud)) {
49801 +                       baud = uup->uart->current_baud_rate;
49802 +               }
49803 +       }
49804 +
49805 +       return uart_set_options(&uup->port, co, baud, 'n', 8, 'n');
49806 +}
49807 +
49808 +/*
49809 + * ubi32_uarttio_console_putchar
49810 + */
49811 +static void ubi32_uarttio_console_putchar(struct uart_port *port, int ch)
49812 +{
49813 +       struct ubi32_uarttio_port *uup = port->private_data;
49814 +
49815 +       while (ubi32_uarttio_put_char(uup->uart, ch)) {
49816 +               cpu_relax();
49817 +       }
49818 +}
49819 +
49820 +/*
49821 + * ubi32_uarttio_console_write
49822 + *     Interrupts are disabled on entering
49823 + */
49824 +static void ubi32_uarttio_console_write(struct console *co, const char *s, unsigned int count)
49825 +{
49826 +       struct uart_port *port = &(uarttio_ports[co->index].port);
49827 +       unsigned long flags = 0;
49828 +
49829 +       spin_lock_irqsave(&port->lock, flags);
49830 +       uart_console_write(port, s, count, ubi32_uarttio_console_putchar);
49831 +       spin_unlock_irqrestore(&port->lock, flags);
49832 +}
49833 +
49834 +static struct console ubi32_uarttio_console = {
49835 +       .name           = UBI32_UARTTIO_NAME,
49836 +       .write          = ubi32_uarttio_console_write,
49837 +       .device         = uart_console_device,
49838 +       .setup          = ubi32_uarttio_console_setup,
49839 +       .flags          = CON_PRINTBUFFER,
49840 +       .index          = -1,
49841 +       .data           = &ubi32_uarttio_uart_driver,
49842 +};
49843 +
49844 +static int __init ubi32_uarttio_console_init(void)
49845 +{
49846 +       int res;
49847 +
49848 +       res = ubi32_uarttio_probe();
49849 +       if (res) {
49850 +               return res;
49851 +       }
49852 +
49853 +       register_console(&ubi32_uarttio_console);
49854 +       return 0;
49855 +}
49856 +console_initcall(ubi32_uarttio_console_init);
49857 +#endif /* CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE */
49858 +
49859 +/*
49860 + * ubi32_serial_suspend
49861 + */
49862 +static int ubi32_uarttio_suspend(struct platform_device *pdev, pm_message_t state)
49863 +{
49864 +       int i;
49865 +       for (i = 0; i < uarttio_nports; i++) {
49866 +               uart_suspend_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49867 +       }
49868 +
49869 +       return 0;
49870 +}
49871 +
49872 +/*
49873 + * ubi32_serial_resume
49874 + */
49875 +static int ubi32_uarttio_resume(struct platform_device *pdev)
49876 +{
49877 +       int i;
49878 +       for (i = 0; i < uarttio_nports; i++) {
49879 +               uart_resume_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49880 +       }
49881 +
49882 +       return 0;
49883 +}
49884 +
49885 +/*
49886 + * ubi32_uarttio_remove
49887 + */
49888 +static int __devexit ubi32_uarttio_remove(struct platform_device *pdev)
49889 +{
49890 +       ubi32_uarttio_cleanup();
49891 +
49892 +       uart_unregister_driver(&ubi32_uarttio_uart_driver);
49893 +
49894 +       return 0;
49895 +}
49896 +
49897 +static struct platform_driver ubi32_uarttio_platform_driver = {
49898 +       .remove         = __devexit_p(ubi32_uarttio_remove),
49899 +       .suspend        = ubi32_uarttio_suspend,
49900 +       .resume         = ubi32_uarttio_resume,
49901 +       .driver         = {
49902 +               .name   = DRIVER_NAME,
49903 +               .owner  = THIS_MODULE,
49904 +       },
49905 +};
49906 +
49907 +#ifndef MODULE
49908 +/*
49909 + * Called at boot time.
49910 + *
49911 + * uarttio=TIONAME,(baud,tx_pin,rx_pin,handshake[,cts_pin,rts_pin],...)
49912 + *     TIONAME is the name of the devtree node which describes the UARTTIO
49913 + *     pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]
49914 + *     handshake = 1 to enable handshaking, provide cts_pin, rts_pin (UNSUPPORTED)
49915 + *     handshake = 0 to disable handshaking, do not provide cts_pin, rts_pin
49916 + *     Ex: uarttio=UARTTIO,57600,7,6,0,9600,8,9,0
49917 + */
49918 +static int __init ubi32_uarttio_setup(char *str)
49919 +{
49920 +       strncpy(utio_ports_param, str, UBI32_UARTTIO_MAX_PARAM_LEN);
49921 +       utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN - 1] = 0;
49922 +       return 1;
49923 +}
49924 +__setup("uarttio=", ubi32_uarttio_setup);
49925 +#endif
49926 +
49927 +/*
49928 + * ubi32_uarttio_init
49929 + */
49930 +static int __init ubi32_uarttio_init(void)
49931 +{
49932 +       int ret;
49933 +       int i;
49934 +
49935 +       ret = ubi32_uarttio_probe();
49936 +       if (ret) {
49937 +               return ret;
49938 +       }
49939 +
49940 +       /*
49941 +        * Request the IRQ (do it here since many ports share the same IRQ)
49942 +        */
49943 +       ret = request_irq(uarttio_inst.irq, ubi32_uarttio_isr, IRQF_DISABLED, DRIVER_NAME, NULL);
49944 +       if (ret != 0) {
49945 +               printk(KERN_WARNING "Could not request IRQ %d\n", uarttio_inst.irq);
49946 +               goto fail;
49947 +       }
49948 +       uarttio_inst.irq_requested = 1;
49949 +
49950 +       /*
49951 +        * Register the UART driver and add the ports
49952 +        */
49953 +       ret = uart_register_driver(&ubi32_uarttio_uart_driver);
49954 +       if (ret != 0) {
49955 +               goto fail;
49956 +       }
49957 +       uarttio_inst.driver_registered = 1;
49958 +
49959 +       ret = ubi32_uarttio_add_ports();
49960 +       if (ret != 0) {
49961 +               ubi32_uarttio_cleanup();
49962 +               return ret;
49963 +       }
49964 +
49965 +       /*
49966 +        * Start the thread
49967 +        */
49968 +       thread_enable(uarttio_inst.regs->thread);
49969 +
49970 +       for (i = 0; i < uarttio_nports; i++) {
49971 +               pr_info("Serial: Ubicom32 uarttio #%d: tx:%d rx:%d baud:%d\n",
49972 +                       i, uarttio_ports[i].tx_pin, uarttio_ports[i].rx_pin,
49973 +                       uarttio_ports[i].uart->current_baud_rate);
49974 +       }
49975 +       pr_info("Serial: Ubicom32 uarttio started on thread:%d irq:%d\n", uarttio_inst.regs->thread, uarttio_inst.irq);
49976 +
49977 +       return ret;
49978 +
49979 +fail:
49980 +       ubi32_uarttio_cleanup();
49981 +       return ret;
49982 +}
49983 +module_init(ubi32_uarttio_init);
49984 +
49985 +/*
49986 + * ubi32_uarttio_exit
49987 + */
49988 +static void __exit ubi32_uarttio_exit(void)
49989 +{
49990 +       platform_driver_unregister(&ubi32_uarttio_platform_driver);
49991 +}
49992 +module_exit(ubi32_uarttio_exit);
49993 +
49994 +module_param_string(ports, utio_ports_param, sizeof(utio_ports_param), 0444);
49995 +MODULE_PARM_DESC(ports, "Sets the ports to allocate: ports=TIONAME,(baud,txpin,rxpin,handshake[,ctspin,rtspin],...)\n"
49996 +                       "     TIONAME is the name of the devtree node which describes the UARTTIO\n"
49997 +                       "     pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]\n"
49998 +                       "     handshake = 1 to enable handshaking, provide ctspin, rtspin (UNSUPPORTED)\n"
49999 +                       "     handshake = 0 to disable handshaking, do not provide ctspin, rtspin\n"
50000 +                       "     Ex: ports=UARTTIO,57600,7,6,0,9600,8,9,0\n");
50001 +MODULE_AUTHOR("Patrick Tjin <pat.tjin@ubicom.com>");
50002 +MODULE_DESCRIPTION("Ubicom serial virtual peripherial driver");
50003 +MODULE_LICENSE("GPL");
50004 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_UARTTIO_MAJOR);
50005 +MODULE_ALIAS("platform:" DRIVER_NAME);
50006 diff -ruN linux-2.6.30.10/drivers/spi/Kconfig linux-2.6.30.10-ubi/drivers/spi/Kconfig
50007 --- linux-2.6.30.10/drivers/spi/Kconfig 2009-12-14 11:54:29.000000000 +0200
50008 +++ linux-2.6.30.10-ubi/drivers/spi/Kconfig     2009-12-14 11:54:27.000000000 +0200
50009 @@ -196,6 +196,15 @@
50010         help
50011           SPI driver for Samsung S3C24XX series ARM SoCs
50012  
50013 +config SPI_UBICOM32_GPIO
50014 +       tristate "Ubicom32 SPI over GPIO"
50015 +       depends on SPI_MASTER && UBICOM32 && EXPERIMENTAL
50016 +       select SPI_BITBANG
50017 +       select HAS_DMA
50018 +       help
50019 +         SPI driver for the Ubicom32 architecture using
50020 +         GPIO lines to provide the SPI bus.
50021 +
50022  config SPI_S3C24XX_GPIO
50023         tristate "Samsung S3C24XX series SPI by GPIO"
50024         depends on ARCH_S3C2410 && EXPERIMENTAL
50025 diff -ruN linux-2.6.30.10/drivers/spi/Makefile linux-2.6.30.10-ubi/drivers/spi/Makefile
50026 --- linux-2.6.30.10/drivers/spi/Makefile        2009-12-14 11:55:29.000000000 +0200
50027 +++ linux-2.6.30.10-ubi/drivers/spi/Makefile    2009-12-14 11:55:25.000000000 +0200
50028 @@ -27,6 +27,7 @@
50029  obj-$(CONFIG_SPI_MPC52xx_PSC)          += mpc52xx_psc_spi.o
50030  obj-$(CONFIG_SPI_MPC83xx)              += spi_mpc83xx.o
50031  obj-$(CONFIG_SPI_S3C24XX_GPIO)         += spi_s3c24xx_gpio.o
50032 +obj-$(CONFIG_SPI_UBICOM32_GPIO)                += spi_ubicom32_gpio.o
50033  obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx.o
50034  obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
50035  obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
50036 diff -ruN linux-2.6.30.10/drivers/spi/spi_ubicom32_gpio.c linux-2.6.30.10-ubi/drivers/spi/spi_ubicom32_gpio.c
50037 --- linux-2.6.30.10/drivers/spi/spi_ubicom32_gpio.c     1970-01-01 02:00:00.000000000 +0200
50038 +++ linux-2.6.30.10-ubi/drivers/spi/spi_ubicom32_gpio.c 2009-12-11 11:45:19.000000000 +0200
50039 @@ -0,0 +1,267 @@
50040 +/*
50041 + * drivers/spi_spi_ubicom32_gpio.c
50042 + *     Ubicom32 GPIO based SPI driver
50043 + *
50044 + * (C) Copyright 2009, Ubicom, Inc.
50045 + *
50046 + * This file is part of the Ubicom32 Linux Kernel Port.
50047 + *
50048 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
50049 + * it and/or modify it under the terms of the GNU General Public License
50050 + * as published by the Free Software Foundation, either version 2 of the
50051 + * License, or (at your option) any later version.
50052 + *
50053 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
50054 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
50055 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
50056 + * the GNU General Public License for more details.
50057 + *
50058 + * You should have received a copy of the GNU General Public License
50059 + * along with the Ubicom32 Linux Kernel Port.  If not,
50060 + * see <http://www.gnu.org/licenses/>.
50061 + *
50062 + * Ubicom32 implementation derived from (with many thanks):
50063 + *   arch/m68knommu
50064 + *   arch/blackfin
50065 + *   arch/parisc
50066 + */
50067 +#include <linux/kernel.h>
50068 +#include <linux/init.h>
50069 +#include <linux/delay.h>
50070 +#include <linux/spinlock.h>
50071 +#include <linux/workqueue.h>
50072 +#include <linux/platform_device.h>
50073 +
50074 +#include <linux/spi/spi.h>
50075 +#include <linux/spi/spi_bitbang.h>
50076 +
50077 +#include <linux/gpio.h>
50078 +
50079 +#include <asm/ubicom32-spi-gpio.h>
50080 +
50081 +#define DRIVER_NAME "ubicom32-spi-gpio"
50082 +
50083 +struct ubicom32_spi_gpio {
50084 +       struct spi_bitbang                       bitbang;
50085 +
50086 +       struct ubicom32_spi_gpio_platform_data  *pdata;
50087 +
50088 +       struct platform_device                  *dev;
50089 +};
50090 +
50091 +/*
50092 + * The following 4 functions are used by EXPAND_BITBANG_TXRX to bitbang the data out.
50093 + */
50094 +static inline void setsck(struct spi_device *dev, int on)
50095 +{
50096 +       struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
50097 +       gpio_set_value(usg->pdata->pin_clk, on ? 1 : 0);
50098 +}
50099 +
50100 +static inline void setmosi(struct spi_device *dev, int on)
50101 +{
50102 +       struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
50103 +       gpio_set_value(usg->pdata->pin_mosi, on ? 1 : 0);
50104 +}
50105 +
50106 +static inline u32 getmiso(struct spi_device *dev)
50107 +{
50108 +       struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
50109 +       return gpio_get_value(usg->pdata->pin_miso) ? 1 : 0;
50110 +}
50111 +
50112 +#define spidelay(x) ndelay(x)
50113 +
50114 +#define        EXPAND_BITBANG_TXRX
50115 +#include <linux/spi/spi_bitbang.h>
50116 +
50117 +/*
50118 + * ubicom32_spi_gpio_txrx_mode0
50119 + */
50120 +static u32 ubicom32_spi_gpio_txrx_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50121 +{
50122 +       return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
50123 +}
50124 +
50125 +/*
50126 + * ubicom32_spi_gpio_txrx_mode1
50127 + */
50128 +static u32 ubicom32_spi_gpio_txrx_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50129 +{
50130 +       return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
50131 +}
50132 +
50133 +/*
50134 + * ubicom32_spi_gpio_txrx_mode2
50135 + */
50136 +static u32 ubicom32_spi_gpio_txrx_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50137 +{
50138 +       return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
50139 +}
50140 +
50141 +/*
50142 + * ubicom32_spi_gpio_txrx_mode3
50143 + */
50144 +static u32 ubicom32_spi_gpio_txrx_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50145 +{
50146 +       return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
50147 +}
50148 +
50149 +/*
50150 + * ubicom32_spi_gpio_chipselect
50151 + */
50152 +static void ubicom32_spi_gpio_chipselect(struct spi_device *dev, int value)
50153 +{
50154 +       struct ubicom32_spi_gpio_controller_data *cd = (struct ubicom32_spi_gpio_controller_data *)dev->controller_data;
50155 +       unsigned int cs_polarity = dev->mode & SPI_CS_HIGH ? 1 : 0;
50156 +
50157 +       if (value == BITBANG_CS_ACTIVE) {
50158 +               gpio_set_value(cd->pin_cs, cs_polarity);
50159 +               return;
50160 +       }
50161 +       gpio_set_value(cd->pin_cs, !cs_polarity);
50162 +}
50163 +
50164 +/*
50165 + * ubicom32_spi_gpio_probe
50166 + */
50167 +static int ubicom32_spi_gpio_probe(struct platform_device *dev)
50168 +{
50169 +       struct ubicom32_spi_gpio_platform_data *pdata;
50170 +       struct spi_master *master;
50171 +       struct ubicom32_spi_gpio *usg;
50172 +       int ret;
50173 +
50174 +       master = spi_alloc_master(&dev->dev, sizeof(struct ubicom32_spi_gpio));
50175 +       if (master == NULL) {
50176 +               dev_err(&dev->dev, "failed to allocate spi master\n");
50177 +               ret = -ENOMEM;
50178 +               goto err;
50179 +       }
50180 +
50181 +       usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(master);
50182 +
50183 +       platform_set_drvdata(dev, usg);
50184 +
50185 +       /*
50186 +        * Copy in the platform data
50187 +        */
50188 +       pdata = dev->dev.platform_data;
50189 +       usg->pdata = dev->dev.platform_data;
50190 +
50191 +       /*
50192 +        * Request the GPIO lines
50193 +        */
50194 +       ret = gpio_request(pdata->pin_mosi, "spi-mosi");
50195 +       if (ret) {
50196 +               dev_err(&dev->dev, "Failed to allocate spi-mosi GPIO\n");
50197 +               goto err;
50198 +       }
50199 +
50200 +       ret = gpio_request(pdata->pin_miso, "spi-miso");
50201 +       if (ret) {
50202 +               dev_err(&dev->dev, "Failed to allocate spi-miso GPIO\n");
50203 +               goto err_nomiso;
50204 +       }
50205 +
50206 +       ret = gpio_request(pdata->pin_clk, "spi-clk");
50207 +       if (ret) {
50208 +               dev_err(&dev->dev, "Failed to allocate spi-clk GPIO\n");
50209 +               goto err_noclk;
50210 +       }
50211 +
50212 +       /*
50213 +        * Setup spi-bitbang adaptor
50214 +        */
50215 +       usg->bitbang.flags |= SPI_CS_HIGH;
50216 +       usg->bitbang.master = spi_master_get(master);
50217 +       usg->bitbang.master->bus_num = pdata->bus_num;
50218 +       usg->bitbang.master->num_chipselect = pdata->num_chipselect;
50219 +       usg->bitbang.chipselect = ubicom32_spi_gpio_chipselect;
50220 +
50221 +       usg->bitbang.txrx_word[SPI_MODE_0] = ubicom32_spi_gpio_txrx_mode0;
50222 +       usg->bitbang.txrx_word[SPI_MODE_1] = ubicom32_spi_gpio_txrx_mode1;
50223 +       usg->bitbang.txrx_word[SPI_MODE_2] = ubicom32_spi_gpio_txrx_mode2;
50224 +       usg->bitbang.txrx_word[SPI_MODE_3] = ubicom32_spi_gpio_txrx_mode3;
50225 +
50226 +       /*
50227 +        * Setup the GPIO pins
50228 +        */
50229 +       gpio_direction_output(pdata->pin_clk, pdata->clk_default);
50230 +       gpio_direction_output(pdata->pin_mosi, 0);
50231 +       gpio_direction_input(pdata->pin_miso);
50232 +
50233 +       /*
50234 +        * Ready to go
50235 +        */
50236 +       ret = spi_bitbang_start(&usg->bitbang);
50237 +       if (ret) {
50238 +               goto err_no_bitbang;
50239 +       }
50240 +
50241 +       return 0;
50242 +
50243 +err_no_bitbang:
50244 +       spi_master_put(usg->bitbang.master);
50245 +
50246 +       gpio_free(pdata->pin_clk);
50247 +
50248 +err_noclk:
50249 +       gpio_free(pdata->pin_miso);
50250 +
50251 +err_nomiso:
50252 +       gpio_free(pdata->pin_mosi);
50253 +
50254 +err:
50255 +       return ret;
50256 +}
50257 +
50258 +/*
50259 + * ubicom32_spi_gpio_remove
50260 + */
50261 +static int ubicom32_spi_gpio_remove(struct platform_device *dev)
50262 +{
50263 +       struct ubicom32_spi_gpio *sp = platform_get_drvdata(dev);
50264 +
50265 +       spi_bitbang_stop(&sp->bitbang);
50266 +       spi_master_put(sp->bitbang.master);
50267 +
50268 +       return 0;
50269 +}
50270 +
50271 +/*
50272 + * Work with hotplug and coldplug
50273 + */
50274 +MODULE_ALIAS("platform:ubicom32_spi_gpio");
50275 +
50276 +static struct platform_driver ubicom32_spi_gpio_drv = {
50277 +       .probe          = ubicom32_spi_gpio_probe,
50278 +        .remove                = ubicom32_spi_gpio_remove,
50279 +        .driver                = {
50280 +               .name   = DRIVER_NAME,
50281 +               .owner  = THIS_MODULE,
50282 +        },
50283 +};
50284 +
50285 +/*
50286 + * ubicom32_spi_gpio_init
50287 + */
50288 +static int __init ubicom32_spi_gpio_init(void)
50289 +{
50290 +        return platform_driver_register(&ubicom32_spi_gpio_drv);
50291 +}
50292 +
50293 +/*
50294 + * ubicom32_spi_gpio_exit
50295 + */
50296 +static void __exit ubicom32_spi_gpio_exit(void)
50297 +{
50298 +        platform_driver_unregister(&ubicom32_spi_gpio_drv);
50299 +}
50300 +
50301 +module_init(ubicom32_spi_gpio_init);
50302 +module_exit(ubicom32_spi_gpio_exit);
50303 +
50304 +MODULE_DESCRIPTION("Ubicom32 SPI-GPIO Driver");
50305 +MODULE_AUTHOR("Pat Tjin, <@ubicom.com>");
50306 +MODULE_LICENSE("GPL");
50307 diff -ruN linux-2.6.30.10/drivers/uio/Kconfig linux-2.6.30.10-ubi/drivers/uio/Kconfig
50308 --- linux-2.6.30.10/drivers/uio/Kconfig 2009-12-04 08:00:07.000000000 +0200
50309 +++ linux-2.6.30.10-ubi/drivers/uio/Kconfig     2009-12-11 11:45:20.000000000 +0200
50310 @@ -89,4 +89,12 @@
50311  
50312           If you compile this as a module, it will be called uio_sercos3.
50313  
50314 +config UIO_UBICOM32RING
50315 +       tristate "Ubicom32 Ring Buffer driver"
50316 +       default n
50317 +       help
50318 +         Userspace I/O interface for a Ubicom32 Ring Buffer.
50319 +
50320 +         If you compile this as a module, it will be called uio_ubicom32ring
50321 +
50322  endif
50323 diff -ruN linux-2.6.30.10/drivers/uio/Makefile linux-2.6.30.10-ubi/drivers/uio/Makefile
50324 --- linux-2.6.30.10/drivers/uio/Makefile        2009-12-04 08:00:07.000000000 +0200
50325 +++ linux-2.6.30.10-ubi/drivers/uio/Makefile    2009-12-11 11:45:20.000000000 +0200
50326 @@ -5,3 +5,4 @@
50327  obj-$(CONFIG_UIO_SMX)  += uio_smx.o
50328  obj-$(CONFIG_UIO_AEC)  += uio_aec.o
50329  obj-$(CONFIG_UIO_SERCOS3)      += uio_sercos3.o
50330 +obj-$(CONFIG_UIO_UBICOM32RING) += uio_ubicom32ring.o
50331 diff -ruN linux-2.6.30.10/drivers/uio/uio_ubicom32ring.c linux-2.6.30.10-ubi/drivers/uio/uio_ubicom32ring.c
50332 --- linux-2.6.30.10/drivers/uio/uio_ubicom32ring.c      1970-01-01 02:00:00.000000000 +0200
50333 +++ linux-2.6.30.10-ubi/drivers/uio/uio_ubicom32ring.c  2009-12-11 11:45:20.000000000 +0200
50334 @@ -0,0 +1,288 @@
50335 +/*
50336 + * drivers/uio/uio_ubicom32ring.c
50337 + *
50338 + * Userspace I/O platform driver for Ubicom32 ring buffers
50339 + *
50340 + * (C) Copyright 2009, Ubicom, Inc.
50341 + *
50342 + * This file is part of the Ubicom32 Linux Kernel Port.
50343 + *
50344 + * Based on uio_ubicom32ring.c by Magnus Damm
50345 + *
50346 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
50347 + * it and/or modify it under the terms of the GNU General Public License
50348 + * as published by the Free Software Foundation, either version 2 of the
50349 + * License, or (at your option) any later version.
50350 + *
50351 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
50352 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
50353 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
50354 + * the GNU General Public License for more details.
50355 + *
50356 + * You should have received a copy of the GNU General Public License
50357 + * along with the Ubicom32 Linux Kernel Port.  If not,
50358 + * see <http://www.gnu.org/licenses/>.
50359 + */
50360 +
50361 +#include <linux/platform_device.h>
50362 +#include <linux/uio_driver.h>
50363 +#include <linux/spinlock.h>
50364 +#include <linux/bitops.h>
50365 +#include <linux/interrupt.h>
50366 +#include <linux/stringify.h>
50367 +
50368 +#include <asm/ip5000.h>
50369 +#include <asm/ubicom32ring.h>
50370 +
50371 +#define DRIVER_NAME "uio_ubicom32ring"
50372 +
50373 +struct uio_ubicom32ring_data {
50374 +       struct uio_info                 *uioinfo;
50375 +
50376 +       struct uio_ubicom32ring_regs    *regs;
50377 +
50378 +       /*
50379 +        * IRQ used to kick the ring buffer
50380 +        */
50381 +       int                             irq_tx;
50382 +       int                             irq_rx;
50383 +
50384 +       spinlock_t                      lock;
50385 +
50386 +       unsigned long                   flags;
50387 +
50388 +       char                            name[0];
50389 +};
50390 +
50391 +static irqreturn_t uio_ubicom32ring_handler(int irq, struct uio_info *dev_info)
50392 +{
50393 +       struct uio_ubicom32ring_data *priv = dev_info->priv;
50394 +
50395 +       /* Just disable the interrupt in the interrupt controller, and
50396 +        * remember the state so we can allow user space to enable it later.
50397 +        */
50398 +
50399 +       if (!test_and_set_bit(0, &priv->flags))
50400 +               disable_irq_nosync(irq);
50401 +
50402 +       return IRQ_HANDLED;
50403 +}
50404 +
50405 +static int uio_ubicom32ring_irqcontrol(struct uio_info *dev_info, s32 irq_on)
50406 +{
50407 +       struct uio_ubicom32ring_data *priv = dev_info->priv;
50408 +       unsigned long flags;
50409 +
50410 +       /* Allow user space to enable and disable the interrupt
50411 +        * in the interrupt controller, but keep track of the
50412 +        * state to prevent per-irq depth damage.
50413 +        *
50414 +        * Serialize this operation to support multiple tasks.
50415 +        */
50416 +
50417 +       spin_lock_irqsave(&priv->lock, flags);
50418 +
50419 +       if (irq_on & 2) {
50420 +               /*
50421 +                * Kick the ring buffer (if we can)
50422 +                */
50423 +               if (priv->irq_tx != 0xFF) {
50424 +                       ubicom32_set_interrupt(priv->irq_tx);
50425 +               }
50426 +       }
50427 +
50428 +       if (priv->irq_rx != 0xFF) {
50429 +               if (irq_on & 1) {
50430 +                       if (test_and_clear_bit(0, &priv->flags))
50431 +                               enable_irq(dev_info->irq);
50432 +               } else {
50433 +                       if (!test_and_set_bit(0, &priv->flags))
50434 +                               disable_irq(dev_info->irq);
50435 +               }
50436 +       }
50437 +
50438 +       spin_unlock_irqrestore(&priv->lock, flags);
50439 +
50440 +       return 0;
50441 +}
50442 +
50443 +static int uio_ubicom32ring_probe(struct platform_device *pdev)
50444 +{
50445 +       struct uio_info *uioinfo;
50446 +       struct uio_mem *uiomem;
50447 +       struct uio_ubicom32ring_data *priv;
50448 +       struct uio_ubicom32ring_regs *regs;
50449 +       struct resource *mem_resource;
50450 +       struct resource *irqtx_resource;
50451 +       struct resource *irqrx_resource;
50452 +       int ret = -EINVAL;
50453 +       int i;
50454 +
50455 +       uioinfo = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
50456 +       if (!uioinfo) {
50457 +               dev_err(&pdev->dev, "unable to kmalloc\n");
50458 +               return -ENOMEM;
50459 +       }
50460 +
50461 +       /*
50462 +        * Allocate private data with some string space after
50463 +        */
50464 +       i = sizeof(DRIVER_NAME) + 1;
50465 +       i += pdev->dev.platform_data ? strlen(pdev->dev.platform_data) : 0;
50466 +       priv = kzalloc(sizeof(struct uio_ubicom32ring_data) + i, GFP_KERNEL);
50467 +       if (!priv) {
50468 +               dev_err(&pdev->dev, "unable to kmalloc\n");
50469 +               kfree(uioinfo);
50470 +               return -ENOMEM;
50471 +       }
50472 +
50473 +       strcpy(priv->name, DRIVER_NAME ":");
50474 +       if (pdev->dev.platform_data) {
50475 +               strcat(priv->name, pdev->dev.platform_data);
50476 +       }
50477 +       uioinfo->priv = priv;
50478 +       uioinfo->name = priv->name;
50479 +       uioinfo->version = "0.1";
50480 +
50481 +       priv->uioinfo = uioinfo;
50482 +       spin_lock_init(&priv->lock);
50483 +       priv->flags = 0; /* interrupt is enabled to begin with */
50484 +
50485 +       /*
50486 +        * Get our resources, the IRQ_TX and IRQ_RX are optional.
50487 +        */
50488 +       priv->irq_tx = 0xFF;
50489 +       irqtx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
50490 +       if (irqtx_resource) {
50491 +               priv->irq_tx = irqtx_resource->start;
50492 +       }
50493 +
50494 +       uioinfo->irq = -1;
50495 +       priv->irq_rx = 0xFF;
50496 +       irqrx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
50497 +       if (irqrx_resource) {
50498 +               priv->irq_rx = irqrx_resource->start;
50499 +               uioinfo->irq = priv->irq_rx;
50500 +               uioinfo->handler = uio_ubicom32ring_handler;
50501 +       }
50502 +
50503 +       mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
50504 +       if (!mem_resource || !mem_resource->start) {
50505 +               dev_err(&pdev->dev, "No valid memory resource found\n");
50506 +               ret = -ENODEV;
50507 +               goto fail;
50508 +       }
50509 +       regs = (struct uio_ubicom32ring_regs *)mem_resource->start;
50510 +       priv->regs = regs;
50511 +
50512 +       if (regs->version != UIO_UBICOM32RING_REG_VERSION) {
50513 +               dev_err(&pdev->dev, "version %d not supported\n", regs->version);
50514 +               ret = -ENODEV;
50515 +               goto fail;
50516 +       }
50517 +
50518 +       /*
50519 +        * First range is the shared register space, if we have any
50520 +        */
50521 +       uiomem = &uioinfo->mem[0];
50522 +       if (regs->regs_size) {
50523 +               uiomem->memtype = UIO_MEM_PHYS;
50524 +               uiomem->addr = (u32_t)regs->regs;
50525 +               uiomem->size = regs->regs_size;
50526 +               ++uiomem;
50527 +               dev_info(&pdev->dev, "regs:%p (%u) / rings: %d found\n", regs->regs, regs->regs_size, regs->num_rings);
50528 +       } else {
50529 +               dev_info(&pdev->dev, "rings: %d found\n", regs->num_rings);
50530 +       }
50531 +
50532 +       /*
50533 +        * The rest of the range correspond to the rings
50534 +        */
50535 +       for (i = 0; i < regs->num_rings; i++) {
50536 +               dev_info(&pdev->dev, "\t%d: entries:%d ring:%p\n",
50537 +                        i, regs->rings[i]->entries, &(regs->rings[i]->ring));
50538 +               if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
50539 +                       dev_warn(&pdev->dev, "device has more than "
50540 +                                       __stringify(MAX_UIO_MAPS)
50541 +                                       " I/O memory resources.\n");
50542 +                       break;
50543 +               }
50544 +
50545 +               uiomem->memtype = UIO_MEM_PHYS;
50546 +               uiomem->addr = (u32_t)&(regs->rings[i]->head);
50547 +               uiomem->size = (regs->rings[i]->entries * sizeof(u32_t)) +
50548 +                               sizeof(struct uio_ubicom32ring_desc);
50549 +               ++uiomem;
50550 +       }
50551 +
50552 +       while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
50553 +               uiomem->size = 0;
50554 +               ++uiomem;
50555 +       }
50556 +
50557 +       /* This driver requires no hardware specific kernel code to handle
50558 +        * interrupts. Instead, the interrupt handler simply disables the
50559 +        * interrupt in the interrupt controller. User space is responsible
50560 +        * for performing hardware specific acknowledge and re-enabling of
50561 +        * the interrupt in the interrupt controller.
50562 +        *
50563 +        * Interrupt sharing is not supported.
50564 +        */
50565 +       uioinfo->irq_flags = IRQF_DISABLED;
50566 +       uioinfo->irqcontrol = uio_ubicom32ring_irqcontrol;
50567 +
50568 +       ret = uio_register_device(&pdev->dev, priv->uioinfo);
50569 +       if (ret) {
50570 +               dev_err(&pdev->dev, "unable to register uio device\n");
50571 +               goto fail;
50572 +       }
50573 +
50574 +       platform_set_drvdata(pdev, priv);
50575 +
50576 +       dev_info(&pdev->dev, "'%s' using irq: rx %d tx %d, regs %p\n",
50577 +                priv->name, priv->irq_rx, priv->irq_tx, priv->regs);
50578 +
50579 +       return 0;
50580 +
50581 +fail:
50582 +       kfree(uioinfo);
50583 +       kfree(priv);
50584 +       return ret;
50585 +}
50586 +
50587 +static int uio_ubicom32ring_remove(struct platform_device *pdev)
50588 +{
50589 +       struct uio_ubicom32ring_data *priv = platform_get_drvdata(pdev);
50590 +
50591 +       uio_unregister_device(priv->uioinfo);
50592 +       kfree(priv->uioinfo);
50593 +       kfree(priv);
50594 +       return 0;
50595 +}
50596 +
50597 +static struct platform_driver uio_ubicom32ring = {
50598 +       .probe = uio_ubicom32ring_probe,
50599 +       .remove = uio_ubicom32ring_remove,
50600 +       .driver = {
50601 +               .name = DRIVER_NAME,
50602 +               .owner = THIS_MODULE,
50603 +       },
50604 +};
50605 +
50606 +static int __init uio_ubicom32ring_init(void)
50607 +{
50608 +       return platform_driver_register(&uio_ubicom32ring);
50609 +}
50610 +
50611 +static void __exit uio_ubicom32ring_exit(void)
50612 +{
50613 +       platform_driver_unregister(&uio_ubicom32ring);
50614 +}
50615 +
50616 +module_init(uio_ubicom32ring_init);
50617 +module_exit(uio_ubicom32ring_exit);
50618 +
50619 +MODULE_AUTHOR("Patrick Tjin");
50620 +MODULE_DESCRIPTION("Userspace I/O driver for Ubicom32 ring buffers");
50621 +MODULE_LICENSE("GPL v2");
50622 +MODULE_ALIAS("platform:" DRIVER_NAME);
50623 diff -ruN linux-2.6.30.10/drivers/usb/gadget/epautoconf.c linux-2.6.30.10-ubi/drivers/usb/gadget/epautoconf.c
50624 --- linux-2.6.30.10/drivers/usb/gadget/epautoconf.c     2009-12-04 08:00:07.000000000 +0200
50625 +++ linux-2.6.30.10-ubi/drivers/usb/gadget/epautoconf.c 2009-12-11 11:45:20.000000000 +0200
50626 @@ -154,6 +154,10 @@
50627                         /* configure your hardware with enough buffering!! */
50628                 }
50629                 break;
50630 +
50631 +       case USB_ENDPOINT_XFER_BULK:
50632 +               if ((gadget->is_dualspeed) && (ep->maxpacket < 512))
50633 +                       return 0;
50634         }
50635  
50636         /* MATCH!! */
50637 diff -ruN linux-2.6.30.10/drivers/usb/Kconfig linux-2.6.30.10-ubi/drivers/usb/Kconfig
50638 --- linux-2.6.30.10/drivers/usb/Kconfig 2009-12-04 08:00:07.000000000 +0200
50639 +++ linux-2.6.30.10-ubi/drivers/usb/Kconfig     2009-12-11 11:45:20.000000000 +0200
50640 @@ -22,6 +22,7 @@
50641         default y if PCMCIA && !M32R                    # sl811_cs
50642         default y if ARM                                # SL-811
50643         default y if SUPERH                             # r8a66597-hcd
50644 +       default y if UBICOM32                           # Ubicom's onchip USB Duial role controller
50645         default PCI
50646  
50647  # many non-PCI SOC chips embed OHCI
50648 diff -ruN linux-2.6.30.10/drivers/usb/musb/Kconfig linux-2.6.30.10-ubi/drivers/usb/musb/Kconfig
50649 --- linux-2.6.30.10/drivers/usb/musb/Kconfig    2009-12-04 08:00:07.000000000 +0200
50650 +++ linux-2.6.30.10-ubi/drivers/usb/musb/Kconfig        2009-12-11 11:45:20.000000000 +0200
50651 @@ -12,7 +12,7 @@
50652         depends on !SUPERH
50653         select TWL4030_USB if MACH_OMAP_3430SDP
50654         select USB_OTG_UTILS
50655 -       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
50656 +       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, Ubicom, ...)'
50657         help
50658           Say Y here if your system has a dual role high speed USB
50659           controller based on the Mentor Graphics silicon IP.  Then
50660 diff -ruN linux-2.6.30.10/drivers/usb/musb/Makefile linux-2.6.30.10-ubi/drivers/usb/musb/Makefile
50661 --- linux-2.6.30.10/drivers/usb/musb/Makefile   2009-12-04 08:00:07.000000000 +0200
50662 +++ linux-2.6.30.10-ubi/drivers/usb/musb/Makefile       2009-12-11 11:45:20.000000000 +0200
50663 @@ -30,6 +30,10 @@
50664         musb_hdrc-objs  += blackfin.o
50665  endif
50666  
50667 +ifeq ($(CONFIG_UBICOM32), y)
50668 +        musb_hdrc-objs  += ubi32_usb.o
50669 +endif
50670 +
50671  ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
50672         musb_hdrc-objs          += musb_gadget_ep0.o musb_gadget.o
50673  endif
50674 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_core.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.c
50675 --- linux-2.6.30.10/drivers/usb/musb/musb_core.c        2009-12-04 08:00:07.000000000 +0200
50676 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.c    2009-12-11 11:45:20.000000000 +0200
50677 @@ -105,6 +105,13 @@
50678  #include <asm/mach-types.h>
50679  #endif
50680  
50681 +#ifdef CONFIG_UBICOM32
50682 +#include <asm/ip5000.h>
50683 +#include <asm/ubicom32-tio.h>
50684 +extern void ubi32_usb_init(void);
50685 +extern void ubi32_usb_int_clr(void);
50686 +#endif
50687 +
50688  #include "musb_core.h"
50689  
50690  
50691 @@ -147,8 +154,37 @@
50692  }
50693  
50694  /*-------------------------------------------------------------------------*/
50695 +#if defined(CONFIG_UBICOM32)
50696 +
50697 +/*
50698 + * Load an endpoint's FIFO
50699 + */
50700 +void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 wCount, const u8 *pSource)
50701 +{
50702 +       void __iomem *fifo = hw_ep->fifo;
50703 +
50704 +       prefetch((u8 *)pSource);
50705 +
50706 +       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50707 +                       'T', hw_ep->epnum, fifo, wCount, pSource);
50708 +
50709 +       usb_tio_write_fifo((u32)fifo, (u32)pSource, wCount);
50710 +
50711 +}
50712 +
50713 +/*
50714 + * Unload an endpoint's FIFO
50715 + */
50716 +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 wCount, u8 *pDest)
50717 +{
50718 +
50719 +       void __iomem *fifo = hw_ep->fifo;
50720 +       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50721 +                       'R', hw_ep->epnum, fifo, wCount, pDest);
50722 +       usb_tio_read_fifo((u32)fifo, (u32)pDest, wCount);
50723 +}
50724  
50725 -#if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50726 +#elif !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50727  
50728  /*
50729   * Load an endpoint's FIFO
50730 @@ -227,8 +263,7 @@
50731                 readsb(fifo, dst, len);
50732         }
50733  }
50734 -
50735 -#endif /* normal PIO */
50736 +#endif /* !T6010 && !BLACKFIN */
50737  
50738  
50739  /*-------------------------------------------------------------------------*/
50740 @@ -874,12 +909,19 @@
50741         musb_writeb(regs, MUSB_TESTMODE, 0);
50742  
50743         /* put into basic highspeed mode and start session */
50744 +#ifndef CONFIG_UBICOM32
50745         musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
50746                                                 | MUSB_POWER_SOFTCONN
50747                                                 | MUSB_POWER_HSENAB
50748                                                 /* ENSUSPEND wedges tusb */
50749                                                 /* | MUSB_POWER_ENSUSPEND */
50750                                                 );
50751 +#else
50752 +       musb_writeb(regs, MUSB_POWER,  MUSB_POWER_HSENAB
50753 +                                               /* ENSUSPEND wedges tusb */
50754 +                                               /* | MUSB_POWER_ENSUSPEND */
50755 +                                               );
50756 +#endif
50757  
50758         musb->is_active = 0;
50759         devctl = musb_readb(regs, MUSB_DEVCTL);
50760 @@ -1081,6 +1123,7 @@
50761  };
50762  
50763  
50764 +#ifndef CONFIG_UBICOM32
50765  /*
50766   * configure a fifo; for non-shared endpoints, this may be called
50767   * once for a tx fifo and once for an rx fifo.
50768 @@ -1240,7 +1283,7 @@
50769  
50770         return 0;
50771  }
50772 -
50773 +#endif /* CONFIG_UBICOM32 */
50774  
50775  /*
50776   * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
50777 @@ -1256,6 +1299,11 @@
50778         DBG(2, "<== static silicon ep config\n");
50779  
50780         /* FIXME pick up ep0 maxpacket size */
50781 +#ifdef CONFIG_UBICOM32
50782 +       /* set ep0 to shared_fifo, otherwise urb will be put to out_qh but ep0_irq try to get the urb from in_qh*/
50783 +       hw_ep = musb->endpoints;
50784 +       hw_ep->is_shared_fifo = true;
50785 +#endif
50786  
50787         for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
50788                 musb_ep_select(mbase, epnum);
50789 @@ -1276,14 +1324,27 @@
50790                 /* REVISIT:  this algorithm is lazy, we should at least
50791                  * try to pick a double buffered endpoint.
50792                  */
50793 +#ifndef CONFIG_UBICOM32
50794                 if (musb->bulk_ep)
50795                         continue;
50796                 musb->bulk_ep = hw_ep;
50797 +#else
50798 +               if ((musb->bulk_ep_in) && (musb->bulk_ep_out))
50799 +                       continue;
50800 +               /* Save theEP with 1024 Bytes FIFO for ISO */
50801 +               if(hw_ep->max_packet_sz_tx == 512) {
50802 +                       if (!musb->bulk_ep_in) {
50803 +                               musb->bulk_ep_in = hw_ep;
50804 +                       } else if (!musb->bulk_ep_out) {
50805 +                               musb->bulk_ep_out = hw_ep;
50806 +                       }
50807 +               }
50808 +#endif /* CONFIG_UBICOM32 */
50809  #endif
50810         }
50811  
50812  #ifdef CONFIG_USB_MUSB_HDRC_HCD
50813 -       if (!musb->bulk_ep) {
50814 +       if ((!musb->bulk_ep_in) || (!musb->bulk_ep_out)) {
50815                 pr_debug("%s: missing bulk\n", musb_driver_name);
50816                 return -EINVAL;
50817         }
50818 @@ -1393,12 +1454,16 @@
50819         musb->epmask = 1;
50820  
50821         if (reg & MUSB_CONFIGDATA_DYNFIFO) {
50822 +#ifndef CONFIG_UBICOM32
50823                 if (musb->config->dyn_fifo)
50824                         status = ep_config_from_table(musb);
50825 -               else {
50826 +               else
50827 +#endif
50828 +               {
50829                         ERR("reconfigure software for Dynamic FIFOs\n");
50830                         status = -ENODEV;
50831                 }
50832 +
50833         } else {
50834                 if (!musb->config->dyn_fifo)
50835                         status = ep_config_from_hw(musb);
50836 @@ -1462,8 +1527,8 @@
50837  
50838  /*-------------------------------------------------------------------------*/
50839  
50840 -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
50841 -
50842 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_UBICOM32)
50843 +static u32_t musb_int_count = 0;
50844  static irqreturn_t generic_interrupt(int irq, void *__hci)
50845  {
50846         unsigned long   flags;
50847 @@ -1472,10 +1537,17 @@
50848  
50849         spin_lock_irqsave(&musb->lock, flags);
50850  
50851 +#ifndef CONFIG_UBICOM32
50852         musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
50853         musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
50854         musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
50855 +#else
50856 +       musb_read_int_status(&musb->int_usb, &musb->int_tx, &musb->int_rx);
50857 +       //ubi32_usb_int_clr();
50858 +       musb_int_count++;
50859 +#endif
50860  
50861 +       DBG(4, "usb %x, tx %x, rx %x", musb->int_usb, musb->int_tx, musb->int_rx);
50862         if (musb->int_usb || musb->int_tx || musb->int_rx)
50863                 retval = musb_interrupt(musb);
50864  
50865 @@ -2210,6 +2282,10 @@
50866  
50867  static int __init musb_init(void)
50868  {
50869 +#ifdef CONFIG_UBICOM32
50870 +       ubi32_usb_init();
50871 +#endif
50872 +
50873  #ifdef CONFIG_USB_MUSB_HDRC_HCD
50874         if (usb_disabled())
50875                 return 0;
50876 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_core.h linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.h
50877 --- linux-2.6.30.10/drivers/usb/musb/musb_core.h        2009-12-04 08:00:07.000000000 +0200
50878 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.h    2009-12-11 11:45:20.000000000 +0200
50879 @@ -326,7 +326,12 @@
50880          * queue until it completes or NAKs too much; then we try the next
50881          * endpoint.
50882          */
50883 +#ifdef CONFIG_UBICOM32
50884 +       struct musb_hw_ep       *bulk_ep_in;
50885 +       struct musb_hw_ep       *bulk_ep_out;
50886 +#else
50887         struct musb_hw_ep       *bulk_ep;
50888 +#endif
50889  
50890         struct list_head        control;        /* of musb_qh */
50891         struct list_head        in_bulk;        /* of musb_qh */
50892 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_gadget.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget.c
50893 --- linux-2.6.30.10/drivers/usb/musb/musb_gadget.c      2009-12-04 08:00:07.000000000 +0200
50894 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget.c  2009-12-11 11:45:20.000000000 +0200
50895 @@ -432,7 +432,7 @@
50896                  * probably rates reporting as a host error
50897                  */
50898                 if (csr & MUSB_TXCSR_P_SENTSTALL) {
50899 -                       csr |= MUSB_TXCSR_P_WZC_BITS;
50900 +                       csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50901                         csr &= ~MUSB_TXCSR_P_SENTSTALL;
50902                         musb_writew(epio, MUSB_TXCSR, csr);
50903                         if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
50904 @@ -448,7 +448,7 @@
50905  
50906                 if (csr & MUSB_TXCSR_P_UNDERRUN) {
50907                         /* we NAKed, no big deal ... little reason to care */
50908 -                       csr |= MUSB_TXCSR_P_WZC_BITS;
50909 +                       csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50910                         csr &= ~(MUSB_TXCSR_P_UNDERRUN
50911                                         | MUSB_TXCSR_TXPKTRDY);
50912                         musb_writew(epio, MUSB_TXCSR, csr);
50913 @@ -584,10 +584,16 @@
50914         u16                     csr = 0;
50915         const u8                epnum = req->epnum;
50916         struct usb_request      *request = &req->request;
50917 -       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
50918 +       struct musb_ep          *musb_ep = NULL;
50919         void __iomem            *epio = musb->endpoints[epnum].regs;
50920 -       unsigned                fifo_count = 0;
50921 -       u16                     len = musb_ep->packet_sz;
50922 +       u16                     fifo_count = 0;
50923 +       u16                     len = 0;
50924 +
50925 +       if (musb->endpoints[epnum].is_shared_fifo)
50926 +               musb_ep = &musb->endpoints[epnum].ep_in;
50927 +       else
50928 +               musb_ep = &musb->endpoints[epnum].ep_out;
50929 +       len =  musb_ep->packet_sz;
50930  
50931         csr = musb_readw(epio, MUSB_RXCSR);
50932  
50933 @@ -726,7 +732,7 @@
50934                          */
50935  
50936                         /* ack the read! */
50937 -                       csr |= MUSB_RXCSR_P_WZC_BITS;
50938 +                       csr &= ~MUSB_RXCSR_P_WZC_BITS;
50939                         csr &= ~MUSB_RXCSR_RXPKTRDY;
50940                         musb_writew(epio, MUSB_RXCSR, csr);
50941                 }
50942 @@ -745,10 +751,15 @@
50943         u16                     csr;
50944         struct usb_request      *request;
50945         void __iomem            *mbase = musb->mregs;
50946 -       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
50947 +       struct musb_ep          *musb_ep = NULL;
50948         void __iomem            *epio = musb->endpoints[epnum].regs;
50949         struct dma_channel      *dma;
50950  
50951 +       if (musb->endpoints[epnum].is_shared_fifo)
50952 +               musb_ep = &musb->endpoints[epnum].ep_in;
50953 +       else
50954 +               musb_ep = &musb->endpoints[epnum].ep_out;
50955 +
50956         musb_ep_select(mbase, epnum);
50957  
50958         request = next_request(musb_ep);
50959 @@ -1769,7 +1780,9 @@
50960                         }
50961                 }
50962         }
50963 -
50964 +#ifndef CONFIG_USB_MUSB_OTG
50965 +       musb_pullup(musb, 1);
50966 +#endif
50967         return retval;
50968  }
50969  EXPORT_SYMBOL(usb_gadget_register_driver);
50970 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_gadget_ep0.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget_ep0.c
50971 --- linux-2.6.30.10/drivers/usb/musb/musb_gadget_ep0.c  2009-12-04 08:00:07.000000000 +0200
50972 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget_ep0.c      2009-12-11 11:45:20.000000000 +0200
50973 @@ -240,14 +240,14 @@
50974                 case USB_REQ_SET_ADDRESS:
50975                         /* change it after the status stage */
50976                         musb->set_address = true;
50977 -                       musb->address = (u8) (ctrlrequest->wValue & 0x7f);
50978 +                       musb->address = (u8) (le16_to_cpu(ctrlrequest->wValue) & 0x7f);
50979                         handled = 1;
50980                         break;
50981  
50982                 case USB_REQ_CLEAR_FEATURE:
50983                         switch (recip) {
50984                         case USB_RECIP_DEVICE:
50985 -                               if (ctrlrequest->wValue
50986 +                               if (le16_to_cpu(ctrlrequest->wValue)
50987                                                 != USB_DEVICE_REMOTE_WAKEUP)
50988                                         break;
50989                                 musb->may_wakeup = 0;
50990 @@ -261,8 +261,8 @@
50991  
50992                                 if (num == 0
50993                                                 || num >= MUSB_C_NUM_EPS
50994 -                                               || ctrlrequest->wValue
50995 -                                                       != USB_ENDPOINT_HALT)
50996 +                                               || le16_to_cpu(ctrlrequest->wValue
50997 +                                                       != USB_ENDPOINT_HALT))
50998                                         break;
50999  
51000                                 if (ctrlrequest->wIndex & USB_DIR_IN)
51001 @@ -292,7 +292,7 @@
51002                         switch (recip) {
51003                         case USB_RECIP_DEVICE:
51004                                 handled = 1;
51005 -                               switch (ctrlrequest->wValue) {
51006 +                               switch (le16_to_cpu(ctrlrequest->wValue)) {
51007                                 case USB_DEVICE_REMOTE_WAKEUP:
51008                                         musb->may_wakeup = 1;
51009                                         break;
51010 @@ -374,8 +374,8 @@
51011  
51012                                 if (epnum == 0
51013                                                 || epnum >= MUSB_C_NUM_EPS
51014 -                                               || ctrlrequest->wValue
51015 -                                                       != USB_ENDPOINT_HALT)
51016 +                                               || le16_to_cpu(ctrlrequest->wValue
51017 +                                                       != USB_ENDPOINT_HALT))
51018                                         break;
51019  
51020                                 ep = musb->endpoints + epnum;
51021 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_host.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_host.c
51022 --- linux-2.6.30.10/drivers/usb/musb/musb_host.c        2009-12-04 08:00:07.000000000 +0200
51023 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_host.c    2009-12-11 11:45:20.000000000 +0200
51024 @@ -160,7 +160,11 @@
51025         /* NOTE: no locks here; caller should lock and select EP */
51026         if (ep->epnum) {
51027                 txcsr = musb_readw(ep->regs, MUSB_TXCSR);
51028 +#ifndef CONFIG_UBICOM32
51029                 txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
51030 +#else
51031 +               txcsr |= (MUSB_TXCSR_TXPKTRDY & (~MUSB_TXCSR_H_WZC_BITS));
51032 +#endif
51033                 musb_writew(ep->regs, MUSB_TXCSR, txcsr);
51034         } else {
51035                 txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
51036 @@ -223,6 +227,8 @@
51037                 break;
51038         default:                /* bulk, interrupt */
51039                 /* actual_length may be nonzero on retry paths */
51040 +               if (urb->actual_length)
51041 +                       DBG(3 ,"musb_start_urb: URB %p retried, len: %d\n", urb, urb->actual_length);
51042                 buf = urb->transfer_buffer + urb->actual_length;
51043                 len = urb->transfer_buffer_length - urb->actual_length;
51044         }
51045 @@ -342,13 +348,13 @@
51046         if (!is_in) {
51047                 csr = musb_readw(epio, MUSB_TXCSR);
51048                 usb_settoggle(udev, qh->epnum, 1,
51049 -                       (csr & MUSB_TXCSR_H_DATATOGGLE)
51050 -                               ? 1 : 0);
51051 +                       ((csr & MUSB_TXCSR_H_DATATOGGLE)
51052 +                               ? 1 : 0));
51053         } else {
51054                 csr = musb_readw(epio, MUSB_RXCSR);
51055                 usb_settoggle(udev, qh->epnum, 0,
51056 -                       (csr & MUSB_RXCSR_H_DATATOGGLE)
51057 -                               ? 1 : 0);
51058 +                       ((csr & MUSB_RXCSR_H_DATATOGGLE)
51059 +                               ? 1 : 0));
51060         }
51061  }
51062  
51063 @@ -556,7 +562,11 @@
51064         musb_read_fifo(hw_ep, length, buf);
51065  
51066         csr = musb_readw(epio, MUSB_RXCSR);
51067 +#ifndef CONFIG_UBICOM32
51068         csr |= MUSB_RXCSR_H_WZC_BITS;
51069 +#else
51070 +       csr &= ~MUSB_RXCSR_H_WZC_BITS;
51071 +#endif
51072         if (unlikely(do_flush))
51073                 musb_h_flush_rxfifo(hw_ep, csr);
51074         else {
51075 @@ -590,6 +600,7 @@
51076  
51077         /* if programmed for Tx, put it in RX mode */
51078         if (ep->is_shared_fifo) {
51079 +#ifndef  CONFIG_UBICOM32
51080                 csr = musb_readw(ep->regs, MUSB_TXCSR);
51081                 if (csr & MUSB_TXCSR_MODE) {
51082                         musb_h_tx_flush_fifo(ep);
51083 @@ -604,7 +615,18 @@
51084                  */
51085                 if (csr & MUSB_TXCSR_DMAMODE)
51086                         musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
51087 +
51088 +#else
51089 +               /* clear mode (and everything else) to enable Rx */
51090                 musb_writew(ep->regs, MUSB_TXCSR, 0);
51091 +               /* scrub all previous state, clearing toggle */
51092 +               csr = musb_readw(ep->regs, MUSB_RXCSR);
51093 +               if (csr & MUSB_RXCSR_RXPKTRDY)
51094 +                       WARNING("rx%d, packet/%d ready?\n", ep->epnum,
51095 +                               musb_readw(ep->regs, MUSB_RXCOUNT));
51096 +
51097 +               musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
51098 +#endif
51099  
51100         /* scrub all previous state, clearing toggle */
51101         } else {
51102 @@ -1138,8 +1160,18 @@
51103         void __iomem            *mbase = musb->mregs;
51104         struct dma_channel      *dma;
51105  
51106 +#ifdef CONFIG_UBICOM32
51107 +       if (hw_ep->is_shared_fifo) {
51108 +               qh = hw_ep->in_qh;
51109 +       }
51110 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
51111 +       printk(KERN_DEBUG "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr,
51112 +                       dma ? ", dma" : "");
51113 +#endif
51114 +#endif
51115         urb = next_urb(qh);
51116  
51117 +
51118         musb_ep_select(mbase, epnum);
51119         tx_csr = musb_readw(epio, MUSB_TXCSR);
51120  
51121 @@ -1180,9 +1212,14 @@
51122                  * we have a candidate... NAKing is *NOT* an error
51123                  */
51124                 musb_ep_select(mbase, epnum);
51125 +#ifndef CONFIG_UBICOM32
51126                 musb_writew(epio, MUSB_TXCSR,
51127                                 MUSB_TXCSR_H_WZC_BITS
51128                                 | MUSB_TXCSR_TXPKTRDY);
51129 +#else
51130 +               musb_writew(epio, MUSB_TXCSR,
51131 +                                MUSB_TXCSR_TXPKTRDY);
51132 +#endif
51133                 return;
51134         }
51135  
51136 @@ -1353,8 +1390,14 @@
51137         qh->segsize = length;
51138  
51139         musb_ep_select(mbase, epnum);
51140 +#ifndef CONFIG_UBICOM32
51141 +       musb_writew(epio, MUSB_TXCSR,
51142 +                   MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
51143 +#else
51144         musb_writew(epio, MUSB_TXCSR,
51145 -                       MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
51146 +                   MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
51147 +#endif
51148 +
51149  }
51150  
51151  
51152 @@ -1414,7 +1457,11 @@
51153  
51154         /* clear nak timeout bit */
51155         rx_csr = musb_readw(epio, MUSB_RXCSR);
51156 +#ifndef CONFIG_UBICOM32
51157         rx_csr |= MUSB_RXCSR_H_WZC_BITS;
51158 +#else
51159 +       rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
51160 +#endif
51161         rx_csr &= ~MUSB_RXCSR_DATAERROR;
51162         musb_writew(epio, MUSB_RXCSR, rx_csr);
51163  
51164 @@ -1483,6 +1530,13 @@
51165  
51166         pipe = urb->pipe;
51167  
51168 +#ifdef CONFIG_UBICOM32
51169 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
51170 +               printk(KERN_DEBUG  "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
51171 +                               xfer_len, dma ? ", dma" : "");
51172 +#endif
51173 +#endif
51174 +
51175         DBG(5, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
51176                 epnum, rx_csr, urb->actual_length,
51177                 dma ? dma->actual_len : 0);
51178 @@ -1521,8 +1575,15 @@
51179                                 return;
51180                         }
51181                         musb_ep_select(mbase, epnum);
51182 +#ifndef CONFIG_UBICOM32
51183                         rx_csr |= MUSB_RXCSR_H_WZC_BITS;
51184                         rx_csr &= ~MUSB_RXCSR_DATAERROR;
51185 +#else
51186 +                       /* NEED TO EVALUATE CHANGE */
51187 +                       rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
51188 +                       rx_csr &= ~MUSB_RXCSR_DATAERROR;
51189 +//                     musb_writew(epio, MUSB_RXCSR, (~(MUSB_RXCSR_H_WZC_BITS))| MUSB_RXCSR_H_REQPKT);
51190 +#endif
51191                         musb_writew(epio, MUSB_RXCSR, rx_csr);
51192  
51193                         goto finish;
51194 @@ -1579,8 +1640,13 @@
51195                 rx_csr &= ~MUSB_RXCSR_H_REQPKT;
51196  
51197                 musb_ep_select(mbase, epnum);
51198 +#ifndef CONFIG_UBICOM32
51199                 musb_writew(epio, MUSB_RXCSR,
51200                                 MUSB_RXCSR_H_WZC_BITS | rx_csr);
51201 +#else
51202 +               musb_writew(epio, MUSB_RXCSR,
51203 +                               (~MUSB_RXCSR_H_WZC_BITS) & rx_csr);
51204 +#endif
51205         }
51206  #endif
51207         if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
51208 @@ -1610,7 +1676,7 @@
51209                         else
51210                                 done = false;
51211  
51212 -               } else  {
51213 +               } else {
51214                 /* done if urb buffer is full or short packet is recd */
51215                 done = (urb->actual_length + xfer_len >=
51216                                 urb->transfer_buffer_length
51217 @@ -1823,7 +1889,11 @@
51218                 } else  if (hw_ep->out_qh != NULL)
51219                         continue;
51220  
51221 +#ifndef CONFIG_UBICOM32
51222                 if (hw_ep == musb->bulk_ep)
51223 +#else
51224 +               if ((hw_ep == musb->bulk_ep_in) || (hw_ep == musb->bulk_ep_out)) /* Ubicom */
51225 +#endif
51226                         continue;
51227  
51228                 if (is_in)
51229 @@ -1836,7 +1906,14 @@
51230                         best_end = epnum;
51231                 }
51232         }
51233 +
51234 +#ifdef CONFIG_UBICOM32
51235 +       if (((best_diff >= qh->maxpacket)) && ((qh->type == USB_ENDPOINT_XFER_BULK) && (!is_in)))
51236 +               best_end = -1;
51237 +#endif
51238 +
51239         /* use bulk reserved ep1 if no other ep is free */
51240 +#ifndef CONFIG_UBICOM32
51241         if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
51242                 hw_ep = musb->bulk_ep;
51243                 if (is_in)
51244 @@ -1858,6 +1935,22 @@
51245         } else if (best_end < 0) {
51246                 return -ENOSPC;
51247         }
51248 +#else
51249 +       if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
51250 +               /* hw_ep = musb->bulk_ep; */
51251 +               if (is_in) {
51252 +                       head = &musb->in_bulk;
51253 +                       hw_ep = musb->bulk_ep_in; /* UBICOM */
51254 +               }
51255 +               else {
51256 +                       head = &musb->out_bulk;
51257 +                       hw_ep = musb->bulk_ep_out; /* UBICOM */
51258 +               }
51259 +               goto success;
51260 +       } else if (best_end < 0) {
51261 +               return -ENOSPC;
51262 +       }
51263 +#endif
51264  
51265         idle = 1;
51266         qh->mux = 0;
51267 @@ -1869,6 +1962,13 @@
51268                 list_add_tail(&qh->ring, head);
51269                 qh->mux = 1;
51270         }
51271 +       /*
51272 +        * It's not make sense to set NAK timeout when qh->mux = 0,
51273 +        * There is nothing else to schedule
51274 +        */
51275 +       if ((qh->type == USB_ENDPOINT_XFER_BULK) && (qh->mux == 0))
51276 +               qh->intv_reg = 0;
51277 +
51278         qh->hw_ep = hw_ep;
51279         qh->hep->hcpriv = qh;
51280         if (idle)
51281 @@ -1975,6 +2075,15 @@
51282                 /* ISO always uses logarithmic encoding */
51283                 interval = min_t(u8, epd->bInterval, 16);
51284                 break;
51285 +#ifdef COMFIG_UBICOM32
51286 +       case USB_ENDPOINT_XFER_BULK:
51287 +                if (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
51288 +                       interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16: 2;
51289 +                else
51290 +                       interval = 0;
51291 +                break;
51292 +#endif
51293 +
51294         default:
51295                 /* REVISIT we actually want to use NAK limits, hinting to the
51296                  * transfer scheduling logic to try some other qh, e.g. try
51297 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_io.h linux-2.6.30.10-ubi/drivers/usb/musb/musb_io.h
51298 --- linux-2.6.30.10/drivers/usb/musb/musb_io.h  2009-12-04 08:00:07.000000000 +0200
51299 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_io.h      2009-12-11 11:45:20.000000000 +0200
51300 @@ -58,6 +58,7 @@
51301  
51302  #ifndef CONFIG_BLACKFIN
51303  
51304 +#ifndef CONFIG_UBICOM32
51305  /* NOTE:  these offsets are all in bytes */
51306  
51307  static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51308 @@ -72,7 +73,37 @@
51309  
51310  static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
51311         { __raw_writel(data, addr + offset); }
51312 +#else
51313 +#include <asm/ubicom32-tio.h>
51314 +static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51315 +{
51316 +        u16 data;
51317 +        usb_tio_read_u16((u32)(addr + offset), &data);
51318 +        return data;
51319 +}
51320  
51321 +static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51322 +{
51323 +        u8 data;
51324 +        usb_tio_read_u8((u32)(addr + offset), &data);
51325 +        return data;
51326 +}
51327 +
51328 +static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
51329 +{
51330 +        usb_tio_write_u16((u32)(addr + offset), data);
51331 +}
51332 +
51333 +static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
51334 +{
51335 +        usb_tio_write_u8((u32)(addr + offset), data);
51336 +}
51337 +
51338 +static inline void  musb_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
51339 +{
51340 +       return usb_tio_read_int_status(int_usb, int_tx, int_rx);
51341 +}
51342 +#endif /* CONFIG_UBICOM32 */
51343  
51344  #ifdef CONFIG_USB_TUSB6010
51345  
51346 @@ -106,7 +137,7 @@
51347         __raw_writew(tmp, addr + (offset & ~1));
51348  }
51349  
51350 -#else
51351 +#elif !defined(CONFIG_UBICOM32)
51352  
51353  static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51354         { return __raw_readb(addr + offset); }
51355 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_regs.h linux-2.6.30.10-ubi/drivers/usb/musb/musb_regs.h
51356 --- linux-2.6.30.10/drivers/usb/musb/musb_regs.h        2009-12-04 08:00:07.000000000 +0200
51357 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_regs.h    2009-12-11 11:45:20.000000000 +0200
51358 @@ -167,6 +167,7 @@
51359         (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
51360         | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
51361  
51362 +
51363  /* RXCSR in Peripheral and Host mode */
51364  #define MUSB_RXCSR_AUTOCLEAR           0x8000
51365  #define MUSB_RXCSR_DMAENAB             0x2000
51366 diff -ruN linux-2.6.30.10/drivers/usb/musb/ubi32_usb.c linux-2.6.30.10-ubi/drivers/usb/musb/ubi32_usb.c
51367 --- linux-2.6.30.10/drivers/usb/musb/ubi32_usb.c        1970-01-01 02:00:00.000000000 +0200
51368 +++ linux-2.6.30.10-ubi/drivers/usb/musb/ubi32_usb.c    2009-12-11 11:45:20.000000000 +0200
51369 @@ -0,0 +1,156 @@
51370 +/*
51371 + * drivers/usb/musb/ubi32_usb.c
51372 + *   Ubicom32 usb controller driver.
51373 + *
51374 + * (C) Copyright 2009, Ubicom, Inc.
51375 + * Copyright (C) 2005-2006 by Texas Instruments
51376 + *
51377 + * Derived from the Texas Instruments Inventra Controller Driver for Linux.
51378 + *
51379 + * This file is part of the Ubicom32 Linux Kernel Port.
51380 + *
51381 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51382 + * it and/or modify it under the terms of the GNU General Public License
51383 + * as published by the Free Software Foundation, either version 2 of the
51384 + * License, or (at your option) any later version.
51385 + *
51386 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51387 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51388 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
51389 + * the GNU General Public License for more details.
51390 + *
51391 + * You should have received a copy of the GNU General Public License
51392 + * along with the Ubicom32 Linux Kernel Port.  If not,
51393 + * see <http://www.gnu.org/licenses/>.
51394 + *
51395 + * Ubicom32 implementation derived from (with many thanks):
51396 + *   arch/m68knommu
51397 + *   arch/blackfin
51398 + *   arch/parisc
51399 + */
51400 +#include <linux/module.h>
51401 +#include <linux/kernel.h>
51402 +#include <linux/sched.h>
51403 +#include <linux/slab.h>
51404 +#include <linux/init.h>
51405 +#include <linux/list.h>
51406 +#include <linux/clk.h>
51407 +#include <linux/io.h>
51408 +
51409 +#include <asm/io.h>
51410 +#include <asm/ip5000.h>
51411 +#include "musb_core.h"
51412 +
51413 +void musb_platform_enable(struct musb *musb)
51414 +{
51415 +}
51416 +void musb_platform_disable(struct musb *musb)
51417 +{
51418 +}
51419 +
51420 +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {
51421 +       return 0;
51422 +}
51423 +
51424 +static void ip5k_usb_hcd_vbus_power(struct musb *musb, int is_on, int sleeping)
51425 +{
51426 +}
51427 +
51428 +static void ip5k_usb_hcd_set_vbus(struct musb *musb, int is_on)
51429 +{
51430 +       u8              devctl;
51431 +       /* HDRC controls CPEN, but beware current surges during device
51432 +        * connect.  They can trigger transient overcurrent conditions
51433 +        * that must be ignored.
51434 +        */
51435 +
51436 +       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
51437 +
51438 +       if (is_on) {
51439 +               musb->is_active = 1;
51440 +               musb->xceiv.default_a = 1;
51441 +               musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
51442 +               devctl |= MUSB_DEVCTL_SESSION;
51443 +
51444 +               MUSB_HST_MODE(musb);
51445 +       } else {
51446 +               musb->is_active = 0;
51447 +
51448 +               /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
51449 +                * jumping right to B_IDLE...
51450 +                */
51451 +
51452 +               musb->xceiv.default_a = 0;
51453 +               musb->xceiv.state = OTG_STATE_B_IDLE;
51454 +               devctl &= ~MUSB_DEVCTL_SESSION;
51455 +
51456 +               MUSB_DEV_MODE(musb);
51457 +       }
51458 +       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
51459 +
51460 +       DBG(1, "VBUS %s, devctl %02x "
51461 +               /* otg %3x conf %08x prcm %08x */ "\n",
51462 +               otg_state_string(musb),
51463 +               musb_readb(musb->mregs, MUSB_DEVCTL));
51464 +}
51465 +static int ip5k_usb_hcd_set_power(struct otg_transceiver *x, unsigned mA)
51466 +{
51467 +       return 0;
51468 +}
51469 +
51470 +static int musb_platform_resume(struct musb *musb);
51471 +
51472 +int __init musb_platform_init(struct musb *musb)
51473 +{
51474 +
51475 +#ifdef CONFIG_UBICOM32_V4
51476 +       u32_t chip_id;
51477 +       asm volatile (
51478 +                     "move.4   %0, CHIP_ID     \n\t"
51479 +                     : "=r" (chip_id)
51480 +       );
51481 +       if (chip_id == 0x30001) {
51482 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 30);
51483 +               udelay(1);
51484 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 31);
51485 +       } else {
51486 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 17);
51487 +               udelay(1);
51488 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 14);
51489 +       }
51490 +#endif
51491 +
51492 +        *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_CFG)) |= ((1 << 14) | (1 <<15));
51493 +
51494 +       /* The i-clk is AUTO gated. Hence there is no need
51495 +        * to disable it until the driver is shutdown */
51496 +
51497 +       clk_enable(musb->clock);
51498 +       musb_platform_resume(musb);
51499 +
51500 +       ip5k_usb_hcd_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
51501 +
51502 +       if (is_host_enabled(musb))
51503 +               musb->board_set_vbus = ip5k_usb_hcd_set_vbus;
51504 +       if (is_peripheral_enabled(musb))
51505 +               musb->xceiv.set_power = ip5k_usb_hcd_set_power;
51506 +
51507 +       return 0;
51508 +}
51509 +
51510 +
51511 +int musb_platform_suspend(struct musb *musb)
51512 +{
51513 +       return 0;
51514 +}
51515 +int musb_platform_resume(struct musb *musb)
51516 +{
51517 +       return 0;
51518 +}
51519 +
51520 +int musb_platform_exit(struct musb *musb)
51521 +{
51522 +       ip5k_usb_hcd_vbus_power(musb, 0 /*off*/, 1);
51523 +       musb_platform_suspend(musb);
51524 +       return 0;
51525 +}
51526 diff -ruN linux-2.6.30.10/drivers/video/backlight/Kconfig linux-2.6.30.10-ubi/drivers/video/backlight/Kconfig
51527 --- linux-2.6.30.10/drivers/video/backlight/Kconfig     2009-12-04 08:00:07.000000000 +0200
51528 +++ linux-2.6.30.10-ubi/drivers/video/backlight/Kconfig 2009-12-11 11:45:20.000000000 +0200
51529 @@ -93,6 +93,63 @@
51530           If you have an HP Jornada 700 series handheld (710/720/728)
51531           say Y to enable LCD control driver.
51532  
51533 +config LCD_UBICOM32POWER
51534 +       tristate "Ubicom LCD power Driver"
51535 +       depends on LCD_CLASS_DEVICE && UBICOM32
51536 +       default n
51537 +       help
51538 +         If you have a Ubicom32 based system with an LCD panel that requires
51539 +         power control, say Y to enable the power control driver for it.
51540 +
51541 +config LCD_UBICOM32
51542 +       tristate "Ubicom Backlight Driver"
51543 +       depends on LCD_CLASS_DEVICE && UBICOM32
51544 +       default n
51545 +       help
51546 +         This driver takes care of initialization of LCD panels with
51547 +         built in controllers.
51548 +
51549 +menu "Ubicom32 LCD Panel Support"
51550 +       depends on UBICOM32 && LCD_UBICOM32
51551 +
51552 +config LCD_UBICOM32_TFT2N0369E_P
51553 +       bool "TFT2N0369E (Portrait)"
51554 +       default n
51555 +       help
51556 +         Support for TFT2N0369 in portrait mode
51557 +
51558 +config LCD_UBICOM32_TFT2N0369E_L
51559 +       bool "TFT2N0369E (Landscape)"
51560 +       default n
51561 +       help
51562 +         Support for TFT2N0369 in landscape mode
51563 +
51564 +config LCD_UBICOM32_CFAF240320KTTS
51565 +       bool "CFAF240320KTTS"
51566 +       default n
51567 +       help
51568 +         Support for CFAF240320KTTS
51569 +
51570 +config LCD_UBICOM32_CFAF240320KTTS_180
51571 +       bool "CFAF240320KTTS (180 rotation)"
51572 +       default n
51573 +       help
51574 +         Support for CFAF240320KTTS rotated 180 degrees
51575 +
51576 +config LCD_UBICOM32_CFAF240320D
51577 +       bool "CFAF240320D"
51578 +       default n
51579 +       help
51580 +         Support for CFAF240320D
51581 +
51582 +config LCD_UBICOM32_CFAF320240F
51583 +       bool "CFAF320240F"
51584 +       default n
51585 +       help
51586 +         Support for CFAF320240F
51587 +
51588 +endmenu
51589 +
51590  #
51591  # Backlight
51592  #
51593 @@ -229,3 +286,11 @@
51594         help
51595           If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
51596           backlight driver.
51597 +
51598 +config BACKLIGHT_UBICOM32
51599 +       tristate "Ubicom Backlight Driver"
51600 +       depends on BACKLIGHT_CLASS_DEVICE && UBICOM32
51601 +       default n
51602 +       help
51603 +         If you have a Ubicom32 based system with a backlight say Y to enable the
51604 +         backlight driver.
51605 diff -ruN linux-2.6.30.10/drivers/video/backlight/Makefile linux-2.6.30.10-ubi/drivers/video/backlight/Makefile
51606 --- linux-2.6.30.10/drivers/video/backlight/Makefile    2009-12-04 08:00:07.000000000 +0200
51607 +++ linux-2.6.30.10-ubi/drivers/video/backlight/Makefile        2009-12-11 11:45:20.000000000 +0200
51608 @@ -9,6 +9,9 @@
51609  obj-$(CONFIG_LCD_VGG2432A4)       += vgg2432a4.o
51610  obj-$(CONFIG_LCD_TDO24M)          += tdo24m.o
51611  obj-$(CONFIG_LCD_TOSA)            += tosa_lcd.o
51612 +obj-$(CONFIG_LCD_LTV350QV)        += ltv350qv.o
51613 +obj-$(CONFIG_LCD_UBICOM32POWER)           += ubicom32lcdpower.o
51614 +obj-$(CONFIG_LCD_UBICOM32)        += ubicom32lcd.o
51615  
51616  obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
51617  obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)    += atmel-pwm-bl.o
51618 @@ -24,4 +27,4 @@
51619  obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
51620  obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
51621  obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
51622 -
51623 +obj-$(CONFIG_BACKLIGHT_UBICOM32) += ubicom32bl.o
51624 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32bl.c linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32bl.c
51625 --- linux-2.6.30.10/drivers/video/backlight/ubicom32bl.c        1970-01-01 02:00:00.000000000 +0200
51626 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32bl.c    2009-12-11 11:45:20.000000000 +0200
51627 @@ -0,0 +1,399 @@
51628 +/*
51629 + * drivers/video/backlight/ubicom32bl.c
51630 + *     Backlight driver for the Ubicom32 platform
51631 + *
51632 + * (C) Copyright 2009, Ubicom, Inc.
51633 + *
51634 + * This file is part of the Ubicom32 Linux Kernel Port.
51635 + *
51636 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51637 + * it and/or modify it under the terms of the GNU General Public License
51638 + * as published by the Free Software Foundation, either version 2 of the
51639 + * License, or (at your option) any later version.
51640 + *
51641 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51642 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51643 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
51644 + * the GNU General Public License for more details.
51645 + *
51646 + * You should have received a copy of the GNU General Public License
51647 + * along with the Ubicom32 Linux Kernel Port.  If not,
51648 + * see <http://www.gnu.org/licenses/>.
51649 + *
51650 + * Ubicom32 implementation derived from (with many thanks):
51651 + *   arch/m68knommu
51652 + *   arch/blackfin
51653 + *   arch/parisc
51654 + */
51655 +#include <linux/init.h>
51656 +#include <linux/kernel.h>
51657 +#include <linux/module.h>
51658 +#include <linux/platform_device.h>
51659 +#include <linux/backlight.h>
51660 +#include <linux/fb.h>
51661 +
51662 +#include <asm/ubicom32bl.h>
51663 +#include <asm/ip5000.h>
51664 +
51665 +#define DRIVER_NAME                    "ubicom32bl"
51666 +#define UBICOM32BL_MAX_BRIGHTNESS      255
51667 +
51668 +struct ubicom32bl_data {
51669 +       /*
51670 +        * Pointer to the platform data structure.  Keep this around since we need values
51671 +        * from it to set the backlight intensity.
51672 +        */
51673 +       const struct ubicom32bl_platform_data   *pdata;
51674 +
51675 +       /*
51676 +        * Backlight device, we have to save this for use when we remove ourselves.
51677 +        */
51678 +       struct backlight_device                 *bldev;
51679 +
51680 +       /*
51681 +        * Current intensity, used for get_intensity.
51682 +        */
51683 +       int                                     cur_intensity;
51684 +
51685 +       /*
51686 +        * Init function for PWM
51687 +        */
51688 +       int (*init_fn)(struct ubicom32bl_data *);
51689 +
51690 +       /*
51691 +        * Set intensity function depending on the backlight type
51692 +        */
51693 +       int (*set_intensity_fn)(struct ubicom32bl_data *, int);
51694 +};
51695 +
51696 +/*
51697 + * ubicom32bl_set_intensity_gpio
51698 + */
51699 +static int ubicom32bl_set_intensity_gpio(struct ubicom32bl_data *ud, int intensity)
51700 +{
51701 +       ud->cur_intensity = intensity ? 255 : 0;
51702 +
51703 +       if (intensity) {
51704 +               // set gpio
51705 +               return 0;
51706 +       }
51707 +
51708 +       // clear gpio
51709 +       return 0;
51710 +}
51711 +
51712 +/*
51713 + * ubicom32bl_set_intensity_hw
51714 + */
51715 +static int ubicom32bl_set_intensity_hw(struct ubicom32bl_data *ud, int intensity)
51716 +{
51717 +       u16_t period = ud->pdata->pwm_period;
51718 +       u16_t duty;
51719 +
51720 +       /*
51721 +        * Calculate the new duty cycle
51722 +        */
51723 +       duty = (period * intensity) / (UBICOM32BL_MAX_BRIGHTNESS + 1);
51724 +
51725 +       /*
51726 +        * Set the new duty cycle
51727 +        */
51728 +       switch (ud->pdata->pwm_channel) {
51729 +       case 0:
51730 +               /*
51731 +                * Channel 0 is in the lower half of PORT C ctl0 and ctl1
51732 +                */
51733 +               UBICOM32_IO_PORT(RC)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51734 +               break;
51735 +
51736 +       case 1:
51737 +               /*
51738 +                * Channel 1 is in the upper half of PORT C ctl0 and ctl2
51739 +                */
51740 +               UBICOM32_IO_PORT(RC)->ctl2 = (ud->pdata->pwm_period << 16) | duty;
51741 +               break;
51742 +
51743 +       case 2:
51744 +               /*
51745 +                * Channel 2 is in PORT H ctl0 and ctl1
51746 +                */
51747 +               UBICOM32_IO_PORT(RH)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51748 +               break;
51749 +       }
51750 +
51751 +       ud->cur_intensity = intensity;
51752 +
51753 +       return 0;
51754 +}
51755 +
51756 +/*
51757 + * ubicom32bl_set_intensity
51758 + */
51759 +static int ubicom32bl_set_intensity(struct backlight_device *bd)
51760 +{
51761 +       struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51762 +       int intensity = bd->props.brightness;
51763 +
51764 +       /*
51765 +        * If we're blanked the the intensity doesn't matter.
51766 +        */
51767 +       if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
51768 +               intensity = 0;
51769 +       }
51770 +
51771 +       /*
51772 +        * Check for inverted backlight.
51773 +        */
51774 +       if (ud->pdata->invert) {
51775 +               intensity = UBICOM32BL_MAX_BRIGHTNESS - intensity;
51776 +       }
51777 +
51778 +       if (ud->set_intensity_fn) {
51779 +               return ud->set_intensity_fn(ud, intensity);
51780 +       }
51781 +
51782 +       return -ENXIO;
51783 +}
51784 +
51785 +/*
51786 + * ubicom32bl_get_intensity
51787 + *     Return the current intensity of the backlight.
51788 + */
51789 +static int ubicom32bl_get_intensity(struct backlight_device *bd)
51790 +{
51791 +       struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51792 +
51793 +       return ud->cur_intensity;
51794 +}
51795 +
51796 +/*
51797 + * ubicom32bl_init_hw_pwm
51798 + *     Set the appropriate PWM registers
51799 + */
51800 +static int ubicom32bl_init_hw_pwm(struct ubicom32bl_data *ud)
51801 +{
51802 +       /*
51803 +        * bit 13: enable
51804 +        */
51805 +       u16_t pwm_cfg = (1 << 13) | (ud->pdata->pwm_prescale << 8) ;
51806 +
51807 +       switch (ud->pdata->pwm_channel) {
51808 +       case 0:
51809 +               /*
51810 +                * Channel 0 is in the lower half of PORT C ctl0 and ctl1 (PA5)
51811 +                */
51812 +               UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF;
51813 +               UBICOM32_IO_PORT(RC)->ctl0 |= pwm_cfg;
51814 +               UBICOM32_IO_PORT(RC)->ctl1 = ud->pdata->pwm_period << 16;
51815 +
51816 +               /*
51817 +                * If the port function is not set, set it to GPIO/PWM
51818 +                */
51819 +               if (!UBICOM32_IO_PORT(RA)->function) {
51820 +                       UBICOM32_IO_PORT(RA)->function = 3;
51821 +               }
51822 +               break;
51823 +
51824 +       case 1:
51825 +               /*
51826 +                * Channel 1 is in the upper half of PORT C ctl0 and ctl2 (PE4)
51827 +                */
51828 +               UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF0000;
51829 +               UBICOM32_IO_PORT(RC)->ctl0 |= (pwm_cfg << 16);
51830 +               UBICOM32_IO_PORT(RC)->ctl2 = ud->pdata->pwm_period << 16;
51831 +
51832 +               /*
51833 +                * If the port function is not set, set it to GPIO/ExtIOInt
51834 +                */
51835 +               if (!UBICOM32_IO_PORT(RE)->function) {
51836 +                       UBICOM32_IO_PORT(RE)->function = 3;
51837 +               }
51838 +               break;
51839 +
51840 +       case 2:
51841 +               /*
51842 +                * Channel 2 is in PORT H ctl0 and ctl1 (PD0)
51843 +                */
51844 +               UBICOM32_IO_PORT(RH)->ctl0 &= ~0xFFFF0000;
51845 +               UBICOM32_IO_PORT(RH)->ctl0 = pwm_cfg;
51846 +               UBICOM32_IO_PORT(RH)->ctl1 = ud->pdata->pwm_period << 16;
51847 +
51848 +               /*
51849 +                * If the port function is not set, set it to GPIO
51850 +                */
51851 +               if (!UBICOM32_IO_PORT(RD)->function) {
51852 +                       UBICOM32_IO_PORT(RD)->function = 3;
51853 +               }
51854 +               break;
51855 +       }
51856 +
51857 +       return 0;
51858 +}
51859 +
51860 +/*
51861 + * ubicom32bl_init_gpio
51862 + *     Allocate the appropriate GPIO
51863 + */
51864 +static int ubicom32bl_init_gpio(struct ubicom32bl_data *ud)
51865 +{
51866 +       return 0;
51867 +}
51868 +
51869 +static struct backlight_ops ubicom32bl_ops = {
51870 +       .get_brightness = ubicom32bl_get_intensity,
51871 +       .update_status  = ubicom32bl_set_intensity,
51872 +};
51873 +
51874 +/*
51875 + * ubicom32bl_probe
51876 + */
51877 +static int ubicom32bl_probe(struct platform_device *pdev)
51878 +{
51879 +       const struct ubicom32bl_platform_data *pdata = pdev->dev.platform_data;
51880 +       struct ubicom32bl_data *ud;
51881 +       struct backlight_device *bldev;
51882 +       int retval;
51883 +
51884 +       /*
51885 +        * Check to see if we have any platform data, if we don't then the backlight is not
51886 +        * configured on this device.
51887 +        */
51888 +       if (!pdata) {
51889 +               return -ENODEV;
51890 +       }
51891 +
51892 +       /*
51893 +        * Allocate our private data
51894 +        */
51895 +       ud = kzalloc(sizeof(struct ubicom32bl_data), GFP_KERNEL);
51896 +       if (!ud) {
51897 +               return -ENOMEM;
51898 +       }
51899 +
51900 +       ud->pdata = pdata;
51901 +
51902 +       /*
51903 +        * Check to see that the platform data is valid for this driver
51904 +        */
51905 +       switch (pdata->type) {
51906 +       case UBICOM32BL_TYPE_PWM:
51907 +               {
51908 +                       /*
51909 +                        * Make sure we have a PWM peripheral
51910 +                        */
51911 +                       u32_t chipid;
51912 +                       asm volatile (
51913 +                               "move.4         %0, CHIP_ID     \n\t"
51914 +                               : "=r" (chipid)
51915 +                       );
51916 +                       if (chipid != 0x00030001) {
51917 +                               retval = -ENODEV;
51918 +                               goto fail;
51919 +                       }
51920 +
51921 +                       if (pdata->pwm_channel > 3) {
51922 +                               retval = -ENODEV;
51923 +                               goto fail;
51924 +                       }
51925 +                       if (pdata->pwm_prescale > 16) {
51926 +                               retval = -EINVAL;
51927 +                               goto fail;
51928 +                       }
51929 +
51930 +                       ud->init_fn = ubicom32bl_init_hw_pwm;
51931 +                       ud->set_intensity_fn = ubicom32bl_set_intensity_hw;
51932 +                       break;
51933 +               }
51934 +
51935 +       case UBICOM32BL_TYPE_PWM_HRT:
51936 +               // For now, PWM HRT devices are treated as binary lights.
51937 +
51938 +       case UBICOM32BL_TYPE_BINARY:
51939 +               ud->init_fn = ubicom32bl_init_gpio;
51940 +               ud->set_intensity_fn = ubicom32bl_set_intensity_gpio;
51941 +               break;
51942 +       }
51943 +
51944 +       /*
51945 +        * Register our backlight device
51946 +        */
51947 +       bldev = backlight_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32bl_ops);
51948 +       if (IS_ERR(bldev)) {
51949 +               retval = PTR_ERR(bldev);
51950 +               goto fail;
51951 +       }
51952 +
51953 +       ud->bldev = bldev;
51954 +       ud->cur_intensity = pdata->default_intensity;
51955 +       platform_set_drvdata(pdev, ud);
51956 +
51957 +       /*
51958 +        * Start up the backlight at the prescribed default intensity
51959 +        */
51960 +       bldev->props.power = FB_BLANK_UNBLANK;
51961 +       bldev->props.max_brightness = UBICOM32BL_MAX_BRIGHTNESS;
51962 +       bldev->props.brightness = pdata->default_intensity;
51963 +
51964 +       if (ud->init_fn) {
51965 +               if (ud->init_fn(ud) != 0) {
51966 +                       retval = -ENODEV;
51967 +                       backlight_device_unregister(ud->bldev);
51968 +                       goto fail;
51969 +               }
51970 +       }
51971 +       ubicom32bl_set_intensity(bldev);
51972 +
51973 +       printk(KERN_INFO DRIVER_NAME ": Backlight driver started\n");
51974 +
51975 +       return 0;
51976 +
51977 +fail:
51978 +       platform_set_drvdata(pdev, NULL);
51979 +       kfree(ud);
51980 +       return retval;
51981 +}
51982 +
51983 +/*
51984 + * ubicom32bl_remove
51985 + */
51986 +static int __exit ubicom32bl_remove(struct platform_device *pdev)
51987 +{
51988 +       struct ubicom32bl_data *ud = platform_get_drvdata(pdev);
51989 +
51990 +       backlight_device_unregister(ud->bldev);
51991 +       platform_set_drvdata(pdev, NULL);
51992 +       kfree(ud);
51993 +
51994 +       return 0;
51995 +}
51996 +
51997 +static struct platform_driver ubicom32bl_driver = {
51998 +       .driver = {
51999 +               .name = DRIVER_NAME,
52000 +               .owner = THIS_MODULE,
52001 +       },
52002 +
52003 +       .remove = __exit_p(ubicom32bl_remove),
52004 +};
52005 +
52006 +/*
52007 + * ubicom32bl_init
52008 + */
52009 +static int __init ubicom32bl_init(void)
52010 +{
52011 +       return platform_driver_probe(&ubicom32bl_driver, ubicom32bl_probe);
52012 +}
52013 +module_init(ubicom32bl_init);
52014 +
52015 +/*
52016 + * ubicom32bl_exit
52017 + */
52018 +static void __exit ubicom32bl_exit(void)
52019 +{
52020 +       platform_driver_unregister(&ubicom32bl_driver);
52021 +}
52022 +module_exit(ubicom32bl_exit);
52023 +
52024 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52025 +MODULE_DESCRIPTION("Ubicom32 backlight driver");
52026 +MODULE_LICENSE("GPL");
52027 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.c linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.c
52028 --- linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.c       1970-01-01 02:00:00.000000000 +0200
52029 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.c   2009-12-11 11:45:20.000000000 +0200
52030 @@ -0,0 +1,372 @@
52031 +/*
52032 + * drivers/video/ubicom32lcd.c
52033 + *     LCD initilization code
52034 + *
52035 + * (C) Copyright 2009, Ubicom, Inc.
52036 + *
52037 + * This file is part of the Ubicom32 Linux Kernel Port.
52038 + *
52039 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52040 + * it and/or modify it under the terms of the GNU General Public License
52041 + * as published by the Free Software Foundation, either version 2 of the
52042 + * License, or (at your option) any later version.
52043 + *
52044 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52045 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52046 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
52047 + * the GNU General Public License for more details.
52048 + *
52049 + * You should have received a copy of the GNU General Public License
52050 + * along with the Ubicom32 Linux Kernel Port.  If not,
52051 + * see <http://www.gnu.org/licenses/>.
52052 + */
52053 +#include <linux/init.h>
52054 +#include <linux/kernel.h>
52055 +#include <linux/module.h>
52056 +#include <linux/platform_device.h>
52057 +#include <linux/delay.h>
52058 +
52059 +#include <asm/ip5000.h>
52060 +#include <asm/gpio.h>
52061 +#include <asm/ubicom32lcd.h>
52062 +
52063 +#include "ubicom32lcd.h"
52064 +
52065 +#define DRIVER_NAME                    "ubicom32lcd"
52066 +
52067 +struct ubicom32lcd_data {
52068 +       const struct ubicom32lcd_panel  *panel;
52069 +
52070 +       int                             pin_cs;
52071 +       int                             pin_rd;
52072 +       int                             pin_rs;
52073 +       int                             pin_wr;
52074 +       int                             pin_reset;
52075 +       struct ubicom32_io_port         *port_data;
52076 +       int                             data_shift;
52077 +};
52078 +
52079 +/*
52080 + * ubicom32lcd_write
52081 + *     Performs a write cycle on the bus (assumes CS asserted, RD & WR set)
52082 + */
52083 +static void ubicom32lcd_write(struct ubicom32lcd_data *ud, int command, u16 data)
52084 +{
52085 +       if (command) {
52086 +               UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rs);
52087 +       } else {
52088 +               UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52089 +       }
52090 +
52091 +       asm volatile (
52092 +               "or.4   4(%[port]), 4(%[port]), %[mask] \n\t"
52093 +               "not.4  %[mask], %[mask]                \n\t"
52094 +               "and.4  8(%[port]), 8(%[port]), %[mask] \n\t"
52095 +               "or.4   8(%[port]), 8(%[port]), %[cmd]  \n\t"
52096 +               :
52097 +               : [port] "a" (ud->port_data),
52098 +                 [mask] "d" (0xFFFF << ud->data_shift),
52099 +                 [cmd] "d" (data << ud->data_shift)
52100 +               : "cc"
52101 +       );
52102 +
52103 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_wr);
52104 +
52105 +       //ndelay(50);
52106 +       udelay(1);
52107 +
52108 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
52109 +
52110 +       udelay(1);
52111 +       //ndelay(50);
52112 +}
52113 +
52114 +/*
52115 + * ubicom32lcd_read_data
52116 + *     Performs a read cycle on the bus (assumes CS asserted, RD & WR set)
52117 + */
52118 +static u16 ubicom32lcd_read_data(struct ubicom32lcd_data *ud)
52119 +{
52120 +       u32_t data;
52121 +
52122 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52123 +
52124 +       asm volatile (
52125 +               "and.4  4(%[port]), 4(%[port]), %[mask]\n\t"
52126 +               :
52127 +               : [port] "a" (ud->port_data),
52128 +                 [mask] "d" (~(0xFFFF << ud->data_shift))
52129 +               : "cc"
52130 +       );
52131 +
52132 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rd);
52133 +
52134 +       ndelay(300);
52135 +
52136 +       asm volatile (
52137 +               "lsr.4  %[data], 12(%[port]), %[shamt]  \n\t"
52138 +               "and.4  %[data], %[data], %[mask]       \n\t"
52139 +               : [data] "=d" (data)
52140 +               : [port] "a" (ud->port_data),
52141 +                 [mask] "d" (0xFFFF),
52142 +                 [shamt] "d" (ud->data_shift)
52143 +               : "cc"
52144 +       );
52145 +
52146 +       ndelay(200);
52147 +
52148 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
52149 +
52150 +       ndelay(500);
52151 +
52152 +       return data;
52153 +}
52154 +
52155 +/*
52156 + * ubicom32lcd_execute
52157 + *     Executes a script for performing operations on the LCD (assumes CS set)
52158 + */
52159 +static void ubicom32lcd_execute(struct ubicom32lcd_data *ud, const struct ubicom32lcd_step *script)
52160 +{
52161 +       while (1) {
52162 +               switch (script->op) {
52163 +               case LCD_STEP_CMD:
52164 +                       ubicom32lcd_write(ud, 1, script->cmd);
52165 +                       break;
52166 +
52167 +               case LCD_STEP_DATA:
52168 +                       ubicom32lcd_write(ud, 0, script->data);
52169 +                       break;
52170 +
52171 +               case LCD_STEP_CMD_DATA:
52172 +                       ubicom32lcd_write(ud, 1, script->cmd);
52173 +                       ubicom32lcd_write(ud, 0, script->data);
52174 +                       break;
52175 +
52176 +               case LCD_STEP_SLEEP:
52177 +                       udelay(script->data);
52178 +                       break;
52179 +
52180 +               case LCD_STEP_DONE:
52181 +                       return;
52182 +               }
52183 +               script++;
52184 +       }
52185 +}
52186 +
52187 +/*
52188 + * ubicom32lcd_goto
52189 + *     Places the gram pointer at a specific X, Y address
52190 + */
52191 +static void ubicom32lcd_goto(struct ubicom32lcd_data *ud, int x, int y)
52192 +{
52193 +       ubicom32lcd_write(ud, 1, ud->panel->horz_reg);
52194 +       ubicom32lcd_write(ud, 0, x);
52195 +       ubicom32lcd_write(ud, 1, ud->panel->vert_reg);
52196 +       ubicom32lcd_write(ud, 0, y);
52197 +       ubicom32lcd_write(ud, 1, ud->panel->gram_reg);
52198 +}
52199 +
52200 +/*
52201 + * ubicom32lcd_panel_init
52202 + *     Initializes the lcd panel.
52203 + */
52204 +static int ubicom32lcd_panel_init(struct ubicom32lcd_data *ud)
52205 +{
52206 +       u16 id;
52207 +
52208 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_reset);
52209 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_reset);
52210 +       UBICOM32_GPIO_ENABLE(ud->pin_reset);
52211 +
52212 +       asm volatile (
52213 +               "or.4   0x50(%[port]), 0x50(%[port]), %[mask]   \n\t"
52214 +               "not.4  %[mask], %[mask]                        \n\t"
52215 +               "and.4  0x04(%[port]), 0x04(%[port]), %[mask]   \n\t"
52216 +               :
52217 +               : [port] "a" (ud->port_data),
52218 +                 [mask] "d" (0xFFFF << ud->data_shift)
52219 +               : "cc"
52220 +       );
52221 +
52222 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52223 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
52224 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
52225 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
52226 +
52227 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rs);
52228 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rd);
52229 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_wr);
52230 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_cs);
52231 +
52232 +       UBICOM32_GPIO_ENABLE(ud->pin_rs);
52233 +       UBICOM32_GPIO_ENABLE(ud->pin_rd);
52234 +       UBICOM32_GPIO_ENABLE(ud->pin_wr);
52235 +       UBICOM32_GPIO_ENABLE(ud->pin_cs);
52236 +
52237 +       udelay(20);
52238 +
52239 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_reset);
52240 +
52241 +       udelay(20);
52242 +
52243 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_cs);
52244 +
52245 +       id = ubicom32lcd_read_data(ud);
52246 +
52247 +       /*
52248 +        * We will try to figure out what kind of panel we have if we were not told.
52249 +        */
52250 +       if (!ud->panel) {
52251 +               const struct ubicom32lcd_panel **p = ubicom32lcd_panels;
52252 +               while (*p) {
52253 +                       if ((*p)->id && ((*p)->id == id)) {
52254 +                               break;
52255 +                       }
52256 +                       p++;
52257 +               }
52258 +               if (!*p) {
52259 +                       printk(KERN_WARNING DRIVER_NAME ":Could not find compatible panel, id=%x\n", id);
52260 +                       return -ENODEV;
52261 +               }
52262 +               ud->panel = *p;
52263 +       }
52264 +
52265 +       /*
52266 +        * Make sure panel ID matches if we were supplied a panel type
52267 +        */
52268 +       if (ud->panel->id && (ud->panel->id != id)) {
52269 +               UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
52270 +
52271 +               return -ENODEV;
52272 +       }
52273 +
52274 +       ubicom32lcd_execute(ud, ud->panel->init_seq);
52275 +
52276 +       ubicom32lcd_goto(ud, 0, 0);
52277 +
52278 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
52279 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
52280 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
52281 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52282 +
52283 +       printk(KERN_INFO DRIVER_NAME ": Initialized panel %s\n", ud->panel->desc);
52284 +
52285 +       return 0;
52286 +}
52287 +
52288 +/*
52289 + * ubicom32lcd_probe
52290 + */
52291 +static int ubicom32lcd_probe(struct platform_device *pdev)
52292 +{
52293 +       const struct ubicom32lcd_platform_data *pdata = pdev->dev.platform_data;
52294 +       struct ubicom32lcd_data *ud;
52295 +       int retval;
52296 +
52297 +       /*
52298 +        * Allocate our private data
52299 +        */
52300 +       ud = kzalloc(sizeof(struct ubicom32lcd_data), GFP_KERNEL);
52301 +       if (!ud) {
52302 +               return -ENOMEM;
52303 +       }
52304 +
52305 +       if (pdata) {
52306 +               ud->pin_cs = pdata->pin_cs;
52307 +               ud->pin_rd = pdata->pin_rd;
52308 +               ud->pin_wr = pdata->pin_wr;
52309 +               ud->pin_rs = pdata->pin_rs;
52310 +               ud->pin_reset = pdata->pin_reset;
52311 +               ud->port_data = pdata->port_data;
52312 +               ud->data_shift = pdata->data_shift;
52313 +       } else {
52314 +               /*
52315 +                * Defaults
52316 +                */
52317 +               ud->pin_cs = GPIO_RD_4;
52318 +               ud->pin_rd = GPIO_RD_5;
52319 +               ud->pin_rs = GPIO_RD_3;
52320 +               ud->pin_wr = GPIO_RD_2;
52321 +               ud->pin_reset = GPIO_RD_7;
52322 +               ud->port_data = (struct ubicom32_io_port *)RI;
52323 +               ud->data_shift = 0;
52324 +       }
52325 +
52326 +       /*
52327 +        * Initialize the display
52328 +        */
52329 +       retval = ubicom32lcd_panel_init(ud);
52330 +       if (retval) {
52331 +               kfree(ud);
52332 +               return retval;
52333 +       }
52334 +
52335 +       printk(KERN_INFO DRIVER_NAME ": LCD initialized\n");
52336 +
52337 +       return 0;
52338 +}
52339 +
52340 +/*
52341 + * ubicom32lcd_remove
52342 + */
52343 +static int __exit ubicom32lcd_remove(struct platform_device *pdev)
52344 +{
52345 +       struct ubicom32lcd_data *ud = platform_get_drvdata(pdev);
52346 +
52347 +       kfree(ud);
52348 +
52349 +       return 0;
52350 +}
52351 +
52352 +static struct platform_driver ubicom32lcd_driver = {
52353 +       .probe          = ubicom32lcd_probe,
52354 +       .remove         = ubicom32lcd_remove,
52355 +
52356 +       .driver = {
52357 +               .name = DRIVER_NAME,
52358 +               .owner = THIS_MODULE,
52359 +       },
52360 +
52361 +       .remove = __exit_p(ubicom32lcd_remove),
52362 +};
52363 +
52364 +static struct platform_device *ubicom32lcd_device;
52365 +
52366 +/*
52367 + * ubicom32lcd_init
52368 + */
52369 +static int __init ubicom32lcd_init(void)
52370 +{
52371 +       int res;
52372 +
52373 +       res = platform_driver_register(&ubicom32lcd_driver);
52374 +       if (res == 0) {
52375 +               ubicom32lcd_device = platform_device_alloc(DRIVER_NAME, 0);
52376 +               if (ubicom32lcd_device) {
52377 +                       res = platform_device_add(ubicom32lcd_device);
52378 +               } else {
52379 +                       res = -ENOMEM;
52380 +               }
52381 +               if (res) {
52382 +                       platform_device_put(ubicom32lcd_device);
52383 +                       platform_driver_unregister(&ubicom32lcd_driver);
52384 +               }
52385 +       }
52386 +       return res;
52387 +}
52388 +module_init(ubicom32lcd_init);
52389 +
52390 +/*
52391 + * ubicom32lcd_exit
52392 + */
52393 +static void __exit ubicom32lcd_exit(void)
52394 +{
52395 +       platform_device_unregister(ubicom32lcd_device);
52396 +       platform_driver_unregister(&ubicom32lcd_driver);
52397 +}
52398 +module_exit(ubicom32lcd_exit);
52399 +
52400 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52401 +MODULE_DESCRIPTION("Ubicom32 LCD driver");
52402 +MODULE_LICENSE("GPL");
52403 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.h linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.h
52404 --- linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.h       1970-01-01 02:00:00.000000000 +0200
52405 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.h   2009-12-11 11:45:20.000000000 +0200
52406 @@ -0,0 +1,546 @@
52407 +/*
52408 + * ubicom32lcd.h
52409 + *     Ubicom32 lcd panel drivers
52410 + *
52411 + * (C) Copyright 2009, Ubicom, Inc.
52412 + *
52413 + * This file is part of the Ubicom32 Linux Kernel Port.
52414 + *
52415 + * This Ubicom32 library is free software: you can redistribute
52416 + * it and/or modify it under the terms of the GNU General Public License
52417 + * as published by the Free Software Foundation, either version 2 of the
52418 + * License, or (at your option) any later version.
52419 + *
52420 + * This Ubicom32 library is distributed in the hope that it
52421 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52422 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
52423 + * the GNU General Public License for more details.
52424 + *
52425 + * You should have received a copy of the GNU General Public License
52426 + * along with the Ubicom32 Linux Kernel Port.  If not,
52427 + * see <http://www.gnu.org/licenses/>.
52428 + */
52429 +
52430 +#ifndef _UBICOM32LCD_H_
52431 +#define _UBICOM32LCD_H_
52432 +
52433 +enum ubicom32lcd_op {
52434 +       /*
52435 +        * Sleep for (data) ms
52436 +        */
52437 +       LCD_STEP_SLEEP,
52438 +
52439 +       /*
52440 +        * Execute write of command
52441 +        */
52442 +       LCD_STEP_CMD,
52443 +
52444 +       /*
52445 +        * Execute write of data
52446 +        */
52447 +       LCD_STEP_DATA,
52448 +
52449 +       /*
52450 +        * Execute write of command/data
52451 +        */
52452 +       LCD_STEP_CMD_DATA,
52453 +
52454 +       /*
52455 +        * Script done
52456 +        */
52457 +       LCD_STEP_DONE,
52458 +};
52459 +
52460 +struct ubicom32lcd_step {
52461 +       enum ubicom32lcd_op             op;
52462 +       u16                             cmd;
52463 +       u16                             data;
52464 +};
52465 +
52466 +struct ubicom32lcd_panel {
52467 +       const struct ubicom32lcd_step   *init_seq;
52468 +       const char                      *desc;
52469 +
52470 +       u32                             xres;
52471 +       u32                             yres;
52472 +       u32                             stride;
52473 +       u32                             flags;
52474 +
52475 +       u16                             id;
52476 +       u16                             horz_reg;
52477 +       u16                             vert_reg;
52478 +       u16                             gram_reg;
52479 +};
52480 +
52481 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS
52482 +static const struct ubicom32lcd_step cfaf240320ktts_init_0[] = {
52483 +       {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h)          Page 14, SPFD5408B Datasheet
52484 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h)            Page 15, SPFD5408B Datasheet
52485 +       {LCD_STEP_CMD_DATA, 0x0003, 0x50A0,}, // Entry Mode (R03h)                              0 degrees
52486 +       {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h)                Page 16, SPFD5408B Datasheet
52487 +       {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h)                       Page 17, SPFD5408B Datasheet
52488 +       {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h)                       Page 18, SPFD5408B Datasheet
52489 +       {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah)                     Page 19, SPFD5408B Datasheet
52490 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch)    Page 20, SPFD5408B Datasheet
52491 +       {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh)                    Page 21, SPFD5408B Datasheet
52492 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh)    Page 21, SPFD5408B Datasheet
52493 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52494 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52495 +       {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52496 +       {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52497 +       {LCD_STEP_SLEEP, 0, 200},
52498 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52499 +       {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52500 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52501 +       {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52502 +       {LCD_STEP_SLEEP, 0, 50},
52503 +       {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52504 +       {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h)                         Page 30, SPFD5408B Datasheet
52505 +       {LCD_STEP_SLEEP, 0, 50},
52506 +       {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1                                Page 32, SPFD5408B Datasheet
52507 +       {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2                                Page 32, SPFD5408B Datasheet
52508 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3                                Page 32, SPFD5408B Datasheet
52509 +       {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4                                Page 32, SPFD5408B Datasheet
52510 +       {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5                                Page 32, SPFD5408B Datasheet
52511 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6                                Page 32, SPFD5408B Datasheet
52512 +       {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7                                Page 32, SPFD5408B Datasheet
52513 +       {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8                                Page 32, SPFD5408B Datasheet
52514 +       {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9                                Page 32, SPFD5408B Datasheet
52515 +       {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10                               Page 32, SPFD5408B Datasheet
52516 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11                               Page 32, SPFD5408B Datasheet
52517 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12                               Page 32, SPFD5408B Datasheet
52518 +       {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13                               Page 32, SPFD5408B Datasheet
52519 +       {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14                               Page 32, SPFD5408B Datasheet
52520 +       {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15                               Page 32, SPFD5408B Datasheet
52521 +       {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16                               Page 32, SPFD5408B Datasheet
52522 +       {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h)     Page 32, SPFD5408B Datasheet
52523 +       {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h)       Page 32, SPFD5408B Datasheet
52524 +       {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h)       Page 33, SPFD5408B Datasheet
52525 +       {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h)         Page 33, SPFD5408B Datasheet
52526 +       {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h)                   Page 33, SPFD5408B Datasheet
52527 +       {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h)                   Page 35, SPFD5408B Datasheet
52528 +       {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah)                 Page 35, SPFD5408B Datasheet
52529 +       {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h)    Page 35, SPFD5408B Datasheet
52530 +       {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h)   Page 35, SPFD5408B Datasheet
52531 +       {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h)     Page 36, SPFD5408B Datasheet
52532 +       {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h)    Page 36, SPFD5408B Datasheet
52533 +       {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h)   Page 36, SPFD5408B Datasheet
52534 +       {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h)     Page 36, SPFD5408B Datasheet
52535 +       {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h)               Page 36, SPFD5408B Datasheet
52536 +       {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h)               Page 37, SPFD5408B Datasheet
52537 +       {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h)               Page 38, SPFD5408B Datasheet
52538 +       {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h)               Page 38, SPFD5408B Datasheet
52539 +       {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h)               Page 40, SPFD5408B Datasheet
52540 +       {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h)               Page 41, SPFD5408B Datasheet
52541 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52542 +       {LCD_STEP_DONE, 0, 0},
52543 +};
52544 +
52545 +const struct ubicom32lcd_panel cfaf240320ktts_0 = {
52546 +       .desc           = "CFAF240320KTTS",
52547 +       .init_seq       = cfaf240320ktts_init_0,
52548 +       .horz_reg       = 0x20,
52549 +       .vert_reg       = 0x21,
52550 +       .gram_reg       = 0x22,
52551 +       .xres           = 240,
52552 +       .yres           = 320,
52553 +       .stride         = 240,
52554 +       .id             = 0x5408,
52555 +};
52556 +#endif
52557 +
52558 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS_180
52559 +static const struct ubicom32lcd_step cfaf240320ktts_init_180[] = {
52560 +       {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h)          Page 14, SPFD5408B Datasheet
52561 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h)            Page 15, SPFD5408B Datasheet
52562 +       {LCD_STEP_CMD_DATA, 0x0003, 0x5000,}, // Entry Mode (R03h)                              180 degrees
52563 +       {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h)                Page 16, SPFD5408B Datasheet
52564 +       {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h)                       Page 17, SPFD5408B Datasheet
52565 +       {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h)                       Page 18, SPFD5408B Datasheet
52566 +       {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah)                     Page 19, SPFD5408B Datasheet
52567 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch)    Page 20, SPFD5408B Datasheet
52568 +       {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh)                    Page 21, SPFD5408B Datasheet
52569 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh)    Page 21, SPFD5408B Datasheet
52570 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52571 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52572 +       {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52573 +       {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52574 +       {LCD_STEP_SLEEP, 0, 200},
52575 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52576 +       {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52577 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52578 +       {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52579 +       {LCD_STEP_SLEEP, 0, 50},
52580 +       {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52581 +       {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h)                         Page 30, SPFD5408B Datasheet
52582 +       {LCD_STEP_SLEEP, 0, 50},
52583 +       {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1                                Page 32, SPFD5408B Datasheet
52584 +       {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2                                Page 32, SPFD5408B Datasheet
52585 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3                                Page 32, SPFD5408B Datasheet
52586 +       {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4                                Page 32, SPFD5408B Datasheet
52587 +       {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5                                Page 32, SPFD5408B Datasheet
52588 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6                                Page 32, SPFD5408B Datasheet
52589 +       {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7                                Page 32, SPFD5408B Datasheet
52590 +       {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8                                Page 32, SPFD5408B Datasheet
52591 +       {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9                                Page 32, SPFD5408B Datasheet
52592 +       {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10                               Page 32, SPFD5408B Datasheet
52593 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11                               Page 32, SPFD5408B Datasheet
52594 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12                               Page 32, SPFD5408B Datasheet
52595 +       {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13                               Page 32, SPFD5408B Datasheet
52596 +       {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14                               Page 32, SPFD5408B Datasheet
52597 +       {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15                               Page 32, SPFD5408B Datasheet
52598 +       {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16                               Page 32, SPFD5408B Datasheet
52599 +       {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h)     Page 32, SPFD5408B Datasheet
52600 +       {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h)       Page 32, SPFD5408B Datasheet
52601 +       {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h)       Page 33, SPFD5408B Datasheet
52602 +       {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h)         Page 33, SPFD5408B Datasheet
52603 +       {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h)                   Page 33, SPFD5408B Datasheet
52604 +       {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h)                   Page 35, SPFD5408B Datasheet
52605 +       {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah)                 Page 35, SPFD5408B Datasheet
52606 +       {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h)    Page 35, SPFD5408B Datasheet
52607 +       {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h)   Page 35, SPFD5408B Datasheet
52608 +       {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h)     Page 36, SPFD5408B Datasheet
52609 +       {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h)    Page 36, SPFD5408B Datasheet
52610 +       {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h)   Page 36, SPFD5408B Datasheet
52611 +       {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h)     Page 36, SPFD5408B Datasheet
52612 +       {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h)               Page 36, SPFD5408B Datasheet
52613 +       {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h)               Page 37, SPFD5408B Datasheet
52614 +       {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h)               Page 38, SPFD5408B Datasheet
52615 +       {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h)               Page 38, SPFD5408B Datasheet
52616 +       {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h)               Page 40, SPFD5408B Datasheet
52617 +       {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h)               Page 41, SPFD5408B Datasheet
52618 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52619 +       {LCD_STEP_DONE, 0, 0},
52620 +};
52621 +
52622 +const struct ubicom32lcd_panel cfaf240320ktts_180 = {
52623 +       .desc           = "CFAF240320KTTS 180",
52624 +       .init_seq       = cfaf240320ktts_init_180,
52625 +       .horz_reg       = 0x20,
52626 +       .vert_reg       = 0x21,
52627 +       .gram_reg       = 0x22,
52628 +       .xres           = 240,
52629 +       .yres           = 320,
52630 +       .stride         = 240,
52631 +       .id             = 0x5408,
52632 +};
52633 +#endif
52634 +
52635 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52636 +static const struct ubicom32lcd_step tft2n0369ep_init[] = {
52637 +       {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52638 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52639 +       {LCD_STEP_SLEEP, 0, 15},
52640 +       {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52641 +       {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52642 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52643 +       {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52644 +       {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52645 +       {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52646 +       {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52647 +       {LCD_STEP_SLEEP, 0, 15},
52648 +       {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52649 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52650 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52651 +       {LCD_STEP_CMD_DATA, 0x0011, 0x6030},
52652 +       {LCD_STEP_SLEEP, 0, 20},
52653 +       {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52654 +       {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52655 +       {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52656 +       {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52657 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52658 +       {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52659 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52660 +       {LCD_STEP_SLEEP, 0, 20},
52661 +       {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52662 +       {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52663 +       {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52664 +       {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52665 +       {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52666 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52667 +       {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52668 +       {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52669 +       {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52670 +       {LCD_STEP_SLEEP, 0, 20},
52671 +       {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52672 +       {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52673 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52674 +       {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52675 +       {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52676 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52677 +       {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52678 +       {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52679 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52680 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52681 +       {LCD_STEP_SLEEP, 0, 20},
52682 +       {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52683 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52684 +       {LCD_STEP_CMD_DATA, 0x0046, 319},
52685 +       {LCD_STEP_DONE, 0, 0},
52686 +};
52687 +
52688 +const struct ubicom32lcd_panel tft2n0369ep = {
52689 +       .desc           = "TFT2N0369E-Portrait",
52690 +       .init_seq       = tft2n0369ep_init,
52691 +       .horz_reg       = 0x4e,
52692 +       .vert_reg       = 0x4f,
52693 +       .gram_reg       = 0x22,
52694 +       .xres           = 240,
52695 +       .yres           = 320,
52696 +       .stride         = 240,
52697 +       .id             = 0x8989,
52698 +};
52699 +#endif
52700 +
52701 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52702 +static const struct ubicom32lcd_step tft2n0369e_init[] = {
52703 +       {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52704 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52705 +       {LCD_STEP_SLEEP, 0, 15},
52706 +       {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52707 +       {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52708 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52709 +       {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52710 +       {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52711 +       {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52712 +       {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52713 +       {LCD_STEP_SLEEP, 0, 15},
52714 +       {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52715 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52716 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52717 +       {LCD_STEP_CMD_DATA, 0x0011, 0x60A8},
52718 +       {LCD_STEP_SLEEP, 0, 20},
52719 +       {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52720 +       {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52721 +       {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52722 +       {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52723 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52724 +       {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52725 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52726 +       {LCD_STEP_SLEEP, 0, 20},
52727 +       {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52728 +       {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52729 +       {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52730 +       {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52731 +       {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52732 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52733 +       {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52734 +       {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52735 +       {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52736 +       {LCD_STEP_SLEEP, 0, 20},
52737 +       {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52738 +       {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52739 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52740 +       {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52741 +       {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52742 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52743 +       {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52744 +       {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52745 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52746 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52747 +       {LCD_STEP_SLEEP, 0, 20},
52748 +       {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52749 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52750 +       {LCD_STEP_CMD_DATA, 0x0046, 319},
52751 +       {LCD_STEP_DONE, 0, 0},
52752 +};
52753 +
52754 +const struct ubicom32lcd_panel tft2n0369e = {
52755 +       .desc           = "TFT2N0369E-Landscape",
52756 +       .init_seq       = tft2n0369e_init,
52757 +       .horz_reg       = 0x4e,
52758 +       .vert_reg       = 0x4f,
52759 +       .gram_reg       = 0x22,
52760 +       .xres           = 320,
52761 +       .yres           = 240,
52762 +       .stride         = 320,
52763 +       .id             = 0x8989,
52764 +};
52765 +#endif
52766 +
52767 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52768 +static const struct ubicom32lcd_step cfaf240400d_init[] = {
52769 +       {LCD_STEP_CMD_DATA, 0x0606, 0x0000},    // Pin Control (R606h)          // Page 41 of SPFD5420A Datasheet
52770 +       {LCD_STEP_SLEEP, 0, 50},
52771 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0001},    // Display Control 1 (R007h)    // Page 16 of SPFD5420A Datasheet
52772 +       {LCD_STEP_SLEEP, 0, 50},
52773 +       {LCD_STEP_CMD_DATA, 0x0110, 0x0001},    // Power Control 6(R110h)       // Page 30 of SPFD5420A Datasheet
52774 +       {LCD_STEP_SLEEP, 0, 50},
52775 +       {LCD_STEP_CMD_DATA, 0x0100, 0x17B0},    // Power Control 1 (R100h)      // Page 26 of SPFD5420A Datasheet
52776 +       {LCD_STEP_CMD_DATA, 0x0101, 0x0147},    // Power Control 2 (R101h)      // Page 27 of SPFD5420A Datasheet
52777 +       {LCD_STEP_CMD_DATA, 0x0102, 0x019D},    // Power Control 3 (R102h)      // Page 28 of SPFD5420A Datasheet
52778 +       {LCD_STEP_CMD_DATA, 0x0103, 0x3600},    // Power Control 4 (R103h)      // Page 29 of SPFD5420A Datasheet
52779 +       {LCD_STEP_CMD_DATA, 0x0281, 0x0010},    // NVM read data 2 (R281h)      // Page 34 of SPFD5420A Datasheet
52780 +       {LCD_STEP_SLEEP, 0, 50},
52781 +       {LCD_STEP_CMD_DATA, 0x0102, 0x01BD},    // Power Control 3 (R102h)      // Page 28 of SPFD5420A Datasheet
52782 +       {LCD_STEP_SLEEP, 0, 50},
52783 +
52784 +       //--------------- Power control 1~6 ---------------//
52785 +       {LCD_STEP_CMD_DATA, 0x0100, 0x16B0},    // Power Control 1 (R100h)      // Page 26 of SPFD5420A Datasheet
52786 +       {LCD_STEP_CMD_DATA, 0x0101, 0x0147},    // Power Control 2 (R101h)      // Page 27 of SPFD5420A Datasheet
52787 +       {LCD_STEP_CMD_DATA, 0x0102, 0x01BD},    // Power Control 3 (R102h)      // Page 28 of SPFD5420A Datasheet
52788 +       {LCD_STEP_CMD_DATA, 0x0103, 0x2d00},    // Power Control 4 (R103h)      // Page 29 of SPFD5420A Datasheet
52789 +       {LCD_STEP_CMD_DATA, 0x0107, 0x0000},    // Power Control 5 (R107h)      // Page 30 of SPFD5420A Datasheet
52790 +       {LCD_STEP_CMD_DATA, 0x0110, 0x0001},    // Power Control 6(R110h)       // Page 30 of SPFD5420A Datasheet
52791 +       {LCD_STEP_CMD_DATA, 0x0280, 0x0000},    // NVM read data 1 (R280h)      // Page 33 of SPFD5420A Datasheet
52792 +       {LCD_STEP_CMD_DATA, 0x0281, 0x0006},    // NVM read data 2 (R281h)      // Page 34 of SPFD5420A Datasheet
52793 +       {LCD_STEP_CMD_DATA, 0x0282, 0x0000},    // NVM read data 3 (R282h)      // Page 34 of SPFD5420A Datasheet
52794 +
52795 +       //------- Gamma 2.2 control (R300h to R30Fh) ------//
52796 +       {LCD_STEP_CMD_DATA, 0x0300, 0x0101},
52797 +       {LCD_STEP_CMD_DATA, 0x0301, 0x0b27},
52798 +       {LCD_STEP_CMD_DATA, 0x0302, 0x132a},
52799 +       {LCD_STEP_CMD_DATA, 0x0303, 0x2a13},
52800 +       {LCD_STEP_CMD_DATA, 0x0304, 0x270b},
52801 +       {LCD_STEP_CMD_DATA, 0x0305, 0x0101},
52802 +       {LCD_STEP_CMD_DATA, 0x0306, 0x1205},
52803 +       {LCD_STEP_CMD_DATA, 0x0307, 0x0512},
52804 +       {LCD_STEP_CMD_DATA, 0x0308, 0x0005},
52805 +       {LCD_STEP_CMD_DATA, 0x0309, 0x0003},
52806 +       {LCD_STEP_CMD_DATA, 0x030A, 0x0f04},
52807 +       {LCD_STEP_CMD_DATA, 0x030B, 0x0f00},
52808 +       {LCD_STEP_CMD_DATA, 0x030C, 0x000f},
52809 +       {LCD_STEP_CMD_DATA, 0x030D, 0x040f},
52810 +       {LCD_STEP_CMD_DATA, 0x030E, 0x0300},
52811 +       {LCD_STEP_CMD_DATA, 0x030F, 0x0500},
52812 +
52813 +       {LCD_STEP_CMD_DATA, 0x0400, 0x3500},    // Base Image Number of Line (R400h)            // Page 36 of SPFD5420A Datasheet
52814 +       {LCD_STEP_CMD_DATA, 0x0401, 0x0001},    // Base Image Display Control (R401h)           // Page 39 of SPFD5420A Datasheet
52815 +       {LCD_STEP_CMD_DATA, 0x0404, 0x0000},    // Based Image Vertical Scroll Control (R404h)  // Page 40 of SPFD5420A Datasheet
52816 +
52817 +       //--------------- Normal set ---------------//
52818 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0000},    // ID Read Register (R000h)                     // Page 13 of SPFD5420A Datasheet
52819 +       {LCD_STEP_CMD_DATA, 0x0001, 0x0100},    // Driver Output Control Register (R001h)       // Page 14 of SPFD5420A Datasheet
52820 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0100},    // LCD Driving Waveform Control (R002h)         // Page 14 of SPFD5420A Datasheet
52821 +       {LCD_STEP_CMD_DATA, 0x0003, 0x1030},    // Entry Mode (R003h)                           // Page 15 of SPFD5420A Datasheet
52822 +       {LCD_STEP_CMD_DATA, 0x0006, 0x0000},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52823 +       {LCD_STEP_CMD_DATA, 0x0008, 0x0808},    // Display Control 2 (R008h)                    // Page 17 of SPFD5420A Datasheet
52824 +       {LCD_STEP_CMD_DATA, 0x0009, 0x0001},    // Display Control 3 (R009h)                    // Page 18 of SPFD5420A Datasheet
52825 +       {LCD_STEP_CMD_DATA, 0x000B, 0x0010},    // Low Power Control (R00Bh)                    // Page 19 of SPFD5420A Datasheet
52826 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0000},    // External Display Interface Control 1 (R00Ch) // Page 19 of SPFD5420A Datasheet
52827 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000},    // External Display Interface Control 2 (R00Fh) // Page 20 of SPFD5420A Datasheet
52828 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0001},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52829 +
52830 +       //--------------- Panel interface control 1~6 ---------------//
52831 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0012},    // Panel Interface Control 1 (R010h)            // Page 20 of SPFD5420A Datasheet
52832 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0202},    // Panel Interface Control 2 (R011h)            // Page 21 of SPFD5420A Datasheet
52833 +       {LCD_STEP_CMD_DATA, 0x0012, 0x0300},    // Panel Interface control 3 (R012h)            // Page 22 of SPFD5420A Datasheet
52834 +       {LCD_STEP_CMD_DATA, 0x0020, 0x021E},    // Panel Interface control 4 (R020h)            // Page 22 of SPFD5420A Datasheet
52835 +       {LCD_STEP_CMD_DATA, 0x0021, 0x0202},    // Panel Interface Control 5 (021Rh)            // Page 24 of SPFD5420A Datasheet
52836 +       {LCD_STEP_CMD_DATA, 0x0022, 0x0100},    // Panel Interface Control 6 (R022h)            // Page 25 of SPFD5420A Datasheet
52837 +       {LCD_STEP_CMD_DATA, 0x0090, 0x8000},    // Frame Marker Control (R090h)                 // Page 25 of SPFD5420A Datasheet
52838 +
52839 +       //--------------- Partial display ---------------//
52840 +       {LCD_STEP_CMD_DATA, 0x0210, 0x0000},    // Window Horizontal RAM Address Start (R210h)  // Page 35 of SPFD5420A Datasheet
52841 +       {LCD_STEP_CMD_DATA, 0x0211, 0x00EF},    // Window Horziontal RAM Address End (R211h)    // Page 35 of SPFD5420A Datasheet
52842 +       {LCD_STEP_CMD_DATA, 0x0212, 0x0000},    // Window Vertical RAM Address Start (R212h)    // Page 35 of SPFD5420A Datasheet
52843 +       {LCD_STEP_CMD_DATA, 0x0213, 0x018F},    // Window Vertical RAM Address End (R213h)      // Page 35 of SPFD5420A Datasheet
52844 +       {LCD_STEP_CMD_DATA, 0x0500, 0x0000},    // Display Position - Partial Display 1 (R500h) // Page 40 of SPFD5420A Datasheet
52845 +       {LCD_STEP_CMD_DATA, 0x0501, 0x0000},    // RAM Address Start - Partial Display 1 (R501h)// Page 40 of SPFD5420A Datasheet
52846 +       {LCD_STEP_CMD_DATA, 0x0502, 0x0000},    // RAM Address End - Partail Display 1 (R502h)  // Page 40 of SPFD5420A Datasheet
52847 +       {LCD_STEP_CMD_DATA, 0x0503, 0x0000},    // Display Position - Partial Display 2 (R503h) // Page 40 of SPFD5420A Datasheet
52848 +       {LCD_STEP_CMD_DATA, 0x0504, 0x0000},    // RAM Address Start . Partial Display 2 (R504h)// Page 41 of SPFD5420A Datasheet
52849 +       {LCD_STEP_CMD_DATA, 0x0505, 0x0000},    // RAM Address End . Partial Display 2 (R505h)  // Page 41 of SPFD5420A Datasheet
52850 +       {LCD_STEP_CMD_DATA, 0x0606, 0x0000},    // Pin Control (R606h)                          // Page 41 of SPFD5420A Datasheet
52851 +       {LCD_STEP_CMD_DATA, 0x06F0, 0x0000},    // NVM Access Control (R6F0h)                   // Page 41 of SPFD5420A Datasheet
52852 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52853 +       {LCD_STEP_SLEEP, 0, 50},
52854 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0171},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52855 +       {LCD_STEP_SLEEP, 0, 10},
52856 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52857 +       {LCD_STEP_DONE, 0, 0},
52858 +};
52859 +
52860 +const struct ubicom32lcd_panel cfaf240400d = {
52861 +       .desc           = "CFAF240400D",
52862 +       .init_seq       = cfaf240400d_init,
52863 +       .horz_reg       = 0x0200,
52864 +       .vert_reg       = 0x0201,
52865 +       .gram_reg       = 0x0202,
52866 +       .xres           = 240,
52867 +       .yres           = 400,
52868 +       .stride         = 240,
52869 +       .id             = 0x5420,
52870 +};
52871 +#endif
52872 +
52873 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52874 +static const struct ubicom32lcd_step cfaf320240f_init[] = {
52875 +       {LCD_STEP_CMD_DATA, 0x0028, 0x0006},    // VCOM OTP                             Page 55-56 of SSD2119 datasheet
52876 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0001},    // start Oscillator                     Page 36 of SSD2119 datasheet
52877 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000},    // Sleep mode                           Page 49 of SSD2119 datasheet
52878 +       {LCD_STEP_CMD_DATA, 0x0001, 0x32EF},    // Driver Output Control                Page 36-39 of SSD2119 datasheet
52879 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0600},    // LCD Driving Waveform Control         Page 40-42 of SSD2119 datasheet
52880 +       {LCD_STEP_CMD_DATA, 0x0003, 0x6A38},    // Power Control 1                      Page 43-44 of SSD2119 datasheet
52881 +       {LCD_STEP_CMD_DATA, 0x0011, 0x6870},    // Entry Mode                           Page 50-52 of SSD2119 datasheet
52882 +       {LCD_STEP_CMD_DATA, 0X000F, 0x0000},    // Gate Scan Position                   Page 49 of SSD2119 datasheet
52883 +       {LCD_STEP_CMD_DATA, 0X000B, 0x5308},    // Frame Cycle Control                  Page 45 of SSD2119 datasheet
52884 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0003},    // Power Control 2                      Page 47 of SSD2119 datasheet
52885 +       {LCD_STEP_CMD_DATA, 0x000D, 0x000A},    // Power Control 3                      Page 48 of SSD2119 datasheet
52886 +       {LCD_STEP_CMD_DATA, 0x000E, 0x2E00},    // Power Control 4                      Page 48 of SSD2119 datasheet
52887 +       {LCD_STEP_CMD_DATA, 0x001E, 0x00BE},    // Power Control 5                      Page 53 of SSD2119 datasheet
52888 +       {LCD_STEP_CMD_DATA, 0x0025, 0x8000},    // Frame Frequency Control              Page 53 of SSD2119 datasheet
52889 +       {LCD_STEP_CMD_DATA, 0x0026, 0x7800},    // Analog setting                       Page 54 of SSD2119 datasheet
52890 +       {LCD_STEP_CMD_DATA, 0x004E, 0x0000},    // Ram Address Set                      Page 58 of SSD2119 datasheet
52891 +       {LCD_STEP_CMD_DATA, 0x004F, 0x0000},    // Ram Address Set                      Page 58 of SSD2119 datasheet
52892 +       {LCD_STEP_CMD_DATA, 0x0012, 0x08D9},    // Sleep mode                           Page 49 of SSD2119 datasheet
52893 +
52894 +       // Gamma Control (R30h to R3Bh) -- Page 56 of SSD2119 datasheet
52895 +       {LCD_STEP_CMD_DATA, 0x0030, 0x0000},
52896 +       {LCD_STEP_CMD_DATA, 0x0031, 0x0104},
52897 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0100},
52898 +       {LCD_STEP_CMD_DATA, 0x0033, 0x0305},
52899 +       {LCD_STEP_CMD_DATA, 0x0034, 0x0505},
52900 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0305},
52901 +       {LCD_STEP_CMD_DATA, 0x0036, 0x0707},
52902 +       {LCD_STEP_CMD_DATA, 0x0037, 0x0300},
52903 +       {LCD_STEP_CMD_DATA, 0x003A, 0x1200},
52904 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0800},
52905 +
52906 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0033},    // Display Control                       Page 45 of SSD2119 datasheet
52907 +
52908 +       {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},    // Vertical RAM address position         Page 57 of SSD2119 datasheet
52909 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},    // Horizontal RAM address position       Page 57 of SSD2119 datasheet
52910 +       {LCD_STEP_CMD_DATA, 0x0046, 0x013F},    // Horizontal RAM address position       Page 57 of SSD2119 datasheet
52911 +
52912 +       {LCD_STEP_SLEEP, 0, 150},
52913 +
52914 +       {LCD_STEP_DONE, 0, 0},
52915 +};
52916 +
52917 +const struct ubicom32lcd_panel cfaf320240f = {
52918 +       .desc           = "CFAF320240F",
52919 +       .init_seq       = cfaf320240f_init,
52920 +       .horz_reg       = 0x4e,
52921 +       .vert_reg       = 0x4f,
52922 +       .gram_reg       = 0x22,
52923 +       .xres           = 320,
52924 +       .yres           = 240,
52925 +       .stride         = 320,
52926 +       .id             = 0x9919,
52927 +};
52928 +#endif
52929 +
52930 +const struct ubicom32lcd_panel *ubicom32lcd_panels[] = {
52931 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS_180
52932 +       &cfaf240320ktts_180,
52933 +#endif
52934 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS
52935 +       &cfaf240320ktts_0,
52936 +#endif
52937 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52938 +       &cfaf240400d,
52939 +#endif
52940 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52941 +       &tft2n0369ep,
52942 +#endif
52943 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52944 +       &tft2n0369e,
52945 +#endif
52946 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52947 +       &cfaf320240f,
52948 +#endif
52949 +       NULL,
52950 +};
52951 +
52952 +#endif
52953 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32lcdpower.c linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcdpower.c
52954 --- linux-2.6.30.10/drivers/video/backlight/ubicom32lcdpower.c  1970-01-01 02:00:00.000000000 +0200
52955 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcdpower.c      2009-12-11 11:45:20.000000000 +0200
52956 @@ -0,0 +1,194 @@
52957 +/*
52958 + * drivers/video/backlight/ubicom32lcdpowerpower.c
52959 + *     LCD power driver for the Ubicom32 platform
52960 + *
52961 + * (C) Copyright 2009, Ubicom, Inc.
52962 + *
52963 + * This file is part of the Ubicom32 Linux Kernel Port.
52964 + *
52965 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52966 + * it and/or modify it under the terms of the GNU General Public License
52967 + * as published by the Free Software Foundation, either version 2 of the
52968 + * License, or (at your option) any later version.
52969 + *
52970 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52971 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52972 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
52973 + * the GNU General Public License for more details.
52974 + *
52975 + * You should have received a copy of the GNU General Public License
52976 + * along with the Ubicom32 Linux Kernel Port.  If not,
52977 + * see <http://www.gnu.org/licenses/>.
52978 + *
52979 + * Ubicom32 implementation derived from (with many thanks):
52980 + *   arch/m68knommu
52981 + *   arch/blackfin
52982 + *   arch/parisc
52983 + */
52984 +#include <linux/init.h>
52985 +#include <linux/kernel.h>
52986 +#include <linux/module.h>
52987 +#include <linux/platform_device.h>
52988 +#include <linux/lcd.h>
52989 +#include <linux/fb.h>
52990 +#include <linux/gpio.h>
52991 +
52992 +#include <asm/ubicom32lcdpower.h>
52993 +#include <asm/ip5000.h>
52994 +
52995 +#define DRIVER_NAME                    "ubicom32lcdpower"
52996 +
52997 +struct ubicom32lcdpower_data {
52998 +       /*
52999 +        * Pointer to the platform data structure.  Keep this around since we need values
53000 +        * from it to set the backlight intensity.
53001 +        */
53002 +       const struct ubicom32lcdpower_platform_data     *pdata;
53003 +
53004 +       /*
53005 +        * LCD device, we have to save this for use when we remove ourselves.
53006 +        */
53007 +       struct lcd_device                       *lcddev;
53008 +};
53009 +
53010 +/*
53011 + * ubicom32lcdpower_set_power
53012 + */
53013 +static int ubicom32lcdpower_set_power(struct lcd_device *ld, int power)
53014 +{
53015 +       struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
53016 +       if (power == FB_BLANK_UNBLANK) {
53017 +               gpio_direction_output(ud->pdata->vgh_gpio, ud->pdata->vgh_polarity);
53018 +               return 0;
53019 +       }
53020 +
53021 +       gpio_direction_output(ud->pdata->vgh_gpio, !ud->pdata->vgh_polarity);
53022 +       return 0;
53023 +}
53024 +
53025 +/*
53026 + * ubicom32lcdpower_get_power
53027 + */
53028 +static int ubicom32lcdpower_get_power(struct lcd_device *ld)
53029 +{
53030 +       struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
53031 +       int vgh = gpio_get_value(ud->pdata->vgh_gpio);
53032 +       if ((vgh && ud->pdata->vgh_polarity) || (!vgh && !ud->pdata->vgh_polarity)) {
53033 +               return 1;
53034 +       }
53035 +
53036 +       return 0;
53037 +}
53038 +
53039 +static struct lcd_ops ubicom32lcdpower_ops = {
53040 +       .get_power = ubicom32lcdpower_get_power,
53041 +       .set_power = ubicom32lcdpower_set_power,
53042 +};
53043 +
53044 +/*
53045 + * ubicom32lcdpower_probe
53046 + */
53047 +static int ubicom32lcdpower_probe(struct platform_device *pdev)
53048 +{
53049 +       const struct ubicom32lcdpower_platform_data *pdata = pdev->dev.platform_data;
53050 +       struct ubicom32lcdpower_data *ud;
53051 +       struct lcd_device *lcddev;
53052 +       int retval;
53053 +
53054 +       /*
53055 +        * Check to see if we have any platform data, if we don't have a LCD to control
53056 +        */
53057 +       if (!pdata) {
53058 +               return -ENODEV;
53059 +       }
53060 +
53061 +       /*
53062 +        * Allocate our private data
53063 +        */
53064 +       ud = kzalloc(sizeof(struct ubicom32lcdpower_data), GFP_KERNEL);
53065 +       if (!ud) {
53066 +               return -ENOMEM;
53067 +       }
53068 +
53069 +       ud->pdata = pdata;
53070 +
53071 +       /*
53072 +        * Request our GPIOs
53073 +        */
53074 +       retval = gpio_request(pdata->vgh_gpio, "vgh");
53075 +       if (retval) {
53076 +               dev_err(&pdev->dev, "Failed to allocate vgh GPIO\n");
53077 +               goto fail_gpio;
53078 +       }
53079 +
53080 +       /*
53081 +        * Register our lcd device
53082 +        */
53083 +       lcddev = lcd_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32lcdpower_ops);
53084 +       if (IS_ERR(lcddev)) {
53085 +               retval = PTR_ERR(lcddev);
53086 +               goto fail;
53087 +       }
53088 +
53089 +       ud->lcddev = lcddev;
53090 +       platform_set_drvdata(pdev, ud);
53091 +
53092 +       ubicom32lcdpower_set_power(lcddev, FB_BLANK_UNBLANK);
53093 +
53094 +       printk(KERN_INFO DRIVER_NAME ": LCD driver started\n");
53095 +
53096 +       return 0;
53097 +
53098 +fail:
53099 +       gpio_free(pdata->vgh_gpio);
53100 +
53101 +fail_gpio:
53102 +       platform_set_drvdata(pdev, NULL);
53103 +       kfree(ud);
53104 +       return retval;
53105 +}
53106 +
53107 +/*
53108 + * ubicom32lcdpower_remove
53109 + */
53110 +static int __exit ubicom32lcdpower_remove(struct platform_device *pdev)
53111 +{
53112 +       struct ubicom32lcdpower_data *ud = platform_get_drvdata(pdev);
53113 +
53114 +       lcd_device_unregister(ud->lcddev);
53115 +       platform_set_drvdata(pdev, NULL);
53116 +       kfree(ud);
53117 +
53118 +       return 0;
53119 +}
53120 +
53121 +static struct platform_driver ubicom32lcdpower_driver = {
53122 +       .driver = {
53123 +               .name = DRIVER_NAME,
53124 +               .owner = THIS_MODULE,
53125 +       },
53126 +
53127 +       .remove = __exit_p(ubicom32lcdpower_remove),
53128 +};
53129 +
53130 +/*
53131 + * ubicom32lcdpower_init
53132 + */
53133 +static int __init ubicom32lcdpower_init(void)
53134 +{
53135 +       return platform_driver_probe(&ubicom32lcdpower_driver, ubicom32lcdpower_probe);
53136 +}
53137 +module_init(ubicom32lcdpower_init);
53138 +
53139 +/*
53140 + * ubicom32lcdpower_exit
53141 + */
53142 +static void __exit ubicom32lcdpower_exit(void)
53143 +{
53144 +       platform_driver_unregister(&ubicom32lcdpower_driver);
53145 +}
53146 +module_exit(ubicom32lcdpower_exit);
53147 +
53148 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
53149 +MODULE_DESCRIPTION("Ubicom32 lcd power driver");
53150 +MODULE_LICENSE("GPL");
53151 diff -ruN linux-2.6.30.10/drivers/video/Kconfig linux-2.6.30.10-ubi/drivers/video/Kconfig
53152 --- linux-2.6.30.10/drivers/video/Kconfig       2009-12-04 08:00:07.000000000 +0200
53153 +++ linux-2.6.30.10-ubi/drivers/video/Kconfig   2009-12-11 11:45:20.000000000 +0200
53154 @@ -609,6 +609,50 @@
53155          This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
53156          It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
53157  
53158 +config FB_UBICOM32
53159 +       tristate "Ubicom32 Frame Buffer driver"
53160 +       depends on FB && UBICOM32
53161 +       select FB_CFB_FILLRECT
53162 +       select FB_CFB_COPYAREA
53163 +       select FB_CFB_IMAGEBLIT
53164 +       select FONT_6x11 if FRAMEBUFFER_CONSOLE
53165 +       help
53166 +        This is the framebuffer device driver for the Ubicom32 architecture.
53167 +        You can configure video memory by using kernel command line parameters, for example:
53168 +               video=ubicomfb:vram_size=512,init_value=0xffff
53169 +
53170 +config FB_UBICOM32_PLIO80
53171 +       tristate "Ubicom32 80 Bus PLIO Frame Buffer driver"
53172 +       depends on FB && UBICOM32
53173 +       select FB_CFB_FILLRECT
53174 +       select FB_CFB_COPYAREA
53175 +       select FB_CFB_IMAGEBLIT
53176 +       select FONT_6x11 if FRAMEBUFFER_CONSOLE
53177 +       select UBICOM32_PLIO
53178 +       help
53179 +        This is a framebuffer device driver for the Ubicom32 architecture.
53180 +        You can configure the xres, yres and vram size (in kilobytes) by using
53181 +        kernel command line parameters, for example:
53182 +               video=ubicom32vfb:xres=320,yres=240,vram_size=512
53183 +
53184 +config FB_UBICOM32_VIRTUAL
53185 +       tristate "Ubicom32 Virtual Frame Buffer driver"
53186 +       depends on FB && UBICOM32
53187 +       select FB_CFB_FILLRECT
53188 +       select FB_CFB_COPYAREA
53189 +       select FB_CFB_IMAGEBLIT
53190 +       select FONT_6x11 if FRAMEBUFFER_CONSOLE
53191 +       help
53192 +        This is a virtual framebuffer device driver for the Ubicom32 architecture.
53193 +        You can configure the xres, yres and vram size (in kilobytes) by using
53194 +        kernel command line parameters, for example:
53195 +               video=ubicom32vfb:xres=320,yres=240,vram_size=512
53196 +
53197 +config FB_UBICOM32_VIRTUAL_NOAUTO
53198 +       bool "Do not automatically load"
53199 +       depends on FB_UBICOM32_VIRTUAL
53200 +       help
53201 +        Select this option to prevent the VFB from automatically loading at boot.
53202  
53203  config FB_STI
53204         tristate "HP STI frame buffer device support"
53205 diff -ruN linux-2.6.30.10/drivers/video/Makefile linux-2.6.30.10-ubi/drivers/video/Makefile
53206 --- linux-2.6.30.10/drivers/video/Makefile      2009-12-04 08:00:07.000000000 +0200
53207 +++ linux-2.6.30.10-ubi/drivers/video/Makefile  2009-12-11 11:45:20.000000000 +0200
53208 @@ -136,6 +136,10 @@
53209  obj-$(CONFIG_FB_BFIN_T350MCQB)   += bfin-t350mcqb-fb.o
53210  obj-$(CONFIG_FB_MX3)             += mx3fb.o
53211  
53212 +obj-$(CONFIG_FB_UBICOM32)         += ubicom32fb.o
53213 +obj-$(CONFIG_FB_UBICOM32_PLIO80)  += ubicom32plio80.o
53214 +obj-$(CONFIG_FB_UBICOM32_VIRTUAL) += ubicom32vfb.o
53215 +
53216  # the test framebuffer is last
53217  obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
53218  
53219 diff -ruN linux-2.6.30.10/drivers/video/ubicom32fb.c linux-2.6.30.10-ubi/drivers/video/ubicom32fb.c
53220 --- linux-2.6.30.10/drivers/video/ubicom32fb.c  1970-01-01 02:00:00.000000000 +0200
53221 +++ linux-2.6.30.10-ubi/drivers/video/ubicom32fb.c      2009-12-11 11:45:21.000000000 +0200
53222 @@ -0,0 +1,779 @@
53223 +/*
53224 + * drivers/video/ubicom32fb.c
53225 + *     Ubicom32 frame buffer driver
53226 + *
53227 + * (C) Copyright 2009, Ubicom, Inc.
53228 + *
53229 + * This file is part of the Ubicom32 Linux Kernel Port.
53230 + *
53231 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
53232 + * it and/or modify it under the terms of the GNU General Public License
53233 + * as published by the Free Software Foundation, either version 2 of the
53234 + * License, or (at your option) any later version.
53235 + *
53236 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
53237 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
53238 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
53239 + * the GNU General Public License for more details.
53240 + *
53241 + * You should have received a copy of the GNU General Public License
53242 + * along with the Ubicom32 Linux Kernel Port.  If not,
53243 + * see <http://www.gnu.org/licenses/>.
53244 + *
53245 + * Ubicom32 implementation derived from (with many thanks):
53246 + *   arch/m68knommu
53247 + *   arch/blackfin
53248 + *   arch/parisc
53249 + */
53250 +
53251 +/*
53252 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
53253 + * Geert Uytterhoeven.
53254 + */
53255 +
53256 +#include <linux/device.h>
53257 +#include <linux/module.h>
53258 +#include <linux/kernel.h>
53259 +#include <linux/version.h>
53260 +#include <linux/errno.h>
53261 +#include <linux/string.h>
53262 +#include <linux/mm.h>
53263 +#include <linux/fb.h>
53264 +#include <linux/init.h>
53265 +#include <linux/dma-mapping.h>
53266 +#include <linux/platform_device.h>
53267 +#include <linux/device.h>
53268 +#include <linux/uaccess.h>
53269 +#include <linux/interrupt.h>
53270 +
53271 +#include <asm/io.h>
53272 +#include <asm/ip5000.h>
53273 +#include <asm/vdc_tio.h>
53274 +#include <asm/ubicom32fb.h>
53275 +
53276 +#define DRIVER_NAME            "ubicom32fb"
53277 +#define DRIVER_DESCRIPTION     "Ubicom32 frame buffer driver"
53278 +
53279 +#define PALETTE_ENTRIES_NO     16
53280 +
53281 +/*
53282 + * Option variables
53283 + *
53284 + * vram_size:  VRAM size in kilobytes, subject to alignment
53285 + */
53286 +static int vram_size = 0;
53287 +module_param(vram_size, int, 0);
53288 +MODULE_PARM_DESC(vram, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
53289 +static int init_value = 0;
53290 +module_param(init_value, int, 0);
53291 +MODULE_PARM_DESC(init, "Initial value of the framebuffer (16-bit number).");
53292 +
53293 +/*
53294 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
53295 + */
53296 +static struct fb_fix_screeninfo ubicom32fb_fix = {
53297 +       .id =           "Ubicom32",
53298 +       .type =         FB_TYPE_PACKED_PIXELS,
53299 +       .visual =       FB_VISUAL_TRUECOLOR,
53300 +       .accel =        FB_ACCEL_UBICOM32,
53301 +};
53302 +
53303 +/*
53304 + * Filled in at probe time when we find out what the hardware supports
53305 + */
53306 +static struct fb_var_screeninfo ubicom32fb_var;
53307 +
53308 +/*
53309 + * Private data structure
53310 + */
53311 +struct ubicom32fb_drvdata {
53312 +       struct fb_info                  *fbinfo;
53313 +       bool                            cmap_alloc;
53314 +
53315 +       /*
53316 +        * The address of the framebuffer in memory
53317 +        */
53318 +       void                            *fb;
53319 +       void                            *fb_aligned;
53320 +
53321 +       /*
53322 +        * Total size of vram including alignment allowance
53323 +        */
53324 +       u32                             total_vram_size;
53325 +
53326 +       /*
53327 +        * Interrupt to set when changing registers
53328 +        */
53329 +       u32                             vp_int;
53330 +
53331 +       /*
53332 +        * Optional: Interrupt used by TIO to signal us
53333 +        */
53334 +       u32                             rx_int;
53335 +
53336 +       /*
53337 +        * Base address of the regs for VDC_TIO
53338 +        */
53339 +       volatile struct vdc_tio_vp_regs *regs;
53340 +
53341 +       /*
53342 +        * non-zero if we are in yuv mode
53343 +        */
53344 +       u8_t                            is_yuv;
53345 +
53346 +       /*
53347 +        * Fake palette of 16 colors
53348 +        */
53349 +       u32                             pseudo_palette[PALETTE_ENTRIES_NO];
53350 +
53351 +       /*
53352 +        * Wait queue and lock used to block when we need to wait
53353 +        * for something to happen.
53354 +        */
53355 +       wait_queue_head_t               waitq;
53356 +       struct mutex                    lock;
53357 +
53358 +};
53359 +
53360 +/*
53361 + * ubicom32fb_set_next_frame
53362 + *     Sets the next frame buffer to display
53363 + *
53364 + * if sync is TRUE then this function will block until the hardware
53365 + * acknowledges the change
53366 + */
53367 +static inline void ubicom32fb_set_next_frame(struct ubicom32fb_drvdata *ud, void *fb, u8_t sync)
53368 +{
53369 +       ud->regs->next_frame_flags = ud->is_yuv ? VDCTIO_NEXT_FRAME_FLAG_YUV : 0;
53370 +       ud->regs->next_frame = (void *)((u32_t)fb | 1);
53371 +
53372 +       /*
53373 +        * If we have interrupts, then we can wait on it
53374 +        */
53375 +       if (ud->rx_int != -1) {
53376 +               DEFINE_WAIT(wait);
53377 +               unsigned long flags;
53378 +
53379 +               spin_lock_irqsave(&ud->lock, flags);
53380 +               prepare_to_wait(&ud->waitq, &wait, TASK_INTERRUPTIBLE);
53381 +               spin_unlock_irqrestore(&ud->lock, flags);
53382 +               schedule();
53383 +               finish_wait(&ud->waitq, &wait);
53384 +               return;
53385 +       }
53386 +
53387 +       /*
53388 +        * No interrupt, we will just spin here
53389 +        */
53390 +       while (sync && ((u32_t)ud->regs->next_frame & 1));
53391 +}
53392 +
53393 +/*
53394 + * ubicom32fb_send_command
53395 + *     Sends a command/data pair to the VDC
53396 + */
53397 +static inline void ubicom32fb_send_command(struct ubicom32fb_drvdata *ud, u16 command, u8_t block)
53398 +{
53399 +       ud->regs->command = command;
53400 +       ubicom32_set_interrupt(ud->vp_int);
53401 +       while (block && ud->regs->command);
53402 +}
53403 +
53404 +/*
53405 + * ubicom32fb_ioctl
53406 + *     Handles any ioctls sent to us
53407 + */
53408 +static int ubicom32fb_ioctl(struct fb_info *fbi, unsigned int cmd,
53409 +                      unsigned long arg)
53410 +{
53411 +       struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53412 +       void __user *argp = (void __user *)arg;
53413 +       int retval = -EFAULT;
53414 +
53415 +       switch (cmd) {
53416 +       case UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC:
53417 +               // check alignment, return -EINVAL if necessary
53418 +               ubicom32fb_set_next_frame(ud, argp, 1);
53419 +               retval = 0;
53420 +               break;
53421 +
53422 +       case UBICOM32FB_IOCTL_SET_NEXT_FRAME:
53423 +               // check alignment, return -EINVAL if necessary
53424 +               ubicom32fb_set_next_frame(ud, argp, 0);
53425 +               retval = 0;
53426 +               break;
53427 +
53428 +       case UBICOM32FB_IOCTL_SET_MODE:
53429 +               if (!(ud->regs->caps & VDCTIO_CAPS_SUPPORTS_SCALING)) {
53430 +                       break;
53431 +               } else {
53432 +                       struct ubicom32fb_mode mode;
53433 +                       volatile struct vdc_tio_vp_regs *regs = ud->regs;
53434 +                       u32_t flags = 0;
53435 +
53436 +                       if (copy_from_user(&mode, argp, sizeof(mode))) {
53437 +                               break;
53438 +                       }
53439 +
53440 +                       regs->x_in = mode.width;
53441 +                       regs->y_in = mode.height;
53442 +                       regs->x_out = regs->xres;
53443 +                       regs->y_out = regs->yres;
53444 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER) {
53445 +                               flags |= VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER;
53446 +                       }
53447 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER) {
53448 +                               flags |= VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER;
53449 +                       }
53450 +                       ud->is_yuv = mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV;
53451 +                       if (ud->is_yuv) {
53452 +                               flags |= VDCTIO_SCALE_FLAG_YUV;
53453 +                       }
53454 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255) {
53455 +                               flags |= VDCTIO_SCALE_FLAG_VRANGE_16_255;
53456 +                       }
53457 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255) {
53458 +                               flags |= VDCTIO_SCALE_FLAG_VRANGE_0_255;
53459 +                       }
53460 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB) {
53461 +                               flags |= VDCTIO_SCALE_FLAG_VSUB;
53462 +                       }
53463 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1) {
53464 +                               flags |= VDCTIO_SCALE_FLAG_HSUB_2_1;
53465 +                       }
53466 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1) {
53467 +                               flags |= VDCTIO_SCALE_FLAG_HSUB_1_1;
53468 +                       }
53469 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE) {
53470 +                               flags |= VDCTIO_SCALE_FLAG_ENABLE;
53471 +                       }
53472 +                       if (mode.next_frame) {
53473 +                               flags |= VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER;
53474 +                               regs->next_frame = mode.next_frame;
53475 +                       }
53476 +
53477 +                       regs->scale_flags = flags;
53478 +                       ubicom32fb_send_command(ud, VDCTIO_COMMAND_SET_SCALE_MODE, 1);
53479 +                       retval = 0;
53480 +                       break;
53481 +               }
53482 +
53483 +       default:
53484 +               retval = -ENOIOCTLCMD;
53485 +               break;
53486 +       }
53487 +
53488 +       return retval;
53489 +}
53490 +
53491 +/*
53492 + * ubicom32fb_interrupt
53493 + *     Called by the OS when the TIO has set the rx_int
53494 + */
53495 +static irqreturn_t ubicom32fb_interrupt(int vec, void *appdata)
53496 +{
53497 +       struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)appdata;
53498 +
53499 +       spin_lock(&ud->lock);
53500 +       if (waitqueue_active(&ud->waitq)) {
53501 +               wake_up(&ud->waitq);
53502 +       }
53503 +       spin_unlock(&ud->lock);
53504 +
53505 +       return IRQ_HANDLED;
53506 +}
53507 +
53508 +/*
53509 + * ubicom32fb_pan_display
53510 + *     Pans the display to a given location.  Supports only y direction panning.
53511 + */
53512 +static int ubicom32fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
53513 +{
53514 +       struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53515 +       void *new_addr;
53516 +
53517 +       /*
53518 +        * Get the last y line that would be displayed.  Since we don't support YWRAP,
53519 +        * it must be less than our virtual y size.
53520 +        */
53521 +       u32 lasty = var->yoffset + var->yres;
53522 +       if (lasty > fbi->var.yres_virtual) {
53523 +               /*
53524 +                * We would fall off the end of our frame buffer if we panned here.
53525 +                */
53526 +               return -EINVAL;
53527 +       }
53528 +
53529 +       if (var->xoffset) {
53530 +               /*
53531 +                * We don't support panning in the x direction
53532 +                */
53533 +               return -EINVAL;
53534 +       }
53535 +
53536 +       /*
53537 +        * Everything looks sane, go ahead and pan
53538 +        *
53539 +        * We have to calculate a new address for the VDC to look at
53540 +        */
53541 +       new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
53542 +
53543 +       /*
53544 +        * Send down the command.  The buffer will switch at the next vertical blank
53545 +        */
53546 +       ubicom32fb_set_next_frame(ud, (void *)new_addr, 0);
53547 +
53548 +       return 0;
53549 +}
53550 +
53551 +/*
53552 + * ubicom32fb_setcolreg
53553 + *     Sets a color in our virtual palette
53554 + */
53555 +static int ubicom32fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
53556 +{
53557 +       u32 *palette = fbi->pseudo_palette;
53558 +
53559 +       if (regno >= PALETTE_ENTRIES_NO) {
53560 +               return -EINVAL;
53561 +       }
53562 +
53563 +       /*
53564 +        * We only use 8 bits from each color
53565 +        */
53566 +       red >>= 8;
53567 +       green >>= 8;
53568 +       blue >>= 8;
53569 +
53570 +       /*
53571 +        * Convert any grayscale values
53572 +        */
53573 +       if (fbi->var.grayscale) {
53574 +               u16 gray = red + green + blue;
53575 +               gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
53576 +               gray >>= 2;
53577 +               if (gray > 255) {
53578 +                       gray = 255;
53579 +               }
53580 +               red = gray;
53581 +               blue = gray;
53582 +               green = gray;
53583 +       }
53584 +
53585 +       palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
53586 +                        (blue << fbi->var.blue.offset);
53587 +
53588 +       return 0;
53589 +}
53590 +
53591 +/*
53592 + * ubicom32fb_mmap
53593 + */
53594 +static int ubicom32fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
53595 +{
53596 +       struct ubicom32fb_drvdata *drvdata = (struct ubicom32fb_drvdata *)info->par;
53597 +
53598 +       vma->vm_start = (unsigned long)(drvdata->fb_aligned);
53599 +
53600 +       vma->vm_end = vma->vm_start + info->fix.smem_len;
53601 +
53602 +       /* For those who don't understand how mmap works, go read
53603 +        *   Documentation/nommu-mmap.txt.
53604 +        * For those that do, you will know that the VM_MAYSHARE flag
53605 +        * must be set in the vma->vm_flags structure on noMMU
53606 +        *   Other flags can be set, and are documented in
53607 +        *   include/linux/mm.h
53608 +        */
53609 +
53610 +       vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
53611 +
53612 +       return 0;
53613 +}
53614 +
53615 +/*
53616 + * ubicom32fb_blank
53617 + */
53618 +static int ubicom32fb_blank(int blank_mode, struct fb_info *fbi)
53619 +{
53620 +       return 0;
53621 +#if 0
53622 +       struct ubicom32fb_drvdata *drvdata = to_ubicom32fb_drvdata(fbi);
53623 +
53624 +       switch (blank_mode) {
53625 +       case FB_BLANK_UNBLANK:
53626 +               /* turn on panel */
53627 +               ubicom32fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
53628 +               break;
53629 +
53630 +       case FB_BLANK_NORMAL:
53631 +       case FB_BLANK_VSYNC_SUSPEND:
53632 +       case FB_BLANK_HSYNC_SUSPEND:
53633 +       case FB_BLANK_POWERDOWN:
53634 +               /* turn off panel */
53635 +               ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53636 +       default:
53637 +               break;
53638 +
53639 +       }
53640 +       return 0; /* success */
53641 +#endif
53642 +}
53643 +
53644 +static struct fb_ops ubicom32fb_ops =
53645 +{
53646 +       .owner                  = THIS_MODULE,
53647 +       .fb_pan_display         = ubicom32fb_pan_display,
53648 +       .fb_setcolreg           = ubicom32fb_setcolreg,
53649 +       .fb_blank               = ubicom32fb_blank,
53650 +       .fb_mmap                = ubicom32fb_mmap,
53651 +       .fb_ioctl               = ubicom32fb_ioctl,
53652 +       .fb_fillrect            = cfb_fillrect,
53653 +       .fb_copyarea            = cfb_copyarea,
53654 +       .fb_imageblit           = cfb_imageblit,
53655 +};
53656 +
53657 +/*
53658 + * ubicom32fb_release
53659 + */
53660 +static int ubicom32fb_release(struct device *dev)
53661 +{
53662 +       struct ubicom32fb_drvdata *ud = dev_get_drvdata(dev);
53663 +
53664 +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
53665 +       //ubicom32fb_blank(VESA_POWERDOWN, &drvdata->info);
53666 +#endif
53667 +
53668 +       unregister_framebuffer(ud->fbinfo);
53669 +
53670 +       if (ud->cmap_alloc) {
53671 +               fb_dealloc_cmap(&ud->fbinfo->cmap);
53672 +       }
53673 +
53674 +       if (ud->fb) {
53675 +               kfree(ud->fb);
53676 +       }
53677 +
53678 +       if (ud->rx_int != -1) {
53679 +               free_irq(ud->rx_int, ud);
53680 +       }
53681 +
53682 +       /*
53683 +        * Turn off the display
53684 +        */
53685 +       //ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53686 +       //iounmap(drvdata->regs);
53687 +
53688 +       framebuffer_release(ud->fbinfo);
53689 +       dev_set_drvdata(dev, NULL);
53690 +
53691 +       return 0;
53692 +}
53693 +
53694 +/*
53695 + * ubicom32fb_platform_probe
53696 + */
53697 +static int __init ubicom32fb_platform_probe(struct platform_device *pdev)
53698 +{
53699 +       struct ubicom32fb_drvdata *ud;
53700 +       struct resource *irq_resource_rx;
53701 +       struct resource *irq_resource_tx;
53702 +       struct resource *mem_resource;
53703 +       struct fb_info *fbinfo;
53704 +       int rc;
53705 +       size_t fbsize;
53706 +       struct device *dev = &pdev->dev;
53707 +       int offset;
53708 +       struct vdc_tio_vp_regs *regs;
53709 +
53710 +       /*
53711 +        * Get our resources
53712 +        */
53713 +       irq_resource_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
53714 +       if (!irq_resource_tx) {
53715 +               dev_err(dev, "No tx IRQ resource assigned\n");
53716 +               return -ENODEV;
53717 +       }
53718 +
53719 +       irq_resource_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
53720 +       if (!irq_resource_rx) {
53721 +               dev_err(dev, "No rx IRQ resource assigned\n");
53722 +               return -ENODEV;
53723 +       }
53724 +
53725 +       mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
53726 +       if (!mem_resource || !mem_resource->start) {
53727 +               dev_err(dev, "No mem resource assigned\n");
53728 +               return -ENODEV;
53729 +       }
53730 +       regs = (struct vdc_tio_vp_regs *)mem_resource->start;
53731 +       if (regs->version != VDCTIO_VP_VERSION) {
53732 +               dev_err(dev, "VDCTIO is not compatible with this driver tio:%x drv:%x\n",
53733 +                       regs->version, VDCTIO_VP_VERSION);
53734 +               return -ENODEV;
53735 +       }
53736 +
53737 +       /*
53738 +        * This is the minimum VRAM size
53739 +        */
53740 +       fbsize = regs->xres * regs->yres * (regs->bpp / 8);
53741 +       if (!vram_size) {
53742 +               vram_size = (fbsize + 1023) / 1024;
53743 +       } else {
53744 +               if (fbsize > (vram_size * 1024)) {
53745 +                       dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
53746 +                       return -ENOMEM; // should be ebadparam?
53747 +               }
53748 +       }
53749 +
53750 +       /*
53751 +        * Allocate the framebuffer instance + our private data
53752 +        */
53753 +       fbinfo = framebuffer_alloc(sizeof(struct ubicom32fb_drvdata), &pdev->dev);
53754 +       if (!fbinfo) {
53755 +               dev_err(dev, "Not enough memory to allocate instance.\n");
53756 +               return -ENOMEM;
53757 +       }
53758 +
53759 +       /*
53760 +        * Fill in our private data.
53761 +        */
53762 +       ud = (struct ubicom32fb_drvdata *)fbinfo->par;
53763 +       ud->fbinfo = fbinfo;
53764 +       ud->regs = (struct vdc_tio_vp_regs *)(mem_resource->start);
53765 +       dev_set_drvdata(dev, ud);
53766 +
53767 +       ud->vp_int = irq_resource_tx->start;
53768 +
53769 +       /*
53770 +        * If we were provided an rx_irq then we need to init the appropriate
53771 +        * queues, locks, and functions.
53772 +        */
53773 +       ud->rx_int = -1;
53774 +       if (irq_resource_rx->start != DEVTREE_IRQ_NONE) {
53775 +               init_waitqueue_head(&ud->waitq);
53776 +               mutex_init(&ud->lock);
53777 +               if (request_irq(ud->rx_int, ubicom32fb_interrupt, IRQF_SHARED, "ubicom32fb_rx", ud)) {
53778 +                       dev_err(dev, "Couldn't request rx IRQ\n");
53779 +                       rc = -ENOMEM;
53780 +                       goto fail;
53781 +               }
53782 +               ud->rx_int = irq_resource_rx->start;
53783 +       }
53784 +
53785 +       /*
53786 +        * Allocate and align the requested amount of VRAM
53787 +        */
53788 +       ud->total_vram_size = (vram_size * 1024) + regs->fb_align;
53789 +       ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
53790 +       if (ud->fb == NULL) {
53791 +               dev_err(dev, "Couldn't allocate VRAM\n");
53792 +               rc = -ENOMEM;
53793 +               goto fail;
53794 +       }
53795 +
53796 +       offset = (u32_t)ud->fb & (regs->fb_align - 1);
53797 +       if (!offset) {
53798 +               ud->fb_aligned = ud->fb;
53799 +       } else {
53800 +               offset = regs->fb_align - offset;
53801 +               ud->fb_aligned = ud->fb + offset;
53802 +       }
53803 +
53804 +       /*
53805 +        * Clear the entire frame buffer
53806 +        */
53807 +       if (!init_value) {
53808 +               memset(ud->fb_aligned, 0, vram_size * 1024);
53809 +       } else {
53810 +               unsigned short *p = ud->fb_aligned;
53811 +               int i;
53812 +               for (i = 0; i < ((vram_size * 1024) / sizeof(u16_t)); i++) {
53813 +                       *p++ = init_value;
53814 +               }
53815 +       }
53816 +
53817 +       /*
53818 +        * Fill in the fb_var_screeninfo structure
53819 +        */
53820 +       memset(&ubicom32fb_var, 0, sizeof(ubicom32fb_var));
53821 +       ubicom32fb_var.bits_per_pixel = regs->bpp;
53822 +       ubicom32fb_var.red.offset = regs->rshift;
53823 +       ubicom32fb_var.green.offset = regs->gshift;
53824 +       ubicom32fb_var.blue.offset = regs->bshift;
53825 +       ubicom32fb_var.red.length = regs->rbits;
53826 +       ubicom32fb_var.green.length = regs->gbits;
53827 +       ubicom32fb_var.blue.length = regs->bbits;
53828 +       ubicom32fb_var.activate = FB_ACTIVATE_NOW;
53829 +
53830 +#if 0
53831 +       /*
53832 +        * Turn on the display
53833 +        */
53834 +       ud->reg_ctrl_default = REG_CTRL_ENABLE;
53835 +       if (regs->rotate_screen)
53836 +               ud->reg_ctrl_default |= REG_CTRL_ROTATE;
53837 +       ubicom32fb_out_be32(ud, REG_CTRL, ud->reg_ctrl_default);
53838 +#endif
53839 +
53840 +       /*
53841 +        * Fill in the fb_info structure
53842 +        */
53843 +       ud->fbinfo->device = dev;
53844 +       ud->fbinfo->screen_base = (void *)ud->fb_aligned;
53845 +       ud->fbinfo->fbops = &ubicom32fb_ops;
53846 +       ud->fbinfo->fix = ubicom32fb_fix;
53847 +       ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
53848 +       ud->fbinfo->fix.smem_len = vram_size * 1024;
53849 +       ud->fbinfo->fix.line_length = regs->xres * (regs->bpp / 8);
53850 +       ud->fbinfo->fix.mmio_start = (u32)regs;
53851 +       ud->fbinfo->fix.mmio_len = sizeof(struct vdc_tio_vp_regs);
53852 +
53853 +       /*
53854 +        * We support panning in the y direction only
53855 +        */
53856 +       ud->fbinfo->fix.xpanstep = 0;
53857 +       ud->fbinfo->fix.ypanstep = 1;
53858 +
53859 +       ud->fbinfo->pseudo_palette = ud->pseudo_palette;
53860 +       ud->fbinfo->flags = FBINFO_DEFAULT;
53861 +       ud->fbinfo->var = ubicom32fb_var;
53862 +       ud->fbinfo->var.xres = regs->xres;
53863 +       ud->fbinfo->var.yres = regs->yres;
53864 +
53865 +       /*
53866 +        * We cannot pan in the X direction, so xres_virtual is regs->xres
53867 +        * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
53868 +        */
53869 +       ud->fbinfo->var.xres_virtual = regs->xres;
53870 +       ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
53871 +
53872 +       //ud->fbinfo->var.height = regs->height_mm;
53873 +       //ud->fbinfo->var.width = regs->width_mm;
53874 +
53875 +       /*
53876 +        * Allocate a color map
53877 +        */
53878 +       rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
53879 +       if (rc) {
53880 +               dev_err(dev, "Fail to allocate colormap (%d entries)\n",
53881 +                       PALETTE_ENTRIES_NO);
53882 +               goto fail;
53883 +       }
53884 +       ud->cmap_alloc = true;
53885 +
53886 +       /*
53887 +        * Register new frame buffer
53888 +        */
53889 +       rc = register_framebuffer(ud->fbinfo);
53890 +       if (rc) {
53891 +               dev_err(dev, "Could not register frame buffer\n");
53892 +               goto fail;
53893 +       }
53894 +
53895 +       /*
53896 +        * Start up the VDC
53897 +        */
53898 +       ud->regs->next_frame = ud->fb;
53899 +       ubicom32fb_send_command(ud, VDCTIO_COMMAND_START, 0);
53900 +
53901 +       /*
53902 +        * Tell the log we are here
53903 +        */
53904 +       dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u), regs=%p irqtx=%u irqrx=%u\n",
53905 +               ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
53906 +               ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual, ud->regs,
53907 +               irq_resource_tx->start, irq_resource_rx->start);
53908 +
53909 +       /*
53910 +        * Success
53911 +        */
53912 +       return 0;
53913 +
53914 +fail:
53915 +       ubicom32fb_release(dev);
53916 +       return rc;
53917 +}
53918 +
53919 +/*
53920 + * ubicom32fb_platform_remove
53921 + */
53922 +static int ubicom32fb_platform_remove(struct platform_device *pdev)
53923 +{
53924 +       dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
53925 +       return ubicom32fb_release(&pdev->dev);
53926 +}
53927 +
53928 +static struct platform_driver ubicom32fb_platform_driver = {
53929 +       .probe          = ubicom32fb_platform_probe,
53930 +       .remove         = ubicom32fb_platform_remove,
53931 +       .driver = {
53932 +               .name = DRIVER_NAME,
53933 +               .owner = THIS_MODULE,
53934 +       },
53935 +};
53936 +
53937 +#ifndef MODULE
53938 +/*
53939 + * ubicom32fb_setup
53940 + *     Process kernel boot options
53941 + */
53942 +static int __init ubicom32fb_setup(char *options)
53943 +{
53944 +       char *this_opt;
53945 +
53946 +       if (!options || !*options) {
53947 +               return 0;
53948 +       }
53949 +
53950 +       while ((this_opt = strsep(&options, ",")) != NULL) {
53951 +               if (!*this_opt) {
53952 +                       continue;
53953 +               }
53954 +
53955 +               if (!strncmp(this_opt, "init_value=", 10)) {
53956 +                       init_value = simple_strtoul(this_opt + 11, NULL, 0);
53957 +                       continue;
53958 +               }
53959 +
53960 +               if (!strncmp(this_opt, "vram_size=", 10)) {
53961 +                       vram_size = simple_strtoul(this_opt + 10, NULL, 0);
53962 +                       continue;
53963 +               }
53964 +       }
53965 +       return 0;
53966 +}
53967 +#endif /* MODULE */
53968 +
53969 +/*
53970 + * ubicom32fb_init
53971 + */
53972 +static int __devinit ubicom32fb_init(void)
53973 +{
53974 +#ifndef MODULE
53975 +       /*
53976 +        * Get kernel boot options (in 'video=ubicom32fb:<options>')
53977 +        */
53978 +       char *option = NULL;
53979 +
53980 +       if (fb_get_options(DRIVER_NAME, &option)) {
53981 +               return -ENODEV;
53982 +       }
53983 +       ubicom32fb_setup(option);
53984 +#endif /* MODULE */
53985 +
53986 +       return platform_driver_register(&ubicom32fb_platform_driver);
53987 +}
53988 +module_init(ubicom32fb_init);
53989 +
53990 +/*
53991 + * ubicom32fb_exit
53992 + */
53993 +static void __exit ubicom32fb_exit(void)
53994 +{
53995 +       platform_driver_unregister(&ubicom32fb_platform_driver);
53996 +}
53997 +module_exit(ubicom32fb_exit);
53998 +
53999 +MODULE_LICENSE("GPL");
54000 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
54001 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
54002 diff -ruN linux-2.6.30.10/drivers/video/ubicom32plio80.c linux-2.6.30.10-ubi/drivers/video/ubicom32plio80.c
54003 --- linux-2.6.30.10/drivers/video/ubicom32plio80.c      1970-01-01 02:00:00.000000000 +0200
54004 +++ linux-2.6.30.10-ubi/drivers/video/ubicom32plio80.c  2009-12-11 11:45:21.000000000 +0200
54005 @@ -0,0 +1,780 @@
54006 +/*
54007 + * drivers/video/ubicom32plio80.c
54008 + *     Ubicom32 80 bus PLIO buffer driver
54009 + *
54010 + * (C) Copyright 2009, Ubicom, Inc.
54011 + *
54012 + * This file is part of the Ubicom32 Linux Kernel Port.
54013 + *
54014 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
54015 + * it and/or modify it under the terms of the GNU General Public License
54016 + * as published by the Free Software Foundation, either version 2 of the
54017 + * License, or (at your option) any later version.
54018 + *
54019 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
54020 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
54021 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
54022 + * the GNU General Public License for more details.
54023 + *
54024 + * You should have received a copy of the GNU General Public License
54025 + * along with the Ubicom32 Linux Kernel Port.  If not,
54026 + * see <http://www.gnu.org/licenses/>.
54027 + */
54028 +
54029 +/*
54030 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
54031 + * Geert Uytterhoeven.
54032 + */
54033 +
54034 +#include <linux/device.h>
54035 +#include <linux/module.h>
54036 +#include <linux/kernel.h>
54037 +#include <linux/version.h>
54038 +#include <linux/errno.h>
54039 +#include <linux/string.h>
54040 +#include <linux/mm.h>
54041 +#include <linux/fb.h>
54042 +#include <linux/init.h>
54043 +#include <linux/interrupt.h>
54044 +#include <linux/dma-mapping.h>
54045 +#include <linux/platform_device.h>
54046 +#include <linux/device.h>
54047 +#include <linux/uaccess.h>
54048 +#include <asm/plio.h>
54049 +
54050 +#define DRIVER_NAME            "ubicom32plio80"
54051 +#define DRIVER_DESCRIPTION     "Ubicom32 80 bus PLIO frame buffer driver"
54052 +
54053 +#define PALETTE_ENTRIES_NO     16
54054 +
54055 +/*
54056 + * Option variables
54057 + *
54058 + * vram_size:  VRAM size in kilobytes, subject to alignment
54059 + */
54060 +static int vram_size = 0;
54061 +module_param(vram_size, int, 0);
54062 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
54063 +
54064 +static int xres = 240;
54065 +module_param(xres, int, 0);
54066 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
54067 +
54068 +static int yres = 320;
54069 +module_param(yres, int, 0);
54070 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
54071 +
54072 +static int bgr = 0;
54073 +module_param(bgr, int, 0);
54074 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
54075 +
54076 +#define BITS_PER_PIXEL 16
54077 +
54078 +/*
54079 + * Buffer alignment, must not be 0
54080 + */
54081 +#define UBICOM32PLIO80_ALIGNMENT 4
54082 +
54083 +/*
54084 + * PLIO FSM
54085 + *     16-bit data bus on port I
54086 + *     CS on EXTCTL[6]
54087 + *     WR on EXTCTL[4]
54088 + */
54089 +static const plio_fctl_t plio_fctl = {
54090 +       .fctl0 = {
54091 +               .ptif_port_mode = PLIO_PORT_MODE_DI,
54092 +               .ptif_portd_cfg = 0,
54093 +               .ptif_porti_cfg = 3,
54094 +               .edif_ds = 6,
54095 +               .edif_cmp_mode = 1,
54096 +               .ecif_extclk_ena = 0, // enable clock output on PD7 table 2.65/p111 says extctl[0]?
54097 +               .icif_clk_src_sel = PLIO_CLK_IO,
54098 +       },
54099 +       .fctl2 = {
54100 +               .icif_eclk_div = 10,
54101 +               .icif_iclk_div = 10,
54102 +       },
54103 +
54104 +       };
54105 +
54106 +       static const plio_config_t plio_config = {
54107 +       .pfsm = {
54108 +               /*
54109 +                * Table 12.63
54110 +                */
54111 +               .grpsel[0] = {1,1,1,1,1,1,1,1,1,1},
54112 +
54113 +               /*
54114 +               * Table 12.66 Counter load value
54115 +               */
54116 +               .cs_lut[0] = {0,0,0,0,0,0,0,0},
54117 +
54118 +               /*
54119 +                * Table 2.75 PLIO PFSM Configuration Registers
54120 +                */
54121 +               //                      3     2     1     0
54122 +               .extctl_o_lut[0] = {0x3f, 0x2f, 0x3f, 0x3f},
54123 +               //                      7     6     5     4
54124 +               .extctl_o_lut[1] = {0x3f, 0x3f, 0x3f, 0x2f},
54125 +       },
54126 +       .edif = {
54127 +               .odr_oe = 0xffff,
54128 +       },
54129 +       .ecif = {
54130 +               .output_ena = (1 << 6) | (1 << 4),
54131 +       },
54132 +};
54133 +
54134 +static const u32_t ubicom32plio80_plio_fsm[] = {
54135 +       // 0-F
54136 +       0x00070007, 0x00070007,
54137 +       0x00070007, 0x00070007,
54138 +       0x00070007, 0x00070007,
54139 +       0x00070007, 0x00070007,
54140 +
54141 +       0x16260806, 0x16260806,
54142 +       0x16260806, 0x16260806,
54143 +       0x16260806, 0x16260806,
54144 +       0x16260806, 0x16260806,
54145 +
54146 +       // 10 - 1f
54147 +       0x22061806, 0x22061806,
54148 +       0x22061806, 0x22061806,
54149 +       0x22061806, 0x22061806,
54150 +       0x22061806, 0x22061806,
54151 +
54152 +       0x22061806, 0x22061806,
54153 +       0x22061806, 0x22061806,
54154 +       0x22061806, 0x22061806,
54155 +       0x22061806, 0x22061806,
54156 +
54157 +       // 20 - 2f
54158 +       0x00070806, 0x00070806,
54159 +       0x00070806, 0x00070806,
54160 +       0x00070806, 0x00070806,
54161 +       0x00070806, 0x00070806,
54162 +
54163 +       0x00070806, 0x00070806,
54164 +       0x00070806, 0x00070806,
54165 +       0x00070806, 0x00070806,
54166 +       0x00070806, 0x00070806,
54167 +};
54168 +
54169 +/*
54170 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
54171 + */
54172 +static struct fb_fix_screeninfo ubicom32plio80_fix = {
54173 +       .id =           "Ubicom32",
54174 +       .type =         FB_TYPE_PACKED_PIXELS,
54175 +       .visual =       FB_VISUAL_TRUECOLOR,
54176 +       .accel =        FB_ACCEL_UBICOM32_PLIO80,
54177 +};
54178 +
54179 +/*
54180 + * Filled in at probe time when we find out what the hardware supports
54181 + */
54182 +static struct fb_var_screeninfo ubicom32plio80_var;
54183 +
54184 +/*
54185 + * Private data structure
54186 + */
54187 +struct ubicom32plio80_drvdata {
54188 +       struct fb_info                  *fbinfo;
54189 +       bool                            cmap_alloc;
54190 +
54191 +       /*
54192 +        * The address of the framebuffer in memory
54193 +        */
54194 +       void                            *fb;
54195 +       void                            *fb_aligned;
54196 +
54197 +       /*
54198 +        * Total size of vram including alignment allowance
54199 +        */
54200 +       u32                             total_vram_size;
54201 +
54202 +       /*
54203 +        * Fake palette of 16 colors
54204 +        */
54205 +       u32                             pseudo_palette[PALETTE_ENTRIES_NO];
54206 +
54207 +       int                             irq_req;
54208 +
54209 +       /*
54210 +        * Current pointer and bytes left to transfer with the PLIO
54211 +        */
54212 +       void                            *xfer_ptr;
54213 +       u32                             bytes_to_xfer;
54214 +       u32                             busy;
54215 +};
54216 +
54217 +static struct platform_device *ubicom32plio80_platform_device;
54218 +
54219 +/*
54220 + * ubicom32plio80_isr
54221 + */
54222 +static int ubicom32plio80_isr(int irq, void *appdata)
54223 +{
54224 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)appdata;
54225 +
54226 +       if (!ud->bytes_to_xfer) {
54227 +               ubicom32_disable_interrupt(TX_FIFO_INT(PLIO_PORT));
54228 +               PLIO_NBR->intmask.txfifo_wm = 0;
54229 +               ud->busy = 0;
54230 +               return IRQ_HANDLED;
54231 +       }
54232 +
54233 +       asm volatile (
54234 +               ".rept 8                                \n\t"
54235 +               "move.4 (%[fifo]), (%[data])4++         \n\t"
54236 +               ".endr                                  \n\t"
54237 +               : [data] "+a" (ud->xfer_ptr)
54238 +               : [fifo] "a" (&PLIO_NBR->tx_lo)
54239 +       );
54240 +
54241 +       ud->bytes_to_xfer -= 32;
54242 +
54243 +       return IRQ_HANDLED;
54244 +}
54245 +
54246 +/*
54247 + * ubicom32plio80_update
54248 + */
54249 +static void ubicom32plio80_update(struct ubicom32plio80_drvdata *ud, u32 *fb)
54250 +{
54251 +       struct ubicom32_io_port *ri = (struct ubicom32_io_port *)RI;
54252 +       struct ubicom32_io_port *rd = (struct ubicom32_io_port *)RD;
54253 +
54254 +       ud->xfer_ptr = fb;
54255 +       ud->bytes_to_xfer = (xres * yres * 2) - 64;
54256 +       ud->busy = 1;
54257 +
54258 +       ri->gpio_mask = 0;
54259 +       rd->gpio_mask &= ~((1 << 4) | (1 << 2));
54260 +
54261 +       *(u32 *)(&PLIO_NBR->intclr) = ~0;
54262 +       PLIO_NBR->intmask.txfifo_wm = 1;
54263 +       PLIO_NBR->fifo_wm.tx = 8;
54264 +       ubicom32_enable_interrupt(TX_FIFO_INT(PLIO_PORT));
54265 +
54266 +       asm volatile (
54267 +               ".rept 16                               \n\t"
54268 +               "move.4 (%[fifo]), (%[data])4++         \n\t"
54269 +               ".endr                                  \n\t"
54270 +               : [data] "+a" (ud->xfer_ptr)
54271 +               : [fifo] "a" (&PLIO_NBR->tx_lo)
54272 +       );
54273 +}
54274 +
54275 +/*
54276 + * ubicom32plio80_pan_display
54277 + *     Pans the display to a given location.  Supports only y direction panning.
54278 + */
54279 +static int ubicom32plio80_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
54280 +{
54281 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)fbi->par;
54282 +       void *new_addr;
54283 +
54284 +       /*
54285 +        * Get the last y line that would be displayed.  Since we don't support YWRAP,
54286 +        * it must be less than our virtual y size.
54287 +        */
54288 +       u32 lasty = var->yoffset + var->yres;
54289 +       if (lasty > fbi->var.yres_virtual) {
54290 +               /*
54291 +                * We would fall off the end of our frame buffer if we panned here.
54292 +                */
54293 +               return -EINVAL;
54294 +       }
54295 +
54296 +       if (var->xoffset) {
54297 +               /*
54298 +                * We don't support panning in the x direction
54299 +                */
54300 +               return -EINVAL;
54301 +       }
54302 +
54303 +       /*
54304 +        * Everything looks sane, go ahead and pan
54305 +        *
54306 +        * We have to calculate a new address for the VDC to look at
54307 +        */
54308 +       new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54309 +
54310 +       return 0;
54311 +}
54312 +
54313 +/*
54314 + * ubicom32plio80_setcolreg
54315 + *     Sets a color in our virtual palette
54316 + */
54317 +static int ubicom32plio80_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54318 +{
54319 +       u32 *palette = fbi->pseudo_palette;
54320 +
54321 +       if (regno >= PALETTE_ENTRIES_NO) {
54322 +               return -EINVAL;
54323 +       }
54324 +
54325 +       /*
54326 +        * We only use 8 bits from each color
54327 +        */
54328 +       red >>= 8;
54329 +       green >>= 8;
54330 +       blue >>= 8;
54331 +
54332 +       /*
54333 +        * Convert any grayscale values
54334 +        */
54335 +       if (fbi->var.grayscale) {
54336 +               u16 gray = red + green + blue;
54337 +               gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54338 +               gray >>= 2;
54339 +               if (gray > 255) {
54340 +                       gray = 255;
54341 +               }
54342 +               red = gray;
54343 +               blue = gray;
54344 +               green = gray;
54345 +       }
54346 +
54347 +       palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54348 +                        (blue << fbi->var.blue.offset);
54349 +
54350 +       return 0;
54351 +}
54352 +
54353 +/*
54354 + * ubicom32plio80_mmap
54355 + */
54356 +static int ubicom32plio80_mmap(struct fb_info *info, struct vm_area_struct *vma)
54357 +{
54358 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54359 +
54360 +       vma->vm_start = (unsigned long)(ud->fb_aligned);
54361 +
54362 +       vma->vm_end = vma->vm_start + info->fix.smem_len;
54363 +
54364 +       /* For those who don't understand how mmap works, go read
54365 +        *   Documentation/nommu-mmap.txt.
54366 +        * For those that do, you will know that the VM_MAYSHARE flag
54367 +        * must be set in the vma->vm_flags structure on noMMU
54368 +        *   Other flags can be set, and are documented in
54369 +        *   include/linux/mm.h
54370 +        */
54371 +
54372 +       vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
54373 +
54374 +       return 0;
54375 +}
54376 +
54377 +/*
54378 + * ubicom32plio80_check_var
54379 + *     Check the var, tweak it but don't change operational parameters.
54380 + */
54381 +static int ubicom32plio80_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
54382 +{
54383 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54384 +       u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
54385 +
54386 +       /*
54387 +        * See if we can handle this bpp
54388 +        */
54389 +       if (var->bits_per_pixel > BITS_PER_PIXEL) {
54390 +               return -EINVAL;
54391 +       }
54392 +       var->bits_per_pixel = BITS_PER_PIXEL;
54393 +
54394 +       /*
54395 +        * See if we have enough memory to handle this resolution
54396 +        */
54397 +       if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
54398 +               return -EINVAL;
54399 +       }
54400 +
54401 +       var->xres_virtual = var->xres;
54402 +       var->yres_virtual = ud->total_vram_size / line_size;
54403 +
54404 +       var->red.length = 5;
54405 +       var->green.length = 6;
54406 +       var->green.offset = 5;
54407 +       var->blue.length = 5;
54408 +       var->transp.offset = var->transp.length = 0;
54409 +
54410 +       if (bgr) {
54411 +               var->red.offset = 0;
54412 +               var->blue.offset = 11;
54413 +       } else {
54414 +               var->red.offset = 11;
54415 +               var->blue.offset = 0;
54416 +       }
54417 +
54418 +       var->nonstd = 0;
54419 +       var->height = -1;
54420 +       var->width = -1;
54421 +       var->vmode = FB_VMODE_NONINTERLACED;
54422 +       var->sync = 0;
54423 +
54424 +       return 0;
54425 +}
54426 +
54427 +/*
54428 + * ubicom32plio80_set_par
54429 + *     Set the video mode according to info->var
54430 + */
54431 +static int ubicom32plio80_set_par(struct fb_info *info)
54432 +{
54433 +       /*
54434 +        * Anything changed?
54435 +        */
54436 +       if ((xres == info->var.xres) && (yres == info->var.yres)) {
54437 +               return 0;
54438 +       }
54439 +
54440 +       /*
54441 +        * Implement changes
54442 +        */
54443 +       xres = info->var.xres;
54444 +       yres = info->var.yres;
54445 +       info->fix.visual = FB_VISUAL_TRUECOLOR;
54446 +       info->fix.xpanstep = 0;
54447 +       info->fix.ypanstep = 1;
54448 +       info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
54449 +
54450 +       return 0;
54451 +}
54452 +
54453 +/*
54454 + * ubicom32plio80_ops
54455 + *     List of supported operations
54456 + */
54457 +static struct fb_ops ubicom32plio80_ops =
54458 +{
54459 +       .owner                  = THIS_MODULE,
54460 +       .fb_pan_display         = ubicom32plio80_pan_display,
54461 +       .fb_setcolreg           = ubicom32plio80_setcolreg,
54462 +       .fb_mmap                = ubicom32plio80_mmap,
54463 +       .fb_check_var           = ubicom32plio80_check_var,
54464 +       .fb_set_par             = ubicom32plio80_set_par,
54465 +       .fb_fillrect            = cfb_fillrect,
54466 +       .fb_copyarea            = cfb_copyarea,
54467 +       .fb_imageblit           = cfb_imageblit,
54468 +};
54469 +
54470 +/*
54471 + * ubicom32plio80_release
54472 + */
54473 +static int ubicom32plio80_release(struct device *dev)
54474 +{
54475 +       struct ubicom32plio80_drvdata *ud = dev_get_drvdata(dev);
54476 +
54477 +       unregister_framebuffer(ud->fbinfo);
54478 +
54479 +       if (ud->irq_req) {
54480 +               free_irq(TX_FIFO_INT(PLIO_PORT), ud);
54481 +       }
54482 +       if (ud->cmap_alloc) {
54483 +               fb_dealloc_cmap(&ud->fbinfo->cmap);
54484 +       }
54485 +
54486 +       if (ud->fb) {
54487 +               kfree(ud->fb);
54488 +       }
54489 +
54490 +       framebuffer_release(ud->fbinfo);
54491 +       dev_set_drvdata(dev, NULL);
54492 +
54493 +       return 0;
54494 +}
54495 +
54496 +/*
54497 + * ubicom32plio80_platform_probe
54498 + */
54499 +static int __init ubicom32plio80_platform_probe(struct platform_device *pdev)
54500 +{
54501 +       struct ubicom32plio80_drvdata *ud;
54502 +       struct fb_info *fbinfo;
54503 +       int rc;
54504 +       size_t fbsize;
54505 +       struct device *dev = &pdev->dev;
54506 +       int offset;
54507 +
54508 +       /*
54509 +        * This is the minimum VRAM size
54510 +        */
54511 +       fbsize = xres * yres * 2;
54512 +       if (!vram_size) {
54513 +               vram_size = (fbsize + 1023) / 1024;
54514 +       } else {
54515 +               if (fbsize > (vram_size * 1024)) {
54516 +                       dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
54517 +                       return -ENOMEM; // should be ebadparam?
54518 +               }
54519 +       }
54520 +
54521 +       /*
54522 +        * Allocate the framebuffer instance + our private data
54523 +        */
54524 +       fbinfo = framebuffer_alloc(sizeof(struct ubicom32plio80_drvdata), &pdev->dev);
54525 +       if (!fbinfo) {
54526 +               dev_err(dev, "Not enough memory to allocate instance.\n");
54527 +               return -ENOMEM;
54528 +       }
54529 +
54530 +       /*
54531 +        * Fill in our private data.
54532 +        */
54533 +       ud = (struct ubicom32plio80_drvdata *)fbinfo->par;
54534 +       ud->fbinfo = fbinfo;
54535 +       dev_set_drvdata(dev, ud);
54536 +
54537 +       /*
54538 +        * Allocate and align the requested amount of VRAM
54539 +        */
54540 +       ud->total_vram_size = (vram_size * 1024) + UBICOM32PLIO80_ALIGNMENT;
54541 +       ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
54542 +       if (ud->fb == NULL) {
54543 +               dev_err(dev, "Couldn't allocate VRAM\n");
54544 +               rc = -ENOMEM;
54545 +               goto fail;
54546 +       }
54547 +
54548 +       offset = (u32_t)ud->fb & (UBICOM32PLIO80_ALIGNMENT - 1);
54549 +       if (!offset) {
54550 +               ud->fb_aligned = ud->fb;
54551 +       } else {
54552 +               offset =  UBICOM32PLIO80_ALIGNMENT - offset;
54553 +               ud->fb_aligned = ud->fb + offset;
54554 +       }
54555 +
54556 +       /*
54557 +        * Clear the entire frame buffer
54558 +        */
54559 +       memset(ud->fb_aligned, 0, vram_size * 1024);
54560 +
54561 +       /*
54562 +        * Fill in the fb_var_screeninfo structure
54563 +        */
54564 +       memset(&ubicom32plio80_var, 0, sizeof(ubicom32plio80_var));
54565 +       ubicom32plio80_var.bits_per_pixel = BITS_PER_PIXEL;
54566 +       ubicom32plio80_var.red.length = 5;
54567 +       ubicom32plio80_var.green.length = 6;
54568 +       ubicom32plio80_var.green.offset = 5;
54569 +       ubicom32plio80_var.blue.length = 5;
54570 +       ubicom32plio80_var.activate = FB_ACTIVATE_NOW;
54571 +
54572 +       if (bgr) {
54573 +               ubicom32plio80_var.red.offset = 0;
54574 +               ubicom32plio80_var.blue.offset = 11;
54575 +       } else {
54576 +               ubicom32plio80_var.red.offset = 11;
54577 +               ubicom32plio80_var.blue.offset = 0;
54578 +       }
54579 +
54580 +       /*
54581 +        * Fill in the fb_info structure
54582 +        */
54583 +       ud->fbinfo->device = dev;
54584 +       ud->fbinfo->screen_base = (void *)ud->fb_aligned;
54585 +       ud->fbinfo->fbops = &ubicom32plio80_ops;
54586 +       ud->fbinfo->fix = ubicom32plio80_fix;
54587 +       ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
54588 +       ud->fbinfo->fix.smem_len = vram_size * 1024;
54589 +       ud->fbinfo->fix.line_length = xres * 2;
54590 +       ud->fbinfo->fix.mmio_start = (u32)ud;
54591 +       ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32plio80_drvdata);
54592 +
54593 +       /*
54594 +        * We support panning in the y direction only
54595 +        */
54596 +       ud->fbinfo->fix.xpanstep = 0;
54597 +       ud->fbinfo->fix.ypanstep = 1;
54598 +
54599 +       ud->fbinfo->pseudo_palette = ud->pseudo_palette;
54600 +       ud->fbinfo->flags = FBINFO_DEFAULT;
54601 +       ud->fbinfo->var = ubicom32plio80_var;
54602 +       ud->fbinfo->var.xres = xres;
54603 +       ud->fbinfo->var.yres = yres;
54604 +
54605 +       /*
54606 +        * We cannot pan in the X direction, so xres_virtual is xres
54607 +        * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
54608 +        */
54609 +       ud->fbinfo->var.xres_virtual = xres;
54610 +       ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
54611 +
54612 +       /*
54613 +        * Allocate a color map
54614 +        */
54615 +       rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
54616 +       if (rc) {
54617 +               dev_err(dev, "Fail to allocate colormap (%d entries)\n",
54618 +                       PALETTE_ENTRIES_NO);
54619 +               goto fail;
54620 +       }
54621 +       ud->cmap_alloc = true;
54622 +
54623 +       /*
54624 +        * Register new frame buffer
54625 +        */
54626 +       rc = register_framebuffer(ud->fbinfo);
54627 +       if (rc) {
54628 +               dev_err(dev, "Could not register frame buffer\n");
54629 +               goto fail;
54630 +       }
54631 +
54632 +       /*
54633 +        * request the PLIO IRQ
54634 +        */
54635 +       rc = request_irq(TX_FIFO_INT(PLIO_PORT), ubicom32plio80_isr, IRQF_DISABLED, "ubicom32plio80", ud);
54636 +       if (rc) {
54637 +               dev_err(dev, "Could not request IRQ\n");
54638 +               goto fail;
54639 +       }
54640 +       ud->irq_req = 1;
54641 +
54642 +       /*
54643 +        * Clear any garbage out of the TX FIFOs (idif_txfifo_flush)
54644 +        *
54645 +        * cast through ubicom32_io_port to make sure the compiler does a word write
54646 +        */
54647 +       ((struct ubicom32_io_port *)PLIO_NBR)->int_set = (1 << 18);
54648 +
54649 +       /*
54650 +        * Start up the state machine
54651 +        */
54652 +       plio_init(&plio_fctl, &plio_config, (plio_sram_t *)ubicom32plio80_plio_fsm, sizeof(ubicom32plio80_plio_fsm));
54653 +       PLIO_NBR->fctl0.pfsm_cmd = 0;
54654 +
54655 +       ubicom32plio80_update(ud, ud->fb_aligned);
54656 +
54657 +       /*
54658 +        * Tell the log we are here
54659 +        */
54660 +       dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
54661 +               ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
54662 +               ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
54663 +
54664 +       /*
54665 +        * Success
54666 +        */
54667 +       return 0;
54668 +
54669 +fail:
54670 +       ubicom32plio80_release(dev);
54671 +       return rc;
54672 +}
54673 +
54674 +/*
54675 + * ubicom32plio80_platform_remove
54676 + */
54677 +static int ubicom32plio80_platform_remove(struct platform_device *pdev)
54678 +{
54679 +       dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
54680 +       return ubicom32plio80_release(&pdev->dev);
54681 +}
54682 +
54683 +static struct platform_driver ubicom32plio80_platform_driver = {
54684 +       .probe          = ubicom32plio80_platform_probe,
54685 +       .remove         = ubicom32plio80_platform_remove,
54686 +       .driver = {
54687 +               .name = DRIVER_NAME,
54688 +               .owner = THIS_MODULE,
54689 +       },
54690 +};
54691 +
54692 +#ifndef MODULE
54693 +/*
54694 + * ubicom32plio80_setup
54695 + *     Process kernel boot options
54696 + */
54697 +static int __init ubicom32plio80_setup(char *options)
54698 +{
54699 +       char *this_opt;
54700 +
54701 +       if (!options || !*options) {
54702 +               return 0;
54703 +       }
54704 +
54705 +       while ((this_opt = strsep(&options, ",")) != NULL) {
54706 +               if (!*this_opt) {
54707 +                       continue;
54708 +               }
54709 +
54710 +               if (!strncmp(this_opt, "vram_size=", 10)) {
54711 +                       vram_size = simple_strtoul(this_opt + 10, NULL, 0);
54712 +                       continue;
54713 +               }
54714 +
54715 +               if (!strncmp(this_opt, "bgr=", 4)) {
54716 +                       bgr = simple_strtoul(this_opt + 4, NULL, 0);
54717 +                       continue;
54718 +               }
54719 +
54720 +               if (!strncmp(this_opt, "xres=", 5)) {
54721 +                       xres = simple_strtoul(this_opt + 5, NULL, 0);
54722 +                       continue;
54723 +               }
54724 +
54725 +               if (!strncmp(this_opt, "yres=", 5)) {
54726 +                       yres = simple_strtoul(this_opt + 5, NULL, 0);
54727 +                       continue;
54728 +               }
54729 +       }
54730 +       return 0;
54731 +}
54732 +#endif /* MODULE */
54733 +
54734 +/*
54735 + * ubicom32plio80_init
54736 + */
54737 +static int __devinit ubicom32plio80_init(void)
54738 +{
54739 +       int ret;
54740 +
54741 +#ifndef MODULE
54742 +       /*
54743 +        * Get kernel boot options (in 'video=ubicom32plio80:<options>')
54744 +        */
54745 +       char *option = NULL;
54746 +
54747 +       if (fb_get_options(DRIVER_NAME, &option)) {
54748 +               return -ENODEV;
54749 +       }
54750 +       ubicom32plio80_setup(option);
54751 +#endif /* MODULE */
54752 +
54753 +       ret = platform_driver_register(&ubicom32plio80_platform_driver);
54754 +
54755 +       if (!ret) {
54756 +               ubicom32plio80_platform_device = platform_device_alloc(DRIVER_NAME, 0);
54757 +
54758 +               if (ubicom32plio80_platform_device)
54759 +                       ret = platform_device_add(ubicom32plio80_platform_device);
54760 +               else
54761 +                       ret = -ENOMEM;
54762 +
54763 +               if (ret) {
54764 +                       platform_device_put(ubicom32plio80_platform_device);
54765 +                       platform_driver_unregister(&ubicom32plio80_platform_driver);
54766 +               }
54767 +       }
54768 +
54769 +       return ret;
54770 +}
54771 +module_init(ubicom32plio80_init);
54772 +
54773 +/*
54774 + * ubicom32plio80_exit
54775 + */
54776 +static void __exit ubicom32plio80_exit(void)
54777 +{
54778 +       platform_device_unregister(ubicom32plio80_platform_device);
54779 +       platform_driver_unregister(&ubicom32plio80_platform_driver);
54780 +}
54781 +module_exit(ubicom32plio80_exit);
54782 +
54783 +MODULE_LICENSE("GPL");
54784 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
54785 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
54786 diff -ruN linux-2.6.30.10/drivers/video/ubicom32vfb.c linux-2.6.30.10-ubi/drivers/video/ubicom32vfb.c
54787 --- linux-2.6.30.10/drivers/video/ubicom32vfb.c 1970-01-01 02:00:00.000000000 +0200
54788 +++ linux-2.6.30.10-ubi/drivers/video/ubicom32vfb.c     2009-12-11 11:45:21.000000000 +0200
54789 @@ -0,0 +1,603 @@
54790 +/*
54791 + * drivers/video/ubicom32vfb.c
54792 + *     Ubicom32 virtual frame buffer driver
54793 + *
54794 + * (C) Copyright 2009, Ubicom, Inc.
54795 + *
54796 + * This file is part of the Ubicom32 Linux Kernel Port.
54797 + *
54798 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
54799 + * it and/or modify it under the terms of the GNU General Public License
54800 + * as published by the Free Software Foundation, either version 2 of the
54801 + * License, or (at your option) any later version.
54802 + *
54803 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
54804 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
54805 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
54806 + * the GNU General Public License for more details.
54807 + *
54808 + * You should have received a copy of the GNU General Public License
54809 + * along with the Ubicom32 Linux Kernel Port.  If not,
54810 + * see <http://www.gnu.org/licenses/>.
54811 + */
54812 +
54813 +/*
54814 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
54815 + * Geert Uytterhoeven.
54816 + */
54817 +
54818 +#include <linux/device.h>
54819 +#include <linux/module.h>
54820 +#include <linux/kernel.h>
54821 +#include <linux/version.h>
54822 +#include <linux/errno.h>
54823 +#include <linux/string.h>
54824 +#include <linux/mm.h>
54825 +#include <linux/fb.h>
54826 +#include <linux/init.h>
54827 +#include <linux/dma-mapping.h>
54828 +#include <linux/platform_device.h>
54829 +#include <linux/device.h>
54830 +#include <linux/uaccess.h>
54831 +
54832 +#define DRIVER_NAME            "ubicom32vfb"
54833 +#define DRIVER_DESCRIPTION     "Ubicom32 virtual frame buffer driver"
54834 +
54835 +#define PALETTE_ENTRIES_NO     16
54836 +
54837 +/*
54838 + * Option variables
54839 + *
54840 + * vram_size:  VRAM size in kilobytes, subject to alignment
54841 + */
54842 +static int vram_size = 0;
54843 +module_param(vram_size, int, 0);
54844 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
54845 +
54846 +static int xres = 320;
54847 +module_param(xres, int, 0);
54848 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
54849 +
54850 +static int yres = 240;
54851 +module_param(yres, int, 0);
54852 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
54853 +
54854 +static int bgr = 0;
54855 +module_param(bgr, int, 0);
54856 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
54857 +
54858 +#define BITS_PER_PIXEL 16
54859 +
54860 +/*
54861 + * Buffer alignment, must not be 0
54862 + */
54863 +#define UBICOM32VFB_ALIGNMENT 4
54864 +
54865 +/*
54866 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
54867 + */
54868 +static struct fb_fix_screeninfo ubicom32vfb_fix = {
54869 +       .id =           "Ubicom32",
54870 +       .type =         FB_TYPE_PACKED_PIXELS,
54871 +       .visual =       FB_VISUAL_TRUECOLOR,
54872 +       .accel =        FB_ACCEL_UBICOM32_VFB,
54873 +};
54874 +
54875 +/*
54876 + * Filled in at probe time when we find out what the hardware supports
54877 + */
54878 +static struct fb_var_screeninfo ubicom32vfb_var;
54879 +
54880 +/*
54881 + * Private data structure
54882 + */
54883 +struct ubicom32vfb_drvdata {
54884 +       struct fb_info                  *fbinfo;
54885 +       bool                            cmap_alloc;
54886 +
54887 +       /*
54888 +        * The address of the framebuffer in memory
54889 +        */
54890 +       void                            *fb;
54891 +       void                            *fb_aligned;
54892 +
54893 +       /*
54894 +        * Total size of vram including alignment allowance
54895 +        */
54896 +       u32                             total_vram_size;
54897 +
54898 +       /*
54899 +        * Fake palette of 16 colors
54900 +        */
54901 +       u32                             pseudo_palette[PALETTE_ENTRIES_NO];
54902 +};
54903 +
54904 +static struct platform_device *ubicom32vfb_platform_device;
54905 +
54906 +/*
54907 + * ubicom32vfb_pan_display
54908 + *     Pans the display to a given location.  Supports only y direction panning.
54909 + */
54910 +static int ubicom32vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
54911 +{
54912 +       struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)fbi->par;
54913 +       void *new_addr;
54914 +
54915 +       /*
54916 +        * Get the last y line that would be displayed.  Since we don't support YWRAP,
54917 +        * it must be less than our virtual y size.
54918 +        */
54919 +       u32 lasty = var->yoffset + var->yres;
54920 +       if (lasty > fbi->var.yres_virtual) {
54921 +               /*
54922 +                * We would fall off the end of our frame buffer if we panned here.
54923 +                */
54924 +               return -EINVAL;
54925 +       }
54926 +
54927 +       if (var->xoffset) {
54928 +               /*
54929 +                * We don't support panning in the x direction
54930 +                */
54931 +               return -EINVAL;
54932 +       }
54933 +
54934 +       /*
54935 +        * Everything looks sane, go ahead and pan
54936 +        *
54937 +        * We have to calculate a new address for the VDC to look at
54938 +        */
54939 +       new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54940 +
54941 +       return 0;
54942 +}
54943 +
54944 +/*
54945 + * ubicom32vfb_setcolreg
54946 + *     Sets a color in our virtual palette
54947 + */
54948 +static int ubicom32vfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54949 +{
54950 +       u32 *palette = fbi->pseudo_palette;
54951 +
54952 +       if (regno >= PALETTE_ENTRIES_NO) {
54953 +               return -EINVAL;
54954 +       }
54955 +
54956 +       /*
54957 +        * We only use 8 bits from each color
54958 +        */
54959 +       red >>= 8;
54960 +       green >>= 8;
54961 +       blue >>= 8;
54962 +
54963 +       /*
54964 +        * Convert any grayscale values
54965 +        */
54966 +       if (fbi->var.grayscale) {
54967 +               u16 gray = red + green + blue;
54968 +               gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54969 +               gray >>= 2;
54970 +               if (gray > 255) {
54971 +                       gray = 255;
54972 +               }
54973 +               red = gray;
54974 +               blue = gray;
54975 +               green = gray;
54976 +       }
54977 +
54978 +       palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54979 +                        (blue << fbi->var.blue.offset);
54980 +
54981 +       return 0;
54982 +}
54983 +
54984 +/*
54985 + * ubicom32vfb_mmap
54986 + */
54987 +static int ubicom32vfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
54988 +{
54989 +       struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
54990 +
54991 +       vma->vm_start = (unsigned long)(ud->fb_aligned);
54992 +
54993 +       vma->vm_end = vma->vm_start + info->fix.smem_len;
54994 +
54995 +       /* For those who don't understand how mmap works, go read
54996 +        *   Documentation/nommu-mmap.txt.
54997 +        * For those that do, you will know that the VM_MAYSHARE flag
54998 +        * must be set in the vma->vm_flags structure on noMMU
54999 +        *   Other flags can be set, and are documented in
55000 +        *   include/linux/mm.h
55001 +        */
55002 +
55003 +       vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
55004 +
55005 +       return 0;
55006 +}
55007 +
55008 +/*
55009 + * ubicom32vfb_check_var
55010 + *     Check the var, tweak it but don't change operational parameters.
55011 + */
55012 +static int ubicom32vfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
55013 +{
55014 +       struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
55015 +       u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
55016 +
55017 +       /*
55018 +        * See if we can handle this bpp
55019 +        */
55020 +       if (var->bits_per_pixel > BITS_PER_PIXEL) {
55021 +               return -EINVAL;
55022 +       }
55023 +       var->bits_per_pixel = BITS_PER_PIXEL;
55024 +
55025 +       /*
55026 +        * See if we have enough memory to handle this resolution
55027 +        */
55028 +       if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
55029 +               return -EINVAL;
55030 +       }
55031 +
55032 +       var->xres_virtual = var->xres;
55033 +       var->yres_virtual = ud->total_vram_size / line_size;
55034 +
55035 +       var->red.length = 5;
55036 +       var->green.length = 6;
55037 +       var->green.offset = 5;
55038 +       var->blue.length = 5;
55039 +       var->transp.offset = var->transp.length = 0;
55040 +
55041 +       if (bgr) {
55042 +               var->red.offset = 0;
55043 +               var->blue.offset = 11;
55044 +       } else {
55045 +               var->red.offset = 11;
55046 +               var->blue.offset = 0;
55047 +       }
55048 +
55049 +       var->nonstd = 0;
55050 +       var->height = -1;
55051 +       var->width = -1;
55052 +       var->vmode = FB_VMODE_NONINTERLACED;
55053 +       var->sync = 0;
55054 +
55055 +       return 0;
55056 +}
55057 +
55058 +/*
55059 + * ubicom32vfb_set_par
55060 + *     Set the video mode according to info->var
55061 + */
55062 +static int ubicom32vfb_set_par(struct fb_info *info)
55063 +{
55064 +       /*
55065 +        * Anything changed?
55066 +        */
55067 +       if ((xres == info->var.xres) && (yres == info->var.yres)) {
55068 +               return 0;
55069 +       }
55070 +
55071 +       /*
55072 +        * Implement changes
55073 +        */
55074 +       xres = info->var.xres;
55075 +       yres = info->var.yres;
55076 +       info->fix.visual = FB_VISUAL_TRUECOLOR;
55077 +       info->fix.xpanstep = 0;
55078 +       info->fix.ypanstep = 1;
55079 +       info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
55080 +
55081 +       return 0;
55082 +}
55083 +
55084 +/*
55085 + * ubicom32vfb_ops
55086 + *     List of supported operations
55087 + */
55088 +static struct fb_ops ubicom32vfb_ops =
55089 +{
55090 +       .owner                  = THIS_MODULE,
55091 +       .fb_pan_display         = ubicom32vfb_pan_display,
55092 +       .fb_setcolreg           = ubicom32vfb_setcolreg,
55093 +       .fb_mmap                = ubicom32vfb_mmap,
55094 +       .fb_check_var           = ubicom32vfb_check_var,
55095 +       .fb_set_par             = ubicom32vfb_set_par,
55096 +       .fb_fillrect            = cfb_fillrect,
55097 +       .fb_copyarea            = cfb_copyarea,
55098 +       .fb_imageblit           = cfb_imageblit,
55099 +};
55100 +
55101 +/*
55102 + * ubicom32vfb_release
55103 + */
55104 +static int ubicom32vfb_release(struct device *dev)
55105 +{
55106 +       struct ubicom32vfb_drvdata *ud = dev_get_drvdata(dev);
55107 +
55108 +       unregister_framebuffer(ud->fbinfo);
55109 +
55110 +       if (ud->cmap_alloc) {
55111 +               fb_dealloc_cmap(&ud->fbinfo->cmap);
55112 +       }
55113 +
55114 +       if (ud->fb) {
55115 +               kfree(ud->fb);
55116 +       }
55117 +
55118 +       framebuffer_release(ud->fbinfo);
55119 +       dev_set_drvdata(dev, NULL);
55120 +
55121 +       return 0;
55122 +}
55123 +
55124 +/*
55125 + * ubicom32vfb_platform_probe
55126 + */
55127 +static int __init ubicom32vfb_platform_probe(struct platform_device *pdev)
55128 +{
55129 +       struct ubicom32vfb_drvdata *ud;
55130 +       struct fb_info *fbinfo;
55131 +       int rc;
55132 +       size_t fbsize;
55133 +       struct device *dev = &pdev->dev;
55134 +       int offset;
55135 +
55136 +       /*
55137 +        * This is the minimum VRAM size
55138 +        */
55139 +       fbsize = xres * yres * 2;
55140 +       if (!vram_size) {
55141 +               vram_size = (fbsize + 1023) / 1024;
55142 +       } else {
55143 +               if (fbsize > (vram_size * 1024)) {
55144 +                       dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
55145 +                       return -ENOMEM; // should be ebadparam?
55146 +               }
55147 +       }
55148 +
55149 +       /*
55150 +        * Allocate the framebuffer instance + our private data
55151 +        */
55152 +       fbinfo = framebuffer_alloc(sizeof(struct ubicom32vfb_drvdata), &pdev->dev);
55153 +       if (!fbinfo) {
55154 +               dev_err(dev, "Not enough memory to allocate instance.\n");
55155 +               return -ENOMEM;
55156 +       }
55157 +
55158 +       /*
55159 +        * Fill in our private data.
55160 +        */
55161 +       ud = (struct ubicom32vfb_drvdata *)fbinfo->par;
55162 +       ud->fbinfo = fbinfo;
55163 +       dev_set_drvdata(dev, ud);
55164 +
55165 +       /*
55166 +        * Allocate and align the requested amount of VRAM
55167 +        */
55168 +       ud->total_vram_size = (vram_size * 1024) + UBICOM32VFB_ALIGNMENT;
55169 +       ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
55170 +       if (ud->fb == NULL) {
55171 +               dev_err(dev, "Couldn't allocate VRAM\n");
55172 +               rc = -ENOMEM;
55173 +               goto fail;
55174 +       }
55175 +
55176 +       offset = (u32_t)ud->fb & (UBICOM32VFB_ALIGNMENT - 1);
55177 +       if (!offset) {
55178 +               ud->fb_aligned = ud->fb;
55179 +       } else {
55180 +               offset =  UBICOM32VFB_ALIGNMENT - offset;
55181 +               ud->fb_aligned = ud->fb + offset;
55182 +       }
55183 +
55184 +       /*
55185 +        * Clear the entire frame buffer
55186 +        */
55187 +       memset(ud->fb_aligned, 0, vram_size * 1024);
55188 +
55189 +       /*
55190 +        * Fill in the fb_var_screeninfo structure
55191 +        */
55192 +       memset(&ubicom32vfb_var, 0, sizeof(ubicom32vfb_var));
55193 +       ubicom32vfb_var.bits_per_pixel = BITS_PER_PIXEL;
55194 +       ubicom32vfb_var.red.length = 5;
55195 +       ubicom32vfb_var.green.length = 6;
55196 +       ubicom32vfb_var.green.offset = 5;
55197 +       ubicom32vfb_var.blue.length = 5;
55198 +       ubicom32vfb_var.activate = FB_ACTIVATE_NOW;
55199 +
55200 +       if (bgr) {
55201 +               ubicom32vfb_var.red.offset = 0;
55202 +               ubicom32vfb_var.blue.offset = 11;
55203 +       } else {
55204 +               ubicom32vfb_var.red.offset = 11;
55205 +               ubicom32vfb_var.blue.offset = 0;
55206 +       }
55207 +
55208 +       /*
55209 +        * Fill in the fb_info structure
55210 +        */
55211 +       ud->fbinfo->device = dev;
55212 +       ud->fbinfo->screen_base = (void *)ud->fb_aligned;
55213 +       ud->fbinfo->fbops = &ubicom32vfb_ops;
55214 +       ud->fbinfo->fix = ubicom32vfb_fix;
55215 +       ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
55216 +       ud->fbinfo->fix.smem_len = vram_size * 1024;
55217 +       ud->fbinfo->fix.line_length = xres * 2;
55218 +       ud->fbinfo->fix.mmio_start = (u32)ud;
55219 +       ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32vfb_drvdata);
55220 +
55221 +       /*
55222 +        * We support panning in the y direction only
55223 +        */
55224 +       ud->fbinfo->fix.xpanstep = 0;
55225 +       ud->fbinfo->fix.ypanstep = 1;
55226 +
55227 +       ud->fbinfo->pseudo_palette = ud->pseudo_palette;
55228 +       ud->fbinfo->flags = FBINFO_DEFAULT;
55229 +       ud->fbinfo->var = ubicom32vfb_var;
55230 +       ud->fbinfo->var.xres = xres;
55231 +       ud->fbinfo->var.yres = yres;
55232 +
55233 +       /*
55234 +        * We cannot pan in the X direction, so xres_virtual is xres
55235 +        * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
55236 +        */
55237 +       ud->fbinfo->var.xres_virtual = xres;
55238 +       ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
55239 +
55240 +       /*
55241 +        * Allocate a color map
55242 +        */
55243 +       rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
55244 +       if (rc) {
55245 +               dev_err(dev, "Fail to allocate colormap (%d entries)\n",
55246 +                       PALETTE_ENTRIES_NO);
55247 +               goto fail;
55248 +       }
55249 +       ud->cmap_alloc = true;
55250 +
55251 +       /*
55252 +        * Register new frame buffer
55253 +        */
55254 +       rc = register_framebuffer(ud->fbinfo);
55255 +       if (rc) {
55256 +               dev_err(dev, "Could not register frame buffer\n");
55257 +               goto fail;
55258 +       }
55259 +
55260 +       /*
55261 +        * Tell the log we are here
55262 +        */
55263 +       dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
55264 +               ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
55265 +               ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
55266 +
55267 +       /*
55268 +        * Success
55269 +        */
55270 +       return 0;
55271 +
55272 +fail:
55273 +       ubicom32vfb_release(dev);
55274 +       return rc;
55275 +}
55276 +
55277 +/*
55278 + * ubicom32vfb_platform_remove
55279 + */
55280 +static int ubicom32vfb_platform_remove(struct platform_device *pdev)
55281 +{
55282 +       dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
55283 +       return ubicom32vfb_release(&pdev->dev);
55284 +}
55285 +
55286 +static struct platform_driver ubicom32vfb_platform_driver = {
55287 +       .probe          = ubicom32vfb_platform_probe,
55288 +       .remove         = ubicom32vfb_platform_remove,
55289 +       .driver = {
55290 +               .name = DRIVER_NAME,
55291 +               .owner = THIS_MODULE,
55292 +       },
55293 +};
55294 +
55295 +#ifndef MODULE
55296 +/*
55297 + * ubicom32vfb_setup
55298 + *     Process kernel boot options
55299 + */
55300 +static int __init ubicom32vfb_setup(char *options)
55301 +{
55302 +       char *this_opt;
55303 +
55304 +       if (!options || !*options) {
55305 +               return 0;
55306 +       }
55307 +
55308 +       while ((this_opt = strsep(&options, ",")) != NULL) {
55309 +               if (!*this_opt) {
55310 +                       continue;
55311 +               }
55312 +
55313 +               if (!strncmp(this_opt, "vram_size=", 10)) {
55314 +                       vram_size = simple_strtoul(this_opt + 10, NULL, 0);
55315 +                       continue;
55316 +               }
55317 +
55318 +               if (!strncmp(this_opt, "bgr=", 4)) {
55319 +                       bgr = simple_strtoul(this_opt + 4, NULL, 0);
55320 +                       continue;
55321 +               }
55322 +
55323 +               if (!strncmp(this_opt, "xres=", 5)) {
55324 +                       xres = simple_strtoul(this_opt + 5, NULL, 0);
55325 +                       continue;
55326 +               }
55327 +
55328 +               if (!strncmp(this_opt, "yres=", 5)) {
55329 +                       yres = simple_strtoul(this_opt + 5, NULL, 0);
55330 +                       continue;
55331 +               }
55332 +       }
55333 +       return 0;
55334 +}
55335 +#endif /* MODULE */
55336 +
55337 +/*
55338 + * ubicom32vfb_init
55339 + */
55340 +static int __devinit ubicom32vfb_init(void)
55341 +{
55342 +       int ret;
55343 +
55344 +#ifndef MODULE
55345 +       /*
55346 +        * Get kernel boot options (in 'video=ubicom32vfb:<options>')
55347 +        */
55348 +       char *option = NULL;
55349 +
55350 +       if (fb_get_options(DRIVER_NAME, &option)) {
55351 +               return -ENODEV;
55352 +       }
55353 +       ubicom32vfb_setup(option);
55354 +#endif /* MODULE */
55355 +
55356 +       ret = platform_driver_register(&ubicom32vfb_platform_driver);
55357 +
55358 +#ifdef CONFIG_FB_UBICOM32_VIRTUAL_NOAUTO
55359 +       return ret;
55360 +#else
55361 +       if (!ret) {
55362 +               ubicom32vfb_platform_device = platform_device_alloc(DRIVER_NAME, 0);
55363 +
55364 +               if (ubicom32vfb_platform_device)
55365 +                       ret = platform_device_add(ubicom32vfb_platform_device);
55366 +               else
55367 +                       ret = -ENOMEM;
55368 +
55369 +               if (ret) {
55370 +                       platform_device_put(ubicom32vfb_platform_device);
55371 +                       platform_driver_unregister(&ubicom32vfb_platform_driver);
55372 +               }
55373 +       }
55374 +
55375 +       return ret;
55376 +#endif
55377 +}
55378 +module_init(ubicom32vfb_init);
55379 +
55380 +/*
55381 + * ubicom32vfb_exit
55382 + */
55383 +static void __exit ubicom32vfb_exit(void)
55384 +{
55385 +       platform_device_unregister(ubicom32vfb_platform_device);
55386 +       platform_driver_unregister(&ubicom32vfb_platform_driver);
55387 +}
55388 +module_exit(ubicom32vfb_exit);
55389 +
55390 +MODULE_LICENSE("GPL");
55391 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
55392 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
55393 diff -ruN linux-2.6.30.10/drivers/watchdog/Kconfig linux-2.6.30.10-ubi/drivers/watchdog/Kconfig
55394 --- linux-2.6.30.10/drivers/watchdog/Kconfig    2009-12-04 08:00:07.000000000 +0200
55395 +++ linux-2.6.30.10-ubi/drivers/watchdog/Kconfig        2009-12-11 11:45:21.000000000 +0200
55396 @@ -887,6 +887,19 @@
55397           machines.  The watchdog timeout period is normally one minute but
55398           can be changed with a boot-time parameter.
55399  
55400 +# Ubicom32
55401 +
55402 +config UBI32_WDT
55403 +       tristate "Ubicom32 Hardware Watchdog support"
55404 +       depends on UBICOM32
55405 +       ---help---
55406 +         If you say yes here you will get support for the Ubicom32 On-Chip
55407 +         Watchdog Timer. If you have one of these processors and wish to
55408 +         have watchdog support enabled, say Y, otherwise say N.
55409 +
55410 +         To compile this driver as a module, choose M here: the
55411 +         module will be called ubi32_wdt.
55412 +
55413  # XTENSA Architecture
55414  
55415  #
55416 diff -ruN linux-2.6.30.10/drivers/watchdog/Makefile linux-2.6.30.10-ubi/drivers/watchdog/Makefile
55417 --- linux-2.6.30.10/drivers/watchdog/Makefile   2009-12-04 08:00:07.000000000 +0200
55418 +++ linux-2.6.30.10-ubi/drivers/watchdog/Makefile       2009-12-11 11:45:21.000000000 +0200
55419 @@ -131,6 +131,9 @@
55420  obj-$(CONFIG_WATCHDOG_RIO)             += riowd.o
55421  obj-$(CONFIG_WATCHDOG_CP1XXX)          += cpwd.o
55422  
55423 +# Ubicom32 Architecture
55424 +obj-$(CONFIG_UBI32_WDT)                        += ubi32_wdt.o
55425 +
55426  # XTENSA Architecture
55427  
55428  # Architecture Independant
55429 diff -ruN linux-2.6.30.10/drivers/watchdog/ubi32_wdt.c linux-2.6.30.10-ubi/drivers/watchdog/ubi32_wdt.c
55430 --- linux-2.6.30.10/drivers/watchdog/ubi32_wdt.c        1970-01-01 02:00:00.000000000 +0200
55431 +++ linux-2.6.30.10-ubi/drivers/watchdog/ubi32_wdt.c    2009-12-11 11:45:21.000000000 +0200
55432 @@ -0,0 +1,630 @@
55433 +/*
55434 + * drivers/watchdog/ubi32_wdt.c
55435 + *   Ubicom32 Watchdog Driver
55436 + *
55437 + * Originally based on softdog.c
55438 + * Copyright 2006-2007 Analog Devices Inc.
55439 + * Copyright 2006-2007 Michele d'Amico
55440 + * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
55441 + * (C) Copyright 2009, Ubicom, Inc.
55442 + *
55443 + * This file is part of the Ubicom32 Linux Kernel Port.
55444 + *
55445 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
55446 + * it and/or modify it under the terms of the GNU General Public License
55447 + * as published by the Free Software Foundation, either version 2 of the
55448 + * License, or (at your option) any later version.
55449 + *
55450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
55451 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
55452 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
55453 + * the GNU General Public License for more details.
55454 + *
55455 + * You should have received a copy of the GNU General Public License
55456 + * along with the Ubicom32 Linux Kernel Port.  If not,
55457 + * see <http://www.gnu.org/licenses/>.
55458 + *
55459 + * Ubicom32 implementation derived from (with many thanks):
55460 + *   arch/m68knommu
55461 + *   arch/blackfin
55462 + *   arch/parisc
55463 + */
55464 +#include <linux/platform_device.h>
55465 +#include <linux/module.h>
55466 +#include <linux/moduleparam.h>
55467 +#include <linux/types.h>
55468 +#include <linux/timer.h>
55469 +#include <linux/miscdevice.h>
55470 +#include <linux/watchdog.h>
55471 +#include <linux/fs.h>
55472 +#include <linux/notifier.h>
55473 +#include <linux/reboot.h>
55474 +#include <linux/init.h>
55475 +#include <linux/interrupt.h>
55476 +#include <linux/uaccess.h>
55477 +#include <asm/ip5000.h>
55478 +
55479 +#define WATCHDOG_NAME "ubi32-wdt"
55480 +#define PFX WATCHDOG_NAME ": "
55481 +
55482 +#define OSC1_FREQ 12000000
55483 +#define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
55484 +#define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
55485 +
55486 +#define MIN_PROCESSOR_ADDRESS 0x03000000
55487 +
55488 +static DEFINE_SPINLOCK(ubi32_wdt_spinlock);
55489 +
55490 +#define WATCHDOG_TIMEOUT 20
55491 +
55492 +#if defined(CONFIG_WATCHDOG_NOWAYOUT)
55493 +#define WATCHDOG_NOWAYOUT 1
55494 +#else
55495 +#define WATCHDOG_NOWAYOUT 0
55496 +#endif
55497 +
55498 +static unsigned int timeout = WATCHDOG_TIMEOUT;
55499 +static int nowayout = WATCHDOG_NOWAYOUT;
55500 +static struct watchdog_info ubi32_wdt_info;
55501 +static unsigned long open_check;
55502 +static char expect_close;
55503 +
55504 +#if !defined(CONFIG_SMP)
55505 +#define UBI32_WDT_LOCK(lock, flags) local_irq_save(flags)
55506 +#define UBI32_WDT_UNLOCK(lock, flags) local_irq_restore(flags)
55507 +#define UBI32_WDT_LOCK_CHECK()
55508 +#else
55509 +#define UBI32_WDT_LOCK(lock, flags) spin_lock_irqsave((lock), (flags));
55510 +#define UBI32_WDT_UNLOCK(lock, flags) spin_unlock_irqrestore((lock), (flags));
55511 +#define UBI32_WDT_LOCK_CHECK() BUG_ON(!spin_is_locked(&ubi32_wdt_spinlock));
55512 +#endif
55513 +
55514 +/*
55515 + * ubi32_wdt_remaining()
55516 + *     Return the approximate number of seconds remaining
55517 + */
55518 +static int ubi32_wdt_remaining(void)
55519 +{
55520 +       int compare;
55521 +       int curr;
55522 +
55523 +       UBI32_WDT_LOCK_CHECK();
55524 +
55525 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55526 +       compare = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcom);
55527 +       curr = ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval);
55528 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55529 +       return (compare - curr) / OSC1_FREQ;
55530 +
55531 +}
55532 +
55533 +/*
55534 + * ubi32_wdt_keepalive()
55535 + *     Keep the Userspace Watchdog Alive
55536 + *
55537 + * The Userspace watchdog got a KeepAlive: schedule the next timeout.
55538 + */
55539 +static int ubi32_wdt_keepalive(void)
55540 +{
55541 +       UBI32_WDT_LOCK_CHECK();
55542 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55543 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55544 +                       ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55545 +                       + WATCHDOG_SEC_TO_CYC(timeout));
55546 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55547 +       return 0;
55548 +}
55549 +
55550 +/*
55551 + * ubi32_wdt_stop()
55552 + *     Stop the on-chip Watchdog
55553 + */
55554 +static int ubi32_wdt_stop(void)
55555 +{
55556 +       UBI32_WDT_LOCK_CHECK();
55557 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55558 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, TIMER_WATCHDOG_DISABLE);
55559 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55560 +       return 0;
55561 +}
55562 +
55563 +/*
55564 + * ubi32_wdt_start()
55565 + *     Start the on-chip Watchdog
55566 + */
55567 +static int ubi32_wdt_start(void)
55568 +{
55569 +       UBI32_WDT_LOCK_CHECK();
55570 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55571 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55572 +                       ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55573 +                       + WATCHDOG_SEC_TO_CYC(timeout));
55574 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, ~TIMER_WATCHDOG_DISABLE);
55575 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55576 +       return 0;
55577 +}
55578 +
55579 +/*
55580 + * ubi32_wdt_running()
55581 + *     Return true if the watchdog is configured
55582 + */
55583 +static int ubi32_wdt_running(void)
55584 +{
55585 +       int enabled;
55586 +
55587 +       UBI32_WDT_LOCK_CHECK();
55588 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55589 +       enabled = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcfg) == ~TIMER_WATCHDOG_DISABLE;
55590 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55591 +       return enabled;
55592 +}
55593 +
55594 +/*
55595 + * ubi32_wdt_set_timeout()
55596 + *     Set the Userspace Watchdog timeout
55597 + *
55598 + * - @t: new timeout value (in seconds)
55599 + */
55600 +static int ubi32_wdt_set_timeout(unsigned long t)
55601 +{
55602 +       UBI32_WDT_LOCK_CHECK();
55603 +
55604 +       if (t > WATCHDOG_MAX_SEC) {
55605 +               printk(KERN_WARNING PFX "request to large: %ld [1-%d] sec)\n", t, WATCHDOG_MAX_SEC);
55606 +               return -EINVAL;
55607 +       }
55608 +
55609 +       /*
55610 +        * If we are running, then reset the time value so
55611 +        * that the new value has an immediate effect.
55612 +        */
55613 +       timeout = t;
55614 +       if (ubi32_wdt_running()) {
55615 +               ubi32_wdt_keepalive();
55616 +       }
55617 +       return 0;
55618 +}
55619 +
55620 +/*
55621 + * ubi32_wdt_open()
55622 + *     Open the Device
55623 + */
55624 +static int ubi32_wdt_open(struct inode *inode, struct file *file)
55625 +{
55626 +       unsigned long flags;
55627 +
55628 +       if (test_and_set_bit(0, &open_check))
55629 +               return -EBUSY;
55630 +
55631 +       if (nowayout)
55632 +               __module_get(THIS_MODULE);
55633 +
55634 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55635 +       ubi32_wdt_start();
55636 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55637 +
55638 +       return nonseekable_open(inode, file);
55639 +}
55640 +
55641 +/*
55642 + * ubi32_wdt_close()
55643 + *     Close the Device
55644 + */
55645 +static int ubi32_wdt_release(struct inode *inode, struct file *file)
55646 +{
55647 +       unsigned long flags;
55648 +
55649 +       /*
55650 +        * If we don't expect a close, then the watchdog continues
55651 +        * even though the device is closed.  The caller will have
55652 +        * a full timeout value to reopen the device and continue
55653 +        * stroking it.
55654 +        */
55655 +       if (expect_close != 42) {
55656 +               printk(KERN_CRIT PFX
55657 +                       "Unexpected close, not stopping watchdog!\n");
55658 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55659 +               ubi32_wdt_keepalive();
55660 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55661 +       } else {
55662 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55663 +               ubi32_wdt_stop();
55664 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55665 +       }
55666 +
55667 +       expect_close = 0;
55668 +       clear_bit(0, &open_check);
55669 +       return 0;
55670 +}
55671 +
55672 +/*
55673 + * ubi32_wdt_write()
55674 + *     Write to Device
55675 + *
55676 + * If the user writes nothing, nothing happens.
55677 + * If the user writes a V, then we expect a close and allow a release.
55678 + * If the user writes anything else, it is ignored.
55679 + */
55680 +static ssize_t ubi32_wdt_write(struct file *file, const char __user *data,
55681 +                                               size_t len, loff_t *ppos)
55682 +{
55683 +       size_t i;
55684 +       unsigned long flags;
55685 +
55686 +       /*
55687 +        * Every write resets the expect_close.  The last write
55688 +        * must be a V to allow shutdown on close.
55689 +        */
55690 +       expect_close = 0;
55691 +
55692 +       /*
55693 +        * Empty writes still ping.
55694 +        */
55695 +       if (!len) {
55696 +               goto ping;
55697 +       }
55698 +
55699 +       /*
55700 +        * If nowayout is set, it does not matter if the caller
55701 +        * is trying to send the magic 'V' we will not allow a
55702 +        * close to stop us.
55703 +        */
55704 +       if (nowayout) {
55705 +               goto ping;
55706 +       }
55707 +
55708 +       /*
55709 +        * See if the program wrote a 'V' and if so disable
55710 +        * the watchdog on release.
55711 +        */
55712 +       for (i = 0; i < len; i++) {
55713 +               char c;
55714 +               if (get_user(c, data + i)) {
55715 +                       return -EFAULT;
55716 +               }
55717 +
55718 +               if (c == 'V') {
55719 +                       expect_close = 42;
55720 +               }
55721 +       }
55722 +
55723 +ping:
55724 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55725 +       ubi32_wdt_keepalive();
55726 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55727 +       return len;
55728 +}
55729 +
55730 +/*
55731 + * ubi32_wdt_ioctl()
55732 + *     Query the watchdog device.
55733 + *
55734 + * Query basic information from the device or ping it, as outlined by the
55735 + * watchdog API.
55736 + */
55737 +static long ubi32_wdt_ioctl(struct file *file,
55738 +                               unsigned int cmd, unsigned long arg)
55739 +{
55740 +       void __user *argp = (void __user *)arg;
55741 +       int __user *p = argp;
55742 +
55743 +       switch (cmd) {
55744 +       case WDIOC_GETSUPPORT:
55745 +               if (copy_to_user(argp, &ubi32_wdt_info, sizeof(ubi32_wdt_info))) {
55746 +                       return -EFAULT;
55747 +               }
55748 +               return 0;
55749 +
55750 +       case WDIOC_GETSTATUS: {
55751 +               unsigned long flags;
55752 +               int running;
55753 +
55754 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55755 +               running = ubi32_wdt_running();
55756 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55757 +               return running;
55758 +       }
55759 +
55760 +       case WDIOC_GETBOOTSTATUS:
55761 +               return ubicom32_get_reset_reason();
55762 +
55763 +       case WDIOC_SETOPTIONS: {
55764 +               unsigned long flags;
55765 +               int options, ret = -EINVAL;
55766 +
55767 +               /*
55768 +                * The sample application does not pass a pointer
55769 +                * but directly passes a value of 1 or 2; however
55770 +                * all of the implementations (and thus probably
55771 +                * the real applications) pass a pointer to a value.
55772 +                *
55773 +                * It should be noted that  WDIOC_SETOPTIONS is defined as
55774 +                * _IOR(WATCHDOG_IOCTL_BASE, 4, int), which means
55775 +                * that it should be an int and NOT a pointer.
55776 +                *
55777 +                * TODO: Examine this code for future chips.
55778 +                * TODO: Report the sample code defect.
55779 +                */
55780 +               if ((int)p < MIN_PROCESSOR_ADDRESS) {
55781 +                       options = (int)p;
55782 +               } else {
55783 +                       if (get_user(options, p))
55784 +                       return -EFAULT;
55785 +               }
55786 +
55787 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55788 +               if (options & WDIOS_DISABLECARD) {
55789 +                       ubi32_wdt_stop();
55790 +                       ret = 0;
55791 +               }
55792 +               if (options & WDIOS_ENABLECARD) {
55793 +                       ubi32_wdt_start();
55794 +                       ret = 0;
55795 +               }
55796 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55797 +               return ret;
55798 +       }
55799 +
55800 +       case WDIOC_KEEPALIVE: {
55801 +               unsigned long flags;
55802 +
55803 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55804 +               ubi32_wdt_keepalive();
55805 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55806 +               return 0;
55807 +       }
55808 +
55809 +       case WDIOC_SETTIMEOUT: {
55810 +               int new_timeout;
55811 +               unsigned long flags;
55812 +               int ret  = 0;
55813 +
55814 +               if (get_user(new_timeout, p))
55815 +                       return -EFAULT;
55816 +
55817 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55818 +               ret = ubi32_wdt_set_timeout(new_timeout);
55819 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55820 +               return ret;
55821 +
55822 +       }
55823 +
55824 +       case WDIOC_GETTIMEOUT:
55825 +               return put_user(timeout, p);
55826 +
55827 +       case WDIOC_GETTIMELEFT: {
55828 +               unsigned long flags;
55829 +               int remaining = 0;
55830 +
55831 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55832 +               remaining = ubi32_wdt_remaining();
55833 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55834 +               return put_user(remaining, p);
55835 +       }
55836 +
55837 +       default:
55838 +               return -ENOTTY;
55839 +       }
55840 +}
55841 +
55842 +/*
55843 + * ubi32_wdt_notify_sys()
55844 + *     Notification callback function for system events.
55845 + *
55846 + * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
55847 + */
55848 +static int ubi32_wdt_notify_sys(struct notifier_block *this,
55849 +                                       unsigned long code, void *unused)
55850 +{
55851 +       if (code == SYS_DOWN || code == SYS_HALT) {
55852 +               unsigned long flags;
55853 +
55854 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55855 +               ubi32_wdt_stop();
55856 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55857 +       }
55858 +
55859 +       return NOTIFY_DONE;
55860 +}
55861 +
55862 +#ifdef CONFIG_PM
55863 +static int state_before_suspend;
55864 +
55865 +/*
55866 + * ubi32_wdt_suspend()
55867 + *     suspend the watchdog
55868 + *
55869 + * Remember if the watchdog was running and stop it.
55870 + */
55871 +static int ubi32_wdt_suspend(struct platform_device *pdev, pm_message_t state)
55872 +{
55873 +       unsigned long flags;
55874 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55875 +       state_before_suspend = ubi32_wdt_running();
55876 +       ubi32_wdt_stop();
55877 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55878 +
55879 +       return 0;
55880 +}
55881 +
55882 +/*
55883 + * ubi32_wdt_resume()
55884 + *     Resume the watchdog
55885 + *
55886 + * If the watchdog was running, turn it back on.
55887 + */
55888 +static int ubi32_wdt_resume(struct platform_device *pdev)
55889 +{
55890 +       if (state_before_suspend) {
55891 +               unsigned long flags;
55892 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55893 +               ubi32_wdt_set_timeout(timeout);
55894 +               ubi32_wdt_start();
55895 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55896 +       }
55897 +
55898 +       return 0;
55899 +}
55900 +#else
55901 +# define ubi32_wdt_suspend NULL
55902 +# define ubi32_wdt_resume NULL
55903 +#endif
55904 +
55905 +static const struct file_operations ubi32_wdt_fops = {
55906 +       .owner          = THIS_MODULE,
55907 +       .llseek         = no_llseek,
55908 +       .write          = ubi32_wdt_write,
55909 +       .unlocked_ioctl = ubi32_wdt_ioctl,
55910 +       .open           = ubi32_wdt_open,
55911 +       .release        = ubi32_wdt_release,
55912 +};
55913 +
55914 +static struct miscdevice ubi32_wdt_miscdev = {
55915 +       .minor    = WATCHDOG_MINOR,
55916 +       .name     = "watchdog",
55917 +       .fops     = &ubi32_wdt_fops,
55918 +};
55919 +
55920 +static struct watchdog_info ubi32_wdt_info = {
55921 +       .identity = "Ubicom32 Watchdog",
55922 +       .options  = WDIOF_SETTIMEOUT |
55923 +                   WDIOF_KEEPALIVEPING |
55924 +                   WDIOF_MAGICCLOSE,
55925 +};
55926 +
55927 +static struct notifier_block ubi32_wdt_notifier = {
55928 +       .notifier_call = ubi32_wdt_notify_sys,
55929 +};
55930 +
55931 +/*
55932 + * ubi32_wdt_probe()
55933 + *     Probe/register the watchdog module
55934 + *
55935 + * Registers the misc device and notifier handler.  Actual device
55936 + * initialization is handled by ubi32_wdt_open().
55937 + */
55938 +static int __devinit ubi32_wdt_probe(struct platform_device *pdev)
55939 +{
55940 +       int ret;
55941 +
55942 +       ret = register_reboot_notifier(&ubi32_wdt_notifier);
55943 +       if (ret) {
55944 +               printk(KERN_ERR PFX
55945 +                       "cannot register reboot notifier (err=%d)\n", ret);
55946 +               return ret;
55947 +       }
55948 +
55949 +       ret = misc_register(&ubi32_wdt_miscdev);
55950 +       if (ret) {
55951 +               printk(KERN_ERR PFX
55952 +                       "cannot register miscdev on minor=%d (err=%d)\n",
55953 +                               WATCHDOG_MINOR, ret);
55954 +               unregister_reboot_notifier(&ubi32_wdt_notifier);
55955 +               return ret;
55956 +       }
55957 +
55958 +       printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
55959 +              timeout, nowayout);
55960 +
55961 +       return 0;
55962 +}
55963 +
55964 +/*
55965 + * ubi32_wdt_remove()
55966 + *     Uninstall the module
55967 + *
55968 + * Unregisters the misc device and notifier handler.  Actual device
55969 + * deinitialization is handled by ubi32_wdt_close().
55970 + */
55971 +static int __devexit ubi32_wdt_remove(struct platform_device *pdev)
55972 +{
55973 +       misc_deregister(&ubi32_wdt_miscdev);
55974 +       unregister_reboot_notifier(&ubi32_wdt_notifier);
55975 +       return 0;
55976 +}
55977 +
55978 +static struct platform_device *ubi32_wdt_device;
55979 +
55980 +static struct platform_driver ubi32_wdt_driver = {
55981 +       .probe     = ubi32_wdt_probe,
55982 +       .remove    = __devexit_p(ubi32_wdt_remove),
55983 +       .suspend   = ubi32_wdt_suspend,
55984 +       .resume    = ubi32_wdt_resume,
55985 +       .driver    = {
55986 +               .name  = WATCHDOG_NAME,
55987 +               .owner = THIS_MODULE,
55988 +       },
55989 +};
55990 +
55991 +/*
55992 + * ubi32_wdt_init()
55993 + *     Initialize the watchdog.
55994 + *
55995 + * Checks the module params and registers the platform device & driver.
55996 + * Real work is in the platform probe function.
55997 + */
55998 +static int __init ubi32_wdt_init(void)
55999 +{
56000 +       unsigned long flags;
56001 +       int ret;
56002 +
56003 +       /*
56004 +        * Check that the timeout value is within range
56005 +        */
56006 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
56007 +       ret = ubi32_wdt_set_timeout(timeout);
56008 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
56009 +       if (ret) {
56010 +               return ret;
56011 +       }
56012 +
56013 +       /*
56014 +        * Since this is an on-chip device and needs no board-specific
56015 +        * resources, we'll handle all the platform device stuff here.
56016 +        */
56017 +       ret = platform_driver_register(&ubi32_wdt_driver);
56018 +       if (ret) {
56019 +               printk(KERN_ERR PFX "unable to register driver\n");
56020 +               return ret;
56021 +       }
56022 +
56023 +       ubi32_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
56024 +       if (IS_ERR(ubi32_wdt_device)) {
56025 +               printk(KERN_ERR PFX "unable to register device\n");
56026 +               platform_driver_unregister(&ubi32_wdt_driver);
56027 +               return PTR_ERR(ubi32_wdt_device);
56028 +       }
56029 +
56030 +       return 0;
56031 +}
56032 +
56033 +/*
56034 + * ubi32_wdt_exit()
56035 + *     Deinitialize module
56036 + *
56037 + * Back out the platform device & driver steps.  Real work is in the
56038 + * platform remove function.
56039 + */
56040 +static void __exit ubi32_wdt_exit(void)
56041 +{
56042 +       platform_device_unregister(ubi32_wdt_device);
56043 +       platform_driver_unregister(&ubi32_wdt_driver);
56044 +}
56045 +
56046 +module_init(ubi32_wdt_init);
56047 +module_exit(ubi32_wdt_exit);
56048 +
56049 +MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>");
56050 +MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver");
56051 +MODULE_LICENSE("GPL");
56052 +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
56053 +
56054 +module_param(timeout, uint, 0);
56055 +MODULE_PARM_DESC(timeout,
56056 +       "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
56057 +               __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
56058 +
56059 +module_param(nowayout, int, 0);
56060 +MODULE_PARM_DESC(nowayout,
56061 +       "Watchdog cannot be stopped once started (default="
56062 +               __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
56063 diff -ruN linux-2.6.30.10/fs/binfmt_flat.c linux-2.6.30.10-ubi/fs/binfmt_flat.c
56064 --- linux-2.6.30.10/fs/binfmt_flat.c    2009-12-04 08:00:07.000000000 +0200
56065 +++ linux-2.6.30.10-ubi/fs/binfmt_flat.c        2009-12-11 11:45:21.000000000 +0200
56066 @@ -67,6 +67,11 @@
56067  #define FLAT_DATA_ALIGN        (sizeof(void *))
56068  #endif
56069  
56070 +#ifndef ARCH_FLAT_ALIGN
56071 +#undef FLAT_DATA_ALIGN
56072 +#define FLAT_DATA_ALIGN        ARCH_FLAT_ALIGN
56073 +#endif
56074 +
56075  #define RELOC_FAILED 0xff00ff01                /* Relocation incorrect somewhere */
56076  #define UNLOADED_LIB 0x7ff000ff                /* Placeholder for unused library */
56077  
56078 @@ -436,6 +441,7 @@
56079         loff_t fpos;
56080         unsigned long start_code, end_code;
56081         int ret;
56082 +       int flush_happened = 0;
56083  
56084         hdr = ((struct flat_hdr *) bprm->buf);          /* exec-header */
56085         inode = bprm->file->f_path.dentry->d_inode;
56086 @@ -521,6 +527,7 @@
56087  
56088                 /* OK, This is the point of no return */
56089                 set_personality(PER_LINUX_32BIT);
56090 +               flush_happened = 1;
56091         }
56092  
56093         /*
56094 @@ -535,6 +542,12 @@
56095          * it all together.
56096          */
56097         if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
56098 +
56099 +#ifdef ARCH_FLAT_ALIGN_TEXT
56100 +               printk("Unable to mmap rom with ARCH alignment requirements\n");
56101 +               ret = -ENOEXEC;
56102 +               goto err;
56103 +#endif
56104                 /*
56105                  * this should give us a ROM ptr,  but if it doesn't we don't
56106                  * really care
56107 @@ -553,7 +566,7 @@
56108                         goto err;
56109                 }
56110  
56111 -               len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
56112 +               len = data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
56113                 len = PAGE_ALIGN(len);
56114                 down_write(&current->mm->mmap_sem);
56115                 realdatastart = do_mmap(0, 0, len,
56116 @@ -572,6 +585,7 @@
56117                 datapos = ALIGN(realdatastart +
56118                                 MAX_SHARED_LIBS * sizeof(unsigned long),
56119                                 FLAT_DATA_ALIGN);
56120 +               //datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
56121  
56122                 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
56123                                 (int)(data_len + bss_len + stack_len), (int)datapos);
56124 @@ -600,7 +614,11 @@
56125                 memp_size = len;
56126         } else {
56127  
56128 -               len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
56129 +               len = text_len + data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
56130 +#ifdef ARCH_FLAT_ALIGN_TEXT
56131 +               /* Reserve space for the text alignment. */
56132 +               len += FLAT_DATA_ALIGN;
56133 +#endif
56134                 len = PAGE_ALIGN(len);
56135                 down_write(&current->mm->mmap_sem);
56136                 textpos = do_mmap(0, 0, len,
56137 @@ -616,10 +634,17 @@
56138                         goto err;
56139                 }
56140  
56141 +               memp = textpos;
56142 +#ifdef ARCH_FLAT_ALIGN_TEXT
56143 +               textpos = ALIGN(textpos + sizeof(struct flat_hdr), FLAT_DATA_ALIGN) - sizeof(struct flat_hdr);
56144 +#endif
56145                 realdatastart = textpos + ntohl(hdr->data_start);
56146                 datapos = ALIGN(realdatastart +
56147                                 MAX_SHARED_LIBS * sizeof(unsigned long),
56148                                 FLAT_DATA_ALIGN);
56149 +//             datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
56150 +//             reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
56151 +//                                        ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN));
56152  
56153                 reloc = (unsigned long *)
56154                         (datapos + (ntohl(hdr->reloc_start) - text_len));
56155 @@ -659,7 +684,7 @@
56156                 }
56157                 if (result >= (unsigned long)-4096) {
56158                         printk("Unable to read code+data+bss, errno %d\n",(int)-result);
56159 -                       do_munmap(current->mm, textpos, text_len + data_len + extra +
56160 +                       do_munmap(current->mm, memp, text_len + data_len + extra +
56161                                 MAX_SHARED_LIBS * sizeof(unsigned long));
56162                         ret = result;
56163                         goto err;
56164 @@ -672,6 +697,9 @@
56165  
56166         /* The main program needs a little extra setup in the task structure */
56167         start_code = textpos + sizeof (struct flat_hdr);
56168 +#ifdef ARCH_FLAT_ALIGN_TEXT
56169 +       BUG_ON(ALIGN(start_code, FLAT_DATA_ALIGN) != start_code);
56170 +#endif
56171         end_code = textpos + text_len;
56172         if (id == 0) {
56173                 current->mm->start_code = start_code;
56174 @@ -800,6 +828,13 @@
56175  
56176         return 0;
56177  err:
56178 +       if (flush_happened) {
56179 +               /*
56180 +                * The parent process has already started running. We cannot allow the child to return back to user space
56181 +                * as this child is still uning the parent stack and 2 will clobber each other. We are going to kill this child.
56182 +                */
56183 +               do_exit(SIGTERM);
56184 +       }
56185         return ret;
56186  }
56187  
56188 diff -ruN linux-2.6.30.10/fs/Kconfig.binfmt linux-2.6.30.10-ubi/fs/Kconfig.binfmt
56189 --- linux-2.6.30.10/fs/Kconfig.binfmt   2009-12-04 08:00:07.000000000 +0200
56190 +++ linux-2.6.30.10-ubi/fs/Kconfig.binfmt       2009-12-11 11:45:21.000000000 +0200
56191 @@ -30,7 +30,7 @@
56192  config BINFMT_ELF_FDPIC
56193         bool "Kernel support for FDPIC ELF binaries"
56194         default y
56195 -       depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
56196 +       depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || UBICOM32)
56197         help
56198           ELF FDPIC binaries are based on ELF, but allow the individual load
56199           segments of a binary to be located in memory independently of each
56200 diff -ruN linux-2.6.30.10/include/asm-generic/resource.h linux-2.6.30.10-ubi/include/asm-generic/resource.h
56201 --- linux-2.6.30.10/include/asm-generic/resource.h      2009-12-04 08:00:07.000000000 +0200
56202 +++ linux-2.6.30.10-ubi/include/asm-generic/resource.h  2009-12-11 11:45:23.000000000 +0200
56203 @@ -69,13 +69,16 @@
56204  /*
56205   * boot-time rlimit defaults for the init task:
56206   */
56207 +#ifndef        CONFIG_ELF_CORE
56208 +#define        CONFIG_USER_ELF_CORE_SIZE       0
56209 +#endif
56210  #define INIT_RLIMITS                                                   \
56211  {                                                                      \
56212         [RLIMIT_CPU]            = {  RLIM_INFINITY,  RLIM_INFINITY },   \
56213         [RLIMIT_FSIZE]          = {  RLIM_INFINITY,  RLIM_INFINITY },   \
56214         [RLIMIT_DATA]           = {  RLIM_INFINITY,  RLIM_INFINITY },   \
56215         [RLIMIT_STACK]          = {       _STK_LIM,   _STK_LIM_MAX },   \
56216 -       [RLIMIT_CORE]           = {              0,  RLIM_INFINITY },   \
56217 +       [RLIMIT_CORE]           = { CONFIG_USER_ELF_CORE_SIZE,  RLIM_INFINITY },        \
56218         [RLIMIT_RSS]            = {  RLIM_INFINITY,  RLIM_INFINITY },   \
56219         [RLIMIT_NPROC]          = {              0,              0 },   \
56220         [RLIMIT_NOFILE]         = {       INR_OPEN,       INR_OPEN },   \
56221 diff -ruN linux-2.6.30.10/include/linux/elf-em.h linux-2.6.30.10-ubi/include/linux/elf-em.h
56222 --- linux-2.6.30.10/include/linux/elf-em.h      2009-12-04 08:00:07.000000000 +0200
56223 +++ linux-2.6.30.10-ubi/include/linux/elf-em.h  2009-12-11 11:45:23.000000000 +0200
56224 @@ -41,6 +41,7 @@
56225   * up with a final number.
56226   */
56227  #define EM_ALPHA       0x9026
56228 +#define EM_UBICOM32            0xde3d  /* Ubicom32; no ABI */
56229  
56230  /* Bogus old v850 magic number, used by old tools. */
56231  #define EM_CYGNUS_V850 0x9080
56232 diff -ruN linux-2.6.30.10/include/linux/fb.h linux-2.6.30.10-ubi/include/linux/fb.h
56233 --- linux-2.6.30.10/include/linux/fb.h  2009-12-14 12:16:53.000000000 +0200
56234 +++ linux-2.6.30.10-ubi/include/linux/fb.h      2009-12-14 12:16:56.000000000 +0200
56235 @@ -151,6 +151,10 @@
56236  #define FB_ACCEL_PROSAVAGE_DDR  0x8d   /* S3 ProSavage DDR             */
56237  #define FB_ACCEL_PROSAVAGE_DDRK 0x8e   /* S3 ProSavage DDR-K           */
56238  
56239 +#define FB_ACCEL_UBICOM32              0x0100  /* Ubicom32                     */
56240 +#define FB_ACCEL_UBICOM32_VFB          0x0101  /* Ubicom32 VFB                 */
56241 +#define FB_ACCEL_UBICOM32_PLIO80       0x0102  /* Ubicom32 PLIO80              */
56242 +
56243  struct fb_fix_screeninfo {
56244         char id[16];                    /* identification string eg "TT Builtin" */
56245         unsigned long smem_start;       /* Start of frame buffer mem */
56246 diff -ruN linux-2.6.30.10/include/linux/if_ppp.h linux-2.6.30.10-ubi/include/linux/if_ppp.h
56247 --- linux-2.6.30.10/include/linux/if_ppp.h      2009-12-04 08:00:07.000000000 +0200
56248 +++ linux-2.6.30.10-ubi/include/linux/if_ppp.h  2009-12-11 11:45:23.000000000 +0200
56249 @@ -114,14 +114,14 @@
56250         __u16           tunnel_id;      /* redundant */
56251         __u16           session_id;     /* if zero, get tunnel stats */
56252         __u32           using_ipsec:1;  /* valid only for session_id == 0 */
56253 -       aligned_u64     tx_packets;
56254 -       aligned_u64     tx_bytes;
56255 -       aligned_u64     tx_errors;
56256 -       aligned_u64     rx_packets;
56257 -       aligned_u64     rx_bytes;
56258 -       aligned_u64     rx_seq_discards;
56259 -       aligned_u64     rx_oos_packets;
56260 -       aligned_u64     rx_errors;
56261 +       __u64   tx_packets;
56262 +       __u64   tx_bytes;
56263 +       __u64   tx_errors;
56264 +       __u64   rx_packets;
56265 +       __u64   rx_bytes;
56266 +       __u64   rx_seq_discards;
56267 +       __u64   rx_oos_packets;
56268 +       __u64   rx_errors;
56269  };
56270  
56271  #define ifr__name       b.ifr_ifrn.ifrn_name
56272 diff -ruN linux-2.6.30.10/include/linux/oprofile.h linux-2.6.30.10-ubi/include/linux/oprofile.h
56273 --- linux-2.6.30.10/include/linux/oprofile.h    2009-12-04 08:00:07.000000000 +0200
56274 +++ linux-2.6.30.10-ubi/include/linux/oprofile.h        2009-12-11 11:45:23.000000000 +0200
56275 @@ -99,6 +99,8 @@
56276   */
56277  void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
56278                                 unsigned long event, int is_kernel);
56279 +void oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
56280 +                               unsigned long event, int is_kernel, int cpu);
56281  
56282  /* Use this instead when the PC value is not from the regs. Doesn't
56283   * backtrace. */
56284 diff -ruN linux-2.6.30.10/include/linux/serial_core.h linux-2.6.30.10-ubi/include/linux/serial_core.h
56285 --- linux-2.6.30.10/include/linux/serial_core.h 2009-12-04 08:00:07.000000000 +0200
56286 +++ linux-2.6.30.10-ubi/include/linux/serial_core.h     2009-12-11 11:45:23.000000000 +0200
56287 @@ -167,6 +167,9 @@
56288  /* MAX3100 */
56289  #define PORT_MAX3100    86
56290  
56291 +/* Ubicom32 */
56292 +#define PORT_UBI32_UARTTIO     87
56293 +
56294  #ifdef __KERNEL__
56295  
56296  #include <linux/compiler.h>
56297 diff -ruN linux-2.6.30.10/include/linux/slab.h linux-2.6.30.10-ubi/include/linux/slab.h
56298 --- linux-2.6.30.10/include/linux/slab.h        2009-12-04 08:00:07.000000000 +0200
56299 +++ linux-2.6.30.10-ubi/include/linux/slab.h    2009-12-11 11:45:23.000000000 +0200
56300 @@ -317,4 +317,14 @@
56301         return kmalloc_node(size, flags | __GFP_ZERO, node);
56302  }
56303  
56304 +struct kmem_cache_size_info {
56305 +       unsigned short page;
56306 +       unsigned short order;
56307 +};
56308 +
56309 +/*
56310 + * get info on all the memory allocated by slab for this named cache
56311 + */
56312 +extern int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data);
56313 +
56314  #endif /* _LINUX_SLAB_H */
56315 diff -ruN linux-2.6.30.10/init/Kconfig linux-2.6.30.10-ubi/init/Kconfig
56316 --- linux-2.6.30.10/init/Kconfig        2009-12-14 13:00:08.000000000 +0200
56317 +++ linux-2.6.30.10-ubi/init/Kconfig    2009-12-14 13:00:11.000000000 +0200
56318 @@ -865,6 +865,12 @@
56319         help
56320           Enable support for generating core dumps. Disabling saves about 4k.
56321  
56322 +config USER_ELF_CORE_SIZE
56323 +       int "user core dump size (10MB to 32MB)"
56324 +       range 10485760 33554432
56325 +       default 16777216
56326 +       depends on ELF_CORE
56327 +
56328  config PCSPKR_PLATFORM
56329         bool "Enable PC-Speaker support" if EMBEDDED
56330         depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
56331 diff -ruN linux-2.6.30.10/kernel/module.c linux-2.6.30.10-ubi/kernel/module.c
56332 --- linux-2.6.30.10/kernel/module.c     2009-12-04 08:00:07.000000000 +0200
56333 +++ linux-2.6.30.10-ubi/kernel/module.c 2009-12-11 11:45:24.000000000 +0200
56334 @@ -2688,6 +2688,9 @@
56335         /* Used by oprofile and other similar tools. */
56336         seq_printf(m, " 0x%p", mod->module_core);
56337  
56338 +#ifdef ARCH_PROC_MODULES_EXTRA
56339 +       ARCH_PROC_MODULES_EXTRA(m, mod);
56340 +#endif
56341         /* Taints info */
56342         if (mod->taints)
56343                 seq_printf(m, " %s", module_flags(mod, buf));
56344 @@ -2840,8 +2843,12 @@
56345         printk("Modules linked in:");
56346         /* Most callers should already have preempt disabled, but make sure */
56347         preempt_disable();
56348 -       list_for_each_entry_rcu(mod, &modules, list)
56349 +       list_for_each_entry_rcu(mod, &modules, list) {
56350                 printk(" %s%s", mod->name, module_flags(mod, buf));
56351 +#ifdef ARCH_OOPS_MODULE_EXTRA
56352 +               ARCH_OOPS_MODULE_EXTRA(mod);
56353 +#endif
56354 +       }
56355         preempt_enable();
56356         if (last_unloaded_module[0])
56357                 printk(" [last unloaded: %s]", last_unloaded_module);
56358 diff -ruN linux-2.6.30.10/kernel/sched_clock.c linux-2.6.30.10-ubi/kernel/sched_clock.c
56359 --- linux-2.6.30.10/kernel/sched_clock.c        2009-12-04 08:00:07.000000000 +0200
56360 +++ linux-2.6.30.10-ubi/kernel/sched_clock.c    2009-12-11 11:45:24.000000000 +0200
56361 @@ -38,8 +38,7 @@
56362   */
56363  unsigned long long __attribute__((weak)) sched_clock(void)
56364  {
56365 -       return (unsigned long long)(jiffies - INITIAL_JIFFIES)
56366 -                                       * (NSEC_PER_SEC / HZ);
56367 +       return (get_jiffies_64() - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
56368  }
56369  
56370  static __read_mostly int sched_clock_running;
56371 diff -ruN linux-2.6.30.10/lib/Kconfig.debug linux-2.6.30.10-ubi/lib/Kconfig.debug
56372 --- linux-2.6.30.10/lib/Kconfig.debug   2009-12-04 08:00:07.000000000 +0200
56373 +++ linux-2.6.30.10-ubi/lib/Kconfig.debug       2009-12-11 11:45:24.000000000 +0200
56374 @@ -621,7 +621,7 @@
56375         bool "Compile the kernel with frame pointers"
56376         depends on DEBUG_KERNEL && \
56377                 (CRIS || M68K || M68KNOMMU || FRV || UML || \
56378 -                AVR32 || SUPERH || BLACKFIN || MN10300) || \
56379 +                AVR32 || SUPERH || BLACKFIN || MN10300 || UBICOM32) || \
56380                 ARCH_WANT_FRAME_POINTERS
56381         default y if (DEBUG_INFO && UML) || ARCH_WANT_FRAME_POINTERS
56382         help
56383 diff -ruN linux-2.6.30.10/mm/Makefile linux-2.6.30.10-ubi/mm/Makefile
56384 --- linux-2.6.30.10/mm/Makefile 2009-12-04 08:00:07.000000000 +0200
56385 +++ linux-2.6.30.10-ubi/mm/Makefile     2009-12-11 11:45:24.000000000 +0200
56386 @@ -38,3 +38,5 @@
56387  endif
56388  obj-$(CONFIG_QUICKLIST) += quicklist.o
56389  obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
56390 +
56391 +CFLAGS_slab.o := $(PROFILING) -O2
56392 diff -ruN linux-2.6.30.10/mm/slab.c linux-2.6.30.10-ubi/mm/slab.c
56393 --- linux-2.6.30.10/mm/slab.c   2009-12-04 08:00:07.000000000 +0200
56394 +++ linux-2.6.30.10-ubi/mm/slab.c       2009-12-11 11:45:24.000000000 +0200
56395 @@ -4100,6 +4100,68 @@
56396  
56397  #ifdef CONFIG_SLABINFO
56398  
56399 +
56400 +/*
56401 + * get info on all the memory allocated by slab for this named cache
56402 + */
56403 +int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data)
56404 +{
56405 +       int res = 0;
56406 +       int found = 0;
56407 +       int node;
56408 +       struct kmem_cache *cachep;
56409 +       struct kmem_list3 *l3;
56410 +       struct slab *slabp;
56411 +
56412 +       /* Find the cache in the chain of caches. */
56413 +       mutex_lock(&cache_chain_mutex);
56414 +       list_for_each_entry(cachep, &cache_chain, next) {
56415 +               if (strcmp(cachep->name, name) == 0) {
56416 +                       found = 1;
56417 +                       break;
56418 +               }
56419 +       }
56420 +       mutex_unlock(&cache_chain_mutex);
56421 +       if (!found) {
56422 +               return 0;
56423 +       }
56424 +       for_each_online_node(node) {
56425 +               l3 = cachep->nodelists[node];
56426 +               if (!l3)
56427 +                       continue;
56428 +               if (res >= max_data)
56429 +                       break;
56430 +               check_irq_on();
56431 +               spin_lock_irq(&l3->list_lock);
56432 +
56433 +               list_for_each_entry(slabp, &l3->slabs_full, list) {
56434 +                       if (res >= max_data)
56435 +                               break;
56436 +                       data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56437 +                       data[res].order = cachep->gfporder;
56438 +                       res++;
56439 +               }
56440 +               list_for_each_entry(slabp, &l3->slabs_partial, list) {
56441 +                       if (res >= max_data)
56442 +                               break;
56443 +                       data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56444 +                       data[res].order = cachep->gfporder;
56445 +                       res++;
56446 +               }
56447 +               list_for_each_entry(slabp, &l3->slabs_free, list) {
56448 +                       if (res >= max_data)
56449 +                               break;
56450 +                       data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56451 +                       data[res].order = cachep->gfporder;
56452 +                       res++;
56453 +               }
56454 +
56455 +               spin_unlock_irq(&l3->list_lock);
56456 +       }
56457 +
56458 +       return res;
56459 +}
56460 +
56461  static void print_slabinfo_header(struct seq_file *m)
56462  {
56463         /*
56464 diff -ruN linux-2.6.30.10/scripts/mod/file2alias.c linux-2.6.30.10-ubi/scripts/mod/file2alias.c
56465 --- linux-2.6.30.10/scripts/mod/file2alias.c    2009-12-04 08:00:07.000000000 +0200
56466 +++ linux-2.6.30.10-ubi/scripts/mod/file2alias.c        2009-12-11 11:45:24.000000000 +0200
56467 @@ -774,6 +774,15 @@
56468                         + sym->st_value;
56469         }
56470  
56471 +       /*
56472 +        * somehow our gcc is not generating st_size correctly and set 0 for some symbols.
56473 +        * and 0 size will break do_table since it adjust size to (size - id_size)
56474 +        * this is to make sure st_size fall in range.
56475 +        */
56476 +       if (sym->st_size == 0 || sym->st_size > info->sechdrs[sym->st_shndx].sh_size) {
56477 +               sym->st_size = info->sechdrs[sym->st_shndx].sh_size;
56478 +       }
56479 +
56480         if (sym_is(symname, "__mod_pci_device_table"))
56481                 do_table(symval, sym->st_size,
56482                          sizeof(struct pci_device_id), "pci",
56483 diff -ruN linux-2.6.30.10/sound/Kconfig linux-2.6.30.10-ubi/sound/Kconfig
56484 --- linux-2.6.30.10/sound/Kconfig       2009-12-04 08:00:07.000000000 +0200
56485 +++ linux-2.6.30.10-ubi/sound/Kconfig   2009-12-11 11:45:24.000000000 +0200
56486 @@ -82,6 +82,8 @@
56487  
56488  source "sound/soc/Kconfig"
56489  
56490 +source "sound/ubicom32/Kconfig"
56491 +
56492  endif # SND
56493  
56494  menuconfig SOUND_PRIME
56495 diff -ruN linux-2.6.30.10/sound/Makefile linux-2.6.30.10-ubi/sound/Makefile
56496 --- linux-2.6.30.10/sound/Makefile      2009-12-04 08:00:07.000000000 +0200
56497 +++ linux-2.6.30.10-ubi/sound/Makefile  2009-12-11 11:45:24.000000000 +0200
56498 @@ -6,7 +6,7 @@
56499  obj-$(CONFIG_SOUND_PRIME) += oss/
56500  obj-$(CONFIG_DMASOUND) += oss/
56501  obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
56502 -       sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
56503 +       sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ ubicom32/
56504  obj-$(CONFIG_SND_AOA) += aoa/
56505  
56506  # This one must be compilable even if sound is configured out
56507 diff -ruN linux-2.6.30.10/sound/ubicom32/Kconfig linux-2.6.30.10-ubi/sound/ubicom32/Kconfig
56508 --- linux-2.6.30.10/sound/ubicom32/Kconfig      1970-01-01 02:00:00.000000000 +0200
56509 +++ linux-2.6.30.10-ubi/sound/ubicom32/Kconfig  2009-12-11 11:45:25.000000000 +0200
56510 @@ -0,0 +1,42 @@
56511 +# ALSA Ubicom32 drivers
56512 +
56513 +menuconfig SND_UBI32
56514 +       tristate "Ubicom32 sound devices"
56515 +       select SND_PCM
56516 +       default n
56517 +       help
56518 +         Say Y here to include support for audio on the Ubicom32 platform.
56519 +         To compile this driver as a module, say M here: the module will be
56520 +         called snd_ubi32.
56521 +
56522 +if SND_UBI32
56523 +
56524 +config SND_UBI32_AUDIO_GENERIC_CAPTURE
56525 +       bool "Generic Capture Support"
56526 +       default n
56527 +       help
56528 +         Use this option to support ADCs which don't require special drivers.
56529 +
56530 +config SND_UBI32_AUDIO_GENERIC
56531 +       bool "Generic Playback Support"
56532 +       default n
56533 +       help
56534 +         Use this option to support DACs which don't require special drivers.
56535 +
56536 +comment "I2C Based Codecs"
56537 +
56538 +config SND_UBI32_AUDIO_CS4350
56539 +       bool "Cirrus Logic CS4350 DAC"
56540 +       depends on I2C
56541 +       default n
56542 +       help
56543 +         Support for the Cirrus Logic CS4350 DAC.
56544 +
56545 +config SND_UBI32_AUDIO_CS4384
56546 +       bool "Cirrus Logic CS4384 DAC"
56547 +       depends on I2C
56548 +       default n
56549 +       help
56550 +         Support for the Cirrus Logic CS4384 DAC.
56551 +
56552 +endif #SND_UBI32
56553 diff -ruN linux-2.6.30.10/sound/ubicom32/Makefile linux-2.6.30.10-ubi/sound/ubicom32/Makefile
56554 --- linux-2.6.30.10/sound/ubicom32/Makefile     1970-01-01 02:00:00.000000000 +0200
56555 +++ linux-2.6.30.10-ubi/sound/ubicom32/Makefile 2009-12-11 11:45:25.000000000 +0200
56556 @@ -0,0 +1,41 @@
56557 +#
56558 +# sound/ubicom32/Makefile
56559 +#      Makefile for ALSA
56560 +#
56561 +# (C) Copyright 2009, Ubicom, Inc.
56562 +#
56563 +# This file is part of the Ubicom32 Linux Kernel Port.
56564 +#
56565 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
56566 +# it and/or modify it under the terms of the GNU General Public License
56567 +# as published by the Free Software Foundation, either version 2 of the
56568 +# License, or (at your option) any later version.
56569 +#
56570 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
56571 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
56572 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
56573 +# the GNU General Public License for more details.
56574 +#
56575 +# You should have received a copy of the GNU General Public License
56576 +# along with the Ubicom32 Linux Kernel Port.  If not,
56577 +# see <http://www.gnu.org/licenses/>.
56578 +#
56579 +# Ubicom32 implementation derived from (with many thanks):
56580 +#   arch/m68knommu
56581 +#   arch/blackfin
56582 +#   arch/parisc
56583 +#
56584 +
56585 +CFLAGS_ubi32.o += -O2
56586 +snd-ubi32-pcm-objs := ubi32-pcm.o
56587 +snd-ubi32-generic-objs := ubi32-generic.o
56588 +snd-ubi32-generic-capture-objs := ubi32-generic-capture.o
56589 +snd-ubi32-cs4350-objs := ubi32-cs4350.o
56590 +snd-ubi32-cs4384-objs := ubi32-cs4384.o
56591 +
56592 +# Toplevel Module Dependency
56593 +obj-$(CONFIG_SND_UBI32) += snd-ubi32-pcm.o
56594 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC) += snd-ubi32-generic.o
56595 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC_CAPTURE) += snd-ubi32-generic-capture.o
56596 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4350) += snd-ubi32-cs4350.o
56597 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4384) += snd-ubi32-cs4384.o
56598 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-cs4350.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4350.c
56599 --- linux-2.6.30.10/sound/ubicom32/ubi32-cs4350.c       1970-01-01 02:00:00.000000000 +0200
56600 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4350.c   2009-12-11 11:45:25.000000000 +0200
56601 @@ -0,0 +1,583 @@
56602 +/*
56603 + * sound/ubicom32/ubi32-cs4350.c
56604 + *     Interface to ubicom32 virtual audio peripheral - using CS4350 DAC
56605 + *
56606 + * (C) Copyright 2009, Ubicom, Inc.
56607 + *
56608 + * This file is part of the Ubicom32 Linux Kernel Port.
56609 + *
56610 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
56611 + * it and/or modify it under the terms of the GNU General Public License
56612 + * as published by the Free Software Foundation, either version 2 of the
56613 + * License, or (at your option) any later version.
56614 + *
56615 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
56616 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
56617 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
56618 + * the GNU General Public License for more details.
56619 + *
56620 + * You should have received a copy of the GNU General Public License
56621 + * along with the Ubicom32 Linux Kernel Port.  If not,
56622 + * see <http://www.gnu.org/licenses/>.
56623 + */
56624 +
56625 +#include <linux/i2c.h>
56626 +#include <linux/module.h>
56627 +#include <linux/moduleparam.h>
56628 +#include <sound/core.h>
56629 +#include <sound/tlv.h>
56630 +#include <sound/control.h>
56631 +#include <sound/pcm.h>
56632 +#include <sound/initval.h>
56633 +#include "ubi32.h"
56634 +
56635 +#define DRIVER_NAME "snd-ubi32-cs4350"
56636 +
56637 +/*
56638 + * Module properties
56639 + */
56640 +static const struct i2c_device_id snd_ubi32_cs4350_id[] = {
56641 +       {"cs4350", 0 },
56642 +       { }
56643 +};
56644 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
56645 +
56646 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
56647 +
56648 +/*
56649 + * The dB scale for the Cirrus Logic cs4350.  The output range is from
56650 + * -127.5 dB to 0 dB.
56651 + */
56652 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4350_db, -12750, 50, 0);
56653 +
56654 +#define ubi32_cs4350_mute_info snd_ctl_boolean_stereo_info
56655 +
56656 +/*
56657 + * Private data for cs4350 chip
56658 + */
56659 +struct ubi32_cs4350_priv {
56660 +       /*
56661 +        * The current volume settings
56662 +        */
56663 +       uint8_t volume[2];
56664 +
56665 +       /*
56666 +        * Bitmask of mutes MSB (unused, ..., unused, right_ch, left_ch) LSB
56667 +        */
56668 +       uint8_t mute;
56669 +
56670 +       /*
56671 +        * Lock to protect this struct because callbacks are not atomic.
56672 +        */
56673 +       spinlock_t lock;
56674 +};
56675 +
56676 +/*
56677 + * The info for the cs4350.  The volume currently has one channel,
56678 + * and 255 possible settings.
56679 + */
56680 +static int ubi32_cs4350_volume_info(struct snd_kcontrol *kcontrol,
56681 +                                   struct snd_ctl_elem_info *uinfo)
56682 +{
56683 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
56684 +       uinfo->count = 2;
56685 +       uinfo->value.integer.min = 0;
56686 +       uinfo->value.integer.max = 255; // 8 bits in cirrus logic cs4350 volume register
56687 +       return 0;
56688 +}
56689 +
56690 +static int ubi32_cs4350_volume_get(struct snd_kcontrol *kcontrol,
56691 +                                  struct snd_ctl_elem_value *ucontrol)
56692 +{
56693 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56694 +       struct ubi32_cs4350_priv *cs4350_priv;
56695 +       unsigned long flags;
56696 +
56697 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56698 +
56699 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56700 +
56701 +       ucontrol->value.integer.value[0] = cs4350_priv->volume[0];
56702 +       ucontrol->value.integer.value[1] = cs4350_priv->volume[1];
56703 +
56704 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56705 +
56706 +       return 0;
56707 +}
56708 +
56709 +static int ubi32_cs4350_volume_put(struct snd_kcontrol *kcontrol,
56710 +                                  struct snd_ctl_elem_value *ucontrol)
56711 +{
56712 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56713 +       struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56714 +       struct ubi32_cs4350_priv *cs4350_priv;
56715 +       unsigned long flags;
56716 +       int ret, changed;
56717 +       char send[2];
56718 +       uint8_t volume_reg_value_left, volume_reg_value_right;
56719 +
56720 +       changed = 0;
56721 +
56722 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56723 +       volume_reg_value_left = 255 - (ucontrol->value.integer.value[0] & 0xFF);
56724 +       volume_reg_value_right = 255 - (ucontrol->value.integer.value[1] & 0xFF);
56725 +
56726 +#if SND_UBI32_DEBUG
56727 +       snd_printk(KERN_INFO "Setting volume: writing %d,%d to CS4350 volume registers\n", volume_reg_value_left, volume_reg_value_right);
56728 +#endif
56729 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56730 +
56731 +       if (cs4350_priv->volume[0] != ucontrol->value.integer.value[0]) {
56732 +               send[0] = 0x05; // left channel
56733 +               send[1] = volume_reg_value_left;
56734 +               ret = i2c_master_send(client, send, 2);
56735 +               if (ret != 2) {
56736 +                       snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56737 +                       return changed;
56738 +               }
56739 +               cs4350_priv->volume[0] = ucontrol->value.integer.value[0];
56740 +               changed = 1;
56741 +       }
56742 +
56743 +       if (cs4350_priv->volume[1] != ucontrol->value.integer.value[1]) {
56744 +               send[0] = 0x06; // right channel
56745 +               send[1] = volume_reg_value_right;
56746 +               ret = i2c_master_send(client, send, 2);
56747 +               if (ret != 2) {
56748 +                       snd_printk(KERN_ERR "Failed to set channel B volume on CS4350\n");
56749 +                       return changed;
56750 +               }
56751 +               cs4350_priv->volume[1] = ucontrol->value.integer.value[1];
56752 +               changed = 1;
56753 +       }
56754 +
56755 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56756 +
56757 +       return changed;
56758 +}
56759 +
56760 +static struct snd_kcontrol_new ubi32_cs4350_volume __devinitdata = {
56761 +       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56762 +       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56763 +                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56764 +       .name = "PCM Playback Volume",
56765 +       .info = ubi32_cs4350_volume_info,
56766 +       .get = ubi32_cs4350_volume_get,
56767 +       .put = ubi32_cs4350_volume_put,
56768 +       .tlv.p = snd_ubi32_cs4350_db,
56769 +};
56770 +
56771 +static int ubi32_cs4350_mute_get(struct snd_kcontrol *kcontrol,
56772 +                                struct snd_ctl_elem_value *ucontrol)
56773 +{
56774 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56775 +       struct ubi32_cs4350_priv *cs4350_priv;
56776 +       unsigned long flags;
56777 +
56778 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56779 +
56780 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56781 +
56782 +       ucontrol->value.integer.value[0] = cs4350_priv->mute & 1;
56783 +       ucontrol->value.integer.value[1] = (cs4350_priv->mute & (1 << 1)) ? 1 : 0;
56784 +
56785 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56786 +
56787 +       return 0;
56788 +}
56789 +
56790 +static int ubi32_cs4350_mute_put(struct snd_kcontrol *kcontrol,
56791 +                                struct snd_ctl_elem_value *ucontrol)
56792 +{
56793 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56794 +       struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56795 +       struct ubi32_cs4350_priv *cs4350_priv;
56796 +       unsigned long flags;
56797 +       int ret, changed;
56798 +       char send[2];
56799 +       char recv[1];
56800 +       uint8_t mute;
56801 +
56802 +        changed = 0;
56803 +
56804 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56805 +
56806 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56807 +
56808 +       if ((cs4350_priv->mute & 1) != ucontrol->value.integer.value[0]) {
56809 +               send[0] = 0x04;
56810 +               ret = i2c_master_send(client, send, 1);
56811 +               if (ret != 1) {
56812 +                       snd_printk(KERN_ERR "Failed to write to mute register: channel 0\n");
56813 +                       return changed;
56814 +               }
56815 +
56816 +               ret = i2c_master_recv(client, recv, 1);
56817 +               if (ret != 1) {
56818 +                       snd_printk(KERN_ERR "Failed to read mute register: channel 0\n");
56819 +                       return changed;
56820 +               }
56821 +
56822 +               mute = recv[0];
56823 +
56824 +               if (ucontrol->value.integer.value[0]) {
56825 +                       cs4350_priv->mute |= 1;
56826 +                       mute &= ~(1 << 4);
56827 +#if SND_UBI32_DEBUG
56828 +                       snd_printk(KERN_INFO "Unmuted channel A\n");
56829 +#endif
56830 +               } else {
56831 +                       cs4350_priv->mute &= ~1;
56832 +                       mute |= (1 << 4);
56833 +#if SND_UBI32_DEBUG
56834 +                       snd_printk(KERN_INFO "Muted channel A\n");
56835 +#endif
56836 +               }
56837 +
56838 +               send[0] = 0x04;
56839 +               send[1] = mute;
56840 +               ret = i2c_master_send(client, send, 2);
56841 +               if (ret != 2) {
56842 +                       snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56843 +                       return changed;
56844 +               }
56845 +               changed = 1;
56846 +       }
56847 +
56848 +       if (((cs4350_priv->mute & 2) >> 1) != ucontrol->value.integer.value[1]) {
56849 +               send[0] = 0x04;
56850 +               ret = i2c_master_send(client, send, 1);
56851 +               if (ret != 1) {
56852 +                       snd_printk(KERN_ERR "Failed to write to mute register: channel 1\n");
56853 +                       return changed;
56854 +               }
56855 +
56856 +               ret = i2c_master_recv(client, recv, 1);
56857 +               if (ret != 1) {
56858 +                       snd_printk(KERN_ERR "Failed to read mute register: channel 1\n");
56859 +                       return changed;
56860 +               }
56861 +
56862 +               mute = recv[0];
56863 +
56864 +               if (ucontrol->value.integer.value[1]) {
56865 +                       cs4350_priv->mute |= (1 << 1);
56866 +                       mute &= ~(1 << 3);
56867 +#if SND_UBI32_DEBUG
56868 +                       snd_printk(KERN_INFO "Unmuted channel B\n");
56869 +#endif
56870 +               } else {
56871 +                       cs4350_priv->mute &= ~(1 << 1);
56872 +                       mute |= (1 << 3);
56873 +#if SND_UBI32_DEBUG
56874 +                       snd_printk(KERN_INFO "Muted channel B\n");
56875 +#endif
56876 +               }
56877 +
56878 +               send[0] = 0x04;
56879 +               send[1] = mute;
56880 +               ret = i2c_master_send(client, send, 2);
56881 +               if (ret != 2) {
56882 +                       snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56883 +                       return changed;
56884 +               }
56885 +               changed = 1;
56886 +       }
56887 +
56888 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56889 +
56890 +       return changed;
56891 +}
56892 +
56893 +static struct snd_kcontrol_new ubi32_cs4350_mute __devinitdata = {
56894 +       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56895 +       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
56896 +       .name = "PCM Playback Switch",
56897 +       .info = ubi32_cs4350_mute_info,
56898 +       .get = ubi32_cs4350_mute_get,
56899 +       .put = ubi32_cs4350_mute_put,
56900 +};
56901 +
56902 +/*
56903 + * snd_ubi32_cs4350_free
56904 + *     Card private data free function
56905 + */
56906 +void snd_ubi32_cs4350_free(struct snd_card *card)
56907 +{
56908 +       struct ubi32_snd_priv *ubi32_priv;
56909 +       struct ubi32_cs4350_priv *cs4350_priv;
56910 +
56911 +       ubi32_priv = card->private_data;
56912 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56913 +       if (cs4350_priv) {
56914 +               kfree(cs4350_priv);
56915 +       }
56916 +}
56917 +
56918 +/*
56919 + * snd_ubi32_cs4350_dac_init
56920 + */
56921 +static int snd_ubi32_cs4350_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
56922 +{
56923 +       int ret;
56924 +       char send[2];
56925 +       char recv[8];
56926 +
56927 +       /*
56928 +        * Initialize the CS4350 DAC over the I2C interface
56929 +        */
56930 +       snd_printk(KERN_INFO "Initializing CS4350 DAC\n");
56931 +
56932 +       /*
56933 +        * Register 0x01: device/revid
56934 +        */
56935 +       send[0] = 0x01;
56936 +       ret = i2c_master_send(client, send, 1);
56937 +       if (ret != 1) {
56938 +               snd_printk(KERN_ERR "Failed 1st attempt to write to CS4350 register 0x01\n");
56939 +               goto fail;
56940 +       }
56941 +       ret = i2c_master_recv(client, recv, 1);
56942 +       if (ret != 1) {
56943 +               snd_printk(KERN_ERR "Failed initial read of CS4350 registers\n");
56944 +               goto fail;
56945 +       }
56946 +       snd_printk(KERN_INFO "CS4350 DAC Device/Rev: %08x\n", recv[0]);
56947 +
56948 +       /*
56949 +        * Register 0x02: Mode control
56950 +        *      I2S DIF[2:0] = 001, no De-Emphasis, Auto speed mode
56951 +        */
56952 +       send[0] = 0x02;
56953 +       send[1] = 0x10;
56954 +       ret = i2c_master_send(client, send, 2);
56955 +       if (ret != 2) {
56956 +               snd_printk(KERN_ERR "Failed to set CS4350 to I2S mode\n");
56957 +               goto fail;
56958 +       }
56959 +
56960 +       /*
56961 +        * Register 0x05/0x06: Volume control
56962 +        *      Channel A volume set to 0 dB
56963 +        *      Channel B volume set to 0 dB
56964 +        */
56965 +       send[0] = 0x05;
56966 +       send[1] = 0x00;
56967 +       ret = i2c_master_send(client, send, 2);
56968 +       if (ret != 2) {
56969 +               snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56970 +               goto fail;
56971 +       }
56972 +
56973 +       send[0] = 0x06;
56974 +       send[1] = 0x00;
56975 +       ret = i2c_master_send(client, send, 2);
56976 +       if (ret != 2) {
56977 +               snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56978 +               goto fail;
56979 +       }
56980 +
56981 +       /*
56982 +        * Make sure the changes took place, this helps verify we are talking to
56983 +        * the correct chip.
56984 +        */
56985 +       send[0] = 0x81;
56986 +       ret = i2c_master_send(client, send, 1);
56987 +       if (ret != 1) {
56988 +               snd_printk(KERN_ERR "Failed to initiate readback\n");
56989 +               goto fail;
56990 +       }
56991 +
56992 +       ret = i2c_master_recv(client, recv, 8);
56993 +       if (ret != 8) {
56994 +               snd_printk(KERN_ERR "Failed second read of CS4350 registers\n");
56995 +               goto fail;
56996 +       }
56997 +
56998 +       if ((recv[1] != 0x10) || (recv[4] != 0x00) || (recv[5] != 0x00)) {
56999 +               snd_printk(KERN_ERR "Failed to initialize CS4350 DAC\n");
57000 +               goto fail;
57001 +       }
57002 +
57003 +       snd_printk(KERN_INFO "CS4350 DAC Initialized\n");
57004 +       return 0;
57005 +
57006 +fail:
57007 +       return -ENODEV;
57008 +}
57009 +
57010 +/*
57011 + * snd_ubi32_cs4350_i2c_probe
57012 + */
57013 +static int snd_ubi32_cs4350_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
57014 +{
57015 +       struct snd_card *card;
57016 +       struct ubi32_snd_priv *ubi32_priv;
57017 +       struct ubi32_cs4350_priv *cs4350_priv;
57018 +       int err, ret;
57019 +       struct platform_device *pdev;
57020 +
57021 +       pdev = client->dev.platform_data;
57022 +       if (!pdev) {
57023 +               return -ENODEV;
57024 +       }
57025 +
57026 +       /*
57027 +        * Initialize the CS4350 DAC
57028 +        */
57029 +       ret = snd_ubi32_cs4350_dac_init(client, id);
57030 +       if (ret < 0) {
57031 +               /*
57032 +                * Initialization failed.  Propagate the error.
57033 +                */
57034 +               return ret;
57035 +       }
57036 +
57037 +       /*
57038 +        * Create a snd_card structure
57039 +        */
57040 +       card = snd_card_new(index, "Ubi32-CS4350", THIS_MODULE, sizeof(struct ubi32_snd_priv));
57041 +       if (card == NULL) {
57042 +               return -ENOMEM;
57043 +       }
57044 +
57045 +       card->private_free = snd_ubi32_cs4350_free; /* Not sure if correct */
57046 +       ubi32_priv = card->private_data;
57047 +
57048 +       /*
57049 +        * CS4350 DAC has a minimum sample rate of 30khz and an
57050 +        * upper limit of 216khz for it's auto-detect.
57051 +        */
57052 +       ubi32_priv->min_sample_rate = 30000;
57053 +       ubi32_priv->max_sample_rate = 216000;
57054 +
57055 +       /*
57056 +        * Initialize the snd_card's private data structure
57057 +        */
57058 +       ubi32_priv->card = card;
57059 +       ubi32_priv->client = client;
57060 +
57061 +       /*
57062 +        * Create our private data structure
57063 +        */
57064 +       cs4350_priv = kzalloc(sizeof(struct ubi32_cs4350_priv), GFP_KERNEL);
57065 +       if (!cs4350_priv) {
57066 +               snd_card_free(card);
57067 +               return -ENOMEM;
57068 +       }
57069 +       snd_ubi32_priv_set_drv(ubi32_priv, cs4350_priv);
57070 +       spin_lock_init(&cs4350_priv->lock);
57071 +
57072 +       /*
57073 +        * Initial volume is set to max by probe function
57074 +        */
57075 +       cs4350_priv->volume[0] = 0xFF;
57076 +       cs4350_priv->volume[1] = 0xFF;
57077 +
57078 +       /*
57079 +        * The CS4350 starts off unmuted (bit set = not muted)
57080 +        */
57081 +       cs4350_priv->mute = 3;
57082 +
57083 +       /*
57084 +        * Create the new PCM instance
57085 +        */
57086 +       err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
57087 +       if (err < 0) {
57088 +               snd_card_free(card);
57089 +               return err; /* What is err?  Need to include correct file */
57090 +       }
57091 +
57092 +       strcpy(card->driver, "Ubi32-CS4350");
57093 +       strcpy(card->shortname, "Ubi32-CS4350");
57094 +       snprintf(card->longname, sizeof(card->longname),
57095 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
57096 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
57097 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
57098 +
57099 +       snd_card_set_dev(card, &client->dev);
57100 +
57101 +       /*
57102 +        * Set up the mixer components
57103 +        */
57104 +       err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_volume, ubi32_priv));
57105 +       if (err) {
57106 +               snd_printk(KERN_WARNING "Failed to add volume mixer control\n");
57107 +       }
57108 +       err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_mute, ubi32_priv));
57109 +       if (err) {
57110 +               snd_printk(KERN_WARNING "Failed to add mute mixer control\n");
57111 +       }
57112 +
57113 +       /*
57114 +        * Register the sound card
57115 +        */
57116 +       if ((err = snd_card_register(card)) != 0) {
57117 +               snd_printk(KERN_WARNING "snd_card_register error\n");
57118 +       }
57119 +
57120 +       /*
57121 +        * Store card for access from other methods
57122 +        */
57123 +       i2c_set_clientdata(client, card);
57124 +
57125 +       return 0;
57126 +}
57127 +
57128 +/*
57129 + * snd_ubi32_cs4350_i2c_remove
57130 + */
57131 +static int __devexit snd_ubi32_cs4350_i2c_remove(struct i2c_client *client)
57132 +{
57133 +       struct snd_card *card;
57134 +       struct ubi32_snd_priv *ubi32_priv;
57135 +
57136 +       card = i2c_get_clientdata(client);
57137 +
57138 +       ubi32_priv = card->private_data;
57139 +       snd_ubi32_pcm_remove(ubi32_priv);
57140 +
57141 +       snd_card_free(i2c_get_clientdata(client));
57142 +       i2c_set_clientdata(client, NULL);
57143 +
57144 +       return 0;
57145 +}
57146 +
57147 +/*
57148 + * I2C driver description
57149 + */
57150 +static struct i2c_driver snd_ubi32_cs4350_driver = {
57151 +       .driver = {
57152 +               .name = DRIVER_NAME,
57153 +               .owner = THIS_MODULE,
57154 +       },
57155 +       .id_table       = snd_ubi32_cs4350_id,
57156 +       .probe          = snd_ubi32_cs4350_i2c_probe,
57157 +       .remove         = __devexit_p(snd_ubi32_cs4350_i2c_remove),
57158 +};
57159 +
57160 +/*
57161 + * Driver init
57162 + */
57163 +static int __init snd_ubi32_cs4350_init(void)
57164 +{
57165 +       return i2c_add_driver(&snd_ubi32_cs4350_driver);
57166 +}
57167 +module_init(snd_ubi32_cs4350_init);
57168 +
57169 +/*
57170 + * snd_ubi32_cs4350_exit
57171 + */
57172 +static void __exit snd_ubi32_cs4350_exit(void)
57173 +{
57174 +       i2c_del_driver(&snd_ubi32_cs4350_driver);
57175 +}
57176 +module_exit(snd_ubi32_cs4350_exit);
57177 +
57178 +/*
57179 + * Module properties
57180 + */
57181 +MODULE_ALIAS("i2c:" DRIVER_NAME);
57182 +MODULE_AUTHOR("Patrick Tjin");
57183 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4350");
57184 +MODULE_LICENSE("GPL");
57185 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-cs4384.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4384.c
57186 --- linux-2.6.30.10/sound/ubicom32/ubi32-cs4384.c       1970-01-01 02:00:00.000000000 +0200
57187 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4384.c   2009-12-11 11:45:25.000000000 +0200
57188 @@ -0,0 +1,996 @@
57189 +/*
57190 + * sound/ubicom32/ubi32-cs4384.c
57191 + *     Interface to ubicom32 virtual audio peripheral - using CS4384 DAC
57192 + *
57193 + * (C) Copyright 2009, Ubicom, Inc.
57194 + *
57195 + * This file is part of the Ubicom32 Linux Kernel Port.
57196 + *
57197 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
57198 + * it and/or modify it under the terms of the GNU General Public License
57199 + * as published by the Free Software Foundation, either version 2 of the
57200 + * License, or (at your option) any later version.
57201 + *
57202 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
57203 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
57204 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
57205 + * the GNU General Public License for more details.
57206 + *
57207 + * You should have received a copy of the GNU General Public License
57208 + * along with the Ubicom32 Linux Kernel Port.  If not,
57209 + * see <http://www.gnu.org/licenses/>.
57210 + */
57211 +
57212 +#include <linux/i2c.h>
57213 +#include <linux/module.h>
57214 +#include <linux/moduleparam.h>
57215 +#include <linux/delay.h>
57216 +#include <sound/core.h>
57217 +#include <sound/tlv.h>
57218 +#include <sound/control.h>
57219 +#include <sound/pcm.h>
57220 +#include <sound/initval.h>
57221 +#include <asm/ip5000.h>
57222 +#include <asm/gpio.h>
57223 +#include <asm/audio.h>
57224 +#include <asm/ubi32-cs4384.h>
57225 +#include "ubi32.h"
57226 +
57227 +#define DRIVER_NAME "snd-ubi32-cs4384"
57228 +
57229 +/*
57230 + * Module properties
57231 + */
57232 +static const struct i2c_device_id snd_ubi32_cs4384_id[] = {
57233 +       {"cs4384", 0 },
57234 +       { }
57235 +};
57236 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
57237 +
57238 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
57239 +
57240 +/*
57241 + * Mixer properties
57242 + */
57243 +enum {
57244 +       /*
57245 +        * Be careful of changing the order of these IDs, they
57246 +        * are used to index the volume array.
57247 +        */
57248 +       SND_UBI32_CS4384_FRONT_ID,
57249 +       SND_UBI32_CS4384_SURROUND_ID,
57250 +       SND_UBI32_CS4384_CENTER_ID,
57251 +       SND_UBI32_CS4384_LFE_ID,
57252 +       SND_UBI32_CS4384_REAR_ID,
57253 +
57254 +       /*
57255 +        * This should be the last ID
57256 +        */
57257 +       SND_UBI32_CS4384_LAST_ID,
57258 +};
57259 +static const u8_t snd_ubi32_cs4384_ch_ofs[] = {0, 2, 4, 5, 6};
57260 +
57261 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4384_db, -12750, 50, 0);
57262 +
57263 +#define snd_ubi32_cs4384_info_mute     snd_ctl_boolean_stereo_info
57264 +#define snd_ubi32_cs4384_info_mute_mono        snd_ctl_boolean_mono_info
57265 +
57266 +/*
57267 + * Mixer controls
57268 + */
57269 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
57270 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57271 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57272 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57273 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57274 +
57275 +/*
57276 + * Make sure to update these if the structure below is changed
57277 + */
57278 +#define SND_UBI32_MUTE_CTL_START       5
57279 +#define SND_UBI32_MUTE_CTL_END         9
57280 +static struct snd_kcontrol_new snd_ubi32_cs4384_controls[] __devinitdata = {
57281 +       {
57282 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57283 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57284 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57285 +               .name = "Front Playback Volume",
57286 +               .info = snd_ubi32_cs4384_info_volume,
57287 +               .get = snd_ubi32_cs4384_get_volume,
57288 +               .put = snd_ubi32_cs4384_put_volume,
57289 +               .private_value = SND_UBI32_CS4384_FRONT_ID,
57290 +               .tlv = {
57291 +                       .p = snd_ubi32_cs4384_db,
57292 +               },
57293 +       },
57294 +       {
57295 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57296 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57297 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57298 +               .name = "Surround Playback Volume",
57299 +               .info = snd_ubi32_cs4384_info_volume,
57300 +               .get = snd_ubi32_cs4384_get_volume,
57301 +               .put = snd_ubi32_cs4384_put_volume,
57302 +               .private_value = SND_UBI32_CS4384_SURROUND_ID,
57303 +               .tlv = {
57304 +                       .p = snd_ubi32_cs4384_db,
57305 +               },
57306 +       },
57307 +       {
57308 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57309 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57310 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57311 +               .name = "Center Playback Volume",
57312 +               .info = snd_ubi32_cs4384_info_volume,
57313 +               .get = snd_ubi32_cs4384_get_volume,
57314 +               .put = snd_ubi32_cs4384_put_volume,
57315 +               .private_value = SND_UBI32_CS4384_CENTER_ID,
57316 +               .tlv = {
57317 +                       .p = snd_ubi32_cs4384_db,
57318 +               },
57319 +       },
57320 +       {
57321 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57322 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57323 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57324 +               .name = "LFE Playback Volume",
57325 +               .info = snd_ubi32_cs4384_info_volume,
57326 +               .get = snd_ubi32_cs4384_get_volume,
57327 +               .put = snd_ubi32_cs4384_put_volume,
57328 +               .private_value = SND_UBI32_CS4384_LFE_ID,
57329 +               .tlv = {
57330 +                       .p = snd_ubi32_cs4384_db,
57331 +               },
57332 +       },
57333 +       {
57334 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57335 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57336 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57337 +               .name = "Rear Playback Volume",
57338 +               .info = snd_ubi32_cs4384_info_volume,
57339 +               .get = snd_ubi32_cs4384_get_volume,
57340 +               .put = snd_ubi32_cs4384_put_volume,
57341 +               .private_value = SND_UBI32_CS4384_REAR_ID,
57342 +               .tlv = {
57343 +                       .p = snd_ubi32_cs4384_db,
57344 +               },
57345 +       },
57346 +       {
57347 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57348 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57349 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57350 +               .name = "Front Playback Switch",
57351 +               .info = snd_ubi32_cs4384_info_mute,
57352 +               .get = snd_ubi32_cs4384_get_mute,
57353 +               .put = snd_ubi32_cs4384_put_mute,
57354 +               .private_value = SND_UBI32_CS4384_FRONT_ID,
57355 +       },
57356 +       {
57357 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57358 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57359 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57360 +               .name = "Surround Playback Switch",
57361 +               .info = snd_ubi32_cs4384_info_mute,
57362 +               .get = snd_ubi32_cs4384_get_mute,
57363 +               .put = snd_ubi32_cs4384_put_mute,
57364 +               .private_value = SND_UBI32_CS4384_SURROUND_ID,
57365 +       },
57366 +       {
57367 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57368 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57369 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57370 +               .name = "Center Playback Switch",
57371 +               .info = snd_ubi32_cs4384_info_mute_mono,
57372 +               .get = snd_ubi32_cs4384_get_mute,
57373 +               .put = snd_ubi32_cs4384_put_mute,
57374 +               .private_value = SND_UBI32_CS4384_CENTER_ID,
57375 +       },
57376 +       {
57377 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57378 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57379 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57380 +               .name = "LFE Playback Switch",
57381 +               .info = snd_ubi32_cs4384_info_mute_mono,
57382 +               .get = snd_ubi32_cs4384_get_mute,
57383 +               .put = snd_ubi32_cs4384_put_mute,
57384 +               .private_value = SND_UBI32_CS4384_LFE_ID,
57385 +       },
57386 +       {
57387 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57388 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57389 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57390 +               .name = "Rear Playback Switch",
57391 +               .info = snd_ubi32_cs4384_info_mute,
57392 +               .get = snd_ubi32_cs4384_get_mute,
57393 +               .put = snd_ubi32_cs4384_put_mute,
57394 +               .private_value = SND_UBI32_CS4384_REAR_ID,
57395 +       },
57396 +};
57397 +
57398 +/*
57399 + * Our private data
57400 + */
57401 +struct snd_ubi32_cs4384_priv {
57402 +       /*
57403 +        * Array of current volumes
57404 +        *      (L, R, SL, SR, C, LFE, RL, RR)
57405 +        */
57406 +       uint8_t volume[8];
57407 +
57408 +       /*
57409 +        * Bitmask of mutes
57410 +        *      MSB (RR, RL, LFE, C, SR, SL, R, L) LSB
57411 +        */
57412 +       uint8_t mute;
57413 +
57414 +       /*
57415 +        * Array of controls
57416 +        */
57417 +       struct snd_kcontrol *kctls[ARRAY_SIZE(snd_ubi32_cs4384_controls)];
57418 +
57419 +       /*
57420 +        * Lock to protect our card
57421 +        */
57422 +       spinlock_t lock;
57423 +};
57424 +
57425 +/*
57426 + * snd_ubi32_cs4384_info_volume
57427 + */
57428 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
57429 +{
57430 +       unsigned int id = (unsigned int)kcontrol->private_value;
57431 +
57432 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
57433 +       uinfo->count = 1;
57434 +       if ((id != SND_UBI32_CS4384_LFE_ID) &&
57435 +           (id != SND_UBI32_CS4384_CENTER_ID)) {
57436 +               uinfo->count = 2;
57437 +       }
57438 +       uinfo->value.integer.min = 0;
57439 +       uinfo->value.integer.max = 255;
57440 +       return 0;
57441 +}
57442 +
57443 +/*
57444 + * snd_ubi32_cs4384_get_volume
57445 + */
57446 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57447 +{
57448 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57449 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57450 +       unsigned int id = (unsigned int)kcontrol->private_value;
57451 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57452 +       unsigned long flags;
57453 +
57454 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57455 +               return -EINVAL;
57456 +       }
57457 +
57458 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57459 +
57460 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57461 +
57462 +       ucontrol->value.integer.value[0] = cs4384_priv->volume[ch];
57463 +       if ((id != SND_UBI32_CS4384_LFE_ID) &&
57464 +           (id != SND_UBI32_CS4384_CENTER_ID)) {
57465 +               ch++;
57466 +               ucontrol->value.integer.value[1] = cs4384_priv->volume[ch];
57467 +       }
57468 +
57469 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57470 +
57471 +       return 0;
57472 +}
57473 +
57474 +/*
57475 + * snd_ubi32_cs4384_put_volume
57476 + */
57477 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57478 +{
57479 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57480 +       struct i2c_client *client = (struct i2c_client *)priv->client;
57481 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57482 +       unsigned int id = (unsigned int)kcontrol->private_value;
57483 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57484 +       unsigned long flags;
57485 +       unsigned char send[3];
57486 +       int nch;
57487 +       int ret = -EINVAL;
57488 +
57489 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57490 +               return -EINVAL;
57491 +       }
57492 +
57493 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57494 +
57495 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57496 +
57497 +       send[0] = 0;
57498 +       switch (id) {
57499 +       case SND_UBI32_CS4384_REAR_ID:
57500 +               send[0] = 0x06;
57501 +
57502 +               /*
57503 +                * Fall through
57504 +                */
57505 +
57506 +       case SND_UBI32_CS4384_SURROUND_ID:
57507 +               send[0] += 0x03;
57508 +
57509 +               /*
57510 +                * Fall through
57511 +                */
57512 +
57513 +       case SND_UBI32_CS4384_FRONT_ID:
57514 +               send[0] += 0x8B;
57515 +               nch = 2;
57516 +               send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57517 +               send[2] = 255 - (ucontrol->value.integer.value[1] & 0xFF);
57518 +               cs4384_priv->volume[ch++] = send[1];
57519 +               cs4384_priv->volume[ch] = send[2];
57520 +               break;
57521 +
57522 +       case SND_UBI32_CS4384_LFE_ID:
57523 +               send[0] = 0x81;
57524 +
57525 +               /*
57526 +                * Fall through
57527 +                */
57528 +
57529 +       case SND_UBI32_CS4384_CENTER_ID:
57530 +               send[0] += 0x11;
57531 +               nch = 1;
57532 +               send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57533 +               cs4384_priv->volume[ch] = send[1];
57534 +               break;
57535 +
57536 +       default:
57537 +               spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57538 +               goto done;
57539 +
57540 +       }
57541 +
57542 +       /*
57543 +        * Send the volume to the chip
57544 +        */
57545 +       nch++;
57546 +       ret = i2c_master_send(client, send, nch);
57547 +       if (ret != nch) {
57548 +               snd_printk(KERN_ERR "Failed to set volume on CS4384\n");
57549 +       }
57550 +
57551 +done:
57552 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57553 +
57554 +       return ret;
57555 +}
57556 +
57557 +/*
57558 + * snd_ubi32_cs4384_get_mute
57559 + */
57560 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57561 +{
57562 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57563 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57564 +       unsigned int id = (unsigned int)kcontrol->private_value;
57565 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57566 +       unsigned long flags;
57567 +
57568 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57569 +               return -EINVAL;
57570 +       }
57571 +
57572 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57573 +
57574 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57575 +
57576 +       ucontrol->value.integer.value[0] = !(cs4384_priv->mute & (1 << ch));
57577 +
57578 +       if ((id != SND_UBI32_CS4384_LFE_ID) &&
57579 +           (id != SND_UBI32_CS4384_CENTER_ID)) {
57580 +               ch++;
57581 +               ucontrol->value.integer.value[1] = !(cs4384_priv->mute & (1 << ch));
57582 +       }
57583 +
57584 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57585 +
57586 +       return 0;
57587 +}
57588 +
57589 +/*
57590 + * snd_ubi32_cs4384_put_mute
57591 + */
57592 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57593 +{
57594 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57595 +       struct i2c_client *client = (struct i2c_client *)priv->client;
57596 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57597 +       unsigned int id = (unsigned int)kcontrol->private_value;
57598 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57599 +       unsigned long flags;
57600 +       unsigned char send[2];
57601 +       int ret = -EINVAL;
57602 +
57603 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57604 +               return -EINVAL;
57605 +       }
57606 +
57607 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57608 +
57609 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57610 +
57611 +       if (ucontrol->value.integer.value[0]) {
57612 +               cs4384_priv->mute &= ~(1 << ch);
57613 +       } else {
57614 +               cs4384_priv->mute |= (1 << ch);
57615 +       }
57616 +
57617 +       if ((id != SND_UBI32_CS4384_LFE_ID) && (id != SND_UBI32_CS4384_CENTER_ID)) {
57618 +               ch++;
57619 +               if (ucontrol->value.integer.value[1]) {
57620 +                       cs4384_priv->mute &= ~(1 << ch);
57621 +               } else {
57622 +                       cs4384_priv->mute |= (1 << ch);
57623 +               }
57624 +       }
57625 +
57626 +       /*
57627 +        * Update the chip's mute reigster
57628 +        */
57629 +       send[0] = 0x09;
57630 +       send[1] = cs4384_priv->mute;
57631 +       ret = i2c_master_send(client, send, 2);
57632 +       if (ret != 2) {
57633 +               snd_printk(KERN_ERR "Failed to set mute on CS4384\n");
57634 +       }
57635 +
57636 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57637 +
57638 +       return ret;
57639 +}
57640 +
57641 +/*
57642 + * snd_ubi32_cs4384_mixer
57643 + *     Setup the mixer controls
57644 + */
57645 +static int __devinit snd_ubi32_cs4384_mixer(struct ubi32_snd_priv *priv)
57646 +{
57647 +       struct snd_card *card = priv->card;
57648 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57649 +       int i;
57650 +
57651 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57652 +       for (i = 0; i < ARRAY_SIZE(snd_ubi32_cs4384_controls); i++) {
57653 +               int err;
57654 +
57655 +               cs4384_priv->kctls[i] = snd_ctl_new1(&snd_ubi32_cs4384_controls[i], priv);
57656 +               err = snd_ctl_add(card, cs4384_priv->kctls[i]);
57657 +               if (err) {
57658 +                       snd_printk(KERN_WARNING "Failed to add control %d\n", i);
57659 +                       return err;
57660 +               }
57661 +       }
57662 +       return 0;
57663 +}
57664 +
57665 +/*
57666 + * snd_ubi32_cs4384_free
57667 + *     Card private data free function
57668 + */
57669 +void snd_ubi32_cs4384_free(struct snd_card *card)
57670 +{
57671 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57672 +       struct ubi32_snd_priv *ubi32_priv;
57673 +
57674 +       ubi32_priv = card->private_data;
57675 +       cs4384_priv = snd_ubi32_priv_get_drv(ubi32_priv);
57676 +       if (cs4384_priv) {
57677 +               kfree(cs4384_priv);
57678 +       }
57679 +}
57680 +
57681 +/*
57682 + * snd_ubi32_cs4384_setup_mclk
57683 + */
57684 +static int snd_ubi32_cs4384_setup_mclk(struct ubi32_cs4384_platform_data *pdata)
57685 +{
57686 +       struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57687 +       struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57688 +       struct ubicom32_io_port *iod = (struct ubicom32_io_port *)RD;
57689 +       struct ubicom32_io_port *ioe = (struct ubicom32_io_port *)RE;
57690 +       struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57691 +       unsigned int ctl0;
57692 +       unsigned int ctlx;
57693 +       unsigned int div;
57694 +
57695 +       div = pdata->mclk_entries[0].div;
57696 +
57697 +       ctl0 = (1 << 13);
57698 +       ctlx = ((div - 1) << 16) | (div / 2);
57699 +
57700 +       switch (pdata->mclk_src) {
57701 +       case UBI32_CS4384_MCLK_PWM_0:
57702 +               ioc->function |= 2;
57703 +               ioc->ctl0 |= ctl0;
57704 +               ioc->ctl1 = ctlx;
57705 +               if (!ioa->function) {
57706 +                       ioa->function = 3;
57707 +               }
57708 +               return 0;
57709 +
57710 +       case UBI32_CS4384_MCLK_PWM_1:
57711 +               ioc->function |= 2;
57712 +               ioc->ctl0 |= ctl0 << 16;
57713 +               ioc->ctl2 = ctlx;
57714 +               if (!ioe->function) {
57715 +                       ioe->function = 3;
57716 +               }
57717 +               return 0;
57718 +
57719 +       case UBI32_CS4384_MCLK_PWM_2:
57720 +               ioh->ctl0 |= ctl0;
57721 +               ioh->ctl1 = ctlx;
57722 +               if (!iod->function) {
57723 +                       iod->function = 3;
57724 +               }
57725 +               return 0;
57726 +
57727 +       case UBI32_CS4384_MCLK_CLKDIV_1:
57728 +               ioa->gpio_mask &= (1 << 7);
57729 +               ioa->ctl1 &= ~(0x7F << 14);
57730 +               ioa->ctl1 |= ((div - 1) << 14);
57731 +               return 0;
57732 +
57733 +       case UBI32_CS4384_MCLK_OTHER:
57734 +               return 0;
57735 +       }
57736 +
57737 +       return 1;
57738 +}
57739 +
57740 +/*
57741 + * snd_ubi32_cs4384_set_rate
57742 + */
57743 +static int snd_ubi32_cs4384_set_rate(struct ubi32_snd_priv *priv, int rate)
57744 +{
57745 +       struct ubi32_cs4384_platform_data *cpd = priv->pdata->priv_data;
57746 +       struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57747 +       struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57748 +       struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57749 +       unsigned int ctl;
57750 +       unsigned int div = 0;
57751 +       const u16_t mult[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024};
57752 +       int i;
57753 +       int j;
57754 +
57755 +
57756 +       for (i = 0; i < sizeof(mult) / sizeof(u16_t); i++) {
57757 +               for (j = 0; j < cpd->n_mclk; j++) {
57758 +                       if (((unsigned int)rate * (unsigned int)mult[i]) ==
57759 +                            cpd->mclk_entries[j].rate) {
57760 +                               div = cpd->mclk_entries[j].div;
57761 +                               break;
57762 +                       }
57763 +               }
57764 +       }
57765 +
57766 +       ctl = ((div - 1) << 16) | (div / 2);
57767 +
57768 +       switch (cpd->mclk_src) {
57769 +       case UBI32_CS4384_MCLK_PWM_0:
57770 +               ioc->ctl1 = ctl;
57771 +               return 0;
57772 +
57773 +       case UBI32_CS4384_MCLK_PWM_1:
57774 +               ioc->ctl2 = ctl;
57775 +               return 0;
57776 +
57777 +       case UBI32_CS4384_MCLK_PWM_2:
57778 +               ioh->ctl1 = ctl;
57779 +               return 0;
57780 +
57781 +       case UBI32_CS4384_MCLK_CLKDIV_1:
57782 +               ioa->ctl1 &= ~(0x7F << 14);
57783 +               ioa->ctl1 |= ((div - 1) << 14);
57784 +               return 0;
57785 +
57786 +       case UBI32_CS4384_MCLK_OTHER:
57787 +               return 0;
57788 +       }
57789 +
57790 +       return 1;
57791 +}
57792 +
57793 +/*
57794 + * snd_ubi32_cs4384_set_channels
57795 + *     Mute unused channels
57796 + */
57797 +static int snd_ubi32_cs4384_set_channels(struct ubi32_snd_priv *priv, int channels)
57798 +{
57799 +       struct i2c_client *client = (struct i2c_client *)priv->client;
57800 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57801 +       unsigned char send[2];
57802 +       int ret;
57803 +       int i;
57804 +       unsigned long flags;
57805 +
57806 +       /*
57807 +        * Only support 0, 2, 4, 6, 8 channels
57808 +        */
57809 +       if ((channels > 8) || (channels & 1)) {
57810 +               return -EINVAL;
57811 +       }
57812 +
57813 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57814 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57815 +
57816 +       /*
57817 +        * Address 09h, Mute control
57818 +        */
57819 +       send[0] = 0x09;
57820 +       send[1] = (unsigned char)(0xFF << channels);
57821 +
57822 +       ret = i2c_master_send(client, send, 2);
57823 +
57824 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57825 +
57826 +       /*
57827 +        * Notify the system that we changed the mutes
57828 +        */
57829 +       cs4384_priv->mute = (unsigned char)(0xFF << channels);
57830 +
57831 +       for (i = SND_UBI32_MUTE_CTL_START; i < SND_UBI32_MUTE_CTL_END; i++) {
57832 +               snd_ctl_notify(priv->card, SNDRV_CTL_EVENT_MASK_VALUE,
57833 +                              &cs4384_priv->kctls[i]->id);
57834 +       }
57835 +
57836 +       if (ret != 2) {
57837 +               return -ENXIO;
57838 +       }
57839 +
57840 +       return 0;
57841 +}
57842 +
57843 +/*
57844 + * snd_ubi32_cs4384_dac_init
57845 + */
57846 +static int snd_ubi32_cs4384_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
57847 +{
57848 +       int ret;
57849 +       unsigned char send[2];
57850 +       unsigned char recv[2];
57851 +
57852 +       /*
57853 +        * Initialize the CS4384 DAC over the I2C interface
57854 +        */
57855 +       snd_printk(KERN_INFO "Initializing CS4384 DAC\n");
57856 +
57857 +       /*
57858 +        * Register 0x01: device/revid
57859 +        */
57860 +       send[0] = 0x01;
57861 +       ret = i2c_master_send(client, send, 1);
57862 +       if (ret != 1) {
57863 +               snd_printk(KERN_ERR "Failed 1st attempt to write to CS4384 register 0x01\n");
57864 +               goto fail;
57865 +       }
57866 +       ret = i2c_master_recv(client, recv, 1);
57867 +       if (ret != 1) {
57868 +               snd_printk(KERN_ERR "Failed initial read of CS4384 registers\n");
57869 +               goto fail;
57870 +       }
57871 +       snd_printk(KERN_INFO "CS4384 DAC Device/Rev: %08x\n", recv[0]);
57872 +
57873 +       /*
57874 +        * Register 0x02: Mode Control 1
57875 +        *      Control Port Enable, PCM, All DACs enabled, Power Down
57876 +        */
57877 +       send[0] = 0x02;
57878 +       send[1] = 0x81;
57879 +       ret = i2c_master_send(client, send, 2);
57880 +       if (ret != 2) {
57881 +               snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57882 +               goto fail;
57883 +       }
57884 +
57885 +       /*
57886 +        * Register 0x08: Ramp and Mute
57887 +        *      RMP_UP, RMP_DN, PAMUTE, DAMUTE
57888 +        */
57889 +       send[0] = 0x08;
57890 +       send[1] = 0xBC;
57891 +       ret = i2c_master_send(client, send, 2);
57892 +       if (ret != 2) {
57893 +               snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57894 +               goto fail;
57895 +       }
57896 +
57897 +       /*
57898 +        * Register 0x03: PCM Control
57899 +        *      I2S DIF[3:0] = 0001, no De-Emphasis, Auto speed mode
57900 +        */
57901 +       send[0] = 0x03;
57902 +       send[1] = 0x13;
57903 +       ret = i2c_master_send(client, send, 2);
57904 +       if (ret != 2) {
57905 +               snd_printk(KERN_ERR "Failed to set CS4384 to I2S mode\n");
57906 +               goto fail;
57907 +       }
57908 +
57909 +       /*
57910 +        * Register 0x0B/0x0C: Volume control A1/B1
57911 +        * Register 0x0E/0x0F: Volume control A2/B2
57912 +        * Register 0x11/0x12: Volume control A3/B3
57913 +        * Register 0x14/0x15: Volume control A4/B4
57914 +        */
57915 +       send[0] = 0x80 | 0x0B;
57916 +       send[1] = 0x00;
57917 +       send[2] = 0x00;
57918 +       ret = i2c_master_send(client, send, 3);
57919 +       if (ret != 3) {
57920 +               snd_printk(KERN_ERR "Failed to set ch1 volume on CS4384\n");
57921 +               goto fail;
57922 +       }
57923 +
57924 +       send[0] = 0x80 | 0x0E;
57925 +       send[1] = 0x00;
57926 +       send[2] = 0x00;
57927 +       ret = i2c_master_send(client, send, 3);
57928 +       if (ret != 3) {
57929 +               snd_printk(KERN_ERR "Failed to set ch2 volume on CS4384\n");
57930 +               goto fail;
57931 +       }
57932 +
57933 +       send[0] = 0x80 | 0x11;
57934 +       send[1] = 0x00;
57935 +       send[2] = 0x00;
57936 +       ret = i2c_master_send(client, send, 3);
57937 +       if (ret != 3) {
57938 +               snd_printk(KERN_ERR "Failed to set ch3 volume on CS4384\n");
57939 +               goto fail;
57940 +       }
57941 +
57942 +       send[0] = 0x80 | 0x14;
57943 +       send[1] = 0x00;
57944 +       send[2] = 0x00;
57945 +       ret = i2c_master_send(client, send, 3);
57946 +       if (ret != 3) {
57947 +               snd_printk(KERN_ERR "Failed to set ch4 volume on CS4384\n");
57948 +               goto fail;
57949 +       }
57950 +
57951 +       /*
57952 +        * Register 09h: Mute control
57953 +        *      Mute all (we will unmute channels as needed)
57954 +        */
57955 +       send[0] = 0x09;
57956 +       send[1] = 0xFF;
57957 +       ret = i2c_master_send(client, send, 2);
57958 +       if (ret != 2) {
57959 +               snd_printk(KERN_ERR "Failed to power up CS4384\n");
57960 +               goto fail;
57961 +       }
57962 +
57963 +       /*
57964 +        * Register 0x02: Mode Control 1
57965 +        *      Control Port Enable, PCM, All DACs enabled, Power Up
57966 +        */
57967 +       send[0] = 0x02;
57968 +       send[1] = 0x80;
57969 +       ret = i2c_master_send(client, send, 2);
57970 +       if (ret != 2) {
57971 +               snd_printk(KERN_ERR "Failed to power up CS4384\n");
57972 +               goto fail;
57973 +       }
57974 +
57975 +       /*
57976 +        * Make sure the changes took place, this helps verify we are talking to
57977 +        * the correct chip.
57978 +        */
57979 +       send[0] = 0x80 | 0x03;
57980 +       ret = i2c_master_send(client, send, 1);
57981 +       if (ret != 1) {
57982 +               snd_printk(KERN_ERR "Failed to initiate readback\n");
57983 +               goto fail;
57984 +       }
57985 +
57986 +       ret = i2c_master_recv(client, recv, 1);
57987 +       if (ret != 1) {
57988 +               snd_printk(KERN_ERR "Failed second read of CS4384 registers\n");
57989 +               goto fail;
57990 +       }
57991 +
57992 +       if (recv[0] != 0x13) {
57993 +               snd_printk(KERN_ERR "Failed to initialize CS4384 DAC\n");
57994 +               goto fail;
57995 +       }
57996 +
57997 +       snd_printk(KERN_INFO "CS4384 DAC Initialized\n");
57998 +       return 0;
57999 +
58000 +fail:
58001 +       return -ENODEV;
58002 +}
58003 +
58004 +/*
58005 + * snd_ubi32_cs4384_i2c_probe
58006 + */
58007 +static int snd_ubi32_cs4384_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
58008 +{
58009 +       struct snd_card *card;
58010 +       struct ubi32_snd_priv *ubi32_priv;
58011 +       int err, ret;
58012 +       struct platform_device *pdev;
58013 +       struct ubi32_cs4384_platform_data *pdata;
58014 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
58015 +
58016 +       /*
58017 +        * pdev is audio device
58018 +        */
58019 +       pdev = client->dev.platform_data;
58020 +       if (!pdev) {
58021 +               return -ENODEV;
58022 +       }
58023 +
58024 +       /*
58025 +        * pdev->dev.platform_data is ubi32-pcm platform_data
58026 +        */
58027 +       pdata = audio_device_priv(pdev);
58028 +       if (!pdata) {
58029 +               return -ENODEV;
58030 +       }
58031 +
58032 +       /*
58033 +        * Initialize the CS4384 DAC
58034 +        */
58035 +       ret = snd_ubi32_cs4384_dac_init(client, id);
58036 +       if (ret < 0) {
58037 +               /*
58038 +                * Initialization failed.  Propagate the error.
58039 +                */
58040 +               return ret;
58041 +       }
58042 +
58043 +       if (snd_ubi32_cs4384_setup_mclk(pdata)) {
58044 +               return -EINVAL;
58045 +       }
58046 +
58047 +       /*
58048 +        * Create a snd_card structure
58049 +        */
58050 +       card = snd_card_new(index, "Ubi32-CS4384", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58051 +       if (card == NULL) {
58052 +               return -ENOMEM;
58053 +       }
58054 +
58055 +       card->private_free = snd_ubi32_cs4384_free;
58056 +       ubi32_priv = card->private_data;
58057 +
58058 +       /*
58059 +        * Initialize the snd_card's private data structure
58060 +        */
58061 +       ubi32_priv->card = card;
58062 +       ubi32_priv->client = client;
58063 +       ubi32_priv->set_channels = snd_ubi32_cs4384_set_channels;
58064 +       ubi32_priv->set_rate = snd_ubi32_cs4384_set_rate;
58065 +
58066 +       /*
58067 +        * CS4384 DAC has a minimum sample rate of 4khz and an
58068 +        * upper limit of 216khz for it's auto-detect.
58069 +        */
58070 +       ubi32_priv->min_sample_rate = 4000;
58071 +       ubi32_priv->max_sample_rate = 216000;
58072 +
58073 +       /*
58074 +        * Create our private data (to manage volume, etc)
58075 +        */
58076 +       cs4384_priv = kzalloc(sizeof(struct snd_ubi32_cs4384_priv), GFP_KERNEL);
58077 +       if (!cs4384_priv) {
58078 +               snd_card_free(card);
58079 +               return -ENOMEM;
58080 +       }
58081 +       snd_ubi32_priv_set_drv(ubi32_priv, cs4384_priv);
58082 +       spin_lock_init(&cs4384_priv->lock);
58083 +
58084 +       /*
58085 +        * We start off all muted and max volume
58086 +        */
58087 +       cs4384_priv->mute = 0xFF;
58088 +       memset(cs4384_priv->volume, 0xFF, 8);
58089 +
58090 +       /*
58091 +        * Create the new PCM instance
58092 +        */
58093 +       err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
58094 +       if (err < 0) {
58095 +               snd_card_free(card);
58096 +               return err; /* What is err?  Need to include correct file */
58097 +       }
58098 +
58099 +       strcpy(card->driver, "Ubi32-CS4384");
58100 +       strcpy(card->shortname, "Ubi32-CS4384");
58101 +       snprintf(card->longname, sizeof(card->longname),
58102 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58103 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58104 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58105 +
58106 +       snd_card_set_dev(card, &client->dev);
58107 +
58108 +       /*
58109 +        * Set up the mixer
58110 +        */
58111 +       snd_ubi32_cs4384_mixer(ubi32_priv);
58112 +
58113 +       /*
58114 +        * Register the sound card
58115 +        */
58116 +       if ((err = snd_card_register(card)) != 0) {
58117 +               snd_printk(KERN_INFO "snd_card_register error\n");
58118 +       }
58119 +
58120 +       /*
58121 +        * Store card for access from other methods
58122 +        */
58123 +       i2c_set_clientdata(client, card);
58124 +
58125 +       return 0;
58126 +}
58127 +
58128 +/*
58129 + * snd_ubi32_cs4384_i2c_remove
58130 + */
58131 +static int __devexit snd_ubi32_cs4384_i2c_remove(struct i2c_client *client)
58132 +{
58133 +       struct snd_card *card;
58134 +       struct ubi32_snd_priv *ubi32_priv;
58135 +
58136 +       card = i2c_get_clientdata(client);
58137 +
58138 +       ubi32_priv = card->private_data;
58139 +       snd_ubi32_pcm_remove(ubi32_priv);
58140 +
58141 +       snd_card_free(i2c_get_clientdata(client));
58142 +       i2c_set_clientdata(client, NULL);
58143 +
58144 +       return 0;
58145 +}
58146 +
58147 +/*
58148 + * I2C driver description
58149 + */
58150 +static struct i2c_driver snd_ubi32_cs4384_driver = {
58151 +       .driver = {
58152 +               .name = DRIVER_NAME,
58153 +               .owner = THIS_MODULE,
58154 +       },
58155 +       .id_table       = snd_ubi32_cs4384_id,
58156 +       .probe          = snd_ubi32_cs4384_i2c_probe,
58157 +       .remove         = __devexit_p(snd_ubi32_cs4384_i2c_remove),
58158 +};
58159 +
58160 +/*
58161 + * Driver init
58162 + */
58163 +static int __init snd_ubi32_cs4384_init(void)
58164 +{
58165 +       return i2c_add_driver(&snd_ubi32_cs4384_driver);
58166 +}
58167 +module_init(snd_ubi32_cs4384_init);
58168 +
58169 +/*
58170 + * snd_ubi32_cs4384_exit
58171 + */
58172 +static void __exit snd_ubi32_cs4384_exit(void)
58173 +{
58174 +       i2c_del_driver(&snd_ubi32_cs4384_driver);
58175 +}
58176 +module_exit(snd_ubi32_cs4384_exit);
58177 +
58178 +/*
58179 + * Module properties
58180 + */
58181 +MODULE_ALIAS("i2c:" DRIVER_NAME);
58182 +MODULE_AUTHOR("Patrick Tjin");
58183 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4384");
58184 +MODULE_LICENSE("GPL");
58185 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-generic.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic.c
58186 --- linux-2.6.30.10/sound/ubicom32/ubi32-generic.c      1970-01-01 02:00:00.000000000 +0200
58187 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic.c  2009-12-11 11:45:25.000000000 +0200
58188 @@ -0,0 +1,166 @@
58189 +/*
58190 + * sound/ubicom32/ubi32-generic.c
58191 + *     Interface to ubicom32 virtual audio peripheral
58192 + *
58193 + * (C) Copyright 2009, Ubicom, Inc.
58194 + *
58195 + * This file is part of the Ubicom32 Linux Kernel Port.
58196 + *
58197 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58198 + * it and/or modify it under the terms of the GNU General Public License
58199 + * as published by the Free Software Foundation, either version 2 of the
58200 + * License, or (at your option) any later version.
58201 + *
58202 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58203 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58204 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58205 + * the GNU General Public License for more details.
58206 + *
58207 + * You should have received a copy of the GNU General Public License
58208 + * along with the Ubicom32 Linux Kernel Port.  If not,
58209 + * see <http://www.gnu.org/licenses/>.
58210 + *
58211 + * Ubicom32 implementation derived from (with many thanks):
58212 + *   arch/m68knommu
58213 + *   arch/blackfin
58214 + *   arch/parisc
58215 + */
58216 +
58217 +#include <linux/platform_device.h>
58218 +#include <linux/module.h>
58219 +#include <linux/moduleparam.h>
58220 +#include <sound/core.h>
58221 +#include <sound/pcm.h>
58222 +#include <sound/initval.h>
58223 +#include "ubi32.h"
58224 +
58225 +#define DRIVER_NAME "snd-ubi32-generic"
58226 +
58227 +/*
58228 + * Module properties
58229 + */
58230 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
58231 +
58232 +/*
58233 + * Card private data free function
58234 + */
58235 +void snd_ubi32_generic_free(struct snd_card *card)
58236 +{
58237 +       /*
58238 +        * Free all the fields in the snd_ubi32_priv struct
58239 +        */
58240 +       // Nothing to free at this time because ubi32_priv just maintains pointers
58241 +}
58242 +
58243 +/*
58244 + * Ubicom audio driver probe() method.  Args change depending on whether we use
58245 + * platform_device or i2c_device.
58246 + */
58247 +static int snd_ubi32_generic_probe(struct platform_device *dev)
58248 +{
58249 +       struct snd_card *card;
58250 +       struct ubi32_snd_priv *ubi32_priv;
58251 +       int err;
58252 +
58253 +       /*
58254 +        * Create a snd_card structure
58255 +        */
58256 +       card = snd_card_new(index, "Ubi32-Generic", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58257 +
58258 +       if (card == NULL) {
58259 +               return -ENOMEM;
58260 +       }
58261 +
58262 +       card->private_free = snd_ubi32_generic_free; /* Not sure if correct */
58263 +       ubi32_priv = card->private_data;
58264 +
58265 +       /*
58266 +        * Initialize the snd_card's private data structure
58267 +        */
58268 +       ubi32_priv->card = card;
58269 +
58270 +       /*
58271 +        * Create the new PCM instance
58272 +        */
58273 +       err = snd_ubi32_pcm_probe(ubi32_priv, dev);
58274 +       if (err < 0) {
58275 +               snd_card_free(card);
58276 +               return err;
58277 +       }
58278 +
58279 +       strcpy(card->driver, "Ubi32-Generic");
58280 +       strcpy(card->shortname, "Ubi32-Generic");
58281 +       snprintf(card->longname, sizeof(card->longname),
58282 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58283 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58284 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58285 +
58286 +       snd_card_set_dev(card, &dev->dev);
58287 +
58288 +       /* Register the sound card */
58289 +       if ((err = snd_card_register(card)) != 0) {
58290 +               snd_printk(KERN_INFO "snd_card_register error\n");
58291 +       }
58292 +
58293 +       /* Store card for access from other methods */
58294 +       platform_set_drvdata(dev, card);
58295 +
58296 +       return 0;
58297 +}
58298 +
58299 +/*
58300 + * Ubicom audio driver remove() method
58301 + */
58302 +static int __devexit snd_ubi32_generic_remove(struct platform_device *dev)
58303 +{
58304 +       struct snd_card *card;
58305 +       struct ubi32_snd_priv *ubi32_priv;
58306 +
58307 +       card = platform_get_drvdata(dev);
58308 +       ubi32_priv = card->private_data;
58309 +       snd_ubi32_pcm_remove(ubi32_priv);
58310 +
58311 +       snd_card_free(platform_get_drvdata(dev));
58312 +       platform_set_drvdata(dev, NULL);
58313 +       return 0;
58314 +}
58315 +
58316 +/*
58317 + * Platform driver definition
58318 + */
58319 +static struct platform_driver snd_ubi32_generic_driver = {
58320 +       .driver = {
58321 +               .name = DRIVER_NAME,
58322 +               .owner = THIS_MODULE,
58323 +       },
58324 +       .probe = snd_ubi32_generic_probe,
58325 +       .remove = __devexit_p(snd_ubi32_generic_remove),
58326 +};
58327 +
58328 +/*
58329 + * snd_ubi32_generic_init
58330 + */
58331 +static int __init snd_ubi32_generic_init(void)
58332 +{
58333 +       return platform_driver_register(&snd_ubi32_generic_driver);
58334 +}
58335 +module_init(snd_ubi32_generic_init);
58336 +
58337 +/*
58338 + * snd_ubi32_generic_exit
58339 + */
58340 +static void __exit snd_ubi32_generic_exit(void)
58341 +{
58342 +       platform_driver_unregister(&snd_ubi32_generic_driver);
58343 +}
58344 +module_exit(snd_ubi32_generic_exit);
58345 +
58346 +/*
58347 + * Module properties
58348 + */
58349 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58350 +//MODULE_ALIAS("i2c:snd-ubi32");
58351 +//#endif
58352 +MODULE_AUTHOR("Aaron Jow, Patrick Tjin");
58353 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58354 +MODULE_LICENSE("GPL");
58355 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-generic-capture.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic-capture.c
58356 --- linux-2.6.30.10/sound/ubicom32/ubi32-generic-capture.c      1970-01-01 02:00:00.000000000 +0200
58357 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic-capture.c  2009-12-11 11:45:25.000000000 +0200
58358 @@ -0,0 +1,167 @@
58359 +/*
58360 + * sound/ubicom32/ubi32-generic-capture.c
58361 + *     Interface to ubicom32 virtual audio peripheral
58362 + *
58363 + * (C) Copyright 2009, Ubicom, Inc.
58364 + *
58365 + * This file is part of the Ubicom32 Linux Kernel Port.
58366 + *
58367 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58368 + * it and/or modify it under the terms of the GNU General Public License
58369 + * as published by the Free Software Foundation, either version 2 of the
58370 + * License, or (at your option) any later version.
58371 + *
58372 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58373 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58374 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58375 + * the GNU General Public License for more details.
58376 + *
58377 + * You should have received a copy of the GNU General Public License
58378 + * along with the Ubicom32 Linux Kernel Port.  If not,
58379 + * see <http://www.gnu.org/licenses/>.
58380 + *
58381 + * Ubicom32 implementation derived from (with many thanks):
58382 + *   arch/m68knommu
58383 + *   arch/blackfin
58384 + *   arch/parisc
58385 + */
58386 +
58387 +#include <linux/platform_device.h>
58388 +#include <linux/module.h>
58389 +#include <linux/moduleparam.h>
58390 +#include <sound/core.h>
58391 +#include <sound/pcm.h>
58392 +#include <sound/initval.h>
58393 +#include "ubi32.h"
58394 +
58395 +#define DRIVER_NAME "snd-ubi32-generic-capture"
58396 +
58397 +/*
58398 + * Module properties
58399 + */
58400 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
58401 +
58402 +/*
58403 + * Card private data free function
58404 + */
58405 +void snd_ubi32_generic_capture_free(struct snd_card *card)
58406 +{
58407 +       /*
58408 +        * Free all the fields in the snd_ubi32_priv struct
58409 +        */
58410 +       // Nothing to free at this time because ubi32_priv just maintains pointers
58411 +}
58412 +
58413 +/*
58414 + * Ubicom audio driver probe() method.  Args change depending on whether we use
58415 + * platform_device or i2c_device.
58416 + */
58417 +static int snd_ubi32_generic_capture_probe(struct platform_device *dev)
58418 +{
58419 +       struct snd_card *card;
58420 +       struct ubi32_snd_priv *ubi32_priv;
58421 +       int err;
58422 +
58423 +       /*
58424 +        * Create a snd_card structure
58425 +        */
58426 +       card = snd_card_new(index, "Ubi32-Generic-C", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58427 +
58428 +       if (card == NULL) {
58429 +               return -ENOMEM;
58430 +       }
58431 +
58432 +       card->private_free = snd_ubi32_generic_capture_free; /* Not sure if correct */
58433 +       ubi32_priv = card->private_data;
58434 +
58435 +       /*
58436 +        * Initialize the snd_card's private data structure
58437 +        */
58438 +       ubi32_priv->card = card;
58439 +       ubi32_priv->is_capture = 1;
58440 +
58441 +       /*
58442 +        * Create the new PCM instance
58443 +        */
58444 +       err = snd_ubi32_pcm_probe(ubi32_priv, dev);
58445 +       if (err < 0) {
58446 +               snd_card_free(card);
58447 +               return err;
58448 +       }
58449 +
58450 +       strcpy(card->driver, "Ubi32-Generic-C");
58451 +       strcpy(card->shortname, "Ubi32-Generic-C");
58452 +       snprintf(card->longname, sizeof(card->longname),
58453 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58454 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58455 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58456 +
58457 +       snd_card_set_dev(card, &dev->dev);
58458 +
58459 +       /* Register the sound card */
58460 +       if ((err = snd_card_register(card)) != 0) {
58461 +               snd_printk(KERN_INFO "snd_card_register error\n");
58462 +       }
58463 +
58464 +       /* Store card for access from other methods */
58465 +       platform_set_drvdata(dev, card);
58466 +
58467 +       return 0;
58468 +}
58469 +
58470 +/*
58471 + * Ubicom audio driver remove() method
58472 + */
58473 +static int __devexit snd_ubi32_generic_capture_remove(struct platform_device *dev)
58474 +{
58475 +       struct snd_card *card;
58476 +       struct ubi32_snd_priv *ubi32_priv;
58477 +
58478 +       card = platform_get_drvdata(dev);
58479 +       ubi32_priv = card->private_data;
58480 +       snd_ubi32_pcm_remove(ubi32_priv);
58481 +
58482 +       snd_card_free(platform_get_drvdata(dev));
58483 +       platform_set_drvdata(dev, NULL);
58484 +       return 0;
58485 +}
58486 +
58487 +/*
58488 + * Platform driver definition
58489 + */
58490 +static struct platform_driver snd_ubi32_generic_capture_driver = {
58491 +       .driver = {
58492 +               .name = DRIVER_NAME,
58493 +               .owner = THIS_MODULE,
58494 +       },
58495 +       .probe = snd_ubi32_generic_capture_probe,
58496 +       .remove = __devexit_p(snd_ubi32_generic_capture_remove),
58497 +};
58498 +
58499 +/*
58500 + * snd_ubi32_generic_capture_init
58501 + */
58502 +static int __init snd_ubi32_generic_capture_init(void)
58503 +{
58504 +       return platform_driver_register(&snd_ubi32_generic_capture_driver);
58505 +}
58506 +module_init(snd_ubi32_generic_capture_init);
58507 +
58508 +/*
58509 + * snd_ubi32_generic_capture_exit
58510 + */
58511 +static void __exit snd_ubi32_generic_capture_exit(void)
58512 +{
58513 +       platform_driver_unregister(&snd_ubi32_generic_capture_driver);
58514 +}
58515 +module_exit(snd_ubi32_generic_capture_exit);
58516 +
58517 +/*
58518 + * Module properties
58519 + */
58520 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58521 +//MODULE_ALIAS("i2c:snd-ubi32");
58522 +//#endif
58523 +MODULE_AUTHOR("Patrick Tjin");
58524 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58525 +MODULE_LICENSE("GPL");
58526 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32.h linux-2.6.30.10-ubi/sound/ubicom32/ubi32.h
58527 --- linux-2.6.30.10/sound/ubicom32/ubi32.h      1970-01-01 02:00:00.000000000 +0200
58528 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32.h  2009-12-11 11:45:25.000000000 +0200
58529 @@ -0,0 +1,102 @@
58530 +/*
58531 + * sound/ubicom32/ubi32.h
58532 + *     Common header file for all ubi32- sound drivers
58533 + *
58534 + * (C) Copyright 2009, Ubicom, Inc.
58535 + *
58536 + * This file is part of the Ubicom32 Linux Kernel Port.
58537 + *
58538 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58539 + * it and/or modify it under the terms of the GNU General Public License
58540 + * as published by the Free Software Foundation, either version 2 of the
58541 + * License, or (at your option) any later version.
58542 + *
58543 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58544 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58545 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58546 + * the GNU General Public License for more details.
58547 + *
58548 + * You should have received a copy of the GNU General Public License
58549 + * along with the Ubicom32 Linux Kernel Port.  If not,
58550 + * see <http://www.gnu.org/licenses/>.
58551 + */
58552 +
58553 +#ifndef _UBI32_H
58554 +#define _UBI32_H
58555 +
58556 +#define SND_UBI32_DEBUG 0 // Debug flag
58557 +
58558 +#include <linux/platform_device.h>
58559 +#include <asm/devtree.h>
58560 +#include <asm/audio.h>
58561 +#include <asm/ubi32-pcm.h>
58562 +
58563 +struct ubi32_snd_priv;
58564 +
58565 +typedef int (*set_channels_t)(struct ubi32_snd_priv *priv, int channels);
58566 +typedef int (*set_rate_t)(struct ubi32_snd_priv *priv, int rate);
58567 +
58568 +struct ubi32_snd_priv {
58569 +       /*
58570 +        * Any variables that are needed locally here but NOT in
58571 +        * the VP itself should go in here.
58572 +        */
58573 +       struct snd_card *card;
58574 +       struct snd_pcm *pcm;
58575 +
58576 +       /*
58577 +        * capture (1) or playback (0)
58578 +        */
58579 +       int is_capture;
58580 +       /*
58581 +        * DAC parameters.  These are the parameters for the specific
58582 +        * DAC we are driving.  The I2S component can run at a range
58583 +        * of frequencies, but the DAC may be limited.  We may want
58584 +        * to make this an array of some sort in the future?
58585 +        *
58586 +        * min/max_sample_rate if set to 0 are ignored.
58587 +        */
58588 +       int max_sample_rate;
58589 +       int min_sample_rate;
58590 +
58591 +       /*
58592 +        * The size a period (group) of audio samples.  The VP does
58593 +        * not need to know this; each DMA transfer is made to be
58594 +        * one period.
58595 +        */
58596 +       u32_t period_size;
58597 +
58598 +       spinlock_t ubi32_lock;
58599 +
58600 +       struct audio_regs *ar;
58601 +       struct audio_dev_regs *adr;
58602 +       u32 irq_idx;
58603 +       u8 tx_irq;
58604 +       u8 rx_irq;
58605 +
58606 +       void *client;
58607 +
58608 +       /*
58609 +        * Operations which the base DAC driver can implement
58610 +        */
58611 +       set_channels_t set_channels;
58612 +       set_rate_t set_rate;
58613 +
58614 +       /*
58615 +        * platform data
58616 +        */
58617 +       struct ubi32pcm_platform_data *pdata;
58618 +
58619 +       /*
58620 +        * Private driver data (used for DAC driver control, etc)
58621 +        */
58622 +       void *drvdata;
58623 +};
58624 +
58625 +#define snd_ubi32_priv_get_drv(priv) ((priv)->drvdata)
58626 +#define snd_ubi32_priv_set_drv(priv, data) (((priv)->drvdata) = (void *)(data))
58627 +
58628 +extern int snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev);
58629 +extern void snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv);
58630 +
58631 +#endif
58632 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-pcm.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-pcm.c
58633 --- linux-2.6.30.10/sound/ubicom32/ubi32-pcm.c  1970-01-01 02:00:00.000000000 +0200
58634 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-pcm.c      2009-12-11 11:45:25.000000000 +0200
58635 @@ -0,0 +1,711 @@
58636 +/*
58637 + * sound/ubicom32/ubi32-pcm.c
58638 + *     Interface to ubicom32 virtual audio peripheral
58639 + *
58640 + * (C) Copyright 2009, Ubicom, Inc.
58641 + *
58642 + * This file is part of the Ubicom32 Linux Kernel Port.
58643 + *
58644 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58645 + * it and/or modify it under the terms of the GNU General Public License
58646 + * as published by the Free Software Foundation, either version 2 of the
58647 + * License, or (at your option) any later version.
58648 + *
58649 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58650 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58651 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58652 + * the GNU General Public License for more details.
58653 + *
58654 + * You should have received a copy of the GNU General Public License
58655 + * along with the Ubicom32 Linux Kernel Port.  If not,
58656 + * see <http://www.gnu.org/licenses/>.
58657 + *
58658 + * Ubicom32 implementation derived from (with many thanks):
58659 + *   arch/m68knommu
58660 + *   arch/blackfin
58661 + *   arch/parisc
58662 + */
58663 +
58664 +#include <linux/interrupt.h>
58665 +#include <sound/core.h>
58666 +#include <sound/pcm.h>
58667 +#include <sound/pcm_params.h>
58668 +#include <asm/ip5000.h>
58669 +#include <asm/ubi32-pcm.h>
58670 +#include <linux/dma-mapping.h>
58671 +#include <linux/delay.h>
58672 +#include "ubi32.h"
58673 +
58674 +struct ubi32_snd_runtime_data {
58675 +       dma_addr_t dma_buffer;          /* Physical address of DMA buffer */
58676 +       dma_addr_t dma_buffer_end;      /* First address beyond end of DMA buffer */
58677 +       size_t period_size;
58678 +       dma_addr_t period_ptr;          /* Physical address of next period */
58679 +       unsigned int flags;
58680 +};
58681 +
58682 +static void snd_ubi32_vp_int_set(struct snd_pcm *pcm)
58683 +{
58684 +       struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
58685 +       ubi32_priv->ar->int_req |= (1 << ubi32_priv->irq_idx);
58686 +       ubicom32_set_interrupt(ubi32_priv->tx_irq);
58687 +}
58688 +
58689 +static snd_pcm_uframes_t snd_ubi32_pcm_pointer(struct snd_pcm_substream *substream)
58690 +{
58691 +
58692 +       struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58693 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58694 +       struct snd_pcm_runtime *runtime = substream->runtime;
58695 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58696 +
58697 +       dma_addr_t read_pos;
58698 +
58699 +       snd_pcm_uframes_t frames;
58700 +       if (!adr->primary_os_buffer_ptr) {
58701 +               /*
58702 +                * If primary_os_buffer_ptr is NULL (e.g. right after the HW is started or
58703 +                * when the HW is stopped), then handle this case separately.
58704 +                */
58705 +               return 0;
58706 +       }
58707 +
58708 +       read_pos = (dma_addr_t)adr->primary_os_buffer_ptr;
58709 +       frames = bytes_to_frames(runtime, read_pos - ubi32_rd->dma_buffer);
58710 +       if (frames == runtime->buffer_size) {
58711 +               frames = 0;
58712 +       }
58713 +       return frames;
58714 +}
58715 +
58716 +/*
58717 + * Audio trigger
58718 + */
58719 +static int snd_ubi32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
58720 +{
58721 +       struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58722 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58723 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58724 +       int ret = 0;
58725 +
58726 +#ifdef CONFIG_SND_DEBUG
58727 +       snd_printk(KERN_INFO "snd_ubi32_pcm_trigger cmd=%d=", cmd);
58728 +#endif
58729 +
58730 +       if (adr->command != AUDIO_CMD_NONE) {
58731 +               snd_printk(KERN_WARNING "Can't send command to audio device at this time\n");
58732 +               // Set a timer to call this function back later.  How to do this?
58733 +               return 0;
58734 +       }
58735 +
58736 +       /*
58737 +        * Set interrupt flag to indicate that we interrupted audio device
58738 +        * to send a command
58739 +        */
58740 +
58741 +       switch (cmd) {
58742 +       case SNDRV_PCM_TRIGGER_START:
58743 +
58744 +#ifdef CONFIG_SND_DEBUG
58745 +               snd_printk(KERN_INFO "START\n");
58746 +#endif
58747 +               /*
58748 +                * Ready the DMA transfer
58749 +                */
58750 +               ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
58751 +
58752 +#ifdef CONFIG_SND_DEBUG
58753 +               snd_printk(KERN_INFO "trigger period_ptr=%lx\n", (unsigned long)ubi32_rd->period_ptr);
58754 +#endif
58755 +               adr->dma_xfer_requests[0].ptr = (void *)ubi32_rd->period_ptr;
58756 +               adr->dma_xfer_requests[0].ctr = ubi32_rd->period_size;
58757 +               adr->dma_xfer_requests[0].active = 1;
58758 +
58759 +#ifdef CONFIG_SND_DEBUG
58760 +               snd_printk(KERN_INFO "xfer_request 0 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58761 +#endif
58762 +
58763 +               ubi32_rd->period_ptr += ubi32_rd->period_size;
58764 +               adr->dma_xfer_requests[1].ptr = (void *)ubi32_rd->period_ptr;
58765 +               adr->dma_xfer_requests[1].ctr = ubi32_rd->period_size;
58766 +               adr->dma_xfer_requests[1].active = 1;
58767 +
58768 +#ifdef CONFIG_SND_DEBUG
58769 +               snd_printk(KERN_INFO "xfer_request 1 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58770 +#endif
58771 +
58772 +               /*
58773 +                * Tell the VP that we want to begin playback by filling in the
58774 +                * command field and then interrupting the audio VP
58775 +                */
58776 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58777 +               adr->command = AUDIO_CMD_START;
58778 +               snd_ubi32_vp_int_set(substream->pcm);
58779 +               break;
58780 +
58781 +       case SNDRV_PCM_TRIGGER_STOP:
58782 +
58783 +#ifdef CONFIG_SND_DEBUG
58784 +               snd_printk(KERN_INFO "STOP\n");
58785 +#endif
58786 +
58787 +               /*
58788 +                * Tell the VP that we want to stop playback by filling in the
58789 +                * command field and then interrupting the audio VP
58790 +                */
58791 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58792 +               adr->command = AUDIO_CMD_STOP;
58793 +               snd_ubi32_vp_int_set(substream->pcm);
58794 +               break;
58795 +
58796 +       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
58797 +
58798 +#ifdef CONFIG_SND_DEBUG
58799 +               snd_printk(KERN_INFO "PAUSE_PUSH\n");
58800 +#endif
58801 +
58802 +               /*
58803 +                * Tell the VP that we want to pause playback by filling in the
58804 +                * command field and then interrupting the audio VP
58805 +                */
58806 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58807 +               adr->command = AUDIO_CMD_PAUSE;
58808 +               snd_ubi32_vp_int_set(substream->pcm);
58809 +               break;
58810 +
58811 +       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
58812 +
58813 +#ifdef CONFIG_SND_DEBUG
58814 +               snd_printk(KERN_INFO "PAUSE_RELEASE\n");
58815 +#endif
58816 +               /*
58817 +                * Tell the VP that we want to resume paused playback by filling
58818 +                * in the command field and then interrupting the audio VP
58819 +                */
58820 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58821 +               adr->command = AUDIO_CMD_RESUME;
58822 +               snd_ubi32_vp_int_set(substream->pcm);
58823 +               break;
58824 +
58825 +       default:
58826 +               snd_printk(KERN_WARNING "Unhandled trigger\n");
58827 +               ret = -EINVAL;
58828 +               break;
58829 +       }
58830 +
58831 +       return ret;
58832 +}
58833 +
58834 +/*
58835 + * Prepare to transfer an audio stream to the codec
58836 + */
58837 +static int snd_ubi32_pcm_prepare(struct snd_pcm_substream *substream)
58838 +{
58839 +       /*
58840 +        * Configure registers and setup the runtime instance for DMA transfers
58841 +        */
58842 +       struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58843 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58844 +
58845 +#ifdef CONFIG_SND_DEBUG
58846 +       snd_printk(KERN_INFO "snd_ubi32_pcm_prepare: sending STOP command to audio device\n");
58847 +#endif
58848 +
58849 +       /*
58850 +        * Make sure the audio device is stopped
58851 +        */
58852 +
58853 +       /*
58854 +        * Set interrupt flag to indicate that we interrupted audio device
58855 +        * to send a command
58856 +        */
58857 +       adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58858 +       adr->command = AUDIO_CMD_STOP;
58859 +       snd_ubi32_vp_int_set(substream->pcm);
58860 +
58861 +       return 0;
58862 +}
58863 +
58864 +/*
58865 + * Allocate DMA buffers from preallocated memory.
58866 + * Preallocation was done in snd_ubi32_pcm_new()
58867 + */
58868 +static int snd_ubi32_pcm_hw_params(struct snd_pcm_substream *substream,
58869 +                                       struct snd_pcm_hw_params *hw_params)
58870 +{
58871 +       struct snd_pcm_runtime *runtime = substream->runtime;
58872 +       struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58873 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58874 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58875 +
58876 +       /*
58877 +        * Use pre-allocated memory from ubi32_snd_pcm_new() to satisfy
58878 +        * this memory request.
58879 +        */
58880 +       int ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
58881 +       if (ret < 0) {
58882 +               return ret;
58883 +       }
58884 +
58885 +#ifdef CONFIG_SND_DEBUG
58886 +       snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params\n");
58887 +#endif
58888 +
58889 +       if (!(adr->channel_mask & (1 << params_channels(hw_params)))) {
58890 +               snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params unsupported number of channels %d mask %08x\n", params_channels(hw_params), adr->channel_mask);
58891 +               return -EINVAL;
58892 +       }
58893 +
58894 +       if (ubi32_priv->set_channels) {
58895 +               int ret = ubi32_priv->set_channels(ubi32_priv, params_channels(hw_params));
58896 +               if (ret) {
58897 +                       snd_printk(KERN_WARNING "Unable to set channels to %d, ret=%d\n", params_channels(hw_params), ret);
58898 +                       return ret;
58899 +               }
58900 +       }
58901 +
58902 +       if (ubi32_priv->set_rate) {
58903 +               int ret = ubi32_priv->set_rate(ubi32_priv, params_rate(hw_params));
58904 +               if (ret) {
58905 +                       snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58906 +                       return ret;
58907 +               }
58908 +       }
58909 +
58910 +       if (ubi32_priv->pdata->set_rate) {
58911 +               int ret = ubi32_priv->pdata->set_rate(ubi32_priv->pdata->appdata, params_rate(hw_params));
58912 +               if (ret) {
58913 +                       snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58914 +                       return ret;
58915 +               }
58916 +       }
58917 +
58918 +       if (adr->command != AUDIO_CMD_NONE) {
58919 +               snd_printk(KERN_WARNING "snd_ubi32_pcm_hw_params: tio busy\n");
58920 +               return -EAGAIN;
58921 +       }
58922 +
58923 +       if (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) {
58924 +               adr->flags |= CMD_START_FLAG_LE;
58925 +       } else {
58926 +               adr->flags &= ~CMD_START_FLAG_LE;
58927 +       }
58928 +       adr->channels = params_channels(hw_params);
58929 +       adr->sample_rate = params_rate(hw_params);
58930 +       adr->command = AUDIO_CMD_SETUP;
58931 +       adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58932 +       snd_ubi32_vp_int_set(substream->pcm);
58933 +
58934 +       /*
58935 +        * Wait for the command to complete
58936 +        */
58937 +       while (adr->command != AUDIO_CMD_NONE) {
58938 +               udelay(1);
58939 +       }
58940 +
58941 +       /*
58942 +        * Put the DMA info into the DMA descriptor that we will
58943 +        * use to do transfers to our audio VP "hardware"
58944 +        */
58945 +
58946 +       /*
58947 +        * Mark both DMA transfers as not ready/inactive
58948 +        */
58949 +       adr->dma_xfer_requests[0].active = 0;
58950 +       adr->dma_xfer_requests[1].active = 0;
58951 +
58952 +       /*
58953 +        * Put the location of the buffer into the runtime data instance
58954 +        */
58955 +       ubi32_rd->dma_buffer = (dma_addr_t)runtime->dma_area;
58956 +       ubi32_rd->dma_buffer_end = (dma_addr_t)(runtime->dma_area + runtime->dma_bytes);
58957 +
58958 +       /*
58959 +        * Get the period size
58960 +        */
58961 +       ubi32_rd->period_size = params_period_bytes(hw_params);
58962 +
58963 +#ifdef CONFIG_SND_DEBUG
58964 +       snd_printk(KERN_INFO "DMA for ubi32 audio initialized dma_area=0x%x dma_bytes=%d, period_size=%d\n", (unsigned int)runtime->dma_area, (unsigned int)runtime->dma_bytes, ubi32_rd->period_size);
58965 +       snd_printk(KERN_INFO "Private buffer ubi32_rd: dma_buffer=0x%x dma_buffer_end=0x%x ret=%d\n", ubi32_rd->dma_buffer, ubi32_rd->dma_buffer_end, ret);
58966 +#endif
58967 +
58968 +       return ret;
58969 +}
58970 +
58971 +/*
58972 + * This is the reverse of snd_ubi32_pcm_hw_params
58973 + */
58974 +static int snd_ubi32_pcm_hw_free(struct snd_pcm_substream *substream)
58975 +{
58976 +#ifdef CONFIG_SND_DEBUG
58977 +       snd_printk(KERN_INFO "snd_ubi32_pcm_hw_free\n");
58978 +#endif
58979 +       return snd_pcm_lib_free_pages(substream);
58980 +}
58981 +
58982 +/*
58983 + * Audio virtual peripheral capabilities (capture and playback are identical)
58984 + */
58985 +static struct snd_pcm_hardware snd_ubi32_pcm_hw =
58986 +{
58987 +       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
58988 +                SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
58989 +       .buffer_bytes_max = (64*1024),
58990 +       .period_bytes_min       = 64,
58991 +       .period_bytes_max       = 8184,//8184,//8176,
58992 +       .periods_min = 2,
58993 +       .periods_max = 255,
58994 +       .fifo_size = 0, // THIS IS IGNORED BY ALSA
58995 +};
58996 +
58997 +/*
58998 + * We fill this in later
58999 + */
59000 +static struct snd_pcm_hw_constraint_list ubi32_pcm_rates;
59001 +
59002 +/*
59003 + * snd_ubi32_pcm_close
59004 + */
59005 +static int snd_ubi32_pcm_close(struct snd_pcm_substream *substream)
59006 +{
59007 +       /* Disable codec, stop DMA, free private data structures */
59008 +       //struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
59009 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
59010 +
59011 +#ifdef CONFIG_SND_DEBUG
59012 +       snd_printk(KERN_INFO "snd_ubi32_pcm_close\n");
59013 +#endif
59014 +
59015 +       substream->runtime->private_data = NULL;
59016 +
59017 +       kfree(ubi32_rd);
59018 +
59019 +       return 0;
59020 +}
59021 +
59022 +/*
59023 + * snd_ubi32_pcm_open
59024 + */
59025 +static int snd_ubi32_pcm_open(struct snd_pcm_substream *substream)
59026 +{
59027 +       struct snd_pcm_runtime *runtime = substream->runtime;
59028 +       struct ubi32_snd_runtime_data *ubi32_rd;
59029 +       int ret = 0;
59030 +
59031 +#ifdef CONFIG_SND_DEBUG
59032 +       snd_printk(KERN_INFO "ubi32 pcm open\n");
59033 +#endif
59034 +
59035 +       /* Associate capabilities with component */
59036 +       runtime->hw = snd_ubi32_pcm_hw;
59037 +
59038 +       /*
59039 +        * Inform ALSA about constraints of the audio device
59040 +        */
59041 +       ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &ubi32_pcm_rates);
59042 +       if (ret < 0) {
59043 +               snd_printk(KERN_INFO "invalid rate\n");
59044 +               goto out;
59045 +       }
59046 +
59047 +       /* Force the buffer size to be an integer multiple of period size */
59048 +       ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
59049 +       if (ret < 0) {
59050 +               snd_printk(KERN_INFO "invalid period\n");
59051 +               goto out;
59052 +       }
59053 +       /* Initialize structures/registers */
59054 +       ubi32_rd = kzalloc(sizeof(struct ubi32_snd_runtime_data), GFP_KERNEL);
59055 +       if (ubi32_rd == NULL) {
59056 +               ret = -ENOMEM;
59057 +               goto out;
59058 +       }
59059 +
59060 +       runtime->private_data = ubi32_rd;
59061 +
59062 +#ifdef CONFIG_SND_DEBUG
59063 +       snd_printk(KERN_INFO "snd_ubi32_pcm_open returned 0\n");
59064 +#endif
59065 +
59066 +       return 0;
59067 +out:
59068 +#ifdef CONFIG_SND_DEBUG
59069 +       snd_printk(KERN_INFO "snd_ubi32_pcm_open returned %d\n", ret);
59070 +#endif
59071 +
59072 +       return ret;
59073 +}
59074 +
59075 +static struct snd_pcm_ops snd_ubi32_pcm_ops = {
59076 +       .open =         snd_ubi32_pcm_open, /* Open */
59077 +       .close =        snd_ubi32_pcm_close, /* Close */
59078 +       .ioctl =        snd_pcm_lib_ioctl, /* Generic IOCTL handler */
59079 +       .hw_params =    snd_ubi32_pcm_hw_params, /* Hardware parameters/capabilities */
59080 +       .hw_free =      snd_ubi32_pcm_hw_free, /* Free function for hw_params */
59081 +       .prepare =      snd_ubi32_pcm_prepare,
59082 +       .trigger =      snd_ubi32_pcm_trigger,
59083 +       .pointer =      snd_ubi32_pcm_pointer,
59084 +};
59085 +
59086 +/*
59087 + * Interrupt handler that gets called when the audio device
59088 + * interrupts Linux
59089 + */
59090 +static irqreturn_t snd_ubi32_pcm_interrupt(int irq, void *appdata)
59091 +{
59092 +       struct snd_pcm *pcm = (struct snd_pcm *)appdata;
59093 +       struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
59094 +       struct audio_dev_regs *adr = ubi32_priv->adr;
59095 +       struct snd_pcm_substream *substream;
59096 +       struct ubi32_snd_runtime_data *ubi32_rd;
59097 +       int dma_to_fill = 0;
59098 +
59099 +       /*
59100 +        * Check to see if the interrupt is for us
59101 +        */
59102 +       if (!(ubi32_priv->ar->int_status & (1 << ubi32_priv->irq_idx))) {
59103 +               return IRQ_NONE;
59104 +       }
59105 +
59106 +       /*
59107 +        * Clear the interrupt
59108 +        */
59109 +       ubi32_priv->ar->int_status &= ~(1 << ubi32_priv->irq_idx);
59110 +
59111 +       /*
59112 +        * We only have one stream since we don't mix.  Therefore
59113 +        * we don't need to search through substreams.
59114 +        */
59115 +       if (ubi32_priv->is_capture) {
59116 +               substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
59117 +       } else {
59118 +               substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
59119 +       }
59120 +
59121 +       if (!substream->runtime) {
59122 +               snd_printk(KERN_WARNING "No runtime data\n");
59123 +               return IRQ_NONE;
59124 +       }
59125 +
59126 +       ubi32_rd = substream->runtime->private_data;
59127 +
59128 +#ifdef CONFIG_SND_DEBUG
59129 +       snd_printk(KERN_INFO "Ubi32 ALSA interrupt\n");
59130 +#endif
59131 +
59132 +       if (ubi32_rd == NULL) {
59133 +               snd_printk(KERN_WARNING "No private data\n");
59134 +               return IRQ_NONE;
59135 +       }
59136 +
59137 +       // Check interrupt cause
59138 +       if (0) {
59139 +               // Handle the underflow case
59140 +       } else if ((adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) ||
59141 +                  (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST)) {
59142 +               if (adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) {
59143 +                       dma_to_fill = 0;
59144 +                       adr->status &= ~AUDIO_STATUS_PLAY_DMA0_REQUEST;
59145 +               } else if (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST) {
59146 +                       dma_to_fill = 1;
59147 +                       adr->status &= ~AUDIO_STATUS_PLAY_DMA1_REQUEST;
59148 +               }
59149 +               ubi32_rd->period_ptr += ubi32_rd->period_size;
59150 +               if (ubi32_rd->period_ptr >= ubi32_rd->dma_buffer_end) {
59151 +                       ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
59152 +               }
59153 +               adr->dma_xfer_requests[dma_to_fill].ptr = (void *)ubi32_rd->period_ptr;
59154 +               adr->dma_xfer_requests[dma_to_fill].ctr = ubi32_rd->period_size;
59155 +               adr->dma_xfer_requests[dma_to_fill].active = 1;
59156 +#ifdef CONFIG_SND_DEBUG
59157 +               snd_printk(KERN_INFO "xfer_request %d ptr=0x%x ctr=%u\n", dma_to_fill, ubi32_rd->period_ptr, ubi32_rd->period_size);
59158 +#endif
59159 +               adr->int_flags |= AUDIO_INT_FLAG_MORE_SAMPLES;
59160 +               snd_ubi32_vp_int_set(substream->pcm);
59161 +       }
59162 +       // If we are interrupted by the VP, that means we completed
59163 +       // processing one period of audio.  We need to inform the upper
59164 +       // layers of ALSA of this.
59165 +       snd_pcm_period_elapsed(substream);
59166 +
59167 +       return IRQ_HANDLED;
59168 +}
59169 +
59170 +void __devexit snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv)
59171 +{
59172 +       struct snd_pcm *pcm = ubi32_priv->pcm;
59173 +       free_irq(ubi32_priv->rx_irq, pcm);
59174 +}
59175 +
59176 +#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
59177 +#error "Change this table to match pcm.h"
59178 +#endif
59179 +static unsigned int rates[] __initdata = {5512, 8000, 11025, 16000, 22050,
59180 +                                         32000, 44100, 48000, 64000, 88200,
59181 +                                         96000, 176400, 192000};
59182 +
59183 +/*
59184 + * snd_ubi32_pcm_probe
59185 + */
59186 +int __devinit snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev)
59187 +{
59188 +       struct snd_pcm *pcm;
59189 +       int ret, err;
59190 +       int i;
59191 +       int j;
59192 +       int nrates;
59193 +       unsigned int rate_max = 0;
59194 +       unsigned int rate_min = 0xFFFFFFFF;
59195 +       unsigned int rate_mask = 0;
59196 +       struct audio_dev_regs *adr;
59197 +       struct resource *res_adr;
59198 +       struct resource *res_irq_tx;
59199 +       struct resource *res_irq_rx;
59200 +       struct ubi32pcm_platform_data *pdata;
59201 +
59202 +       pdata = pdev->dev.platform_data;
59203 +       if (!pdata) {
59204 +               return -ENODEV;
59205 +       }
59206 +
59207 +       /*
59208 +        * Get our resources, adr is the hardware driver base address
59209 +        * and the tx and rx irqs are used to communicate with the
59210 +        * hardware driver.
59211 +        */
59212 +       res_adr = platform_get_resource(pdev, IORESOURCE_MEM, AUDIO_MEM_RESOURCE);
59213 +       res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_TX_IRQ_RESOURCE);
59214 +       res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_RX_IRQ_RESOURCE);
59215 +       if (!res_adr || !res_irq_tx || !res_irq_rx) {
59216 +               snd_printk(KERN_WARNING "Could not get resources");
59217 +               return -ENODEV;
59218 +       }
59219 +
59220 +       ubi32_priv->ar = (struct audio_regs *)res_adr->start;
59221 +       ubi32_priv->tx_irq = res_irq_tx->start;
59222 +       ubi32_priv->rx_irq = res_irq_rx->start;
59223 +       ubi32_priv->irq_idx = pdata->inst_num;
59224 +       ubi32_priv->adr = &(ubi32_priv->ar->adr[pdata->inst_num]);
59225 +
59226 +       /*
59227 +        * Check the version
59228 +        */
59229 +       adr = ubi32_priv->adr;
59230 +       if (adr->version != AUDIO_DEV_REGS_VERSION) {
59231 +               snd_printk(KERN_WARNING "This audio_dev_reg is not compatible with this driver\n");
59232 +               return -ENODEV;
59233 +       }
59234 +
59235 +       /*
59236 +        * Find out the standard rates, also find max and min rates
59237 +        */
59238 +       for (i = 0; i < ARRAY_SIZE(rates); i++) {
59239 +               int found = 0;
59240 +               for (j = 0; j < adr->n_sample_rates; j++) {
59241 +                       if (rates[i] == adr->sample_rates[j]) {
59242 +                               /*
59243 +                                * Check to see if it is supported by the dac
59244 +                                */
59245 +                               if ((rates[i] >= ubi32_priv->min_sample_rate) &&
59246 +                                   (!ubi32_priv->max_sample_rate ||
59247 +                                    (ubi32_priv->max_sample_rate && (rates[i] <= ubi32_priv->max_sample_rate)))) {
59248 +                                       found = 1;
59249 +                                       rate_mask |= (1 << i);
59250 +                                       nrates++;
59251 +                                       if (rates[i] < rate_min) {
59252 +                                               rate_min = rates[i];
59253 +                                       }
59254 +                                       if (rates[i] > rate_max) {
59255 +                                               rate_max = rates[i];
59256 +                                       }
59257 +                                       break;
59258 +                               }
59259 +                       }
59260 +               }
59261 +               if (!found) {
59262 +                       rate_mask |= SNDRV_PCM_RATE_KNOT;
59263 +               }
59264 +       }
59265 +
59266 +       snd_ubi32_pcm_hw.rates = rate_mask;
59267 +       snd_ubi32_pcm_hw.rate_min = rate_min;
59268 +       snd_ubi32_pcm_hw.rate_max = rate_max;
59269 +       ubi32_pcm_rates.count = adr->n_sample_rates;
59270 +       ubi32_pcm_rates.list = (unsigned int *)adr->sample_rates;
59271 +       ubi32_pcm_rates.mask = 0;
59272 +
59273 +       for (i = 0; i < 32; i++) {
59274 +               if (adr->channel_mask & (1 << i)) {
59275 +                       if (!snd_ubi32_pcm_hw.channels_min) {
59276 +                               snd_ubi32_pcm_hw.channels_min = i;
59277 +                       }
59278 +                       snd_ubi32_pcm_hw.channels_max = i;
59279 +               }
59280 +       }
59281 +       snd_printk(KERN_INFO "Ubi32PCM: channels_min:%u channels_max:%u\n",
59282 +                  snd_ubi32_pcm_hw.channels_min,
59283 +                  snd_ubi32_pcm_hw.channels_max);
59284 +
59285 +       if (adr->caps & AUDIONODE_CAP_BE) {
59286 +               snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_BE;
59287 +       }
59288 +       if (adr->caps & AUDIONODE_CAP_LE) {
59289 +               snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
59290 +       }
59291 +
59292 +       snd_printk(KERN_INFO "Ubi32PCM: rates:%08x min:%u max:%u count:%d fmts:%016llx (%s)\n",
59293 +                  snd_ubi32_pcm_hw.rates,
59294 +                  snd_ubi32_pcm_hw.rate_min,
59295 +                  snd_ubi32_pcm_hw.rate_max,
59296 +                  ubi32_pcm_rates.count,
59297 +                  snd_ubi32_pcm_hw.formats,
59298 +                  ubi32_priv->is_capture ? "capture" : "playback");
59299 +
59300 +       if (ubi32_priv->is_capture) {
59301 +               ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 0, 1, &pcm);
59302 +       } else {
59303 +               ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 1, 0, &pcm);
59304 +       }
59305 +
59306 +       if (ret < 0) {
59307 +               return ret;
59308 +       }
59309 +
59310 +       pcm->private_data = ubi32_priv;
59311 +       ubi32_priv->pcm = pcm;
59312 +       ubi32_priv->pdata = pdata;
59313 +
59314 +       pcm->info_flags = 0;
59315 +
59316 +       strcpy(pcm->name, "Ubi32-PCM");
59317 +
59318 +       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
59319 +                                             snd_dma_continuous_data(GFP_KERNEL),
59320 +                                             45*1024, 64*1024);
59321 +
59322 +       if (ubi32_priv->is_capture) {
59323 +               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ubi32_pcm_ops);
59324 +       } else {
59325 +               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ubi32_pcm_ops);
59326 +       }
59327 +
59328 +       /*
59329 +        * Start up the audio device
59330 +        */
59331 +       adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
59332 +       adr->command = AUDIO_CMD_ENABLE;
59333 +       snd_ubi32_vp_int_set(pcm);
59334 +
59335 +       /*
59336 +        * Request IRQ
59337 +        */
59338 +       err = request_irq(ubi32_priv->rx_irq, snd_ubi32_pcm_interrupt, IRQF_SHARED | IRQF_DISABLED, pcm->name, pcm);
59339 +       if (err) {
59340 +               snd_printk(KERN_WARNING "request_irq failed: irq=%d err=%d\n", ubi32_priv->rx_irq, err);
59341 +               return -ENODEV;
59342 +       }
59343 +
59344 +       return ret;
59345 +
59346 +}