refresh patch
[lede.git] / target / linux / ubicom32 / patches-2.6.30 / 100-ubicom32_support.patch
1 --- /dev/null
2 +++ b/arch/ubicom32/crypto/aes_ubicom32.c
3 @@ -0,0 +1,458 @@
4 +/*
5 + * arch/ubicom32/crypto/aes_ubicom32.c
6 + *   Ubicom32 implementation of the AES Cipher Algorithm.
7 + *
8 + * (C) Copyright 2009, Ubicom, Inc.
9 + *
10 + * This file is part of the Ubicom32 Linux Kernel Port.
11 + *
12 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13 + * it and/or modify it under the terms of the GNU General Public License
14 + * as published by the Free Software Foundation, either version 2 of the
15 + * License, or (at your option) any later version.
16 + *
17 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
20 + * the GNU General Public License for more details.
21 + *
22 + * You should have received a copy of the GNU General Public License
23 + * along with the Ubicom32 Linux Kernel Port.  If not,
24 + * see <http://www.gnu.org/licenses/>.
25 + *
26 + * Ubicom32 implementation derived from (with many thanks):
27 + *   arch/m68knommu
28 + *   arch/blackfin
29 + *   arch/parisc
30 + */
31 +#include <crypto/aes.h>
32 +#include <crypto/algapi.h>
33 +#include <linux/err.h>
34 +#include <linux/module.h>
35 +#include <linux/init.h>
36 +#include <linux/spinlock.h>
37 +#include "crypto_ubicom32.h"
38 +#include <asm/linkage.h>
39 +
40 +struct ubicom32_aes_ctx {
41 +       u8 key[AES_MAX_KEY_SIZE];
42 +       u32 ctrl;
43 +       int key_len;
44 +};
45 +
46 +static inline void aes_hw_set_key(const u8 *key, u8 key_len)
47 +{
48 +       /*
49 +        * switch case has more overhead than 4 move.4 instructions, so just copy 256 bits
50 +        */
51 +       SEC_SET_KEY_256(key);
52 +}
53 +
54 +static inline void aes_hw_set_iv(const u8 *iv)
55 +{
56 +       SEC_SET_IV_4W(iv);
57 +}
58 +
59 +static inline void aes_hw_cipher(u8 *out, const u8 *in)
60 +{
61 +       SEC_SET_INPUT_4W(in);
62 +
63 +       asm volatile (
64 +       "       ; start AES by writing 0x40(SECURITY_BASE)      \n\t"
65 +       "       move.4 0x40(%0), #0x01                          \n\t"
66 +       "       pipe_flush 0                                    \n\t"
67 +       "                                                       \n\t"
68 +       "       ; wait for the module to calculate the output   \n\t"
69 +       "       btst 0x04(%0), #0                               \n\t"
70 +       "       jmpne.f .-4                                     \n\t"
71 +               :
72 +               : "a" (SEC_BASE)
73 +               : "cc"
74 +       );
75 +
76 +       SEC_GET_OUTPUT_4W(out);
77 +}
78 +
79 +static int __ocm_text aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
80 +                      unsigned int key_len)
81 +{
82 +       struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
83 +
84 +       uctx->key_len = key_len;
85 +       memcpy(uctx->key, in_key, key_len);
86 +
87 +       /*
88 +        * leave out HASH_ALG (none = 0), CBC (no = 0), DIR (unknown) yet
89 +        */
90 +       switch (uctx->key_len) {
91 +       case 16:
92 +               uctx->ctrl = SEC_KEY_128_BITS | SEC_ALG_AES;
93 +               break;
94 +       case 24:
95 +               uctx->ctrl = SEC_KEY_192_BITS | SEC_ALG_AES;
96 +               break;
97 +       case 32:
98 +               uctx->ctrl = SEC_KEY_256_BITS | SEC_ALG_AES;
99 +               break;
100 +       }
101 +
102 +       return 0;
103 +}
104 +
105 +static inline void aes_cipher(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
106 +{
107 +       const struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
108 +
109 +       hw_crypto_lock();
110 +       hw_crypto_check();
111 +       hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
112 +
113 +       aes_hw_set_key(uctx->key, uctx->key_len);
114 +       aes_hw_cipher(out, in);
115 +
116 +       hw_crypto_unlock();
117 +}
118 +
119 +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
120 +{
121 +       aes_cipher(tfm, out, in, SEC_DIR_ENCRYPT);
122 +}
123 +
124 +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
125 +{
126 +       aes_cipher(tfm, out, in, SEC_DIR_DECRYPT);
127 +}
128 +
129 +static struct crypto_alg aes_alg = {
130 +       .cra_name               =       "aes",
131 +       .cra_driver_name        =       "aes-ubicom32",
132 +       .cra_priority           =       CRYPTO_UBICOM32_PRIORITY,
133 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
134 +       .cra_blocksize          =       AES_BLOCK_SIZE,
135 +       .cra_ctxsize            =       sizeof(struct ubicom32_aes_ctx),
136 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
137 +       .cra_module             =       THIS_MODULE,
138 +       .cra_list               =       LIST_HEAD_INIT(aes_alg.cra_list),
139 +       .cra_u                  =       {
140 +               .cipher = {
141 +                       .cia_min_keysize        =       AES_MIN_KEY_SIZE,
142 +                       .cia_max_keysize        =       AES_MAX_KEY_SIZE,
143 +                       .cia_setkey             =       aes_set_key,
144 +                       .cia_encrypt            =       aes_encrypt,
145 +                       .cia_decrypt            =       aes_decrypt,
146 +               }
147 +       }
148 +};
149 +
150 +static void __ocm_text ecb_aes_crypt_loop(u8 *out, u8 *in, unsigned int n)
151 +{
152 +       while (likely(n)) {
153 +               aes_hw_cipher(out, in);
154 +               out += AES_BLOCK_SIZE;
155 +               in += AES_BLOCK_SIZE;
156 +               n -= AES_BLOCK_SIZE;
157 +       }
158 +}
159 +
160 +static int __ocm_text ecb_aes_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
161 +                        struct scatterlist *src, unsigned int nbytes, u32 extra_flags)
162 +{
163 +       const struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
164 +       int ret;
165 +
166 +       struct blkcipher_walk walk;
167 +       blkcipher_walk_init(&walk, dst, src, nbytes);
168 +       ret = blkcipher_walk_virt(desc, &walk);
169 +        if (ret) {
170 +                return ret;
171 +        }
172 +
173 +       hw_crypto_lock();
174 +       hw_crypto_check();
175 +
176 +        hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
177 +        aes_hw_set_key(uctx->key, uctx->key_len);
178 +
179 +       while (likely((nbytes = walk.nbytes))) {
180 +               /* only use complete blocks */
181 +               unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
182 +               u8 *out = walk.dst.virt.addr;
183 +               u8 *in = walk.src.virt.addr;
184 +
185 +               /* finish n/16 blocks */
186 +               ecb_aes_crypt_loop(out, in, n);
187 +
188 +               nbytes &= AES_BLOCK_SIZE - 1;
189 +               ret = blkcipher_walk_done(desc, &walk, nbytes);
190 +       }
191 +
192 +       hw_crypto_unlock();
193 +       return ret;
194 +}
195 +
196 +static int ecb_aes_encrypt(struct blkcipher_desc *desc,
197 +                          struct scatterlist *dst, struct scatterlist *src,
198 +                          unsigned int nbytes)
199 +{
200 +       return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT);
201 +}
202 +
203 +static int ecb_aes_decrypt(struct blkcipher_desc *desc,
204 +                          struct scatterlist *dst, struct scatterlist *src,
205 +                          unsigned int nbytes)
206 +{
207 +       return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT);
208 +}
209 +
210 +static struct crypto_alg ecb_aes_alg = {
211 +       .cra_name               =       "ecb(aes)",
212 +       .cra_driver_name        =       "ecb-aes-ubicom32",
213 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
214 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
215 +       .cra_blocksize          =       AES_BLOCK_SIZE,
216 +       .cra_ctxsize            =       sizeof(struct ubicom32_aes_ctx),
217 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
218 +       .cra_type               =       &crypto_blkcipher_type,
219 +       .cra_module             =       THIS_MODULE,
220 +       .cra_list               =       LIST_HEAD_INIT(ecb_aes_alg.cra_list),
221 +       .cra_u                  =       {
222 +               .blkcipher = {
223 +                       .min_keysize            =       AES_MIN_KEY_SIZE,
224 +                       .max_keysize            =       AES_MAX_KEY_SIZE,
225 +                       .setkey                 =       aes_set_key,
226 +                       .encrypt                =       ecb_aes_encrypt,
227 +                       .decrypt                =       ecb_aes_decrypt,
228 +               }
229 +       }
230 +};
231 +
232 +#if CRYPTO_UBICOM32_LOOP_ASM
233 +void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
234 +{
235 +       asm volatile (
236 +       "; set init. iv 4w                      \n\t"
237 +       "       move.4 0x50(%0), 0x0(%3)        \n\t"
238 +       "       move.4 0x54(%0), 0x4(%3)        \n\t"
239 +       "       move.4 0x58(%0), 0x8(%3)        \n\t"
240 +       "       move.4 0x5c(%0), 0xc(%3)        \n\t"
241 +       "                                       \n\t"
242 +       "; we know n > 0, so we can always      \n\t"
243 +       "; load the first block                 \n\t"
244 +       "; set input 4w                         \n\t"
245 +       "       move.4 0x30(%0), 0x0(%2)        \n\t"
246 +       "       move.4 0x34(%0), 0x4(%2)        \n\t"
247 +       "       move.4 0x38(%0), 0x8(%2)        \n\t"
248 +       "       move.4 0x3c(%0), 0xc(%2)        \n\t"
249 +       "                                       \n\t"
250 +       "; kickoff hw                           \n\t"
251 +       "       move.4 0x40(%0), %2             \n\t"
252 +       "                                       \n\t"
253 +       "; update n & flush                     \n\t"
254 +       "       add.4 %4, #-16, %4              \n\t"
255 +       "       pipe_flush 0                    \n\t"
256 +       "                                       \n\t"
257 +       "; while (n):  work on 2nd block        \n\t"
258 +       " 1:    lsl.4 d15, %4, #0x0             \n\t"
259 +       "       jmpeq.f 5f                      \n\t"
260 +       "                                       \n\t"
261 +       "; set input 4w (2nd)                   \n\t"
262 +       "       move.4 0x30(%0), 0x10(%2)       \n\t"
263 +       "       move.4 0x34(%0), 0x14(%2)       \n\t"
264 +       "       move.4 0x38(%0), 0x18(%2)       \n\t"
265 +       "       move.4 0x3c(%0), 0x1c(%2)       \n\t"
266 +       "                                       \n\t"
267 +       "; update n/in asap while waiting       \n\t"
268 +       "       add.4 %4, #-16, %4              \n\t"
269 +       "       move.4 d15, 16(%2)++            \n\t"
270 +       "                                       \n\t"
271 +       "; wait for the previous output         \n\t"
272 +       "       btst 0x04(%0), #0               \n\t"
273 +       "       jmpne.f -4                      \n\t"
274 +       "                                       \n\t"
275 +       "; read previous output                 \n\t"
276 +       "       move.4 0x0(%1), 0x50(%0)        \n\t"
277 +       "       move.4 0x4(%1), 0x54(%0)        \n\t"
278 +       "       move.4 0x8(%1), 0x58(%0)        \n\t"
279 +       "       move.4 0xc(%1), 0x5c(%0)        \n\t"
280 +       "                                       \n\t"
281 +       "; kick off hw for 2nd input            \n\t"
282 +       "       move.4 0x40(%0), %2             \n\t"
283 +       "                                       \n\t"
284 +       "; update out asap                      \n\t"
285 +       "       move.4 d15, 16(%1)++            \n\t"
286 +       "                                       \n\t"
287 +       "; go back to loop                      \n\t"
288 +       "       jmpt 1b                         \n\t"
289 +       "                                       \n\t"
290 +       "; wait for last output                 \n\t"
291 +       " 5:    btst 0x04(%0), #0               \n\t"
292 +        "       jmpne.f -4                      \n\t"
293 +        "                                       \n\t"
294 +       "; read last output                     \n\t"
295 +       "       move.4 0x0(%1), 0x50(%0)        \n\t"
296 +       "       move.4 0x4(%1), 0x54(%0)        \n\t"
297 +       "       move.4 0x8(%1), 0x58(%0)        \n\t"
298 +       "       move.4 0xc(%1), 0x5c(%0)        \n\t"
299 +        "                                       \n\t"
300 +       "; copy out iv                          \n\t"
301 +       "       move.4 0x0(%3), 0x50(%0)        \n\t"
302 +       "       move.4 0x4(%3), 0x54(%0)        \n\t"
303 +       "       move.4 0x8(%3), 0x58(%0)        \n\t"
304 +       "       move.4 0xc(%3), 0x5c(%0)        \n\t"
305 +        "                                       \n\t"
306 +               :
307 +               : "a" (SEC_BASE), "a" (out), "a" (in), "a" (iv), "d" (n)
308 +               : "d15", "cc"
309 +       );
310 +}
311 +
312 +#else
313 +
314 +static void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
315 +{
316 +       aes_hw_set_iv(iv);
317 +       while (likely(n)) {
318 +               aes_hw_cipher(out, in);
319 +               out += AES_BLOCK_SIZE;
320 +               in += AES_BLOCK_SIZE;
321 +               n -= AES_BLOCK_SIZE;
322 +       }
323 +       SEC_COPY_4W(iv, out - AES_BLOCK_SIZE);
324 +}
325 +
326 +#endif
327 +
328 +static void __ocm_text cbc_aes_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
329 +{
330 +        while (likely(n)) {
331 +                aes_hw_set_iv(iv);
332 +               SEC_COPY_4W(iv, in);
333 +                aes_hw_cipher(out, in);
334 +                out += AES_BLOCK_SIZE;
335 +                in += AES_BLOCK_SIZE;
336 +                n -= AES_BLOCK_SIZE;
337 +        }
338 +}
339 +
340 +static int __ocm_text cbc_aes_crypt(struct blkcipher_desc *desc,
341 +                           struct scatterlist *dst, struct scatterlist *src,
342 +                           unsigned int nbytes, u32 extra_flags)
343 +{
344 +       struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
345 +       int ret;
346 +
347 +        struct blkcipher_walk walk;
348 +        blkcipher_walk_init(&walk, dst, src, nbytes);
349 +       ret = blkcipher_walk_virt(desc, &walk);
350 +       if (unlikely(ret)) {
351 +               return ret;
352 +       }
353 +
354 +        hw_crypto_lock();
355 +       hw_crypto_check();
356 +
357 +        hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
358 +        aes_hw_set_key(uctx->key, uctx->key_len);
359 +
360 +       while (likely((nbytes = walk.nbytes))) {
361 +                /* only use complete blocks */
362 +                unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
363 +               if (likely(n)) {
364 +                       u8 *out = walk.dst.virt.addr;
365 +                       u8 *in = walk.src.virt.addr;
366 +
367 +                       if (extra_flags & SEC_DIR_ENCRYPT) {
368 +                               cbc_aes_encrypt_loop(out, in, walk.iv, n);
369 +                       } else {
370 +                               cbc_aes_decrypt_loop(out, in, walk.iv, n);
371 +                       }
372 +               }
373 +
374 +               nbytes &= AES_BLOCK_SIZE - 1;
375 +                ret = blkcipher_walk_done(desc, &walk, nbytes);
376 +       }
377 +       hw_crypto_unlock();
378 +
379 +       return ret;
380 +}
381 +
382 +static int __ocm_text cbc_aes_encrypt(struct blkcipher_desc *desc,
383 +                          struct scatterlist *dst, struct scatterlist *src,
384 +                          unsigned int nbytes)
385 +{
386 +       return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT | SEC_CBC_SET);
387 +}
388 +
389 +static int __ocm_text cbc_aes_decrypt(struct blkcipher_desc *desc,
390 +                          struct scatterlist *dst, struct scatterlist *src,
391 +                          unsigned int nbytes)
392 +{
393 +       return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT | SEC_CBC_SET);
394 +}
395 +
396 +static struct crypto_alg cbc_aes_alg = {
397 +       .cra_name               =       "cbc(aes)",
398 +       .cra_driver_name        =       "cbc-aes-ubicom32",
399 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
400 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
401 +       .cra_blocksize          =       AES_BLOCK_SIZE,
402 +       .cra_ctxsize            =       sizeof(struct ubicom32_aes_ctx),
403 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
404 +       .cra_type               =       &crypto_blkcipher_type,
405 +       .cra_module             =       THIS_MODULE,
406 +       .cra_list               =       LIST_HEAD_INIT(cbc_aes_alg.cra_list),
407 +       .cra_u                  =       {
408 +               .blkcipher = {
409 +                       .min_keysize            =       AES_MIN_KEY_SIZE,
410 +                       .max_keysize            =       AES_MAX_KEY_SIZE,
411 +                       .ivsize                 =       AES_BLOCK_SIZE,
412 +                       .setkey                 =       aes_set_key,
413 +                       .encrypt                =       cbc_aes_encrypt,
414 +                       .decrypt                =       cbc_aes_decrypt,
415 +               }
416 +       }
417 +};
418 +
419 +static int __init aes_init(void)
420 +{
421 +       int ret;
422 +
423 +       hw_crypto_init();
424 +
425 +       ret = crypto_register_alg(&aes_alg);
426 +       if (ret)
427 +               goto aes_err;
428 +
429 +       ret = crypto_register_alg(&ecb_aes_alg);
430 +       if (ret)
431 +               goto ecb_aes_err;
432 +
433 +       ret = crypto_register_alg(&cbc_aes_alg);
434 +       if (ret)
435 +               goto cbc_aes_err;
436 +
437 +out:
438 +       return ret;
439 +
440 +cbc_aes_err:
441 +       crypto_unregister_alg(&ecb_aes_alg);
442 +ecb_aes_err:
443 +       crypto_unregister_alg(&aes_alg);
444 +aes_err:
445 +       goto out;
446 +}
447 +
448 +static void __exit aes_fini(void)
449 +{
450 +       crypto_unregister_alg(&cbc_aes_alg);
451 +       crypto_unregister_alg(&ecb_aes_alg);
452 +       crypto_unregister_alg(&aes_alg);
453 +}
454 +
455 +module_init(aes_init);
456 +module_exit(aes_fini);
457 +
458 +MODULE_ALIAS("aes");
459 +
460 +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
461 +MODULE_LICENSE("GPL");
462 --- /dev/null
463 +++ b/arch/ubicom32/crypto/crypto_des.h
464 @@ -0,0 +1,34 @@
465 +/*
466 + * arch/ubicom32/crypto/crypto_des.h
467 + *   Function for checking keys for the DES and Triple DES Encryption
468 + *   algorithms.
469 + *
470 + * (C) Copyright 2009, Ubicom, Inc.
471 + *
472 + * This file is part of the Ubicom32 Linux Kernel Port.
473 + *
474 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
475 + * it and/or modify it under the terms of the GNU General Public License
476 + * as published by the Free Software Foundation, either version 2 of the
477 + * License, or (at your option) any later version.
478 + *
479 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
480 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
481 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
482 + * the GNU General Public License for more details.
483 + *
484 + * You should have received a copy of the GNU General Public License
485 + * along with the Ubicom32 Linux Kernel Port.  If not,
486 + * see <http://www.gnu.org/licenses/>.
487 + *
488 + * Ubicom32 implementation derived from (with many thanks):
489 + *   arch/m68knommu
490 + *   arch/blackfin
491 + *   arch/parisc
492 + */
493 +#ifndef __CRYPTO_DES_H__
494 +#define __CRYPTO_DES_H__
495 +
496 +extern int crypto_des_check_key(const u8*, unsigned int, u32*);
497 +
498 +#endif /* __CRYPTO_DES_H__ */
499 --- /dev/null
500 +++ b/arch/ubicom32/crypto/crypto_ubicom32.c
501 @@ -0,0 +1,50 @@
502 +/*
503 + * arch/ubicom32/crypto/crypto_ubicom32.c
504 + *   Generic code to support ubicom32 hardware crypto accelerator
505 + *
506 + * (C) Copyright 2009, Ubicom, Inc.
507 + *
508 + * This file is part of the Ubicom32 Linux Kernel Port.
509 + *
510 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
511 + * it and/or modify it under the terms of the GNU General Public License
512 + * as published by the Free Software Foundation, either version 2 of the
513 + * License, or (at your option) any later version.
514 + *
515 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
516 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
517 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
518 + * the GNU General Public License for more details.
519 + *
520 + * You should have received a copy of the GNU General Public License
521 + * along with the Ubicom32 Linux Kernel Port.  If not,
522 + * see <http://www.gnu.org/licenses/>.
523 + *
524 + * Ubicom32 implementation derived from (with many thanks):
525 + *   arch/m68knommu
526 + *   arch/blackfin
527 + *   arch/parisc
528 + */
529 +#include "crypto_ubicom32.h"
530 +
531 +spinlock_t crypto_ubicom32_lock;
532 +bool crypto_ubicom32_inited = false;
533 +volatile bool crypto_ubicom32_on = false;
534 +volatile unsigned long crypto_ubicom32_last_use;
535 +
536 +struct timer_list crypto_ubicom32_ps_timer;
537 +void crypto_ubicom32_ps_check(unsigned long data)
538 +{
539 +       unsigned long idle_time = msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS);
540 +
541 +       BUG_ON(!crypto_ubicom32_on);
542 +
543 +       if (((jiffies - crypto_ubicom32_last_use) > idle_time) && spin_trylock_bh(&crypto_ubicom32_lock)) {
544 +                hw_crypto_turn_off();
545 +                spin_unlock_bh(&crypto_ubicom32_lock);
546 +               return;
547 +       }
548 +
549 +       /* keep monitoring */
550 +       hw_crypto_ps_start();
551 +}
552 --- /dev/null
553 +++ b/arch/ubicom32/crypto/crypto_ubicom32.h
554 @@ -0,0 +1,346 @@
555 +/*
556 + * arch/ubicom32/crypto/crypto_ubicom32.h
557 + *   Support for Ubicom32 cryptographic instructions.
558 + *
559 + * (C) Copyright 2009, Ubicom, Inc.
560 + *
561 + * This file is part of the Ubicom32 Linux Kernel Port.
562 + *
563 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
564 + * it and/or modify it under the terms of the GNU General Public License
565 + * as published by the Free Software Foundation, either version 2 of the
566 + * License, or (at your option) any later version.
567 + *
568 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
569 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
570 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
571 + * the GNU General Public License for more details.
572 + *
573 + * You should have received a copy of the GNU General Public License
574 + * along with the Ubicom32 Linux Kernel Port.  If not,
575 + * see <http://www.gnu.org/licenses/>.
576 + *
577 + * Ubicom32 implementation derived from (with many thanks):
578 + *   arch/m68knommu
579 + *   arch/blackfin
580 + *   arch/parisc
581 + */
582 +#ifndef _CRYPTO_ARCH_UBICOM32_CRYPT_H
583 +#define _CRYPTO_ARCH_UBICOM32_CRYPT_H
584 +
585 +#include <linux/module.h>
586 +#include <linux/kernel.h>
587 +#include <linux/jiffies.h>
588 +#include <linux/timer.h>
589 +#include <linux/spinlock.h>
590 +#include <asm/errno.h>
591 +#include <asm/io.h>
592 +#include <asm/ip5000.h>
593 +
594 +#define CRYPTO_UBICOM32_LOOP_ASM 1
595 +#define CRYPTO_UBICOM32_ALIGNMENT 4
596 +#define SEC_ALIGNED(p) (((u32)p & 3) == 0)
597 +
598 +#define SEC_BASE               SECURITY_BASE
599 +#define SEC_KEY_OFFSET         SECURITY_KEY_VALUE(0)
600 +#define SEC_INPUT_OFFSET       SECURITY_KEY_IN(0)
601 +#define SEC_OUTPUT_OFFSET      SECURITY_KEY_OUT(0)
602 +#define SEC_HASH_OFFSET                SECURITY_KEY_HASH(0)
603 +
604 +#define SEC_KEY_128_BITS       SECURITY_CTRL_KEY_SIZE(0)
605 +#define SEC_KEY_192_BITS       SECURITY_CTRL_KEY_SIZE(1)
606 +#define SEC_KEY_256_BITS       SECURITY_CTRL_KEY_SIZE(2)
607 +
608 +#define SEC_HASH_NONE          SECURITY_CTRL_HASH_ALG_NONE
609 +#define SEC_HASH_MD5           SECURITY_CTRL_HASH_ALG_MD5
610 +#define SEC_HASH_SHA1          SECURITY_CTRL_HASH_ALG_SHA1
611 +
612 +#define SEC_CBC_SET            SECURITY_CTRL_CBC
613 +#define SEC_CBC_NONE           0
614 +
615 +#define SEC_ALG_AES            SECURITY_CTRL_CIPHER_ALG_AES
616 +#define SEC_ALG_NONE           SECURITY_CTRL_CIPHER_ALG_NONE
617 +#define SEC_ALG_DES            SECURITY_CTRL_CIPHER_ALG_DES
618 +#define SEC_ALG_3DES           SECURITY_CTRL_CIPHER_ALG_3DES
619 +
620 +#define SEC_DIR_ENCRYPT                SECURITY_CTRL_ENCIPHER
621 +#define SEC_DIR_DECRYPT                0
622 +
623 +#define CRYPTO_UBICOM32_PRIORITY 300
624 +#define CRYPTO_UBICOM32_COMPOSITE_PRIORITY 400
625 +
626 +#define HW_CRYPTO_PS_MAX_IDLE_MS 100    /* idle time (ms) before shuting down sm */
627 +
628 +extern spinlock_t crypto_ubicom32_lock;
629 +extern bool crypto_ubicom32_inited;
630 +extern volatile bool crypto_ubicom32_on;
631 +extern volatile unsigned long crypto_ubicom32_last_use;
632 +extern struct timer_list crypto_ubicom32_ps_timer;
633 +extern void crypto_ubicom32_ps_check(unsigned long data);
634 +
635 +#define SEC_COPY_2W(t, s)                              \
636 +       asm volatile (                                  \
637 +       "       move.4 0(%0), 0(%1)             \n\t"   \
638 +       "       move.4 4(%0), 4(%1)             \n\t"   \
639 +                                                       \
640 +               :                                       \
641 +               : "a" (t), "a" (s)                      \
642 +       )
643 +
644 +#define SEC_COPY_4W(t, s)                              \
645 +       asm volatile (                                  \
646 +       "       move.4 0(%0), 0(%1)             \n\t"   \
647 +       "       move.4 4(%0), 4(%1)             \n\t"   \
648 +       "       move.4 8(%0), 8(%1)             \n\t"   \
649 +       "       move.4 12(%0), 12(%1)           \n\t"   \
650 +               :                                       \
651 +               : "a" (t), "a" (s)                      \
652 +       )
653 +
654 +#define SEC_COPY_5W(t, s)                              \
655 +       asm volatile (                                  \
656 +       "       move.4 0(%0), 0(%1)             \n\t"   \
657 +       "       move.4 4(%0), 4(%1)             \n\t"   \
658 +       "       move.4 8(%0), 8(%1)             \n\t"   \
659 +       "       move.4 12(%0), 12(%1)           \n\t"   \
660 +       "       move.4 16(%0), 16(%1)           \n\t"   \
661 +               :                                       \
662 +               : "a" (t), "a" (s)                      \
663 +       )
664 +
665 +#define SEC_SET_KEY_2W(x)                              \
666 +       asm volatile (                                  \
667 +       "       ; write key to Security Keyblock \n\t"  \
668 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
669 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
670 +               :                                       \
671 +               : "a" (SECURITY_BASE), "a" (x)          \
672 +       )
673 +
674 +#define SEC_SET_KEY_4W(x) \
675 +       asm volatile ( \
676 +       "       ; write key to Security Keyblock \n\t"  \
677 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
678 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
679 +       "       move.4 0x18(%0), 8(%1)          \n\t"   \
680 +       "       move.4 0x1c(%0), 12(%1)         \n\t"   \
681 +               :                                       \
682 +               : "a"(SECURITY_BASE), "a"(x)            \
683 +       )
684 +
685 +#define SEC_SET_KEY_6W(x)                              \
686 +       asm volatile (                                  \
687 +       "       ; write key to Security Keyblock \n\t"  \
688 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
689 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
690 +       "       move.4 0x18(%0), 8(%1)          \n\t"   \
691 +       "       move.4 0x1c(%0), 12(%1)         \n\t"   \
692 +       "       move.4 0x20(%0), 16(%1)         \n\t"   \
693 +       "       move.4 0x24(%0), 20(%1)         \n\t"   \
694 +               :                                       \
695 +               : "a" (SECURITY_BASE), "a" (x)          \
696 +       )
697 +
698 +#define SEC_SET_KEY_8W(x)                              \
699 +       asm volatile (                                  \
700 +       "       ; write key to Security Keyblock \n\t"  \
701 +       "       move.4 0x10(%0), 0(%1)          \n\t"   \
702 +       "       move.4 0x14(%0), 4(%1)          \n\t"   \
703 +       "       move.4 0x18(%0), 8(%1)          \n\t"   \
704 +       "       move.4 0x1c(%0), 12(%1)         \n\t"   \
705 +       "       move.4 0x20(%0), 16(%1)         \n\t"   \
706 +       "       move.4 0x24(%0), 20(%1)         \n\t"   \
707 +       "       move.4 0x28(%0), 24(%1)         \n\t"   \
708 +       "       move.4 0x2c(%0), 28(%1)         \n\t"   \
709 +               :                                       \
710 +               : "a" (SECURITY_BASE), "a" (x)          \
711 +       )
712 +
713 +#define SEC_SET_KEY_64(k)      SEC_SET_KEY_2W(k)
714 +#define SEC_SET_KEY_128(k)     SEC_SET_KEY_4W(k)
715 +#define SEC_SET_KEY_192(k)     SEC_SET_KEY_6W(k)
716 +#define SEC_SET_KEY_256(k)     SEC_SET_KEY_8W(k)
717 +
718 +#define DES_SET_KEY(x)                 SEC_SET_KEY_64(x)
719 +#define DES3_SET_KEY(x)        SEC_SET_KEY_192(x)
720 +
721 +#define SEC_SET_INPUT_2W(x)                            \
722 +       asm volatile (                                  \
723 +       "       ; write key to Security Keyblock \n\t"  \
724 +       "       move.4 0x30(%0), 0(%1)          \n\t"   \
725 +       "       move.4 0x34(%0), 4(%1)          \n\t"   \
726 +               :                                       \
727 +               : "a" (SECURITY_BASE), "a" (x)          \
728 +       )
729 +
730 +#define SEC_GET_OUTPUT_2W(x)                           \
731 +       asm volatile (                                  \
732 +       "       ; write key to Security Keyblock \n\t"  \
733 +       "       move.4 0(%1), 0x50(%0)          \n\t"   \
734 +       "       move.4 4(%1), 0x54(%0)          \n\t"   \
735 +               :                                       \
736 +               : "a" (SECURITY_BASE), "a" (x)          \
737 +       )
738 +
739 +#define SEC_SET_INPUT_4W(x) \
740 +       asm volatile ( \
741 +       "       ; write key to Security Keyblock \n\t"  \
742 +       "       move.4 0x30(%0), 0(%1)          \n\t"   \
743 +       "       move.4 0x34(%0), 4(%1)          \n\t"   \
744 +       "       move.4 0x38(%0), 8(%1)          \n\t"   \
745 +       "       move.4 0x3c(%0), 12(%1)         \n\t"   \
746 +               :                                       \
747 +               : "a" (SECURITY_BASE), "a" (x)          \
748 +       )
749 +
750 +#define SEC_GET_OUTPUT_4W(x)                           \
751 +       asm volatile (                                  \
752 +       "       ; read output from Security Keyblock \n\t" \
753 +       "       move.4 0(%1), 0x50(%0)          \n\t"   \
754 +       "       move.4 4(%1), 0x54(%0)          \n\t"   \
755 +       "       move.4 8(%1), 0x58(%0)          \n\t"   \
756 +       "       move.4 12(%1), 0x5c(%0)         \n\t"   \
757 +               :                                       \
758 +               : "a" (SECURITY_BASE), "a" (x)          \
759 +       )
760 +
761 +#define SEC_SET_IV_4W(x)                               \
762 +       asm volatile (                                  \
763 +       "       ; write IV to Security Keyblock  \n\t"  \
764 +       "       move.4 0x50(%0), 0(%1)          \n\t"   \
765 +       "       move.4 0x54(%0), 4(%1)          \n\t"   \
766 +       "       move.4 0x58(%0), 8(%1)          \n\t"   \
767 +       "       move.4 0x5c(%0), 12(%1)         \n\t"   \
768 +               :                                       \
769 +               : "a" (SECURITY_BASE), "a" (x)          \
770 +       )
771 +
772 +#define SEC_PIPE_FLUSH() asm volatile ( " pipe_flush 0 \n\t" )
773 +
774 +static inline void hw_crypto_set_ctrl(uint32_t c)
775 +{
776 +       asm volatile (
777 +       "       move.4  0(%0), %1               \n\t"
778 +               :
779 +               : "a" (SECURITY_BASE + SECURITY_CTRL), "d" (c)
780 +       );
781 +}
782 +
783 +static inline void hw_crypto_ps_start(void)
784 +{
785 +       crypto_ubicom32_ps_timer.expires = jiffies + msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS >> 1);
786 +       add_timer(&crypto_ubicom32_ps_timer);
787 +}
788 +
789 +static inline void hw_crypto_turn_on(void)
790 +{
791 +       asm volatile (
792 +       "       moveai  A4, %0                  \n\t"
793 +       "       bset    0x0(A4), 0x0(A4), %1    \n\t"
794 +       "       cycles 11                       \n\t"
795 +               :
796 +               : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
797 +               : "a4", "cc"
798 +       );
799 +       crypto_ubicom32_on = true;
800 +}
801 +
802 +static inline void hw_crypto_turn_off(void)
803 +{
804 +       asm volatile (
805 +       "       moveai  A4, %0                  \n\t"
806 +       "       bclr    0x0(A4), 0x0(A4), %1    \n\t"
807 +               :
808 +               : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
809 +               : "a4", "cc"
810 +       );
811 +       crypto_ubicom32_on = false;
812 +}
813 +
814 +/*
815 + * hw_crypto_check
816 + *     Most probably hw crypto is called in clusters and it makes no sense to turn it off
817 + *     and on and waster 13 cycles every time.
818 + */
819 +static inline void hw_crypto_check(void)
820 +{
821 +       if (likely(crypto_ubicom32_on)) {
822 +               return;
823 +       }
824 +       crypto_ubicom32_last_use = jiffies;
825 +       hw_crypto_turn_on();
826 +       hw_crypto_ps_start();
827 +}
828 +
829 +/*
830 + * hw_crypto_ps_init
831 + *     Init power save timer
832 + */
833 +static inline void hw_crypto_ps_init(void)
834 +{
835 +       init_timer_deferrable(&crypto_ubicom32_ps_timer);
836 +       crypto_ubicom32_ps_timer.function = crypto_ubicom32_ps_check;
837 +       crypto_ubicom32_ps_timer.data = 0;
838 +}
839 +
840 +/*
841 + * hw_crypto_init()
842 + *      Initialize OCP security module lock and disables its clock.
843 + */
844 +static inline void hw_crypto_init(void)
845 +{
846 +       if (!crypto_ubicom32_inited) {
847 +               crypto_ubicom32_inited = true;
848 +               spin_lock_init(&crypto_ubicom32_lock);
849 +               hw_crypto_ps_init();
850 +               hw_crypto_turn_off();
851 +       }
852 +}
853 +
854 +/*
855 + * hw_crypto_lock()
856 + *      Locks the OCP security module and enables its clock.
857 + */
858 +static inline void hw_crypto_lock(void)
859 +{
860 +       spin_lock_bh(&crypto_ubicom32_lock);
861 +}
862 +
863 +/*
864 + * hw_crypto_unlock()
865 + *      Unlocks the OCP security module and disables its clock.
866 + */
867 +static inline void hw_crypto_unlock(void)
868 +{
869 +       crypto_ubicom32_last_use = jiffies;
870 +       spin_unlock_bh(&crypto_ubicom32_lock);
871 +}
872 +
873 +#define CONFIG_CRYPTO_UBICOM32_DEBUG 1
874 +
875 +#ifdef CONFIG_CRYPTO_UBICOM32_DEBUG
876 +static inline void hex_dump(void *buf, int b_size, const char *msg)
877 +{
878 +       u8 *b = (u8 *)buf;
879 +       int i;
880 +       if (msg) {
881 +               printk("%s:\t", msg);
882 +       }
883 +
884 +       for (i=0; i < b_size; i++) {
885 +               printk("%02x ", b[i]);
886 +               if ((i & 3) == 3) {
887 +                       printk(" ");
888 +               }
889 +               if ((i & 31) == 31) {
890 +                       printk("\n");
891 +               }
892 +       }
893 +       printk("\n");
894 +}
895 +#define UBICOM32_SEC_DUMP(a, b, c) hex_dump(a, b, c)
896 +#else
897 +#define UBICOM32_SEC_DUMP(a, b, c)
898 +#endif
899 +
900 +#endif /* _CRYPTO_ARCH_UBICOM32_CRYPT_H */
901 --- /dev/null
902 +++ b/arch/ubicom32/crypto/des_check_key.c
903 @@ -0,0 +1,148 @@
904 +/*
905 + * arch/ubicom32/crypto/des_check_key.c
906 + *   Ubicom32 architecture function for checking keys for the DES and
907 + *   Tripple DES Encryption algorithms.
908 + *
909 + * (C) Copyright 2009, Ubicom, Inc.
910 + *
911 + * Originally released as descore by Dana L. How <how@isl.stanford.edu>.
912 + * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel.
913 + * Derived from Cryptoapi and Nettle implementations, adapted for in-place
914 + * scatterlist interface.  Changed LGPL to GPL per section 3 of the LGPL.
915 + *
916 + * s390 Version:
917 + *   Copyright IBM Corp. 2003
918 + *   Author(s): Thomas Spatzier
919 + *             Jan Glauber (jan.glauber@de.ibm.com)
920 + *
921 + * Derived from "crypto/des.c"
922 + *   Copyright (c) 1992 Dana L. How.
923 + *   Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de>
924 + *   Copyright (c) Gisle Sflensminde <gisle@ii.uib.no>
925 + *   Copyright (C) 2001 Niels Mvller.
926 + *   Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
927 + *
928 + * This file is part of the Ubicom32 Linux Kernel Port.
929 + *
930 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
931 + * it and/or modify it under the terms of the GNU General Public License
932 + * as published by the Free Software Foundation, either version 2 of the
933 + * License, or (at your option) any later version.
934 + *
935 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
936 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
937 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
938 + * the GNU General Public License for more details.
939 + *
940 + * You should have received a copy of the GNU General Public License
941 + * along with the Ubicom32 Linux Kernel Port.  If not,
942 + * see <http://www.gnu.org/licenses/>.
943 + *
944 + * Ubicom32 implementation derived from (with many thanks):
945 + *   arch/m68knommu
946 + *   arch/blackfin
947 + *   arch/parisc
948 + */
949 +#include <linux/init.h>
950 +#include <linux/module.h>
951 +#include <linux/errno.h>
952 +#include <linux/crypto.h>
953 +#include "crypto_des.h"
954 +
955 +#define ROR(d,c,o)     ((d) = (d) >> (c) | (d) << (o))
956 +
957 +static const u8 parity[] = {
958 +       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,
959 +       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,
960 +       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,
961 +       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,
962 +       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,
963 +       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,
964 +       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,
965 +       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,
966 +};
967 +
968 +/*
969 + * RFC2451: Weak key checks SHOULD be performed.
970 + */
971 +int
972 +crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags)
973 +{
974 +       u32 n, w;
975 +
976 +       n  = parity[key[0]]; n <<= 4;
977 +       n |= parity[key[1]]; n <<= 4;
978 +       n |= parity[key[2]]; n <<= 4;
979 +       n |= parity[key[3]]; n <<= 4;
980 +       n |= parity[key[4]]; n <<= 4;
981 +       n |= parity[key[5]]; n <<= 4;
982 +       n |= parity[key[6]]; n <<= 4;
983 +       n |= parity[key[7]];
984 +       w = 0x88888888L;
985 +
986 +       if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
987 +           && !((n - (w >> 3)) & w)) {  /* 1 in 10^10 keys passes this test */
988 +               if (n < 0x41415151) {
989 +                       if (n < 0x31312121) {
990 +                               if (n < 0x14141515) {
991 +                                       /* 01 01 01 01 01 01 01 01 */
992 +                                       if (n == 0x11111111) goto weak;
993 +                                       /* 01 1F 01 1F 01 0E 01 0E */
994 +                                       if (n == 0x13131212) goto weak;
995 +                               } else {
996 +                                       /* 01 E0 01 E0 01 F1 01 F1 */
997 +                                       if (n == 0x14141515) goto weak;
998 +                                       /* 01 FE 01 FE 01 FE 01 FE */
999 +                                       if (n == 0x16161616) goto weak;
1000 +                               }
1001 +                       } else {
1002 +                               if (n < 0x34342525) {
1003 +                                       /* 1F 01 1F 01 0E 01 0E 01 */
1004 +                                       if (n == 0x31312121) goto weak;
1005 +                                       /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */
1006 +                                       if (n == 0x33332222) goto weak;
1007 +                               } else {
1008 +                                       /* 1F E0 1F E0 0E F1 0E F1 */
1009 +                                       if (n == 0x34342525) goto weak;
1010 +                                       /* 1F FE 1F FE 0E FE 0E FE */
1011 +                                       if (n == 0x36362626) goto weak;
1012 +                               }
1013 +                       }
1014 +               } else {
1015 +                       if (n < 0x61616161) {
1016 +                               if (n < 0x44445555) {
1017 +                                       /* E0 01 E0 01 F1 01 F1 01 */
1018 +                                       if (n == 0x41415151) goto weak;
1019 +                                       /* E0 1F E0 1F F1 0E F1 0E */
1020 +                                       if (n == 0x43435252) goto weak;
1021 +                               } else {
1022 +                                       /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */
1023 +                                       if (n == 0x44445555) goto weak;
1024 +                                       /* E0 FE E0 FE F1 FE F1 FE */
1025 +                                       if (n == 0x46465656) goto weak;
1026 +                               }
1027 +                       } else {
1028 +                               if (n < 0x64646565) {
1029 +                                       /* FE 01 FE 01 FE 01 FE 01 */
1030 +                                       if (n == 0x61616161) goto weak;
1031 +                                       /* FE 1F FE 1F FE 0E FE 0E */
1032 +                                       if (n == 0x63636262) goto weak;
1033 +                               } else {
1034 +                                       /* FE E0 FE E0 FE F1 FE F1 */
1035 +                                       if (n == 0x64646565) goto weak;
1036 +                                       /* FE FE FE FE FE FE FE FE */
1037 +                                       if (n == 0x66666666) goto weak;
1038 +                               }
1039 +                       }
1040 +               }
1041 +       }
1042 +       return 0;
1043 +weak:
1044 +       *flags |= CRYPTO_TFM_RES_WEAK_KEY;
1045 +       return -EINVAL;
1046 +}
1047 +
1048 +EXPORT_SYMBOL(crypto_des_check_key);
1049 +
1050 +MODULE_LICENSE("GPL");
1051 +MODULE_DESCRIPTION("Key Check function for DES &  DES3 Cipher Algorithms");
1052 --- /dev/null
1053 +++ b/arch/ubicom32/crypto/des_ubicom32.c
1054 @@ -0,0 +1,761 @@
1055 +/*
1056 + * arch/ubicom32/crypto/des_ubicom32.c
1057 + *   Ubicom32 implementation of the DES Cipher Algorithm.
1058 + *
1059 + * (C) Copyright 2009, Ubicom, Inc.
1060 + *
1061 + * This file is part of the Ubicom32 Linux Kernel Port.
1062 + *
1063 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1064 + * it and/or modify it under the terms of the GNU General Public License
1065 + * as published by the Free Software Foundation, either version 2 of the
1066 + * License, or (at your option) any later version.
1067 + *
1068 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1069 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1070 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1071 + * the GNU General Public License for more details.
1072 + *
1073 + * You should have received a copy of the GNU General Public License
1074 + * along with the Ubicom32 Linux Kernel Port.  If not,
1075 + * see <http://www.gnu.org/licenses/>.
1076 + *
1077 + * Ubicom32 implementation derived from (with many thanks):
1078 + *   arch/m68knommu
1079 + *   arch/blackfin
1080 + *   arch/parisc
1081 + */
1082 +#include <crypto/algapi.h>
1083 +#include <linux/init.h>
1084 +#include <linux/module.h>
1085 +
1086 +#include "crypto_ubicom32.h"
1087 +extern int crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags);
1088 +
1089 +#define DES_BLOCK_SIZE 8
1090 +#define DES_KEY_SIZE 8
1091 +
1092 +#define DES3_192_KEY_SIZE      (3 * DES_KEY_SIZE)
1093 +#define DES3_192_BLOCK_SIZE    DES_BLOCK_SIZE
1094 +
1095 +#define DES3_SUB_KEY(key, i)   (((u8 *)key) + (i * DES_KEY_SIZE))
1096 +
1097 +enum des_ops {
1098 +       DES_ENCRYPT,
1099 +       DES_DECRYPT,
1100 +
1101 +       DES3_EDE_ENCRYPT,
1102 +       DES3_EDE_DECRYPT,
1103 +
1104 +#ifdef DES3_EEE
1105 +       DES3_EEE_ENCRYPT,
1106 +       DES3_EEE_DECRYPT,
1107 +#endif
1108 +};
1109 +
1110 +struct ubicom32_des_ctx {
1111 +       u8 key[3 * DES_KEY_SIZE];
1112 +       u32 ctrl;
1113 +       int key_len;
1114 +};
1115 +
1116 +static inline void des_hw_set_key(const u8 *key, u8 key_len)
1117 +{
1118 +       /*
1119 +        * HW 3DES is not tested yet, use DES just as ipOS
1120 +        */
1121 +       DES_SET_KEY(key);
1122 +}
1123 +
1124 +static inline void des_hw_cipher(u8 *out, const u8 *in)
1125 +{
1126 +       SEC_SET_INPUT_2W(in);
1127 +
1128 +       asm volatile (
1129 +       "       ; start DES by writing 0x38(SECURITY_BASE)      \n\t"
1130 +       "       move.4 0x38(%0), #0x01                          \n\t"
1131 +       "       pipe_flush 0                                    \n\t"
1132 +       "                                                       \n\t"
1133 +       "       ; wait for the module to calculate the output   \n\t"
1134 +       "       btst 0x04(%0), #0                               \n\t"
1135 +       "       jmpne.f .-4                                     \n\t"
1136 +               :
1137 +               : "a" (SEC_BASE)
1138 +               : "cc"
1139 +       );
1140 +
1141 +       SEC_GET_OUTPUT_2W(out);
1142 +}
1143 +
1144 +
1145 +static void inline des3_hw_ede_encrypt(u8 *keys, u8 *out, const u8 *in)
1146 +{
1147 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1148 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1149 +       des_hw_cipher(out, in);
1150 +
1151 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1152 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1153 +       des_hw_cipher(out, out);
1154 +
1155 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1156 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1157 +       des_hw_cipher(out, out);
1158 +}
1159 +
1160 +static void inline des3_hw_ede_decrypt(u8 *keys, u8 *out, const u8 *in)
1161 +{
1162 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1163 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1164 +       des_hw_cipher(out, in);
1165 +
1166 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1167 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1168 +       des_hw_cipher(out, out);
1169 +
1170 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1171 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1172 +       des_hw_cipher(out, out);
1173 +}
1174 +
1175 +#ifdef DES3_EEE
1176 +static void inline des3_hw_eee_encrypt(u8 *keys, u8 *out, const u8 *in)
1177 +{
1178 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1179 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1180 +       des_hw_cipher(out, in);
1181 +
1182 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1183 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1184 +       des_hw_cipher(out, out);
1185 +
1186 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1187 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1188 +       des_hw_cipher(out, out);
1189 +}
1190 +
1191 +static void inline des3_hw_eee_decrypt(u8 *keys, u8 *out, const u8 *in)
1192 +{
1193 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1194 +       des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1195 +       des_hw_cipher(out, in);
1196 +
1197 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1198 +       des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1199 +       des_hw_cipher(out, out);
1200 +
1201 +       hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1202 +       des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1203 +       des_hw_cipher(out, out);
1204 +}
1205 +#endif
1206 +
1207 +static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
1208 +                     unsigned int keylen)
1209 +{
1210 +       struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1211 +       u32 *flags = &tfm->crt_flags;
1212 +       int ret;
1213 +
1214 +       /* test if key is valid (not a weak key) */
1215 +       ret = crypto_des_check_key(key, keylen, flags);
1216 +       if (ret == 0) {
1217 +               memcpy(dctx->key, key, keylen);
1218 +               dctx->key_len = keylen;
1219 +               //dctx->ctrl = (keylen == DES_KEY_SIZE) ? SEC_ALG_DES : SEC_ALG_3DES
1220 +               /* 2DES and 3DES are both implemented with DES hw function */
1221 +               dctx->ctrl = SEC_ALG_DES;
1222 +       }
1223 +       return ret;
1224 +}
1225 +
1226 +static inline void des_cipher_1b(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
1227 +{
1228 +       const struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1229 +
1230 +       hw_crypto_lock();
1231 +       hw_crypto_check();
1232 +       hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
1233 +
1234 +       des_hw_set_key(uctx->key, uctx->key_len);
1235 +       des_hw_cipher(out, in);
1236 +
1237 +       hw_crypto_unlock();
1238 +}
1239 +
1240 +static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1241 +{
1242 +       des_cipher_1b(tfm, out, in, SEC_DIR_ENCRYPT);
1243 +}
1244 +
1245 +static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1246 +{
1247 +       des_cipher_1b(tfm, out, in, SEC_DIR_DECRYPT);
1248 +}
1249 +
1250 +static struct crypto_alg des_alg = {
1251 +       .cra_name               =       "des",
1252 +       .cra_driver_name        =       "des-ubicom32",
1253 +       .cra_priority           =       CRYPTO_UBICOM32_PRIORITY,
1254 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
1255 +       .cra_blocksize          =       DES_BLOCK_SIZE,
1256 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1257 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1258 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1259 +       .cra_module             =       THIS_MODULE,
1260 +       .cra_list               =       LIST_HEAD_INIT(des_alg.cra_list),
1261 +       .cra_u                  = {
1262 +               .cipher = {
1263 +                       .cia_min_keysize        =       DES_KEY_SIZE,
1264 +                       .cia_max_keysize        =       DES_KEY_SIZE,
1265 +                       .cia_setkey             =       des_setkey,
1266 +                       .cia_encrypt            =       des_encrypt,
1267 +                       .cia_decrypt            =       des_decrypt,
1268 +               }
1269 +       }
1270 +};
1271 +
1272 +static void ecb_des_ciper_loop(u8 *out, u8 *in, unsigned int n)
1273 +{
1274 +       while (likely(n)) {
1275 +               des_hw_cipher(out, in);
1276 +               out += DES_BLOCK_SIZE;
1277 +               in += DES_BLOCK_SIZE;
1278 +               n -= DES_BLOCK_SIZE;
1279 +       }
1280 +}
1281 +
1282 +static void ecb_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1283 +{
1284 +       while (likely(n)) {
1285 +               des3_hw_ede_encrypt(keys, out, in);
1286 +
1287 +               out += DES_BLOCK_SIZE;
1288 +               in += DES_BLOCK_SIZE;
1289 +               n -= DES_BLOCK_SIZE;
1290 +       }
1291 +}
1292 +
1293 +static void ecb_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1294 +{
1295 +       while (likely(n)) {
1296 +               des3_hw_ede_decrypt(keys, out, in);
1297 +
1298 +               out += DES_BLOCK_SIZE;
1299 +               in += DES_BLOCK_SIZE;
1300 +               n -= DES_BLOCK_SIZE;
1301 +       }
1302 +}
1303 +
1304 +#ifdef DES3_EEE
1305 +static void ecb_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1306 +{
1307 +       while (likely(n)) {
1308 +               des3_hw_eee_encrypt(keys, out, in);
1309 +
1310 +               out += DES_BLOCK_SIZE;
1311 +               in += DES_BLOCK_SIZE;
1312 +               n -= DES_BLOCK_SIZE;
1313 +       }
1314 +}
1315 +
1316 +static void ecb_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1317 +{
1318 +       while (likely(n)) {
1319 +               des3_hw_eee_decrypt(keys, out, in);
1320 +
1321 +               out += DES_BLOCK_SIZE;
1322 +               in += DES_BLOCK_SIZE;
1323 +               n -= DES_BLOCK_SIZE;
1324 +       }
1325 +}
1326 +#endif
1327 +
1328 +static inline void ecb_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, unsigned int n)
1329 +{
1330 +       switch (op) {
1331 +       case DES_ENCRYPT:
1332 +       case DES_DECRYPT:
1333 +               /* set the right algo, direction and key once */
1334 +               hw_crypto_set_ctrl(SEC_ALG_DES | (op == DES_ENCRYPT ? SEC_DIR_ENCRYPT : 0));
1335 +               des_hw_set_key(uctx->key, uctx->key_len);
1336 +               ecb_des_ciper_loop(out, in, n);
1337 +               break;
1338 +
1339 +       case DES3_EDE_ENCRYPT:
1340 +               ecb_des3_ede_encrypt_loop(uctx->key, out, in, n);
1341 +               break;
1342 +
1343 +       case DES3_EDE_DECRYPT:
1344 +               ecb_des3_ede_decrypt_loop(uctx->key, out, in, n);
1345 +               break;
1346 +
1347 +#ifdef DES3_EEE
1348 +       case DES3_EEE_ENCRYPT:
1349 +               ecb_des3_eee_encrypt_loop(uctx->key, out, in, n);
1350 +               break;
1351 +
1352 +       case DES3_EEE_DECRYPT:
1353 +               ecb_des3_eee_decrypt_loop(uctx->key, out, in, n);
1354 +               break;
1355 +#endif
1356 +       }
1357 +}
1358 +
1359 +static inline void des_xor_2w(u32 *data, u32 *iv)
1360 +{
1361 +       data[0] ^= iv[0];
1362 +       data[1] ^= iv[1];
1363 +}
1364 +
1365 +static void cbc_des_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1366 +{
1367 +       while (likely(n)) {
1368 +               des_xor_2w((u32 *)in, (u32 *)iv);
1369 +               des_hw_cipher(out, in);
1370 +               SEC_COPY_2W(iv, out);
1371 +               out += DES_BLOCK_SIZE;
1372 +               in += DES_BLOCK_SIZE;
1373 +               n -= DES_BLOCK_SIZE;
1374 +       }
1375 +}
1376 +
1377 +static void cbc_des_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1378 +{
1379 +       u8 next_iv[DES_BLOCK_SIZE];
1380 +       while (likely(n)) {
1381 +               SEC_COPY_2W(next_iv, in);
1382 +               des_hw_cipher(out, in);
1383 +               des_xor_2w((u32 *)out, (u32 *)iv);
1384 +               SEC_COPY_2W(iv, next_iv);
1385 +
1386 +               out += DES_BLOCK_SIZE;
1387 +               in += DES_BLOCK_SIZE;
1388 +               n -= DES_BLOCK_SIZE;
1389 +       }
1390 +}
1391 +
1392 +static void cbc_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1393 +{
1394 +       while (likely(n)) {
1395 +               des_xor_2w((u32 *)in, (u32 *)iv);
1396 +               des3_hw_ede_encrypt(keys, out, in);
1397 +               SEC_COPY_2W(iv, out);
1398 +
1399 +               out += DES_BLOCK_SIZE;
1400 +               in += DES_BLOCK_SIZE;
1401 +               n -= DES_BLOCK_SIZE;
1402 +       }
1403 +}
1404 +
1405 +static void cbc_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1406 +{
1407 +       u8 next_iv[DES_BLOCK_SIZE];
1408 +       while (likely(n)) {
1409 +               SEC_COPY_2W(next_iv, in);
1410 +               des3_hw_ede_decrypt(keys, out, in);
1411 +               des_xor_2w((u32 *)out, (u32 *)iv);
1412 +               SEC_COPY_2W(iv, next_iv);
1413 +
1414 +               out += DES_BLOCK_SIZE;
1415 +               in += DES_BLOCK_SIZE;
1416 +               n -= DES_BLOCK_SIZE;
1417 +       }
1418 +}
1419 +
1420 +#ifdef DES3_EEE
1421 +static void cbc_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1422 +{
1423 +       while (likely(n)) {
1424 +               des_xor_2w((u32 *)in, (u32 *)iv);
1425 +               des3_hw_eee_encrypt(keys, out, in);
1426 +               SEC_COPY_2W(iv, out);
1427 +
1428 +               out += DES_BLOCK_SIZE;
1429 +               in += DES_BLOCK_SIZE;
1430 +               n -= DES_BLOCK_SIZE;
1431 +       }
1432 +}
1433 +
1434 +static void cbc_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1435 +{
1436 +       u8 next_iv[DES_BLOCK_SIZE];
1437 +       while (likely(n)) {
1438 +               SEC_COPY_2W(next_iv, in);
1439 +               des3_hw_eee_decrypt(keys, out, in);
1440 +               des_xor_2w((u32 *)out, (u32 *)iv);
1441 +               SEC_COPY_2W(iv, next_iv);
1442 +
1443 +               out += DES_BLOCK_SIZE;
1444 +               in += DES_BLOCK_SIZE;
1445 +               n -= DES_BLOCK_SIZE;
1446 +       }
1447 +}
1448 +#endif
1449 +
1450 +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)
1451 +{
1452 +       switch (op) {
1453 +       case DES_ENCRYPT:
1454 +               hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1455 +               des_hw_set_key(uctx->key, uctx->key_len);
1456 +               cbc_des_encrypt_loop(out, in, iv, n);
1457 +               break;
1458 +
1459 +       case DES_DECRYPT:
1460 +               /* set the right algo, direction and key once */
1461 +               hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1462 +               des_hw_set_key(uctx->key, uctx->key_len);
1463 +               cbc_des_decrypt_loop(out, in, iv, n);
1464 +               break;
1465 +
1466 +       case DES3_EDE_ENCRYPT:
1467 +               cbc_des3_ede_encrypt_loop(uctx->key, out, in, iv, n);
1468 +               break;
1469 +
1470 +       case DES3_EDE_DECRYPT:
1471 +               cbc_des3_ede_decrypt_loop(uctx->key, out, in, iv, n);
1472 +               break;
1473 +
1474 +#ifdef DES3_EEE
1475 +       case DES3_EEE_ENCRYPT:
1476 +               cbc_des3_eee_encrypt_loop(uctx->key, out, in, iv, n);
1477 +               break;
1478 +
1479 +       case DES3_EEE_DECRYPT:
1480 +               cbc_des3_eee_decrypt_loop(uctx->key, out, in, iv, n);
1481 +               break;
1482 +#endif
1483 +       }
1484 +}
1485 +
1486 +static int des_cipher(struct blkcipher_desc *desc, struct scatterlist *dst,
1487 +                     struct scatterlist *src, unsigned int nbytes, u32 extra_flags, enum des_ops op)
1488 +{
1489 +       struct ubicom32_des_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
1490 +       int ret;
1491 +
1492 +       struct blkcipher_walk walk;
1493 +       blkcipher_walk_init(&walk, dst, src, nbytes);
1494 +       ret = blkcipher_walk_virt(desc, &walk);
1495 +       if (ret) {
1496 +               return ret;
1497 +       }
1498 +
1499 +       hw_crypto_lock();
1500 +       hw_crypto_check();
1501 +
1502 +       while ((nbytes = walk.nbytes)) {
1503 +               /* only use complete blocks */
1504 +               unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
1505 +               u8 *out = walk.dst.virt.addr;
1506 +               u8 *in = walk.src.virt.addr;
1507 +
1508 +               /* finish n/16 blocks */
1509 +               if (extra_flags & SEC_CBC_SET) {
1510 +                       cbc_des_cipher_n(uctx, op, out, in, walk.iv, n);
1511 +               } else {
1512 +                       ecb_des_cipher_n(uctx, op, out, in, n);
1513 +               }
1514 +
1515 +               nbytes &= DES_BLOCK_SIZE - 1;
1516 +               ret = blkcipher_walk_done(desc, &walk, nbytes);
1517 +       }
1518 +
1519 +       hw_crypto_unlock();
1520 +       return ret;
1521 +}
1522 +
1523 +static int ecb_des_encrypt(struct blkcipher_desc *desc,
1524 +                          struct scatterlist *dst, struct scatterlist *src,
1525 +                          unsigned int nbytes)
1526 +{
1527 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_ENCRYPT);
1528 +}
1529 +
1530 +static int ecb_des_decrypt(struct blkcipher_desc *desc,
1531 +                          struct scatterlist *dst, struct scatterlist *src,
1532 +                          unsigned int nbytes)
1533 +{
1534 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_DECRYPT);
1535 +}
1536 +
1537 +static struct crypto_alg ecb_des_alg = {
1538 +       .cra_name               =       "ecb(des)",
1539 +       .cra_driver_name        =       "ecb-des-ubicom32",
1540 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1541 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1542 +       .cra_blocksize          =       DES_BLOCK_SIZE,
1543 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1544 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1545 +       .cra_type               =       &crypto_blkcipher_type,
1546 +       .cra_module             =       THIS_MODULE,
1547 +       .cra_list               =       LIST_HEAD_INIT(ecb_des_alg.cra_list),
1548 +       .cra_u                  = {
1549 +               .blkcipher = {
1550 +                       .min_keysize            =       DES_KEY_SIZE,
1551 +                       .max_keysize            =       DES_KEY_SIZE,
1552 +                       .setkey                 =       des_setkey,
1553 +                       .encrypt                =       ecb_des_encrypt,
1554 +                       .decrypt                =       ecb_des_decrypt,
1555 +               }
1556 +       }
1557 +};
1558 +
1559 +static int cbc_des_encrypt(struct blkcipher_desc *desc,
1560 +                          struct scatterlist *dst, struct scatterlist *src,
1561 +                          unsigned int nbytes)
1562 +{
1563 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_ENCRYPT);
1564 +}
1565 +
1566 +static int cbc_des_decrypt(struct blkcipher_desc *desc,
1567 +                          struct scatterlist *dst, struct scatterlist *src,
1568 +                          unsigned int nbytes)
1569 +{
1570 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_DECRYPT);
1571 +}
1572 +
1573 +static struct crypto_alg cbc_des_alg = {
1574 +       .cra_name               =       "cbc(des)",
1575 +       .cra_driver_name        =       "cbc-des-ubicom32",
1576 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1577 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1578 +       .cra_blocksize          =       DES_BLOCK_SIZE,
1579 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1580 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1581 +       .cra_type               =       &crypto_blkcipher_type,
1582 +       .cra_module             =       THIS_MODULE,
1583 +       .cra_list               =       LIST_HEAD_INIT(cbc_des_alg.cra_list),
1584 +       .cra_u                  = {
1585 +               .blkcipher = {
1586 +                       .min_keysize            =       DES_KEY_SIZE,
1587 +                       .max_keysize            =       DES_KEY_SIZE,
1588 +                       .ivsize                 =       DES_BLOCK_SIZE,
1589 +                       .setkey                 =       des_setkey,
1590 +                       .encrypt                =       cbc_des_encrypt,
1591 +                       .decrypt                =       cbc_des_decrypt,
1592 +               }
1593 +       }
1594 +};
1595 +
1596 +/*
1597 + * RFC2451:
1598 + *
1599 + *   For DES-EDE3, there is no known need to reject weak or
1600 + *   complementation keys.  Any weakness is obviated by the use of
1601 + *   multiple keys.
1602 + *
1603 + *   However, if the first two or last two independent 64-bit keys are
1604 + *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
1605 + *   same as DES.  Implementers MUST reject keys that exhibit this
1606 + *   property.
1607 + *
1608 + */
1609 +static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
1610 +                          unsigned int keylen)
1611 +{
1612 +       int i, ret;
1613 +       struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1614 +       const u8 *temp_key = key;
1615 +       u32 *flags = &tfm->crt_flags;
1616 +
1617 +       if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
1618 +           memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
1619 +                  DES_KEY_SIZE))) {
1620 +
1621 +               *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
1622 +               return -EINVAL;
1623 +       }
1624 +       for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
1625 +               ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
1626 +               if (ret < 0)
1627 +                       return ret;
1628 +       }
1629 +       memcpy(dctx->key, key, keylen);
1630 +       dctx->ctrl = SEC_ALG_DES;       //hw 3DES not working yet
1631 +       dctx->key_len = keylen;
1632 +       return 0;
1633 +}
1634 +
1635 +static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1636 +{
1637 +       struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1638 +
1639 +       hw_crypto_lock();
1640 +       hw_crypto_check();
1641 +
1642 +       des3_hw_ede_encrypt(uctx->key, dst, src);
1643 +
1644 +       hw_crypto_unlock();
1645 +}
1646 +
1647 +static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1648 +{
1649 +       struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1650 +
1651 +       hw_crypto_lock();
1652 +       hw_crypto_check();
1653 +
1654 +       des3_hw_ede_decrypt(uctx->key, dst, src);
1655 +
1656 +       hw_crypto_unlock();
1657 +}
1658 +
1659 +static struct crypto_alg des3_192_alg = {
1660 +       .cra_name               =       "des3_ede",
1661 +       .cra_driver_name        =       "des3_ede-ubicom32",
1662 +       .cra_priority           =       CRYPTO_UBICOM32_PRIORITY,
1663 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
1664 +       .cra_blocksize          =       DES3_192_BLOCK_SIZE,
1665 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1666 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1667 +       .cra_module             =       THIS_MODULE,
1668 +       .cra_list               =       LIST_HEAD_INIT(des3_192_alg.cra_list),
1669 +       .cra_u                  = {
1670 +               .cipher = {
1671 +                       .cia_min_keysize        =       DES3_192_KEY_SIZE,
1672 +                       .cia_max_keysize        =       DES3_192_KEY_SIZE,
1673 +                       .cia_setkey             =       des3_192_setkey,
1674 +                       .cia_encrypt            =       des3_192_encrypt,
1675 +                       .cia_decrypt            =       des3_192_decrypt,
1676 +               }
1677 +       }
1678 +};
1679 +
1680 +static int ecb_des3_192_encrypt(struct blkcipher_desc *desc,
1681 +                               struct scatterlist *dst,
1682 +                               struct scatterlist *src, unsigned int nbytes)
1683 +{
1684 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_ENCRYPT);
1685 +}
1686 +
1687 +static int ecb_des3_192_decrypt(struct blkcipher_desc *desc,
1688 +                               struct scatterlist *dst,
1689 +                               struct scatterlist *src, unsigned int nbytes)
1690 +{
1691 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_DECRYPT);
1692 +}
1693 +
1694 +static struct crypto_alg ecb_des3_192_alg = {
1695 +       .cra_name               =       "ecb(des3_ede)",
1696 +       .cra_driver_name        =       "ecb-des3_ede-ubicom32",
1697 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1698 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1699 +       .cra_blocksize          =       DES3_192_BLOCK_SIZE,
1700 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1701 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1702 +       .cra_type               =       &crypto_blkcipher_type,
1703 +       .cra_module             =       THIS_MODULE,
1704 +       .cra_list               =       LIST_HEAD_INIT(
1705 +                                               ecb_des3_192_alg.cra_list),
1706 +       .cra_u                  = {
1707 +               .blkcipher = {
1708 +                       .min_keysize            =       DES3_192_KEY_SIZE,
1709 +                       .max_keysize            =       DES3_192_KEY_SIZE,
1710 +                       .setkey                 =       des3_192_setkey,
1711 +                       .encrypt                =       ecb_des3_192_encrypt,
1712 +                       .decrypt                =       ecb_des3_192_decrypt,
1713 +               }
1714 +       }
1715 +};
1716 +
1717 +static int cbc_des3_192_encrypt(struct blkcipher_desc *desc,
1718 +                               struct scatterlist *dst,
1719 +                               struct scatterlist *src, unsigned int nbytes)
1720 +{
1721 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_ENCRYPT);
1722 +}
1723 +
1724 +static int cbc_des3_192_decrypt(struct blkcipher_desc *desc,
1725 +                               struct scatterlist *dst,
1726 +                               struct scatterlist *src, unsigned int nbytes)
1727 +{
1728 +       return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_DECRYPT);
1729 +}
1730 +
1731 +static struct crypto_alg cbc_des3_192_alg = {
1732 +       .cra_name               =       "cbc(des3_ede)",
1733 +       .cra_driver_name        =       "cbc-des3_ede-ubicom32",
1734 +       .cra_priority           =       CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1735 +       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
1736 +       .cra_blocksize          =       DES3_192_BLOCK_SIZE,
1737 +       .cra_ctxsize            =       sizeof(struct ubicom32_des_ctx),
1738 +       .cra_alignmask          =       CRYPTO_UBICOM32_ALIGNMENT - 1,
1739 +       .cra_type               =       &crypto_blkcipher_type,
1740 +       .cra_module             =       THIS_MODULE,
1741 +       .cra_list               =       LIST_HEAD_INIT(
1742 +                                               cbc_des3_192_alg.cra_list),
1743 +       .cra_u                  = {
1744 +               .blkcipher = {
1745 +                       .min_keysize            =       DES3_192_KEY_SIZE,
1746 +                       .max_keysize            =       DES3_192_KEY_SIZE,
1747 +                       .ivsize                 =       DES3_192_BLOCK_SIZE,
1748 +                       .setkey                 =       des3_192_setkey,
1749 +                       .encrypt                =       cbc_des3_192_encrypt,
1750 +                       .decrypt                =       cbc_des3_192_decrypt,
1751 +               }
1752 +       }
1753 +};
1754 +
1755 +static int init(void)
1756 +{
1757 +       int ret = 0;
1758 +
1759 +       hw_crypto_init();
1760 +
1761 +       ret = crypto_register_alg(&des_alg);
1762 +       if (ret)
1763 +               goto des_err;
1764 +       ret = crypto_register_alg(&ecb_des_alg);
1765 +       if (ret)
1766 +               goto ecb_des_err;
1767 +       ret = crypto_register_alg(&cbc_des_alg);
1768 +       if (ret)
1769 +               goto cbc_des_err;
1770 +
1771 +       ret = crypto_register_alg(&des3_192_alg);
1772 +       if (ret)
1773 +               goto des3_192_err;
1774 +       ret = crypto_register_alg(&ecb_des3_192_alg);
1775 +       if (ret)
1776 +               goto ecb_des3_192_err;
1777 +       ret = crypto_register_alg(&cbc_des3_192_alg);
1778 +       if (ret)
1779 +               goto cbc_des3_192_err;
1780 +
1781 +out:
1782 +       return ret;
1783 +
1784 +cbc_des3_192_err:
1785 +       crypto_unregister_alg(&ecb_des3_192_alg);
1786 +ecb_des3_192_err:
1787 +       crypto_unregister_alg(&des3_192_alg);
1788 +des3_192_err:
1789 +       crypto_unregister_alg(&cbc_des_alg);
1790 +cbc_des_err:
1791 +       crypto_unregister_alg(&ecb_des_alg);
1792 +ecb_des_err:
1793 +       crypto_unregister_alg(&des_alg);
1794 +des_err:
1795 +       goto out;
1796 +}
1797 +
1798 +static void __exit fini(void)
1799 +{
1800 +       crypto_unregister_alg(&cbc_des3_192_alg);
1801 +       crypto_unregister_alg(&ecb_des3_192_alg);
1802 +       crypto_unregister_alg(&des3_192_alg);
1803 +       crypto_unregister_alg(&cbc_des_alg);
1804 +       crypto_unregister_alg(&ecb_des_alg);
1805 +       crypto_unregister_alg(&des_alg);
1806 +}
1807 +
1808 +module_init(init);
1809 +module_exit(fini);
1810 +
1811 +MODULE_ALIAS("des");
1812 +MODULE_ALIAS("des3_ede");
1813 +
1814 +MODULE_LICENSE("GPL");
1815 +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1816 --- /dev/null
1817 +++ b/arch/ubicom32/crypto/Makefile
1818 @@ -0,0 +1,36 @@
1819 +#
1820 +# arch/ubicom32/crypto/Makefile
1821 +#      <TODO: Replace with short file description>
1822 +#
1823 +# (C) Copyright 2009, Ubicom, Inc.
1824 +#
1825 +# This file is part of the Ubicom32 Linux Kernel Port.
1826 +#
1827 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
1828 +# it and/or modify it under the terms of the GNU General Public License
1829 +# as published by the Free Software Foundation, either version 2 of the
1830 +# License, or (at your option) any later version.
1831 +#
1832 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
1833 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
1834 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1835 +# the GNU General Public License for more details.
1836 +#
1837 +# You should have received a copy of the GNU General Public License
1838 +# along with the Ubicom32 Linux Kernel Port.  If not,
1839 +# see <http://www.gnu.org/licenses/>.
1840 +#
1841 +# Ubicom32 implementation derived from (with many thanks):
1842 +#   arch/m68knommu
1843 +#   arch/blackfin
1844 +#   arch/parisc
1845 +#
1846 +obj-$(CONFIG_CRYPTO_UBICOM32) += crypto_ubicom32.o
1847 +obj-$(CONFIG_CRYPTO_AES_UBICOM32) += aes_ubicom32.o
1848 +obj-$(CONFIG_CRYPTO_DES_UBICOM32) += des.o
1849 +obj-$(CONFIG_CRYPTO_MD5_UBICOM32) += md5.o
1850 +obj-$(CONFIG_CRYPTO_SHA1_UBICOM32) += sha1.o
1851 +
1852 +des-y := des_ubicom32.o des_check_key.o
1853 +md5-y := md5_ubicom32.o md5_ubicom32_asm.o
1854 +sha1-y := sha1_ubicom32.o
1855 --- /dev/null
1856 +++ b/arch/ubicom32/crypto/md5_ubicom32_asm.S
1857 @@ -0,0 +1,234 @@
1858 +/*
1859 + * arch/ubicom32/crypto/md5_ubicom32_asm.S
1860 + *     MD5 (Message Digest 5) support for Ubicom32 v3 architecture
1861 + *
1862 + * (C) Copyright 2009, Ubicom, Inc.
1863 + *
1864 + * This file is part of the Ubicom32 Linux Kernel Port.
1865 + *
1866 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1867 + * it and/or modify it under the terms of the GNU General Public License
1868 + * as published by the Free Software Foundation, either version 2 of the
1869 + * License, or (at your option) any later version.
1870 + *
1871 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1872 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1873 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1874 + * the GNU General Public License for more details.
1875 + *
1876 + * You should have received a copy of the GNU General Public License
1877 + * along with the Ubicom32 Linux Kernel Port.  If not,
1878 + * see <http://www.gnu.org/licenses/>.
1879 + *
1880 + * Ubicom32 implementation derived from (with many thanks):
1881 + *   arch/m68knommu
1882 + *   arch/blackfin
1883 + *   arch/parisc
1884 + */
1885 +
1886 +#define __ASM__
1887 +#include <asm/ip5000.h>
1888 +
1889 +#ifndef RP
1890 +#define RP A5
1891 +#endif
1892 +
1893 +;*****************************************************************************************
1894 +; The function prototypes
1895 +;*****************************************************************************************
1896 +; void md5_ip5k_init(void)
1897 +; void md5_ip5k_transform(u32_t *data_input)
1898 +; void md5_get_digest(u32_t *digest)
1899 +
1900 +;*****************************************************************************************
1901 +; Inputs
1902 +;*****************************************************************************************;
1903 +; data_input is the pointer to the block of data over which the digest will be calculated.
1904 +;      It should be word aligned.
1905 +;
1906 +; digest is the pointer to the block of data into which the digest (the output) will be written.
1907 +;      It should be word aligned.
1908 +;
1909 +
1910 +;*****************************************************************************************
1911 +; Outputs
1912 +;*****************************************************************************************
1913 +; None
1914 +
1915 +;*****************************************************************************************
1916 +; An: Address Registers
1917 +;*****************************************************************************************
1918 +#define an_digest A3
1919 +#define an_data_input A3
1920 +#define an_security_block A4
1921 +
1922 +;*****************************************************************************************
1923 +; Hash Constants
1924 +;*****************************************************************************************
1925 +#define HASH_MD5_IN0 0x01234567
1926 +#define HASH_MD5_IN1 0x89abcdef
1927 +#define HASH_MD5_IN2 0xfedcba98
1928 +#define HASH_MD5_IN3 0x76543210
1929 +
1930 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
1931 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_MD5 ((1 << 4) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
1932 +
1933 +;*****************************************************************************************
1934 +; Hash related defines
1935 +;*****************************************************************************************
1936 +#define hash_control 0x00(an_security_block)
1937 +#define hash_control_low 0x02(an_security_block)
1938 +#define hash_status 0x04(an_security_block)
1939 +
1940 +#define hash_input_0 0x30(an_security_block)
1941 +#define hash_input_1 0x34(an_security_block)
1942 +#define hash_input_2 0x38(an_security_block)
1943 +#define hash_input_3 0x3c(an_security_block)
1944 +#define hash_input_4 0x40(an_security_block)
1945 +
1946 +#define hash_output_0 0x70(an_security_block)
1947 +#define hash_output_0_low 0x72(an_security_block)
1948 +#define hash_output_1 0x74(an_security_block)
1949 +#define hash_output_1_low 0x76(an_security_block)
1950 +#define hash_output_2 0x78(an_security_block)
1951 +#define hash_output_2_low 0x7a(an_security_block)
1952 +#define hash_output_3 0x7c(an_security_block)
1953 +#define hash_output_3_low 0x7e(an_security_block)
1954 +
1955 +;*****************************************************************************************
1956 +; Assembly macros
1957 +;*****************************************************************************************
1958 +       ; C compiler reserves RP (A5) for return address during subroutine call.
1959 +       ; Use RP to return to caller
1960 +.macro call_return_macro
1961 +       calli   RP, 0(RP)
1962 +.endm
1963 +
1964 +#if 0
1965 +;*****************************************************************************************
1966 +;      void md5_ip5k_init(void)
1967 +;              initialize the output registers of the hash module
1968 +;
1969 +       ;.section .text.md5_ip5k_init,"ax",@progbits
1970 +       .section .text
1971 +       .global _md5_ip5k_init
1972 +       .func md5_ip5k_init, _md5_ip5k_init
1973 +
1974 +_md5_ip5k_init:
1975 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
1976 +
1977 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1978 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1979 +
1980 +       movei hash_output_0, #%hi(HASH_MD5_IN0)
1981 +       movei hash_output_0_low, #%lo(HASH_MD5_IN0)
1982 +
1983 +       movei hash_output_1, #%hi(HASH_MD5_IN1)
1984 +       movei hash_output_1_low, #%lo(HASH_MD5_IN1)
1985 +
1986 +       movei hash_output_2, #%hi(HASH_MD5_IN2)
1987 +       movei hash_output_2_low, #%lo(HASH_MD5_IN2)
1988 +
1989 +       movei hash_output_3, #%hi(HASH_MD5_IN3)
1990 +       movei hash_output_3_low, #%lo(HASH_MD5_IN3)
1991 +
1992 +       call_return_macro
1993 +       .endfunc
1994 +#endif
1995 +
1996 +;*****************************************************************************************
1997 +;      void md5_ip5k_init_digest(u32_t *hash_input)
1998 +;              initialize the output registers of the hash module
1999 +
2000 +       ;.section .text.md5_ip5k_init_digest,"ax",@progbits
2001 +       .section .text
2002 +       .global _md5_ip5k_init_digest
2003 +       .func md5_ip5k_init_digest, _md5_ip5k_init_digest
2004 +
2005 +_md5_ip5k_init_digest:
2006 +       movea an_data_input, D0
2007 +
2008 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2009 +
2010 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2011 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2012 +
2013 +       move.4 hash_output_0, (an_data_input)4++
2014 +       move.4 hash_output_1, (an_data_input)4++
2015 +       move.4 hash_output_2, (an_data_input)4++
2016 +       move.4 hash_output_3, (an_data_input)4++
2017 +
2018 +       call_return_macro
2019 +       .endfunc
2020 +
2021 +;*****************************************************************************************
2022 +;      void md5_ip5k_transform(u32_t *data_input)
2023 +;              performs intermediate transformation step for the hash calculation
2024 +;
2025 +       ;.sect .text.md5_ip5k_transform,"ax",@progbits
2026 +       .section .text
2027 +       .global _md5_ip5k_transform
2028 +       .func md5_ip5k_transform, _md5_ip5k_transform
2029 +
2030 +_md5_ip5k_transform:
2031 +       movea an_data_input, D0
2032 +
2033 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2034 +
2035 +       ; Write the first 128bits (16 bytes)
2036 +       move.4 hash_input_0, (an_data_input)4++
2037 +       move.4 hash_input_1, (an_data_input)4++
2038 +       move.4 hash_input_2, (an_data_input)4++
2039 +       move.4 hash_input_3, (an_data_input)4++
2040 +       move.4 hash_input_4, D0
2041 +
2042 +       move.4 hash_input_0, (an_data_input)4++
2043 +       move.4 hash_input_1, (an_data_input)4++
2044 +       move.4 hash_input_2, (an_data_input)4++
2045 +       move.4 hash_input_3, (an_data_input)4++
2046 +       move.4 hash_input_4, D0
2047 +
2048 +       move.4 hash_input_0, (an_data_input)4++
2049 +       move.4 hash_input_1, (an_data_input)4++
2050 +       move.4 hash_input_2, (an_data_input)4++
2051 +       move.4 hash_input_3, (an_data_input)4++
2052 +       move.4 hash_input_4, D0
2053 +
2054 +       move.4 hash_input_0, (an_data_input)4++
2055 +       move.4 hash_input_1, (an_data_input)4++
2056 +       move.4 hash_input_2, (an_data_input)4++
2057 +       move.4 hash_input_3, (an_data_input)4++
2058 +       move.4 hash_input_4, D0
2059 +
2060 +       pipe_flush 0
2061 +
2062 +md5_ip5k_transform_wait:
2063 +       ; wait for the module to calculate the output hash
2064 +       btst hash_status, #0
2065 +       jmpne.f md5_ip5k_transform_wait
2066 +
2067 +       call_return_macro
2068 +       .endfunc
2069 +
2070 +;*****************************************************************************************
2071 +;      void md5_ip5k_get_digest(u32_t *digest)
2072 +;              Return the hash of the input data
2073 +;
2074 +       ;.sect .text.md5_get_digest,"ax",@progbits
2075 +       .section .text
2076 +       .global _md5_ip5k_get_digest
2077 +       .func md5_ip5k_get_digest, _md5_ip5k_get_digest
2078 +
2079 +_md5_ip5k_get_digest:
2080 +       movea an_digest, D0
2081 +
2082 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2083 +
2084 +       ; we have finished
2085 +       move.4 0(an_digest), hash_output_0
2086 +       move.4 4(an_digest), hash_output_1
2087 +       move.4 8(an_digest), hash_output_2
2088 +       move.4 12(an_digest), hash_output_3
2089 +
2090 +       call_return_macro
2091 +       .endfunc
2092 --- /dev/null
2093 +++ b/arch/ubicom32/crypto/md5_ubicom32.c
2094 @@ -0,0 +1,200 @@
2095 +/*
2096 + * arch/ubicom32/crypto/md5_ubicom32.c
2097 + *   Ubicom32 implementation of the MD5 Secure Hash Algorithm
2098 + *
2099 + * (C) Copyright 2009, Ubicom, Inc.
2100 + *
2101 + * This file is part of the Ubicom32 Linux Kernel Port.
2102 + *
2103 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2104 + * it and/or modify it under the terms of the GNU General Public License
2105 + * as published by the Free Software Foundation, either version 2 of the
2106 + * License, or (at your option) any later version.
2107 + *
2108 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2109 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2110 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2111 + * the GNU General Public License for more details.
2112 + *
2113 + * You should have received a copy of the GNU General Public License
2114 + * along with the Ubicom32 Linux Kernel Port.  If not,
2115 + * see <http://www.gnu.org/licenses/>.
2116 + *
2117 + * Ubicom32 implementation derived from (with many thanks):
2118 + *   arch/m68knommu
2119 + *   arch/blackfin
2120 + *   arch/parisc
2121 + */
2122 +#include <linux/init.h>
2123 +#include <linux/module.h>
2124 +#include <linux/crypto.h>
2125 +
2126 +#include "crypto_ubicom32.h"
2127 +
2128 +#define MD5_DIGEST_SIZE        16
2129 +#define MD5_BLOCK_SIZE 64
2130 +#define MD5_HASH_WORDS 4
2131 +
2132 +extern void _md5_ip5k_init_digest(u32_t *digest);
2133 +extern void _md5_ip5k_transform(u32_t *data_input);
2134 +extern void _md5_ip5k_get_digest(u32_t *digest);
2135 +
2136 +struct ubicom32_md5_ctx {
2137 +       u64 count;              /* message length */
2138 +       u32 state[MD5_HASH_WORDS];
2139 +       u8 buf[2 * MD5_BLOCK_SIZE];
2140 +};
2141 +
2142 +static void md5_init(struct crypto_tfm *tfm)
2143 +{
2144 +       struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2145 +       mctx->state[0] = 0x01234567;
2146 +       mctx->state[1] = 0x89abcdef;
2147 +       mctx->state[2] = 0xfedcba98;
2148 +       mctx->state[3] = 0x76543210;
2149 +
2150 +       mctx->count = 0;
2151 +}
2152 +
2153 +static inline void _md5_process(u32 *digest, const u8 *data)
2154 +{
2155 +       _md5_ip5k_transform((u32 *)data);
2156 +}
2157 +
2158 +static void md5_update(struct crypto_tfm *tfm, const u8 *data,
2159 +                       unsigned int len)
2160 +{
2161 +       struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2162 +       int index, clen;
2163 +
2164 +       /* how much is already in the buffer? */
2165 +       index = mctx->count & 0x3f;
2166 +
2167 +       mctx->count += len;
2168 +
2169 +       if (index + len < MD5_BLOCK_SIZE) {
2170 +               goto store_only;
2171 +       }
2172 +
2173 +       hw_crypto_lock();
2174 +       hw_crypto_check();
2175 +
2176 +       /* init digest set ctrl register too */
2177 +       _md5_ip5k_init_digest(mctx->state);
2178 +
2179 +       if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2180 +fast_process:
2181 +               while (len >= MD5_BLOCK_SIZE) {
2182 +                       _md5_process(mctx->state, data);
2183 +                       data += MD5_BLOCK_SIZE;
2184 +                       len -= MD5_BLOCK_SIZE;
2185 +               }
2186 +               goto store;
2187 +       }
2188 +
2189 +       /* process one stored block */
2190 +       if (index) {
2191 +               clen = MD5_BLOCK_SIZE - index;
2192 +               memcpy(mctx->buf + index, data, clen);
2193 +               _md5_process(mctx->state, mctx->buf);
2194 +               data += clen;
2195 +               len -= clen;
2196 +               index = 0;
2197 +       }
2198 +
2199 +       if (likely(SEC_ALIGNED(data))) {
2200 +               goto fast_process;
2201 +       }
2202 +
2203 +       /* process as many blocks as possible */
2204 +       while (len >= MD5_BLOCK_SIZE) {
2205 +               memcpy(mctx->buf, data, MD5_BLOCK_SIZE);
2206 +               _md5_process(mctx->state, mctx->buf);
2207 +               data += MD5_BLOCK_SIZE;
2208 +               len -= MD5_BLOCK_SIZE;
2209 +       }
2210 +
2211 +store:
2212 +       _md5_ip5k_get_digest(mctx->state);
2213 +       hw_crypto_unlock();
2214 +
2215 +store_only:
2216 +       /* anything left? */
2217 +       if (len)
2218 +               memcpy(mctx->buf + index , data, len);
2219 +}
2220 +
2221 +/* Add padding and return the message digest. */
2222 +static void md5_final(struct crypto_tfm *tfm, u8 *out)
2223 +{
2224 +       struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2225 +       u32 bits[2];
2226 +       unsigned int index, end;
2227 +
2228 +       /* must perform manual padding */
2229 +       index = mctx->count & 0x3f;
2230 +       end =  (index < 56) ? MD5_BLOCK_SIZE : (2 * MD5_BLOCK_SIZE);
2231 +
2232 +       /* start pad with 1 */
2233 +       mctx->buf[index] = 0x80;
2234 +
2235 +       /* pad with zeros */
2236 +       index++;
2237 +       memset(mctx->buf + index, 0x00, end - index - 8);
2238 +
2239 +       /* append message length */
2240 +       bits[0] = mctx->count << 3;
2241 +       bits[1] = mctx->count >> 29;
2242 +       __cpu_to_le32s(bits);
2243 +       __cpu_to_le32s(bits + 1);
2244 +
2245 +       memcpy(mctx->buf + end - 8, &bits, sizeof(bits));
2246 +
2247 +       /* force to use the mctx->buf and ignore the partial buf */
2248 +       mctx->count = mctx->count & ~0x3f;
2249 +       md5_update(tfm, mctx->buf, end);
2250 +
2251 +       /* copy digest to out */
2252 +       memcpy(out, mctx->state, MD5_DIGEST_SIZE);
2253 +
2254 +       /* wipe context */
2255 +       memset(mctx, 0, sizeof *mctx);
2256 +}
2257 +
2258 +static struct crypto_alg alg = {
2259 +       .cra_name       =       "md5",
2260 +       .cra_driver_name=       "md5-ubicom32",
2261 +       .cra_priority   =       CRYPTO_UBICOM32_PRIORITY,
2262 +       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
2263 +       .cra_blocksize  =       MD5_BLOCK_SIZE,
2264 +       .cra_ctxsize    =       sizeof(struct ubicom32_md5_ctx),
2265 +       .cra_module     =       THIS_MODULE,
2266 +       .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
2267 +       .cra_u = {
2268 +               .digest = {
2269 +                       .dia_digestsize =       MD5_DIGEST_SIZE,
2270 +                       .dia_init       =       md5_init,
2271 +                       .dia_update     =       md5_update,
2272 +                       .dia_final      =       md5_final,
2273 +               }
2274 +       }
2275 +};
2276 +
2277 +static int __init init(void)
2278 +{
2279 +       hw_crypto_init();
2280 +       return crypto_register_alg(&alg);
2281 +}
2282 +
2283 +static void __exit fini(void)
2284 +{
2285 +       crypto_unregister_alg(&alg);
2286 +}
2287 +
2288 +module_init(init);
2289 +module_exit(fini);
2290 +
2291 +MODULE_ALIAS("md5");
2292 +
2293 +MODULE_LICENSE("GPL");
2294 +MODULE_DESCRIPTION("MD5 Secure Hash Algorithm");
2295 --- /dev/null
2296 +++ b/arch/ubicom32/crypto/sha1_ubicom32_asm.S
2297 @@ -0,0 +1,244 @@
2298 +/*
2299 + * arch/ubicom32/crypto/sha1_ubicom32_asm.S
2300 + *     SHA1 hash support for Ubicom32 architecture V3.
2301 + *
2302 + * (C) Copyright 2009, Ubicom, Inc.
2303 + *
2304 + * This file is part of the Ubicom32 Linux Kernel Port.
2305 + *
2306 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2307 + * it and/or modify it under the terms of the GNU General Public License
2308 + * as published by the Free Software Foundation, either version 2 of the
2309 + * License, or (at your option) any later version.
2310 + *
2311 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2312 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2313 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2314 + * the GNU General Public License for more details.
2315 + *
2316 + * You should have received a copy of the GNU General Public License
2317 + * along with the Ubicom32 Linux Kernel Port.  If not,
2318 + * see <http://www.gnu.org/licenses/>.
2319 + *
2320 + * Ubicom32 implementation derived from (with many thanks):
2321 + *   arch/m68knommu
2322 + *   arch/blackfin
2323 + *   arch/parisc
2324 + */
2325 +
2326 +#define __ASM__
2327 +#include <asm/ip5000.h>
2328 +
2329 +#ifndef RP
2330 +#define RP A5
2331 +#endif
2332 +
2333 +;*****************************************************************************************
2334 +; The function prototype
2335 +;*****************************************************************************************
2336 +; void sha1_ip5k_init(void)
2337 +; void sha1_ip5k_transform(u32_t *data_input)
2338 +; void sha1_ip5k_output(u32_t *digest)
2339 +
2340 +;*****************************************************************************************
2341 +; Inputs
2342 +;*****************************************************************************************
2343 +; data_input is the pointer to the block of data over which the digest will be calculated.
2344 +;      It should be word aligned.
2345 +;
2346 +; digest is the pointer to the block of data into which the digest (the output) will be written.
2347 +;      It should be word aligned.
2348 +;
2349 +
2350 +;*****************************************************************************************
2351 +; Outputs
2352 +;*****************************************************************************************
2353 +; None
2354 +
2355 +;*****************************************************************************************
2356 +; Hash Constants
2357 +;*****************************************************************************************
2358 +#define HASH_SHA1_IN0 0x67452301
2359 +#define HASH_SHA1_IN1 0xefcdab89
2360 +#define HASH_SHA1_IN2 0x98badcfe
2361 +#define HASH_SHA1_IN3 0x10325476
2362 +#define HASH_SHA1_IN4 0xc3d2e1f0
2363 +
2364 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2365 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2366 +
2367 +;*****************************************************************************************
2368 +; An: Address Registers
2369 +;*****************************************************************************************
2370 +#define an_digest a4
2371 +#define an_data_input a4
2372 +#define an_security_block a3
2373 +
2374 +;*****************************************************************************************
2375 +; Hash related defines
2376 +;*****************************************************************************************
2377 +#define hash_control 0x00(an_security_block)
2378 +#define hash_control_low 0x02(an_security_block)
2379 +#define hash_status 0x04(an_security_block)
2380 +
2381 +#define hash_input_0 0x30(an_security_block)
2382 +#define hash_input_1 0x34(an_security_block)
2383 +#define hash_input_2 0x38(an_security_block)
2384 +#define hash_input_3 0x3c(an_security_block)
2385 +#define hash_input_4 0x40(an_security_block)
2386 +
2387 +#define hash_output_0 0x70(an_security_block)
2388 +#define hash_output_0_low 0x72(an_security_block)
2389 +#define hash_output_1 0x74(an_security_block)
2390 +#define hash_output_1_low 0x76(an_security_block)
2391 +#define hash_output_2 0x78(an_security_block)
2392 +#define hash_output_2_low 0x7a(an_security_block)
2393 +#define hash_output_3 0x7c(an_security_block)
2394 +#define hash_output_3_low 0x7e(an_security_block)
2395 +#define hash_output_4 0x80(an_security_block)
2396 +#define hash_output_4_low 0x82(an_security_block)
2397 +
2398 +;*****************************************************************************************
2399 +; Assembly macros
2400 +;*****************************************************************************************
2401 +       ; C compiler reserves RP (A5) for return address during subroutine call.
2402 +       ; Use RP to return to caller
2403 +.macro call_return_macro
2404 +       calli   RP, 0(RP)
2405 +.endm
2406 +
2407 +;*****************************************************************************************
2408 +;      void sha1_ip5k_init(void)
2409 +;              initialize the output registers of the hash module
2410 +
2411 +       ;.section .text.sha1_ip5k_init,"ax",@progbits
2412 +       .section .ocm_text,"ax",@progbits
2413 +       .global _sha1_ip5k_init
2414 +       .func sha1_ip5k_init, _sha1_ip5k_init
2415 +
2416 +_sha1_ip5k_init:
2417 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2418 +
2419 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2420 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2421 +
2422 +       movei hash_output_0, #%hi(HASH_SHA1_IN0)
2423 +       movei hash_output_0_low, #%lo(HASH_SHA1_IN0)
2424 +
2425 +       movei hash_output_1, #%hi(HASH_SHA1_IN1)
2426 +       movei hash_output_1_low, #%lo(HASH_SHA1_IN1)
2427 +
2428 +       movei hash_output_2, #%hi(HASH_SHA1_IN2)
2429 +       movei hash_output_2_low, #%lo(HASH_SHA1_IN2)
2430 +
2431 +       movei hash_output_3, #%hi(HASH_SHA1_IN3)
2432 +       movei hash_output_3_low, #%lo(HASH_SHA1_IN3)
2433 +
2434 +       movei hash_output_4, #%hi(HASH_SHA1_IN4)
2435 +       movei hash_output_4_low, #%lo(HASH_SHA1_IN4)
2436 +
2437 +       call_return_macro
2438 +       .endfunc
2439 +
2440 +;*****************************************************************************************
2441 +;      void sha1_ip5k_init_digest(u32_t *hash_input)
2442 +;              initialize the output registers of the hash module
2443 +
2444 +       ;.section .text.sha1_ip5k_init_digest,"ax",@progbits
2445 +       .section .ocm_text,"ax",@progbits
2446 +       .global _sha1_ip5k_init_digest
2447 +       .func sha1_ip5k_init_digest, _sha1_ip5k_init_digest
2448 +
2449 +_sha1_ip5k_init_digest:
2450 +       movea an_data_input, D0
2451 +
2452 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2453 +
2454 +       movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2455 +       movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2456 +
2457 +       move.4 hash_output_0, (an_data_input)4++
2458 +       move.4 hash_output_1, (an_data_input)4++
2459 +       move.4 hash_output_2, (an_data_input)4++
2460 +       move.4 hash_output_3, (an_data_input)4++
2461 +       move.4 hash_output_4, (an_data_input)4++
2462 +
2463 +       call_return_macro
2464 +       .endfunc
2465 +
2466 +;*****************************************************************************************
2467 +;      void sha1_ip5k_transform(u32_t *data_input)
2468 +;              performs intermediate transformation step for the hash calculation
2469 +
2470 +       ;.section .text.sha1_ip5k_transform,"ax",@progbits
2471 +       .section .ocm_text,"ax",@progbits
2472 +       .global _sha1_ip5k_transform
2473 +       .func sha1_ip5k_transform, _sha1_ip5k_transform
2474 +
2475 +_sha1_ip5k_transform:
2476 +       movea an_data_input, D0
2477 +
2478 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2479 +
2480 +       ; Write the first 128bits (16 bytes)
2481 +       move.4 hash_input_0, (an_data_input)4++
2482 +       move.4 hash_input_1, (an_data_input)4++
2483 +       move.4 hash_input_2, (an_data_input)4++
2484 +       move.4 hash_input_3, (an_data_input)4++
2485 +       move.4 hash_input_4, D0
2486 +
2487 +       move.4 hash_input_0, (an_data_input)4++
2488 +       move.4 hash_input_1, (an_data_input)4++
2489 +       move.4 hash_input_2, (an_data_input)4++
2490 +       move.4 hash_input_3, (an_data_input)4++
2491 +       move.4 hash_input_4, D0
2492 +
2493 +       move.4 hash_input_0, (an_data_input)4++
2494 +       move.4 hash_input_1, (an_data_input)4++
2495 +       move.4 hash_input_2, (an_data_input)4++
2496 +       move.4 hash_input_3, (an_data_input)4++
2497 +       move.4 hash_input_4, D0
2498 +
2499 +       move.4 hash_input_0, (an_data_input)4++
2500 +       move.4 hash_input_1, (an_data_input)4++
2501 +       move.4 hash_input_2, (an_data_input)4++
2502 +       move.4 hash_input_3, (an_data_input)4++
2503 +       move.4 hash_input_4, D0
2504 +
2505 +       pipe_flush 0
2506 +
2507 +sha1_ip5k_transform_wait:
2508 +       ; wait for the module to calculate the output hash
2509 +       btst hash_status, #0
2510 +       jmpne.f sha1_ip5k_transform_wait
2511 +
2512 +       call_return_macro
2513 +       .endfunc
2514 +
2515 +;*****************************************************************************************
2516 +;      void sha1_ip5k_output(u32_t *digest)
2517 +;              Return the hash of the input data
2518 +
2519 +       ;.section .text.sha1_ip5k_output,"ax",@progbits
2520 +       .section .ocm_text,"ax",@progbits
2521 +       .global _sha1_ip5k_output
2522 +       .func sha1_ip5k_output, _sha1_ip5k_output
2523 +
2524 +_sha1_ip5k_output:
2525 +       movea an_digest, D0
2526 +
2527 +       moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2528 +
2529 +       ; we have finished
2530 +       move.4 0(an_digest), hash_output_0
2531 +       move.4 4(an_digest), hash_output_1
2532 +       move.4 8(an_digest), hash_output_2
2533 +       move.4 12(an_digest), hash_output_3
2534 +       move.4 16(an_digest), hash_output_4
2535 +
2536 +       call_return_macro
2537 +       .endfunc
2538 +
2539 +;*****************************************************************************************
2540 +;END                   ;End of program code
2541 +;*****************************************************************************************
2542 --- /dev/null
2543 +++ b/arch/ubicom32/crypto/sha1_ubicom32.c
2544 @@ -0,0 +1,354 @@
2545 +/*
2546 + * arch/ubicom32/crypto/sha1_ubicom32.c
2547 + *   Ubicom32 implementation of the SHA1 Secure Hash Algorithm.
2548 + *
2549 + * (C) Copyright 2009, Ubicom, Inc.
2550 + *
2551 + * This file is part of the Ubicom32 Linux Kernel Port.
2552 + *
2553 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2554 + * it and/or modify it under the terms of the GNU General Public License
2555 + * as published by the Free Software Foundation, either version 2 of the
2556 + * License, or (at your option) any later version.
2557 + *
2558 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2559 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2560 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2561 + * the GNU General Public License for more details.
2562 + *
2563 + * You should have received a copy of the GNU General Public License
2564 + * along with the Ubicom32 Linux Kernel Port.  If not,
2565 + * see <http://www.gnu.org/licenses/>.
2566 + *
2567 + * Ubicom32 implementation derived from (with many thanks):
2568 + *   arch/m68knommu
2569 + *   arch/blackfin
2570 + *   arch/parisc
2571 + */
2572 +#include <linux/init.h>
2573 +#include <linux/module.h>
2574 +#include <linux/crypto.h>
2575 +#include <crypto/sha.h>
2576 +#include <asm/linkage.h>
2577 +
2578 +#include "crypto_ubicom32.h"
2579 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2580 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2581 +
2582 +struct ubicom32_sha1_ctx {
2583 +       u64 count;              /* message length */
2584 +       u32 state[5];
2585 +       u8 buf[2 * SHA1_BLOCK_SIZE];
2586 +};
2587 +
2588 +static inline void sha1_clear_2ws(u8 *buf, int wc)
2589 +{
2590 +       asm volatile (
2591 +       "1:     move.4  (%0)4++, #0             \n\t"
2592 +       "       move.4  (%0)4++, #0             \n\t"
2593 +       "       sub.4   %1, #2, %1              \n\t"
2594 +       "       jmple.f 1b                      \n\t"
2595 +               :
2596 +               : "a" (buf), "d" (wc)
2597 +               : "cc"
2598 +       );
2599 +}
2600 +
2601 +/* only wipe out count, state, and 1st half of buf - 9 bytes at most */
2602 +#define sha1_wipe_out(sctx) sha1_clear_2ws((u8 *)sctx, 2 + 5 + 16 - 2)
2603 +
2604 +static inline void sha1_init_digest(u32 *digest)
2605 +{
2606 +       hw_crypto_set_ctrl(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1);
2607 +       asm volatile (
2608 +       "       ; move digests to hash_output regs      \n\t"
2609 +       "       move.4  0x70(%0), 0x0(%1)               \n\t"
2610 +       "       move.4  0x74(%0), 0x4(%1)               \n\t"
2611 +       "       move.4  0x78(%0), 0x8(%1)               \n\t"
2612 +       "       move.4  0x7c(%0), 0xc(%1)               \n\t"
2613 +       "       move.4  0x80(%0), 0x10(%1)              \n\t"
2614 +               :
2615 +               : "a" (SEC_BASE), "a" (digest)
2616 +       );
2617 +}
2618 +
2619 +static inline void sha1_transform_feed(const u8 *in)
2620 +{
2621 +       asm volatile (
2622 +       "       ; write the 1st 16 bytes        \n\t"
2623 +       "       move.4  0x30(%0), 0x0(%1)       \n\t"
2624 +       "       move.4  0x34(%0), 0x4(%1)       \n\t"
2625 +       "       move.4  0x38(%0), 0x8(%1)       \n\t"
2626 +       "       move.4  0x3c(%0), 0xc(%1)       \n\t"
2627 +       "       move.4  0x40(%0), %1            \n\t"
2628 +       "       ; write the 2nd 16 bytes        \n\t"
2629 +       "       move.4  0x30(%0), 0x10(%1)      \n\t"
2630 +       "       move.4  0x34(%0), 0x14(%1)      \n\t"
2631 +       "       move.4  0x38(%0), 0x18(%1)      \n\t"
2632 +       "       move.4  0x3c(%0), 0x1c(%1)      \n\t"
2633 +       "       move.4  0x40(%0), %1            \n\t"
2634 +       "       ; write the 3rd 16 bytes        \n\t"
2635 +       "       move.4  0x30(%0), 0x20(%1)      \n\t"
2636 +       "       move.4  0x34(%0), 0x24(%1)      \n\t"
2637 +       "       move.4  0x38(%0), 0x28(%1)      \n\t"
2638 +       "       move.4  0x3c(%0), 0x2c(%1)      \n\t"
2639 +       "       move.4  0x40(%0), %1            \n\t"
2640 +       "       ; write the 4th 16 bytes        \n\t"
2641 +       "       move.4  0x30(%0), 0x30(%1)      \n\t"
2642 +       "       move.4  0x34(%0), 0x34(%1)      \n\t"
2643 +       "       move.4  0x38(%0), 0x38(%1)      \n\t"
2644 +       "       move.4  0x3c(%0), 0x3c(%1)      \n\t"
2645 +       "       move.4  0x40(%0), %1            \n\t"
2646 +       "       pipe_flush 0                    \n\t"
2647 +               :
2648 +               : "a"(SEC_BASE), "a"(in)
2649 +       );
2650 +}
2651 +
2652 +static inline void sha1_transform_wait(void)
2653 +{
2654 +       asm volatile (
2655 +       "       btst    0x04(%0), #0            \n\t"
2656 +       "       jmpne.f -4                      \n\t"
2657 +               :
2658 +               : "a"(SEC_BASE)
2659 +               : "cc"
2660 +       );
2661 +}
2662 +
2663 +static inline void sha1_output_digest(u32 *digest)
2664 +{
2665 +       asm volatile (
2666 +       "       move.4  0x0(%1), 0x70(%0)               \n\t"
2667 +       "       move.4  0x4(%1), 0x74(%0)               \n\t"
2668 +       "       move.4  0x8(%1), 0x78(%0)               \n\t"
2669 +       "       move.4  0xc(%1), 0x7c(%0)               \n\t"
2670 +       "       move.4  0x10(%1), 0x80(%0)              \n\t"
2671 +               :
2672 +               : "a" (SEC_BASE), "a" (digest)
2673 +       );
2674 +}
2675 +
2676 +static __ocm_text void sha1_init(struct crypto_tfm *tfm)
2677 +{
2678 +       struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2679 +
2680 +       sctx->state[0] = SHA1_H0;
2681 +       sctx->state[1] = SHA1_H1;
2682 +       sctx->state[2] = SHA1_H2;
2683 +       sctx->state[3] = SHA1_H3;
2684 +       sctx->state[4] = SHA1_H4;
2685 +       sctx->count = 0;
2686 +}
2687 +
2688 +static void __ocm_text sha1_update(struct crypto_tfm *tfm, const u8 *data,
2689 +                       unsigned int len)
2690 +{
2691 +       struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2692 +       int index, clen;
2693 +
2694 +       /* how much is already in the buffer? */
2695 +       index = sctx->count & 0x3f;
2696 +
2697 +       sctx->count += len;
2698 +
2699 +       if (index + len < SHA1_BLOCK_SIZE) {
2700 +               goto store_only;
2701 +       }
2702 +
2703 +       hw_crypto_lock();
2704 +       hw_crypto_check();
2705 +
2706 +       /* init digest set ctrl register too */
2707 +       sha1_init_digest(sctx->state);
2708 +
2709 +       if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2710 +fast_process:
2711 +#if CRYPTO_UBICOM32_LOOP_ASM
2712 +               if (likely(len >= SHA1_BLOCK_SIZE)) {
2713 +                       register unsigned int cnt = len >> 6;   // loop = len / 64;
2714 +                       sha1_transform_feed(data);
2715 +                       data += SHA1_BLOCK_SIZE;
2716 +
2717 +                       /* cnt is pre-decremented in the loop */
2718 +                       asm volatile (
2719 +                       "; while (--loop):  work on 2nd block   \n\t"
2720 +                       "1:     add.4   %2, #-1, %2             \n\t"
2721 +                       "       jmpeq.f 5f                      \n\t"
2722 +                       "                                       \n\t"
2723 +                       "       ; write the 1st 16 bytes        \n\t"
2724 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2725 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2726 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2727 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2728 +                       "       ; can not kick off hw before it \n\t"
2729 +                       "       ; is done with the prev block   \n\t"
2730 +                       "                                       \n\t"
2731 +                       "       btst    0x04(%1), #0            \n\t"
2732 +                       "       jmpne.f -4                      \n\t"
2733 +                       "                                       \n\t"
2734 +                       "       ; tell hw to load 1st 16 bytes  \n\t"
2735 +                       "       move.4  0x40(%1), %2            \n\t"
2736 +                       "                                       \n\t"
2737 +                       "       ; write the 2nd 16 bytes        \n\t"
2738 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2739 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2740 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2741 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2742 +                       "       move.4  0x40(%1), %2            \n\t"
2743 +                       "                                       \n\t"
2744 +                       "       ; write the 3rd 16 bytes        \n\t"
2745 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2746 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2747 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2748 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2749 +                       "       move.4  0x40(%1), %2            \n\t"
2750 +                       "                                       \n\t"
2751 +                       "       ; write the 4th 16 bytes        \n\t"
2752 +                       "       move.4  0x30(%1), (%0)4++       \n\t"
2753 +                       "       move.4  0x34(%1), (%0)4++       \n\t"
2754 +                       "       move.4  0x38(%1), (%0)4++       \n\t"
2755 +                       "       move.4  0x3c(%1), (%0)4++       \n\t"
2756 +                       "       move.4  0x40(%1), %2            \n\t"
2757 +                       "                                       \n\t"
2758 +                       "; no need flush, enough insts          \n\t"
2759 +                       "; before next hw wait                  \n\t"
2760 +                       "                                       \n\t"
2761 +                       "; go back to loop                      \n\t"
2762 +                       "       jmpt 1b                         \n\t"
2763 +                       "                                       \n\t"
2764 +                       "; wait hw for last block               \n\t"
2765 +                       "5:     btst 0x04(%1), #0               \n\t"
2766 +                       "       jmpne.f -4                      \n\t"
2767 +                       "                                       \n\t"
2768 +                               : "+a" (data)
2769 +                               : "a"( SEC_BASE), "d" (cnt)
2770 +                               : "cc"
2771 +                       );
2772 +
2773 +                       len = len & (64 - 1);
2774 +               }
2775 +#else
2776 +               while (likely(len >= SHA1_BLOCK_SIZE)) {
2777 +                       sha1_transform_feed(data);
2778 +                       data += SHA1_BLOCK_SIZE;
2779 +                       len -= SHA1_BLOCK_SIZE;
2780 +                       sha1_transform_wait();
2781 +               }
2782 +#endif
2783 +               goto store;
2784 +       }
2785 +
2786 +       /* process one stored block */
2787 +       if (index) {
2788 +               clen = SHA1_BLOCK_SIZE - index;
2789 +               memcpy(sctx->buf + index, data, clen);
2790 +               sha1_transform_feed(sctx->buf);
2791 +               data += clen;
2792 +               len -= clen;
2793 +               index = 0;
2794 +               sha1_transform_wait();
2795 +       }
2796 +
2797 +       if (likely(SEC_ALIGNED(data))) {
2798 +               goto fast_process;
2799 +       }
2800 +
2801 +       /* process as many blocks as possible */
2802 +       if (likely(len >= SHA1_BLOCK_SIZE)) {
2803 +               memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2804 +               do {
2805 +                       sha1_transform_feed(sctx->buf);
2806 +                       data += SHA1_BLOCK_SIZE;
2807 +                       len -= SHA1_BLOCK_SIZE;
2808 +                       if (likely(len >= SHA1_BLOCK_SIZE)) {
2809 +                               memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2810 +                               sha1_transform_wait();
2811 +                               continue;
2812 +                       }
2813 +                       /* it is the last block */
2814 +                       sha1_transform_wait();
2815 +                       break;
2816 +               } while (1);
2817 +       }
2818 +
2819 +store:
2820 +       sha1_output_digest(sctx->state);
2821 +       hw_crypto_unlock();
2822 +
2823 +store_only:
2824 +       /* anything left? */
2825 +       if (len)
2826 +               memcpy(sctx->buf + index , data, len);
2827 +}
2828 +
2829 +/* Add padding and return the message digest. */
2830 +static void __ocm_text sha1_final(struct crypto_tfm *tfm, u8 *out)
2831 +{
2832 +       struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2833 +       u64 bits;
2834 +       unsigned int index, end;
2835 +
2836 +       /* must perform manual padding */
2837 +       index = sctx->count & 0x3f;
2838 +       end =  (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
2839 +
2840 +       /* start pad with 1 */
2841 +       sctx->buf[index] = 0x80;
2842 +
2843 +       /* pad with zeros */
2844 +       index++;
2845 +       memset(sctx->buf + index, 0x00, end - index - 8);
2846 +
2847 +       /* append message length */
2848 +       bits = sctx->count << 3 ;
2849 +       SEC_COPY_2W(sctx->buf + end - 8, &bits);
2850 +
2851 +       /* force to use the sctx->buf and ignore the partial buf */
2852 +       sctx->count = sctx->count & ~0x3f;
2853 +       sha1_update(tfm, sctx->buf, end);
2854 +
2855 +       /* copy digest to out */
2856 +       SEC_COPY_5W(out, sctx->state);
2857 +
2858 +       /* wipe context */
2859 +       sha1_wipe_out(sctx);
2860 +}
2861 +
2862 +static struct crypto_alg alg = {
2863 +       .cra_name       =       "sha1",
2864 +       .cra_driver_name=       "sha1-ubicom32",
2865 +       .cra_priority   =       CRYPTO_UBICOM32_PRIORITY,
2866 +       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
2867 +       .cra_blocksize  =       SHA1_BLOCK_SIZE,
2868 +       .cra_ctxsize    =       sizeof(struct ubicom32_sha1_ctx),
2869 +       .cra_module     =       THIS_MODULE,
2870 +       .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
2871 +       .cra_u    = {
2872 +               .digest = {
2873 +                       .dia_digestsize =       SHA1_DIGEST_SIZE,
2874 +                       .dia_init       =       sha1_init,
2875 +                       .dia_update     =       sha1_update,
2876 +                       .dia_final      =       sha1_final,
2877 +               }
2878 +       }
2879 +};
2880 +
2881 +static int __init init(void)
2882 +{
2883 +       hw_crypto_init();
2884 +       return crypto_register_alg(&alg);
2885 +}
2886 +
2887 +static void __exit fini(void)
2888 +{
2889 +       crypto_unregister_alg(&alg);
2890 +}
2891 +
2892 +module_init(init);
2893 +module_exit(fini);
2894 +
2895 +MODULE_ALIAS("sha1");
2896 +
2897 +MODULE_LICENSE("GPL");
2898 +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
2899 --- /dev/null
2900 +++ b/arch/ubicom32/include/asm/a.out.h
2901 @@ -0,0 +1,47 @@
2902 +/*
2903 + * arch/ubicom32/include/asm/a.out.h
2904 + *   Definitions for Ubicom32 a.out executable format.
2905 + *
2906 + * (C) Copyright 2009, Ubicom, Inc.
2907 + *
2908 + * This file is part of the Ubicom32 Linux Kernel Port.
2909 + *
2910 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2911 + * it and/or modify it under the terms of the GNU General Public License
2912 + * as published by the Free Software Foundation, either version 2 of the
2913 + * License, or (at your option) any later version.
2914 + *
2915 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2916 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2917 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2918 + * the GNU General Public License for more details.
2919 + *
2920 + * You should have received a copy of the GNU General Public License
2921 + * along with the Ubicom32 Linux Kernel Port.  If not,
2922 + * see <http://www.gnu.org/licenses/>.
2923 + *
2924 + * Ubicom32 implementation derived from (with many thanks):
2925 + *   arch/m68knommu
2926 + *   arch/blackfin
2927 + *   arch/parisc
2928 + */
2929 +#ifndef _ASM_UBICOM32_A_OUT_H
2930 +#define _ASM_UBICOM32_A_OUT_H
2931 +
2932 +struct exec
2933 +{
2934 +  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
2935 +  unsigned a_text;             /* length of text, in bytes */
2936 +  unsigned a_data;             /* length of data, in bytes */
2937 +  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
2938 +  unsigned a_syms;             /* length of symbol table data in file, in bytes */
2939 +  unsigned a_entry;            /* start address */
2940 +  unsigned a_trsize;           /* length of relocation info for text, in bytes */
2941 +  unsigned a_drsize;           /* length of relocation info for data, in bytes */
2942 +};
2943 +
2944 +#define N_TRSIZE(a)    ((a).a_trsize)
2945 +#define N_DRSIZE(a)    ((a).a_drsize)
2946 +#define N_SYMSIZE(a)   ((a).a_syms)
2947 +
2948 +#endif /* _ASM_UBICOM32_A_OUT_H */
2949 --- /dev/null
2950 +++ b/arch/ubicom32/include/asm/atomic.h
2951 @@ -0,0 +1,348 @@
2952 +/*
2953 + * arch/ubicom32/include/asm/atomic.h
2954 + *   Atomic operations definitions for Ubicom32 architecture.
2955 + *
2956 + * (C) Copyright 2009, Ubicom, Inc.
2957 + *
2958 + * This file is part of the Ubicom32 Linux Kernel Port.
2959 + *
2960 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2961 + * it and/or modify it under the terms of the GNU General Public License
2962 + * as published by the Free Software Foundation, either version 2 of the
2963 + * License, or (at your option) any later version.
2964 + *
2965 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2966 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2967 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
2968 + * the GNU General Public License for more details.
2969 + *
2970 + * You should have received a copy of the GNU General Public License
2971 + * along with the Ubicom32 Linux Kernel Port.  If not,
2972 + * see <http://www.gnu.org/licenses/>.
2973 + *
2974 + * Ubicom32 implementation derived from (with many thanks):
2975 + *   arch/m68knommu
2976 + *   arch/blackfin
2977 + *   arch/parisc
2978 + */
2979 +#ifndef _ASM_UBICOM32_ATOMIC_H
2980 +#define _ASM_UBICOM32_ATOMIC_H
2981 +
2982 +#include <asm/system.h>
2983 +#include <asm/ubicom32-common.h>
2984 +#include <asm/types.h>
2985 +
2986 +/*
2987 + * Most instructions on the Ubicom32 processor are atomic in that they
2988 + * execute in one clock cycle.  However, Linux has several operations
2989 + * (e.g. compare and swap) which will require more than a single instruction
2990 + * to perform.   To achieve this, the Ubicom32 processor uses a single
2991 + * global bit in a scratchpad register as a critical section lock. All
2992 + * atomic operations acquire this lock.
2993 + *
2994 + * NOTE: To AVOID DEADLOCK(s), the atomic lock must only be used for atomic
2995 + * operations or by the ldsr to avoid disabling a thread performing an atomic
2996 + * operation.
2997 + *
2998 + * Do not attempt to disable interrupts while holding the atomic operations
2999 + * lock or you will DEADLOCK the system.
3000 + */
3001 +
3002 +#define ATOMIC_INIT(i) { (i) }
3003 +
3004 +/*
3005 + * __atomic_add()
3006 + *     Add i to v and return the result.
3007 + */
3008 +static inline void __atomic_add(int i, atomic_t *v)
3009 +{
3010 +       atomic_t *vt = v;
3011 +
3012 +       __atomic_lock_acquire();
3013 +       vt->counter += i;
3014 +       __atomic_lock_release();
3015 +}
3016 +
3017 +/*
3018 + * __atomic_sub()
3019 + *     Subtract i from v and return the result.
3020 + */
3021 +static inline void __atomic_sub(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_add_return()
3032 + *     Add i to v and return the result.
3033 + *
3034 + * The implementation here looks rather odd because we appear to be doing
3035 + * the addition twice.  In fact that's exactly what we're doing but with
3036 + * the ubicom32 instruction set we can do the inner load and add with two
3037 + * instructions whereas generating both the atomic result and the "ret"
3038 + * result requires three instructions.  The second add is generally only as
3039 + * costly as a move instruction and in cases where we compare the result
3040 + * with a constant the compiler can fold two constant values and do a
3041 + * single instruction, thus saving an instruction overall!
3042 + *
3043 + * At the worst we save one instruction inside the atomic lock.
3044 + */
3045 +static inline int __atomic_add_return(int i, atomic_t *v)
3046 +{
3047 +       int ret;
3048 +       atomic_t *vt = v;
3049 +
3050 +       __atomic_lock_acquire();
3051 +       ret = vt->counter;
3052 +       vt->counter = ret + i;
3053 +       __atomic_lock_release();
3054 +
3055 +       return ret + i;
3056 +}
3057 +
3058 +/*
3059 + * __atomic_sub_return()
3060 + *     Subtract i from v and return the result.
3061 + *
3062 + * The implementation here looks rather odd because we appear to be doing
3063 + * the subtraction twice.  In fact that's exactly what we're doing but with
3064 + * the ubicom32 instruction set we can do the inner load and sub with two
3065 + * instructions whereas generating both the atomic result and the "ret"
3066 + * result requires three instructions.  The second sub is generally only as
3067 + * costly as a move instruction and in cases where we compare the result
3068 + * with a constant the compiler can fold two constant values and do a
3069 + * single instruction, thus saving an instruction overall!
3070 + *
3071 + * At the worst we save one instruction inside the atomic lock.
3072 + */
3073 +static inline int __atomic_sub_return(int i, atomic_t *v)
3074 +{
3075 +       int ret;
3076 +       atomic_t *vt = v;
3077 +
3078 +       __atomic_lock_acquire();
3079 +       ret = vt->counter;
3080 +       vt->counter = ret - i;
3081 +       __atomic_lock_release();
3082 +
3083 +       return ret - i;
3084 +}
3085 +
3086 +/*
3087 + * PUBLIC API FOR ATOMIC!
3088 + */
3089 +#define atomic_add(i,v)        (__atomic_add( ((int)i),(v)))
3090 +#define atomic_sub(i,v)        (__atomic_sub( ((int)i),(v)))
3091 +#define atomic_inc(v)  (__atomic_add(   1,(v)))
3092 +#define atomic_dec(v)  (__atomic_sub(   1,(v)))
3093 +#define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v)))
3094 +#define atomic_sub_return(i,v) (__atomic_sub_return( ((int)i),(v)))
3095 +#define atomic_inc_return(v)   (__atomic_add_return(   1,(v)))
3096 +#define atomic_dec_return(v)   (__atomic_sub_return(   1,(v)))
3097 +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
3098 +#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
3099 +#define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
3100 +#define atomic_sub_and_test(i,v)       (atomic_sub_return((i),(v)) == 0)
3101 +
3102 +/*
3103 + * atomic_read()
3104 + *     Acquire the atomic lock and read the variable.
3105 + */
3106 +static inline int atomic_read(const atomic_t *v)
3107 +{
3108 +       int ret;
3109 +       const atomic_t *vt = v;
3110 +
3111 +       __atomic_lock_acquire();
3112 +       ret = vt->counter;
3113 +       __atomic_lock_release();
3114 +
3115 +       return ret;
3116 +}
3117 +
3118 +/*
3119 + * atomic_set()
3120 + *     Acquire the atomic lock and set the variable.
3121 + */
3122 +static inline void atomic_set(atomic_t *v, int i)
3123 +{
3124 +       atomic_t *vt = v;
3125 +
3126 +       __atomic_lock_acquire();
3127 +       vt->counter = i;
3128 +       __atomic_lock_release();
3129 +}
3130 +
3131 +/*
3132 + * atomic_cmpxchg
3133 + *     Acquire the atomic lock and exchange if current == old.
3134 + */
3135 +static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
3136 +{
3137 +       int prev;
3138 +       atomic_t *vt = v;
3139 +
3140 +       __atomic_lock_acquire();
3141 +       prev = vt->counter;
3142 +       if (prev == old) {
3143 +               vt->counter = new;
3144 +       }
3145 +       __atomic_lock_release();
3146 +
3147 +       return prev;
3148 +}
3149 +
3150 +/*
3151 + * atomic_xchg()
3152 + *     Acquire the atomic lock and exchange values.
3153 + */
3154 +static inline int atomic_xchg(atomic_t *v, int new)
3155 +{
3156 +       int prev;
3157 +       atomic_t *vt = v;
3158 +
3159 +       __atomic_lock_acquire();
3160 +       prev = vt->counter;
3161 +       vt->counter = new;
3162 +       __atomic_lock_release();
3163 +
3164 +       return prev;
3165 +}
3166 +
3167 +/*
3168 + * atomic_add_unless()
3169 + *     Acquire the atomic lock and add a unless the value is u.
3170 + */
3171 +static inline int atomic_add_unless(atomic_t *v, int a, int u)
3172 +{
3173 +       int prev;
3174 +       atomic_t *vt = v;
3175 +
3176 +       __atomic_lock_acquire();
3177 +       prev = vt->counter;
3178 +       if (prev != u) {
3179 +               vt->counter += a;
3180 +               __atomic_lock_release();
3181 +               return 1;
3182 +       }
3183 +
3184 +       __atomic_lock_release();
3185 +       return 0;
3186 +}
3187 +
3188 +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
3189 +
3190 +#include <asm-generic/atomic.h>
3191 +
3192 +/*
3193 + * The following is not a real function.  The compiler should remove the function
3194 + * call as long as the user does not pass in a size that __xchg and __cmpxchg
3195 + * are not prepared for.  If the user does pass in an unknown size, the user
3196 + * will get a link time error.
3197 + *
3198 + * The no return is to prevent a compiler error that can occur when dealing with
3199 + * uninitialized variables. Given that the function doesn't exist there is no
3200 + * net effect (and if it did it would not return).
3201 + */
3202 +extern void __xchg_called_with_bad_pointer(void) __attribute__((noreturn));
3203 +
3204 +/*
3205 + * __xchg()
3206 + *     Xchange *ptr for x atomically.
3207 + *
3208 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3209 + * atomic exchange instruction so we use the global atomic_lock.
3210 + */
3211 +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
3212 +{
3213 +       unsigned long ret;
3214 +
3215 +       __atomic_lock_acquire();
3216 +
3217 +       switch (size) {
3218 +       case 1:
3219 +               ret = *(volatile unsigned char *)ptr;
3220 +               *(volatile unsigned char *)ptr = x;
3221 +               break;
3222 +
3223 +       case 2:
3224 +               ret = *(volatile unsigned short *)ptr;
3225 +               *(volatile unsigned short *)ptr = x;
3226 +               break;
3227 +
3228 +       case 4:
3229 +               ret = *(volatile unsigned int *)ptr;
3230 +               *(volatile unsigned int *)ptr = x;
3231 +               break;
3232 +
3233 +       default:
3234 +               __xchg_called_with_bad_pointer();
3235 +               break;
3236 +       }
3237 +       __atomic_lock_release();
3238 +       return ret;
3239 +}
3240 +
3241 +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
3242 +
3243 +/*
3244 + * __cmpxchg()
3245 + *     Compare and Xchange *ptr for x atomically.
3246 + *
3247 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3248 + * atomic exchange instruction so we use the global atomic_lock.
3249 + */
3250 +static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long next, int size)
3251 +{
3252 +       unsigned long prev;
3253 +
3254 +       __atomic_lock_acquire();
3255 +       switch (size) {
3256 +       case 1:
3257 +               prev = *(u8 *)ptr;
3258 +               if (prev == old) {
3259 +                       *(u8 *)ptr = (u8)next;
3260 +               }
3261 +               break;
3262 +
3263 +       case 2:
3264 +               prev = *(u16 *)ptr;
3265 +               if (prev == old) {
3266 +                       *(u16 *)ptr = (u16)next;
3267 +               }
3268 +               break;
3269 +
3270 +       case 4:
3271 +               prev = *(u32 *)ptr;
3272 +               if (prev == old) {
3273 +                       *(u32 *)ptr = (u32)next;
3274 +               }
3275 +               break;
3276 +
3277 +       default:
3278 +               __xchg_called_with_bad_pointer();
3279 +               break;
3280 +       }
3281 +       __atomic_lock_release();
3282 +       return prev;
3283 +}
3284 +
3285 +/*
3286 + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
3287 + * them available.
3288 + */
3289 +#define cmpxchg_local(ptr, o, n) \
3290 +       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
3291 +
3292 +#define cmpxchg(ptr, o, n) __cmpxchg((ptr), (o), (n), sizeof(*(ptr)))
3293 +
3294 +#define smp_mb__before_atomic_inc() asm volatile ("" : : : "memory")
3295 +#define smp_mb__after_atomic_inc() asm volatile ("" : : : "memory")
3296 +#define smp_mb__before_atomic_dec() asm volatile ("" : : : "memory")
3297 +#define smp_mb__after_atomic_dec() asm volatile ("" : : : "memory")
3298 +
3299 +#endif /* _ASM_UBICOM32_ATOMIC_H */
3300 --- /dev/null
3301 +++ b/arch/ubicom32/include/asm/audio.h
3302 @@ -0,0 +1,40 @@
3303 +/*
3304 + * arch/ubicom32/include/asm/audio.h
3305 + *     Audio include file
3306 + *
3307 + * (C) Copyright 2009, Ubicom, Inc.
3308 + *
3309 + * This file is part of the Ubicom32 Linux Kernel Port.
3310 + *
3311 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3312 + * it and/or modify it under the terms of the GNU General Public License
3313 + * as published by the Free Software Foundation, either version 2 of the
3314 + * License, or (at your option) any later version.
3315 + *
3316 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3317 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3318 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3319 + * the GNU General Public License for more details.
3320 + *
3321 + * You should have received a copy of the GNU General Public License
3322 + * along with the Ubicom32 Linux Kernel Port.  If not,
3323 + * see <http://www.gnu.org/licenses/>.
3324 + */
3325 +
3326 +#ifndef _AUDIO_H
3327 +#define _AUDIO_H
3328 +
3329 +#include <asm/devtree.h>
3330 +#include <asm/audionode.h>
3331 +
3332 +/*
3333 + * Resource indices used to access IRQs via platform_get_resource
3334 + */
3335 +#define AUDIO_MEM_RESOURCE     0
3336 +#define AUDIO_TX_IRQ_RESOURCE  0
3337 +#define AUDIO_RX_IRQ_RESOURCE  1
3338 +
3339 +extern struct platform_device * __init audio_device_alloc(const char *driver_name, const char *node_name, const char *inst_name, int priv_size);
3340 +
3341 +#define audio_device_priv(pdev) (((struct ubi32pcm_platform_data *)(((struct platform_device *)(pdev))->dev.platform_data))->priv_data)
3342 +#endif
3343 --- /dev/null
3344 +++ b/arch/ubicom32/include/asm/audionode.h
3345 @@ -0,0 +1,152 @@
3346 +/*
3347 + * audionode.h
3348 + *     audionode and DMA descriptors
3349 + *
3350 + * Copyright \81© 2009 Ubicom Inc. <www.ubicom.com>.  All rights reserved.
3351 + *
3352 + * This file contains confidential information of Ubicom, Inc. and your use of
3353 + * this file is subject to the Ubicom Software License Agreement distributed with
3354 + * this file. If you are uncertain whether you are an authorized user or to report
3355 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
3356 + * Unauthorized reproduction or distribution of this file is subject to civil and
3357 + * criminal penalties.
3358 + *
3359 + */
3360 +#ifndef _AUDIONODE_H_
3361 +#define _AUDIONODE_H_
3362 +
3363 +#define AUDIO_INT_FLAG_MORE_SAMPLES 0x00000001
3364 +#define AUDIO_INT_FLAG_COMMAND      0x00000002
3365 +
3366 +/*
3367 + * Commands the Primary OS sends to the audio device
3368 + */
3369 +enum audio_command {
3370 +       AUDIO_CMD_NONE,
3371 +       AUDIO_CMD_START,
3372 +       AUDIO_CMD_STOP,
3373 +       AUDIO_CMD_PAUSE,
3374 +       AUDIO_CMD_RESUME,
3375 +       AUDIO_CMD_MUTE,
3376 +       AUDIO_CMD_UNMUTE,
3377 +       AUDIO_CMD_SETUP,
3378 +       AUDIO_CMD_ENABLE,
3379 +       AUDIO_CMD_DISABLE,
3380 +};
3381 +
3382 +/*
3383 + * Flag bits passed in the registers
3384 + */
3385 +#define CMD_START_FLAG_LE              (1 << 0)        /* Use Little Endian Mode */
3386 +
3387 +/*
3388 + * Status bits that audio device can set to indicate reason
3389 + * for interrupting the Primary OS
3390 + */
3391 +#define AUDIO_STATUS_PLAY_DMA0_REQUEST (1 << 0) /* Audio device needs samples in DMA0 for playback */
3392 +#define AUDIO_STATUS_PLAY_DMA1_REQUEST (1 << 1) /* Audio device needs samples in DMA1 for playback */
3393 +
3394 +struct audio_dma {
3395 +       /*
3396 +        * NOTE: The active flag shall only be SET by the producer and CLEARED
3397 +        * by the consumer, NEVER the other way around.  For playback, the
3398 +        * Primary OS sets this flag and ipAudio clears it.
3399 +        *
3400 +        * The producer shall not modify the ptr or ctr fields when the transfer
3401 +        * is marked as active, as these are used by the consumer to do the
3402 +        * transfer.
3403 +        */
3404 +       volatile u32_t active;          /* Nonzero if data in ptr/ctr ready to be transferred */
3405 +       volatile void *ptr;             /* Pointer to data to be transferred */
3406 +       volatile u32_t ctr;             /* Counter: number of data units to transfer */
3407 +};
3408 +
3409 +#define AUDIONODE_CAP_BE       (1 << 0)
3410 +#define AUDIONODE_CAP_LE       (1 << 1)
3411 +
3412 +#define AUDIONODE_VERSION      7
3413 +struct audio_node {
3414 +       struct devtree_node dn;
3415 +
3416 +       /*
3417 +        * Version of this node
3418 +        */
3419 +       u32_t                   version;
3420 +
3421 +       /*
3422 +        * Pointer to the registers
3423 +        */
3424 +       struct audio_regs       *regs;
3425 +};
3426 +
3427 +/*
3428 + * [OCM] Audio registers
3429 + *     Registers exposed as part of our MMIO area
3430 + */
3431 +#define AUDIO_REGS_VERSION     7
3432 +struct audio_regs {
3433 +       /*
3434 +        * Version of this register set
3435 +        */
3436 +       u32_t version;
3437 +
3438 +       /*
3439 +        * Interrupt status
3440 +        */
3441 +       volatile u32_t int_status;
3442 +
3443 +       /*
3444 +        * Interrupt request
3445 +        */
3446 +       volatile u32_t int_req;
3447 +
3448 +       /*
3449 +        * Current IRQ being serviced
3450 +        */
3451 +       u32_t cur_irq;
3452 +
3453 +       /*
3454 +        * Maximum number of devices supported
3455 +        */
3456 +       u32_t max_devs;
3457 +
3458 +       /*
3459 +        * [DDR] Device registers for each of the devices
3460 +        */
3461 +       struct audio_dev_regs *adr;
3462 +};
3463 +
3464 +#define AUDIO_DEV_REGS_VERSION 2
3465 +struct audio_dev_regs {
3466 +       u32_t version;                                  /* Version of this register set */
3467 +
3468 +       u8_t name[32];                                  /* Name of this driver */
3469 +       u32_t caps;                                     /* Capabilities of this driver */
3470 +       const u32_t *sample_rates;                      /* Sample Rates supported by this driver */
3471 +       u32_t n_sample_rates;                           /* Number of sample rates supported by this driver */
3472 +       u32_t channel_mask;                             /* A bit set in a particular position means we support this channel configuration */
3473 +       volatile u32_t int_flags;                       /* Reason for interrupting audio device */
3474 +       volatile enum audio_command command;    /* Command from Primary OS */
3475 +       volatile u32_t flags;                           /* Flag bits for this command */
3476 +       volatile u32_t channels;                        /* Number of channels */
3477 +       volatile u32_t sample_rate;                     /* Sample rate */
3478 +       volatile u32_t status;                          /* Status bits sent from ipAudio to Primary OS */
3479 +       void *primary_os_buffer_ptr;                    /*
3480 +                                                        * Playback: Pointer to next sample to be removed from
3481 +                                                        *           Primary OS sample buffer
3482 +                                                        * Capture: Pointer to where next sample will be inserted
3483 +                                                        *          into Primary OS sample buffer
3484 +                                                        */
3485 +
3486 +       /*
3487 +        * These are the transfer requests.  They are used in alternating
3488 +        * order so that when ipAudio is processing one request, the
3489 +        * Primary OS can fill in the other one.
3490 +        *
3491 +        * NOTE: The active bit shall always be SET by the producer and
3492 +        * CLEARED by the consumer, NEVER the other way around.
3493 +        */
3494 +       struct audio_dma dma_xfer_requests[2];
3495 +};
3496 +
3497 +#endif
3498 --- /dev/null
3499 +++ b/arch/ubicom32/include/asm/auxvec.h
3500 @@ -0,0 +1,32 @@
3501 +/*
3502 + * arch/ubicom32/include/asm/auxvec.h
3503 + *   Symbolic values for the entries in the auxiliary table
3504 + *   put on the initial stack.
3505 + *
3506 + * (C) Copyright 2009, Ubicom, Inc.
3507 + *
3508 + * This file is part of the Ubicom32 Linux Kernel Port.
3509 + *
3510 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3511 + * it and/or modify it under the terms of the GNU General Public License
3512 + * as published by the Free Software Foundation, either version 2 of the
3513 + * License, or (at your option) any later version.
3514 + *
3515 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3516 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3517 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3518 + * the GNU General Public License for more details.
3519 + *
3520 + * You should have received a copy of the GNU General Public License
3521 + * along with the Ubicom32 Linux Kernel Port.  If not,
3522 + * see <http://www.gnu.org/licenses/>.
3523 + *
3524 + * Ubicom32 implementation derived from (with many thanks):
3525 + *   arch/m68knommu
3526 + *   arch/blackfin
3527 + *   arch/parisc
3528 + */
3529 +#ifndef _ASM_UBICOM32_AUXVEC_H
3530 +#define _ASM_UBICOM32_AUXVEC_H
3531 +
3532 +#endif /* _ASM_UBICOM32_AUXVEC_H */
3533 --- /dev/null
3534 +++ b/arch/ubicom32/include/asm/bitops.h
3535 @@ -0,0 +1,172 @@
3536 +/*
3537 + * arch/ubicom32/include/asm/bitops.h
3538 + *   Bit manipulation definitions for Ubicom32 architecture.
3539 + *
3540 + * (C) Copyright 2009, Ubicom, Inc.
3541 + *
3542 + * This file is part of the Ubicom32 Linux Kernel Port.
3543 + *
3544 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3545 + * it and/or modify it under the terms of the GNU General Public License
3546 + * as published by the Free Software Foundation, either version 2 of the
3547 + * License, or (at your option) any later version.
3548 + *
3549 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3550 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3551 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3552 + * the GNU General Public License for more details.
3553 + *
3554 + * You should have received a copy of the GNU General Public License
3555 + * along with the Ubicom32 Linux Kernel Port.  If not,
3556 + * see <http://www.gnu.org/licenses/>.
3557 + *
3558 + * Ubicom32 implementation derived from (with many thanks):
3559 + *   arch/m68knommu
3560 + *   arch/blackfin
3561 + *   arch/parisc
3562 + */
3563 +#ifndef _ASM_UBICOM32_BITOPS_H
3564 +#define _ASM_UBICOM32_BITOPS_H
3565 +
3566 +/*
3567 + * Copyright 1992, Linus Torvalds.
3568 + */
3569 +
3570 +#include <linux/compiler.h>
3571 +#include <asm/byteorder.h>     /* swab32 */
3572 +
3573 +#ifdef __KERNEL__
3574 +
3575 +#ifndef _LINUX_BITOPS_H
3576 +#error only <linux/bitops.h> can be included directly
3577 +#endif
3578 +
3579 +#include <asm-generic/bitops/ffs.h>
3580 +#include <asm-generic/bitops/__ffs.h>
3581 +
3582 +#include <asm-generic/bitops/sched.h>
3583 +#include <asm-generic/bitops/ffz.h>
3584 +
3585 +#include <asm/ubicom32-common.h>
3586 +
3587 +static inline void set_bit(int bit, volatile unsigned long *p)
3588 +{
3589 +       unsigned long mask = 1UL << (bit & 31);
3590 +
3591 +       p += bit >> 5;
3592 +
3593 +       __atomic_lock_acquire();
3594 +       *p |= mask;
3595 +       __atomic_lock_release();
3596 +}
3597 +
3598 +static inline void clear_bit(int bit, volatile unsigned long *p)
3599 +{
3600 +       unsigned long mask = 1UL << (bit & 31);
3601 +
3602 +       p += bit >> 5;
3603 +
3604 +       __atomic_lock_acquire();
3605 +       *p &= ~mask;
3606 +       __atomic_lock_release();
3607 +}
3608 +
3609 +/*
3610 + * clear_bit() doesn't provide any barrier for the compiler.
3611 + */
3612 +#define smp_mb__before_clear_bit()     barrier()
3613 +#define smp_mb__after_clear_bit()      barrier()
3614 +
3615 +static inline void change_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 +static inline int test_and_set_bit(int bit, volatile unsigned long *p)
3627 +{
3628 +       unsigned int res;
3629 +       unsigned long mask = 1UL << (bit & 31);
3630 +
3631 +       p += bit >> 5;
3632 +
3633 +       __atomic_lock_acquire();
3634 +       res = *p;
3635 +       *p = res | mask;
3636 +       __atomic_lock_release();
3637 +
3638 +       return res & mask;
3639 +}
3640 +
3641 +static inline int test_and_clear_bit(int bit, volatile unsigned long *p)
3642 +{
3643 +       unsigned int res;
3644 +       unsigned long mask = 1UL << (bit & 31);
3645 +
3646 +       p += bit >> 5;
3647 +
3648 +       __atomic_lock_acquire();
3649 +       res = *p;
3650 +       *p = res & ~mask;
3651 +       __atomic_lock_release();
3652 +
3653 +       return res & mask;
3654 +}
3655 +
3656 +static inline int test_and_change_bit(int bit, volatile unsigned long *p)
3657 +{
3658 +       unsigned int res;
3659 +       unsigned long mask = 1UL << (bit & 31);
3660 +
3661 +       p += bit >> 5;
3662 +
3663 +       __atomic_lock_acquire();
3664 +       res = *p;
3665 +       *p = res ^ mask;
3666 +       __atomic_lock_release();
3667 +
3668 +       return res & mask;
3669 +}
3670 +
3671 +#include <asm-generic/bitops/non-atomic.h>
3672 +
3673 +/*
3674 + * This routine doesn't need to be atomic.
3675 + */
3676 +static inline int __constant_test_bit(int nr, const volatile unsigned long *addr)
3677 +{
3678 +       return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
3679 +}
3680 +
3681 +static inline int __test_bit(int nr, const volatile unsigned long *addr)
3682 +{
3683 +       int     * a = (int *) addr;
3684 +       int     mask;
3685 +
3686 +       a += nr >> 5;
3687 +       mask = 1 << (nr & 0x1f);
3688 +       return ((mask & *a) != 0);
3689 +}
3690 +
3691 +#define test_bit(nr,addr) (__builtin_constant_p(nr) ?  __constant_test_bit((nr),(addr)) :  __test_bit((nr),(addr)))
3692 +
3693 +#include <asm-generic/bitops/find.h>
3694 +#include <asm-generic/bitops/hweight.h>
3695 +#include <asm-generic/bitops/lock.h>
3696 +
3697 +#include <asm-generic/bitops/ext2-non-atomic.h>
3698 +#include <asm-generic/bitops/ext2-atomic.h>
3699 +#include <asm-generic/bitops/minix.h>
3700 +
3701 +#endif /* __KERNEL__ */
3702 +
3703 +#include <asm-generic/bitops/fls.h>
3704 +#include <asm-generic/bitops/__fls.h>
3705 +#include <asm-generic/bitops/fls64.h>
3706 +
3707 +#endif /* _ASM_UBICOM32_BITOPS_H */
3708 --- /dev/null
3709 +++ b/arch/ubicom32/include/asm/board.h
3710 @@ -0,0 +1,34 @@
3711 +/*
3712 + * arch/ubicom32/include/asm/board.h
3713 + *   Board init and revision definitions for Ubicom32 architecture.
3714 + *
3715 + * (C) Copyright 2009, Ubicom, Inc.
3716 + *
3717 + * This file is part of the Ubicom32 Linux Kernel Port.
3718 + *
3719 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3720 + * it and/or modify it under the terms of the GNU General Public License
3721 + * as published by the Free Software Foundation, either version 2 of the
3722 + * License, or (at your option) any later version.
3723 + *
3724 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3725 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3726 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3727 + * the GNU General Public License for more details.
3728 + *
3729 + * You should have received a copy of the GNU General Public License
3730 + * along with the Ubicom32 Linux Kernel Port.  If not,
3731 + * see <http://www.gnu.org/licenses/>.
3732 + *
3733 + * Ubicom32 implementation derived from (with many thanks):
3734 + *   arch/m68knommu
3735 + *   arch/blackfin
3736 + *   arch/parisc
3737 + */
3738 +#ifndef _ASM_UBICOM32_BOARD_H
3739 +#define _ASM_UBICOM32_BOARD_H
3740 +
3741 +extern const char *board_get_revision(void);
3742 +extern void __init board_init(void);
3743 +
3744 +#endif /* _ASM_UBICOM32_BOARD_H */
3745 --- /dev/null
3746 +++ b/arch/ubicom32/include/asm/bootargs.h
3747 @@ -0,0 +1,34 @@
3748 +/*
3749 + * arch/ubicom32/include/asm/bootargs.h
3750 + *   Kernel command line via the devtree API.
3751 + *
3752 + * (C) Copyright 2009, Ubicom, Inc.
3753 + *
3754 + * This file is part of the Ubicom32 Linux Kernel Port.
3755 + *
3756 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3757 + * it and/or modify it under the terms of the GNU General Public License
3758 + * as published by the Free Software Foundation, either version 2 of the
3759 + * License, or (at your option) any later version.
3760 + *
3761 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3762 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3763 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3764 + * the GNU General Public License for more details.
3765 + *
3766 + * You should have received a copy of the GNU General Public License
3767 + * along with the Ubicom32 Linux Kernel Port.  If not,
3768 + * see <http://www.gnu.org/licenses/>.
3769 + *
3770 + * Ubicom32 implementation derived from (with many thanks):
3771 + *   arch/m68knommu
3772 + *   arch/blackfin
3773 + *   arch/parisc
3774 + */
3775 +#ifndef _ASM_UBICOM32_BOOTARGS_H
3776 +#define _ASM_UBICOM32_BOOTARGS_H
3777 +
3778 +extern const char *bootargs_get_cmdline(void);
3779 +extern void __init bootargs_init(void);
3780 +
3781 +#endif /* _ASM_UBICOM32_BOOTARGS_H */
3782 --- /dev/null
3783 +++ b/arch/ubicom32/include/asm/bootinfo.h
3784 @@ -0,0 +1,34 @@
3785 +/*
3786 + * arch/ubicom32/include/asm/bootinfo.h
3787 + *   Definitions of firmware boot parameters passed to the kernel.
3788 + *
3789 + * (C) Copyright 2009, Ubicom, Inc.
3790 + *
3791 + * This file is part of the Ubicom32 Linux Kernel Port.
3792 + *
3793 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3794 + * it and/or modify it under the terms of the GNU General Public License
3795 + * as published by the Free Software Foundation, either version 2 of the
3796 + * License, or (at your option) any later version.
3797 + *
3798 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3799 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3800 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3801 + * the GNU General Public License for more details.
3802 + *
3803 + * You should have received a copy of the GNU General Public License
3804 + * along with the Ubicom32 Linux Kernel Port.  If not,
3805 + * see <http://www.gnu.org/licenses/>.
3806 + *
3807 + * Ubicom32 implementation derived from (with many thanks):
3808 + *   arch/m68knommu
3809 + *   arch/blackfin
3810 + *   arch/parisc
3811 + */
3812 +
3813 +#ifndef _ASM_UBICOM32_BOOTINFO_H
3814 +#define _ASM_UBICOM32_BOOTINFO_H
3815 +
3816 +/* Nothing for ubicom32 */
3817 +
3818 +#endif /* _ASM_UBICOM32_BOOTINFO_H */
3819 --- /dev/null
3820 +++ b/arch/ubicom32/include/asm/bug.h
3821 @@ -0,0 +1,95 @@
3822 +/*
3823 + * arch/ubicom32/include/asm/bug.h
3824 + *   Generic bug.h for Ubicom32 architecture.
3825 + *
3826 + * (C) Copyright 2009, Ubicom, Inc.
3827 + *
3828 + * This file is part of the Ubicom32 Linux Kernel Port.
3829 + *
3830 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3831 + * it and/or modify it under the terms of the GNU General Public License
3832 + * as published by the Free Software Foundation, either version 2 of the
3833 + * License, or (at your option) any later version.
3834 + *
3835 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3836 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3837 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3838 + * the GNU General Public License for more details.
3839 + *
3840 + * You should have received a copy of the GNU General Public License
3841 + * along with the Ubicom32 Linux Kernel Port.  If not,
3842 + * see <http://www.gnu.org/licenses/>.
3843 + *
3844 + * Ubicom32 implementation derived from (with many thanks):
3845 + *   arch/m68knommu
3846 + *   arch/blackfin
3847 + *   arch/parisc
3848 + */
3849 +#ifndef _ASM_UBICOM32_BUG_H
3850 +#define _ASM_UBICOM32_BUG_H
3851 +
3852 +#include <linux/kernel.h>
3853 +#include <asm/thread.h>
3854 +
3855 +#if defined(CONFIG_BUG) && defined(CONFIG_STOP_ON_BUG)
3856 +
3857 +/*
3858 + * BUG()
3859 + *     Ubicom specific version of the BUG() macro.
3860 + *
3861 + * This implementation performs a THREAD_STALL stopping all threads before
3862 + * calling panic.  This enables a developer to see the "real" state of the
3863 + * machine (since panic alters the system state).  We do the printf first
3864 + * because while it is slow, it does not alter system state (like
3865 + * interrupts).
3866 + *
3867 + * TODO: Implement the trap sequence used by other architectures.
3868 + */
3869 +#define BUG() do { \
3870 +       printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3871 +       THREAD_STALL; \
3872 +       panic("BUG!"); \
3873 +} while (0)
3874 +
3875 +
3876 +/*
3877 + * __WARN()
3878 + *     WARN() using printk() for now.
3879 + *
3880 + * TODO: Implement the trap sequence used by other architectures.
3881 + */
3882 +#define __WARN()                                                       \
3883 +       do {                                                            \
3884 +               printk("WARN: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3885 +       } while(0)
3886 +
3887 +/*
3888 + * WARN_ON()
3889 + *     Ubicom specific version of the WARN_ON macro.
3890 + *
3891 + * This implementation performs a printk for the WARN_ON() instead
3892 + * of faulting into the kernel and using report_bug().
3893 + *
3894 + * TODO: Implement the trap sequence used by other architectures.
3895 + */
3896 +#define WARN_ON(x) ({                                          \
3897 +       int __ret_warn_on = !!(x);                              \
3898 +       if (__builtin_constant_p(__ret_warn_on)) {              \
3899 +               if (__ret_warn_on)                              \
3900 +                       __WARN();                               \
3901 +       } else {                                                \
3902 +               if (unlikely(__ret_warn_on))                    \
3903 +                       __WARN();                               \
3904 +       }                                                       \
3905 +       unlikely(__ret_warn_on);                                \
3906 +})
3907 +
3908 +
3909 +#define HAVE_ARCH_BUG
3910 +#define HAVE_ARCH_WARN_ON
3911 +
3912 +#endif
3913 +
3914 +#include <asm-generic/bug.h>
3915 +
3916 +#endif /* _ASM_UBICOM32_BUG_H */
3917 --- /dev/null
3918 +++ b/arch/ubicom32/include/asm/bugs.h
3919 @@ -0,0 +1,44 @@
3920 +/*
3921 + * arch/ubicom32/include/asm/bugs.h
3922 + *   Definition of check_bugs() for Ubicom32 architecture.
3923 + *
3924 + * (C) Copyright 2009, Ubicom, Inc.
3925 + * Copyright (C) 1994  Linus Torvalds
3926 + *
3927 + * This file is part of the Ubicom32 Linux Kernel Port.
3928 + *
3929 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3930 + * it and/or modify it under the terms of the GNU General Public License
3931 + * as published by the Free Software Foundation, either version 2 of the
3932 + * License, or (at your option) any later version.
3933 + *
3934 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3935 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3936 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3937 + * the GNU General Public License for more details.
3938 + *
3939 + * You should have received a copy of the GNU General Public License
3940 + * along with the Ubicom32 Linux Kernel Port.  If not,
3941 + * see <http://www.gnu.org/licenses/>.
3942 + *
3943 + * Ubicom32 implementation derived from (with many thanks):
3944 + *   arch/m68knommu
3945 + *   arch/blackfin
3946 + *   arch/parisc
3947 + */
3948 +
3949 +/*
3950 + * This is included by init/main.c to check for architecture-dependent bugs.
3951 + *
3952 + * Needs:
3953 + *     void check_bugs(void);
3954 + */
3955 +
3956 +#ifndef _ASM_UBICOM32_BUGS_H
3957 +#define _ASM_UBICOM32_BUGS_H
3958 +
3959 +static void check_bugs(void)
3960 +{
3961 +}
3962 +
3963 +#endif /* _ASM_UBICOM32_BUGS_H */
3964 --- /dev/null
3965 +++ b/arch/ubicom32/include/asm/byteorder.h
3966 @@ -0,0 +1,33 @@
3967 +/*
3968 + * arch/ubicom32/include/asm/byteorder.h
3969 + *   Byte order swapping utility routines.
3970 + *
3971 + * (C) Copyright 2009, Ubicom, Inc.
3972 + *
3973 + * This file is part of the Ubicom32 Linux Kernel Port.
3974 + *
3975 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3976 + * it and/or modify it under the terms of the GNU General Public License
3977 + * as published by the Free Software Foundation, either version 2 of the
3978 + * License, or (at your option) any later version.
3979 + *
3980 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3981 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3982 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
3983 + * the GNU General Public License for more details.
3984 + *
3985 + * You should have received a copy of the GNU General Public License
3986 + * along with the Ubicom32 Linux Kernel Port.  If not,
3987 + * see <http://www.gnu.org/licenses/>.
3988 + *
3989 + * Ubicom32 implementation derived from (with many thanks):
3990 + *   arch/m68knommu
3991 + *   arch/blackfin
3992 + *   arch/parisc
3993 + */
3994 +#ifndef _ASM_UBICOM32_BYTEORDER_H
3995 +#define _ASM_UBICOM32_BYTEORDER_H
3996 +
3997 +#include <linux/byteorder/big_endian.h>
3998 +
3999 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
4000 --- /dev/null
4001 +++ b/arch/ubicom32/include/asm/cachectl.h
4002 @@ -0,0 +1,39 @@
4003 +/*
4004 + * arch/ubicom32/include/asm/cachectl.h
4005 + *   Ubicom32 cache control definitions.
4006 + *
4007 + * (C) Copyright 2009, Ubicom, Inc.
4008 + *
4009 + * This file is part of the Ubicom32 Linux Kernel Port.
4010 + *
4011 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4012 + * it and/or modify it under the terms of the GNU General Public License
4013 + * as published by the Free Software Foundation, either version 2 of the
4014 + * License, or (at your option) any later version.
4015 + *
4016 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4017 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4018 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4019 + * the GNU General Public License for more details.
4020 + *
4021 + * You should have received a copy of the GNU General Public License
4022 + * along with the Ubicom32 Linux Kernel Port.  If not,
4023 + * see <http://www.gnu.org/licenses/>.
4024 + *
4025 + * Ubicom32 implementation derived from (with many thanks):
4026 + *   arch/m68knommu
4027 + *   arch/blackfin
4028 + *   arch/parisc
4029 + */
4030 +#ifndef _ASM_UBICOM32_CACHECTL_H
4031 +#define _ASM_UBICOM32_CACHECTL_H
4032 +
4033 +#include <asm/ip5000.h>
4034 +
4035 +/*
4036 + * mem_cache_control()
4037 + *     Special cache control operation
4038 + */
4039 +extern void mem_cache_control(unsigned long cc, unsigned long begin_addr, unsigned long end_addr, unsigned long op);
4040 +
4041 +#endif /* _ASM_UBICOM32_CACHECTL_H */
4042 --- /dev/null
4043 +++ b/arch/ubicom32/include/asm/cacheflush.h
4044 @@ -0,0 +1,111 @@
4045 +/*
4046 + * arch/ubicom32/include/asm/cacheflush.h
4047 + *   Cache flushing definitions for Ubicom32 architecture.
4048 + *
4049 + * (C) Copyright 2009, Ubicom, Inc.
4050 + *
4051 + * This file is part of the Ubicom32 Linux Kernel Port.
4052 + *
4053 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4054 + * it and/or modify it under the terms of the GNU General Public License
4055 + * as published by the Free Software Foundation, either version 2 of the
4056 + * License, or (at your option) any later version.
4057 + *
4058 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4059 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4060 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4061 + * the GNU General Public License for more details.
4062 + *
4063 + * You should have received a copy of the GNU General Public License
4064 + * along with the Ubicom32 Linux Kernel Port.  If not,
4065 + * see <http://www.gnu.org/licenses/>.
4066 + *
4067 + * Ubicom32 implementation derived from (with many thanks):
4068 + *   arch/m68knommu
4069 + *   arch/blackfin
4070 + *   arch/parisc
4071 + */
4072 +#ifndef _ASM_UBICOM32_CACHEFLUSH_H
4073 +#define _ASM_UBICOM32_CACHEFLUSH_H
4074 +
4075 +/*
4076 + * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
4077 + */
4078 +#include <linux/mm.h>
4079 +#include <asm/cachectl.h>
4080 +#include <asm/ip5000.h>
4081 +
4082 +#define flush_cache_all()                      __flush_cache_all()
4083 +#define flush_cache_mm(mm)                     do { } while (0)
4084 +#define flush_cache_dup_mm(mm)                 do { } while (0)
4085 +#define flush_cache_range(vma, start, end)     __flush_cache_all()
4086 +#define flush_cache_page(vma, vmaddr)          do { } while (0)
4087 +#define flush_dcache_page(page)                        do { } while (0)
4088 +#define flush_dcache_mmap_lock(mapping)                do { } while (0)
4089 +#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
4090 +
4091 +#define flush_dcache_range(start, end)                                 \
4092 +do {                                                                   \
4093 +       /* Flush the data cache and invalidate the I cache. */          \
4094 +       mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR);  \
4095 +       mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR);    \
4096 +} while (0)
4097 +
4098 +#define flush_icache_range(start, end)                                 \
4099 +do {                                                                   \
4100 +       /* Flush the data cache and invalidate the I cache. */          \
4101 +       mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR);  \
4102 +       mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR);    \
4103 +} while (0)
4104 +
4105 +#define flush_icache_page(vma,pg)              do { } while (0)
4106 +#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
4107 +#define flush_cache_vmap(start, end)           do { } while (0)
4108 +#define flush_cache_vunmap(start, end)         do { } while (0)
4109 +
4110 +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
4111 +       memcpy(dst, src, len)
4112 +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
4113 +       memcpy(dst, src, len)
4114 +
4115 +/*
4116 + * Cache handling for IP5000
4117 + */
4118 +extern inline void mem_cache_invalidate_all(unsigned long cc)
4119 +{
4120 +       if (cc == DCCR_BASE)
4121 +               UBICOM32_LOCK(DCCR_LOCK_BIT);
4122 +       else
4123 +               UBICOM32_LOCK(ICCR_LOCK_BIT);
4124 +
4125 +       asm volatile (
4126 +       "       bset    "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)"      \n\t"
4127 +       "       nop                                                                     \n\t"
4128 +       "       bclr    "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)"      \n\t"
4129 +       "       pipe_flush 0                                                            \n\t"
4130 +               :
4131 +               : "a"(cc)
4132 +               : "cc"
4133 +       );
4134 +
4135 +       if (cc == DCCR_BASE)
4136 +               UBICOM32_UNLOCK(DCCR_LOCK_BIT);
4137 +       else
4138 +               UBICOM32_UNLOCK(ICCR_LOCK_BIT);
4139 +
4140 +}
4141 +
4142 +static inline void __flush_cache_all(void)
4143 +{
4144 +       /*
4145 +        * Flush Icache
4146 +        */
4147 +       mem_cache_invalidate_all(ICCR_BASE);
4148 +
4149 +       /*
4150 +        * Flush Dcache
4151 +        */
4152 +       mem_cache_invalidate_all(DCCR_BASE);
4153 +}
4154 +
4155 +#endif /* _ASM_UBICOM32_CACHEFLUSH_H */
4156 --- /dev/null
4157 +++ b/arch/ubicom32/include/asm/cache.h
4158 @@ -0,0 +1,40 @@
4159 +/*
4160 + * arch/ubicom32/include/asm/cache.h
4161 + *   Cache line definitions for Ubicom32 architecture.
4162 + *
4163 + * (C) Copyright 2009, Ubicom, Inc.
4164 + *
4165 + * This file is part of the Ubicom32 Linux Kernel Port.
4166 + *
4167 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4168 + * it and/or modify it under the terms of the GNU General Public License
4169 + * as published by the Free Software Foundation, either version 2 of the
4170 + * License, or (at your option) any later version.
4171 + *
4172 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4173 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4174 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4175 + * the GNU General Public License for more details.
4176 + *
4177 + * You should have received a copy of the GNU General Public License
4178 + * along with the Ubicom32 Linux Kernel Port.  If not,
4179 + * see <http://www.gnu.org/licenses/>.
4180 + *
4181 + * Ubicom32 implementation derived from (with many thanks):
4182 + *   arch/m68knommu
4183 + *   arch/blackfin
4184 + *   arch/parisc
4185 + */
4186 +#ifndef _ASM_UBICOM32_CACHE_H
4187 +#define _ASM_UBICOM32_CACHE_H
4188 +
4189 +/*
4190 + * bytes per L1 cache line
4191 + */
4192 +#define L1_CACHE_SHIFT  5
4193 +#define L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)
4194 +
4195 +#define __cacheline_aligned
4196 +#define ____cacheline_aligned
4197 +
4198 +#endif /* _ASM_UBICOM32_CACHE_H */
4199 --- /dev/null
4200 +++ b/arch/ubicom32/include/asm/checksum.h
4201 @@ -0,0 +1,149 @@
4202 +/*
4203 + * arch/ubicom32/include/asm/checksum.h
4204 + *   Checksum utilities for Ubicom32 architecture.
4205 + *
4206 + * (C) Copyright 2009, Ubicom, Inc.
4207 + *
4208 + * This file is part of the Ubicom32 Linux Kernel Port.
4209 + *
4210 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4211 + * it and/or modify it under the terms of the GNU General Public License
4212 + * as published by the Free Software Foundation, either version 2 of the
4213 + * License, or (at your option) any later version.
4214 + *
4215 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4216 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4217 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4218 + * the GNU General Public License for more details.
4219 + *
4220 + * You should have received a copy of the GNU General Public License
4221 + * along with the Ubicom32 Linux Kernel Port.  If not,
4222 + * see <http://www.gnu.org/licenses/>.
4223 + *
4224 + * Ubicom32 implementation derived from (with many thanks):
4225 + *   arch/m68knommu
4226 + *   arch/blackfin
4227 + *   arch/parisc
4228 + */
4229 +#ifndef _ASM_UBICOM32_CHECKSUM_H
4230 +#define _ASM_UBICOM32_CHECKSUM_H
4231 +
4232 +#include <linux/in6.h>
4233 +
4234 +/*
4235 + * computes the checksum of a memory block at buff, length len,
4236 + * and adds in "sum" (32-bit)
4237 + *
4238 + * returns a 32-bit number suitable for feeding into itself
4239 + * or csum_tcpudp_magic
4240 + *
4241 + * this function must be called with even lengths, except
4242 + * for the last fragment, which may be odd
4243 + *
4244 + * it's best to have buff aligned on a 32-bit boundary
4245 + */
4246 +__wsum csum_partial(const void *buff, int len, __wsum sum);
4247 +
4248 +/*
4249 + * the same as csum_partial, but copies from src while it
4250 + * checksums
4251 + *
4252 + * here even more important to align src and dst on a 32-bit (or even
4253 + * better 64-bit) boundary
4254 + */
4255 +
4256 +__wsum csum_partial_copy_nocheck(const void *src, void *dst,
4257 +       int len, __wsum sum);
4258 +
4259 +
4260 +/*
4261 + * the same as csum_partial_copy, but copies from user space.
4262 + *
4263 + * here even more important to align src and dst on a 32-bit (or even
4264 + * better 64-bit) boundary
4265 + */
4266 +
4267 +extern __wsum csum_partial_copy_from_user(const void __user *src,
4268 +       void *dst, int len, __wsum sum, int *csum_err);
4269 +
4270 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
4271 +
4272 +/*
4273 + *     Fold a partial checksum
4274 + */
4275 +
4276 +static inline __sum16 csum_fold(__wsum sum)
4277 +{
4278 +       asm volatile (
4279 +       "       lsr.4   d15, %0, #16    \n\t"
4280 +       "       bfextu  %0, %0, #16     \n\t"
4281 +       "       add.4   %0, d15, %0     \n\t"
4282 +       "       lsr.4   d15, %0, #16    \n\t"
4283 +       "       bfextu  %0, %0, #16     \n\t"
4284 +       "       add.4   %0, d15, %0     \n\t"
4285 +               : "=&d" (sum)
4286 +               : "0"(sum)
4287 +               : "d15"
4288 +       );
4289 +       return (__force __sum16)~sum;
4290 +}
4291 +
4292 +
4293 +/*
4294 + * computes the checksum of the TCP/UDP pseudo-header
4295 + * returns a 16-bit checksum, already complemented
4296 + */
4297 +
4298 +static inline __wsum
4299 +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
4300 +                 unsigned short proto, __wsum sum)
4301 +{
4302 +       asm volatile (
4303 +       "       add.4   %0, %2, %0      \n\t"
4304 +       "       addc    %0, %3, %0      \n\t"
4305 +       "       addc    %0, %4, %0      \n\t"
4306 +       "       addc    %0, %5, %0      \n\t"
4307 +       "       addc    %0, #0, %0      \n\t"
4308 +               : "=&d" (sum)
4309 +               : "0"(sum), "r" (saddr), "r" (daddr), "r" (len), "r"(proto)
4310 +       );
4311 +       return sum;
4312 +}
4313 +
4314 +static inline __sum16
4315 +csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
4316 +                 unsigned short proto, __wsum sum)
4317 +{
4318 +       return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
4319 +}
4320 +
4321 +/*
4322 + * this routine is used for miscellaneous IP-like checksums, mainly
4323 + * in icmp.c
4324 + */
4325 +extern __sum16 ip_compute_csum(const void *buff, int len);
4326 +
4327 +#define _HAVE_ARCH_IPV6_CSUM
4328 +
4329 +static __inline__ __sum16
4330 +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
4331 +               __u32 len, unsigned short proto, __wsum sum)
4332 +{
4333 +       asm volatile (
4334 +       "       add.4   %0, 0(%2), %0   \n\t"
4335 +       "       addc    %0, 4(%2), %0   \n\t"
4336 +       "       addc    %0, 8(%2), %0   \n\t"
4337 +       "       addc    %0, 12(%2), %0  \n\t"
4338 +       "       addc    %0, 0(%3), %0   \n\t"
4339 +       "       addc    %0, 4(%3), %0   \n\t"
4340 +       "       addc    %0, 8(%3), %0   \n\t"
4341 +       "       addc    %0, 12(%3), %0  \n\t"
4342 +       "       addc    %0, %4, %0      \n\t"
4343 +       "       addc    %0, #0, %0      \n\t"
4344 +               : "=&d" (sum)
4345 +               : "0" (sum), "a" (saddr), "a" (daddr), "d" (len + proto)
4346 +       );
4347 +       return csum_fold(sum);
4348 +}
4349 +
4350 +#endif /* _ASM_UBICOM32_CHECKSUM_H */
4351 --- /dev/null
4352 +++ b/arch/ubicom32/include/asm/cpu.h
4353 @@ -0,0 +1,45 @@
4354 +/*
4355 + * arch/ubicom32/include/asm/cpu.h
4356 + *   CPU definitions for Ubicom32 architecture.
4357 + *
4358 + * (C) Copyright 2009, Ubicom, Inc.
4359 + * Copyright (C) 2004-2005 ARM Ltd.
4360 + *
4361 + * This file is part of the Ubicom32 Linux Kernel Port.
4362 + *
4363 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4364 + * it and/or modify it under the terms of the GNU General Public License
4365 + * as published by the Free Software Foundation, either version 2 of the
4366 + * License, or (at your option) any later version.
4367 + *
4368 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4369 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4370 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4371 + * the GNU General Public License for more details.
4372 + *
4373 + * You should have received a copy of the GNU General Public License
4374 + * along with the Ubicom32 Linux Kernel Port.  If not,
4375 + * see <http://www.gnu.org/licenses/>.
4376 + *
4377 + * Ubicom32 implementation derived from (with many thanks):
4378 + *   arch/m68knommu
4379 + *   arch/blackfin
4380 + *   arch/parisc
4381 + */
4382 +#ifndef _ASM_UBICOM32_CPU_H
4383 +#define _ASM_UBICOM32_CPU_H
4384 +
4385 +#include <linux/percpu.h>
4386 +
4387 +struct cpuinfo_ubicom32 {
4388 +       unsigned long tid;                      /* Hardware thread number */
4389 +
4390 +#ifdef CONFIG_SMP
4391 +       volatile unsigned long ipi_pending;     /* Bit map of operations to execute */
4392 +       unsigned long ipi_count;                /* Number of IPI(s) taken on this cpu */
4393 +#endif
4394 +};
4395 +
4396 +DECLARE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
4397 +
4398 +#endif /* _ASM_UBICOM32_CPU_H */
4399 --- /dev/null
4400 +++ b/arch/ubicom32/include/asm/cputime.h
4401 @@ -0,0 +1,33 @@
4402 +/*
4403 + * arch/ubicom32/include/asm/cputime.h
4404 + *   Generic cputime.h for Ubicom32 architecture.
4405 + *
4406 + * (C) Copyright 2009, Ubicom, Inc.
4407 + *
4408 + * This file is part of the Ubicom32 Linux Kernel Port.
4409 + *
4410 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4411 + * it and/or modify it under the terms of the GNU General Public License
4412 + * as published by the Free Software Foundation, either version 2 of the
4413 + * License, or (at your option) any later version.
4414 + *
4415 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4416 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4417 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4418 + * the GNU General Public License for more details.
4419 + *
4420 + * You should have received a copy of the GNU General Public License
4421 + * along with the Ubicom32 Linux Kernel Port.  If not,
4422 + * see <http://www.gnu.org/licenses/>.
4423 + *
4424 + * Ubicom32 implementation derived from (with many thanks):
4425 + *   arch/m68knommu
4426 + *   arch/blackfin
4427 + *   arch/parisc
4428 + */
4429 +#ifndef _ASM_UBICOM32_CPUTIME_H
4430 +#define _ASM_UBICOM32_CPUTIME_H
4431 +
4432 +#include <asm-generic/cputime.h>
4433 +
4434 +#endif /* _ASM_UBICOM32_CPUTIME_H */
4435 --- /dev/null
4436 +++ b/arch/ubicom32/include/asm/current.h
4437 @@ -0,0 +1,44 @@
4438 +/*
4439 + * arch/ubicom32/include/asm/current.h
4440 + *   Definition of get_current() for Ubicom32 architecture.
4441 + *
4442 + * (C) Copyright 2009, Ubicom, Inc.
4443 + * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
4444 + * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
4445 + *
4446 + * This file is part of the Ubicom32 Linux Kernel Port.
4447 + *
4448 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4449 + * it and/or modify it under the terms of the GNU General Public License
4450 + * as published by the Free Software Foundation, either version 2 of the
4451 + * License, or (at your option) any later version.
4452 + *
4453 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4454 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4455 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4456 + * the GNU General Public License for more details.
4457 + *
4458 + * You should have received a copy of the GNU General Public License
4459 + * along with the Ubicom32 Linux Kernel Port.  If not,
4460 + * see <http://www.gnu.org/licenses/>.
4461 + *
4462 + * Ubicom32 implementation derived from (with many thanks):
4463 + *   arch/m68knommu
4464 + *   arch/blackfin
4465 + *   arch/parisc
4466 + */
4467 +#ifndef _ASM_UBICOM32_CURRENT_H
4468 +#define _ASM_UBICOM32_CURRENT_H
4469 +
4470 +#include <linux/thread_info.h>
4471 +
4472 +struct task_struct;
4473 +
4474 +static inline struct task_struct *get_current(void)
4475 +{
4476 +       return(current_thread_info()->task);
4477 +}
4478 +
4479 +#define        current get_current()
4480 +
4481 +#endif /* _ASM_UBICOM32_CURRENT_H */
4482 --- /dev/null
4483 +++ b/arch/ubicom32/include/asm/delay.h
4484 @@ -0,0 +1,75 @@
4485 +/*
4486 + * arch/ubicom32/include/asm/delay.h
4487 + *   Definition of delay routines for Ubicom32 architecture.
4488 + *
4489 + * (C) Copyright 2009, Ubicom, Inc.
4490 + *
4491 + * This file is part of the Ubicom32 Linux Kernel Port.
4492 + *
4493 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4494 + * it and/or modify it under the terms of the GNU General Public License
4495 + * as published by the Free Software Foundation, either version 2 of the
4496 + * License, or (at your option) any later version.
4497 + *
4498 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4499 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4500 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4501 + * the GNU General Public License for more details.
4502 + *
4503 + * You should have received a copy of the GNU General Public License
4504 + * along with the Ubicom32 Linux Kernel Port.  If not,
4505 + * see <http://www.gnu.org/licenses/>.
4506 + *
4507 + * Ubicom32 implementation derived from (with many thanks):
4508 + *   arch/m68knommu
4509 + *   arch/blackfin
4510 + *   arch/parisc
4511 + */
4512 +#ifndef _ASM_UBICOM32_DELAY_H
4513 +#define _ASM_UBICOM32_DELAY_H
4514 +
4515 +#include <asm/param.h>
4516 +#include <asm/ip5000.h>
4517 +
4518 +static inline void __delay(unsigned long loops)
4519 +{
4520 +       if (loops == 0) {
4521 +               return;
4522 +       }
4523 +
4524 +       asm volatile (
4525 +       "1:     add.4   %0, #-1, %0             \n\t"
4526 +       "       jmpne.t 1b                      \n\t"
4527 +       : "+d" (loops)
4528 +       );
4529 +}
4530 +
4531 +/*
4532 + *     Ubicom32 processor uses fixed 12MHz external OSC.
4533 + *     So we use that as reference to count 12 cycles/us
4534 + */
4535 +
4536 +extern unsigned long loops_per_jiffy;
4537 +
4538 +static inline void _udelay(unsigned long usecs)
4539 +{
4540 +#if defined(CONFIG_UBICOM32_V4) || defined(CONFIG_UBICOM32_V3)
4541 +       asm volatile (
4542 +               "       add.4           d15, 0(%0), %1                  \n\t"
4543 +               "       sub.4           #0, 0(%0), d15                  \n\t"
4544 +               "       jmpmi.w.f       .-4                             \n\t"
4545 +               :
4546 +               : "a"(TIMER_BASE + TIMER_MPTVAL), "d"(usecs * (12000000/1000000))
4547 +               : "d15"
4548 +       );
4549 +#else
4550 +       BUG();
4551 +#endif
4552 +}
4553 +
4554 +/*
4555 + *     Moved the udelay() function into library code, no longer inlined.
4556 + */
4557 +extern void udelay(unsigned long usecs);
4558 +
4559 +#endif /* _ASM_UBICOM32_DELAY_H */
4560 --- /dev/null
4561 +++ b/arch/ubicom32/include/asm/device.h
4562 @@ -0,0 +1,35 @@
4563 +/*
4564 + * arch/ubicom32/include/asm/device.h
4565 + *   Generic device.h for Ubicom32 architecture.
4566 + *
4567 + *   Used for arch specific extensions to struct device
4568 + *
4569 + * (C) Copyright 2009, Ubicom, Inc.
4570 + *
4571 + * This file is part of the Ubicom32 Linux Kernel Port.
4572 + *
4573 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4574 + * it and/or modify it under the terms of the GNU General Public License
4575 + * as published by the Free Software Foundation, either version 2 of the
4576 + * License, or (at your option) any later version.
4577 + *
4578 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4579 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4580 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4581 + * the GNU General Public License for more details.
4582 + *
4583 + * You should have received a copy of the GNU General Public License
4584 + * along with the Ubicom32 Linux Kernel Port.  If not,
4585 + * see <http://www.gnu.org/licenses/>.
4586 + *
4587 + * Ubicom32 implementation derived from (with many thanks):
4588 + *   arch/m68knommu
4589 + *   arch/blackfin
4590 + *   arch/parisc
4591 + */
4592 +#ifndef _ASM_UBICOM32_DEVICE_H
4593 +#define _ASM_UBICOM32_DEVICE_H
4594 +
4595 +#include <asm-generic/device.h>
4596 +
4597 +#endif /* _ASM_UBICOM32_DEVICE_H */
4598 --- /dev/null
4599 +++ b/arch/ubicom32/include/asm/devtree.h
4600 @@ -0,0 +1,52 @@
4601 +/*
4602 + * arch/ubicom32/include/asm/devtree.h
4603 + *   Device Tree Header File (Shared between ultra and the Host OS)
4604 + *
4605 + * (C) Copyright 2009, Ubicom, Inc.
4606 + *
4607 + * This file is part of the Ubicom32 Linux Kernel Port.
4608 + *
4609 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4610 + * it and/or modify it under the terms of the GNU General Public License
4611 + * as published by the Free Software Foundation, either version 2 of the
4612 + * License, or (at your option) any later version.
4613 + *
4614 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4615 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4616 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4617 + * the GNU General Public License for more details.
4618 + *
4619 + * You should have received a copy of the GNU General Public License
4620 + * along with the Ubicom32 Linux Kernel Port.  If not,
4621 + * see <http://www.gnu.org/licenses/>.
4622 + *
4623 + * Ubicom32 implementation derived from (with many thanks):
4624 + *   arch/m68knommu
4625 + *   arch/blackfin
4626 + *   arch/parisc
4627 + */
4628 +
4629 +#ifndef _ASM_UBICOM32_DEVTREE_H
4630 +#define _ASM_UBICOM32_DEVTREE_H
4631 +
4632 +#define DEVTREE_MAX_NAME 32
4633 +#define DEVTREE_IRQ_NONE 0xff
4634 +#define DEVTREE_IRQ_DONTCARE 0xff
4635 +#define DEVTREE_NODE_MAGIC 0x10203040
4636 +
4637 +struct devtree_node {
4638 +       struct devtree_node *next;
4639 +       unsigned char sendirq;
4640 +       unsigned char recvirq;
4641 +       char name[DEVTREE_MAX_NAME];
4642 +       unsigned int magic;
4643 +};
4644 +
4645 +extern struct devtree_node *devtree;
4646 +extern struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq);
4647 +extern struct devtree_node *devtree_find_node(const char *str);
4648 +extern struct devtree_node *devtree_find_next(struct devtree_node **cur);
4649 +extern int devtree_irq(struct devtree_node *dn, unsigned char *sendirq, unsigned char *recvirq);
4650 +extern void devtree_print(void);
4651 +
4652 +#endif /* _ASM_UBICOM32_DEVTREE_H */
4653 --- /dev/null
4654 +++ b/arch/ubicom32/include/asm/div64.h
4655 @@ -0,0 +1,33 @@
4656 +/*
4657 + * arch/ubicom32/include/asm/div64.h
4658 + *   Generic div64.h for Ubicom32 architecture.
4659 + *
4660 + * (C) Copyright 2009, Ubicom, Inc.
4661 + *
4662 + * This file is part of the Ubicom32 Linux Kernel Port.
4663 + *
4664 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4665 + * it and/or modify it under the terms of the GNU General Public License
4666 + * as published by the Free Software Foundation, either version 2 of the
4667 + * License, or (at your option) any later version.
4668 + *
4669 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4670 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4671 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4672 + * the GNU General Public License for more details.
4673 + *
4674 + * You should have received a copy of the GNU General Public License
4675 + * along with the Ubicom32 Linux Kernel Port.  If not,
4676 + * see <http://www.gnu.org/licenses/>.
4677 + *
4678 + * Ubicom32 implementation derived from (with many thanks):
4679 + *   arch/m68knommu
4680 + *   arch/blackfin
4681 + *   arch/parisc
4682 + */
4683 +#ifndef _ASM_UBICOM32_DIV64_H
4684 +#define _ASM_UBICOM32_DIV64_H
4685 +
4686 +#include <asm-generic/div64.h>
4687 +
4688 +#endif /* _ASM_UBICOM32_DIV64_H */
4689 --- /dev/null
4690 +++ b/arch/ubicom32/include/asm/dma.h
4691 @@ -0,0 +1,34 @@
4692 +/*
4693 + * arch/ubicom32/include/asm/dma.h
4694 + *   DMA definitions for Ubicom32 architecture.
4695 + *
4696 + * (C) Copyright 2009, Ubicom, Inc.
4697 + *
4698 + * This file is part of the Ubicom32 Linux Kernel Port.
4699 + *
4700 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4701 + * it and/or modify it under the terms of the GNU General Public License
4702 + * as published by the Free Software Foundation, either version 2 of the
4703 + * License, or (at your option) any later version.
4704 + *
4705 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4706 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4707 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4708 + * the GNU General Public License for more details.
4709 + *
4710 + * You should have received a copy of the GNU General Public License
4711 + * along with the Ubicom32 Linux Kernel Port.  If not,
4712 + * see <http://www.gnu.org/licenses/>.
4713 + *
4714 + * Ubicom32 implementation derived from (with many thanks):
4715 + *   arch/m68knommu
4716 + *   arch/blackfin
4717 + *   arch/parisc
4718 + */
4719 +#ifndef _ASM_UBICOM32_DMA_H
4720 +#define _ASM_UBICOM32_DMA_H
4721 +
4722 +/* Nothing so far */
4723 +#define MAX_DMA_ADDRESS 0x00   /* This is quite suspicious */
4724 +
4725 +#endif /* _ASM_UBICOM32_DMA_H */
4726 --- /dev/null
4727 +++ b/arch/ubicom32/include/asm/dma-mapping.h
4728 @@ -0,0 +1,328 @@
4729 +/*
4730 + * arch/ubicom32/include/asm/dma-mapping.h
4731 + *   Generic dma-mapping.h for Ubicom32 architecture.
4732 + *
4733 + * (C) Copyright 2009, Ubicom, Inc.
4734 + *
4735 + * This file is part of the Ubicom32 Linux Kernel Port.
4736 + *
4737 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4738 + * it and/or modify it under the terms of the GNU General Public License
4739 + * as published by the Free Software Foundation, either version 2 of the
4740 + * License, or (at your option) any later version.
4741 + *
4742 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4743 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4744 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
4745 + * the GNU General Public License for more details.
4746 + *
4747 + * You should have received a copy of the GNU General Public License
4748 + * along with the Ubicom32 Linux Kernel Port.  If not,
4749 + * see <http://www.gnu.org/licenses/>.
4750 + *
4751 + * Ubicom32 implementation derived from (with many thanks):
4752 + *   arch/m68knommu
4753 + *   arch/blackfin
4754 + *   arch/parisc
4755 + */
4756 +#ifndef _ASM_UBICOM32_DMA_MAPPING_H
4757 +#define _ASM_UBICOM32_DMA_MAPPING_H
4758 +
4759 +#include <linux/scatterlist.h>
4760 +#ifdef CONFIG_PCI
4761 +
4762 +/* we implement the API below in terms of the existing PCI one,
4763 + * so include it */
4764 +#include <linux/pci.h>
4765 +/* need struct page definitions */
4766 +#include <linux/mm.h>
4767 +
4768 +static inline int
4769 +dma_supported(struct device *dev, u64 mask)
4770 +{
4771 +       BUG_ON(dev->bus != &pci_bus_type);
4772 +
4773 +       return pci_dma_supported(to_pci_dev(dev), mask);
4774 +}
4775 +
4776 +static inline int
4777 +dma_set_mask(struct device *dev, u64 dma_mask)
4778 +{
4779 +       BUG_ON(dev->bus != &pci_bus_type);
4780 +
4781 +       return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
4782 +}
4783 +
4784 +static inline void *
4785 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4786 +                  gfp_t flag)
4787 +{
4788 +       BUG_ON(dev->bus != &pci_bus_type);
4789 +
4790 +       return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
4791 +}
4792 +
4793 +static inline void
4794 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4795 +                   dma_addr_t dma_handle)
4796 +{
4797 +       BUG_ON(dev->bus != &pci_bus_type);
4798 +
4799 +       pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
4800 +}
4801 +
4802 +static inline dma_addr_t
4803 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4804 +              enum dma_data_direction direction)
4805 +{
4806 +       BUG_ON(dev->bus != &pci_bus_type);
4807 +
4808 +       return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
4809 +}
4810 +
4811 +static inline void
4812 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4813 +                enum dma_data_direction direction)
4814 +{
4815 +       BUG_ON(dev->bus != &pci_bus_type);
4816 +
4817 +       pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
4818 +}
4819 +
4820 +static inline dma_addr_t
4821 +dma_map_page(struct device *dev, struct page *page,
4822 +            unsigned long offset, size_t size,
4823 +            enum dma_data_direction direction)
4824 +{
4825 +       BUG_ON(dev->bus != &pci_bus_type);
4826 +
4827 +       return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
4828 +}
4829 +
4830 +static inline void
4831 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4832 +              enum dma_data_direction direction)
4833 +{
4834 +       BUG_ON(dev->bus != &pci_bus_type);
4835 +
4836 +       pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
4837 +}
4838 +
4839 +static inline int
4840 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
4841 +          enum dma_data_direction direction)
4842 +{
4843 +       BUG_ON(dev->bus != &pci_bus_type);
4844 +
4845 +       return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
4846 +}
4847 +
4848 +static inline void
4849 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
4850 +            enum dma_data_direction direction)
4851 +{
4852 +       BUG_ON(dev->bus != &pci_bus_type);
4853 +
4854 +       pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
4855 +}
4856 +
4857 +static inline void
4858 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
4859 +                       enum dma_data_direction direction)
4860 +{
4861 +       BUG_ON(dev->bus != &pci_bus_type);
4862 +
4863 +       pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
4864 +                                   size, (int)direction);
4865 +}
4866 +
4867 +static inline void
4868 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
4869 +                          enum dma_data_direction direction)
4870 +{
4871 +       BUG_ON(dev->bus != &pci_bus_type);
4872 +
4873 +       pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
4874 +                                      size, (int)direction);
4875 +}
4876 +
4877 +static inline void
4878 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
4879 +                   enum dma_data_direction direction)
4880 +{
4881 +       BUG_ON(dev->bus != &pci_bus_type);
4882 +
4883 +       pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
4884 +}
4885 +
4886 +static inline void
4887 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
4888 +                      enum dma_data_direction direction)
4889 +{
4890 +       BUG_ON(dev->bus != &pci_bus_type);
4891 +
4892 +       pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
4893 +}
4894 +
4895 +static inline int
4896 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
4897 +{
4898 +       return pci_dma_mapping_error(to_pci_dev(dev), dma_addr);
4899 +}
4900 +
4901 +
4902 +#else
4903 +
4904 +static inline int
4905 +dma_supported(struct device *dev, u64 mask)
4906 +{
4907 +       return 0;
4908 +}
4909 +
4910 +static inline int
4911 +dma_set_mask(struct device *dev, u64 dma_mask)
4912 +{
4913 +       BUG();
4914 +       return 0;
4915 +}
4916 +
4917 +static inline void *
4918 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4919 +                  gfp_t flag)
4920 +{
4921 +       BUG();
4922 +       return NULL;
4923 +}
4924 +
4925 +static inline void
4926 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4927 +                   dma_addr_t dma_handle)
4928 +{
4929 +       BUG();
4930 +}
4931 +
4932 +static inline dma_addr_t
4933 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4934 +              enum dma_data_direction direction)
4935 +{
4936 +       BUG();
4937 +       return 0;
4938 +}
4939 +
4940 +static inline void
4941 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4942 +                enum dma_data_direction direction)
4943 +{
4944 +       BUG();
4945 +}
4946 +
4947 +static inline dma_addr_t
4948 +dma_map_page(struct device *dev, struct page *page,
4949 +            unsigned long offset, size_t size,
4950 +            enum dma_data_direction direction)
4951 +{
4952 +       BUG();
4953 +       return 0;
4954 +}
4955 +
4956 +static inline void
4957 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4958 +              enum dma_data_direction direction)
4959 +{
4960 +       BUG();
4961 +}
4962 +
4963 +static inline int
4964 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
4965 +          enum dma_data_direction direction)
4966 +{
4967 +       BUG();
4968 +       return 0;
4969 +}
4970 +
4971 +static inline void
4972 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
4973 +            enum dma_data_direction direction)
4974 +{
4975 +       BUG();
4976 +}
4977 +
4978 +static inline void
4979 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
4980 +                       enum dma_data_direction direction)
4981 +{
4982 +       BUG();
4983 +}
4984 +
4985 +static inline void
4986 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
4987 +                          enum dma_data_direction direction)
4988 +{
4989 +       BUG();
4990 +}
4991 +
4992 +static inline void
4993 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
4994 +                   enum dma_data_direction direction)
4995 +{
4996 +       BUG();
4997 +}
4998 +
4999 +static inline void
5000 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
5001 +                      enum dma_data_direction direction)
5002 +{
5003 +       BUG();
5004 +}
5005 +
5006 +static inline int
5007 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
5008 +{
5009 +       return 0;
5010 +}
5011 +
5012 +#endif
5013 +
5014 +/* Now for the API extensions over the pci_ one */
5015 +
5016 +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
5017 +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
5018 +#define dma_is_consistent(d, h)        (1)
5019 +
5020 +static inline int
5021 +dma_get_cache_alignment(void)
5022 +{
5023 +       /* no easy way to get cache size on all processors, so return
5024 +        * the maximum possible, to be safe */
5025 +       return (1 << INTERNODE_CACHE_SHIFT);
5026 +}
5027 +
5028 +static inline void
5029 +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
5030 +                             unsigned long offset, size_t size,
5031 +                             enum dma_data_direction direction)
5032 +{
5033 +       /* just sync everything, that's all the pci API can do */
5034 +       dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
5035 +}
5036 +
5037 +static inline void
5038 +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
5039 +                                unsigned long offset, size_t size,
5040 +                                enum dma_data_direction direction)
5041 +{
5042 +       /* just sync everything, that's all the pci API can do */
5043 +       dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
5044 +}
5045 +
5046 +static inline void
5047 +dma_cache_sync(struct device *dev, void *vaddr, size_t size,
5048 +              enum dma_data_direction direction)
5049 +{
5050 +       /* could define this in terms of the dma_cache ... operations,
5051 +        * but if you get this on a platform, you should convert the platform
5052 +        * to using the generic device DMA API */
5053 +       BUG();
5054 +}
5055 +
5056 +#endif /* _ASM_UBICOM32_DMA_MAPPING_H */
5057 --- /dev/null
5058 +++ b/arch/ubicom32/include/asm/elf.h
5059 @@ -0,0 +1,173 @@
5060 +/*
5061 + * arch/ubicom32/include/asm/elf.h
5062 + *   Definitions for elf executable format for Ubicom32 architecture.
5063 + *
5064 + * (C) Copyright 2009, Ubicom, Inc.
5065 + *
5066 + * This file is part of the Ubicom32 Linux Kernel Port.
5067 + *
5068 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5069 + * it and/or modify it under the terms of the GNU General Public License
5070 + * as published by the Free Software Foundation, either version 2 of the
5071 + * License, or (at your option) any later version.
5072 + *
5073 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5074 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5075 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5076 + * the GNU General Public License for more details.
5077 + *
5078 + * You should have received a copy of the GNU General Public License
5079 + * along with the Ubicom32 Linux Kernel Port.  If not,
5080 + * see <http://www.gnu.org/licenses/>.
5081 + *
5082 + * Ubicom32 implementation derived from (with many thanks):
5083 + *   arch/m68knommu
5084 + *   arch/blackfin
5085 + *   arch/parisc
5086 + */
5087 +#ifndef _ASM_UBICOM32_ELF_H
5088 +#define _ASM_UBICOM32_ELF_H
5089 +
5090 +/*
5091 + * ELF register definitions..
5092 + */
5093 +
5094 +#include <asm/ptrace.h>
5095 +#include <asm/user.h>
5096 +
5097 +/*
5098 + * Processor specific flags for the ELF header e_flags field.
5099 + */
5100 +#define EF_UBICOM32_V3         0x00000001      /* -fmarch=ubicom32v3 */
5101 +#define EF_UBICOM32_V4         0x00000002      /* -fmarch=ubicom32v4 */
5102 +#define EF_UBICOM32_PIC                0x80000000      /* -fpic */
5103 +#define EF_UBICOM32_FDPIC      0x40000000      /* -mfdpic */
5104 +
5105 +/*
5106 + * Ubicom32 ELF relocation types
5107 + */
5108 +#define R_UBICOM32_NONE                        0
5109 +#define R_UBICOM32_16                  1
5110 +#define R_UBICOM32_32                  2
5111 +#define R_UBICOM32_LO16                        3
5112 +#define R_UBICOM32_HI16                        4
5113 +#define R_UBICOM32_21_PCREL            5
5114 +#define R_UBICOM32_24_PCREL            6
5115 +#define R_UBICOM32_HI24                        7
5116 +#define R_UBICOM32_LO7_S               8
5117 +#define R_UBICOM32_LO7_2_S             9
5118 +#define R_UBICOM32_LO7_4_S             10
5119 +#define R_UBICOM32_LO7_D               11
5120 +#define R_UBICOM32_LO7_2_D             12
5121 +#define R_UBICOM32_LO7_4_D             13
5122 +#define R_UBICOM32_32_HARVARD          14
5123 +#define R_UBICOM32_LO7_CALLI           15
5124 +#define R_UBICOM32_LO16_CALLI          16
5125 +#define R_UBICOM32_GOT_HI24            17
5126 +#define R_UBICOM32_GOT_LO7_S           18
5127 +#define R_UBICOM32_GOT_LO7_2_S         19
5128 +#define R_UBICOM32_GOT_LO7_4_S         20
5129 +#define R_UBICOM32_GOT_LO7_D           21
5130 +#define R_UBICOM32_GOT_LO7_2_D         22
5131 +#define R_UBICOM32_GOT_LO7_4_D         23
5132 +#define R_UBICOM32_FUNCDESC_GOT_HI24    24
5133 +#define R_UBICOM32_FUNCDESC_GOT_LO7_S   25
5134 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_S 26
5135 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_S 27
5136 +#define R_UBICOM32_FUNCDESC_GOT_LO7_D   28
5137 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_D 29
5138 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_D 30
5139 +#define R_UBICOM32_GOT_LO7_CALLI        31
5140 +#define R_UBICOM32_FUNCDESC_GOT_LO7_CALLI 32
5141 +#define R_UBICOM32_FUNCDESC_VALUE       33
5142 +#define R_UBICOM32_FUNCDESC             34
5143 +#define R_UBICOM32_GOTOFFSET_LO         35
5144 +#define R_UBICOM32_GOTOFFSET_HI         36
5145 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_LO 37
5146 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_HI 38
5147 +#define R_UBICOM32_GNU_VTINHERIT        200
5148 +#define R_UBICOM32_GNU_VTENTRY          201
5149 +
5150 +typedef unsigned long elf_greg_t;
5151 +
5152 +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
5153 +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
5154 +
5155 +typedef struct user_ubicom32fp_struct elf_fpregset_t;
5156 +
5157 +/*
5158 + * This is used to ensure we don't load something for the wrong architecture.
5159 + */
5160 +#define elf_check_arch(x) ((x)->e_machine == EM_UBICOM32)
5161 +
5162 +#define elf_check_fdpic(x) ((x)->e_flags & EF_UBICOM32_FDPIC)
5163 +
5164 +#define elf_check_const_displacement(x) ((x)->e_flags & EF_UBICOM32_PIC)
5165 +
5166 +/*
5167 + * These are used to set parameters in the core dumps.
5168 + */
5169 +#define ELF_CLASS      ELFCLASS32
5170 +#define ELF_DATA       ELFDATA2MSB
5171 +#define ELF_ARCH       EM_UBICOM32
5172 +
5173 +/* For SVR4/m68k the function pointer to be registered with `atexit' is
5174 +   passed in %a1.  Although my copy of the ABI has no such statement, it
5175 +   is actually used on ASV.  */
5176 +#define ELF_PLAT_INIT(_r, load_addr)   _r->a1 = 0
5177 +
5178 +#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map_addr, _interp_map_addr,   \
5179 +                           _dynamic_addr)                              \
5180 +       do {                                                            \
5181 +               _regs->dn[1]    = _exec_map_addr;                       \
5182 +               _regs->dn[2]    = _interp_map_addr;                     \
5183 +               _regs->dn[3]    = _dynamic_addr;                        \
5184 +               _regs->an[1]    = 0; /* dl_fini will be set by ldso */  \
5185 +       } while (0)
5186 +
5187 +#define USE_ELF_CORE_DUMP
5188 +#define ELF_EXEC_PAGESIZE      4096
5189 +
5190 +#ifdef __KERNEL__
5191 +#ifdef CONFIG_UBICOM32_V4
5192 +#define ELF_FDPIC_CORE_EFLAGS  (EF_UBICOM32_FDPIC | EF_UBICOM32_V4)
5193 +#elif defined CONFIG_UBICOM32_V3
5194 +#define ELF_FDPIC_CORE_EFLAGS  (EF_UBICOM32_FDPIC | EF_UBICOM32_V3)
5195 +#else
5196 +#error Unknown/Unsupported ubicom32 architecture.
5197 +#endif
5198 +#endif
5199 +
5200 +/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
5201 +   use of this is to invoke "./ld.so someprog" to test out a new version of
5202 +   the loader.  We need to make sure that it is out of the way of the program
5203 +   that it will "exec", and that there is sufficient room for the brk.  */
5204 +
5205 +#define ELF_ET_DYN_BASE         0xD0000000UL
5206 +
5207 +/*
5208 + * For Ubicom32, the elf_gregset_t and struct pt_regs are the same size
5209 + * data structure so a copy is performed instead of providing the
5210 + * ELF_CORE_COPY_REGS macro.
5211 + */
5212 +
5213 +/*
5214 + * ELF_CORE_COPY_TASK_REGS is needed to dump register state from multi threaded user projects.
5215 + */
5216 +extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
5217 +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
5218 +
5219 +/* This yields a mask that user programs can use to figure out what
5220 +   instruction set this cpu supports.  */
5221 +
5222 +#define ELF_HWCAP      (0)
5223 +
5224 +/* This yields a string that ld.so will use to load implementation
5225 +   specific libraries for optimization.  This is more specific in
5226 +   intent than poking at uname or /proc/cpuinfo.  */
5227 +
5228 +#define ELF_PLATFORM  (NULL)
5229 +
5230 +#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
5231 +
5232 +#endif /* _ASM_UBICOM32_ELF_H */
5233 --- /dev/null
5234 +++ b/arch/ubicom32/include/asm/emergency-restart.h
5235 @@ -0,0 +1,33 @@
5236 +/*
5237 + * arch/ubicom32/include/asm/emergency-restart.h
5238 + *   Generic emergency-restart.h for Ubicom32 architecture.
5239 + *
5240 + * (C) Copyright 2009, Ubicom, Inc.
5241 + *
5242 + * This file is part of the Ubicom32 Linux Kernel Port.
5243 + *
5244 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5245 + * it and/or modify it under the terms of the GNU General Public License
5246 + * as published by the Free Software Foundation, either version 2 of the
5247 + * License, or (at your option) any later version.
5248 + *
5249 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5250 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5251 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5252 + * the GNU General Public License for more details.
5253 + *
5254 + * You should have received a copy of the GNU General Public License
5255 + * along with the Ubicom32 Linux Kernel Port.  If not,
5256 + * see <http://www.gnu.org/licenses/>.
5257 + *
5258 + * Ubicom32 implementation derived from (with many thanks):
5259 + *   arch/m68knommu
5260 + *   arch/blackfin
5261 + *   arch/parisc
5262 + */
5263 +#ifndef _ASM_UBICOM32_EMERGENCY_RESTART_H
5264 +#define _ASM_UBICOM32_EMERGENCY_RESTART_H
5265 +
5266 +#include <asm-generic/emergency-restart.h>
5267 +
5268 +#endif /* _ASM_UBICOM32_EMERGENCY_RESTART_H */
5269 --- /dev/null
5270 +++ b/arch/ubicom32/include/asm/entry.h
5271 @@ -0,0 +1,34 @@
5272 +/*
5273 + * arch/ubicom32/include/asm/entry.h
5274 + *   Entry register/stack definitions for Ubicom32 architecture.
5275 + *
5276 + * (C) Copyright 2009, Ubicom, Inc.
5277 + *
5278 + * This file is part of the Ubicom32 Linux Kernel Port.
5279 + *
5280 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5281 + * it and/or modify it under the terms of the GNU General Public License
5282 + * as published by the Free Software Foundation, either version 2 of the
5283 + * License, or (at your option) any later version.
5284 + *
5285 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5286 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5287 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5288 + * the GNU General Public License for more details.
5289 + *
5290 + * You should have received a copy of the GNU General Public License
5291 + * along with the Ubicom32 Linux Kernel Port.  If not,
5292 + * see <http://www.gnu.org/licenses/>.
5293 + *
5294 + * Ubicom32 implementation derived from (with many thanks):
5295 + *   arch/m68knommu
5296 + *   arch/blackfin
5297 + *   arch/parisc
5298 + */
5299 +#ifndef _ASM_UBICOM32_ENTRY_H
5300 +#define _ASM_UBICOM32_ENTRY_H
5301 +
5302 +#include <asm/setup.h>
5303 +#include <asm/page.h>
5304 +
5305 +#endif /* _ASM_UBICOM32_ENTRY_H */
5306 --- /dev/null
5307 +++ b/arch/ubicom32/include/asm/errno.h
5308 @@ -0,0 +1,33 @@
5309 +/*
5310 + * arch/ubicom32/include/asm/errno.h
5311 + *   Generic errno.h for Ubicom32 architecture.
5312 + *
5313 + * (C) Copyright 2009, Ubicom, Inc.
5314 + *
5315 + * This file is part of the Ubicom32 Linux Kernel Port.
5316 + *
5317 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5318 + * it and/or modify it under the terms of the GNU General Public License
5319 + * as published by the Free Software Foundation, either version 2 of the
5320 + * License, or (at your option) any later version.
5321 + *
5322 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5323 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5324 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5325 + * the GNU General Public License for more details.
5326 + *
5327 + * You should have received a copy of the GNU General Public License
5328 + * along with the Ubicom32 Linux Kernel Port.  If not,
5329 + * see <http://www.gnu.org/licenses/>.
5330 + *
5331 + * Ubicom32 implementation derived from (with many thanks):
5332 + *   arch/m68knommu
5333 + *   arch/blackfin
5334 + *   arch/parisc
5335 + */
5336 +#ifndef _ASM_UBICOM32_ERRNO_H
5337 +#define _ASM_UBICOM32_ERRNO_H
5338 +
5339 +#include <asm-generic/errno.h>
5340 +
5341 +#endif /* _ASM_UBICOM32_ERRNO_H */
5342 --- /dev/null
5343 +++ b/arch/ubicom32/include/asm/fb.h
5344 @@ -0,0 +1,39 @@
5345 +/*
5346 + * arch/ubicom32/include/asm/fb.h
5347 + *   Definition of fb_is_primary_device() for Ubicom32 architecture.
5348 + *
5349 + * (C) Copyright 2009, Ubicom, Inc.
5350 + *
5351 + * This file is part of the Ubicom32 Linux Kernel Port.
5352 + *
5353 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5354 + * it and/or modify it under the terms of the GNU General Public License
5355 + * as published by the Free Software Foundation, either version 2 of the
5356 + * License, or (at your option) any later version.
5357 + *
5358 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5359 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5360 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5361 + * the GNU General Public License for more details.
5362 + *
5363 + * You should have received a copy of the GNU General Public License
5364 + * along with the Ubicom32 Linux Kernel Port.  If not,
5365 + * see <http://www.gnu.org/licenses/>.
5366 + *
5367 + * Ubicom32 implementation derived from (with many thanks):
5368 + *   arch/m68knommu
5369 + *   arch/blackfin
5370 + *   arch/parisc
5371 + */
5372 +#ifndef _ASM_UBICOM32_FB_H
5373 +#define _ASM_UBICOM32_FB_H
5374 +#include <linux/fb.h>
5375 +
5376 +#define fb_pgprotect(...) do {} while (0)
5377 +
5378 +static inline int fb_is_primary_device(struct fb_info *info)
5379 +{
5380 +       return 0;
5381 +}
5382 +
5383 +#endif /* _ASM_UBICOM32_FB_H */
5384 --- /dev/null
5385 +++ b/arch/ubicom32/include/asm/fcntl.h
5386 @@ -0,0 +1,38 @@
5387 +/*
5388 + * arch/ubicom32/include/asm/fcntl.h
5389 + *   File control bit definitions for Ubicom32 architecture.
5390 + *
5391 + * (C) Copyright 2009, Ubicom, Inc.
5392 + *
5393 + * This file is part of the Ubicom32 Linux Kernel Port.
5394 + *
5395 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5396 + * it and/or modify it under the terms of the GNU General Public License
5397 + * as published by the Free Software Foundation, either version 2 of the
5398 + * License, or (at your option) any later version.
5399 + *
5400 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5401 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5402 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5403 + * the GNU General Public License for more details.
5404 + *
5405 + * You should have received a copy of the GNU General Public License
5406 + * along with the Ubicom32 Linux Kernel Port.  If not,
5407 + * see <http://www.gnu.org/licenses/>.
5408 + *
5409 + * Ubicom32 implementation derived from (with many thanks):
5410 + *   arch/m68knommu
5411 + *   arch/blackfin
5412 + *   arch/parisc
5413 + */
5414 +#ifndef _ASM_UBICOM32_FCNTL_H
5415 +#define _ASM_UBICOM32_FCNTL_H
5416 +
5417 +#define O_DIRECTORY    040000  /* must be a directory */
5418 +#define O_NOFOLLOW     0100000 /* don't follow links */
5419 +#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
5420 +#define O_LARGEFILE    0400000
5421 +
5422 +#include <asm-generic/fcntl.h>
5423 +
5424 +#endif /* _ASM_UBICOM32_FCNTL_H */
5425 --- /dev/null
5426 +++ b/arch/ubicom32/include/asm/flat.h
5427 @@ -0,0 +1,73 @@
5428 +/*
5429 + * arch/ubicom32/include/asm/flat.h
5430 + *   Definitions to support flat-format executables.
5431 + *
5432 + * (C) Copyright 2009, Ubicom, Inc.
5433 + *
5434 + * This file is part of the Ubicom32 Linux Kernel Port.
5435 + *
5436 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5437 + * it and/or modify it under the terms of the GNU General Public License
5438 + * as published by the Free Software Foundation, either version 2 of the
5439 + * License, or (at your option) any later version.
5440 + *
5441 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5442 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5443 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5444 + * the GNU General Public License for more details.
5445 + *
5446 + * You should have received a copy of the GNU General Public License
5447 + * along with the Ubicom32 Linux Kernel Port.  If not,
5448 + * see <http://www.gnu.org/licenses/>.
5449 + *
5450 + * Ubicom32 implementation derived from (with many thanks):
5451 + *   arch/m68knommu
5452 + *   arch/blackfin
5453 + *   arch/parisc
5454 + */
5455 +
5456 +#ifndef _ASM_UBICOM32_FLAT_H
5457 +#define _ASM_UBICOM32_FLAT_H
5458 +
5459 +#define ARCH_FLAT_ALIGN 0x80
5460 +#define ARCH_FLAT_ALIGN_TEXT 1
5461 +
5462 +#define  R_UBICOM32_32         2
5463 +#define  R_UBICOM32_HI24       7
5464 +#define  R_UBICOM32_LO7_S      8
5465 +#define  R_UBICOM32_LO7_2_S    9
5466 +#define  R_UBICOM32_LO7_4_S    10
5467 +#define  R_UBICOM32_LO7_D      11
5468 +#define  R_UBICOM32_LO7_2_D    12
5469 +#define  R_UBICOM32_LO7_4_D    13
5470 +#define  R_UBICOM32_LO7_CALLI  15
5471 +#define  R_UBICOM32_LO16_CALLI 16
5472 +
5473 +extern void ubicom32_flat_put_addr_at_rp(unsigned long *rp, u32_t val, u32_t rval, unsigned long  *p);
5474 +extern unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp, u32_t relval, u32_t flags, unsigned long *p);
5475 +
5476 +#define        flat_stack_align(sp)                    /* nothing needed */
5477 +#define        flat_argvp_envp_on_stack()              1
5478 +#define        flat_old_ram_flag(flags)                (flags)
5479 +#define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
5480 +#define        flat_get_addr_from_rp(rp, relval, flags, p)     (ubicom32_flat_get_addr_from_rp(rp, relval,flags, p))
5481 +#define        flat_put_addr_at_rp(rp, val, relval)    do {ubicom32_flat_put_addr_at_rp(rp, val, relval, &persistent);} while(0)
5482 +#define        flat_get_relocate_addr(rel)             ((persistent) ? (persistent & 0x07ffffff) : (rel & 0x07ffffff))
5483 +
5484 +static inline int flat_set_persistent(unsigned int relval, unsigned long *p)
5485 +{
5486 +       if (*p) {
5487 +               return 0;
5488 +       } else {
5489 +               if ((relval >> 27) != R_UBICOM32_32) {
5490 +                       /*
5491 +                        * Something other than UBICOM32_32. The next entry has the relocation.
5492 +                        */
5493 +                       *p = relval;
5494 +                       return 1;
5495 +               }
5496 +       }
5497 +       return 0;
5498 +}
5499 +
5500 +#endif /* _ASM_UBICOM32_FLAT_H */
5501 --- /dev/null
5502 +++ b/arch/ubicom32/include/asm/fpu.h
5503 @@ -0,0 +1,37 @@
5504 +/*
5505 + * arch/ubicom32/include/asm/fpu.h
5506 + *   Floating point state definitions for Ubicom32 architecture.
5507 + *
5508 + * (C) Copyright 2009, Ubicom, Inc.
5509 + *
5510 + * This file is part of the Ubicom32 Linux Kernel Port.
5511 + *
5512 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5513 + * it and/or modify it under the terms of the GNU General Public License
5514 + * as published by the Free Software Foundation, either version 2 of the
5515 + * License, or (at your option) any later version.
5516 + *
5517 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5518 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5519 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5520 + * the GNU General Public License for more details.
5521 + *
5522 + * You should have received a copy of the GNU General Public License
5523 + * along with the Ubicom32 Linux Kernel Port.  If not,
5524 + * see <http://www.gnu.org/licenses/>.
5525 + *
5526 + * Ubicom32 implementation derived from (with many thanks):
5527 + *   arch/m68knommu
5528 + *   arch/blackfin
5529 + *   arch/parisc
5530 + */
5531 +#ifndef _ASM_UBICOM32_FPU_H
5532 +#define _ASM_UBICOM32_FPU_H
5533 +
5534 +/*
5535 + * MAX floating point unit state size (FSAVE/FRESTORE)
5536 + */
5537 +/* No FP unit present then... */
5538 +#define FPSTATESIZE (2) /* dummy size */
5539 +
5540 +#endif /* _ASM_UBICOM32_FPU_H */
5541 --- /dev/null
5542 +++ b/arch/ubicom32/include/asm/ftrace.h
5543 @@ -0,0 +1 @@
5544 +/* empty */
5545 --- /dev/null
5546 +++ b/arch/ubicom32/include/asm/futex.h
5547 @@ -0,0 +1,33 @@
5548 +/*
5549 + * arch/ubicom32/include/asm/futex.h
5550 + *   Generic futex.h 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_FUTEX_H
5576 +#define _ASM_UBICOM32_FUTEX_H
5577 +
5578 +#include <asm-generic/futex.h>
5579 +
5580 +#endif /* _ASM_UBICOM32_FUTEX_H */
5581 --- /dev/null
5582 +++ b/arch/ubicom32/include/asm/.gitignore
5583 @@ -0,0 +1 @@
5584 +/ocm_size.h
5585 --- /dev/null
5586 +++ b/arch/ubicom32/include/asm/gpio.h
5587 @@ -0,0 +1,453 @@
5588 +/*
5589 + * arch/ubicom32/include/asm/gpio.h
5590 + *   Definitions for GPIO operations on Ubicom32 architecture.
5591 + *
5592 + * (C) Copyright 2009, Ubicom, Inc.
5593 + *
5594 + * This file is part of the Ubicom32 Linux Kernel Port.
5595 + *
5596 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5597 + * it and/or modify it under the terms of the GNU General Public License
5598 + * as published by the Free Software Foundation, either version 2 of the
5599 + * License, or (at your option) any later version.
5600 + *
5601 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5602 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5603 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
5604 + * the GNU General Public License for more details.
5605 + *
5606 + * You should have received a copy of the GNU General Public License
5607 + * along with the Ubicom32 Linux Kernel Port.  If not,
5608 + * see <http://www.gnu.org/licenses/>.
5609 + *
5610 + * Ubicom32 implementation derived from (with many thanks):
5611 + *   arch/m68knommu
5612 + *   arch/blackfin
5613 + *   arch/parisc
5614 + */
5615 +#ifndef _ASM_UBICOM32_GPIO_H
5616 +#define _ASM_UBICOM32_GPIO_H
5617 +
5618 +#include <linux/compiler.h>
5619 +#include <asm/irq.h>
5620 +
5621 +#include <asm/ip5000.h>
5622 +
5623 +#define ARCH_NR_GPIOS           512
5624 +#define MAX_UBICOM_ONCHIP_GPIO   (9 * 32)
5625 +
5626 +/*
5627 + * Macros for manipulating GPIO numbers
5628 + */
5629 +#define gpio_bit(gn)                   (1 << (gn & 0x1f))
5630 +#define gpio_bank(gn)                  (gn >> 5)
5631 +
5632 +#define gpio_pin_index(gn)             (gn & 0x1f)
5633 +#define gpio_port_index(gn)            (gn >> 5)
5634 +
5635 +#define GPIO_RA_0    ((32 * 0) + 0)
5636 +#define GPIO_RA_1    ((32 * 0) + 1)
5637 +#define GPIO_RA_2    ((32 * 0) + 2)
5638 +#define GPIO_RA_3    ((32 * 0) + 3)
5639 +#define GPIO_RA_4    ((32 * 0) + 4)
5640 +#define GPIO_RA_5    ((32 * 0) + 5)
5641 +#define GPIO_RA_6    ((32 * 0) + 6)
5642 +#define GPIO_RA_7    ((32 * 0) + 7)
5643 +
5644 +#define GPIO_RB_0    ((32 * 1) + 0)
5645 +#define GPIO_RB_1    ((32 * 1) + 1)
5646 +#define GPIO_RB_2    ((32 * 1) + 2)
5647 +#define GPIO_RB_3    ((32 * 1) + 3)
5648 +#define GPIO_RB_4    ((32 * 1) + 4)
5649 +#define GPIO_RB_5    ((32 * 1) + 5)
5650 +#define GPIO_RB_6    ((32 * 1) + 6)
5651 +#define GPIO_RB_7    ((32 * 1) + 7)
5652 +#define GPIO_RB_8    ((32 * 1) + 8)
5653 +#define GPIO_RB_9    ((32 * 1) + 9)
5654 +#define GPIO_RB_10   ((32 * 1) + 10)
5655 +#define GPIO_RB_11   ((32 * 1) + 11)
5656 +#define GPIO_RB_12   ((32 * 1) + 12)
5657 +#define GPIO_RB_13   ((32 * 1) + 13)
5658 +#define GPIO_RB_14   ((32 * 1) + 14)
5659 +#define GPIO_RB_15   ((32 * 1) + 15)
5660 +#define GPIO_RB_16   ((32 * 1) + 16)
5661 +#define GPIO_RB_17   ((32 * 1) + 17)
5662 +#define GPIO_RB_18   ((32 * 1) + 18)
5663 +#define GPIO_RB_19   ((32 * 1) + 19)
5664 +
5665 +#define GPIO_RC_0    ((32 * 2) + 0)
5666 +#define GPIO_RC_1    ((32 * 2) + 1)
5667 +#define GPIO_RC_2    ((32 * 2) + 2)
5668 +#define GPIO_RC_3    ((32 * 2) + 3)
5669 +#define GPIO_RC_4    ((32 * 2) + 4)
5670 +#define GPIO_RC_5    ((32 * 2) + 5)
5671 +#define GPIO_RC_6    ((32 * 2) + 6)
5672 +#define GPIO_RC_7    ((32 * 2) + 7)
5673 +#define GPIO_RC_8    ((32 * 2) + 8)
5674 +#define GPIO_RC_9    ((32 * 2) + 9)
5675 +#define GPIO_RC_10   ((32 * 2) + 10)
5676 +#define GPIO_RC_11   ((32 * 2) + 11)
5677 +#define GPIO_RC_12   ((32 * 2) + 12)
5678 +#define GPIO_RC_13   ((32 * 2) + 13)
5679 +#define GPIO_RC_14   ((32 * 2) + 14)
5680 +#define GPIO_RC_15   ((32 * 2) + 15)
5681 +#define GPIO_RC_16   ((32 * 2) + 16)
5682 +#define GPIO_RC_17   ((32 * 2) + 17)
5683 +#define GPIO_RC_18   ((32 * 2) + 18)
5684 +#define GPIO_RC_19   ((32 * 2) + 19)
5685 +#define GPIO_RC_20   ((32 * 2) + 20)
5686 +#define GPIO_RC_21   ((32 * 2) + 21)
5687 +#define GPIO_RC_22   ((32 * 2) + 22)
5688 +#define GPIO_RC_23   ((32 * 2) + 23)
5689 +#define GPIO_RC_24   ((32 * 2) + 24)
5690 +#define GPIO_RC_25   ((32 * 2) + 25)
5691 +#define GPIO_RC_26   ((32 * 2) + 26)
5692 +#define GPIO_RC_27   ((32 * 2) + 27)
5693 +#define GPIO_RC_28   ((32 * 2) + 28)
5694 +#define GPIO_RC_29   ((32 * 2) + 29)
5695 +#define GPIO_RC_30   ((32 * 2) + 30)
5696 +#define GPIO_RC_31   ((32 * 2) + 31)
5697 +
5698 +#define GPIO_RD_0    ((32 * 3) + 0)
5699 +#define GPIO_RD_1    ((32 * 3) + 1)
5700 +#define GPIO_RD_2    ((32 * 3) + 2)
5701 +#define GPIO_RD_3    ((32 * 3) + 3)
5702 +#define GPIO_RD_4    ((32 * 3) + 4)
5703 +#define GPIO_RD_5    ((32 * 3) + 5)
5704 +#define GPIO_RD_6    ((32 * 3) + 6)
5705 +#define GPIO_RD_7    ((32 * 3) + 7)
5706 +#define GPIO_RD_8    ((32 * 3) + 8)
5707 +#define GPIO_RD_9    ((32 * 3) + 9)
5708 +#define GPIO_RD_10   ((32 * 3) + 10)
5709 +#define GPIO_RD_11   ((32 * 3) + 11)
5710 +
5711 +#define GPIO_RE_0    ((32 * 4) + 0)
5712 +#define GPIO_RE_1    ((32 * 4) + 1)
5713 +#define GPIO_RE_2    ((32 * 4) + 2)
5714 +#define GPIO_RE_3    ((32 * 4) + 3)
5715 +#define GPIO_RE_4    ((32 * 4) + 4)
5716 +#define GPIO_RE_5    ((32 * 4) + 5)
5717 +#define GPIO_RE_6    ((32 * 4) + 6)
5718 +#define GPIO_RE_7    ((32 * 4) + 7)
5719 +
5720 +#define GPIO_RF_0    ((32 * 5) + 0)
5721 +#define GPIO_RF_1    ((32 * 5) + 1)
5722 +#define GPIO_RF_2    ((32 * 5) + 2)
5723 +#define GPIO_RF_3    ((32 * 5) + 3)
5724 +#define GPIO_RF_4    ((32 * 5) + 4)
5725 +#define GPIO_RF_5    ((32 * 5) + 5)
5726 +#define GPIO_RF_6    ((32 * 5) + 6)
5727 +#define GPIO_RF_7    ((32 * 5) + 7)
5728 +#define GPIO_RF_8    ((32 * 5) + 8)
5729 +#define GPIO_RF_9    ((32 * 5) + 9)
5730 +#define GPIO_RF_10   ((32 * 5) + 10)
5731 +#define GPIO_RF_11   ((32 * 5) + 11)
5732 +#define GPIO_RF_12   ((32 * 5) + 12)
5733 +#define GPIO_RF_13   ((32 * 5) + 13)
5734 +#define GPIO_RF_14   ((32 * 5) + 14)
5735 +#define GPIO_RF_15   ((32 * 5) + 15)
5736 +
5737 +#define GPIO_RG_0    ((32 * 6) + 0)
5738 +#define GPIO_RG_1    ((32 * 6) + 1)
5739 +#define GPIO_RG_2    ((32 * 6) + 2)
5740 +#define GPIO_RG_3    ((32 * 6) + 3)
5741 +#define GPIO_RG_4    ((32 * 6) + 4)
5742 +#define GPIO_RG_5    ((32 * 6) + 5)
5743 +#define GPIO_RG_6    ((32 * 6) + 6)
5744 +#define GPIO_RG_7    ((32 * 6) + 7)
5745 +#define GPIO_RG_8    ((32 * 6) + 8)
5746 +#define GPIO_RG_9    ((32 * 6) + 9)
5747 +#define GPIO_RG_10   ((32 * 6) + 10)
5748 +#define GPIO_RG_11   ((32 * 6) + 11)
5749 +#define GPIO_RG_12   ((32 * 6) + 12)
5750 +#define GPIO_RG_13   ((32 * 6) + 13)
5751 +#define GPIO_RG_14   ((32 * 6) + 14)
5752 +#define GPIO_RG_15   ((32 * 6) + 15)
5753 +#define GPIO_RG_16   ((32 * 6) + 16)
5754 +#define GPIO_RG_17   ((32 * 6) + 17)
5755 +#define GPIO_RG_18   ((32 * 6) + 18)
5756 +#define GPIO_RG_19   ((32 * 6) + 19)
5757 +#define GPIO_RG_20   ((32 * 6) + 20)
5758 +#define GPIO_RG_21   ((32 * 6) + 21)
5759 +#define GPIO_RG_22   ((32 * 6) + 22)
5760 +#define GPIO_RG_23   ((32 * 6) + 23)
5761 +#define GPIO_RG_24   ((32 * 6) + 24)
5762 +#define GPIO_RG_25   ((32 * 6) + 25)
5763 +#define GPIO_RG_26   ((32 * 6) + 26)
5764 +#define GPIO_RG_27   ((32 * 6) + 27)
5765 +#define GPIO_RG_28   ((32 * 6) + 28)
5766 +#define GPIO_RG_29   ((32 * 6) + 29)
5767 +#define GPIO_RG_30   ((32 * 6) + 30)
5768 +#define GPIO_RG_31   ((32 * 6) + 31)
5769 +
5770 +#define GPIO_RH_0    ((32 * 7) + 0)
5771 +#define GPIO_RH_1    ((32 * 7) + 1)
5772 +#define GPIO_RH_2    ((32 * 7) + 2)
5773 +#define GPIO_RH_3    ((32 * 7) + 3)
5774 +#define GPIO_RH_4    ((32 * 7) + 4)
5775 +#define GPIO_RH_5    ((32 * 7) + 5)
5776 +#define GPIO_RH_6    ((32 * 7) + 6)
5777 +#define GPIO_RH_7    ((32 * 7) + 7)
5778 +#define GPIO_RH_8    ((32 * 7) + 8)
5779 +#define GPIO_RH_9    ((32 * 7) + 9)
5780 +
5781 +#define GPIO_RI_0    ((32 * 8) + 0)
5782 +#define GPIO_RI_1    ((32 * 8) + 1)
5783 +#define GPIO_RI_2    ((32 * 8) + 2)
5784 +#define GPIO_RI_3    ((32 * 8) + 3)
5785 +#define GPIO_RI_4    ((32 * 8) + 4)
5786 +#define GPIO_RI_5    ((32 * 8) + 5)
5787 +#define GPIO_RI_6    ((32 * 8) + 6)
5788 +#define GPIO_RI_7    ((32 * 8) + 7)
5789 +#define GPIO_RI_8    ((32 * 8) + 8)
5790 +#define GPIO_RI_9    ((32 * 8) + 9)
5791 +#define GPIO_RI_10   ((32 * 8) + 10)
5792 +#define GPIO_RI_11   ((32 * 8) + 11)
5793 +#define GPIO_RI_12   ((32 * 8) + 12)
5794 +#define GPIO_RI_13   ((32 * 8) + 13)
5795 +#define GPIO_RI_14   ((32 * 8) + 14)
5796 +#define GPIO_RI_15   ((32 * 8) + 15)
5797 +
5798 +/*
5799 + * The following section defines extra GPIO available to some boards.
5800 + * These GPIO are generally external to the processor (i.e. SPI/I2C
5801 + * expander chips).
5802 + *
5803 + * Note that these defines show all possible GPIO available, however,
5804 + * depending on the actual board configuration, some GPIO are not
5805 + * available for use.
5806 + */
5807 +#ifdef CONFIG_IP7500MEDIA
5808 +/*
5809 + * U15
5810 + */
5811 +#define IP7500MEDIA_U15_BASE   (32 * 10)
5812 +#define IP7500MEDIA_IO0                (IP7500MEDIA_U15_BASE + 0)
5813 +#define IP7500MEDIA_IO1                (IP7500MEDIA_U15_BASE + 1)
5814 +#define IP7500MEDIA_IO2                (IP7500MEDIA_U15_BASE + 2)
5815 +#define IP7500MEDIA_IO3                (IP7500MEDIA_U15_BASE + 3)
5816 +#define IP7500MEDIA_IO4                (IP7500MEDIA_U15_BASE + 4)
5817 +#define IP7500MEDIA_IO5                (IP7500MEDIA_U15_BASE + 5)
5818 +#define IP7500MEDIA_IO6                (IP7500MEDIA_U15_BASE + 6)
5819 +#define IP7500MEDIA_IO7                (IP7500MEDIA_U15_BASE + 7)
5820 +
5821 +/*
5822 + * U16
5823 + */
5824 +#define IP7500MEDIA_U16_BASE   (32 * 11)
5825 +#define IP7500MEDIA_IO8                (IP7500MEDIA_U16_BASE + 0)
5826 +#define IP7500MEDIA_IO9                (IP7500MEDIA_U16_BASE + 1)
5827 +#define IP7500MEDIA_IO10       (IP7500MEDIA_U16_BASE + 2)
5828 +#define IP7500MEDIA_IO11       (IP7500MEDIA_U16_BASE + 3)
5829 +#define IP7500MEDIA_IO12       (IP7500MEDIA_U16_BASE + 4)
5830 +#define IP7500MEDIA_IO13       (IP7500MEDIA_U16_BASE + 5)
5831 +#define IP7500MEDIA_IO14       (IP7500MEDIA_U16_BASE + 6)
5832 +#define IP7500MEDIA_IO15       (IP7500MEDIA_U16_BASE + 7)
5833 +
5834 +/*
5835 + * U17
5836 + */
5837 +#define IP7500MEDIA_U17_BASE   (32 * 12)
5838 +#define IP7500MEDIA_IO16       (IP7500MEDIA_U17_BASE + 0)
5839 +#define IP7500MEDIA_IO17       (IP7500MEDIA_U17_BASE + 1)
5840 +#define IP7500MEDIA_IO18       (IP7500MEDIA_U17_BASE + 2)
5841 +#define IP7500MEDIA_IO19       (IP7500MEDIA_U17_BASE + 3)
5842 +#define IP7500MEDIA_IO20       (IP7500MEDIA_U17_BASE + 4)
5843 +#define IP7500MEDIA_IO21       (IP7500MEDIA_U17_BASE + 5)
5844 +#define IP7500MEDIA_IO22       (IP7500MEDIA_U17_BASE + 6)
5845 +#define IP7500MEDIA_IO23       (IP7500MEDIA_U17_BASE + 7)
5846 +
5847 +/*
5848 + * U18
5849 + */
5850 +#define IP7500MEDIA_U18_BASE   (32 * 13)
5851 +#define IP7500MEDIA_IO24       (IP7500MEDIA_U18_BASE + 0)
5852 +#define IP7500MEDIA_IO25       (IP7500MEDIA_U18_BASE + 1)
5853 +#define IP7500MEDIA_IO26       (IP7500MEDIA_U18_BASE + 2)
5854 +#define IP7500MEDIA_IO27       (IP7500MEDIA_U18_BASE + 3)
5855 +#define IP7500MEDIA_IO28       (IP7500MEDIA_U18_BASE + 4)
5856 +#define IP7500MEDIA_IO29       (IP7500MEDIA_U18_BASE + 5)
5857 +#define IP7500MEDIA_IO30       (IP7500MEDIA_U18_BASE + 6)
5858 +#define IP7500MEDIA_IO31       (IP7500MEDIA_U18_BASE + 7)
5859 +#endif
5860 +
5861 +#ifdef CONFIG_IP7145DPF
5862 +/*
5863 + * U48
5864 + */
5865 +#define IP7145DPF_U48_BASE     (32 * 10)
5866 +#define IP7145DPF_IO0          (IP7145DPF_U48_BASE + 0)
5867 +#define IP7145DPF_IO1          (IP7145DPF_U48_BASE + 1)
5868 +#define IP7145DPF_IO2          (IP7145DPF_U48_BASE + 2)
5869 +#define IP7145DPF_IO3          (IP7145DPF_U48_BASE + 3)
5870 +#define IP7145DPF_IO4          (IP7145DPF_U48_BASE + 4)
5871 +#define IP7145DPF_IO5          (IP7145DPF_U48_BASE + 5)
5872 +#define IP7145DPF_IO6          (IP7145DPF_U48_BASE + 6)
5873 +#define IP7145DPF_IO7          (IP7145DPF_U48_BASE + 7)
5874 +
5875 +/*
5876 + * U72
5877 + */
5878 +#define IP7145DPF_U72_BASE     (32 * 11)
5879 +#define IP7145DPF_IOB0         (IP7145DPF_U72_BASE + 0)
5880 +#define IP7145DPF_IOB1         (IP7145DPF_U72_BASE + 1)
5881 +#define IP7145DPF_IOB2         (IP7145DPF_U72_BASE + 2)
5882 +#define IP7145DPF_IOB3         (IP7145DPF_U72_BASE + 3)
5883 +#define IP7145DPF_IOB4         (IP7145DPF_U72_BASE + 4)
5884 +#define IP7145DPF_IOB5         (IP7145DPF_U72_BASE + 5)
5885 +#define IP7145DPF_IOB6         (IP7145DPF_U72_BASE + 6)
5886 +#define IP7145DPF_IOB7         (IP7145DPF_U72_BASE + 7)
5887 +#endif
5888 +
5889 +#include <asm-generic/gpio.h>
5890 +
5891 +/*
5892 + * The following macros bypass gpiolib to generate direct references
5893 + * to the port registers.  These assume, minimally, that either
5894 + * gpio_direction_input() or gpio_direction_output() have already been
5895 + * called to setup the pin direction and to enable the pin function to
5896 + * be gpio.  These macros generate the hardware port address based on
5897 + * the assumption that all ports are 32 bits wide (even though we know
5898 + * they are not).  This is so we can efficiently turn pin numbers into
5899 + * port addresses without a lookup.
5900 + *
5901 + * These operations must be done in one instruction to prevent clobbering
5902 + * other thread's accesses to the same port.
5903 + */
5904 +#define UBICOM32_GPIO_ENABLE(pin)                              \
5905 +       do {                                                    \
5906 +               asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t"                                          \
5907 +                               :                                                                               \
5908 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask),  \
5909 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5910 +                               : "cc", "memory"                                                                \
5911 +               );                                                                                              \
5912 +       } while (0);
5913 +
5914 +#define UBICOM32_GPIO_DISABLE(pin)                             \
5915 +       do {                                                    \
5916 +               asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5917 +                               :                                                                               \
5918 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask),  \
5919 +                                 [mask] "d" (~gpio_bit(pin))                                                   \
5920 +                               : "cc", "memory"                                                                \
5921 +               );                                                                                              \
5922 +       } while (0);
5923 +
5924 +#define UBICOM32_GPIO_SET_PIN_INPUT(pin)                       \
5925 +       do {                                                    \
5926 +               asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5927 +                               :                                                                               \
5928 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl),   \
5929 +                                 [mask] "d" (~gpio_bit(pin))                                                   \
5930 +                               : "cc", "memory"                                                                \
5931 +               );                                                                                              \
5932 +       } while (0);
5933 +
5934 +#define UBICOM32_GPIO_SET_PIN_OUTPUT(pin)                      \
5935 +       do {                                                    \
5936 +               asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t"                                          \
5937 +                               :                                                                               \
5938 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl),   \
5939 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5940 +                               : "cc", "memory"                                                                \
5941 +               );                                                                                              \
5942 +       } while (0);
5943 +
5944 +#define UBICOM32_GPIO_SET_PIN_TOGGLE(pin)                      \
5945 +       do {                                                    \
5946 +               asm volatile ("xor.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5947 +                               :                                                                               \
5948 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out),   \
5949 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5950 +                               : "cc", "memory"                                                                \
5951 +               );                                                                                              \
5952 +       } while (0);
5953 +
5954 +#define UBICOM32_GPIO_SET_PIN_HIGH(pin)                                \
5955 +       do {                                                    \
5956 +               asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t"                                          \
5957 +                               :                                                                               \
5958 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out),   \
5959 +                                 [mask] "d" (gpio_bit(pin))                                                    \
5960 +                               : "cc", "memory"                                                                \
5961 +               );                                                                                              \
5962 +       } while (0);
5963 +
5964 +#define UBICOM32_GPIO_SET_PIN_LOW(pin)                         \
5965 +       do {                                                    \
5966 +               asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t"                                         \
5967 +                               :                                                                               \
5968 +                               : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out),   \
5969 +                                 [mask] "d" (~gpio_bit(pin))                                                   \
5970 +                               : "cc", "memory"                                                                \
5971 +               );                                                                                              \
5972 +       } while (0);
5973 +
5974 +#define UBICOM32_GPIO_SET_PIN(pin, val) \
5975 +  if ( val ) {                          \
5976 +    UBICOM32_GPIO_SET_PIN_HIGH(pin);    \
5977 +  } else {                              \
5978 +    UBICOM32_GPIO_SET_PIN_LOW(pin);    \
5979 +  }
5980 +
5981 +#define UBICOM32_GPIO_GET_PIN(pin)                                    \
5982 +  (0 != (UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_in  \
5983 +        & gpio_bit(pin)))
5984 +
5985 +
5986 +static inline int gpio_get_value(unsigned gpio)
5987 +{
5988 +  if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
5989 +    return UBICOM32_GPIO_GET_PIN(gpio);
5990 +  else
5991 +    return __gpio_get_value(gpio);
5992 +}
5993 +
5994 +static inline void gpio_set_value(unsigned gpio, int value)
5995 +{
5996 +  if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
5997 +    {
5998 +      UBICOM32_GPIO_SET_PIN(gpio, value);
5999 +    }
6000 +  else
6001 +    {
6002 +      __gpio_set_value(gpio, value);
6003 +    }
6004 +}
6005 +
6006 +static inline int gpio_cansleep(unsigned gpio)
6007 +{
6008 +  return __gpio_cansleep(gpio);
6009 +}
6010 +
6011 +static inline int gpio_to_irq(unsigned gpio)
6012 +{
6013 +#if defined(IP5000) || defined(IP5000_REV2)
6014 +  if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6015 +    return 25;
6016 +  else
6017 +    return -ENXIO;
6018 +
6019 +#elif defined(IP7000) || defined(IP7000_REV2)
6020 +  if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6021 +    return 44 + (gpio - GPIO_RA_4);
6022 +  else
6023 +    return -ENXIO;
6024 +
6025 +#else
6026 +    return -ENXIO;
6027 +
6028 +#endif
6029 +}
6030 +
6031 +static inline int irq_to_gpio(unsigned gpio)
6032 +{
6033 +       return -ENXIO;
6034 +}
6035 +
6036 +extern struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio);
6037 +
6038 +extern int __init ubi_gpio_init(void);
6039 +
6040 +#endif /* _ASM_UBICOM32_GPIO_H */
6041 --- /dev/null
6042 +++ b/arch/ubicom32/include/asm/hardirq.h
6043 @@ -0,0 +1,55 @@
6044 +/*
6045 + * arch/ubicom32/include/asm/hardirq.h
6046 + *   Definition of ack_bad_irq() for Ubicom32 architecture.
6047 + *
6048 + * (C) Copyright 2009, Ubicom, Inc.
6049 + * Copyright (C) 1997, 98, 99, 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
6050 + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
6051 + * Copyright (C) 2001 MIPS Technologies, Inc.
6052 + *
6053 + * This file is part of the Ubicom32 Linux Kernel Port.
6054 + *
6055 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6056 + * it and/or modify it under the terms of the GNU General Public License
6057 + * as published by the Free Software Foundation, either version 2 of the
6058 + * License, or (at your option) any later version.
6059 + *
6060 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6061 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6062 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6063 + * the GNU General Public License for more details.
6064 + *
6065 + * You should have received a copy of the GNU General Public License
6066 + * along with the Ubicom32 Linux Kernel Port.  If not,
6067 + * see <http://www.gnu.org/licenses/>.
6068 + *
6069 + * Ubicom32 implementation derived from (with many thanks):
6070 + *   arch/m68knommu
6071 + *   arch/blackfin
6072 + *   arch/parisc
6073 + */
6074 +#ifndef _ASM_UBICOM32_HARDIRQ_H
6075 +#define _ASM_UBICOM32_HARDIRQ_H
6076 +
6077 +#include <linux/threads.h>
6078 +#include <linux/irq.h>
6079 +
6080 +/*
6081 + * The hardirq mask has to be large enough to have space
6082 + * for potentially all IRQ sources in the system nesting
6083 + * on a single CPU.  For Ubicom32, we have 64 IRQ sources.
6084 + */
6085 +#define HARDIRQ_BITS   6
6086 +#if (1 << HARDIRQ_BITS) < NR_IRQS
6087 +# error HARDIRQ_BITS is too low!
6088 +#endif
6089 +
6090 +typedef struct {
6091 +       unsigned int __softirq_pending;
6092 +} ____cacheline_aligned irq_cpustat_t;
6093 +
6094 +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
6095 +
6096 +extern void ack_bad_irq(unsigned int irq);
6097 +
6098 +#endif /* _ASM_UBICOM32_HARDIRQ_H */
6099 --- /dev/null
6100 +++ b/arch/ubicom32/include/asm/hw_irq.h
6101 @@ -0,0 +1,31 @@
6102 +/*
6103 + * arch/ubicom32/include/asm/hw_irq.h
6104 + *   Ubicom32 architecture APIC support.
6105 + *
6106 + * (C) Copyright 2009, Ubicom, Inc.
6107 + *
6108 + * This file is part of the Ubicom32 Linux Kernel Port.
6109 + *
6110 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6111 + * it and/or modify it under the terms of the GNU General Public License
6112 + * as published by the Free Software Foundation, either version 2 of the
6113 + * License, or (at your option) any later version.
6114 + *
6115 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6116 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6117 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6118 + * the GNU General Public License for more details.
6119 + *
6120 + * You should have received a copy of the GNU General Public License
6121 + * along with the Ubicom32 Linux Kernel Port.  If not,
6122 + * see <http://www.gnu.org/licenses/>.
6123 + *
6124 + * Ubicom32 implementation derived from (with many thanks):
6125 + *   arch/m68knommu
6126 + *   arch/blackfin
6127 + *   arch/parisc
6128 + */
6129 +#ifndef _ASM_UBICOM32_HW_IRQ_H
6130 +#define _ASM_UBICOM32_HW_IRQ_H
6131 +
6132 +#endif /* _ASM_UBICOM32_HW_IRQ_H */
6133 --- /dev/null
6134 +++ b/arch/ubicom32/include/asm/ioctl.h
6135 @@ -0,0 +1,33 @@
6136 +/*
6137 + * arch/ubicom32/include/asm/ioctl.h
6138 + *   Generic ioctl.h for Ubicom32 architecture.
6139 + *
6140 + * (C) Copyright 2009, Ubicom, Inc.
6141 + *
6142 + * This file is part of the Ubicom32 Linux Kernel Port.
6143 + *
6144 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6145 + * it and/or modify it under the terms of the GNU General Public License
6146 + * as published by the Free Software Foundation, either version 2 of the
6147 + * License, or (at your option) any later version.
6148 + *
6149 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6150 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6151 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6152 + * the GNU General Public License for more details.
6153 + *
6154 + * You should have received a copy of the GNU General Public License
6155 + * along with the Ubicom32 Linux Kernel Port.  If not,
6156 + * see <http://www.gnu.org/licenses/>.
6157 + *
6158 + * Ubicom32 implementation derived from (with many thanks):
6159 + *   arch/m68knommu
6160 + *   arch/blackfin
6161 + *   arch/parisc
6162 + */
6163 +#ifndef _ASM_UBICOM32_IOCTL_H
6164 +#define _ASM_UBICOM32_IOCTL_H
6165 +
6166 +#include <asm-generic/ioctl.h>
6167 +
6168 +#endif /* _ASM_UBICOM32_IOCTL_H */
6169 --- /dev/null
6170 +++ b/arch/ubicom32/include/asm/ioctls.h
6171 @@ -0,0 +1,111 @@
6172 +/*
6173 + * arch/ubicom32/include/asm/ioctls.h
6174 + *   Definitions of ioctls for Ubicom32 architecture.
6175 + *
6176 + * (C) Copyright 2009, Ubicom, Inc.
6177 + *
6178 + * This file is part of the Ubicom32 Linux Kernel Port.
6179 + *
6180 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6181 + * it and/or modify it under the terms of the GNU General Public License
6182 + * as published by the Free Software Foundation, either version 2 of the
6183 + * License, or (at your option) any later version.
6184 + *
6185 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6186 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6187 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6188 + * the GNU General Public License for more details.
6189 + *
6190 + * You should have received a copy of the GNU General Public License
6191 + * along with the Ubicom32 Linux Kernel Port.  If not,
6192 + * see <http://www.gnu.org/licenses/>.
6193 + *
6194 + * Ubicom32 implementation derived from (with many thanks):
6195 + *   arch/m68knommu
6196 + *   arch/blackfin
6197 + *   arch/parisc
6198 + */
6199 +#ifndef _ASM_UBICOM32_IOCTLS_H
6200 +#define _ASM_UBICOM32_IOCTLS_H
6201 +
6202 +#include <asm/ioctl.h>
6203 +
6204 +/* 0x54 is just a magic number to make these relatively unique ('T') */
6205 +
6206 +#define TCGETS         0x5401
6207 +#define TCSETS         0x5402
6208 +#define TCSETSW                0x5403
6209 +#define TCSETSF                0x5404
6210 +#define TCGETA         0x5405
6211 +#define TCSETA         0x5406
6212 +#define TCSETAW                0x5407
6213 +#define TCSETAF                0x5408
6214 +#define TCSBRK         0x5409
6215 +#define TCXONC         0x540A
6216 +#define TCFLSH         0x540B
6217 +#define TIOCEXCL       0x540C
6218 +#define TIOCNXCL       0x540D
6219 +#define TIOCSCTTY      0x540E
6220 +#define TIOCGPGRP      0x540F
6221 +#define TIOCSPGRP      0x5410
6222 +#define TIOCOUTQ       0x5411
6223 +#define TIOCSTI                0x5412
6224 +#define TIOCGWINSZ     0x5413
6225 +#define TIOCSWINSZ     0x5414
6226 +#define TIOCMGET       0x5415
6227 +#define TIOCMBIS       0x5416
6228 +#define TIOCMBIC       0x5417
6229 +#define TIOCMSET       0x5418
6230 +#define TIOCGSOFTCAR   0x5419
6231 +#define TIOCSSOFTCAR   0x541A
6232 +#define FIONREAD       0x541B
6233 +#define TIOCINQ                FIONREAD
6234 +#define TIOCLINUX      0x541C
6235 +#define TIOCCONS       0x541D
6236 +#define TIOCGSERIAL    0x541E
6237 +#define TIOCSSERIAL    0x541F
6238 +#define TIOCPKT                0x5420
6239 +#define FIONBIO                0x5421
6240 +#define TIOCNOTTY      0x5422
6241 +#define TIOCSETD       0x5423
6242 +#define TIOCGETD       0x5424
6243 +#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
6244 +#define TIOCSBRK       0x5427  /* BSD compatibility */
6245 +#define TIOCCBRK       0x5428  /* BSD compatibility */
6246 +#define TIOCGSID       0x5429  /* Return the session ID of FD */
6247 +#define TCGETS2                _IOR('T',0x2A, struct termios2)
6248 +#define TCSETS2                _IOW('T',0x2B, struct termios2)
6249 +#define TCSETSW2       _IOW('T',0x2C, struct termios2)
6250 +#define TCSETSF2       _IOW('T',0x2D, struct termios2)
6251 +#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
6252 +#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
6253 +
6254 +#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
6255 +#define FIOCLEX                0x5451
6256 +#define FIOASYNC       0x5452
6257 +#define TIOCSERCONFIG  0x5453
6258 +#define TIOCSERGWILD   0x5454
6259 +#define TIOCSERSWILD   0x5455
6260 +#define TIOCGLCKTRMIOS 0x5456
6261 +#define TIOCSLCKTRMIOS 0x5457
6262 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
6263 +#define TIOCSERGETLSR   0x5459 /* Get line status register */
6264 +#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
6265 +#define TIOCSERSETMULTI 0x545B /* Set multiport config */
6266 +
6267 +#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
6268 +#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
6269 +#define FIOQSIZE       0x545E
6270 +
6271 +/* Used for packet mode */
6272 +#define TIOCPKT_DATA            0
6273 +#define TIOCPKT_FLUSHREAD       1
6274 +#define TIOCPKT_FLUSHWRITE      2
6275 +#define TIOCPKT_STOP            4
6276 +#define TIOCPKT_START           8
6277 +#define TIOCPKT_NOSTOP         16
6278 +#define TIOCPKT_DOSTOP         32
6279 +
6280 +#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
6281 +
6282 +#endif /* _ASM_UBICOM32_IOCTLS_H */
6283 --- /dev/null
6284 +++ b/arch/ubicom32/include/asm/io.h
6285 @@ -0,0 +1,313 @@
6286 +/*
6287 + * arch/ubicom32/include/asm/io.h
6288 + *   I/O memory accessor functions for Ubicom32 architecture.
6289 + *
6290 + * (C) Copyright 2009, Ubicom, Inc.
6291 + *
6292 + * This file is part of the Ubicom32 Linux Kernel Port.
6293 + *
6294 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6295 + * it and/or modify it under the terms of the GNU General Public License
6296 + * as published by the Free Software Foundation, either version 2 of the
6297 + * License, or (at your option) any later version.
6298 + *
6299 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6300 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6301 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6302 + * the GNU General Public License for more details.
6303 + *
6304 + * You should have received a copy of the GNU General Public License
6305 + * along with the Ubicom32 Linux Kernel Port.  If not,
6306 + * see <http://www.gnu.org/licenses/>.
6307 + *
6308 + * Ubicom32 implementation derived from (with many thanks):
6309 + *   arch/m68knommu
6310 + *   arch/blackfin
6311 + *   arch/parisc
6312 + */
6313 +#ifndef _ASM_UBICOM32_IO_H
6314 +#define _ASM_UBICOM32_IO_H
6315 +
6316 +#ifdef __KERNEL__
6317 +#include <linux/string.h>
6318 +#include <linux/compiler.h>
6319 +
6320 +static inline unsigned short _swapw(volatile unsigned short v)
6321 +{
6322 +    return ((v << 8) | (v >> 8));
6323 +}
6324 +
6325 +static inline unsigned int _swapl(volatile unsigned long v)
6326 +{
6327 +    return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
6328 +}
6329 +
6330 +#ifndef CONFIG_PCI
6331 +#define readb(addr) \
6332 +    ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
6333 +#define readw(addr) \
6334 +    ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
6335 +#define readl(addr) \
6336 +    ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
6337 +
6338 +#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
6339 +#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
6340 +#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
6341 +#else /*CONFIG_PCI */
6342 +
6343 +#define PCI_CPU_REG_BASE (0x00000000UL)   /* taking lower 2GB space */
6344 +#define PCI_DEV_REG_BASE (0x80000000UL)
6345 +
6346 +#if PCI_CPU_REG_BASE > PCI_DEV_REG_BASE
6347 +#define IS_PCI_ADDRESS(x) (((unsigned int)(x)&(PCI_CPU_REG_BASE)) == 0)
6348 +#else
6349 +#define IS_PCI_ADDRESS(x) ((unsigned int)(x)&(PCI_DEV_REG_BASE))
6350 +#endif
6351 +
6352 +extern unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr);
6353 +extern unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr);
6354 +extern unsigned char ubi32_pci_read_u8(const volatile void __iomem *addr);
6355 +extern  void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr);
6356 +extern  void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr);
6357 +extern  void ubi32_pci_write_u8(unsigned char val, const volatile void __iomem *addr);
6358 +
6359 +static  inline unsigned char readb(const volatile void __iomem *addr)
6360 +{
6361 +       if (IS_PCI_ADDRESS(addr))
6362 +               return ubi32_pci_read_u8(addr);
6363 +       else
6364 +               return (unsigned char)(*(volatile unsigned char *)addr);
6365 +}
6366 +static inline unsigned short readw(const volatile void __iomem *addr)
6367 +{
6368 +       if (IS_PCI_ADDRESS(addr))
6369 +               return ubi32_pci_read_u16(addr);
6370 +       else
6371 +               return (unsigned short)(*(volatile unsigned short *)addr);
6372 +}
6373 +
6374 +static  inline unsigned int  readl(const volatile void __iomem *addr)
6375 +{
6376 +       if (IS_PCI_ADDRESS(addr))
6377 +               return ubi32_pci_read_u32(addr);
6378 +       else
6379 +               return (unsigned int)(*(volatile unsigned int *)addr);
6380 +}
6381 +
6382 +static inline void writel(unsigned int val, volatile void __iomem *addr)
6383 +{
6384 +       if (IS_PCI_ADDRESS(addr))
6385 +                ubi32_pci_write_u32(val, addr);
6386 +        else
6387 +               *(volatile unsigned int *)addr = val;
6388 +}
6389 +
6390 +static inline void writew(unsigned short val, volatile void __iomem *addr)
6391 +{
6392 +       if (IS_PCI_ADDRESS(addr))
6393 +                ubi32_pci_write_u16(val, addr);
6394 +        else
6395 +               *(volatile unsigned short *)addr = val;
6396 +}
6397 +
6398 +static inline void writeb(unsigned char val, volatile void __iomem *addr)
6399 +{
6400 +       if (IS_PCI_ADDRESS(addr))
6401 +                ubi32_pci_write_u8(val, addr);
6402 +        else
6403 +               *(volatile unsigned char *)addr = val;
6404 +}
6405 +#endif
6406 +
6407 +#define readb_relaxed(addr) readb(addr)
6408 +#define readw_relaxed(addr) readw(addr)
6409 +#define readl_relaxed(addr) readl(addr)
6410 +
6411 +
6412 +#define __raw_readb readb
6413 +#define __raw_readw readw
6414 +#define __raw_readl readl
6415 +#define __raw_writeb writeb
6416 +#define __raw_writew writew
6417 +#define __raw_writel writel
6418 +
6419 +static inline void io_outsb(unsigned int addr, const void *buf, int len)
6420 +{
6421 +       volatile unsigned char *ap = (volatile unsigned char *) addr;
6422 +       unsigned char *bp = (unsigned char *) buf;
6423 +       while (len--)
6424 +               *ap = *bp++;
6425 +}
6426 +
6427 +static inline void io_outsw(unsigned int addr, const void *buf, int len)
6428 +{
6429 +       volatile unsigned short *ap = (volatile unsigned short *) addr;
6430 +       unsigned short *bp = (unsigned short *) buf;
6431 +       while (len--)
6432 +               *ap = _swapw(*bp++);
6433 +}
6434 +
6435 +static inline void io_outsl(unsigned int addr, const void *buf, int len)
6436 +{
6437 +       volatile unsigned int *ap = (volatile unsigned int *) addr;
6438 +       unsigned int *bp = (unsigned int *) buf;
6439 +       while (len--)
6440 +               *ap = _swapl(*bp++);
6441 +}
6442 +
6443 +static inline void io_insb(unsigned int addr, void *buf, int len)
6444 +{
6445 +       volatile unsigned char *ap = (volatile unsigned char *) addr;
6446 +       unsigned char *bp = (unsigned char *) buf;
6447 +       while (len--)
6448 +               *bp++ = *ap;
6449 +}
6450 +
6451 +static inline void io_insw(unsigned int addr, void *buf, int len)
6452 +{
6453 +       volatile unsigned short *ap = (volatile unsigned short *) addr;
6454 +       unsigned short *bp = (unsigned short *) buf;
6455 +       while (len--)
6456 +               *bp++ = _swapw(*ap);
6457 +}
6458 +
6459 +static inline void io_insl(unsigned int addr, void *buf, int len)
6460 +{
6461 +       volatile unsigned int *ap = (volatile unsigned int *) addr;
6462 +       unsigned int *bp = (unsigned int *) buf;
6463 +       while (len--)
6464 +               *bp++ = _swapl(*ap);
6465 +}
6466 +
6467 +#define mmiowb()
6468 +
6469 +/*
6470 + *     make the short names macros so specific devices
6471 + *     can override them as required
6472 + */
6473 +#ifndef CONFIG_PCI
6474 +#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
6475 +#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
6476 +#define memcpy_toio(a,b,c)     memcpy((void *)(a),(b),(c))
6477 +#else
6478 +extern void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len);
6479 +extern void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len);
6480 +extern void memset_io(volatile void __iomem *addr, int val, size_t count);
6481 +#endif
6482 +
6483 +#define inb(addr)    readb(addr)
6484 +#define inw(addr)    readw(addr)
6485 +#define inl(addr)    readl(addr)
6486 +#define outb(x,addr) ((void) writeb(x,addr))
6487 +#define outw(x,addr) ((void) writew(x,addr))
6488 +#define outl(x,addr) ((void) writel(x,addr))
6489 +
6490 +#define inb_p(addr)    inb(addr)
6491 +#define inw_p(addr)    inw(addr)
6492 +#define inl_p(addr)    inl(addr)
6493 +#define outb_p(x,addr) outb(x,addr)
6494 +#define outw_p(x,addr) outw(x,addr)
6495 +#define outl_p(x,addr) outl(x,addr)
6496 +
6497 +#define outsb(a,b,l) io_outsb(a,b,l)
6498 +#define outsw(a,b,l) io_outsw(a,b,l)
6499 +#define outsl(a,b,l) io_outsl(a,b,l)
6500 +
6501 +#define insb(a,b,l) io_insb(a,b,l)
6502 +#define insw(a,b,l) io_insw(a,b,l)
6503 +#define insl(a,b,l) io_insl(a,b,l)
6504 +
6505 +#ifndef CONFIG_PCI
6506 +#define ioread8_rep(a,d,c)     insb(a,d,c)
6507 +#define ioread16_rep(a,d,c)    insw(a,d,c)
6508 +#define ioread32_rep(a,d,c)    insl(a,d,c)
6509 +#define iowrite8_rep(a,s,c)    outsb(a,s,c)
6510 +#define iowrite16_rep(a,s,c)   outsw(a,s,c)
6511 +#define iowrite32_rep(a,s,c)   outsl(a,s,c)
6512 +#else
6513 +extern void  ioread8_rep(void __iomem *port, void *buf, unsigned long count);
6514 +extern void  ioread16_rep(void __iomem *port, void *buf, unsigned long count);
6515 +extern void  ioread32_rep(void __iomem *port, void *buf, unsigned long count);
6516 +extern void  iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
6517 +extern void  iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
6518 +extern void  iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
6519 +#endif
6520 +
6521 +
6522 +#ifndef CONFIG_PCI
6523 +#define ioread8(X)                     readb(X)
6524 +#define ioread16(X)                    readw(X)
6525 +#define ioread32(X)                    readl(X)
6526 +#define iowrite8(val,X)                        writeb(val,X)
6527 +#define iowrite16(val,X)               writew(val,X)
6528 +#define iowrite32(val,X)               writel(val,X)
6529 +#else /*CONFIG_PCI */
6530 +extern  unsigned char  ioread8(void __iomem *addr);
6531 +extern  unsigned short ioread16(void __iomem *addr);
6532 +extern  unsigned int  ioread32(void __iomem *addr);
6533 +extern  void iowrite8(unsigned char val, void __iomem *addr);
6534 +extern  void iowrite16(unsigned short val, void __iomem *addr);
6535 +extern  void iowrite32(unsigned int val, void __iomem *addr);
6536 +#endif /* CONFIG_PCI */
6537 +
6538 +#define IO_SPACE_LIMIT 0xffff
6539 +
6540 +/* Values for nocacheflag and cmode */
6541 +#define IOMAP_FULL_CACHING             0
6542 +#define IOMAP_NOCACHE_SER              1
6543 +#define IOMAP_NOCACHE_NONSER           2
6544 +#define IOMAP_WRITETHROUGH             3
6545 +
6546 +extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
6547 +extern void __iounmap(void *addr, unsigned long size);
6548 +
6549 +static inline void *ioremap(unsigned long physaddr, unsigned long size)
6550 +{
6551 +       return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6552 +}
6553 +static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
6554 +{
6555 +       return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6556 +}
6557 +static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
6558 +{
6559 +       return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
6560 +}
6561 +static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
6562 +{
6563 +       return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
6564 +}
6565 +
6566 +extern void iounmap(void *addr);
6567 +
6568 +#define ioport_map(port, nr)            ((void __iomem*)(port))
6569 +#define ioport_unmap(addr)
6570 +
6571 +
6572 +/* Pages to physical address... */
6573 +#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
6574 +#define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
6575 +
6576 +/*
6577 + * Macros used for converting between virtual and physical mappings.
6578 + */
6579 +#define phys_to_virt(vaddr)    ((void *) (vaddr))
6580 +#define virt_to_phys(vaddr)    ((unsigned long) (vaddr))
6581 +
6582 +#define virt_to_bus virt_to_phys
6583 +#define bus_to_virt phys_to_virt
6584 +
6585 +/*
6586 + * Convert a physical pointer to a virtual kernel pointer for /dev/mem
6587 + * access
6588 + */
6589 +#define xlate_dev_mem_ptr(p)   __va(p)
6590 +
6591 +/*
6592 + * Convert a virtual cached pointer to an uncached pointer
6593 + */
6594 +#define xlate_dev_kmem_ptr(p)  p
6595 +
6596 +#endif /* __KERNEL__ */
6597 +
6598 +#endif /* _ASM_UBICOM32_IO_H */
6599 --- /dev/null
6600 +++ b/arch/ubicom32/include/asm/ip5000-asm.h
6601 @@ -0,0 +1,156 @@
6602 +/*
6603 + * arch/ubicom32/include/asm/ip5000-asm.h
6604 + *     Instruction macros for the IP5000.
6605 + *
6606 + * (C) Copyright 2009, Ubicom, Inc.
6607 + *
6608 + * This file is part of the Ubicom32 Linux Kernel Port.
6609 + *
6610 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6611 + * it and/or modify it under the terms of the GNU General Public License
6612 + * as published by the Free Software Foundation, either version 2 of the
6613 + * License, or (at your option) any later version.
6614 + *
6615 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6616 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6617 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6618 + * the GNU General Public License for more details.
6619 + *
6620 + * You should have received a copy of the GNU General Public License
6621 + * along with the Ubicom32 Linux Kernel Port.  If not,
6622 + * see <http://www.gnu.org/licenses/>.
6623 + *
6624 + * Ubicom32 implementation derived from (with many thanks):
6625 + *   arch/m68knommu
6626 + *   arch/blackfin
6627 + *   arch/parisc
6628 + */
6629 +
6630 +#ifndef _ASM_UBICOM32_IP5000_ASM_H
6631 +#define _ASM_UBICOM32_IP5000_ASM_H
6632 +
6633 +#if !defined(__LINKER__)
6634 +
6635 +#if defined(__ASSEMBLY__)
6636 +.macro cycles  quant
6637 +.if    (\quant) == 1
6638 +       nop
6639 +.else
6640 +.if    (((\quant) + 3) / 8) > 0
6641 +.rept  (((\quant) + 3) / 8)
6642 +       jmpt.f          .+4
6643 +.endr
6644 +.endif
6645 +.if    ((((\quant) + 3) % 8) / 4) > 0
6646 +       jmpt.t          .+4
6647 +.endif
6648 +.endif
6649 +.endm
6650 +#else
6651 +/*
6652 + * Same macro as above just in C inline asm
6653 + */
6654 +asm ("                                 \n\
6655 +.macro cycles  quant                   \n\
6656 +.if    (\\quant) == 1                  \n\
6657 +       nop                             \n\
6658 +.else                                  \n\
6659 +.if    (((\\quant) + 3) / 8) > 0       \n\
6660 +.rept  (((\\quant) + 3) / 8)           \n\
6661 +       jmpt.f          .+4             \n\
6662 +.endr                                  \n\
6663 +.endif                                 \n\
6664 +.if    ((((\\quant) + 3) % 8) / 4) > 0 \n\
6665 +       jmpt.t          .+4             \n\
6666 +.endif                                 \n\
6667 +.endif                                 \n\
6668 +.endm                                  \n\
6669 +");
6670 +#endif
6671 +
6672 +
6673 +#if defined(__ASSEMBLY__)
6674 +.macro pipe_flush      cyc
6675 +       cycles          11 - (\cyc)
6676 +.endm
6677 +#else
6678 +/*
6679 + * Same macro as above just in C inline asm
6680 + */
6681 +asm ("                                 \n\
6682 +.macro pipe_flush      cyc             \n\
6683 +       cycles          11 - (\\cyc)    \n\
6684 +.endm                                  \n\
6685 +");
6686 +
6687 +#endif
6688 +
6689 +#if defined(__ASSEMBLY__)
6690 +.macro setcsr_flush    cyc
6691 +       cycles          5 - (\cyc)
6692 +.endm
6693 +#else
6694 +/*
6695 + * Same macro as above just in C inline asm
6696 + */
6697 +asm ("                                 \n\
6698 +.macro setcsr_flush    cyc             \n\
6699 +       cycles          5 - (\\cyc)     \n\
6700 +.endm                                  \n\
6701 +");
6702 +#endif
6703 +
6704 +/*
6705 + * Macros for prefetch (using miss-aligned memory write)
6706 + */
6707 +#if defined(__ASSEMBLY__)
6708 +
6709 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length
6710 +       bclr            MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6711 +       bset            \Ascratch, \Aaddress, #0        ; force a miss-aligned address
6712 +       jmpt.t          .+4                             ; delay for both address setup and trap disable
6713 +       move.4          (\Ascratch), #0
6714 +       .if             (\length > 32)
6715 +       move.4          32(\Ascratch), #0
6716 +       .endif
6717 +       .if             (\length > 64)
6718 +       move.4          64(\Ascratch), #0
6719 +       .endif
6720 +       .if             (\length > 96)
6721 +       move.4          96(\Ascratch), #0
6722 +       .endif
6723 +       .if             (\length > 128)
6724 +       invalid_instruction                             ; maximum pre-fetch size is 4 cache lines
6725 +       .endif
6726 +       bset            MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6727 +.endm
6728 +
6729 +#else
6730 +/*
6731 + * Same macro as above just in C inline asm
6732 + */
6733 +asm ("                                                         \n\
6734 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length   \n\
6735 +       bclr            MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)  \n\
6736 +       bset            \\Ascratch, \\Aaddress, #0      ; force a miss-aligned address \n\
6737 +       jmpt.t          .+4                             ; delay for both address setup and trap disable \n\
6738 +       move.4          (\\Ascratch), #0                        \n\
6739 +       .if             (\\length > 32)                         \n\
6740 +       move.4          32(\\Ascratch), #0                      \n\
6741 +       .endif                                                  \n\
6742 +       .if             (\\length > 64)                         \n\
6743 +       move.4          64(\\Ascratch), #0                      \n\
6744 +       .endif                                                  \n\
6745 +       .if             (\\length > 96)                         \n\
6746 +       move.4          96(\\Ascratch), #0                      \n\
6747 +       .endif                                                  \n\
6748 +       .if             (\\length > 128)                        \n\
6749 +       invalid_instruction                             ; maximum pre-fetch size is 4 cache lines \n\
6750 +       .endif                                                  \n\
6751 +       bset            MT_TRAP_EN, MT_TRAP_EN, #(\\thread_num) \n\
6752 +.endm                                                          \n\
6753 +");
6754 +#endif
6755 +
6756 +#endif /* !defined(__LINKER__) */
6757 +#endif /* defined _ASM_UBICOM32_IP5000_ASM_H */
6758 --- /dev/null
6759 +++ b/arch/ubicom32/include/asm/ip5000.h
6760 @@ -0,0 +1,845 @@
6761 +/*
6762 + * arch/ubicom32/include/asm/ip5000.h
6763 + *   Specific details for the Ubicom IP5000 processor.
6764 + *
6765 + * (C) Copyright 2009, Ubicom, Inc.
6766 + *
6767 + * This file is part of the Ubicom32 Linux Kernel Port.
6768 + *
6769 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6770 + * it and/or modify it under the terms of the GNU General Public License
6771 + * as published by the Free Software Foundation, either version 2 of the
6772 + * License, or (at your option) any later version.
6773 + *
6774 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6775 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6776 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
6777 + * the GNU General Public License for more details.
6778 + *
6779 + * You should have received a copy of the GNU General Public License
6780 + * along with the Ubicom32 Linux Kernel Port.  If not,
6781 + * see <http://www.gnu.org/licenses/>.
6782 + *
6783 + * Ubicom32 implementation derived from (with many thanks):
6784 + *   arch/m68knommu
6785 + *   arch/blackfin
6786 + *   arch/parisc
6787 + */
6788 +
6789 +#ifndef _ASM_UBICOM32_IP5000_H
6790 +#define _ASM_UBICOM32_IP5000_H
6791 +
6792 +#include <asm/memory_map.h>
6793 +
6794 +/*
6795 + * Inline assembly define
6796 + */
6797 +#define S(arg) #arg
6798 +#define D(arg) S(arg)
6799 +
6800 +/*
6801 + * Assembler include file
6802 + */
6803 +#include <asm/ip5000-asm.h>
6804 +
6805 +/*
6806 + * Timing
6807 + */
6808 +#define JMPT_PENALTY 3
6809 +#define JMPF_PENALTY 7
6810 +#define RET_PENALTY 7
6811 +
6812 +/*
6813 + * Threads
6814 + */
6815 +#if defined(IP5000) || defined(IP5000_REV2)
6816 +#define THREAD_COUNT 10
6817 +#elif defined(IP7000) || defined(IP7000_REV2)
6818 +#define THREAD_COUNT 12
6819 +#else
6820 +#error "Unknown IP5K silicon"
6821 +#endif
6822 +
6823 +/*
6824 + * Arch
6825 + */
6826 +#if defined(IP5000) || defined(IP5000_REV2)
6827 +#define UBICOM32_ARCH_VERSION 3
6828 +#elif defined(IP7000) || defined(IP7000_REV2)
6829 +#define UBICOM32_ARCH_VERSION 4
6830 +#else
6831 +#error "Unknown IP5K silicon"
6832 +#endif
6833 +
6834 +
6835 +/*
6836 + * Registers
6837 + */
6838 +#define ROSR_INT (1 << 0)
6839 +
6840 +/* Interrupts */
6841 +#define INT_CHIP(reg, bit) (((reg) << 5) | (bit))
6842 +#define INT_REG(interrupt) (((interrupt) >> 5) * 4)
6843 +#define INT_SET(interrupt) 0x0114 + INT_REG(interrupt)
6844 +#define INT_CLR(interrupt) 0x0124 + INT_REG(interrupt)
6845 +#define INT_STAT(interrupt) 0x0104 + INT_REG(interrupt)
6846 +#define INT_MASK(interrupt) 0x00C0 + INT_REG(interrupt)
6847 +#define INT_BIT(interrupt) ((interrupt) & 0x1F)
6848 +#define INT_BIT_MASK(interrupt) (1 << INT_BIT(interrupt))
6849 +
6850 +/*
6851 + * The LOCK_INT and THREAD_INT are used to wake up corresponding thread. They are sharing
6852 + * the same set of SW interrupt resource.
6853 + *
6854 + * LOCK_INT(n): One SW INT per NRT thread that can participate lock operation.
6855 + *     The threads that can participate lock are application threads and DSR thread.
6856 + *     (Lock locks - numbers are hard-coded in lock.h)
6857 + * THREAD_INT(n):   One SW INT per HRT thread for wake up trigger.
6858 + */
6859 +#define LOCK_INT(thread)       INT_CHIP(0, (thread))
6860 +#define THREAD_INT(thread)     INT_CHIP(0, (thread))
6861 +
6862 +/*
6863 + * The SYSTEM_INT and DSR_INT are sharing the same set of SW interrupt resource.
6864 + *
6865 + * SYSTEM_INT(n): One SW INT per NRT threads (application threads) as system queue interrupt,
6866 + *     and for DSR as self-trigger interrupt.
6867 + *     (The application threads include at least thread 0)
6868 + * DSR_INT(n):    One SW INT per HRT thread to request DSR service.
6869 + */
6870 +#define SYSTEM_INT(thread)     INT_CHIP(0, THREAD_COUNT + (thread))
6871 +#define DSR_INT(thread)                INT_CHIP(0, THREAD_COUNT + (thread))
6872 +
6873 +/* GLOBAL_CTRL */
6874 +#define GLOBAL_CTRL_TRAP_RST_EN (1 << 9)
6875 +#define GLOBAL_CTRL_AERROR_RST_EN (1 << 8)
6876 +#define GLOBAL_CTRL_MT_MIN_DELAY(x) ((x) << 3)
6877 +#define GLOBAL_CTRL_HRT_BANK_SELECT (1 << 2)
6878 +#define GLOBAL_CTRL_INT_EN (1 << 0)
6879 +
6880 +/*
6881 + * HRT Tables
6882 + */
6883 +#define HRT_TABLE0_BASE 0x0800
6884 +#define HRT_TABLE1_BASE 0x0900
6885 +#define HRT_TABLE_SIZE 64
6886 +
6887 +/*
6888 + * Break Point Trap Register
6889 + */
6890 +#define ASYNCERROR_INT INT_CHIP(0, 31)
6891 +#define BREAKPOINT_INT INT_CHIP(1, 31)
6892 +
6893 +/*
6894 + * Port interrupts
6895 + *     The non-existing FIFO INTs are mapped to INT2 for the ports.
6896 + */
6897 +#define IO_PORT_PTR_TO_NUM(port) (((port) & 0x0000ffff) >> 12)
6898 +#define RX_FIFO_INT(port) \
6899 +       ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6900 +       ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 26) : \
6901 +       ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6902 +       ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 24) : \
6903 +       ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 27) : \
6904 +       ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 16) : \
6905 +       ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6906 +       ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6907 +       ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 21) : \
6908 +       INT_CHIP(1, 15))))))))))
6909 +#define TX_FIFO_INT(port) \
6910 +       ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 24) : \
6911 +       ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 27) : \
6912 +       ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6913 +       ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 25) : \
6914 +       ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 28) : \
6915 +       ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 17) : \
6916 +       ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6917 +       ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6918 +       ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 22) : \
6919 +       INT_CHIP(1, 15))))))))))
6920 +#define PORT_OTHER_INT(port) \
6921 +       ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6922 +       ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 28) : \
6923 +       ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6924 +       ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 26) : \
6925 +       ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 29) : \
6926 +       ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 18) : \
6927 +       ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6928 +       ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6929 +       ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 23) : \
6930 +       INT_CHIP(1, 15))))))))))
6931 +
6932 +/*
6933 + * On Chip Peripherals Base.
6934 + */
6935 +#define OCP_BASE       0x01000000
6936 +#define OCP_GENERAL    0x000
6937 +#define OCP_TIMERS     0x100
6938 +#define OCP_TRNG       0x200   /* True Random Number Generator Control Reigsters */
6939 +#define OCP_DEBUG      0x300
6940 +#define OCP_SECURITY   0x400
6941 +#define OCP_ICCR       0x500   /* I-Cache Control Registers */
6942 +#define OCP_DCCR       0x600   /* D-Cache Control Registers */
6943 +#define OCP_OCMC       0x700   /* On Chip Memory Control Registers */
6944 +#define OCP_STATISTICS 0x800   /* Statistics Counters */
6945 +#define OCP_MTEST      0x900   /* Memory Test Registers */
6946 +#define OCP_MCFG       0xa00   /* Memory Configuration Registers -- IP7000 only */
6947 +#define OCP_DEBUG_INST 0x000   /* Up to 16M */
6948 +
6949 +/*
6950 + * General Configuration Registers (PLL)
6951 + */
6952 +#define GENERAL_CFG_BASE (OCP_BASE + OCP_GENERAL)
6953 +#define GEN_CLK_CORE_CFG 0x00
6954 +#define GEN_CLK_IO_CFG 0x04
6955 +#define GEN_CLK_DDR_CFG 0x08
6956 +#define GEN_CLK_DDRDS_CFG 0x0c
6957 +#define GEN_CLK_SLIP_CLR 0x10
6958 +#define GEN_CLK_SLIP_START 0x14
6959 +#define GEN_CLK_SERDES_SEL 0x18        /* IP7000 only */
6960 +#define GEN_CLK_DDR_CFG2 0x1c  /* IP7000 only */
6961 +#define GEN_DDR_CAL_CTRL 0x30  /* IP5000 only */
6962 +#define GEN_DDR_CAL_STAT 0x34  /* IP5000 only */
6963 +#define GEN_USB_DFT_CTRL 0x38  /* IP5000 only */
6964 +#define GEN_USB_DFT_STAT 0x3c  /* IP5000 only */
6965 +#define GEN_USB_PHY_CFG 0x40   /* IP7000 only */
6966 +#define GEN_USB_PHY_TEST 0x44  /* IP7000 only */
6967 +#define GEN_USB_PHY_STAT 0x48  /* IP7000 only */
6968 +#define GEN_SW_RESET 0x80
6969 +#define GEN_RESET_REASON 0x84
6970 +#define GEN_BOND_CFG 0x88
6971 +#define GEN_IO_PU_CFG 0x8c
6972 +#define GEN_MEM_RM_CFG 0x90
6973 +#define GEN_IO_CONFIG 0x94
6974 +
6975 +#define GEN_CLK_PLL_SECURITY_BIT_NO 31
6976 +#define GEN_CLK_PLL_SECURITY (1 << GEN_CLK_PLL_SECURITY_BIT_NO)
6977 +#define GEN_CLK_PLL_ENSAT (1 << 30)
6978 +#define GEN_CLK_PLL_FASTEN (1 << 29)
6979 +#define GEN_CLK_PLL_NR(v) (((v) - 1) << 23)
6980 +#define GEN_CLK_PLL_NF(v) (((v) - 1) << 11)
6981 +#define GEN_CLK_PLL_OD(v) (((v) - 1) << 8)
6982 +#define GEN_CLK_PLL_RESET (1 << 7)
6983 +#define GEN_CLK_PLL_BYPASS (1 << 6)
6984 +#define GEN_CLK_PLL_POWERDOWN (1 << 5)
6985 +#define GEN_CLK_PLL_SELECT (1 << 4)
6986 +
6987 +#define GEN_GET_CLK_PLL_NR(v) ((((v) >> 23) & 0x003f) + 1)
6988 +#define GEN_GET_CLK_PLL_NF(v) ((((v) >> 11) & 0x0fff) + 1)
6989 +#define GEN_GET_CLK_PLL_OD(v) ((((v) >> 8) & 0x7) + 1)
6990 +
6991 +
6992 +#define RESET_FLAG_DST_MEM_ERROR (1 << 18)
6993 +#define RESET_FLAG_SRC1_MEM_ERROR (1 << 17)
6994 +#define RESET_FLAG_WRITE_ADDR (1 << 16)
6995 +#define RESET_FLAG_DST_SYNC_ERROR (1 << 15)
6996 +#define RESET_FLAG_SRC1_SYNC_ERROR (1 << 14)
6997 +#define RESET_FLAG_DST_ALGN_ERROR (1 << 13)
6998 +#define RESET_FLAG_SRC1_ALGN_ERROR (1 << 12)
6999 +#define RESET_FLAG_DST_ADDR_ERROR (1 << 11)
7000 +#define RESET_FLAG_SRC1_ADDR_ERROR (1 << 10)
7001 +#define RESET_FLAG_ILLEGAL_INST (1 << 9)
7002 +#define RESET_FLAG_INST_SYNC_ERROR (1 << 8)
7003 +#define RESET_FLAG_INST_ADDR_ERROR (1 << 7)
7004 +#define RESET_FLAG_DATA_PORT_ERROR (1 << 6)
7005 +#define RESET_FLAG_INST_PORT_ERROR (1 << 5)
7006 +#define RESET_FLAG_SW_RESET (1 << 4)
7007 +#define RESET_FLAG_DEBUG (1 << 3)
7008 +#define RESET_FLAG_WATCHDOG (1 << 2)
7009 +#define RESET_FLAG_POWER_ON (1 << 1)
7010 +#define RESET_FLAG_EXTERNAL (1 << 0)
7011 +
7012 +/*
7013 + * Timer block
7014 + */
7015 +#define TIMER_BASE (OCP_BASE + OCP_TIMERS)
7016 +#define TIMER_MPTVAL 0x00
7017 +#define TIMER_RTCOM 0x04
7018 +#define TIMER_TKEY 0x08
7019 +#define TIMER_WDCOM 0x0c
7020 +#define TIMER_WDCFG 0x10
7021 +#define TIMER_SYSVAL 0x14
7022 +#define TIMER_SYSCOM(tmr) (0x18 + (tmr) * 4)
7023 +#define TIMER_TRN_CFG 0x100
7024 +#define TIMER_TRN 0x104
7025 +
7026 +#define TIMER_COUNT 10
7027 +#define TIMER_INT(tmr) INT_CHIP(1, (tmr))
7028 +#define TIMER_TKEYVAL 0xa1b2c3d4
7029 +#define TIMER_WATCHDOG_DISABLE 0x4d3c2b1a
7030 +#define TIMER_TRN_CFG_ENABLE_OSC 0x00000007
7031 +
7032 +#ifndef __ASSEMBLY__
7033 +/*
7034 + * ubicom32_io_timer
7035 + */
7036 +struct ubicom32_io_timer {
7037 +       volatile u32_t mptval;
7038 +       volatile u32_t rtcom;
7039 +       volatile u32_t tkey;
7040 +       volatile u32_t wdcom;
7041 +       volatile u32_t wdcfg;
7042 +       volatile u32_t sysval;
7043 +       volatile u32_t syscom[TIMER_COUNT];
7044 +       volatile u32_t reserved[64 - 6 - TIMER_COUNT];  // skip all the way to OCP-TRNG section
7045 +       volatile u32_t rsgcfg;
7046 +       volatile u32_t trn;
7047 +};
7048 +
7049 +#define UBICOM32_IO_TIMER ((struct ubicom32_io_timer *)TIMER_BASE)
7050 +#endif
7051 +
7052 +#define UBICOM32_VECTOR_TO_TIMER_INDEX(vector) (vector - TIMER_INT(0))
7053 +
7054 +/*
7055 + * OCP-Debug Module (Mailbox)
7056 + */
7057 +#define ISD_MAILBOX_BASE (OCP_BASE + OCP_DEBUG)
7058 +#define ISD_MAILBOX_IN 0x00
7059 +#define ISD_MAILBOX_OUT 0x04
7060 +#define ISD_MAILBOX_STATUS 0x08
7061 +
7062 +#define ISD_MAILBOX_INT INT_CHIP(1, 30)
7063 +
7064 +#define ISD_MAILBOX_STATUS_IN_FULL (1 << 31)
7065 +#define ISD_MAILBOX_STATUS_IN_EMPTY (1 << 30)
7066 +#define ISD_MAILBOX_STATUS_OUT_FULL (1 << 29)
7067 +#define ISD_MAILBOX_STATUS_OUT_EMPTY (1 << 28)
7068 +
7069 +/*
7070 + * OCP-Security
7071 + */
7072 +#define SECURITY_BASE (OCP_BASE + OCP_SECURITY)
7073 +#define SECURITY_BASE_EFFECTIVE_ADDRESS (SECURITY_BASE >> 7) // To load the base address in a single instruction
7074 +#define SECURITY_CTRL 0x00
7075 +#define SECURITY_CTRL_BYTE_OFFSET(x) ((x) << 16)
7076 +#define SECURITY_CTRL_KEY_SIZE(x) ((x) << 8)
7077 +#define SECURITY_CTRL_HASH_ALG_NONE (0 << 4)
7078 +#define SECURITY_CTRL_HASH_ALG_MD5 (1 << 4)
7079 +#define SECURITY_CTRL_HASH_ALG_SHA1 (2 << 4)
7080 +#define SECURITY_CTRL_CBC (1 << 3)
7081 +#define SECURITY_CTRL_CIPHER_ALG_AES (0 << 1)
7082 +#define SECURITY_CTRL_CIPHER_ALG_NONE (1 << 1)
7083 +#define SECURITY_CTRL_CIPHER_ALG_DES (2 << 1)
7084 +#define SECURITY_CTRL_CIPHER_ALG_3DES (3 << 1)
7085 +#define SECURITY_CTRL_ENCIPHER (1 << 0)
7086 +#define SECURITY_CTRL_DECIPHER (0 << 0)
7087 +#define SECURITY_STAT 0x04
7088 +#define SECURITY_STAT_BUSY (1 << 0)
7089 +#define SECURITY_KEY_VALUE(x) (0x10 + (x) * 4)
7090 +#define SECURITY_KEY_IN(x) (0x30 + (x) * 4)
7091 +#define SECURITY_KEY_OUT(x) (0x50 + (x) * 4)
7092 +#define SECURITY_KEY_HASH(x) (0x70 + (x) * 4)
7093 +
7094 +/*
7095 + * OCP-ICCR
7096 + */
7097 +#define ICCR_BASE (OCP_BASE + OCP_ICCR)
7098 +#define ICACHE_TOTAL_SIZE 16384                        /* in bytes */
7099 +
7100 +/*
7101 + * OCP-DCCR
7102 + */
7103 +#define DCCR_BASE (OCP_BASE + OCP_DCCR)
7104 +#if defined(IP5000) || defined(IP5000_REV2)
7105 +#define DCACHE_TOTAL_SIZE 8192                 /* in bytes */
7106 +#elif defined(IP7000) || defined(IP7000_REV2)
7107 +#define DCACHE_TOTAL_SIZE 16384                        /* in bytes */
7108 +#endif
7109 +
7110 +#if defined(IP5000) || defined(IP5000_REV2) || defined(IP7000) || defined(IP7000_REV2)
7111 +#define DCACHE_WRITE_QUEUE_LENGTH 6
7112 +#else
7113 +#error "Unknown IP5K silicon"
7114 +#endif
7115 +
7116 +#define CACHE_LINE_SIZE 32                     /* in bytes */
7117 +
7118 +#define CCR_ADDR 0x00
7119 +#define CCR_RDD 0x04
7120 +#define CCR_WRD 0x08
7121 +#define CCR_STAT 0x0c
7122 +#define CCR_CTRL 0x10
7123 +
7124 +#define CCR_STAT_MCBE 0
7125 +#define CCR_STAT_WIDEL 1                       /* D-cache only */
7126 +
7127 +#define CCR_CTRL_DONE 0
7128 +#define CCR_CTRL_RESET 2
7129 +#define CCR_CTRL_VALID 3
7130 +#define CCR_CTRL_RD_DATA (1 << 4)
7131 +#define CCR_CTRL_RD_TAG (2 << 4)
7132 +#define CCR_CTRL_WR_DATA (3 << 4)
7133 +#define CCR_CTRL_WR_TAG (4 << 4)
7134 +#define CCR_CTRL_INV_INDEX (5 << 4)
7135 +#define CCR_CTRL_INV_ADDR (6 << 4)
7136 +#define CCR_CTRL_FLUSH_INDEX (7 << 4)          /* D-cache only */
7137 +#define CCR_CTRL_FLUSH_INV_INDEX (8 << 4)      /* D-cache only */
7138 +#define CCR_CTRL_FLUSH_ADDR (9 << 4)           /* D-cache only */
7139 +#define CCR_CTRL_FLUSH_INV_ADDR (10 << 4)      /* D-cache only */
7140 +
7141 +/*
7142 + * OCP-OCMC
7143 + */
7144 +#define OCMC_BASE (OCP_BASE + OCP_OCMC)
7145 +#define OCMC_BANK_MASK 0x00
7146 +#define OCMC_BIST_CNTL 0x04    /* IP5000 only */
7147 +#define OCMC_BIST_STAT 0x08    /* IP5000 only */
7148 +
7149 +#define OCMC_BANK_PROG(n) ((1<<(n))-1)
7150 +
7151 +#define OCMC_BIST_WRCK (1 << 7)
7152 +#define OCMC_BIST_RESET (1 << 5)
7153 +#define OCMC_BIST_SMART (1 << 4)
7154 +#define OCMC_BIST_RUN (1 << 3)
7155 +#define OCMC_BIST_REPAIR (1 << 2)
7156 +
7157 +#define OCMC_BIST_READY (1 << 3)
7158 +#define OCMC_BIST_FAIL (1 << 2)
7159 +
7160 +/*
7161 + * OCP-STATISTICS
7162 + */
7163 +#define STATISTICS_BASE (OCP_BASE + OCP_STATISTICS)
7164 +#define STAT_COUNTER_CTRL(n) ((n)*8)
7165 +#define STAT_COUNTER(n) ((n)*8 + 4)
7166 +
7167 +#define STAT_EVENT_MP_INST 0
7168 +#define STAT_EVENT_OCM_ACCESS 4
7169 +#define STAT_EVENT_OCM_REQ 5
7170 +#define STAT_EVENT_IC_REQ_INVAL 13
7171 +#define STAT_EVENT_IC_MISS_INVAL 14
7172 +#define STAT_EVENT_IC_REQ_INVAL_NACK 15
7173 +#define STAT_EVENT_IC_REQ_VAL 16
7174 +#define STAT_EVENT_IC_MISS_VAL 17
7175 +#define STAT_EVENT_IC_REQ_VAL_NACK 18
7176 +#define STAT_EVENT_IC_MISS_Q 19
7177 +#define STAT_EVENT_DC_RD_REQ 20
7178 +#define STAT_EVENT_DC_RD_MISS 21
7179 +#define STAT_EVENT_DC_WR_REQ 22
7180 +#define STAT_EVENT_DC_WR_MISS 23
7181 +#define STAT_EVENT_DC_MISS_Q 24
7182 +#define STAT_EVENT_DC_WB_FULL 25
7183 +#define STAT_EVENT_DC_REQ_NACK 26
7184 +#define STAT_EVENT_DC_CORE_REQ 27
7185 +#define STAT_EVENT_DC_MISS 28
7186 +#define STAT_EVENT_DC_EVICT 29
7187 +#define STAT_EVENT_TRUE 30
7188 +#define STAT_EVENT_FALSE 31
7189 +
7190 +/*
7191 + * OCP_MTEST
7192 + */
7193 +#define MTEST_BASE (OCP_BASE + OCP_MTEST)
7194 +#define MTEST_ADDR 0x00
7195 +#define MTEST_WR 0x04
7196 +#define MTEST_RD 0x08
7197 +#define MTEST_CTRL 0x0c
7198 +
7199 +/*
7200 + * OCP_MCFG (IP7000 only)
7201 + */
7202 +#define MCFG_BASE (OCP_BASE + OCP_MCFG)
7203 +#define MCFG_CTRL 0x00
7204 +#define MCFG_WCFG 0x04
7205 +#define MCFG_RCFG 0x08
7206 +
7207 +/*
7208 + * Port registers
7209 + */
7210 +#define IO_BASE 0x02000000
7211 +#define RA (IO_BASE + 0x00000000)
7212 +#define RB (IO_BASE + 0x00001000)
7213 +#define RC (IO_BASE + 0x00002000)
7214 +#define RD (IO_BASE + 0x00003000)
7215 +#define RE (IO_BASE + 0x00004000)
7216 +#define RF (IO_BASE + 0x00005000)
7217 +#define RG (IO_BASE + 0x00006000)
7218 +#define RH (IO_BASE + 0x00007000)
7219 +#define RI (IO_BASE + 0x00008000)
7220 +#define RJ (IO_BASE + 0x00009000)
7221 +#define RLATCH (IO_BASE + 0x00ff0000)  // For latched output only
7222 +#define IO_PORT_BR_OFFSET 0x00000800
7223 +
7224 +/*
7225 + * General I/O Register Map (per port)
7226 + */
7227 +#define IO_FUNC 0x00
7228 +#define IO_GPIO_CTL 0x04
7229 +#define IO_GPIO_OUT 0x08
7230 +#define IO_GPIO_IN 0x0C
7231 +#define IO_INT_STATUS 0x10
7232 +#define IO_INT_MASK 0x14
7233 +#define IO_INT_SET 0x18
7234 +#define IO_INT_CLR 0x1C
7235 +#define IO_TX_FIFO 0x20
7236 +#define IO_TX_FIFO_HI 0x24
7237 +#define IO_RX_FIFO 0x28
7238 +#define IO_RX_FIFO_HI 0x2c
7239 +#define IO_CTL0 0x30
7240 +#define IO_CTL1 0x34
7241 +#define IO_CTL2 0x38
7242 +#define IO_STATUS0 0x3c
7243 +#define IO_STATUS1 0x40
7244 +#define IO_STATUS2 0x44
7245 +#define IO_FIFO_WATER 0x48
7246 +#define IO_FIFO_LEVEL 0x4c
7247 +#define IO_GPIO_MASK 0x50
7248 +
7249 +#define IO_FUNC_FUNCTION_RESET(func) ((1 << ((func) - 1)) << 4)        /* Function 0 doesn't need reset */
7250 +#define IO_FUNC_RX_FIFO (1 << 3)
7251 +#define IO_FUNC_SELECT(func) ((func) << 0)
7252 +
7253 +/*
7254 + * External interrupt pins.
7255 + */
7256 +#define EXT_INT_IO_BIT(pin) ((pin) + 5)        // Interrupt pin number -> I/O INT bit
7257 +#define EXT_INT_RISING_EDGE(pin) (0x2 << (2*(pin) + 7))
7258 +#define EXT_INT_FALLING_EDGE(pin) (0x1 << (2*(pin) + 7))
7259 +
7260 +/*
7261 + * Flash
7262 + */
7263 +#define IO_XFL_BASE RA
7264 +
7265 +#define IO_XFL_INT_START (1 << 16)
7266 +#define IO_XFL_INT_ERR (1 << 8)
7267 +#define IO_XFL_INT_DONE (1 << 0)
7268 +
7269 +#define IO_XFL_CTL0_MASK (0xffe07fff)
7270 +#define IO_XFL_CTL0_RD_CMD(cmd) (((cmd) & 0xff) << 24)
7271 +#define IO_XFL_CTL0_RD_DUMMY(n) (((n) & 0x7) << 21)
7272 +#define IO_XFL_CTL0_CLK_WIDTH(core_cycles) ((((core_cycles) + 1) & 0x7e) << 8) /* must be even number */
7273 +#define IO_XFL_CTL0_CE_WAIT(spi_cycles) (((spi_cycles) & 0x3f) << 2)
7274 +#define IO_XFL_CTL0_MCB_LOCK (1 << 1)
7275 +#define IO_XFL_CTL0_ENABLE (1 << 0)
7276 +#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)
7277 +#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)
7278 +
7279 +#define IO_XFL_CTL1_MASK (0xc0003fff)
7280 +#define IO_XFL_CTL1_FC_INST(inst) (((inst) & 0x3) << 30)
7281 +#define IO_XFL_CTL1_FC_DATA(n) (((n) & 0x3ff) << 4)
7282 +#define IO_XFL_CTL1_FC_DUMMY(n) (((n) & 0x7) << 1)
7283 +#define IO_XFL_CTL1_FC_ADDR (1 << 0)
7284 +
7285 +#define IO_XFL_CTL2_FC_CMD(cmd) (((cmd) & 0xff) << 24)
7286 +#define IO_XFL_CTL2_FC_ADDR(addr) ((addr) & 0x00ffffff)        /* Only up to 24 bits */
7287 +
7288 +#define IO_XFL_STATUS0_MCB_ACTIVE (1 << 0)
7289 +#define IO_XFL_STATUS0_IOPCS_ACTIVE (1 << 1)
7290 +
7291 +/*
7292 + * SDRAM
7293 + */
7294 +#define IO_SDRAM_DATA_BASE RG
7295 +#define IO_SDRAM_CNTL_BASE RH
7296 +
7297 +#define IO_SDRAM_CTRL0_EN_REF (1 << 0)
7298 +
7299 +/*
7300 + * Port function code (common fucntion codes for all I/O ports)
7301 + */
7302 +#define IO_PORTX_FUNC_GPIO 0x00
7303 +#define IO_PORTX_FUNC_XFL 0x01
7304 +#define IO_PORTX_FUNC_PCI 0x01
7305 +#define IO_PORTX_FUNC_SERDES 0x01
7306 +#define IO_PORTX_FUNC_GMII 0x01
7307 +#define IO_PORTX_FUNC_DDR 0x01
7308 +#define IO_PORTX_FUNC_PCIX 0x01
7309 +#define IO_PORTX_FUNC_USB2_0 0x01
7310 +#define IO_PORTX_FUNC_GPIO_INT_CLK 0x02
7311 +#define IO_PORTX_FUNC_PLIO 0x02
7312 +#define IO_PORTX_FUNC_GPIO_INT 0x03
7313 +#define IO_PORTX_FUNC_MII 0x03
7314 +
7315 +/*
7316 + * Port 0
7317 + */
7318 +#define IO_PORT0_FUNC_GPIO IO_PORTX_FUNC_GPIO
7319 +#define IO_PORT0_FUNC_XFL_INT_CLK IO_PORTX_FUNC_XFL    // Default mode after reset
7320 +#define IO_PORT0_FUNC_GPIO_INT_CLK IO_PORTX_FUNC_GPIO_INT_CLK
7321 +#define IO_PORT0_FUNC_GPIO_INT IO_PORTX_FUNC_GPIO_INT
7322 +
7323 +/*
7324 + * Port 1
7325 + */
7326 +#define IO_PORT1_FUNC_GPIO IO_PORTX_FUNC_GPIO
7327 +#define IO_PORT1_FUNC_PCI IO_PORTX_FUNC_PCI            // PCI control
7328 +#define IO_PORT1_FUNC_MII IO_PORTX_FUNC_MII            // port 4 MII extension
7329 +
7330 +/*
7331 + * Port 2
7332 + */
7333 +#define IO_PORT2_FUNC_GPIO IO_PORTX_FUNC_GPIO
7334 +#define IO_PORT2_FUNC_PCI IO_PORTX_FUNC_PCI            // PCI data I/O
7335 +#define IO_PORT2_FUNC_PLIO IO_PORTX_FUNC_PLIO          // Extended LM
7336 +
7337 +/*
7338 + * Port 3
7339 + */
7340 +#define IO_PORT3_FUNC_GPIO IO_PORTX_FUNC_GPIO
7341 +#define IO_PORT3_FUNC_SERDES IO_PORTX_FUNC_SERDES
7342 +#define IO_PORT3_FUNC_PLIO IO_PORTX_FUNC_PLIO
7343 +
7344 +/*
7345 + * Port 4
7346 + */
7347 +#define IO_PORT4_FUNC_GPIO IO_PORTX_FUNC_GPIO
7348 +#define IO_PORT4_FUNC_SERDES IO_PORTX_FUNC_SERDES
7349 +#define IO_PORT4_FUNC_PLIO IO_PORTX_FUNC_PLIO          // Extended LM
7350 +#define IO_PORT4_FUNC_MII IO_PORTX_FUNC_MII
7351 +
7352 +/*
7353 + * Port 5
7354 + */
7355 +#define IO_PORT5_FUNC_GPIO IO_PORTX_FUNC_GPIO
7356 +#define IO_PORT5_FUNC_GMII IO_PORTX_FUNC_GMII
7357 +
7358 +/*
7359 + * Port 6
7360 + */
7361 +#define IO_PORT6_FUNC_GPIO IO_PORTX_FUNC_GPIO
7362 +#define IO_PORT6_FUNC_DDR IO_PORTX_FUNC_DDR
7363 +
7364 +/*
7365 + * Port 7
7366 + */
7367 +#define IO_PORT7_FUNC_GPIO IO_PORTX_FUNC_GPIO
7368 +#define IO_PORT7_FUNC_DDR IO_PORTX_FUNC_DDR
7369 +
7370 +/*
7371 + * Port 8
7372 + */
7373 +#define IO_PORT8_FUNC_GPIO IO_PORTX_FUNC_GPIO
7374 +#define IO_PORT8_FUNC_PCIX IO_PORTX_FUNC_PCIX
7375 +#define IO_PORT8_FUNC_PLIO IO_PORTX_FUNC_PLIO          // Extended LM
7376 +#define IO_PORT8_FUNC_MII IO_PORTX_FUNC_MII            // port 4 MII extension
7377 +
7378 +/*
7379 + * Port 9
7380 + */
7381 +#define IO_PORT9_FUNC_USB2_0 IO_PORTX_FUNC_USB2_0
7382 +
7383 +/*
7384 + * FIFO
7385 + */
7386 +#define IO_PORTX_INT_FIFO_TX_RESET (1 << 31)
7387 +#define IO_PORTX_INT_FIFO_RX_RESET (1 << 30)
7388 +#define IO_PORTX_INT_FIFO_TX_UF (1 << 15)
7389 +#define IO_PORTX_INT_FIFO_TX_WM (1 << 14)
7390 +#define IO_PORTX_INT_FIFO_RX_OF (1 << 13)
7391 +#define IO_PORTX_INT_FIFO_RX_WM (1 << 12)
7392 +
7393 +#define IO_PORTX_FUNC_FIFO_TX_WM(n) ((n) << 16)
7394 +#define IO_PORTX_FUNC_FIFO_RX_WM(n) ((n) << 0)
7395 +
7396 +/*
7397 + * MII
7398 + */
7399 +#define IO_PORTX_INT_MII_TX_ERR_SEND (1 << 18)
7400 +#define IO_PORTX_INT_MII_TX_HALT (1 << 17)
7401 +#define IO_PORTX_INT_MII_TX_START (1 << 16)
7402 +#define IO_PORTX_INT_MII_THRESHOLD (1 << 8)
7403 +#define IO_PORTX_INT_MII_RX_EOP (1 << 7)
7404 +#define IO_PORTX_INT_MII_RX_SFD (1 << 6)
7405 +#define IO_PORTX_INT_MII_RX_ERR (1 << 5)
7406 +#define IO_PORTX_INT_MII_TX_EOP (1 << 4)
7407 +#define IO_PORTX_INT_MII_COL (1 << 3)
7408 +#define IO_PORTX_INT_MII_CRS (1 << 2)
7409 +#define IO_PORTX_INT_MII_ODD_NIB_ERR (1 << 1)
7410 +#define IO_PORTX_INT_MII_FALSE_CARRIER (1 << 0)
7411 +
7412 +/*
7413 + * SerDes
7414 + */
7415 +#define IO_PORTX_INT_SERDES_TXBUF_VALID (1 << 16)
7416 +#define IO_PORTX_INT_SERDES_RXERR (1 << 7)
7417 +#define IO_PORTX_INT_SERDES_RXEOP (1 << 6)
7418 +#define IO_PORTX_INT_SERDES_SYND (1 << 5)
7419 +#define IO_PORTX_INT_SERDES_TXBE (1 << 4)
7420 +#define IO_PORTX_INT_SERDES_TXEOP (1 << 3)
7421 +#define IO_PORTX_INT_SERDES_SXLP (1 << 2)
7422 +#define IO_PORTX_INT_SERDES_RXBF (1 << 1)
7423 +#define IO_PORTX_INT_SERDES_RXCRS (1 << 0)
7424 +
7425 +#ifndef __ASSEMBLY__
7426 +struct ubicom32_io_port {
7427 +       volatile u32_t function;
7428 +       volatile u32_t gpio_ctl;
7429 +       volatile u32_t gpio_out;
7430 +       volatile u32_t gpio_in;
7431 +       volatile u32_t int_status;
7432 +       volatile u32_t int_mask;
7433 +       volatile u32_t int_set;
7434 +       volatile u32_t int_clr;
7435 +       volatile u32_t tx_fifo;
7436 +       volatile u32_t tx_fifo_hi;
7437 +       volatile u32_t rx_fifo;
7438 +       volatile u32_t rx_fifo_hi;
7439 +       volatile u32_t ctl0;
7440 +       volatile u32_t ctl1;
7441 +       volatile u32_t ctl2;
7442 +       volatile u32_t status0;
7443 +       volatile u32_t status1;
7444 +       volatile u32_t status2;
7445 +       volatile u32_t fifo_watermark;
7446 +       volatile u32_t fifo_level;
7447 +       volatile u32_t gpio_mask;
7448 +};
7449 +
7450 +#define UBICOM32_IO_PORT(port) ((struct ubicom32_io_port *)((port)))
7451 +#endif
7452 +
7453 +#ifndef __ASSEMBLY__
7454 +/*
7455 + * ubicom32_set_interrupt()
7456 + */
7457 +extern inline void ubicom32_set_interrupt(u8_t interrupt)
7458 +{
7459 +       u32_t ibit = INT_BIT_MASK(interrupt);
7460 +
7461 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7462 +               asm volatile (
7463 +                       "move.4         "D(INT_SET(INT_CHIP(0, 0)))", %0\n\t"
7464 +                       :
7465 +                       : "r" (ibit)
7466 +               );
7467 +
7468 +               return;
7469 +       }
7470 +
7471 +       asm volatile (
7472 +               "move.4         "D(INT_SET(INT_CHIP(1, 0)))", %0\n\t"
7473 +               :
7474 +               : "r" (ibit)
7475 +       );
7476 +}
7477 +
7478 +/*
7479 + * ubicom32_clear_interrupt()
7480 + */
7481 +extern inline void ubicom32_clear_interrupt(u8_t interrupt)
7482 +{
7483 +       u32_t ibit = INT_BIT_MASK(interrupt);
7484 +
7485 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7486 +               asm volatile (
7487 +                       "move.4         "D(INT_CLR(INT_CHIP(0, 0)))", %0\n\t"
7488 +                       :
7489 +                       : "r" (ibit)
7490 +               );
7491 +
7492 +               return;
7493 +       }
7494 +
7495 +       asm volatile (
7496 +               "move.4         "D(INT_CLR(INT_CHIP(1, 0)))", %0\n\t"
7497 +               :
7498 +               : "r" (ibit)
7499 +       );
7500 +}
7501 +
7502 +/*
7503 + * ubicom32_enable_interrupt()
7504 + */
7505 +extern inline void ubicom32_enable_interrupt(u8_t interrupt)
7506 +{
7507 +       u32_t ibit = INT_BIT_MASK(interrupt);
7508 +
7509 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7510 +               asm volatile (
7511 +                       "or.4           "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7512 +                       :
7513 +                       : "d" (ibit)
7514 +               );
7515 +
7516 +               return;
7517 +       }
7518 +
7519 +       asm volatile (
7520 +               "or.4           "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7521 +               :
7522 +               : "d" (ibit)
7523 +       );
7524 +}
7525 +
7526 +/*
7527 + * ubicom32_disable_interrupt()
7528 + */
7529 +extern inline void ubicom32_disable_interrupt(u8_t interrupt)
7530 +{
7531 +       u32_t ibit = ~INT_BIT_MASK(interrupt);
7532 +
7533 +       if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7534 +               asm volatile (
7535 +                       "and.4          "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7536 +                       :
7537 +                       : "d" (ibit)
7538 +               );
7539 +
7540 +               return;
7541 +       }
7542 +
7543 +       asm volatile (
7544 +               "and.4          "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7545 +               :
7546 +               : "d" (ibit)
7547 +       );
7548 +}
7549 +
7550 +/*
7551 + * ubicom32_enable_global_interrupts()
7552 + */
7553 +extern inline void ubicom32_enable_global_interrupts(void)
7554 +{
7555 +       asm volatile(
7556 +               "bset           GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7557 +       );
7558 +}
7559 +
7560 +/*
7561 + * ubicom32_disable_global_interrupts()
7562 + */
7563 +extern inline void ubicom32_disable_global_interrupts(void)
7564 +{
7565 +       asm volatile(
7566 +               "bclr           GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7567 +       );
7568 +}
7569 +
7570 +/*
7571 + * ubicom32_get_reset_reason()
7572 + */
7573 +extern inline u32_t ubicom32_get_reset_reason(void)
7574 +{
7575 +       return *(u32_t *)(GENERAL_CFG_BASE + GEN_RESET_REASON);
7576 +}
7577 +
7578 +/*
7579 + * ubicom32_read_reg()
7580 + */
7581 +extern inline u32_t ubicom32_read_reg(volatile void *reg)
7582 +{
7583 +       u32_t v;
7584 +       asm volatile (
7585 +               "move.4         %[dest], %[src] \n\t"
7586 +               : [dest] "=r" (v)
7587 +               : [src] "m" (*(u32_t *)reg)
7588 +       );
7589 +       return v;
7590 +}
7591 +
7592 +/*
7593 + * ubicom32_write_reg()
7594 + */
7595 +extern inline void ubicom32_write_reg(volatile void *reg, u32_t v)
7596 +{
7597 +       asm volatile (
7598 +               "move.4         %[dest], %[src] \n\t"
7599 +               :
7600 +               : [src] "r" (v), [dest] "m" (*(u32_t *)reg)
7601 +       );
7602 +}
7603 +
7604 +#endif /* __ASSEMBLY__ */
7605 +#endif /* _ASM_UBICOM32_IP5000_H */
7606 --- /dev/null
7607 +++ b/arch/ubicom32/include/asm/ipcbuf.h
7608 @@ -0,0 +1,55 @@
7609 +/*
7610 + * arch/ubicom32/include/asm/ipcbuf.h
7611 + *   Definition of ipc64_perm struct for Ubicom32 architecture.
7612 + *
7613 + * (C) Copyright 2009, Ubicom, Inc.
7614 + *
7615 + * This file is part of the Ubicom32 Linux Kernel Port.
7616 + *
7617 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7618 + * it and/or modify it under the terms of the GNU General Public License
7619 + * as published by the Free Software Foundation, either version 2 of the
7620 + * License, or (at your option) any later version.
7621 + *
7622 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7623 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7624 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7625 + * the GNU General Public License for more details.
7626 + *
7627 + * You should have received a copy of the GNU General Public License
7628 + * along with the Ubicom32 Linux Kernel Port.  If not,
7629 + * see <http://www.gnu.org/licenses/>.
7630 + *
7631 + * Ubicom32 implementation derived from (with many thanks):
7632 + *   arch/m68knommu
7633 + *   arch/blackfin
7634 + *   arch/parisc
7635 + */
7636 +#ifndef _ASM_UBICOM32_IPCBUF_H
7637 +#define _ASM_UBICOM32_IPCBUF_H
7638 +
7639 +/*
7640 + * The user_ipc_perm structure for m68k architecture.
7641 + * Note extra padding because this structure is passed back and forth
7642 + * between kernel and user space.
7643 + *
7644 + * Pad space is left for:
7645 + * - 32-bit mode_t and seq
7646 + * - 2 miscellaneous 32-bit values
7647 + */
7648 +struct ipc64_perm
7649 +{
7650 +       __kernel_key_t          key;
7651 +       __kernel_uid32_t        uid;
7652 +       __kernel_gid32_t        gid;
7653 +       __kernel_uid32_t        cuid;
7654 +       __kernel_gid32_t        cgid;
7655 +       __kernel_mode_t         mode;
7656 +       unsigned short          __pad1;
7657 +       unsigned short          seq;
7658 +       unsigned short          __pad2;
7659 +       unsigned long           __unused1;
7660 +       unsigned long           __unused2;
7661 +};
7662 +
7663 +#endif /* _ASM_UBICOM32_IPCBUF_H */
7664 --- /dev/null
7665 +++ b/arch/ubicom32/include/asm/irqflags.h
7666 @@ -0,0 +1,96 @@
7667 +/*
7668 + * arch/ubicom32/include/asm/irqflags.h
7669 + *   Raw implementation of local IRQ functions.
7670 + *
7671 + * (C) Copyright 2009, Ubicom, Inc.
7672 + *
7673 + * This file is part of the Ubicom32 Linux Kernel Port.
7674 + *
7675 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7676 + * it and/or modify it under the terms of the GNU General Public License
7677 + * as published by the Free Software Foundation, either version 2 of the
7678 + * License, or (at your option) any later version.
7679 + *
7680 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7681 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7682 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7683 + * the GNU General Public License for more details.
7684 + *
7685 + * You should have received a copy of the GNU General Public License
7686 + * along with the Ubicom32 Linux Kernel Port.  If not,
7687 + * see <http://www.gnu.org/licenses/>.
7688 + *
7689 + * Ubicom32 implementation derived from (with many thanks):
7690 + *   arch/m68knommu
7691 + *   arch/blackfin
7692 + *   arch/parisc
7693 + */
7694 +#ifndef _ASM_UBICOM32_IRQFLAGS_H
7695 +#define _ASM_UBICOM32_IRQFLAGS_H
7696 +
7697 +#include <linux/thread_info.h>
7698 +#include <asm/ubicom32-common.h>
7699 +#if defined(CONFIG_SMP)
7700 +#include <asm/smp.h>
7701 +#endif
7702 +#include <asm/ldsr.h>
7703 +
7704 +#if defined(CONFIG_PREEMPT)
7705 +#error Not supported by Ubicom32 irq handling, yet!
7706 +#endif
7707 +
7708 +/*
7709 + * raw_local_irq_enable()
7710 + *     Enable interrupts for this thread.
7711 + */
7712 +static inline void raw_local_irq_enable(void)
7713 +{
7714 +       ldsr_local_irq_enable();
7715 +}
7716 +
7717 +/*
7718 + * raw_local_irq_disable()
7719 + *     Disable interrupts for this thread.
7720 + */
7721 +static inline void raw_local_irq_disable(void)
7722 +{
7723 +       ldsr_local_irq_disable();
7724 +}
7725 +
7726 +/*
7727 + * raw_local_save_flags()
7728 + *     Get the current IRQ state.
7729 + */
7730 +#define raw_local_save_flags(flags)            \
7731 +do {                                           \
7732 +       (flags) = ldsr_local_irq_is_disabled(); \
7733 +} while (0)
7734 +
7735 +/*
7736 + * raw_local_irq_save()
7737 + *     Save the current interrupt state and disable interrupts.
7738 + */
7739 +#define raw_local_irq_save(flags)              \
7740 +do {                                           \
7741 +       (flags) = ldsr_local_irq_save();        \
7742 +} while (0)
7743 +
7744 +/*
7745 + * raw_local_irq_restore()
7746 + *     Restore the IRQ state back to flags.
7747 + */
7748 +static inline void raw_local_irq_restore(unsigned long flags)
7749 +{
7750 +       ldsr_local_irq_restore(flags);
7751 +}
7752 +
7753 +/*
7754 + * raw_irqs_disabled_flags()
7755 + *     Return true if the flags indicate that IRQ(s) are disabled.
7756 + */
7757 +static inline int raw_irqs_disabled_flags(unsigned long flags)
7758 +{
7759 +       return (flags);
7760 +}
7761 +
7762 +#endif /* _ASM_UBICOM32_IRQFLAGS_H */
7763 --- /dev/null
7764 +++ b/arch/ubicom32/include/asm/irq.h
7765 @@ -0,0 +1,45 @@
7766 +/*
7767 + * arch/ubicom32/include/asm/irq.h
7768 + *   IRQ definitions for Ubicom32 architecture.
7769 + *
7770 + * (C) Copyright 2009, Ubicom, Inc.
7771 + *
7772 + * This file is part of the Ubicom32 Linux Kernel Port.
7773 + *
7774 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7775 + * it and/or modify it under the terms of the GNU General Public License
7776 + * as published by the Free Software Foundation, either version 2 of the
7777 + * License, or (at your option) any later version.
7778 + *
7779 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7780 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7781 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7782 + * the GNU General Public License for more details.
7783 + *
7784 + * You should have received a copy of the GNU General Public License
7785 + * along with the Ubicom32 Linux Kernel Port.  If not,
7786 + * see <http://www.gnu.org/licenses/>.
7787 + *
7788 + * Ubicom32 implementation derived from (with many thanks):
7789 + *   arch/m68knommu
7790 + *   arch/blackfin
7791 + *   arch/parisc
7792 + */
7793 +#ifndef _ASM_UBICOM32_IRQ_H
7794 +#define _ASM_UBICOM32_IRQ_H
7795 +
7796 +#include <asm/irqflags.h>
7797 +
7798 +/*
7799 + * We setup the IRQS to cover the full range of interrupt registers in
7800 + * processor.
7801 + */
7802 +#define NR_IRQS                64
7803 +
7804 +#define irq_canonicalize(irq) (irq)
7805 +
7806 +extern int irq_soft_alloc(unsigned int *soft);
7807 +extern void ack_bad_irq(unsigned int irq);
7808 +extern void do_IRQ(int irq, struct pt_regs *fp);
7809 +
7810 +#endif /* _ASM_UBICOM32_IRQ_H */
7811 --- /dev/null
7812 +++ b/arch/ubicom32/include/asm/irq_regs.h
7813 @@ -0,0 +1,33 @@
7814 +/*
7815 + * arch/ubicom32/include/asm/irq_regs.h
7816 + *   Generic irq_regs.h for Ubicom32 architecture.
7817 + *
7818 + * (C) Copyright 2009, Ubicom, Inc.
7819 + *
7820 + * This file is part of the Ubicom32 Linux Kernel Port.
7821 + *
7822 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7823 + * it and/or modify it under the terms of the GNU General Public License
7824 + * as published by the Free Software Foundation, either version 2 of the
7825 + * License, or (at your option) any later version.
7826 + *
7827 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7828 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7829 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7830 + * the GNU General Public License for more details.
7831 + *
7832 + * You should have received a copy of the GNU General Public License
7833 + * along with the Ubicom32 Linux Kernel Port.  If not,
7834 + * see <http://www.gnu.org/licenses/>.
7835 + *
7836 + * Ubicom32 implementation derived from (with many thanks):
7837 + *   arch/m68knommu
7838 + *   arch/blackfin
7839 + *   arch/parisc
7840 + */
7841 +#ifndef _ASM_UBICOM32_IRQ_REGS_H
7842 +#define _ASM_UBICOM32_IRQ_REGS_H
7843 +
7844 +#include <asm-generic/irq_regs.h>
7845 +
7846 +#endif /* _ASM_UBICOM32_IRQ_REGS_H */
7847 --- /dev/null
7848 +++ b/arch/ubicom32/include/asm/Kbuild
7849 @@ -0,0 +1 @@
7850 +include include/asm-generic/Kbuild.asm
7851 --- /dev/null
7852 +++ b/arch/ubicom32/include/asm/kdebug.h
7853 @@ -0,0 +1,33 @@
7854 +/*
7855 + * arch/ubicom32/include/asm/kdebug.h
7856 + *   Generic kdebug.h for Ubicom32 architecture.
7857 + *
7858 + * (C) Copyright 2009, Ubicom, Inc.
7859 + *
7860 + * This file is part of the Ubicom32 Linux Kernel Port.
7861 + *
7862 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7863 + * it and/or modify it under the terms of the GNU General Public License
7864 + * as published by the Free Software Foundation, either version 2 of the
7865 + * License, or (at your option) any later version.
7866 + *
7867 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7868 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7869 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7870 + * the GNU General Public License for more details.
7871 + *
7872 + * You should have received a copy of the GNU General Public License
7873 + * along with the Ubicom32 Linux Kernel Port.  If not,
7874 + * see <http://www.gnu.org/licenses/>.
7875 + *
7876 + * Ubicom32 implementation derived from (with many thanks):
7877 + *   arch/m68knommu
7878 + *   arch/blackfin
7879 + *   arch/parisc
7880 + */
7881 +#ifndef _ASM_UBICOM32_KDEBUG_H
7882 +#define _ASM_UBICOM32_KDEBUG_H
7883 +
7884 +#include <asm-generic/kdebug.h>
7885 +
7886 +#endif /* _ASM_UBICOM32_KDEBUG_H */
7887 --- /dev/null
7888 +++ b/arch/ubicom32/include/asm/kmap_types.h
7889 @@ -0,0 +1,48 @@
7890 +/*
7891 + * arch/ubicom32/include/asm/kmap_types.h
7892 + *   Definition of km_type's for Ubicom32 architecture.
7893 + *
7894 + * (C) Copyright 2009, Ubicom, Inc.
7895 + *
7896 + * This file is part of the Ubicom32 Linux Kernel Port.
7897 + *
7898 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7899 + * it and/or modify it under the terms of the GNU General Public License
7900 + * as published by the Free Software Foundation, either version 2 of the
7901 + * License, or (at your option) any later version.
7902 + *
7903 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7904 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7905 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7906 + * the GNU General Public License for more details.
7907 + *
7908 + * You should have received a copy of the GNU General Public License
7909 + * along with the Ubicom32 Linux Kernel Port.  If not,
7910 + * see <http://www.gnu.org/licenses/>.
7911 + *
7912 + * Ubicom32 implementation derived from (with many thanks):
7913 + *   arch/m68knommu
7914 + *   arch/blackfin
7915 + *   arch/parisc
7916 + */
7917 +#ifndef _ASM_UBICOM32_KMAP_TYPES_H
7918 +#define _ASM_UBICOM32_KMAP_TYPES_H
7919 +
7920 +enum km_type {
7921 +       KM_BOUNCE_READ,
7922 +       KM_SKB_SUNRPC_DATA,
7923 +       KM_SKB_DATA_SOFTIRQ,
7924 +       KM_USER0,
7925 +       KM_USER1,
7926 +       KM_BIO_SRC_IRQ,
7927 +       KM_BIO_DST_IRQ,
7928 +       KM_PTE0,
7929 +       KM_PTE1,
7930 +       KM_IRQ0,
7931 +       KM_IRQ1,
7932 +       KM_SOFTIRQ0,
7933 +       KM_SOFTIRQ1,
7934 +       KM_TYPE_NR
7935 +};
7936 +
7937 +#endif /* _ASM_UBICOM32_KMAP_TYPES_H */
7938 --- /dev/null
7939 +++ b/arch/ubicom32/include/asm/ldsr.h
7940 @@ -0,0 +1,186 @@
7941 +/*
7942 + * arch/ubicom32/include/asm/ldsr.h
7943 + *   Ubicom32 LDSR interface definitions.
7944 + *
7945 + * (C) Copyright 2009, Ubicom, Inc.
7946 + *
7947 + * This file is part of the Ubicom32 Linux Kernel Port.
7948 + *
7949 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7950 + * it and/or modify it under the terms of the GNU General Public License
7951 + * as published by the Free Software Foundation, either version 2 of the
7952 + * License, or (at your option) any later version.
7953 + *
7954 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7955 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7956 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
7957 + * the GNU General Public License for more details.
7958 + *
7959 + * You should have received a copy of the GNU General Public License
7960 + * along with the Ubicom32 Linux Kernel Port.  If not,
7961 + * see <http://www.gnu.org/licenses/>.
7962 + *
7963 + * Ubicom32 implementation derived from (with many thanks):
7964 + *   arch/m68knommu
7965 + *   arch/blackfin
7966 + *   arch/parisc
7967 + */
7968 +#ifndef _ASM_UBICOM32_LDSR_H
7969 +#define _ASM_UBICOM32_LDSR_H
7970 +
7971 +#include <asm/ubicom32-common.h>
7972 +#include <asm/types.h>
7973 +#include <asm/thread.h>
7974 +
7975 +extern unsigned int ldsr_soft_irq_mask;
7976 +
7977 +/*
7978 + * ldsr_local_irq_is_disabled()
7979 + *     Test if interrupts are disabled for this thread?
7980 + */
7981 +static inline int ldsr_local_irq_is_disabled(void)
7982 +{
7983 +       int ret;
7984 +       thread_t self = thread_get_self();
7985 +       unsigned int mask = (1 << self);
7986 +
7987 +       asm volatile (
7988 +       "       and.4   %0, scratchpad1, %1     \n\t"
7989 +               : "=r" (ret)
7990 +               : "d" (mask)
7991 +               : "cc"
7992 +       );
7993 +
7994 +       /*
7995 +        *  We return a simple 1 == disabled, 0 == enabled
7996 +        *  losing which tid this is for, because Linux
7997 +        *  can restore interrupts on a different thread.
7998 +        */
7999 +       return ret >> self;
8000 +}
8001 +
8002 +/*
8003 + * ldsr_local_irq_save()
8004 + *     Get the current interrupt state and disable interrupts.
8005 + */
8006 +static inline unsigned int ldsr_local_irq_save(void)
8007 +{
8008 +       int ret;
8009 +       thread_t self = thread_get_self();
8010 +       unsigned int mask = (1 << self);
8011 +
8012 +       /*
8013 +        * Ensure the compiler can not optimize out the code
8014 +        * (volatile) and that it does not "cache" values around
8015 +        * the interrupt state change (memory).  This ensures
8016 +        * that interrupt changes are treated as a critical
8017 +        * section.
8018 +        */
8019 +       asm volatile (
8020 +       "       and.4   %0, scratchpad1, %1             \n\t"
8021 +       "       or.4    scratchpad1, scratchpad1, %1    \n\t"
8022 +               : "=&r" (ret)
8023 +               : "d" (mask)
8024 +               : "cc", "memory"
8025 +       );
8026 +
8027 +       /*
8028 +        *  We return a simple 1 == disabled, 0 == enabled
8029 +        *  losing which tid this is for, because Linux
8030 +        *  can restore interrupts on a different thread.
8031 +        */
8032 +       return ret >> self;
8033 +}
8034 +
8035 +/*
8036 + * ldsr_local_irq_restore()
8037 + *     Restore this cpu's interrupt enable/disable state.
8038 + *
8039 + * Note: flags is either 0 or 1.
8040 + */
8041 +static inline void ldsr_local_irq_restore(unsigned int flags)
8042 +{
8043 +       unsigned int temp;
8044 +       thread_t self = thread_get_self();
8045 +       unsigned int mask = (1 << self);
8046 +       flags = (flags << self);
8047 +
8048 +       /*
8049 +        * Ensure the compiler can not optimize out the code
8050 +        * (volatile) and that it does not "cache" values around
8051 +        * the interrupt state change (memory).  This ensures
8052 +        * that interrupt changes are treated as a critical
8053 +        * section.
8054 +        *
8055 +        * Atomic change to our bit in scratchpad1 without
8056 +        * causing any temporary glitch in the value and
8057 +        * without effecting other values.  Also this uses
8058 +        * no branches so no penalties.
8059 +        */
8060 +       asm volatile (
8061 +       "       xor.4   %0, scratchpad1, %1             \n\t"
8062 +       "       and.4   %0, %2, %0                      \n\t"
8063 +       "       xor.4   scratchpad1, scratchpad1, %0    \n\t"
8064 +       "       move.4  int_set0, %3                    \n\t"
8065 +               : "=&d"(temp)
8066 +               : "d"(flags), "r"(mask), "r"(ldsr_soft_irq_mask)
8067 +               : "cc", "memory"
8068 +       );
8069 +}
8070 +
8071 +/*
8072 + * ldsr_local_irq_disable_interrupt()
8073 + *     Disable ints for this thread.
8074 + */
8075 +static inline void ldsr_local_irq_disable(void)
8076 +{
8077 +       unsigned int mask = (1 << thread_get_self());
8078 +
8079 +       /*
8080 +        * Ensure the compiler can not optimize out the code
8081 +        * (volatile) and that it does not "cache" values around
8082 +        * the interrupt state change (memory).  This ensures
8083 +        * that interrupt changes are treated as a critical
8084 +        * section.
8085 +        */
8086 +       asm  volatile (
8087 +       "       or.4    scratchpad1, scratchpad1, %0    \n\t"
8088 +               :
8089 +               : "d" (mask)
8090 +               : "cc", "memory"
8091 +       );
8092 +}
8093 +
8094 +/*
8095 + * ldsr_local_irq_enable_interrupt
8096 + *     Enable ints for this thread.
8097 + */
8098 +static inline void ldsr_local_irq_enable(void)
8099 +{
8100 +       unsigned int mask = (1 << thread_get_self());
8101 +
8102 +       /*
8103 +        * Ensure the compiler can not optimize out the code
8104 +        * (volatile) and that it does not "cache" values around
8105 +        * the interrupt state change (memory).  This ensures
8106 +        * that interrupt changes are treated as a critical
8107 +        * section.
8108 +        */
8109 +       asm volatile (
8110 +       "       and.4   scratchpad1, scratchpad1, %0    \n\t"
8111 +       "       move.4  int_set0, %1                    \n\t"
8112 +               :
8113 +               : "d" (~mask), "r" (ldsr_soft_irq_mask)
8114 +               : "cc", "memory"
8115 +       );
8116 +}
8117 +
8118 +extern void ldsr_init(void);
8119 +extern void ldsr_set_trap_irq(unsigned int irq);
8120 +extern void ldsr_mask_vector(unsigned int vector);
8121 +extern void ldsr_unmask_vector(unsigned int vector);
8122 +extern void ldsr_enable_vector(unsigned int vector);
8123 +extern void ldsr_disable_vector(unsigned int vector);
8124 +extern thread_t ldsr_get_threadid(void);
8125 +
8126 +#endif /* _ASM_UBICOM32_LDSR_H */
8127 --- /dev/null
8128 +++ b/arch/ubicom32/include/asm/linkage.h
8129 @@ -0,0 +1,34 @@
8130 +/*
8131 + * arch/ubicom32/include/asm/linkage.h
8132 + *   Definition of Ubicom32 architecture specific linkage types.
8133 + *
8134 + * (C) Copyright 2009, Ubicom, Inc.
8135 + *
8136 + * This file is part of the Ubicom32 Linux Kernel Port.
8137 + *
8138 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8139 + * it and/or modify it under the terms of the GNU General Public License
8140 + * as published by the Free Software Foundation, either version 2 of the
8141 + * License, or (at your option) any later version.
8142 + *
8143 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8144 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8145 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8146 + * the GNU General Public License for more details.
8147 + *
8148 + * You should have received a copy of the GNU General Public License
8149 + * along with the Ubicom32 Linux Kernel Port.  If not,
8150 + * see <http://www.gnu.org/licenses/>.
8151 + *
8152 + * Ubicom32 implementation derived from (with many thanks):
8153 + *   arch/m68knommu
8154 + *   arch/blackfin
8155 + *   arch/parisc
8156 + */
8157 +#ifndef _ASM_UBICOM32_LINKAGE_H
8158 +#define _ASM_UBICOM32_LINKAGE_H
8159 +
8160 +#define __ocm_text __section(.ocm_text)
8161 +#define __ocm_data __section(.ocm_data)
8162 +
8163 +#endif /* _ASM_UBICOM32_LINKAGE_H */
8164 --- /dev/null
8165 +++ b/arch/ubicom32/include/asm/local.h
8166 @@ -0,0 +1,33 @@
8167 +/*
8168 + * arch/ubicom32/include/asm/local.h
8169 + *   Generic local.h for Ubicom32 architecture.
8170 + *
8171 + * (C) Copyright 2009, Ubicom, Inc.
8172 + *
8173 + * This file is part of the Ubicom32 Linux Kernel Port.
8174 + *
8175 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8176 + * it and/or modify it under the terms of the GNU General Public License
8177 + * as published by the Free Software Foundation, either version 2 of the
8178 + * License, or (at your option) any later version.
8179 + *
8180 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8181 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8182 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8183 + * the GNU General Public License for more details.
8184 + *
8185 + * You should have received a copy of the GNU General Public License
8186 + * along with the Ubicom32 Linux Kernel Port.  If not,
8187 + * see <http://www.gnu.org/licenses/>.
8188 + *
8189 + * Ubicom32 implementation derived from (with many thanks):
8190 + *   arch/m68knommu
8191 + *   arch/blackfin
8192 + *   arch/parisc
8193 + */
8194 +#ifndef _ASM_UBICOM32_LOCAL_H
8195 +#define _ASM_UBICOM32_LOCAL_H
8196 +
8197 +#include <asm-generic/local.h>
8198 +
8199 +#endif /* _ASM_UBICOM32_LOCAL_H */
8200 --- /dev/null
8201 +++ b/arch/ubicom32/include/asm/machdep.h
8202 @@ -0,0 +1,43 @@
8203 +/*
8204 + * arch/ubicom32/include/asm/machdep.h
8205 + *   Machine dependent utility routines.
8206 + *
8207 + * (C) Copyright 2009, Ubicom, Inc.
8208 + *
8209 + * This file is part of the Ubicom32 Linux Kernel Port.
8210 + *
8211 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8212 + * it and/or modify it under the terms of the GNU General Public License
8213 + * as published by the Free Software Foundation, either version 2 of the
8214 + * License, or (at your option) any later version.
8215 + *
8216 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8217 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8218 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8219 + * the GNU General Public License for more details.
8220 + *
8221 + * You should have received a copy of the GNU General Public License
8222 + * along with the Ubicom32 Linux Kernel Port.  If not,
8223 + * see <http://www.gnu.org/licenses/>.
8224 + *
8225 + * Ubicom32 implementation derived from (with many thanks):
8226 + *   arch/m68knommu
8227 + *   arch/blackfin
8228 + *   arch/parisc
8229 + */
8230 +#ifndef _ASM_UBICOM32_MACHDEP_H
8231 +#define _ASM_UBICOM32_MACHDEP_H
8232 +
8233 +#include <linux/interrupt.h>
8234 +
8235 +/* Hardware clock functions */
8236 +extern unsigned long hw_timer_offset(void);
8237 +
8238 +/* machine dependent power off functions */
8239 +extern void (*mach_reset)(void);
8240 +extern void (*mach_halt)(void);
8241 +extern void (*mach_power_off)(void);
8242 +
8243 +extern void config_BSP(char *command, int len);
8244 +
8245 +#endif /* _ASM_UBICOM32_MACHDEP_H */
8246 --- /dev/null
8247 +++ b/arch/ubicom32/include/asm/mc146818rtc.h
8248 @@ -0,0 +1,36 @@
8249 +/*
8250 + * arch/ubicom32/include/asm/mc146818rtc.h
8251 + *   Generic mc146818rtc.h for Ubicom32 architecture.
8252 + *
8253 + * (C) Copyright 2009, Ubicom, Inc.
8254 + *
8255 + * This file is part of the Ubicom32 Linux Kernel Port.
8256 + *
8257 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8258 + * it and/or modify it under the terms of the GNU General Public License
8259 + * as published by the Free Software Foundation, either version 2 of the
8260 + * License, or (at your option) any later version.
8261 + *
8262 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8263 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8264 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8265 + * the GNU General Public License for more details.
8266 + *
8267 + * You should have received a copy of the GNU General Public License
8268 + * along with the Ubicom32 Linux Kernel Port.  If not,
8269 + * see <http://www.gnu.org/licenses/>.
8270 + *
8271 + * Ubicom32 implementation derived from (with many thanks):
8272 + *   arch/m68knommu
8273 + *   arch/blackfin
8274 + *   arch/parisc
8275 + */
8276 +/*
8277 + * Machine dependent access functions for RTC registers.
8278 + */
8279 +#ifndef _ASM_UBICOM32_MC146818RTC_H
8280 +#define _ASM_UBICOM32_MC146818RTC_H
8281 +
8282 +/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
8283 +
8284 +#endif /* _ASM_UBICOM32_MC146818RTC_H */
8285 --- /dev/null
8286 +++ b/arch/ubicom32/include/asm/memory_map.h
8287 @@ -0,0 +1,66 @@
8288 +/*
8289 + * arch/ubicom32/include/asm/memory_map.h
8290 + *   Machine memory maps/
8291 + *
8292 + * (C) Copyright 2009, Ubicom, Inc.
8293 + *
8294 + * This file is part of the Ubicom32 Linux Kernel Port.
8295 + *
8296 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8297 + * it and/or modify it under the terms of the GNU General Public License
8298 + * as published by the Free Software Foundation, either version 2 of the
8299 + * License, or (at your option) any later version.
8300 + *
8301 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8302 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8303 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8304 + * the GNU General Public License for more details.
8305 + *
8306 + * You should have received a copy of the GNU General Public License
8307 + * along with the Ubicom32 Linux Kernel Port.  If not,
8308 + * see <http://www.gnu.org/licenses/>.
8309 + *
8310 + * Ubicom32 implementation derived from (with many thanks):
8311 + *   arch/m68knommu
8312 + *   arch/blackfin
8313 + *   arch/parisc
8314 + */
8315 +#ifndef _ASM_UBICOM32_MEMORY_MAP_H
8316 +#define _ASM_UBICOM32_MEMORY_MAP_H
8317 +
8318 +/*
8319 + * Memory Size
8320 + */
8321 +#define OCM_SECTOR_SIZE        0x00008000              /* 32K */
8322 +
8323 +#if defined(CONFIG_UBICOM32_V3)
8324 +#define OCMSIZE        0x00030000      /* 192K on-chip RAM for both program and data */
8325 +#elif defined(CONFIG_UBICOM32_V4)
8326 +#define OCMSIZE        0x0003C000      /* 240K on-chip RAM for both program and data */
8327 +#else
8328 +#error "Unknown IP5K silicon"
8329 +#endif
8330 +
8331 +#define OCMSTART       0x3ffc0000 /* alias from 0x03000000 for easy
8332 +                                   * jump to/from SDRAM */
8333 +#define OCMEND         (OCMSTART + OCMSIZE)
8334 +
8335 +#define SDRAMSTART     0x40000000
8336 +
8337 +#define KERNELSTART    (SDRAMSTART + 0x00400000)
8338 +
8339 +#define FLASHSTART     0x60000000
8340 +
8341 +/*
8342 + * CODELOADER / OS_SYSCALL OCM Reservations
8343 + * Don't change these unless you know what you are doing.
8344 + */
8345 +#define CODELOADER_SIZE  0x30
8346 +#define CODELOADER_BEGIN OCMSTART /* Must be OCM start for gdb to work. */
8347 +#define CODELOADER_END  (CODELOADER_BEGIN + CODELOADER_SIZE)
8348 +
8349 +#define OS_SYSCALL_BEGIN CODELOADER_END        /* system_call at this address */
8350 +#define OS_SYSCALL_SIZE  (512 - CODELOADER_SIZE)
8351 +#define OS_SYSCALL_END  (OS_SYSCALL_BEGIN + OS_SYSCALL_SIZE)
8352 +
8353 +#endif /* _ASM_UBICOM32_MEMORY_MAP_H */
8354 --- /dev/null
8355 +++ b/arch/ubicom32/include/asm/mman.h
8356 @@ -0,0 +1,44 @@
8357 +/*
8358 + * arch/ubicom32/include/asm/mman.h
8359 + *   Memory mapping definitions for Ubicom32 architecture.
8360 + *
8361 + * (C) Copyright 2009, Ubicom, Inc.
8362 + *
8363 + * This file is part of the Ubicom32 Linux Kernel Port.
8364 + *
8365 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8366 + * it and/or modify it under the terms of the GNU General Public License
8367 + * as published by the Free Software Foundation, either version 2 of the
8368 + * License, or (at your option) any later version.
8369 + *
8370 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8371 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8372 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8373 + * the GNU General Public License for more details.
8374 + *
8375 + * You should have received a copy of the GNU General Public License
8376 + * along with the Ubicom32 Linux Kernel Port.  If not,
8377 + * see <http://www.gnu.org/licenses/>.
8378 + *
8379 + * Ubicom32 implementation derived from (with many thanks):
8380 + *   arch/m68knommu
8381 + *   arch/blackfin
8382 + *   arch/parisc
8383 + */
8384 +#ifndef _ASM_UBICOM32_MMAN_H
8385 +#define _ASM_UBICOM32_MMAN_H
8386 +
8387 +#include <asm-generic/mman.h>
8388 +
8389 +#define MAP_GROWSDOWN  0x0100          /* stack-like segment */
8390 +#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
8391 +#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
8392 +#define MAP_LOCKED     0x2000          /* pages are locked */
8393 +#define MAP_NORESERVE  0x4000          /* don't check for reservations */
8394 +#define MAP_POPULATE   0x8000          /* populate (prefault) pagetables */
8395 +#define MAP_NONBLOCK   0x10000         /* do not block on IO */
8396 +
8397 +#define MCL_CURRENT    1               /* lock all current mappings */
8398 +#define MCL_FUTURE     2               /* lock all future mappings */
8399 +
8400 +#endif /* _ASM_UBICOM32_MMAN_H */
8401 --- /dev/null
8402 +++ b/arch/ubicom32/include/asm/mmu_context.h
8403 @@ -0,0 +1,60 @@
8404 +/*
8405 + * arch/ubicom32/include/asm/mmu_context.h
8406 + *   MMU context definitions for Ubicom32 architecture.
8407 + *
8408 + * (C) Copyright 2009, Ubicom, Inc.
8409 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
8410 + *
8411 + * This file is part of the Ubicom32 Linux Kernel Port.
8412 + *
8413 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8414 + * it and/or modify it under the terms of the GNU General Public License
8415 + * as published by the Free Software Foundation, either version 2 of the
8416 + * License, or (at your option) any later version.
8417 + *
8418 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8419 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8420 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8421 + * the GNU General Public License for more details.
8422 + *
8423 + * You should have received a copy of the GNU General Public License
8424 + * along with the Ubicom32 Linux Kernel Port.  If not,
8425 + * see <http://www.gnu.org/licenses/>.
8426 + *
8427 + * Ubicom32 implementation derived from (with many thanks):
8428 + *   arch/m68knommu
8429 + *   arch/blackfin
8430 + *   arch/parisc
8431 + */
8432 +
8433 +#ifndef _ASM_UBICOM32_MMU_CONTEXT_H
8434 +#define _ASM_UBICOM32_MMU_CONTEXT_H
8435 +
8436 +#include <asm/setup.h>
8437 +#include <asm/page.h>
8438 +#include <asm/pgalloc.h>
8439 +
8440 +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
8441 +{
8442 +}
8443 +
8444 +extern inline int
8445 +init_new_context(struct task_struct *tsk, struct mm_struct *mm)
8446 +{
8447 +       // mm->context = virt_to_phys(mm->pgd);
8448 +       return(0);
8449 +}
8450 +
8451 +#define destroy_context(mm)            do { } while(0)
8452 +
8453 +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
8454 +{
8455 +}
8456 +
8457 +#define deactivate_mm(tsk,mm)  do { } while (0)
8458 +
8459 +extern inline void activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm)
8460 +{
8461 +}
8462 +
8463 +#endif /* _ASM_UBICOM32_MMU_CONTEXT_H */
8464 --- /dev/null
8465 +++ b/arch/ubicom32/include/asm/mmu.h
8466 @@ -0,0 +1,41 @@
8467 +/*
8468 + * arch/ubicom32/include/asm/mmu.h
8469 + *   Definition of mm_context_t struct for Ubicom32 architecture.
8470 + *
8471 + * (C) Copyright 2009, Ubicom, Inc.
8472 + * Copyright (C) 2002, David McCullough <davidm@snapgear.com>
8473 + *
8474 + * This file is part of the Ubicom32 Linux Kernel Port.
8475 + *
8476 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8477 + * it and/or modify it under the terms of the GNU General Public License
8478 + * as published by the Free Software Foundation, either version 2 of the
8479 + * License, or (at your option) any later version.
8480 + *
8481 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8482 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8483 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8484 + * the GNU General Public License for more details.
8485 + *
8486 + * You should have received a copy of the GNU General Public License
8487 + * along with the Ubicom32 Linux Kernel Port.  If not,
8488 + * see <http://www.gnu.org/licenses/>.
8489 + *
8490 + * Ubicom32 implementation derived from (with many thanks):
8491 + *   arch/m68knommu
8492 + *   arch/blackfin
8493 + *   arch/parisc
8494 + */
8495 +#ifndef _ASM_UBICOM32_MMU_H
8496 +#define _ASM_UBICOM32_MMU_H
8497 +
8498 +typedef struct {
8499 +       struct vm_list_struct   *vmlist;
8500 +       unsigned long           end_brk;
8501 +#ifdef CONFIG_BINFMT_ELF_FDPIC
8502 +       unsigned long   exec_fdpic_loadmap;
8503 +       unsigned long   interp_fdpic_loadmap;
8504 +#endif
8505 +} mm_context_t;
8506 +
8507 +#endif /* _ASM_UBICOM32_MMU_H */
8508 --- /dev/null
8509 +++ b/arch/ubicom32/include/asm/module.h
8510 @@ -0,0 +1,48 @@
8511 +/*
8512 + * arch/ubicom32/include/asm/module.h
8513 + *   Ubicom32 architecture specific module definitions.
8514 + *
8515 + * (C) Copyright 2009, Ubicom, Inc.
8516 + *
8517 + * This file is part of the Ubicom32 Linux Kernel Port.
8518 + *
8519 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8520 + * it and/or modify it under the terms of the GNU General Public License
8521 + * as published by the Free Software Foundation, either version 2 of the
8522 + * License, or (at your option) any later version.
8523 + *
8524 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8525 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8526 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8527 + * the GNU General Public License for more details.
8528 + *
8529 + * You should have received a copy of the GNU General Public License
8530 + * along with the Ubicom32 Linux Kernel Port.  If not,
8531 + * see <http://www.gnu.org/licenses/>.
8532 + *
8533 + * Ubicom32 implementation derived from (with many thanks):
8534 + *   arch/m68knommu
8535 + *   arch/blackfin
8536 + *   arch/parisc
8537 + */
8538 +#ifndef _ASM_UBICOM32_MODULE_H
8539 +#define _ASM_UBICOM32_MODULE_H
8540 +
8541 +struct mod_arch_specific {
8542 +       void *ocm_inst;
8543 +       int ocm_inst_size;
8544 +};
8545 +
8546 +#define Elf_Shdr Elf32_Shdr
8547 +#define Elf_Sym Elf32_Sym
8548 +#define Elf_Ehdr Elf32_Ehdr
8549 +
8550 +#define ARCH_PROC_MODULES_EXTRA(m,mod) \
8551 +       seq_printf(m, " OCM(%d bytes @ 0x%p)", \
8552 +                  (mod)->arch.ocm_inst_size, (mod)->arch.ocm_inst)
8553 +
8554 +#define ARCH_OOPS_MODULE_EXTRA(mod) \
8555 +       printk(KERN_INFO "%p %u OCM(%p %u)\n", \
8556 +               (mod)->module_core, (mod)->core_size, \
8557 +               (mod)->arch.ocm_inst, (mod)->arch.ocm_inst_size)
8558 +#endif /* _ASM_UBICOM32_MODULE_H */
8559 --- /dev/null
8560 +++ b/arch/ubicom32/include/asm/msgbuf.h
8561 @@ -0,0 +1,58 @@
8562 +/*
8563 + * arch/ubicom32/include/asm/msgbuf.h
8564 + *   Definition of msqid64_ds struct for Ubicom32 architecture.
8565 + *
8566 + * (C) Copyright 2009, Ubicom, Inc.
8567 + *
8568 + * This file is part of the Ubicom32 Linux Kernel Port.
8569 + *
8570 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8571 + * it and/or modify it under the terms of the GNU General Public License
8572 + * as published by the Free Software Foundation, either version 2 of the
8573 + * License, or (at your option) any later version.
8574 + *
8575 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8576 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8577 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8578 + * the GNU General Public License for more details.
8579 + *
8580 + * You should have received a copy of the GNU General Public License
8581 + * along with the Ubicom32 Linux Kernel Port.  If not,
8582 + * see <http://www.gnu.org/licenses/>.
8583 + *
8584 + * Ubicom32 implementation derived from (with many thanks):
8585 + *   arch/m68knommu
8586 + *   arch/blackfin
8587 + *   arch/parisc
8588 + */
8589 +#ifndef _ASM_UBICOM32_MSGBUF_H
8590 +#define _ASM_UBICOM32_MSGBUF_H
8591 +
8592 +/*
8593 + * The msqid64_ds structure for ubicom32 architecture.
8594 + * Note extra padding because this structure is passed back and forth
8595 + * between kernel and user space.
8596 + *
8597 + * Pad space is left for:
8598 + * - 64-bit time_t to solve y2038 problem
8599 + * - 2 miscellaneous 32-bit values
8600 + */
8601 +
8602 +struct msqid64_ds {
8603 +       struct ipc64_perm msg_perm;
8604 +       __kernel_time_t msg_stime;      /* last msgsnd time */
8605 +       unsigned long   __unused1;
8606 +       __kernel_time_t msg_rtime;      /* last msgrcv time */
8607 +       unsigned long   __unused2;
8608 +       __kernel_time_t msg_ctime;      /* last change time */
8609 +       unsigned long   __unused3;
8610 +       unsigned long  msg_cbytes;      /* current number of bytes on queue */
8611 +       unsigned long  msg_qnum;        /* number of messages in queue */
8612 +       unsigned long  msg_qbytes;      /* max number of bytes on queue */
8613 +       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
8614 +       __kernel_pid_t msg_lrpid;       /* last receive pid */
8615 +       unsigned long  __unused4;
8616 +       unsigned long  __unused5;
8617 +};
8618 +
8619 +#endif /* _ASM_UBICOM32_MSGBUF_H */
8620 --- /dev/null
8621 +++ b/arch/ubicom32/include/asm/mutex.h
8622 @@ -0,0 +1,41 @@
8623 +/*
8624 + * arch/ubicom32/include/asm/mutex.h
8625 + *   Generic mutex.h for Ubicom32 architecture.
8626 + *
8627 + * (C) Copyright 2009, Ubicom, Inc.
8628 + *
8629 + * This file is part of the Ubicom32 Linux Kernel Port.
8630 + *
8631 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8632 + * it and/or modify it under the terms of the GNU General Public License
8633 + * as published by the Free Software Foundation, either version 2 of the
8634 + * License, or (at your option) any later version.
8635 + *
8636 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8637 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8638 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8639 + * the GNU General Public License for more details.
8640 + *
8641 + * You should have received a copy of the GNU General Public License
8642 + * along with the Ubicom32 Linux Kernel Port.  If not,
8643 + * see <http://www.gnu.org/licenses/>.
8644 + *
8645 + * Ubicom32 implementation derived from (with many thanks):
8646 + *   arch/m68knommu
8647 + *   arch/blackfin
8648 + *   arch/parisc
8649 + */
8650 +/*
8651 + * Pull in the generic implementation for the mutex fastpath.
8652 + *
8653 + * TODO: implement optimized primitives instead, or leave the generic
8654 + * implementation in place, or pick the atomic_xchg() based generic
8655 + * implementation. (see asm-generic/mutex-xchg.h for details)
8656 + */
8657 +
8658 +#ifndef _ASM_UBICOM32_MUTEX_H
8659 +#define _ASM_UBICOM32_MUTEX_H
8660 +
8661 +#include <asm-generic/mutex-dec.h>
8662 +
8663 +#endif /* _ASM_UBICOM32_MUTEX_H */
8664 --- /dev/null
8665 +++ b/arch/ubicom32/include/asm/namei.h
8666 @@ -0,0 +1,38 @@
8667 +/*
8668 + * arch/ubicom32/include/asm/namei.h
8669 + *   Definition of __emul_prefix() for Ubicom32 architecture.
8670 + *
8671 + * (C) Copyright 2009, Ubicom, Inc.
8672 + *
8673 + * This file is part of the Ubicom32 Linux Kernel Port.
8674 + *
8675 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8676 + * it and/or modify it under the terms of the GNU General Public License
8677 + * as published by the Free Software Foundation, either version 2 of the
8678 + * License, or (at your option) any later version.
8679 + *
8680 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8681 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8682 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8683 + * the GNU General Public License for more details.
8684 + *
8685 + * You should have received a copy of the GNU General Public License
8686 + * along with the Ubicom32 Linux Kernel Port.  If not,
8687 + * see <http://www.gnu.org/licenses/>.
8688 + *
8689 + * Ubicom32 implementation derived from (with many thanks):
8690 + *   arch/m68knommu
8691 + *   arch/blackfin
8692 + *   arch/parisc
8693 + */
8694 +#ifndef _ASM_UBICOM32_NAMEI_H
8695 +#define _ASM_UBICOM32_NAMEI_H
8696 +
8697 +/* This dummy routine maybe changed to something useful
8698 + * for /usr/gnemul/ emulation stuff.
8699 + * Look at asm-sparc/namei.h for details.
8700 + */
8701 +
8702 +#define __emul_prefix() NULL
8703 +
8704 +#endif /* _ASM_UBICOM32_NAMEI_H */
8705 --- /dev/null
8706 +++ b/arch/ubicom32/include/asm/ocm-alloc.h
8707 @@ -0,0 +1,36 @@
8708 +/*
8709 + * arch/ubicom32/include/asm/ocm-alloc.h
8710 + *   Ubicom32 architecture specific ocm definitions.
8711 + *
8712 + * (C) Copyright 2009, Ubicom, Inc.
8713 + *
8714 + * This file is part of the Ubicom32 Linux Kernel Port.
8715 + *
8716 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8717 + * it and/or modify it under the terms of the GNU General Public License
8718 + * as published by the Free Software Foundation, either version 2 of the
8719 + * License, or (at your option) any later version.
8720 + *
8721 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8722 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8723 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8724 + * the GNU General Public License for more details.
8725 + *
8726 + * You should have received a copy of the GNU General Public License
8727 + * along with the Ubicom32 Linux Kernel Port.  If not,
8728 + * see <http://www.gnu.org/licenses/>.
8729 + *
8730 + * Ubicom32 implementation derived from (with many thanks):
8731 + *   arch/m68knommu
8732 + *   arch/blackfin
8733 + *   arch/parisc
8734 + */
8735 +#ifndef _ASM_UBICOM32_OCM_ALLOC_H
8736 +#define _ASM_UBICOM32_OCM_ALLOC_H
8737 +
8738 +
8739 +extern void *ocm_inst_alloc(size_t size, pid_t pid);
8740 +extern int ocm_free(const void *ptr);
8741 +extern int ocm_inst_free(const void *ptr);
8742 +
8743 +#endif /* _ASM_UBICOM32_OCM_ALLOC_H */
8744 --- /dev/null
8745 +++ b/arch/ubicom32/include/asm/ocm_size.h
8746 @@ -0,0 +1,3 @@
8747 +#define APP_OCM_CODE_SIZE (0x3ffc2e00-0x3ffc0000)
8748 +#define APP_OCM_DATA_SIZE (0x3ffd3500-0x3ffc8000)
8749 +
8750 --- /dev/null
8751 +++ b/arch/ubicom32/include/asm/ocm_text.lds.inc
8752 @@ -0,0 +1,175 @@
8753 +/*
8754 + * arch/ubicom32/include/asm/ocm_text.lds.inc
8755 + *     <TODO: Replace with short file description>
8756 + *
8757 + * (C) Copyright 2009, Ubicom, Inc.
8758 + *
8759 + * This file is part of the Ubicom32 Linux Kernel Port.
8760 + *
8761 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8762 + * it and/or modify it under the terms of the GNU General Public License
8763 + * as published by the Free Software Foundation, either version 2 of the
8764 + * License, or (at your option) any later version.
8765 + *
8766 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8767 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8768 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8769 + * the GNU General Public License for more details.
8770 + *
8771 + * You should have received a copy of the GNU General Public License
8772 + * along with the Ubicom32 Linux Kernel Port.  If not,
8773 + * see <http://www.gnu.org/licenses/>.
8774 + *
8775 + * Ubicom32 implementation derived from (with many thanks):
8776 + *   arch/m68knommu
8777 + *   arch/blackfin
8778 + *   arch/parisc
8779 + */
8780 +*(.text.do_csum)
8781 +*(.text.tcp_packet)
8782 +*(.text.ipt_do_table)
8783 +*(.text.nf_conntrack_in)
8784 +*(.text.ip_forward)
8785 +*(.text.dev_queue_xmit)
8786 +*(.text.netif_receive_skb)
8787 +*(.text.ip_route_input)
8788 +*(.text.ip_finish_output)
8789 +*(.text.nf_iterate)
8790 +*(.text.__hash_conntrack)
8791 +*(.text.memset)
8792 +*(.text.memcpy)
8793 +*(.text.ip_rcv)
8794 +*(.text.__nf_conntrack_find)
8795 +*(.text.dev_hard_start_xmit)
8796 +*(.text.vlan_dev_hard_start_xmit)
8797 +*(.text.vlan_dev_hard_header)
8798 +*(.text.__nf_ct_refresh_acct)
8799 +*(.text.tcp_error)
8800 +*(.text.pfifo_fast_enqueue)
8801 +*(.text.ipv4_confirm)
8802 +*(.text.ip_output)
8803 +*(.text.neigh_connected_output)
8804 +*(.text.nf_hook_slow)
8805 +*(.text.nf_nat_packet)
8806 +*(.text.local_bh_enable)
8807 +*(.text.pfifo_fast_dequeue)
8808 +*(.text.ubi32_eth_receive)
8809 +*(.text.nf_nat_fn)
8810 +*(.text.skb_checksum)
8811 +*(.text.memmove)
8812 +*(.text.ubi32_eth_tx_done)
8813 +*(.text.eth_header)
8814 +*(.text.skb_release_data)
8815 +*(.text.nf_conntrack_find_get)
8816 +*(.text.process_backlog)
8817 +*(.text.vlan_skb_recv)
8818 +*(.text.ip_rcv_finish)
8819 +*(.text.__qdisc_run)
8820 +*(.text.skb_push)
8821 +*(.text.eth_type_trans)
8822 +*(.text.__alloc_skb)
8823 +*(.text.netif_rx)
8824 +*(.text.nf_ip_checksum)
8825 +*(.text.__skb_checksum_complete_head)
8826 +*(.text.ipv4_conntrack_defrag)
8827 +*(.text.tcp_pkt_to_tuple)
8828 +*(.text.kfree)
8829 +*(.text.tcp_manip_pkt)
8830 +*(.text.skb_put)
8831 +*(.text.nf_ct_get_tuple)
8832 +*(.text.__kmalloc)
8833 +*(.text.ubi32_eth_start_xmit)
8834 +*(.text.free_block)
8835 +*(.text.ipt_hook)
8836 +*(.text.kmem_cache_free)
8837 +*(.text.skb_pull_rcsum)
8838 +*(.text.cache_alloc_refill)
8839 +*(.text.skb_release_head_state)
8840 +*(.text.manip_pkt)
8841 +*(.text.ip_sabotage_in)
8842 +*(.text.ip_forward_finish)
8843 +*(.text.kmem_cache_alloc)
8844 +*(.text.local_bh_disable)
8845 +*(.text.ipv4_pkt_to_tuple)
8846 +*(.text.inet_proto_csum_replace4)
8847 +*(.text.__nf_ct_l4proto_find)
8848 +*(.text.csum_partial)
8849 +*(.text.neigh_resolve_output)
8850 +*(.text.__kfree_skb)
8851 +*(.text.kfree_skb)
8852 +*(.text.__find_vlan_dev)
8853 +*(.text.ldsr_ctxsw_thread)
8854 +*(.text.__do_IRQ)
8855 +*(.text.skb_pull)
8856 +*(.text.ipv4_invert_tuple)
8857 +*(.text.nf_ct_invert_tuplepr)
8858 +*(.text.skb_make_writable)
8859 +*(.text.ipv4_get_l4proto)
8860 +*(.text.handle_IRQ_event)
8861 +*(.text.net_rx_action)
8862 +*(.text.__do_softirq)
8863 +*(.text.nf_nat_in)
8864 +*(.text.note_interrupt)
8865 +*(.text.ipv4_conntrack_in)
8866 +*(.text.dst_release)
8867 +*(.text.tasklet_action)
8868 +*(.text.nf_nat_out)
8869 +*(.text.nf_ct_invert_tuple)
8870 +*(.text.do_IRQ)
8871 +*(.text.__tasklet_schedule)
8872 +*(.text.__skb_checksum_complete)
8873 +*(.text.ubi32_eth_interrupt)
8874 +*(.text.dev_kfree_skb_any)
8875 +*(.text.ret_from_interrupt_to_kernel)
8876 +*(.text.preemptive_context_save)
8877 +*(.text.irq_ack_vector)
8878 +*(.text.update_wall_time)
8879 +*(.text.ldsr_thread)
8880 +*(.text.irq_exit)
8881 +*(.text.ubi32_eth_do_tasklet)
8882 +*(.text.__napi_schedule)
8883 +*(.text.idle_cpu)
8884 +*(.text.run_timer_softirq)
8885 +*(.text.ldsr_mask_vector)
8886 +*(.text.irq_enter)
8887 +*(.text.ldsr_get_lsb)
8888 +*(.text.ldsr_unmask_vector)
8889 +*(.text.ip_fast_csum)
8890 +*(.text.hrtimer_run_queues)
8891 +*(.text.tcp_invert_tuple)
8892 +*(.text.T___705)
8893 +*(.text.run_posix_cpu_timers)
8894 +*(.text.free_hot_cold_page)
8895 +*(.text.lock_timer_base)
8896 +*(.text.calc_delta_mine)
8897 +*(.text.slab_destroy)
8898 +*(.text.rcu_pending)
8899 +*(.text.scheduler_tick)
8900 +*(.text.hrtimer_run_pending)
8901 +*(.text.do_softirq)
8902 +*(.text.del_timer)
8903 +*(.text.irq_end_vector)
8904 +*(.text.pci_read_u32)
8905 +*(.text.udivmodsi4)
8906 +*(.text.memcmp)
8907 +*(.text.memset)
8908 +*(.text.__slab_alloc)
8909 +*(.text.br_handle_frame)
8910 +*(.text.br_fdb_update)
8911 +*(.text.__br_fdb_get)
8912 +*(.text.br_forward)
8913 +*(.text.br_handle_frame_finish)
8914 +*(.text.pci_write_u32)
8915 +*(.text.kmem_freepages)
8916 +*(.text.br_dev_queue_push_xmit)
8917 +*(.text.ioread32)
8918 +*(.text.next_zones_zonelist)
8919 +*(.text.ubi32_pci_read_u32)
8920 +*(.text.zone_watermark_ok)
8921 +*(.text.__rmqueue_smallest)
8922 +*(.text.ubi32_eth_napi_poll)
8923 +*(.text.ubi32_pci_write_u32)
8924 +*(.text.ubi32_pci_read_u32)
8925 +*(.text._local_bh_enable)
8926 +*(.text._local_bh_disable)
8927 +*(.text.get_slab)
8928 --- /dev/null
8929 +++ b/arch/ubicom32/include/asm/page.h
8930 @@ -0,0 +1,106 @@
8931 +/*
8932 + * arch/ubicom32/include/asm/page.h
8933 + *   Memory page related operations and definitions.
8934 + *
8935 + * (C) Copyright 2009, Ubicom, Inc.
8936 + *
8937 + * This file is part of the Ubicom32 Linux Kernel Port.
8938 + *
8939 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8940 + * it and/or modify it under the terms of the GNU General Public License
8941 + * as published by the Free Software Foundation, either version 2 of the
8942 + * License, or (at your option) any later version.
8943 + *
8944 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8945 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8946 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
8947 + * the GNU General Public License for more details.
8948 + *
8949 + * You should have received a copy of the GNU General Public License
8950 + * along with the Ubicom32 Linux Kernel Port.  If not,
8951 + * see <http://www.gnu.org/licenses/>.
8952 + *
8953 + * Ubicom32 implementation derived from (with many thanks):
8954 + *   arch/m68knommu
8955 + *   arch/blackfin
8956 + *   arch/parisc
8957 + */
8958 +#ifndef _ASM_UBICOM32_PAGE_H
8959 +#define _ASM_UBICOM32_PAGE_H
8960 +
8961 +/* PAGE_SHIFT determines the page size */
8962 +
8963 +#define PAGE_SHIFT     12
8964 +#define PAGE_SIZE      (1 << PAGE_SHIFT)
8965 +#define PAGE_MASK      (~(PAGE_SIZE-1))
8966 +
8967 +#include <asm/setup.h>
8968 +
8969 +#ifndef __ASSEMBLY__
8970 +
8971 +#define get_user_page(vaddr)           __get_free_page(GFP_KERNEL)
8972 +#define free_user_page(page, addr)     free_page(addr)
8973 +
8974 +#define clear_page(page)       memset((page), 0, PAGE_SIZE)
8975 +#define copy_page(to,from)     memcpy((to), (from), PAGE_SIZE)
8976 +
8977 +#define clear_user_page(page, vaddr, pg)       clear_page(page)
8978 +#define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
8979 +
8980 +#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
8981 +       alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
8982 +#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
8983 +
8984 +/*
8985 + * These are used to make use of C type-checking..
8986 + */
8987 +typedef struct { unsigned long pte; } pte_t;
8988 +typedef struct { unsigned long pmd[16]; } pmd_t;
8989 +typedef struct { unsigned long pgd; } pgd_t;
8990 +typedef struct { unsigned long pgprot; } pgprot_t;
8991 +typedef struct page *pgtable_t;
8992 +
8993 +#define pte_val(x)     ((x).pte)
8994 +#define pmd_val(x)     ((&x)->pmd[0])
8995 +#define pgd_val(x)     ((x).pgd)
8996 +#define pgprot_val(x)  ((x).pgprot)
8997 +
8998 +#define __pte(x)       ((pte_t) { (x) } )
8999 +#define __pmd(x)       ((pmd_t) { (x) } )
9000 +#define __pgd(x)       ((pgd_t) { (x) } )
9001 +#define __pgprot(x)    ((pgprot_t) { (x) } )
9002 +
9003 +extern unsigned long memory_start;
9004 +extern unsigned long memory_end;
9005 +
9006 +#endif /* !__ASSEMBLY__ */
9007 +
9008 +#include <asm/page_offset.h>
9009 +
9010 +#define PAGE_OFFSET            (PAGE_OFFSET_RAW)
9011 +
9012 +#ifndef __ASSEMBLY__
9013 +
9014 +#define __pa(vaddr)            virt_to_phys((void *)(vaddr))
9015 +#define __va(paddr)            phys_to_virt((unsigned long)(paddr))
9016 +
9017 +#define virt_to_pfn(kaddr)     (__pa(kaddr) >> PAGE_SHIFT)
9018 +#define pfn_to_virt(pfn)       __va((pfn) << PAGE_SHIFT)
9019 +
9020 +#define virt_to_page(addr)     (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
9021 +#define page_to_virt(page)     ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
9022 +
9023 +#define pfn_to_page(pfn)       virt_to_page(pfn_to_virt(pfn))
9024 +#define page_to_pfn(page)      virt_to_pfn(page_to_virt(page))
9025 +#define pfn_valid(pfn)         ((pfn) < max_mapnr)
9026 +
9027 +#define        virt_addr_valid(kaddr)  (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
9028 +                               ((void *)(kaddr) < (void *)memory_end))
9029 +
9030 +#endif /* __ASSEMBLY__ */
9031 +
9032 +#ifdef __KERNEL__
9033 +#include <asm-generic/page.h>
9034 +#endif
9035 +
9036 +#endif /* _ASM_UBICOM32_PAGE_H */
9037 --- /dev/null
9038 +++ b/arch/ubicom32/include/asm/page_offset.h
9039 @@ -0,0 +1,35 @@
9040 +/*
9041 + * arch/ubicom32/include/asm/page_offset.h
9042 + *   Definition of PAGE_OFFSET_RAW for Ubicom32 architecture.
9043 + *
9044 + * (C) Copyright 2009, Ubicom, Inc.
9045 + *
9046 + * This file is part of the Ubicom32 Linux Kernel Port.
9047 + *
9048 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9049 + * it and/or modify it under the terms of the GNU General Public License
9050 + * as published by the Free Software Foundation, either version 2 of the
9051 + * License, or (at your option) any later version.
9052 + *
9053 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9054 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9055 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9056 + * the GNU General Public License for more details.
9057 + *
9058 + * You should have received a copy of the GNU General Public License
9059 + * along with the Ubicom32 Linux Kernel Port.  If not,
9060 + * see <http://www.gnu.org/licenses/>.
9061 + *
9062 + * Ubicom32 implementation derived from (with many thanks):
9063 + *   arch/m68knommu
9064 + *   arch/blackfin
9065 + *   arch/parisc
9066 + */
9067 +
9068 +#ifndef _ASM_UBICOM32_PAGE_OFFSET_H
9069 +#define _ASM_UBICOM32_PAGE_OFFSET_H
9070 +
9071 +/* This handles the memory map.. */
9072 +#define        PAGE_OFFSET_RAW         0x3ffc0000
9073 +
9074 +#endif /* _ASM_UBICOM32_PAGE_OFFSET_H */
9075 --- /dev/null
9076 +++ b/arch/ubicom32/include/asm/param.h
9077 @@ -0,0 +1,49 @@
9078 +/*
9079 + * arch/ubicom32/include/asm/param.h
9080 + *   Definition of miscellaneous constants, including HZ.
9081 + *
9082 + * (C) Copyright 2009, Ubicom, Inc.
9083 + *
9084 + * This file is part of the Ubicom32 Linux Kernel Port.
9085 + *
9086 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9087 + * it and/or modify it under the terms of the GNU General Public License
9088 + * as published by the Free Software Foundation, either version 2 of the
9089 + * License, or (at your option) any later version.
9090 + *
9091 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9092 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9093 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9094 + * the GNU General Public License for more details.
9095 + *
9096 + * You should have received a copy of the GNU General Public License
9097 + * along with the Ubicom32 Linux Kernel Port.  If not,
9098 + * see <http://www.gnu.org/licenses/>.
9099 + *
9100 + * Ubicom32 implementation derived from (with many thanks):
9101 + *   arch/m68knommu
9102 + *   arch/blackfin
9103 + *   arch/parisc
9104 + */
9105 +#ifndef _ASM_UBICOM32_PARAM_H
9106 +#define _ASM_UBICOM32_PARAM_H
9107 +
9108 +#ifdef __KERNEL__
9109 +#define HZ CONFIG_HZ
9110 +#define        USER_HZ         HZ
9111 +#define        CLOCKS_PER_SEC  (USER_HZ)
9112 +#endif
9113 +
9114 +#ifndef HZ
9115 +#define HZ     100
9116 +#endif
9117 +
9118 +#define EXEC_PAGESIZE  4096
9119 +
9120 +#ifndef NOGROUP
9121 +#define NOGROUP                (-1)
9122 +#endif
9123 +
9124 +#define MAXHOSTNAMELEN 64      /* max length of hostname */
9125 +
9126 +#endif /* _ASM_UBICOM32_PARAM_H */
9127 --- /dev/null
9128 +++ b/arch/ubicom32/include/asm/pci.h
9129 @@ -0,0 +1,210 @@
9130 +/*
9131 + * arch/ubicom32/include/asm/pci.h
9132 + *   Definitions of PCI operations for Ubicom32 architecture.
9133 + *
9134 + * (C) Copyright 2009, Ubicom, Inc.
9135 + *
9136 + * This file is part of the Ubicom32 Linux Kernel Port.
9137 + *
9138 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9139 + * it and/or modify it under the terms of the GNU General Public License
9140 + * as published by the Free Software Foundation, either version 2 of the
9141 + * License, or (at your option) any later version.
9142 + *
9143 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9144 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9145 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9146 + * the GNU General Public License for more details.
9147 + *
9148 + * You should have received a copy of the GNU General Public License
9149 + * along with the Ubicom32 Linux Kernel Port.  If not,
9150 + * see <http://www.gnu.org/licenses/>.
9151 + *
9152 + * Ubicom32 implementation derived from (with many thanks):
9153 + *   arch/m68knommu
9154 + *   arch/blackfin
9155 + *   arch/parisc
9156 + */
9157 +#ifndef _ASM_UBICOM32_PCI_H
9158 +#define _ASM_UBICOM32_PCI_H
9159 +
9160 +#include <asm/io.h>
9161 +
9162 +/* The PCI address space does equal the physical memory
9163 + * address space.  The networking and block device layers use
9164 + * this boolean for bounce buffer decisions.
9165 + */
9166 +#define PCI_DMA_BUS_IS_PHYS    (1)
9167 +
9168 +
9169 +
9170 +/*
9171 + * Perform a master read/write to the PCI bus.
9172 + * These functions return a PCI_RESP_xxx code.
9173 + */
9174 +extern u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data);
9175 +extern u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data);
9176 +extern u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data);
9177 +extern u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data);
9178 +extern u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data);
9179 +extern u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data);
9180 +
9181 +
9182 +#define PCIBIOS_MIN_IO          0x100
9183 +#define PCIBIOS_MIN_MEM         0x10000000
9184 +
9185 +#define pcibios_assign_all_busses()    0
9186 +#define pcibios_scan_all_fns(a, b)     0
9187 +extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
9188 +       struct resource *res);
9189 +
9190 +extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
9191 +       struct pci_bus_region *region);
9192 +
9193 +struct pci_sys_data;
9194 +struct pci_bus;
9195 +
9196 +struct hw_pci {
9197 +        struct list_head buses;
9198 +        int             nr_controllers;
9199 +        int             (*setup)(int nr, struct pci_sys_data *);
9200 +        struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
9201 +        void            (*preinit)(void);
9202 +        void            (*postinit)(void);
9203 +        u8              (*swizzle)(struct pci_dev *dev, u8 *pin);
9204 +        int             (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
9205 +};
9206 +
9207 +/*
9208 + * Per-controller structure
9209 + */
9210 +struct pci_sys_data {
9211 +        struct list_head node;
9212 +        int             busnr;          /* primary bus number                   */
9213 +        u64             mem_offset;     /* bus->cpu memory mapping offset       */
9214 +        unsigned long   io_offset;      /* bus->cpu IO mapping offset           */
9215 +        struct pci_bus  *bus;           /* PCI bus                              */
9216 +        struct resource *resource[3];   /* Primary PCI bus resources            */
9217 +                                        /* Bridge swizzling                     */
9218 +        u8              (*swizzle)(struct pci_dev *, u8 *);
9219 +                                        /* IRQ mapping                          */
9220 +        int             (*map_irq)(struct pci_dev *, u8, u8);
9221 +        struct hw_pci   *hw;
9222 +};
9223 +
9224 +static  inline struct resource *
9225 +pcibios_select_root(struct pci_dev *pdev, struct resource *res)
9226 +{
9227 +        struct resource *root = NULL;
9228 +
9229 +        if (res->flags & IORESOURCE_IO)
9230 +                root = &ioport_resource;
9231 +        if (res->flags & IORESOURCE_MEM)
9232 +                root = &iomem_resource;
9233 +
9234 +        return root;
9235 +}
9236 +
9237 +static inline void pcibios_set_master(struct pci_dev *dev)
9238 +{
9239 +        /* No special bus mastering setup handling */
9240 +}
9241 +#define HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE 1
9242 +#define HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY 1
9243 +
9244 +#ifdef CONFIG_PCI
9245 +static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
9246 +                     dma_addr_t *dma_handle)
9247 +{
9248 +    void *vaddr = kmalloc(size, GFP_KERNEL);
9249 +    if(vaddr != NULL) {
9250 +        *dma_handle = virt_to_phys(vaddr);
9251 +    }
9252 +    return vaddr;
9253 +}
9254 +
9255 +static  inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
9256 +{
9257 +       return 1;
9258 +}
9259 +
9260 +static  inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
9261 +       void *cpu_addr, dma_addr_t dma_handle)
9262 +{
9263 +       kfree(cpu_addr);
9264 +       return;
9265 +}
9266 +
9267 +static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
9268 +       size_t size, int direction)
9269 +{
9270 +        return virt_to_phys(ptr);
9271 +}
9272 +
9273 +static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
9274 +       size_t size, int direction)
9275 +{
9276 +        return;
9277 +}
9278 +
9279 +static inline dma_addr_t
9280 +pci_map_page(struct pci_dev *hwdev, struct page *page,
9281 +             unsigned long offset, size_t size, int direction)
9282 +{
9283 +        return pci_map_single(hwdev, page_address(page) + offset, size, (int)direction);
9284 +}
9285 +
9286 +static inline void
9287 +pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
9288 +               size_t size, int direction)
9289 +{
9290 +       pci_unmap_single(hwdev, dma_address, size, direction);
9291 +}
9292 +
9293 +static inline int
9294 +pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9295 +           int nents, int direction)
9296 +{
9297 +        return nents;
9298 +}
9299 +
9300 +static inline void
9301 +pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9302 +             int nents, int direction)
9303 +{
9304 +}
9305 +
9306 +static inline void
9307 +pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
9308 +                int nelems, int direction)
9309 +{
9310 +}
9311 +
9312 +static inline void
9313 +pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
9314 +                int nelems, int direction)
9315 +{
9316 +}
9317 +
9318 +static inline void
9319 +pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
9320 +                    size_t size, int direction)
9321 +{
9322 +}
9323 +
9324 +static inline void
9325 +pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
9326 +                    size_t size, int direction)
9327 +{
9328 +}
9329 +
9330 +static inline int
9331 +pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
9332 +{
9333 +        return dma_addr == 0;
9334 +}
9335 +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
9336 +extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
9337 +#endif
9338 +
9339 +#endif /* _ASM_UBICOM32_PCI_H */
9340 --- /dev/null
9341 +++ b/arch/ubicom32/include/asm/pcm_tio.h
9342 @@ -0,0 +1,84 @@
9343 +/*
9344 + * arch/ubicom32/include/asm/pcm_tio.h
9345 + *   Ubicom32 architecture PCM TIO definitions.
9346 + *
9347 + * (C) Copyright 2009, Ubicom, Inc.
9348 + *
9349 + * This file is part of the Ubicom32 Linux Kernel Port.
9350 + *
9351 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9352 + * it and/or modify it under the terms of the GNU General Public License
9353 + * as published by the Free Software Foundation, either version 2 of the
9354 + * License, or (at your option) any later version.
9355 + *
9356 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9357 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9358 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9359 + * the GNU General Public License for more details.
9360 + *
9361 + * You should have received a copy of the GNU General Public License
9362 + * along with the Ubicom32 Linux Kernel Port.  If not,
9363 + * see <http://www.gnu.org/licenses/>.
9364 + */
9365 +#ifndef _ASM_UBICOM32_PCM_TIO_H
9366 +#define _ASM_UBICOM32_PCM_TIO_H
9367 +
9368 +#include <asm/devtree.h>
9369 +
9370 +#define PCM_TIO_REGS_VERSION   2
9371 +struct pcm_tio_regs {
9372 +       /*
9373 +        * set this value to 1 to reload the parameters and restart the HRT
9374 +        */
9375 +       u32_t           reload;
9376 +
9377 +       /*
9378 +        * Pointers to the input and output buffers
9379 +        */
9380 +       void            *input_buf;
9381 +       void            *output_buf;
9382 +
9383 +       /*
9384 +        * Buffer size (see pcm_hrt.S for constraints)
9385 +        */
9386 +       u32_t           buffer_size;
9387 +
9388 +       /*
9389 +        * Current cycle.  This variable increases every time half the buffer
9390 +        * is consumed.
9391 +        */
9392 +       u32_t           cycle;
9393 +
9394 +       /*
9395 +        * Fields below this line are not accessed by the HRT.  They are purely
9396 +        * informational for the user of this TIO.
9397 +        */
9398 +
9399 +       /*
9400 +        * Version of this structure
9401 +        */
9402 +       u32_t           version;
9403 +
9404 +       /*
9405 +        * Number of channels supported
9406 +        */
9407 +       u32_t           channels;
9408 +
9409 +       /*
9410 +        * Maximum buffer size
9411 +        */
9412 +       u32_t           max_buffer_size;
9413 +};
9414 +
9415 +/*
9416 + * Our device node
9417 + */
9418 +#define PCM_TIO_NODE_VERSION   1
9419 +struct pcm_tio_node {
9420 +       struct devtree_node     dn;
9421 +       u32_t                   version;
9422 +       struct pcm_tio_regs     *regs;
9423 +};
9424 +
9425 +#endif
9426 +
9427 --- /dev/null
9428 +++ b/arch/ubicom32/include/asm/percpu.h
9429 @@ -0,0 +1,33 @@
9430 +/*
9431 + * arch/ubicom32/include/asm/percpu.h
9432 + *   Generic percpu.h for the Ubicom32 architecture.
9433 + *
9434 + * (C) Copyright 2009, Ubicom, Inc.
9435 + *
9436 + * This file is part of the Ubicom32 Linux Kernel Port.
9437 + *
9438 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9439 + * it and/or modify it under the terms of the GNU General Public License
9440 + * as published by the Free Software Foundation, either version 2 of the
9441 + * License, or (at your option) any later version.
9442 + *
9443 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9444 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9445 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9446 + * the GNU General Public License for more details.
9447 + *
9448 + * You should have received a copy of the GNU General Public License
9449 + * along with the Ubicom32 Linux Kernel Port.  If not,
9450 + * see <http://www.gnu.org/licenses/>.
9451 + *
9452 + * Ubicom32 implementation derived from (with many thanks):
9453 + *   arch/m68knommu
9454 + *   arch/blackfin
9455 + *   arch/parisc
9456 + */
9457 +#ifndef _ASM_UBICOM32_PERCPU_H
9458 +#define _ASM_UBICOM32_PERCPU_H
9459 +
9460 +#include <asm-generic/percpu.h>
9461 +
9462 +#endif /* _ASM_UBICOM32_PERCPU_H */
9463 --- /dev/null
9464 +++ b/arch/ubicom32/include/asm/pgalloc.h
9465 @@ -0,0 +1,36 @@
9466 +/*
9467 + * arch/ubicom32/include/asm/pgalloc.h
9468 + *   Page table allocation definitions.
9469 + *
9470 + * (C) Copyright 2009, Ubicom, Inc.
9471 + *
9472 + * This file is part of the Ubicom32 Linux Kernel Port.
9473 + *
9474 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9475 + * it and/or modify it under the terms of the GNU General Public License
9476 + * as published by the Free Software Foundation, either version 2 of the
9477 + * License, or (at your option) any later version.
9478 + *
9479 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9480 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9481 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9482 + * the GNU General Public License for more details.
9483 + *
9484 + * You should have received a copy of the GNU General Public License
9485 + * along with the Ubicom32 Linux Kernel Port.  If not,
9486 + * see <http://www.gnu.org/licenses/>.
9487 + *
9488 + * Ubicom32 implementation derived from (with many thanks):
9489 + *   arch/m68knommu
9490 + *   arch/blackfin
9491 + *   arch/parisc
9492 + */
9493 +#ifndef _ASM_UBICOM32_PGALLOC_H
9494 +#define _ASM_UBICOM32_PGALLOC_H
9495 +
9496 +#include <linux/mm.h>
9497 +#include <asm/setup.h>
9498 +
9499 +#define check_pgt_cache()      do { } while (0)
9500 +
9501 +#endif /* _ASM_UBICOM32_PGALLOC_H */
9502 --- /dev/null
9503 +++ b/arch/ubicom32/include/asm/pgtable.h
9504 @@ -0,0 +1,124 @@
9505 +/*
9506 + * arch/ubicom32/include/asm/pgtable.h
9507 + *   Ubicom32 pseudo page table definitions and operations.
9508 + *
9509 + * (C) Copyright 2009, Ubicom, Inc.
9510 + * Copyright (C) 2004   Microtronix Datacom Ltd
9511 + *
9512 + * This file is part of the Ubicom32 Linux Kernel Port.
9513 + *
9514 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9515 + * it and/or modify it under the terms of the GNU General Public License
9516 + * as published by the Free Software Foundation, either version 2 of the
9517 + * License, or (at your option) any later version.
9518 + *
9519 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9520 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9521 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9522 + * the GNU General Public License for more details.
9523 + *
9524 + * You should have received a copy of the GNU General Public License
9525 + * along with the Ubicom32 Linux Kernel Port.  If not,
9526 + * see <http://www.gnu.org/licenses/>.
9527 + *
9528 + * Ubicom32 implementation derived from (with many thanks):
9529 + *   arch/m68knommu
9530 + *   arch/blackfin
9531 + *   arch/parisc
9532 + *   and various works, Alpha, ix86, M68K, Sparc, ...et al
9533 + */
9534 +#ifndef _ASM_UBICOM32_PGTABLE_H
9535 +#define _ASM_UBICOM32_PGTABLE_H
9536 +
9537 +#include <asm-generic/4level-fixup.h>
9538 +
9539 +//vic - this bit copied from m68knommu version
9540 +#include <asm/setup.h>
9541 +#include <asm/io.h>
9542 +#include <linux/sched.h>
9543 +
9544 +typedef pte_t *pte_addr_t;
9545 +
9546 +#define pgd_present(pgd)       (1)       /* pages are always present on NO_MM */
9547 +#define pgd_none(pgd)          (0)
9548 +#define pgd_bad(pgd)           (0)
9549 +#define pgd_clear(pgdp)
9550 +#define kern_addr_valid(addr)  (1)
9551 +#define        pmd_offset(a, b)        ((void *)0)
9552 +
9553 +#define PAGE_NONE              __pgprot(0)    /* these mean nothing to NO_MM */
9554 +#define PAGE_SHARED            __pgprot(0)    /* these mean nothing to NO_MM */
9555 +#define PAGE_COPY              __pgprot(0)    /* these mean nothing to NO_MM */
9556 +#define PAGE_READONLY          __pgprot(0)    /* these mean nothing to NO_MM */
9557 +#define PAGE_KERNEL            __pgprot(0)    /* these mean nothing to NO_MM */
9558 +//vic - this bit copied from m68knommu version
9559 +
9560 +extern void paging_init(void);
9561 +#define swapper_pg_dir ((pgd_t *) 0)
9562 +
9563 +#define __swp_type(x)          (0)
9564 +#define __swp_offset(x)                (0)
9565 +#define __swp_entry(typ,off)   ((swp_entry_t) { ((typ) | ((off) << 7)) })
9566 +#define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
9567 +#define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
9568 +
9569 +/*
9570 + * pgprot_noncached() is only for infiniband pci support, and a real
9571 + * implementation for RAM would be more complicated.
9572 + */
9573 +#define pgprot_noncached(prot) (prot)
9574 +
9575 +static inline int pte_file(pte_t pte) { return 0; }
9576 +
9577 +/*
9578 + * ZERO_PAGE is a global shared page that is always zero: used
9579 + * for zero-mapped memory areas etc..
9580 + */
9581 +#define ZERO_PAGE(vaddr)       (virt_to_page(0))
9582 +
9583 +extern unsigned int kobjsize(const void *objp);
9584 +extern int is_in_rom(unsigned long);
9585 +
9586 +/*
9587 + * No page table caches to initialise
9588 + */
9589 +#define pgtable_cache_init()   do { } while (0)
9590 +
9591 +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
9592 +               remap_pfn_range(vma, vaddr, pfn, size, prot)
9593 +
9594 +extern inline void flush_cache_mm(struct mm_struct *mm)
9595 +{
9596 +}
9597 +
9598 +extern inline void flush_cache_range(struct mm_struct *mm,
9599 +                                    unsigned long start,
9600 +                                    unsigned long end)
9601 +{
9602 +}
9603 +
9604 +/* Push the page at kernel virtual address and clear the icache */
9605 +extern inline void flush_page_to_ram (unsigned long address)
9606 +{
9607 +}
9608 +
9609 +/* Push n pages at kernel virtual address and clear the icache */
9610 +extern inline void flush_pages_to_ram (unsigned long address, int n)
9611 +{
9612 +}
9613 +
9614 +/*
9615 + * All 32bit addresses are effectively valid for vmalloc...
9616 + * Sort of meaningless for non-VM targets.
9617 + */
9618 +#define        VMALLOC_START   0
9619 +#define        VMALLOC_END     0xffffffff
9620 +
9621 +#define arch_enter_lazy_mmu_mode()     do {} while (0)
9622 +#define arch_leave_lazy_mmu_mode()     do {} while (0)
9623 +#define arch_flush_lazy_mmu_mode()     do {} while (0)
9624 +#define arch_enter_lazy_cpu_mode()     do {} while (0)
9625 +#define arch_leave_lazy_cpu_mode()     do {} while (0)
9626 +#define arch_flush_lazy_cpu_mode()     do {} while (0)
9627 +
9628 +#endif /* _ASM_UBICOM32_PGTABLE_H */
9629 --- /dev/null
9630 +++ b/arch/ubicom32/include/asm/plio.h
9631 @@ -0,0 +1,313 @@
9632 +/*
9633 + * plio.h
9634 + *     PLIO defines.
9635 + *
9636 + * Copyright Â© 2009 Ubicom Inc. <www.ubicom.com>.  All Rights Reserved.
9637 + *
9638 + * This file is part of the Ubicom32 Linux Kernel Port.
9639 + *
9640 + * The Ubicom32 Linux Kernel Port is free software: you can
9641 + * redistribute it and/or modify it under the terms of the GNU General
9642 + * Public License as published by the Free Software Foundation, either
9643 + * version 2 of the License, or (at your option) any later version.
9644 + *
9645 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9646 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9647 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9648 + * See the GNU General Public License for more details.
9649 + *
9650 + * You should have received a copy of the GNU General Public License
9651 + * along with the Ubicom32 Linux Kernel Port.  If not,
9652 + * see <http://www.gnu.org/licenses/>.
9653 + * This file contains confidential information of Ubicom, Inc. and your use of
9654 + * this file is subject to the Ubicom Software License Agreement distributed with
9655 + * this file. If you are uncertain whether you are an authorized user or to report
9656 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
9657 + * Unauthorized reproduction or distribution of this file is subject to civil and
9658 + * criminal penalties.
9659 + */
9660 +
9661 +#ifndef __PLIO__H__
9662 +#define __PLIO__H__
9663 +
9664 +#include <asm/ip5000.h>
9665 +#include <asm/thread.h>
9666 +
9667 +#define PLIO_PORT              RD
9668 +#define PLIO_EXT_PORT          RI
9669 +
9670 +#define TRANSMIT_FIFO_WATERMARK 8
9671 +
9672 +/*
9673 + * PLIO non-blocking register definitions
9674 + */
9675 +#define PLIO_FN                2
9676 +
9677 +typedef struct {
9678 +       unsigned        : 10;
9679 +       unsigned        rxfifo_thread_enable: 1;   /* allowed rxfifo thread enable */
9680 +       unsigned        : 1;
9681 +       unsigned        rxfifo_thread: 4;          /* allowed rxfifo thread access */
9682 +       unsigned        : 4;
9683 +       unsigned        br_thread: 4;              /* allowed blocking region thread access */
9684 +       unsigned        fn_reset: 4;               /* function reset bit vector */
9685 +       unsigned        rxfifo_sel: 1;             /* select between RXFIFO 0 and 1 */
9686 +       unsigned        fn_sel: 3;                 /* select port function */
9687 +} plio_io_function_t;
9688 +
9689 +typedef struct {
9690 +       unsigned        : 24;
9691 +       unsigned        pin:8;
9692 +} plio_gpio_t;
9693 +
9694 +typedef struct {
9695 +       unsigned        : 16;
9696 +       unsigned        txfifo_uf: 1;              /* TXFIFO underflow */
9697 +       unsigned        txfifo_wm: 1;              /* TXFIFO watermark */
9698 +       unsigned        rxfifo_of: 1;              /* RXFIFO overflow */
9699 +       unsigned        rxfifo_wm: 1;              /* RXFIFO watermark */
9700 +       unsigned        : 5;
9701 +       unsigned        lreg_int_addr_rd: 1;       /* read from specified LREG address */
9702 +       unsigned        lreg_int_addr_wr: 1;       /* write to specified LREG address */
9703 +       unsigned        extctl_int: 4;             /* synchronized external interrupts */
9704 +       unsigned        pfsm_int: 1;               /* state machine */
9705 +} plio_intstat_t;
9706 +
9707 +typedef struct {
9708 +       unsigned        txfifo_reset: 1;           /* TXFIFO reset for int_set only */
9709 +       unsigned        rxfifo_reset: 1;           /* RXFIFO reset for int_set only */
9710 +       unsigned        : 11;
9711 +       unsigned        idif_txfifo_flush: 1;      /* flush TXFIFO and idif_txfifo */
9712 +       unsigned        idif_rxfifo_flush: 1;      /* flush RXFIFO and idif_rxfifo */
9713 +       unsigned        pfsm_start: 1;             /* input to fsm */
9714 +       unsigned        txfifo_uf: 1;              /* TXFIFO underflow */
9715 +       unsigned        txfifo_wm: 1;              /* TXFIFO watermark */
9716 +       unsigned        rxfifo_of: 1;              /* RXFIFO overflow */
9717 +       unsigned        rxfifo_wm: 1;              /* RXFIFO watermark */
9718 +       unsigned        : 5;
9719 +       unsigned        lreg_int_addr_rd: 1;       /* read from specified LREG address */
9720 +       unsigned        lreg_int_addr_wr: 1;       /* write to specified LREG address */
9721 +       unsigned        extctl_int: 4;             /* synchronized external interrupts */
9722 +       unsigned        pfsm_int: 1;               /* state machine */
9723 +} plio_intset_t;
9724 +
9725 +typedef enum {
9726 +       PLIO_PORT_MODE_D,
9727 +       PLIO_PORT_MODE_DE,
9728 +       PLIO_PORT_MODE_DI,
9729 +       PLIO_PORT_MODE_DEI,
9730 +       PLIO_PORT_MODE_DC,
9731 +} plio_port_mode_t;
9732 +
9733 +typedef enum {
9734 +       PLIO_CLK_CORE,  /* CORE CLK */
9735 +       PLIO_CLK_IO,    /* IO CLK */
9736 +       PLIO_CLK_EXT,   /* EXT CLK */
9737 +} plio_clk_src_t;
9738 +typedef struct {
9739 +       unsigned                : 4;
9740 +       unsigned                edif_iaena_sel: 1;         /* Input Address Enable Select */
9741 +       unsigned                edif_iaclk_sel: 1;         /* Input Address Clock Select */
9742 +       unsigned                edif_iald_inv: 1;          /* Input Address Strobe Invert */
9743 +       unsigned                edif_idclk_sel: 1;         /* Input Data Clock Select */
9744 +       unsigned                edif_idld_inv: 1;          /* Input Data Strobe Invert */
9745 +       unsigned                edif_ds: 3;                /* specify IDR and ODR data shift */
9746 +       unsigned                edif_cmp_mode: 1;          /* configure IDR comparator output */
9747 +       unsigned                edif_idena_sel: 1;         /* Input Data Enable Select */
9748 +       unsigned                ecif_extclk_ena: 1;        /* plio_extctl output select */
9749 +       unsigned                idif_tx_fifo_cmd_sel: 1;   /* select pfsm_cmd data word position */
9750 +       unsigned                ptif_porti_cfg: 2;         /* select port I pin configuration */
9751 +       unsigned                ptif_portd_cfg: 3;         /* select port D pin configuration */
9752 +       plio_port_mode_t        ptif_port_mode: 3;      /* select other plio ports  */
9753 +       unsigned                icif_clk_plio_ext_inv: 1;  /* invert external plio clock when set */
9754 +       unsigned                icif_rst_plio: 1;          /* reset plio function and io fifos */
9755 +       plio_clk_src_t          icif_clk_src_sel: 2;      /* select plio clock source */
9756 +       unsigned                pfsm_prog: 1;              /* enable pfsm programming */
9757 +       unsigned                pfsm_cmd: 3;               /* software input to pfsm */
9758 +} plio_fctl0_t;
9759 +
9760 +typedef struct {
9761 +       unsigned        : 2;
9762 +       unsigned        idif_byteswap_tx: 3;       /* swap TXFIFO byte order */
9763 +       unsigned        idif_byteswap_rx: 3;       /* swap RXFIFO byte order */
9764 +       unsigned        : 1;
9765 +       unsigned        lreg_ena: 1;               /* enable local register map */
9766 +       unsigned        lreg_addr_fifo_cmp_ena: 1; /* enable a specific LREG address from/to TX/RX fifos */
9767 +       unsigned        lreg_addr_fifo_cmp: 5;     /* LREG address routed from/to TX/RX fifos */
9768 +       unsigned        : 1;
9769 +       unsigned        dcod_iald_idld_sel: 2;     /* select address/data strobes */
9770 +       unsigned        dcod_rw_src_sel: 1;        /* select LREG strobe source */
9771 +       unsigned        dcod_rd_sel: 5;            /* select read strobe source */
9772 +       unsigned        dcod_wr_sel: 5;            /* select write strobe source */
9773 +       unsigned        dcod_rd_lvl: 1;            /* select active level of read strobe */
9774 +       unsigned        dcod_wr_lvl: 1;            /* select active level of read strobe */
9775 +} plio_fctl1_t;
9776 +
9777 +typedef struct {
9778 +       unsigned        icif_eclk_div: 16;         /* external plio clock divider */
9779 +       unsigned        icif_iclk_div: 16;         /* internal plio clock divider */
9780 +} plio_fctl2_t;
9781 +
9782 +typedef struct {
9783 +       unsigned        : 27;
9784 +       unsigned        pfsm_state: 5;             /* current pfsm state */
9785 +} plio_stat_0_t;
9786 +
9787 +typedef struct {
9788 +       unsigned        : 3;
9789 +       unsigned        lreg_r_int_addr: 5;
9790 +       unsigned        : 11;
9791 +       unsigned        lreg_w_int_addr: 5;
9792 +       unsigned        lreg_w_int_data: 8;
9793 +} plio_stat_1_t;
9794 +
9795 +typedef struct {
9796 +       unsigned        : 32;
9797 +} plio_stat_2_t;
9798 +
9799 +typedef struct {
9800 +       unsigned        tx: 16;
9801 +       unsigned        rx: 16;
9802 +} plio_io_fifo_wm_t, plio_io_fifo_lvl_t;
9803 +
9804 +
9805 +/* plio blocking region register definitions
9806 + */
9807 +typedef struct {
9808 +       unsigned         ns1: 5;
9809 +       unsigned         ic1: 7;
9810 +       unsigned         ec1: 4;
9811 +       unsigned         ns0: 5;
9812 +       unsigned         ic0: 7;
9813 +       unsigned         ec0: 4;
9814 +} plio_sram_t;
9815 +
9816 +typedef struct {
9817 +       unsigned         : 2;
9818 +       unsigned         s9: 3;
9819 +       unsigned         s8: 3;
9820 +       unsigned         s7: 3;
9821 +       unsigned         s6: 3;
9822 +       unsigned         s5: 3;
9823 +       unsigned         s4: 3;
9824 +       unsigned         s3: 3;
9825 +       unsigned         s2: 3;
9826 +       unsigned         s1: 3;
9827 +       unsigned         s0: 3;
9828 +} plio_grpsel_t;
9829 +
9830 +typedef struct {
9831 +       unsigned        s7: 4;
9832 +       unsigned        s6: 4;
9833 +       unsigned        s5: 4;
9834 +       unsigned        s4: 4;
9835 +       unsigned        s3: 4;
9836 +       unsigned        s2: 4;
9837 +       unsigned        s1: 4;
9838 +       unsigned        s0: 4;
9839 +} plio_cs_lut_t;
9840 +
9841 +typedef struct {
9842 +       unsigned        lut3: 8;
9843 +       unsigned        lut2: 8;
9844 +       unsigned        lut1: 8;
9845 +       unsigned        lut0: 8;
9846 +} plio_extctl_t;
9847 +
9848 +typedef struct {
9849 +       plio_grpsel_t   grpsel[4];
9850 +       u16_t           cv[16];
9851 +       plio_cs_lut_t   cs_lut[4];
9852 +       plio_extctl_t   extctl_o_lut[8];
9853 +} plio_pfsm_t;
9854 +
9855 +typedef struct {
9856 +       u32_t           odr_oe_sel;
9857 +       u32_t           odr_oe;
9858 +       u32_t           cmp;
9859 +       u32_t           ncmp;
9860 +       u32_t           cmp_mask;
9861 +} plio_edif_t;
9862 +
9863 +typedef enum {
9864 +       PLIO_ECIF_CLK_OUT       = 9,
9865 +       PLIO_ECIF_IALD          = 9,
9866 +       PLIO_ECIF_CLK_IN        = 8,
9867 +       PLIO_ECIF_IDLD          = 8,
9868 +       PLIO_ECIF_INT           = 2,
9869 +} plio_ecif_output_t;
9870 +
9871 +typedef struct {
9872 +       u32_t           bypass_sync;
9873 +       u32_t           ift;
9874 +       u32_t           output_type;
9875 +       u32_t           output_ena;
9876 +       u32_t           output_lvl;
9877 +} plio_ecif_t;
9878 +
9879 +typedef struct {
9880 +       u32_t           idr_addr_pos_mask;
9881 +       u32_t           reserved;
9882 +       u32_t           lreg_bar;
9883 +} plio_dcod_t;
9884 +
9885 +typedef struct {
9886 +       u32_t           addr_rd_ena;
9887 +       u32_t           addr_wr_ena;
9888 +       u32_t           addr_rd_int_ena;
9889 +       u32_t           addr_wr_int_ena;
9890 +} plio_lcfg_t;
9891 +
9892 +
9893 +/*
9894 + * PLIO configuration
9895 + */
9896 +typedef struct {
9897 +       plio_fctl0_t    fctl0;
9898 +       plio_fctl1_t    fctl1;
9899 +       plio_fctl2_t    fctl2;
9900 +} plio_fctl_t;
9901 +
9902 +typedef struct {
9903 +       plio_pfsm_t     pfsm;
9904 +       plio_edif_t     edif;
9905 +       plio_ecif_t     ecif;
9906 +       plio_dcod_t     dcod;
9907 +       plio_lcfg_t     lcfg;
9908 +} plio_config_t;
9909 +
9910 +typedef struct {
9911 +       plio_io_function_t      function;
9912 +       plio_gpio_t             gpio_ctl;
9913 +       plio_gpio_t             gpio_out;
9914 +       plio_gpio_t             gpio_in;
9915 +       plio_intstat_t          intstat;
9916 +       plio_intstat_t          intmask;
9917 +       plio_intset_t           intset;
9918 +       plio_intstat_t          intclr;
9919 +       unsigned                tx_lo;
9920 +       unsigned                tx_hi;
9921 +       unsigned                rx_lo;
9922 +       unsigned                rx_hi;
9923 +       plio_fctl0_t            fctl0;
9924 +       plio_fctl1_t            fctl1;
9925 +       plio_fctl2_t            fctl2;
9926 +       plio_stat_0_t           stat0;
9927 +       plio_stat_1_t           stat1;
9928 +       plio_stat_2_t           stat2;
9929 +       plio_io_fifo_wm_t       fifo_wm;
9930 +       plio_io_fifo_lvl_t      fifo_lvl;
9931 +} plio_nbr_t;
9932 +
9933 +typedef struct {
9934 +       u32_t                   pfsm_sram[256];
9935 +       plio_config_t           config;
9936 +} plio_br_t;
9937 +
9938 +#define PLIO_NBR       ((plio_nbr_t *)(PLIO_PORT))
9939 +#define PLIO_BR                ((plio_br_t *)((PLIO_PORT + IO_PORT_BR_OFFSET)))
9940 +#define PEXT_NBR       ((plio_nbr_t *)(PLIO_EXT_PORT))
9941 +
9942 +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);
9943 +
9944 +#endif // __PLIO__H__
9945 --- /dev/null
9946 +++ b/arch/ubicom32/include/asm/poll.h
9947 @@ -0,0 +1,36 @@
9948 +/*
9949 + * arch/ubicom32/include/asm/poll.h
9950 + *   Ubicom32 specific poll() related flags definitions.
9951 + *
9952 + * (C) Copyright 2009, Ubicom, Inc.
9953 + *
9954 + * This file is part of the Ubicom32 Linux Kernel Port.
9955 + *
9956 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9957 + * it and/or modify it under the terms of the GNU General Public License
9958 + * as published by the Free Software Foundation, either version 2 of the
9959 + * License, or (at your option) any later version.
9960 + *
9961 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9962 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9963 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
9964 + * the GNU General Public License for more details.
9965 + *
9966 + * You should have received a copy of the GNU General Public License
9967 + * along with the Ubicom32 Linux Kernel Port.  If not,
9968 + * see <http://www.gnu.org/licenses/>.
9969 + *
9970 + * Ubicom32 implementation derived from (with many thanks):
9971 + *   arch/m68knommu
9972 + *   arch/blackfin
9973 + *   arch/parisc
9974 + */
9975 +#ifndef _ASM_UBICOM32_POLL_H
9976 +#define _ASM_UBICOM32_POLL_H
9977 +
9978 +#define POLLWRNORM     POLLOUT
9979 +#define POLLWRBAND     0x0100
9980 +
9981 +#include <asm-generic/poll.h>
9982 +
9983 +#endif /* _ASM_UBICOM32_POLL_H */
9984 --- /dev/null
9985 +++ b/arch/ubicom32/include/asm/posix_types.h
9986 @@ -0,0 +1,93 @@
9987 +/*
9988 + * arch/ubicom32/include/asm/posix_types.h
9989 + *   Ubicom32 architecture posix types.
9990 + *
9991 + * (C) Copyright 2009, Ubicom, Inc.
9992 + * Copyright (C) 2004   Microtronix Datacom Ltd
9993 + *
9994 + * This file is part of the Ubicom32 Linux Kernel Port.
9995 + *
9996 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9997 + * it and/or modify it under the terms of the GNU General Public License
9998 + * as published by the Free Software Foundation, either version 2 of the
9999 + * License, or (at your option) any later version.
10000 + *
10001 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10002 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10003 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10004 + * the GNU General Public License for more details.
10005 + *
10006 + * You should have received a copy of the GNU General Public License
10007 + * along with the Ubicom32 Linux Kernel Port.  If not,
10008 + * see <http://www.gnu.org/licenses/>.
10009 + *
10010 + * Ubicom32 implementation derived from (with many thanks):
10011 + *   arch/m68knommu
10012 + *   arch/blackfin
10013 + *   arch/parisc
10014 + */
10015 +#ifndef __ARCH_UBICOM32_POSIX_TYPES_H
10016 +#define __ARCH_UBICOM32_POSIX_TYPES_H
10017 +
10018 +/*
10019 + * This file is generally used by user-level software, so you need to
10020 + * be a little careful about namespace pollution etc.  Also, we cannot
10021 + * assume GCC is being used.
10022 + */
10023 +
10024 +typedef unsigned long  __kernel_ino_t;
10025 +typedef unsigned short __kernel_mode_t;
10026 +typedef unsigned short __kernel_nlink_t;
10027 +typedef long           __kernel_off_t;
10028 +typedef int            __kernel_pid_t;
10029 +typedef unsigned short __kernel_ipc_pid_t;
10030 +typedef unsigned short __kernel_uid_t;
10031 +typedef unsigned short __kernel_gid_t;
10032 +typedef unsigned int   __kernel_size_t;
10033 +typedef int            __kernel_ssize_t;
10034 +typedef int            __kernel_ptrdiff_t;
10035 +typedef long           __kernel_time_t;
10036 +typedef long           __kernel_suseconds_t;
10037 +typedef long           __kernel_clock_t;
10038 +typedef int            __kernel_timer_t;
10039 +typedef int            __kernel_clockid_t;
10040 +typedef int            __kernel_daddr_t;
10041 +typedef char *         __kernel_caddr_t;
10042 +typedef unsigned short __kernel_uid16_t;
10043 +typedef unsigned short __kernel_gid16_t;
10044 +typedef unsigned int   __kernel_uid32_t;
10045 +typedef unsigned int   __kernel_gid32_t;
10046 +
10047 +typedef unsigned short __kernel_old_uid_t;
10048 +typedef unsigned short __kernel_old_gid_t;
10049 +typedef unsigned short __kernel_old_dev_t;
10050 +
10051 +#ifdef __GNUC__
10052 +typedef long long      __kernel_loff_t;
10053 +#endif
10054 +
10055 +typedef struct {
10056 +#if defined(__KERNEL__) || defined(__USE_ALL)
10057 +       int     val[2];
10058 +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10059 +       int     __val[2];
10060 +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10061 +} __kernel_fsid_t;
10062 +
10063 +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
10064 +
10065 +#undef __FD_SET
10066 +#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
10067 +
10068 +#undef __FD_CLR
10069 +#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
10070 +
10071 +#undef __FD_ISSET
10072 +#define        __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
10073 +
10074 +#undef __FD_ZERO
10075 +#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
10076 +
10077 +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
10078 +
10079 +#endif
10080 --- /dev/null
10081 +++ b/arch/ubicom32/include/asm/processor.h
10082 @@ -0,0 +1,163 @@
10083 +/*
10084 + * arch/ubicom32/include/asm/processor.h
10085 + *   Thread related definitions for Ubicom32 architecture.
10086 + *
10087 + * (C) Copyright 2009, Ubicom, Inc.
10088 + * Copyright (C) 1995 Hamish Macdonald
10089 + *
10090 + * This file is part of the Ubicom32 Linux Kernel Port.
10091 + *
10092 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10093 + * it and/or modify it under the terms of the GNU General Public License
10094 + * as published by the Free Software Foundation, either version 2 of the
10095 + * License, or (at your option) any later version.
10096 + *
10097 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10098 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10099 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10100 + * the GNU General Public License for more details.
10101 + *
10102 + * You should have received a copy of the GNU General Public License
10103 + * along with the Ubicom32 Linux Kernel Port.  If not,
10104 + * see <http://www.gnu.org/licenses/>.
10105 + *
10106 + * Ubicom32 implementation derived from (with many thanks):
10107 + *   arch/m68knommu
10108 + *   arch/blackfin
10109 + *   arch/parisc
10110 + */
10111 +
10112 +#ifndef _ASM_UBICOM32_PROCESSOR_H
10113 +#define _ASM_UBICOM32_PROCESSOR_H
10114 +
10115 +/*
10116 + * Default implementation of macro that returns current
10117 + * instruction pointer ("program counter").
10118 + */
10119 +#define current_text_addr() ({ __label__ _l; _l: &&_l;})
10120 +
10121 +#include <linux/compiler.h>
10122 +#include <linux/threads.h>
10123 +#include <asm/types.h>
10124 +#include <asm/segment.h>
10125 +#include <asm/fpu.h>
10126 +#include <asm/ptrace.h>
10127 +#include <asm/current.h>
10128 +#include <asm/thread_info.h>
10129 +
10130 +#if defined(CONFIG_UBICOM32_V3)
10131 +       #define CPU "IP5K"
10132 +#endif
10133 +#if defined(CONFIG_UBICOM32_V4)
10134 +       #define CPU "IP7K"
10135 +#endif
10136 +#ifndef CPU
10137 +       #define CPU "UNKNOWN"
10138 +#endif
10139 +
10140 +/*
10141 + * User space process size: 1st byte beyond user address space.
10142 + */
10143 +extern unsigned long memory_end;
10144 +#define TASK_SIZE      (memory_end)
10145 +
10146 +/*
10147 + * This decides where the kernel will search for a free chunk of vm
10148 + * space during mmap's. We won't be using it
10149 + */
10150 +#define TASK_UNMAPPED_BASE     0
10151 +
10152 +/*
10153 + * This is the structure where we are going to save callee-saved registers.
10154 + * A5 is the return address, A7 is the stack pointer, A6 is the frame
10155 + * pointer.  This is the frame that is created because of switch_to. This
10156 + * is not the frame due to interrupt preemption or because of syscall entry.
10157 + */
10158 +
10159 +struct thread_struct {
10160 +       unsigned long  d10;             /* D10  */
10161 +       unsigned long  d11;             /* D11  */
10162 +       unsigned long  d12;             /* D12  */
10163 +       unsigned long  d13;             /* D13  */
10164 +       unsigned long  a1;              /* A1  */
10165 +       unsigned long  a2;              /* A2  */
10166 +       unsigned long  a5;              /* A5 return address. */
10167 +       unsigned long  a6;              /* A6 */
10168 +       unsigned long  sp;              /* A7 kernel stack pointer. */
10169 +};
10170 +
10171 +#define INIT_THREAD  { \
10172 +       0, 0, 0, 0, 0, 0, 0, 0, \
10173 +       sizeof(init_stack) + (unsigned long) init_stack - 8, \
10174 +}
10175 +
10176 +/*
10177 + * Do necessary setup to start up a newly executed thread.
10178 + *
10179 + * pass the data segment into user programs if it exists,
10180 + * it can't hurt anything as far as I can tell
10181 + */
10182 +/*
10183 + * Do necessary setup to start up a newly executed thread.
10184 + */
10185 +#define start_thread(regs, new_pc, new_sp)      \
10186 +       do {                                     \
10187 +               regs->pc = new_pc & ~3;          \
10188 +               regs->an[5] = new_pc & ~3;       \
10189 +               regs->an[7] = new_sp;            \
10190 +               regs->nesting_level = -1;        \
10191 +               regs->frame_type = UBICOM32_FRAME_TYPE_NEW_THREAD; \
10192 +               regs->thread_type = NORMAL_THREAD; \
10193 +       } while(0)
10194 +
10195 +/* Forward declaration, a strange C thing */
10196 +struct task_struct;
10197 +
10198 +/* Free all resources held by a thread. */
10199 +static inline void release_thread(struct task_struct *dead_task)
10200 +{
10201 +}
10202 +
10203 +/* Prepare to copy thread state - unlazy all lazy status */
10204 +#define prepare_to_copy(tsk)   do { } while (0)
10205 +
10206 +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
10207 +
10208 +/*
10209 + * Free current thread data structures etc..
10210 + */
10211 +static inline void exit_thread(void)
10212 +{
10213 +}
10214 +
10215 +unsigned long thread_saved_pc(struct task_struct *tsk);
10216 +unsigned long get_wchan(struct task_struct *p);
10217 +
10218 +#define        KSTK_EIP(tsk)   (tsk->thread.a5)
10219 +#define        KSTK_ESP(tsk)   (tsk->thread.sp)
10220 +
10221 +#define cpu_relax()    barrier()
10222 +
10223 +extern void processor_init(void);
10224 +extern unsigned int processor_timers(void);
10225 +extern unsigned int processor_threads(void);
10226 +extern unsigned int processor_frequency(void);
10227 +extern int processor_interrupts(unsigned int *int0, unsigned int *int1);
10228 +extern void processor_ocm(unsigned long *socm, unsigned long *eocm);
10229 +extern void processor_dram(unsigned long *sdram, unsigned long *edram);
10230 +
10231 +#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
10232 +#define KSTK_TOP(info)                                                 \
10233 +({                                                                     \
10234 +       unsigned long *__ptr = (unsigned long *)(info);                 \
10235 +       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
10236 +})
10237 +
10238 +#define task_pt_regs(task)                                             \
10239 +({                                                                     \
10240 +       struct pt_regs *__regs__;                                       \
10241 +       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
10242 +       __regs__ - 1;                                                   \
10243 +})
10244 +
10245 +#endif /* _ASM_UBICOM32_PROCESSOR_H */
10246 --- /dev/null
10247 +++ b/arch/ubicom32/include/asm/profilesample.h
10248 @@ -0,0 +1,44 @@
10249 +/*
10250 + * arch/ubicom32/mach-common/profile.h
10251 + *   Private data for the profile module
10252 + *
10253 + * (C) Copyright 2009, Ubicom, Inc.
10254 + *
10255 + * This file is part of the Ubicom32 Linux Kernel Port.
10256 + *
10257 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10258 + * it and/or modify it under the terms of the GNU General Public License
10259 + * as published by the Free Software Foundation, either version 2 of the
10260 + * License, or (at your option) any later version.
10261 + *
10262 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10263 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10264 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10265 + * the GNU General Public License for more details.
10266 + *
10267 + * You should have received a copy of the GNU General Public License
10268 + * along with the Ubicom32 Linux Kernel Port.  If not,
10269 + * see <http://www.gnu.org/licenses/>.
10270 + *
10271 + */
10272 +
10273 +
10274 +#ifndef _PROFILESAMPLE_H_
10275 +#define _PROFILESAMPLE_H_
10276 +
10277 +/*
10278 + * a sample taken by the ipProfile package for sending to the profilertool
10279 + */
10280 +struct profile_sample {
10281 +       unsigned int pc;                        /* PC value */
10282 +       unsigned int a5;                        /* a5 contents for parent of leaf function */
10283 +       unsigned int parent;                    /* return address from stack, to find the caller */
10284 +       unsigned int latency;                   /* CPU clocks since the last message dispatch in this thread (thread 0 ony for now) */
10285 +       unsigned short active;                  /* which threads are active - for accurate counting */
10286 +       unsigned short d_blocked;               /* which threads are blocked due to D cache misses */
10287 +       unsigned short i_blocked;               /* which threads are blocked due to I cache misses */
10288 +       unsigned char cond_codes;               /* for branch prediction */
10289 +       unsigned char thread;                   /* I-blocked, D-blocked, 4-bit thread number */
10290 +};
10291 +
10292 +#endif
10293 --- /dev/null
10294 +++ b/arch/ubicom32/include/asm/ptrace.h
10295 @@ -0,0 +1,177 @@
10296 +/*
10297 + * arch/ubicom32/include/asm/ptrace.h
10298 + *   Ubicom32 architecture ptrace support.
10299 + *
10300 + * (C) Copyright 2009, Ubicom, Inc.
10301 + *
10302 + * This file is part of the Ubicom32 Linux Kernel Port.
10303 + *
10304 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10305 + * it and/or modify it under the terms of the GNU General Public License
10306 + * as published by the Free Software Foundation, either version 2 of the
10307 + * License, or (at your option) any later version.
10308 + *
10309 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10310 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10311 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10312 + * the GNU General Public License for more details.
10313 + *
10314 + * You should have received a copy of the GNU General Public License
10315 + * along with the Ubicom32 Linux Kernel Port.  If not,
10316 + * see <http://www.gnu.org/licenses/>.
10317 + *
10318 + * Ubicom32 implementation derived from (with many thanks):
10319 + *   arch/m68knommu
10320 + *   arch/blackfin
10321 + *   arch/parisc
10322 + */
10323 +#ifndef _ASM_UBICOM32_PTRACE_H
10324 +#define _ASM_UBICOM32_PTRACE_H
10325 +
10326 +#ifndef __ASSEMBLY__
10327 +
10328 +/*
10329 + * We use hard coded constants because this is shared with user
10330 + * space and the values are NOT allowed to change.  Only fields
10331 + * that are intended to be exposed get values.
10332 + */
10333 +#define PT_D0           0
10334 +#define PT_D1           4
10335 +#define PT_D2           8
10336 +#define PT_D3           12
10337 +#define PT_D4           16
10338 +#define PT_D5           20
10339 +#define PT_D6           24
10340 +#define PT_D7           28
10341 +#define PT_D8           32
10342 +#define PT_D9           36
10343 +#define PT_D10          40
10344 +#define PT_D11          44
10345 +#define PT_D12          48
10346 +#define PT_D13          52
10347 +#define PT_D14          56
10348 +#define PT_D15          60
10349 +#define PT_A0           64
10350 +#define PT_A1           68
10351 +#define PT_A2           72
10352 +#define PT_A3           76
10353 +#define PT_A4           80
10354 +#define PT_A5           84
10355 +#define PT_A6           88
10356 +#define PT_A7           92
10357 +#define PT_SP           92
10358 +#define PT_ACC0HI       96
10359 +#define PT_ACC0LO       100
10360 +#define PT_MAC_RC16     104
10361 +#define PT_ACC1HI       108
10362 +#define PT_ACC1LO       112
10363 +#define PT_SOURCE3      116
10364 +#define PT_INST_CNT     120
10365 +#define PT_CSR          124
10366 +#define PT_DUMMY_UNUSED 128
10367 +#define PT_INT_MASK0    132
10368 +#define PT_INT_MASK1    136
10369 +#define PT_TRAP_CAUSE   140
10370 +#define PT_PC           144
10371 +#define PT_ORIGINAL_D0  148
10372 +#define PT_FRAME_TYPE   152
10373 +
10374 +/*
10375 + * The following 'registers' are not registers at all but are used
10376 + * locate the relocated sections.
10377 + */
10378 +#define PT_TEXT_ADDR           200
10379 +#define PT_TEXT_END_ADDR       204
10380 +#define PT_DATA_ADDR           208
10381 +#define PT_EXEC_FDPIC_LOADMAP  212
10382 +#define PT_INTERP_FDPIC_LOADMAP        216
10383 +
10384 +/*
10385 + * This struct defines the way the registers are stored on the
10386 + * stack during a system call.
10387 + */
10388 +enum thread_type {
10389 +       NORMAL_THREAD,
10390 +       KERNEL_THREAD,
10391 +};
10392 +
10393 +#define UBICOM32_FRAME_TYPE_SYSCALL    -1 /* System call frame */
10394 +#define UBICOM32_FRAME_TYPE_INVALID    0 /* Invalid frame, no longer in use */
10395 +#define UBICOM32_FRAME_TYPE_INTERRUPT  1 /* Interrupt frame */
10396 +#define UBICOM32_FRAME_TYPE_TRAP       2 /* Trap frame */
10397 +#define UBICOM32_FRAME_TYPE_SIGTRAMP   3 /* Signal trampoline frame. */
10398 +#define UBICOM32_FRAME_TYPE_NEW_THREAD 4 /* New Thread. */
10399 +
10400 +struct pt_regs {
10401 +       /*
10402 +        * Data Registers
10403 +        */
10404 +       unsigned long dn[16];
10405 +
10406 +       /*
10407 +        * Address Registers
10408 +        */
10409 +       unsigned long an[8];
10410 +
10411 +       /*
10412 +        * Per thread misc registers.
10413 +        */
10414 +       unsigned long acc0[2];
10415 +       unsigned long mac_rc16;
10416 +       unsigned long acc1[2];
10417 +       unsigned long source3;
10418 +       unsigned long inst_cnt;
10419 +       unsigned long csr;
10420 +       unsigned long dummy_unused;
10421 +       unsigned long int_mask0;
10422 +       unsigned long int_mask1;
10423 +       unsigned long trap_cause;
10424 +       unsigned long pc;
10425 +       unsigned long original_dn_0;
10426 +
10427 +       /*
10428 +        * Frame type. Syscall frames are -1. For other types look above.
10429 +        */
10430 +       unsigned long frame_type;
10431 +
10432 +       /*
10433 +        * These fields are not exposed to ptrace.
10434 +        */
10435 +       unsigned long previous_pc;
10436 +       long nesting_level;             /* When the kernel in in user space this
10437 +                                        * will be -1. */
10438 +       unsigned long thread_type;      /* This indicates if this is a kernel
10439 +                                        * thread. */
10440 +};
10441 +
10442 +/*
10443 + * This is the extended stack used by signal handlers and the context
10444 + * switcher: it's pushed after the normal "struct pt_regs".
10445 + */
10446 +struct switch_stack {
10447 +       unsigned long  dummy;
10448 +};
10449 +
10450 +#ifdef __KERNEL__
10451 +
10452 +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
10453 +#define PTRACE_GETREGS         12
10454 +#define PTRACE_SETREGS         13
10455 +
10456 +#ifndef PS_S
10457 +#define PS_S  (0x2000)
10458 +#define PS_M  (0x1000)
10459 +#endif
10460 +
10461 +extern  int __user_mode(unsigned long sp);
10462 +
10463 +#define user_mode(regs) (__user_mode((regs->an[7])))
10464 +#define user_stack(regs) ((regs)->an[7])
10465 +#define instruction_pointer(regs) ((regs)->pc)
10466 +#define profile_pc(regs) instruction_pointer(regs)
10467 +extern void show_regs(struct pt_regs *);
10468 +#endif /* __KERNEL__ */
10469 +
10470 +#endif /* __ASSEMBLY__ */
10471 +
10472 +#endif /* _ASM_UBICOM32_PTRACE_H */
10473 --- /dev/null
10474 +++ b/arch/ubicom32/include/asm/range-protect-asm.h
10475 @@ -0,0 +1,91 @@
10476 +/*
10477 + * arch/ubicom32/include/asm/range-protect-asm.h
10478 + *   Assembly macros for enabling memory protection.
10479 + *
10480 + * (C) Copyright 2009, Ubicom, Inc.
10481 + *
10482 + * This file is part of the Ubicom32 Linux Kernel Port.
10483 + *
10484 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10485 + * it and/or modify it under the terms of the GNU General Public License
10486 + * as published by the Free Software Foundation, either version 2 of the
10487 + * License, or (at your option) any later version.
10488 + *
10489 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10490 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10491 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10492 + * the GNU General Public License for more details.
10493 + *
10494 + * You should have received a copy of the GNU General Public License
10495 + * along with the Ubicom32 Linux Kernel Port.  If not,
10496 + * see <http://www.gnu.org/licenses/>.
10497 + *
10498 + * Ubicom32 implementation derived from (with many thanks):
10499 + *   arch/m68knommu
10500 + *   arch/blackfin
10501 + *   arch/parisc
10502 + */
10503 +
10504 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10505 +#define _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10506 +
10507 +#if defined(__ASSEMBLY__)
10508 +
10509 +#include <asm/thread-asm.h>
10510 +
10511 +/*
10512 + * You should only use the enable/disable ranges when you have the atomic lock,
10513 + * if you do not there will be problems.
10514 + */
10515 +
10516 +/*
10517 + * enable_kernel_ranges
10518 + *     Enable the kernel ranges (disabling protection) for thread,
10519 + *     where thread == (1 << thread number)
10520 + */
10521 +.macro enable_kernel_ranges thread
10522 +#ifdef CONFIG_PROTECT_KERNEL
10523 +       or.4    I_RANGE0_EN, I_RANGE0_EN, \thread        /* Enable Range Register */
10524 +       or.4    D_RANGE0_EN, D_RANGE0_EN, \thread
10525 +       or.4    D_RANGE1_EN, D_RANGE1_EN, \thread
10526 +#endif
10527 +.endm
10528 +
10529 +/*
10530 + * enable_kernel_ranges_for_current
10531 + *     Enable the kernel ranges (disabling protection) for this thread
10532 + */
10533 +.macro enable_kernel_ranges_for_current scratch_reg
10534 +#ifdef CONFIG_PROTECT_KERNEL
10535 +       thread_get_self_mask \scratch_reg
10536 +       enable_kernel_ranges \scratch_reg
10537 +#endif
10538 +.endm
10539 +
10540 +/*
10541 + * disable_kernel_ranges
10542 + *     Disables the kernel ranges (enabling protection) for thread
10543 + *     where thread == (1 << thread number)
10544 + */
10545 +.macro disable_kernel_ranges thread
10546 +#ifdef CONFIG_PROTECT_KERNEL
10547 +       not.4   \thread, \thread
10548 +       and.4   I_RANGE0_EN, I_RANGE0_EN, \thread        /* Disable Range Register */
10549 +       and.4   D_RANGE0_EN, D_RANGE0_EN, \thread
10550 +       and.4   D_RANGE1_EN, D_RANGE1_EN, \thread
10551 +#endif
10552 +.endm
10553 +
10554 +/*
10555 + * disable_kernel_ranges_for_current
10556 + *     Disable kernel ranges (enabling protection) for this thread
10557 + */
10558 +.macro disable_kernel_ranges_for_current scratch_reg
10559 +#ifdef CONFIG_PROTECT_KERNEL
10560 +       thread_get_self_mask \scratch_reg
10561 +       disable_kernel_ranges \scratch_reg
10562 +#endif
10563 +.endm
10564 +#endif
10565 +
10566 +#endif  /* _ASM_UBICOM32_RANGE_PROTECT_ASM_H */
10567 --- /dev/null
10568 +++ b/arch/ubicom32/include/asm/range-protect.h
10569 @@ -0,0 +1,62 @@
10570 +/*
10571 + * arch/ubicom32/include/asm/range-protect.h
10572 + *   Assembly macros declared in C for enabling memory protection.
10573 + *
10574 + * (C) Copyright 2009, Ubicom, Inc.
10575 + *
10576 + * This file is part of the Ubicom32 Linux Kernel Port.
10577 + *
10578 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10579 + * it and/or modify it under the terms of the GNU General Public License
10580 + * as published by the Free Software Foundation, either version 2 of the
10581 + * License, or (at your option) any later version.
10582 + *
10583 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10584 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10585 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10586 + * the GNU General Public License for more details.
10587 + *
10588 + * You should have received a copy of the GNU General Public License
10589 + * along with the Ubicom32 Linux Kernel Port.  If not,
10590 + * see <http://www.gnu.org/licenses/>.
10591 + *
10592 + * Ubicom32 implementation derived from (with many thanks):
10593 + *   arch/m68knommu
10594 + *   arch/blackfin
10595 + *   arch/parisc
10596 + */
10597 +
10598 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_H
10599 +#define _ASM_UBICOM32_RANGE_PROTECT_H
10600 +
10601 +#if !defined(__ASSEMBLY__)
10602 +#include <asm/thread.h>
10603 +/*
10604 + * The following macros should be the identical to the ones in
10605 + * range-protect-asm.h
10606 + *
10607 + * You should only use the enable/disable ranges when you have the atomic lock,
10608 + * if you do not there will be problems.
10609 + */
10610 +
10611 +/*
10612 + * enable_kernel_ranges
10613 + *     Enable the kernel ranges (disabling protection) for thread,
10614 + *     where thread == (1 << thread number)
10615 + */
10616 +asm (
10617 +       ".macro enable_kernel_ranges thread                     \n\t"
10618 +#ifdef CONFIG_PROTECT_KERNEL
10619 +       "       or.4    I_RANGE0_EN, I_RANGE0_EN, \\thread      \n\t" /* Enable Range Register */
10620 +       "       or.4    D_RANGE0_EN, D_RANGE0_EN, \\thread      \n\t"
10621 +       "       or.4    D_RANGE1_EN, D_RANGE1_EN, \\thread      \n\t"
10622 +#endif
10623 +       ".endm                                                  \n\t"
10624 +);
10625 +
10626 +#else /* __ASSEMBLY__ */
10627 +
10628 +#include <asm/range-protect-asm.h>
10629 +
10630 +#endif
10631 +#endif  /* _ASM_UBICOM32_RANGE_PROTECT_H */
10632 --- /dev/null
10633 +++ b/arch/ubicom32/include/asm/resource.h
10634 @@ -0,0 +1,33 @@
10635 +/*
10636 + * arch/ubicom32/include/asm/resource.h
10637 + *   Generic definitions for Ubicom32 architecture.
10638 + *
10639 + * (C) Copyright 2009, Ubicom, Inc.
10640 + *
10641 + * This file is part of the Ubicom32 Linux Kernel Port.
10642 + *
10643 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10644 + * it and/or modify it under the terms of the GNU General Public License
10645 + * as published by the Free Software Foundation, either version 2 of the
10646 + * License, or (at your option) any later version.
10647 + *
10648 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10649 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10650 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10651 + * the GNU General Public License for more details.
10652 + *
10653 + * You should have received a copy of the GNU General Public License
10654 + * along with the Ubicom32 Linux Kernel Port.  If not,
10655 + * see <http://www.gnu.org/licenses/>.
10656 + *
10657 + * Ubicom32 implementation derived from (with many thanks):
10658 + *   arch/m68knommu
10659 + *   arch/blackfin
10660 + *   arch/parisc
10661 + */
10662 +#ifndef _ASM_UBICOM32_RESOURCE_H
10663 +#define _ASM_UBICOM32_RESOURCE_H
10664 +
10665 +#include <asm-generic/resource.h>
10666 +
10667 +#endif /* _ASM_UBICOM32_RESOURCE_H */
10668 --- /dev/null
10669 +++ b/arch/ubicom32/include/asm/ring_tio.h
10670 @@ -0,0 +1,42 @@
10671 +/*
10672 + * arch/ubicom32/include/asm/ring_tio.h
10673 + *   Ubicom32 architecture Ring TIO definitions.
10674 + *
10675 + * (C) Copyright 2009, Ubicom, Inc.
10676 + *
10677 + * This file is part of the Ubicom32 Linux Kernel Port.
10678 + *
10679 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10680 + * it and/or modify it under the terms of the GNU General Public License
10681 + * as published by the Free Software Foundation, either version 2 of the
10682 + * License, or (at your option) any later version.
10683 + *
10684 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10685 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10686 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10687 + * the GNU General Public License for more details.
10688 + *
10689 + * You should have received a copy of the GNU General Public License
10690 + * along with the Ubicom32 Linux Kernel Port.  If not,
10691 + * see <http://www.gnu.org/licenses/>.
10692 + */
10693 +#ifndef _ASM_UBICOM32_RING_TIO_H
10694 +#define _ASM_UBICOM32_RING_TIO_H
10695 +
10696 +#include <asm/devtree.h>
10697 +
10698 +#define RING_TIO_NODE_VERSION  2
10699 +
10700 +/*
10701 + * Devtree node for ring
10702 + */
10703 +struct ring_tio_node {
10704 +       struct devtree_node     dn;
10705 +
10706 +       u32_t                   version;
10707 +       void                    *regs;
10708 +};
10709 +
10710 +extern void ring_tio_init(const char *node_name);
10711 +
10712 +#endif /* _ASM_UBICOM32_RING_TIO_H */
10713 --- /dev/null
10714 +++ b/arch/ubicom32/include/asm/scatterlist.h
10715 @@ -0,0 +1,49 @@
10716 +/*
10717 + * arch/ubicom32/include/asm/scatterlist.h
10718 + *   Definitions of struct scatterlist for Ubicom32 architecture.
10719 + *
10720 + * (C) Copyright 2009, Ubicom, Inc.
10721 + *
10722 + * This file is part of the Ubicom32 Linux Kernel Port.
10723 + *
10724 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10725 + * it and/or modify it under the terms of the GNU General Public License
10726 + * as published by the Free Software Foundation, either version 2 of the
10727 + * License, or (at your option) any later version.
10728 + *
10729 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10730 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10731 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10732 + * the GNU General Public License for more details.
10733 + *
10734 + * You should have received a copy of the GNU General Public License
10735 + * along with the Ubicom32 Linux Kernel Port.  If not,
10736 + * see <http://www.gnu.org/licenses/>.
10737 + *
10738 + * Ubicom32 implementation derived from (with many thanks):
10739 + *   arch/m68knommu
10740 + *   arch/blackfin
10741 + *   arch/parisc
10742 + */
10743 +#ifndef _ASM_UBICOM32_SCATTERLIST_H
10744 +#define _ASM_UBICOM32_SCATTERLIST_H
10745 +
10746 +#include <linux/mm.h>
10747 +#include <asm/types.h>
10748 +
10749 +struct scatterlist {
10750 +#ifdef CONFIG_DEBUG_SG
10751 +       unsigned long   sg_magic;
10752 +#endif
10753 +       unsigned long   page_link;
10754 +       unsigned int    offset;
10755 +       dma_addr_t      dma_address;
10756 +       unsigned int    length;
10757 +};
10758 +
10759 +#define sg_dma_address(sg)      ((sg)->dma_address)
10760 +#define sg_dma_len(sg)          ((sg)->length)
10761 +
10762 +#define ISA_DMA_THRESHOLD      (0xffffffff)
10763 +
10764 +#endif /* _ASM_UBICOM32_SCATTERLIST_H */
10765 --- /dev/null
10766 +++ b/arch/ubicom32/include/asm/sd_tio.h
10767 @@ -0,0 +1,36 @@
10768 +/*
10769 + * arch/ubicom32/include/asm/sd_tio.h
10770 + *   SD TIO definitions
10771 + *
10772 + * (C) Copyright 2009, Ubicom, Inc.
10773 + *
10774 + * This file is part of the Ubicom32 Linux Kernel Port.
10775 + *
10776 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10777 + * it and/or modify it under the terms of the GNU General Public License
10778 + * as published by the Free Software Foundation, either version 2 of the
10779 + * License, or (at your option) any later version.
10780 + *
10781 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10782 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10783 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10784 + * the GNU General Public License for more details.
10785 + *
10786 + * You should have received a copy of the GNU General Public License
10787 + * along with the Ubicom32 Linux Kernel Port.  If not,
10788 + * see <http://www.gnu.org/licenses/>.
10789 + */
10790 +#ifndef _ASM_UBICOM32_SD_TIO_H
10791 +#define _ASM_UBICOM32_SD_TIO_H
10792 +
10793 +#include <asm/devtree.h>
10794 +
10795 +/*
10796 + * Devtree node for SD
10797 + */
10798 +struct sd_tio_node {
10799 +       struct devtree_node     dn;
10800 +       void                    *regs;
10801 +};
10802 +
10803 +#endif /* _ASM_UBICOM32_SD_TIO_H */
10804 --- /dev/null
10805 +++ b/arch/ubicom32/include/asm/sections.h
10806 @@ -0,0 +1,33 @@
10807 +/*
10808 + * arch/ubicom32/include/asm/sections.h
10809 + *   Generic sections.h definitions for Ubicom32 architecture.
10810 + *
10811 + * (C) Copyright 2009, Ubicom, Inc.
10812 + *
10813 + * This file is part of the Ubicom32 Linux Kernel Port.
10814 + *
10815 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10816 + * it and/or modify it under the terms of the GNU General Public License
10817 + * as published by the Free Software Foundation, either version 2 of the
10818 + * License, or (at your option) any later version.
10819 + *
10820 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10821 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10822 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10823 + * the GNU General Public License for more details.
10824 + *
10825 + * You should have received a copy of the GNU General Public License
10826 + * along with the Ubicom32 Linux Kernel Port.  If not,
10827 + * see <http://www.gnu.org/licenses/>.
10828 + *
10829 + * Ubicom32 implementation derived from (with many thanks):
10830 + *   arch/m68knommu
10831 + *   arch/blackfin
10832 + *   arch/parisc
10833 + */
10834 +#ifndef _ASM_UBICOM32_SECTIONS_H
10835 +#define _ASM_UBICOM32_SECTIONS_H
10836 +
10837 +#include <asm-generic/sections.h>
10838 +
10839 +#endif /* _ASM_UBICOM32_SECTIONS_H */
10840 --- /dev/null
10841 +++ b/arch/ubicom32/include/asm/segment.h
10842 @@ -0,0 +1,78 @@
10843 +/*
10844 + * arch/ubicom32/include/asm/segment.h
10845 + *   Memory segment definitions for Ubicom32 architecture.
10846 + *
10847 + * (C) Copyright 2009, Ubicom, Inc.
10848 + *
10849 + * This file is part of the Ubicom32 Linux Kernel Port.
10850 + *
10851 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10852 + * it and/or modify it under the terms of the GNU General Public License
10853 + * as published by the Free Software Foundation, either version 2 of the
10854 + * License, or (at your option) any later version.
10855 + *
10856 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10857 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10858 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10859 + * the GNU General Public License for more details.
10860 + *
10861 + * You should have received a copy of the GNU General Public License
10862 + * along with the Ubicom32 Linux Kernel Port.  If not,
10863 + * see <http://www.gnu.org/licenses/>.
10864 + *
10865 + * Ubicom32 implementation derived from (with many thanks):
10866 + *   arch/m68knommu
10867 + *   arch/blackfin
10868 + *   arch/parisc
10869 + */
10870 +#ifndef _ASM_UBICOM32_SEGMENT_H
10871 +#define _ASM_UBICOM32_SEGMENT_H
10872 +
10873 +/* define constants */
10874 +/* Address spaces (FC0-FC2) */
10875 +#define USER_DATA     (1)
10876 +#ifndef __USER_DS
10877 +#define __USER_DS     (USER_DATA)
10878 +#endif
10879 +#define USER_PROGRAM  (2)
10880 +#define SUPER_DATA    (5)
10881 +#ifndef __KERNEL_DS
10882 +#define __KERNEL_DS   (SUPER_DATA)
10883 +#endif
10884 +#define SUPER_PROGRAM (6)
10885 +#define CPU_SPACE     (7)
10886 +
10887 +#ifndef __ASSEMBLY__
10888 +
10889 +typedef struct {
10890 +       unsigned long seg;
10891 +} mm_segment_t;
10892 +
10893 +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
10894 +#define USER_DS                MAKE_MM_SEG(__USER_DS)
10895 +#define KERNEL_DS      MAKE_MM_SEG(__KERNEL_DS)
10896 +
10897 +/*
10898 + * Get/set the SFC/DFC registers for MOVES instructions
10899 + */
10900 +
10901 +static inline mm_segment_t get_fs(void)
10902 +{
10903 +    return USER_DS;
10904 +}
10905 +
10906 +static inline mm_segment_t get_ds(void)
10907 +{
10908 +    /* return the supervisor data space code */
10909 +    return KERNEL_DS;
10910 +}
10911 +
10912 +static inline void set_fs(mm_segment_t val)
10913 +{
10914 +}
10915 +
10916 +#define segment_eq(a,b)        ((a).seg == (b).seg)
10917 +
10918 +#endif /* __ASSEMBLY__ */
10919 +
10920 +#endif /* _ASM_UBICOM32_SEGMENT_H */
10921 --- /dev/null
10922 +++ b/arch/ubicom32/include/asm/semaphore.h
10923 @@ -0,0 +1,140 @@
10924 +/*
10925 + * arch/ubicom32/include/asm/semaphore.h
10926 + *   Interrupt-safe semaphores for Ubicom32 architecture.
10927 + *
10928 + * (C) Copyright 2009, Ubicom, Inc.
10929 + * (C) Copyright 1996 Linus Torvalds
10930 + * m68k version by Andreas Schwab
10931 + * Copyright (C) 2004   Microtronix Datacom Ltd
10932 + *
10933 + * This file is part of the Ubicom32 Linux Kernel Port.
10934 + *
10935 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10936 + * it and/or modify it under the terms of the GNU General Public License
10937 + * as published by the Free Software Foundation, either version 2 of the
10938 + * License, or (at your option) any later version.
10939 + *
10940 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10941 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10942 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
10943 + * the GNU General Public License for more details.
10944 + *
10945 + * You should have received a copy of the GNU General Public License
10946 + * along with the Ubicom32 Linux Kernel Port.  If not,
10947 + * see <http://www.gnu.org/licenses/>.
10948 + *
10949 + * Ubicom32 implementation derived from (with many thanks):
10950 + *   arch/m68knommu
10951 + *   arch/blackfin
10952 + *   arch/parisc
10953 + */
10954 +#ifndef _ASM_UBICOM32_SEMAPHORE_H
10955 +#define _ASM_UBICOM32_SEMAPHORE_H
10956 +
10957 +#define RW_LOCK_BIAS            0x01000000
10958 +
10959 +#ifndef __ASSEMBLY__
10960 +
10961 +#include <linux/linkage.h>
10962 +#include <linux/wait.h>
10963 +#include <linux/spinlock.h>
10964 +#include <linux/rwsem.h>
10965 +
10966 +#include <asm/system.h>
10967 +#include <asm/atomic.h>
10968 +
10969 +struct semaphore {
10970 +       atomic_t count;
10971 +       atomic_t waking;
10972 +       wait_queue_head_t wait;
10973 +};
10974 +
10975 +#define __SEMAPHORE_INITIALIZER(name, n)                               \
10976 +{                                                                      \
10977 +       .count          = ATOMIC_INIT(n),                               \
10978 +       .waking         = ATOMIC_INIT(0),                               \
10979 +       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
10980 +}
10981 +
10982 +#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
10983 +       struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
10984 +
10985 +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
10986 +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
10987 +
10988 +static inline void sema_init (struct semaphore *sem, int val)
10989 +{
10990 +       *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
10991 +}
10992 +
10993 +static inline void init_MUTEX (struct semaphore *sem)
10994 +{
10995 +       sema_init(sem, 1);
10996 +}
10997 +
10998 +static inline void init_MUTEX_LOCKED (struct semaphore *sem)
10999 +{
11000 +       sema_init(sem, 0);
11001 +}
11002 +
11003 +asmlinkage void __down_failed(void /* special register calling convention */);
11004 +asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
11005 +asmlinkage int  __down_failed_trylock(void  /* params in registers */);
11006 +asmlinkage void __up_wakeup(void /* special register calling convention */);
11007 +
11008 +asmlinkage void __down(struct semaphore * sem);
11009 +asmlinkage int  __down_interruptible(struct semaphore * sem);
11010 +asmlinkage int  __down_trylock(struct semaphore * sem);
11011 +asmlinkage void __up(struct semaphore * sem);
11012 +
11013 +extern spinlock_t semaphore_wake_lock;
11014 +
11015 +/*
11016 + * This is ugly, but we want the default case to fall through.
11017 + * "down_failed" is a special asm handler that calls the C
11018 + * routine that actually waits.
11019 + */
11020 +static inline void down(struct semaphore * sem)
11021 +{
11022 +       might_sleep();
11023 +
11024 +       if (atomic_dec_return(&sem->count) < 0)
11025 +               __down(sem);
11026 +}
11027 +
11028 +static inline int down_interruptible(struct semaphore * sem)
11029 +{
11030 +       int ret = 0;
11031 +
11032 +
11033 +       might_sleep();
11034 +
11035 +       if(atomic_dec_return(&sem->count) < 0)
11036 +               ret = __down_interruptible(sem);
11037 +       return ret;
11038 +}
11039 +
11040 +static inline int down_trylock(struct semaphore * sem)
11041 +{
11042 +       int ret = 0;
11043 +
11044 +       if (atomic_dec_return (&sem->count) < 0)
11045 +               ret = __down_trylock(sem);
11046 +       return ret;
11047 +}
11048 +
11049 +/*
11050 + * Note! This is subtle. We jump to wake people up only if
11051 + * the semaphore was negative (== somebody was waiting on it).
11052 + * The default case (no contention) will result in NO
11053 + * jumps for both down() and up().
11054 + */
11055 +static inline void up(struct semaphore * sem)
11056 +{
11057 +       if (atomic_inc_return(&sem->count) <= 0)
11058 +               __up(sem);
11059 +}
11060 +
11061 +#endif /* __ASSEMBLY__ */
11062 +
11063 +#endif /* _ASM_UBICOM32_SEMAPHORE_H */
11064 --- /dev/null
11065 +++ b/arch/ubicom32/include/asm/semaphore-helper.h
11066 @@ -0,0 +1,109 @@
11067 +/*
11068 + * arch/ubicom32/include/asm/semaphore-helper.h
11069 + *   Semaphore related definitions for Ubicom32 architecture.
11070 + *
11071 + * (C) Copyright 2009, Ubicom, Inc.
11072 + *
11073 + * This file is part of the Ubicom32 Linux Kernel Port.
11074 + *
11075 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11076 + * it and/or modify it under the terms of the GNU General Public License
11077 + * as published by the Free Software Foundation, either version 2 of the
11078 + * License, or (at your option) any later version.
11079 + *
11080 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11081 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11082 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11083 + * the GNU General Public License for more details.
11084 + *
11085 + * You should have received a copy of the GNU General Public License
11086 + * along with the Ubicom32 Linux Kernel Port.  If not,
11087 + * see <http://www.gnu.org/licenses/>.
11088 + *
11089 + * Ubicom32 implementation derived from (with many thanks):
11090 + *   arch/m68knommu
11091 + *   arch/blackfin
11092 + *   arch/parisc
11093 + */
11094 +#ifndef _ASM_UBICOM32_SEMAPHORE_HELPER_H
11095 +#define _ASM_UBICOM32_SEMAPHORE_HELPER_H
11096 +
11097 +/*
11098 + * SMP- and interrupt-safe semaphores helper functions.
11099 + *
11100 + * (C) Copyright 1996 Linus Torvalds
11101 + *
11102 + * m68k version by Andreas Schwab
11103 + */
11104 +
11105 +
11106 +/*
11107 + * These two _must_ execute atomically wrt each other.
11108 + */
11109 +static inline void wake_one_more(struct semaphore * sem)
11110 +{
11111 +       atomic_inc(&sem->waking);
11112 +}
11113 +
11114 +static inline int waking_non_zero(struct semaphore *sem)
11115 +{
11116 +       int ret;
11117 +       unsigned long flags;
11118 +
11119 +       spin_lock_irqsave(&semaphore_wake_lock, flags);
11120 +       ret = 0;
11121 +       if (atomic_read(&sem->waking) > 0) {
11122 +               atomic_dec(&sem->waking);
11123 +               ret = 1;
11124 +       }
11125 +       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11126 +       return ret;
11127 +}
11128 +
11129 +/*
11130 + * waking_non_zero_interruptible:
11131 + *     1       got the lock
11132 + *     0       go to sleep
11133 + *     -EINTR  interrupted
11134 + */
11135 +static inline int waking_non_zero_interruptible(struct semaphore *sem,
11136 +                                               struct task_struct *tsk)
11137 +{
11138 +       int ret;
11139 +       unsigned long flags;
11140 +
11141 +       spin_lock_irqsave(&semaphore_wake_lock, flags);
11142 +       ret = 0;
11143 +       if (atomic_read(&sem->waking) > 0) {
11144 +               atomic_dec(&sem->waking);
11145 +               ret = 1;
11146 +       } else if (signal_pending(tsk)) {
11147 +               atomic_inc(&sem->count);
11148 +               ret = -EINTR;
11149 +       }
11150 +       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11151 +       return ret;
11152 +}
11153 +
11154 +/*
11155 + * waking_non_zero_trylock:
11156 + *     1       failed to lock
11157 + *     0       got the lock
11158 + */
11159 +static inline int waking_non_zero_trylock(struct semaphore *sem)
11160 +{
11161 +       int ret;
11162 +       unsigned long flags;
11163 +
11164 +       spin_lock_irqsave(&semaphore_wake_lock, flags);
11165 +       ret = 1;
11166 +       if (atomic_read(&sem->waking) > 0) {
11167 +               atomic_dec(&sem->waking);
11168 +               ret = 0;
11169 +       } else
11170 +               atomic_inc(&sem->count);
11171 +       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11172 +       return ret;
11173 +}
11174 +
11175 +#endif /* _ASM_UBICOM32_SEMAPHORE_HELPER_H */
11176 --- /dev/null
11177 +++ b/arch/ubicom32/include/asm/sembuf.h
11178 @@ -0,0 +1,52 @@
11179 +/*
11180 + * arch/ubicom32/include/asm/sembuf.h
11181 + *   The semid64_ds structure for Ubicom32 architecture.
11182 + *
11183 + * (C) Copyright 2009, Ubicom, Inc.
11184 + *
11185 + * This file is part of the Ubicom32 Linux Kernel Port.
11186 + *
11187 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11188 + * it and/or modify it under the terms of the GNU General Public License
11189 + * as published by the Free Software Foundation, either version 2 of the
11190 + * License, or (at your option) any later version.
11191 + *
11192 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11193 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11194 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11195 + * the GNU General Public License for more details.
11196 + *
11197 + * You should have received a copy of the GNU General Public License
11198 + * along with the Ubicom32 Linux Kernel Port.  If not,
11199 + * see <http://www.gnu.org/licenses/>.
11200 + *
11201 + * Ubicom32 implementation derived from (with many thanks):
11202 + *   arch/m68knommu
11203 + *   arch/blackfin
11204 + *   arch/parisc
11205 + */
11206 +#ifndef _ASM_UBICOM32_SEMBUF_H
11207 +#define _ASM_UBICOM32_SEMBUF_H
11208 +
11209 +/*
11210 + * The semid64_ds structure for ubicom32 architecture.
11211 + * Note extra padding because this structure is passed back and forth
11212 + * between kernel and user space.
11213 + *
11214 + * Pad space is left for:
11215 + * - 64-bit time_t to solve y2038 problem
11216 + * - 2 miscellaneous 32-bit values
11217 + */
11218 +
11219 +struct semid64_ds {
11220 +       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
11221 +       __kernel_time_t sem_otime;              /* last semop time */
11222 +       unsigned long   __unused1;
11223 +       __kernel_time_t sem_ctime;              /* last change time */
11224 +       unsigned long   __unused2;
11225 +       unsigned long   sem_nsems;              /* no. of semaphores in array */
11226 +       unsigned long   __unused3;
11227 +       unsigned long   __unused4;
11228 +};
11229 +
11230 +#endif /* _ASM_UBICOM32_SEMBUF_H */
11231 --- /dev/null
11232 +++ b/arch/ubicom32/include/asm/setup.h
11233 @@ -0,0 +1,35 @@
11234 +/*
11235 + * arch/ubicom32/include/asm/setup.h
11236 + *   Kernel command line length definition.
11237 + *
11238 + * (C) Copyright 2009, Ubicom, Inc.
11239 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
11240 + *
11241 + * This file is part of the Ubicom32 Linux Kernel Port.
11242 + *
11243 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11244 + * it and/or modify it under the terms of the GNU General Public License
11245 + * as published by the Free Software Foundation, either version 2 of the
11246 + * License, or (at your option) any later version.
11247 + *
11248 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11249 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11250 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11251 + * the GNU General Public License for more details.
11252 + *
11253 + * You should have received a copy of the GNU General Public License
11254 + * along with the Ubicom32 Linux Kernel Port.  If not,
11255 + * see <http://www.gnu.org/licenses/>.
11256 + *
11257 + * Ubicom32 implementation derived from (with many thanks):
11258 + *   arch/m68knommu
11259 + *   arch/blackfin
11260 + *   arch/parisc
11261 + */
11262 +
11263 +#ifndef _ASM_UBICOM32_SETUP_H
11264 +#define _ASM_UBICOM32_SETUP_H
11265 +
11266 +#define COMMAND_LINE_SIZE 512
11267 +
11268 +#endif /* _ASM_UBICOM32_SETUP_H */
11269 --- /dev/null
11270 +++ b/arch/ubicom32/include/asm/shmbuf.h
11271 @@ -0,0 +1,69 @@
11272 +/*
11273 + * arch/ubicom32/include/asm/shmbuf.h
11274 + *   The shmid64_ds structure for the Ubicom32 architecture.
11275 + *
11276 + * (C) Copyright 2009, Ubicom, Inc.
11277 + *
11278 + * This file is part of the Ubicom32 Linux Kernel Port.
11279 + *
11280 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11281 + * it and/or modify it under the terms of the GNU General Public License
11282 + * as published by the Free Software Foundation, either version 2 of the
11283 + * License, or (at your option) any later version.
11284 + *
11285 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11286 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11287 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11288 + * the GNU General Public License for more details.
11289 + *
11290 + * You should have received a copy of the GNU General Public License
11291 + * along with the Ubicom32 Linux Kernel Port.  If not,
11292 + * see <http://www.gnu.org/licenses/>.
11293 + *
11294 + * Ubicom32 implementation derived from (with many thanks):
11295 + *   arch/m68knommu
11296 + *   arch/blackfin
11297 + *   arch/parisc
11298 + */
11299 +#ifndef _ASM_UBICOM32_SHMBUF_H
11300 +#define _ASM_UBICOM32_SHMBUF_H
11301 +
11302 +/*
11303 + * The shmid64_ds structure for m68k architecture.
11304 + * Note extra padding because this structure is passed back and forth
11305 + * between kernel and user space.
11306 + *
11307 + * Pad space is left for:
11308 + * - 64-bit time_t to solve y2038 problem
11309 + * - 2 miscellaneous 32-bit values
11310 + */
11311 +
11312 +struct shmid64_ds {
11313 +       struct ipc64_perm       shm_perm;       /* operation perms */
11314 +       size_t                  shm_segsz;      /* size of segment (bytes) */
11315 +       __kernel_time_t         shm_atime;      /* last attach time */
11316 +       unsigned long           __unused1;
11317 +       __kernel_time_t         shm_dtime;      /* last detach time */
11318 +       unsigned long           __unused2;
11319 +       __kernel_time_t         shm_ctime;      /* last change time */
11320 +       unsigned long           __unused3;
11321 +       __kernel_pid_t          shm_cpid;       /* pid of creator */
11322 +       __kernel_pid_t          shm_lpid;       /* pid of last operator */
11323 +       unsigned long           shm_nattch;     /* no. of current attaches */
11324 +       unsigned long           __unused4;
11325 +       unsigned long           __unused5;
11326 +};
11327 +
11328 +struct shminfo64 {
11329 +       unsigned long   shmmax;
11330 +       unsigned long   shmmin;
11331 +       unsigned long   shmmni;
11332 +       unsigned long   shmseg;
11333 +       unsigned long   shmall;
11334 +       unsigned long   __unused1;
11335 +       unsigned long   __unused2;
11336 +       unsigned long   __unused3;
11337 +       unsigned long   __unused4;
11338 +};
11339 +
11340 +#endif /* _ASM_UBICOM32_SHMBUF_H */
11341 --- /dev/null
11342 +++ b/arch/ubicom32/include/asm/shmparam.h
11343 @@ -0,0 +1,35 @@
11344 +/*
11345 + * arch/ubicom32/include/asm/shmparam.h
11346 + *   Shared memory definitions for Ubicom32 architecture.
11347 + *
11348 + * (C) Copyright 2009, Ubicom, Inc.
11349 + * Copyright (C) 2004   Microtronix Datacom Ltd
11350 + *
11351 + * This file is part of the Ubicom32 Linux Kernel Port.
11352 + *
11353 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11354 + * it and/or modify it under the terms of the GNU General Public License
11355 + * as published by the Free Software Foundation, either version 2 of the
11356 + * License, or (at your option) any later version.
11357 + *
11358 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11359 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11360 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11361 + * the GNU General Public License for more details.
11362 + *
11363 + * You should have received a copy of the GNU General Public License
11364 + * along with the Ubicom32 Linux Kernel Port.  If not,
11365 + * see <http://www.gnu.org/licenses/>.
11366 + *
11367 + * Ubicom32 implementation derived from (with many thanks):
11368 + *   arch/m68knommu
11369 + *   arch/blackfin
11370 + *   arch/parisc
11371 + *   Alpha, ix86, M68K, Sparc, ...et al
11372 + */
11373 +#ifndef _ASM_UBICOM32_SHMPARAM_H
11374 +#define _ASM_UBICOM32_SHMPARAM_H
11375 +
11376 +#define        SHMLBA          PAGE_SIZE       /* attach addr a multiple of this */
11377 +
11378 +#endif /* _ASM_UBICOM32_SHMPARAM_H */
11379 --- /dev/null
11380 +++ b/arch/ubicom32/include/asm/sigcontext.h
11381 @@ -0,0 +1,37 @@
11382 +/*
11383 + * arch/ubicom32/include/asm/sigcontext.h
11384 + *   Definition of sigcontext struct for Ubicom32 architecture.
11385 + *
11386 + * (C) Copyright 2009, Ubicom, Inc.
11387 + *
11388 + * This file is part of the Ubicom32 Linux Kernel Port.
11389 + *
11390 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11391 + * it and/or modify it under the terms of the GNU General Public License
11392 + * as published by the Free Software Foundation, either version 2 of the
11393 + * License, or (at your option) any later version.
11394 + *
11395 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11396 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11397 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11398 + * the GNU General Public License for more details.
11399 + *
11400 + * You should have received a copy of the GNU General Public License
11401 + * along with the Ubicom32 Linux Kernel Port.  If not,
11402 + * see <http://www.gnu.org/licenses/>.
11403 + *
11404 + * Ubicom32 implementation derived from (with many thanks):
11405 + *   arch/m68knommu
11406 + *   arch/blackfin
11407 + *   arch/parisc
11408 + */
11409 +#ifndef _ASM_UBICOM32_SIGCONTEXT_H
11410 +#define _ASM_UBICOM32_SIGCONTEXT_H
11411 +
11412 +#include <asm/ptrace.h>
11413 +
11414 +struct sigcontext {
11415 +       struct pt_regs sc_regs;
11416 +};
11417 +
11418 +#endif /* _ASM_UBICOM32_SIGCONTEXT_H */
11419 --- /dev/null
11420 +++ b/arch/ubicom32/include/asm/siginfo.h
11421 @@ -0,0 +1,33 @@
11422 +/*
11423 + * arch/ubicom32/include/asm/siginfo.h
11424 + *   Generic siginfo.h definitions for Ubicom32 architecture.
11425 + *
11426 + * (C) Copyright 2009, Ubicom, Inc.
11427 + *
11428 + * This file is part of the Ubicom32 Linux Kernel Port.
11429 + *
11430 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11431 + * it and/or modify it under the terms of the GNU General Public License
11432 + * as published by the Free Software Foundation, either version 2 of the
11433 + * License, or (at your option) any later version.
11434 + *
11435 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11436 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11437 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11438 + * the GNU General Public License for more details.
11439 + *
11440 + * You should have received a copy of the GNU General Public License
11441 + * along with the Ubicom32 Linux Kernel Port.  If not,
11442 + * see <http://www.gnu.org/licenses/>.
11443 + *
11444 + * Ubicom32 implementation derived from (with many thanks):
11445 + *   arch/m68knommu
11446 + *   arch/blackfin
11447 + *   arch/parisc
11448 + */
11449 +#ifndef _ASM_UBICOM32_SIGINFO_H
11450 +#define _ASM_UBICOM32_SIGINFO_H
11451 +
11452 +#include <asm-generic/siginfo.h>
11453 +
11454 +#endif /* _ASM_UBICOM32_SIGINFO_H */
11455 --- /dev/null
11456 +++ b/arch/ubicom32/include/asm/signal.h
11457 @@ -0,0 +1,180 @@
11458 +/*
11459 + * arch/ubicom32/include/asm/signal.h
11460 + *   Signal related definitions for Ubicom32 architecture.
11461 + *
11462 + * (C) Copyright 2009, Ubicom, Inc.
11463 + *
11464 + * This file is part of the Ubicom32 Linux Kernel Port.
11465 + *
11466 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11467 + * it and/or modify it under the terms of the GNU General Public License
11468 + * as published by the Free Software Foundation, either version 2 of the
11469 + * License, or (at your option) any later version.
11470 + *
11471 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11472 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11473 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11474 + * the GNU General Public License for more details.
11475 + *
11476 + * You should have received a copy of the GNU General Public License
11477 + * along with the Ubicom32 Linux Kernel Port.  If not,
11478 + * see <http://www.gnu.org/licenses/>.
11479 + *
11480 + * Ubicom32 implementation derived from (with many thanks):
11481 + *   arch/m68knommu
11482 + *   arch/blackfin
11483 + *   arch/parisc
11484 + */
11485 +#ifndef _ASM_UBICOM32_SIGNAL_H
11486 +#define _ASM_UBICOM32_SIGNAL_H
11487 +
11488 +#include <linux/types.h>
11489 +
11490 +/* Avoid too many header ordering problems.  */
11491 +struct siginfo;
11492 +
11493 +#ifdef __KERNEL__
11494 +/* Most things should be clean enough to redefine this at will, if care
11495 +   is taken to make libc match.  */
11496 +
11497 +#define _NSIG          64
11498 +#define _NSIG_BPW      32
11499 +#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
11500 +
11501 +typedef unsigned long old_sigset_t;            /* at least 32 bits */
11502 +
11503 +typedef struct {
11504 +       unsigned long sig[_NSIG_WORDS];
11505 +} sigset_t;
11506 +
11507 +#endif /* __KERNEL__ */
11508 +
11509 +#define SIGHUP          1
11510 +#define SIGINT          2
11511 +#define SIGQUIT                 3
11512 +#define SIGILL          4
11513 +#define SIGTRAP                 5
11514 +#define SIGABRT                 6
11515 +#define SIGIOT          6
11516 +#define SIGBUS          7
11517 +#define SIGFPE          8
11518 +#define SIGKILL                 9
11519 +#define SIGUSR1                10
11520 +#define SIGSEGV                11
11521 +#define SIGUSR2                12
11522 +#define SIGPIPE                13
11523 +#define SIGALRM                14
11524 +#define SIGTERM                15
11525 +#define SIGSTKFLT      16
11526 +#define SIGCHLD                17
11527 +#define SIGCONT                18
11528 +#define SIGSTOP                19
11529 +#define SIGTSTP                20
11530 +#define SIGTTIN                21
11531 +#define SIGTTOU                22
11532 +#define SIGURG         23
11533 +#define SIGXCPU                24
11534 +#define SIGXFSZ                25
11535 +#define SIGVTALRM      26
11536 +#define SIGPROF                27
11537 +#define SIGWINCH       28
11538 +#define SIGIO          29
11539 +#define SIGPOLL                SIGIO
11540 +/*
11541 +#define SIGLOST                29
11542 +*/
11543 +#define SIGPWR         30
11544 +#define SIGSYS         31
11545 +#define        SIGUNUSED       31
11546 +
11547 +/* These should not be considered constants from userland.  */
11548 +#define SIGRTMIN       32
11549 +#define SIGRTMAX       _NSIG
11550 +
11551 +/*
11552 + * SA_FLAGS values:
11553 + *
11554 + * SA_ONSTACK indicates that a registered stack_t will be used.
11555 + * SA_RESTART flag to get restarting signals (which were the default long ago)
11556 + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
11557 + * SA_RESETHAND clears the handler when the signal is delivered.
11558 + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
11559 + * SA_NODEFER prevents the current signal from being masked in the handler.
11560 + *
11561 + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
11562 + * Unix names RESETHAND and NODEFER respectively.
11563 + */
11564 +#define SA_NOCLDSTOP   0x00000001
11565 +#define SA_NOCLDWAIT   0x00000002
11566 +#define SA_SIGINFO     0x00000004
11567 +#define SA_ONSTACK     0x08000000
11568 +#define SA_RESTART     0x10000000
11569 +#define SA_NODEFER     0x40000000
11570 +#define SA_RESETHAND   0x80000000
11571 +
11572 +#define SA_NOMASK      SA_NODEFER
11573 +#define SA_ONESHOT     SA_RESETHAND
11574 +
11575 +/*
11576 + * sigaltstack controls
11577 + */
11578 +#define SS_ONSTACK     1
11579 +#define SS_DISABLE     2
11580 +
11581 +#define MINSIGSTKSZ    2048
11582 +#define SIGSTKSZ       8192
11583 +
11584 +#include <asm-generic/signal.h>
11585 +
11586 +#ifdef __KERNEL__
11587 +struct old_sigaction {
11588 +       __sighandler_t sa_handler;
11589 +       old_sigset_t sa_mask;
11590 +       unsigned long sa_flags;
11591 +       void (*sa_restorer)(void);
11592 +};
11593 +
11594 +struct sigaction {
11595 +       __sighandler_t sa_handler;
11596 +       unsigned long sa_flags;
11597 +       void (*sa_restorer)(void);
11598 +       sigset_t sa_mask;               /* mask last for extensibility */
11599 +};
11600 +
11601 +struct k_sigaction {
11602 +       struct sigaction sa;
11603 +};
11604 +#else
11605 +/* Here we must cater to libcs that poke about in kernel headers.  */
11606 +
11607 +struct sigaction {
11608 +       union {
11609 +         __sighandler_t _sa_handler;
11610 +         void (*_sa_sigaction)(int, struct siginfo *, void *);
11611 +       } _u;
11612 +       sigset_t sa_mask;
11613 +       unsigned long sa_flags;
11614 +       void (*sa_restorer)(void);
11615 +};
11616 +
11617 +#define sa_handler     _u._sa_handler
11618 +#define sa_sigaction   _u._sa_sigaction
11619 +
11620 +#endif /* __KERNEL__ */
11621 +
11622 +typedef struct sigaltstack {
11623 +       void *ss_sp;
11624 +       int ss_flags;
11625 +       size_t ss_size;
11626 +} stack_t;
11627 +
11628 +#ifdef __KERNEL__
11629 +
11630 +#include <asm/sigcontext.h>
11631 +#undef __HAVE_ARCH_SIG_BITOPS
11632 +
11633 +#define ptrace_signal_deliver(regs, cookie) do { } while (0)
11634 +
11635 +#endif /* __KERNEL__ */
11636 +
11637 +#endif /* _ASM_UBICOM32_SIGNAL_H */
11638 --- /dev/null
11639 +++ b/arch/ubicom32/include/asm/smp.h
11640 @@ -0,0 +1,87 @@
11641 +/*
11642 + * arch/ubicom32/include/asm/smp.h
11643 + *   SMP definitions for Ubicom32 architecture.
11644 + *
11645 + * (C) Copyright 2009, Ubicom, Inc.
11646 + *
11647 + * This file is part of the Ubicom32 Linux Kernel Port.
11648 + *
11649 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11650 + * it and/or modify it under the terms of the GNU General Public License
11651 + * as published by the Free Software Foundation, either version 2 of the
11652 + * License, or (at your option) any later version.
11653 + *
11654 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11655 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11656 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11657 + * the GNU General Public License for more details.
11658 + *
11659 + * You should have received a copy of the GNU General Public License
11660 + * along with the Ubicom32 Linux Kernel Port.  If not,
11661 + * see <http://www.gnu.org/licenses/>.
11662 + *
11663 + * Ubicom32 implementation derived from (with many thanks):
11664 + *   arch/m68knommu
11665 + *   arch/blackfin
11666 + *   arch/parisc
11667 + */
11668 +#ifndef _ASM_UBICOM32_SMP_H
11669 +#define _ASM_UBICOM32_SMP_H
11670 +
11671 +#ifndef CONFIG_SMP
11672 +#error you should not include smp.h if smp is off
11673 +#endif
11674 +
11675 +#ifndef ASSEMBLY
11676 +#include <linux/bitops.h>
11677 +#include <linux/threads.h>
11678 +#include <linux/cpumask.h>
11679 +#include <asm/ip5000.h>
11680 +
11681 +typedef unsigned long address_t;
11682 +extern unsigned int smp_ipi_irq;
11683 +
11684 +/*
11685 + * This magic constant controls our willingness to transfer
11686 + * a process across CPUs.
11687 + *
11688 + * Such a transfer incurs cache and tlb
11689 + * misses. The current value is inherited from i386. Still needs
11690 + * to be tuned for parisc.
11691 + */
11692 +#define PROC_CHANGE_PENALTY    15              /* Schedule penalty */
11693 +#define NO_PROC_ID             0xFF            /* No processor magic marker */
11694 +#define ANY_PROC_ID            0xFF            /* Any processor magic marker */
11695 +
11696 +#ifdef CONFIG_SMP
11697 +#define raw_smp_processor_id() (current_thread_info()->cpu)
11698 +#endif /* CONFIG_SMP */
11699 +
11700 +static inline int __cpu_disable (void)
11701 +{
11702 +  return 0;
11703 +}
11704 +
11705 +static inline void __cpu_die (unsigned int cpu)
11706 +{
11707 +       while(1) {
11708 +       };
11709 +}
11710 +
11711 +extern int __cpu_up(unsigned int cpu);
11712 +extern void smp_send_timer_all(void);
11713 +extern void smp_timer_broadcast(const struct cpumask *mask);
11714 +extern void smp_set_affinity(unsigned int irq, const struct cpumask *dest);
11715 +extern void arch_send_call_function_single_ipi(int cpu);
11716 +#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
11717 +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
11718 +
11719 +/*
11720 + * TODO: Once these are fully tested, we should turn them into
11721 + * inline macros for performance.
11722 + */
11723 +extern unsigned long smp_get_affinity(unsigned int irq, int *all);
11724 +extern void smp_reset_ipi(unsigned long mask);
11725 +
11726 +#endif /* !ASSEMBLY */
11727 +#endif /*  _ASM_UBICOM32_SMP_H */
11728 --- /dev/null
11729 +++ b/arch/ubicom32/include/asm/socket.h
11730 @@ -0,0 +1,87 @@
11731 +/*
11732 + * arch/ubicom32/include/asm/socket.h
11733 + *   Socket options definitions for Ubicom32 architecture.
11734 + *
11735 + * (C) Copyright 2009, Ubicom, Inc.
11736 + *
11737 + * This file is part of the Ubicom32 Linux Kernel Port.
11738 + *
11739 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11740 + * it and/or modify it under the terms of the GNU General Public License
11741 + * as published by the Free Software Foundation, either version 2 of the
11742 + * License, or (at your option) any later version.
11743 + *
11744 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11745 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11746 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11747 + * the GNU General Public License for more details.
11748 + *
11749 + * You should have received a copy of the GNU General Public License
11750 + * along with the Ubicom32 Linux Kernel Port.  If not,
11751 + * see <http://www.gnu.org/licenses/>.
11752 + *
11753 + * Ubicom32 implementation derived from (with many thanks):
11754 + *   arch/m68knommu
11755 + *   arch/blackfin
11756 + *   arch/parisc
11757 + */
11758 +#ifndef _ASM_UBICOM32_SOCKET_H
11759 +#define _ASM_UBICOM32_SOCKET_H
11760 +
11761 +#include <asm/sockios.h>
11762 +
11763 +/* For setsockopt(2) */
11764 +#define SOL_SOCKET     1
11765 +
11766 +#define SO_DEBUG       1
11767 +#define SO_REUSEADDR   2
11768 +#define SO_TYPE                3
11769 +#define SO_ERROR       4
11770 +#define SO_DONTROUTE   5
11771 +#define SO_BROADCAST   6
11772 +#define SO_SNDBUF      7
11773 +#define SO_RCVBUF      8
11774 +#define SO_SNDBUFFORCE 32
11775 +#define SO_RCVBUFFORCE 33
11776 +#define SO_KEEPALIVE   9
11777 +#define SO_OOBINLINE   10
11778 +#define SO_NO_CHECK    11
11779 +#define SO_PRIORITY    12
11780 +#define SO_LINGER      13
11781 +#define SO_BSDCOMPAT   14
11782 +/* To add :#define SO_REUSEPORT 15 */
11783 +#define SO_PASSCRED    16
11784 +#define SO_PEERCRED    17
11785 +#define SO_RCVLOWAT    18
11786 +#define SO_SNDLOWAT    19
11787 +#define SO_RCVTIMEO    20
11788 +#define SO_SNDTIMEO    21
11789 +
11790 +/* Security levels - as per NRL IPv6 - don't actually do anything */
11791 +#define SO_SECURITY_AUTHENTICATION             22
11792 +#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
11793 +#define SO_SECURITY_ENCRYPTION_NETWORK         24
11794 +
11795 +#define SO_BINDTODEVICE        25
11796 +
11797 +/* Socket filtering */
11798 +#define SO_ATTACH_FILTER        26
11799 +#define SO_DETACH_FILTER        27
11800 +
11801 +#define SO_PEERNAME             28
11802 +#define SO_TIMESTAMP           29
11803 +#define SCM_TIMESTAMP          SO_TIMESTAMP
11804 +
11805 +#define SO_ACCEPTCONN          30
11806 +
11807 +#define SO_PEERSEC              31
11808 +#define SO_PASSSEC             34
11809 +#define SO_TIMESTAMPNS         35
11810 +#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
11811 +
11812 +#define SO_MARK                        36
11813 +
11814 +#define SO_TIMESTAMPING                37
11815 +#define SCM_TIMESTAMPING       SO_TIMESTAMPING
11816 +
11817 +#endif /* _ASM_UBICOM32_SOCKET_H */
11818 --- /dev/null
11819 +++ b/arch/ubicom32/include/asm/sockios.h
11820 @@ -0,0 +1,40 @@
11821 +/*
11822 + * arch/ubicom32/include/asm/sockios.h
11823 + *   Socket-level ioctl definitions for Ubicom32 architecture.
11824 + *
11825 + * (C) Copyright 2009, Ubicom, Inc.
11826 + *
11827 + * This file is part of the Ubicom32 Linux Kernel Port.
11828 + *
11829 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11830 + * it and/or modify it under the terms of the GNU General Public License
11831 + * as published by the Free Software Foundation, either version 2 of the
11832 + * License, or (at your option) any later version.
11833 + *
11834 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11835 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11836 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11837 + * the GNU General Public License for more details.
11838 + *
11839 + * You should have received a copy of the GNU General Public License
11840 + * along with the Ubicom32 Linux Kernel Port.  If not,
11841 + * see <http://www.gnu.org/licenses/>.
11842 + *
11843 + * Ubicom32 implementation derived from (with many thanks):
11844 + *   arch/m68knommu
11845 + *   arch/blackfin
11846 + *   arch/parisc
11847 + */
11848 +#ifndef _ASM_UBICOM32_SOCKIOS_H
11849 +#define _ASM_UBICOM32_SOCKIOS_H
11850 +
11851 +/* Socket-level I/O control calls. */
11852 +#define FIOSETOWN      0x8901
11853 +#define SIOCSPGRP      0x8902
11854 +#define FIOGETOWN      0x8903
11855 +#define SIOCGPGRP      0x8904
11856 +#define SIOCATMARK     0x8905
11857 +#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
11858 +#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
11859 +
11860 +#endif /* _ASM_UBICOM32_SOCKIOS_H */
11861 --- /dev/null
11862 +++ b/arch/ubicom32/include/asm/spinlock.h
11863 @@ -0,0 +1,296 @@
11864 +/*
11865 + * arch/ubicom32/include/asm/spinlock.h
11866 + *   Spinlock related definitions for Ubicom32 architecture.
11867 + *
11868 + * (C) Copyright 2009, Ubicom, Inc.
11869 + *
11870 + * This file is part of the Ubicom32 Linux Kernel Port.
11871 + *
11872 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11873 + * it and/or modify it under the terms of the GNU General Public License
11874 + * as published by the Free Software Foundation, either version 2 of the
11875 + * License, or (at your option) any later version.
11876 + *
11877 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11878 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11879 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11880 + * the GNU General Public License for more details.
11881 + *
11882 + * You should have received a copy of the GNU General Public License
11883 + * along with the Ubicom32 Linux Kernel Port.  If not,
11884 + * see <http://www.gnu.org/licenses/>.
11885 + *
11886 + * Ubicom32 implementation derived from (with many thanks):
11887 + *   arch/m68knommu
11888 + *   arch/blackfin
11889 + *   arch/parisc
11890 + */
11891 +#ifndef _ASM_UBICOM32_SPINLOCK_H
11892 +#define _ASM_UBICOM32_SPINLOCK_H
11893 +
11894 +#include <asm/system.h>
11895 +#include <asm/processor.h>
11896 +#include <asm/spinlock_types.h>
11897 +
11898 +/*
11899 + * __raw_spin_lock()
11900 + *     Lock the lock.
11901 + */
11902 +static inline void __raw_spin_lock(raw_spinlock_t *x)
11903 +{
11904 +       asm volatile (
11905 +       "1:     bset    %0, %0, #0      \n\t"
11906 +       "       jmpne.f 1b              \n\t"
11907 +               : "+U4" (x->lock)
11908 +               :
11909 +               : "memory", "cc"
11910 +       );
11911 +}
11912 +
11913 +/*
11914 + * __raw_spin_unlock()
11915 + *     Unlock the lock.
11916 + */
11917 +static inline void __raw_spin_unlock(raw_spinlock_t *x)
11918 +{
11919 +       asm volatile (
11920 +       "       bclr    %0, %0, #0      \n\t"
11921 +               : "+U4" (x->lock)
11922 +               :
11923 +               : "memory", "cc"
11924 +       );
11925 +}
11926 +
11927 +/*
11928 + * __raw_spin_is_locked()
11929 + *     Test if the lock is locked.
11930 + */
11931 +static inline int __raw_spin_is_locked(raw_spinlock_t *x)
11932 +{
11933 +       return x->lock;
11934 +}
11935 +
11936 +/*
11937 + * __raw_spin_unlock_wait()
11938 + *     Wait for the lock to be unlocked.
11939 + *
11940 + * Note: the caller has not guarantee that the lock will not
11941 + * be acquired before they get to it.
11942 + */
11943 +static inline void __raw_spin_unlock_wait(raw_spinlock_t *x)
11944 +{
11945 +       do {
11946 +               cpu_relax();
11947 +       } while (__raw_spin_is_locked(x));
11948 +}
11949 +
11950 +/*
11951 + * __raw_spin_trylock()
11952 + *     Try the lock, return 0 on failure, 1 on success.
11953 + */
11954 +static inline int __raw_spin_trylock(raw_spinlock_t *x)
11955 +{
11956 +       int ret = 0;
11957 +
11958 +       asm volatile (
11959 +       "       bset    %1, %1, #0      \n\t"
11960 +       "       jmpne.f 1f              \n\t"
11961 +       "       move.4  %0, #1          \n\t"
11962 +       "1:                             \n\t"
11963 +               : "+r" (ret), "+U4" (x->lock)
11964 +               :
11965 +               : "memory", "cc"
11966 +       );
11967 +
11968 +       return ret;
11969 +}
11970 +
11971 +/*
11972 + * __raw_spin_lock_flags()
11973 + *     Spin waiting for the lock (enabling IRQ(s))
11974 + */
11975 +static inline void __raw_spin_lock_flags(raw_spinlock_t *x, unsigned long flags)
11976 +{
11977 +       mb();
11978 +       while (!__raw_spin_trylock(x)) {
11979 +               /*
11980 +                * If the flags from the IRQ are set, interrupts are disabled and we
11981 +                * need to re-enable them.
11982 +                */
11983 +               if (!flags) {
11984 +                       cpu_relax();
11985 +               } else {
11986 +                       raw_local_irq_enable();
11987 +                       cpu_relax();
11988 +                       raw_local_irq_disable();
11989 +               }
11990 +       }
11991 +       mb();
11992 +}
11993 +
11994 +/*
11995 + * Read-write spinlocks, allowing multiple readers but only one writer.
11996 + * Linux rwlocks are unfair to writers; they can be starved for an indefinite
11997 + * time by readers.  With care, they can also be taken in interrupt context.
11998 + *
11999 + * In Ubicom32 architecture implementation, we have a spinlock and a counter.
12000 + * Readers use the lock to serialise their access to the counter (which
12001 + * records how many readers currently hold the lock).
12002 + * Writers hold the spinlock, preventing any readers or other writers from
12003 + * grabbing the rwlock.
12004 + */
12005 +
12006 +/*
12007 + * __raw_read_lock()
12008 + *     Increment the counter in the rwlock.
12009 + *
12010 + * Note that we have to ensure interrupts are disabled in case we're
12011 + * interrupted by some other code that wants to grab the same read lock
12012 + */
12013 +static inline void __raw_read_lock(raw_rwlock_t *rw)
12014 +{
12015 +       unsigned long flags;
12016 +       raw_local_irq_save(flags);
12017 +       __raw_spin_lock_flags(&rw->lock, flags);
12018 +       rw->counter++;
12019 +       __raw_spin_unlock(&rw->lock);
12020 +       raw_local_irq_restore(flags);
12021 +}
12022 +
12023 +/*
12024 + * __raw_read_unlock()
12025 + *     Decrement the counter.
12026 + *
12027 + * Note that we have to ensure interrupts are disabled in case we're
12028 + * interrupted by some other code that wants to grab the same read lock
12029 + */
12030 +static inline void __raw_read_unlock(raw_rwlock_t *rw)
12031 +{
12032 +       unsigned long flags;
12033 +       raw_local_irq_save(flags);
12034 +       __raw_spin_lock_flags(&rw->lock, flags);
12035 +       rw->counter--;
12036 +       __raw_spin_unlock(&rw->lock);
12037 +       raw_local_irq_restore(flags);
12038 +}
12039 +
12040 +/*
12041 + * __raw_read_trylock()
12042 + *     Increment the counter if we can.
12043 + *
12044 + * Note that we have to ensure interrupts are disabled in case we're
12045 + * interrupted by some other code that wants to grab the same read lock
12046 + */
12047 +static inline int __raw_read_trylock(raw_rwlock_t *rw)
12048 +{
12049 +       unsigned long flags;
12050 + retry:
12051 +       raw_local_irq_save(flags);
12052 +       if (__raw_spin_trylock(&rw->lock)) {
12053 +               rw->counter++;
12054 +               __raw_spin_unlock(&rw->lock);
12055 +               raw_local_irq_restore(flags);
12056 +               return 1;
12057 +       }
12058 +
12059 +       raw_local_irq_restore(flags);
12060 +
12061 +       /*
12062 +        * If write-locked, we fail to acquire the lock
12063 +        */
12064 +       if (rw->counter < 0) {
12065 +               return 0;
12066 +       }
12067 +
12068 +       /*
12069 +        * Wait until we have a realistic chance at the lock
12070 +        */
12071 +       while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0) {
12072 +               cpu_relax();
12073 +       }
12074 +
12075 +       goto retry;
12076 +}
12077 +
12078 +/*
12079 + * __raw_write_lock()
12080 + *
12081 + * Note that we have to ensure interrupts are disabled in case we're
12082 + * interrupted by some other code that wants to read_trylock() this lock
12083 + */
12084 +static inline void __raw_write_lock(raw_rwlock_t *rw)
12085 +{
12086 +       unsigned long flags;
12087 +retry:
12088 +       raw_local_irq_save(flags);
12089 +       __raw_spin_lock_flags(&rw->lock, flags);
12090 +
12091 +       if (rw->counter != 0) {
12092 +               __raw_spin_unlock(&rw->lock);
12093 +               raw_local_irq_restore(flags);
12094 +
12095 +               while (rw->counter != 0)
12096 +                       cpu_relax();
12097 +
12098 +               goto retry;
12099 +       }
12100 +
12101 +       rw->counter = -1; /* mark as write-locked */
12102 +       mb();
12103 +       raw_local_irq_restore(flags);
12104 +}
12105 +
12106 +static inline void __raw_write_unlock(raw_rwlock_t *rw)
12107 +{
12108 +       rw->counter = 0;
12109 +       __raw_spin_unlock(&rw->lock);
12110 +}
12111 +
12112 +/* Note that we have to ensure interrupts are disabled in case we're
12113 + * interrupted by some other code that wants to read_trylock() this lock */
12114 +static inline int __raw_write_trylock(raw_rwlock_t *rw)
12115 +{
12116 +       unsigned long flags;
12117 +       int result = 0;
12118 +
12119 +       raw_local_irq_save(flags);
12120 +       if (__raw_spin_trylock(&rw->lock)) {
12121 +               if (rw->counter == 0) {
12122 +                       rw->counter = -1;
12123 +                       result = 1;
12124 +               } else {
12125 +                       /* Read-locked.  Oh well. */
12126 +                       __raw_spin_unlock(&rw->lock);
12127 +               }
12128 +       }
12129 +       raw_local_irq_restore(flags);
12130 +
12131 +       return result;
12132 +}
12133 +
12134 +/*
12135 + * read_can_lock - would read_trylock() succeed?
12136 + * @lock: the rwlock in question.
12137 + */
12138 +static inline int __raw_read_can_lock(raw_rwlock_t *rw)
12139 +{
12140 +       return rw->counter >= 0;
12141 +}
12142 +
12143 +/*
12144 + * write_can_lock - would write_trylock() succeed?
12145 + * @lock: the rwlock in question.
12146 + */
12147 +static inline int __raw_write_can_lock(raw_rwlock_t *rw)
12148 +{
12149 +       return !rw->counter;
12150 +}
12151 +
12152 +#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
12153 +#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
12154 +
12155 +#define _raw_spin_relax(lock)  cpu_relax()
12156 +#define _raw_read_relax(lock)  cpu_relax()
12157 +#define _raw_write_relax(lock) cpu_relax()
12158 +
12159 +#endif /* _ASM_UBICOM32_SPINLOCK_H */
12160 --- /dev/null
12161 +++ b/arch/ubicom32/include/asm/spinlock_types.h
12162 @@ -0,0 +1,43 @@
12163 +/*
12164 + * arch/ubicom32/include/asm/spinlock_types.h
12165 + *   Spinlock related structure definitions for Ubicom32 architecture.
12166 + *
12167 + * (C) Copyright 2009, Ubicom, Inc.
12168 + *
12169 + * This file is part of the Ubicom32 Linux Kernel Port.
12170 + *
12171 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12172 + * it and/or modify it under the terms of the GNU General Public License
12173 + * as published by the Free Software Foundation, either version 2 of the
12174 + * License, or (at your option) any later version.
12175 + *
12176 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12177 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12178 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12179 + * the GNU General Public License for more details.
12180 + *
12181 + * You should have received a copy of the GNU General Public License
12182 + * along with the Ubicom32 Linux Kernel Port.  If not,
12183 + * see <http://www.gnu.org/licenses/>.
12184 + *
12185 + * Ubicom32 implementation derived from (with many thanks):
12186 + *   arch/m68knommu
12187 + *   arch/blackfin
12188 + *   arch/parisc
12189 + */
12190 +#ifndef _ASM_UBICOM32_SPINLOCK_TYPES_H
12191 +#define _ASM_UBICOM32_SPINLOCK_TYPES_H
12192 +
12193 +typedef struct {
12194 +       volatile unsigned int lock;
12195 +} raw_spinlock_t;
12196 +
12197 +typedef struct {
12198 +       raw_spinlock_t lock;
12199 +       volatile int counter;
12200 +} raw_rwlock_t;
12201 +
12202 +#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
12203 +#define __RAW_RW_LOCK_UNLOCKED         { __RAW_SPIN_LOCK_UNLOCKED, 0 }
12204 +
12205 +#endif /* _ASM_UBICOM32_SPINLOCK_TYPES_H */
12206 --- /dev/null
12207 +++ b/arch/ubicom32/include/asm/stacktrace.h
12208 @@ -0,0 +1,72 @@
12209 +/*
12210 + * arch/ubicom32/include/asm/stacktrace.h
12211 + *   Stacktrace functions for the Ubicom32 architecture.
12212 + *
12213 + * (C) Copyright 2009, Ubicom, Inc.
12214 + *
12215 + * This file is part of the Ubicom32 Linux Kernel Port.
12216 + *
12217 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12218 + * it and/or modify it under the terms of the GNU General Public License
12219 + * as published by the Free Software Foundation, either version 2 of the
12220 + * License, or (at your option) any later version.
12221 + *
12222 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12223 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12224 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12225 + * the GNU General Public License for more details.
12226 + *
12227 + * You should have received a copy of the GNU General Public License
12228 + * along with the Ubicom32 Linux Kernel Port.  If not,
12229 + * see <http://www.gnu.org/licenses/>.
12230 + *
12231 + * Ubicom32 implementation derived from (with many thanks):
12232 + *   arch/m68knommu
12233 + *   arch/blackfin
12234 + *   arch/parisc
12235 + */
12236 +#ifndef _ASM_UBICOM32_STACKTRACE_H
12237 +#define _ASM_UBICOM32_STACKTRACE_H
12238 +
12239 +#define between(a, b, c)       (( \
12240 +                       ((unsigned long) a) >= ((unsigned long) b)) && \
12241 +                       (((unsigned long)a) <= ((unsigned long)c)))
12242 +
12243 +/*
12244 + * These symbols are filled in by the linker.
12245 + */
12246 +extern unsigned long _stext;
12247 +extern unsigned long _etext;
12248 +
12249 +/* OCM text goes from __ocm_text_run_begin to __data_begin */
12250 +extern unsigned long __ocm_text_run_begin;
12251 +extern unsigned long __data_begin;
12252 +
12253 +/* Account for OCM case - see stacktrace.c maybe combine(also trap.c) */
12254 +/*
12255 + * ubicom32_is_kernel()
12256 + *
12257 + *     Check to see if the given address belongs to the kernel.
12258 + * NOMMU does not permit any other means.
12259 + */
12260 +static inline int ubicom32_is_kernel(unsigned long addr)
12261 +{
12262 +       int is_kernel = between(addr, &_stext, &_etext) || \
12263 +                       between(addr, &__ocm_text_run_begin, &__data_begin);
12264 +
12265 +#ifdef CONFIG_MODULES
12266 +       if (!is_kernel)
12267 +               is_kernel = is_module_address(addr);
12268 +#endif
12269 +       return is_kernel;
12270 +}
12271 +
12272 +extern unsigned long stacktrace_iterate(
12273 +                               unsigned long **trace,
12274 +                               unsigned long stext, unsigned long etext,
12275 +                               unsigned long ocm_stext, unsigned long ocm_etext,
12276 +                               unsigned long sstack, unsigned long estack);
12277 +#ifdef CONFIG_STACKTRACE
12278 +void stacktrace_save_entries(struct task_struct *tsk, struct stack_trace *trace, unsigned long sp);
12279 +#endif
12280 +#endif /* _ASM_UBICOM32_STACKTRACE_H */
12281 --- /dev/null
12282 +++ b/arch/ubicom32/include/asm/statfs.h
12283 @@ -0,0 +1,33 @@
12284 +/*
12285 + * arch/ubicom32/include/asm/statfs.h
12286 + *   Generic statfs.h definitions
12287 + *
12288 + * (C) Copyright 2009, Ubicom, Inc.
12289 + *
12290 + * This file is part of the Ubicom32 Linux Kernel Port.
12291 + *
12292 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12293 + * it and/or modify it under the terms of the GNU General Public License
12294 + * as published by the Free Software Foundation, either version 2 of the
12295 + * License, or (at your option) any later version.
12296 + *
12297 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12298 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12299 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12300 + * the GNU General Public License for more details.
12301 + *
12302 + * You should have received a copy of the GNU General Public License
12303 + * along with the Ubicom32 Linux Kernel Port.  If not,
12304 + * see <http://www.gnu.org/licenses/>.
12305 + *
12306 + * Ubicom32 implementation derived from (with many thanks):
12307 + *   arch/m68knommu
12308 + *   arch/blackfin
12309 + *   arch/parisc
12310 + */
12311 +#ifndef _ASM_UBICOM32_STATFS_H
12312 +#define _ASM_UBICOM32_STATFS_H
12313 +
12314 +#include <asm-generic/statfs.h>
12315 +
12316 +#endif /* _ASM_UBICOM32_STATFS_H */
12317 --- /dev/null
12318 +++ b/arch/ubicom32/include/asm/stat.h
12319 @@ -0,0 +1,104 @@
12320 +/*
12321 + * arch/ubicom32/include/asm/stat.h
12322 + *   File status definitions for Ubicom32 architecture.
12323 + *
12324 + * (C) Copyright 2009, Ubicom, Inc.
12325 + *
12326 + * This file is part of the Ubicom32 Linux Kernel Port.
12327 + *
12328 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12329 + * it and/or modify it under the terms of the GNU General Public License
12330 + * as published by the Free Software Foundation, either version 2 of the
12331 + * License, or (at your option) any later version.
12332 + *
12333 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12334 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12335 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12336 + * the GNU General Public License for more details.
12337 + *
12338 + * You should have received a copy of the GNU General Public License
12339 + * along with the Ubicom32 Linux Kernel Port.  If not,
12340 + * see <http://www.gnu.org/licenses/>.
12341 + *
12342 + * Ubicom32 implementation derived from (with many thanks):
12343 + *   arch/m68knommu
12344 + *   arch/blackfin
12345 + *   arch/parisc
12346 + */
12347 +#ifndef _ASM_UBICOM32_STAT_H
12348 +#define _ASM_UBICOM32_STAT_H
12349 +
12350 +struct __old_kernel_stat {
12351 +       unsigned short st_dev;
12352 +       unsigned short st_ino;
12353 +       unsigned short st_mode;
12354 +       unsigned short st_nlink;
12355 +       unsigned short st_uid;
12356 +       unsigned short st_gid;
12357 +       unsigned short st_rdev;
12358 +       unsigned long  st_size;
12359 +       unsigned long  st_atime;
12360 +       unsigned long  st_mtime;
12361 +       unsigned long  st_ctime;
12362 +};
12363 +
12364 +struct stat {
12365 +       unsigned short st_dev;
12366 +       unsigned short __pad1;
12367 +       unsigned long  st_ino;
12368 +       unsigned short st_mode;
12369 +       unsigned short st_nlink;
12370 +       unsigned short st_uid;
12371 +       unsigned short st_gid;
12372 +       unsigned short st_rdev;
12373 +       unsigned short __pad2;
12374 +       unsigned long  st_size;
12375 +       unsigned long  st_blksize;
12376 +       unsigned long  st_blocks;
12377 +       unsigned long  st_atime;
12378 +       unsigned long  __unused1;
12379 +       unsigned long  st_mtime;
12380 +       unsigned long  __unused2;
12381 +       unsigned long  st_ctime;
12382 +       unsigned long  __unused3;
12383 +       unsigned long  __unused4;
12384 +       unsigned long  __unused5;
12385 +};
12386 +
12387 +/* This matches struct stat64 in glibc2.1, hence the absolutely
12388 + * insane amounts of padding around dev_t's.
12389 + */
12390 +struct stat64 {
12391 +       unsigned long long      st_dev;
12392 +       unsigned char   __pad1[2];
12393 +
12394 +#define STAT64_HAS_BROKEN_ST_INO       1
12395 +       unsigned long   __st_ino;
12396 +
12397 +       unsigned int    st_mode;
12398 +       unsigned int    st_nlink;
12399 +
12400 +       unsigned long   st_uid;
12401 +       unsigned long   st_gid;
12402 +
12403 +       unsigned long long      st_rdev;
12404 +       unsigned char   __pad3[2];
12405 +
12406 +       long long       st_size;
12407 +       unsigned long   st_blksize;
12408 +
12409 +       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
12410 +
12411 +       unsigned long   st_atime;
12412 +       unsigned long   st_atime_nsec;
12413 +
12414 +       unsigned long   st_mtime;
12415 +       unsigned long   st_mtime_nsec;
12416 +
12417 +       unsigned long   st_ctime;
12418 +       unsigned long   st_ctime_nsec;
12419 +
12420 +       unsigned long long      st_ino;
12421 +};
12422 +
12423 +#endif /* _ASM_UBICOM32_STAT_H */
12424 --- /dev/null
12425 +++ b/arch/ubicom32/include/asm/string.h
12426 @@ -0,0 +1,40 @@
12427 +/*
12428 + * arch/ubicom32/include/asm/string.h
12429 + *   String operation definitions for Ubicom32 architecture.
12430 + *
12431 + * (C) Copyright 2009, Ubicom, Inc.
12432 + *
12433 + * This file is part of the Ubicom32 Linux Kernel Port.
12434 + *
12435 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12436 + * it and/or modify it under the terms of the GNU General Public License
12437 + * as published by the Free Software Foundation, either version 2 of the
12438 + * License, or (at your option) any later version.
12439 + *
12440 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12441 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12442 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12443 + * the GNU General Public License for more details.
12444 + *
12445 + * You should have received a copy of the GNU General Public License
12446 + * along with the Ubicom32 Linux Kernel Port.  If not,
12447 + * see <http://www.gnu.org/licenses/>.
12448 + *
12449 + * Ubicom32 implementation derived from (with many thanks):
12450 + *   arch/m68knommu
12451 + *   arch/blackfin
12452 + *   arch/parisc
12453 + */
12454 +#ifndef _ASM_UBICOM32_STRING_H
12455 +#define _ASM_UBICOM32_STRING_H
12456 +
12457 +#define __HAVE_ARCH_MEMSET
12458 +extern void *memset(void *b, int c, size_t len);
12459 +
12460 +#define __HAVE_ARCH_MEMCPY
12461 +extern void *memcpy(void *to, const void *from, size_t len);
12462 +
12463 +#define __HAVE_ARCH_MEMMOVE
12464 +extern void * memmove(void *to, const void *from, size_t len);
12465 +
12466 +#endif /* _ASM_UBICOM32_STRING_H */
12467 --- /dev/null
12468 +++ b/arch/ubicom32/include/asm/swab.h
12469 @@ -0,0 +1,45 @@
12470 +/*
12471 + * arch/ubicom32/include/asm/byteorder.h
12472 + *   Byte order swapping utility routines.
12473 + *
12474 + * (C) Copyright 2009, Ubicom, Inc.
12475 + *
12476 + * This file is part of the Ubicom32 Linux Kernel Port.
12477 + *
12478 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12479 + * it and/or modify it under the terms of the GNU General Public License
12480 + * as published by the Free Software Foundation, either version 2 of the
12481 + * License, or (at your option) any later version.
12482 + *
12483 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12484 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12485 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12486 + * the GNU General Public License for more details.
12487 + *
12488 + * You should have received a copy of the GNU General Public License
12489 + * along with the Ubicom32 Linux Kernel Port.  If not,
12490 + * see <http://www.gnu.org/licenses/>.
12491 + *
12492 + * Ubicom32 implementation derived from (with many thanks):
12493 + *   arch/m68knommu
12494 + *   arch/blackfin
12495 + *   arch/parisc
12496 + */
12497 +#ifndef _ASM_UBICOM32_BYTEORDER_H
12498 +#define _ASM_UBICOM32_BYTEORDER_H
12499 +
12500 +#include <linux/types.h>
12501 +
12502 +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
12503 +#  define __BYTEORDER_HAS_U64__
12504 +#  define __SWAB_64_THRU_32__
12505 +#endif
12506 +
12507 +#if defined(IP7000) || defined(IP7000_REV2)
12508 +
12509 +#define __arch__swab16 __builtin_ubicom32_swapb_2
12510 +#define __arch__swab32 __builtin_ubicom32_swapb_4
12511 +
12512 +#endif /* IP7000 */
12513 +
12514 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
12515 --- /dev/null
12516 +++ b/arch/ubicom32/include/asm/switch-dev.h
12517 @@ -0,0 +1,51 @@
12518 +/*
12519 + * arch/ubicom32/include/asm/switch-dev.h
12520 + *   generic Ethernet switch platform data definitions for Ubicom32 architecture.
12521 + *
12522 + * (C) Copyright 2009, Ubicom, Inc.
12523 + *
12524 + * This file is part of the Ubicom32 Linux Kernel Port.
12525 + *
12526 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12527 + * it and/or modify it under the terms of the GNU General Public License
12528 + * as published by the Free Software Foundation, either version 2 of the
12529 + * License, or (at your option) any later version.
12530 + *
12531 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12532 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12533 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12534 + * the GNU General Public License for more details.
12535 + *
12536 + * You should have received a copy of the GNU General Public License
12537 + * along with the Ubicom32 Linux Kernel Port.  If not,
12538 + * see <http://www.gnu.org/licenses/>.
12539 + *
12540 + * Ubicom32 implementation derived from (with many thanks):
12541 + *   arch/m68knommu
12542 + *   arch/blackfin
12543 + *   arch/parisc
12544 + */
12545 +#ifndef _ASM_UBICOM32_SWITCH_DEV_H
12546 +#define _ASM_UBICOM32_SWITCH_DEV_H
12547 +
12548 +#define SWITCH_DEV_FLAG_HW_RESET       0x01
12549 +#define SWITCH_DEV_FLAG_SW_RESET       0x02
12550 +
12551 +struct switch_core_platform_data {
12552 +       /*
12553 +        * See flags above
12554 +        */
12555 +       u32_t           flags;
12556 +
12557 +       /*
12558 +        * GPIO to use for nReset
12559 +        */
12560 +       int             pin_reset;
12561 +
12562 +       /*
12563 +        * Name of this switch
12564 +        */
12565 +       const char      *name;
12566 +};
12567 +
12568 +#endif /* _ASM_UBICOM32_SWITCH_DEV_H */
12569 --- /dev/null
12570 +++ b/arch/ubicom32/include/asm/system.h
12571 @@ -0,0 +1,101 @@
12572 +/*
12573 + * arch/ubicom32/include/asm/system.h
12574 + *   Low level switching definitions.
12575 + *
12576 + * (C) Copyright 2009, Ubicom, Inc.
12577 + *
12578 + * This file is part of the Ubicom32 Linux Kernel Port.
12579 + *
12580 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12581 + * it and/or modify it under the terms of the GNU General Public License
12582 + * as published by the Free Software Foundation, either version 2 of the
12583 + * License, or (at your option) any later version.
12584 + *
12585 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12586 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12587 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12588 + * the GNU General Public License for more details.
12589 + *
12590 + * You should have received a copy of the GNU General Public License
12591 + * along with the Ubicom32 Linux Kernel Port.  If not,
12592 + * see <http://www.gnu.org/licenses/>.
12593 + *
12594 + * Ubicom32 implementation derived from (with many thanks):
12595 + *   arch/m68knommu
12596 + *   arch/blackfin
12597 + *   arch/parisc
12598 + */
12599 +#ifndef _ASM_UBICOM32_SYSTEM_H
12600 +#define _ASM_UBICOM32_SYSTEM_H
12601 +
12602 +#include <linux/irqflags.h>
12603 +#include <linux/linkage.h>
12604 +#include <asm/segment.h>
12605 +#include <asm/entry.h>
12606 +#include <asm/ldsr.h>
12607 +#include <asm/irq.h>
12608 +#include <asm/percpu.h>
12609 +#include <asm/ubicom32-common.h>
12610 +#include <asm/processor.h>
12611 +
12612 +/*
12613 + * switch_to(n) should switch tasks to task ptr, first checking that
12614 + * ptr isn't the current task, in which case it does nothing.
12615 + */
12616 +asmlinkage void resume(void);
12617 +extern void *__switch_to(struct task_struct *prev,
12618 +               struct thread_struct *prev_switch,
12619 +               struct thread_struct *next_switch);
12620 +
12621 +/*
12622 + * We will need a per linux thread sw_ksp for the switch_to macro to
12623 + * track the kernel stack pointer for the current thread on that linux thread.
12624 + */
12625 +#define switch_to(prev,next,last)                                      \
12626 +({                                                                     \
12627 +       void *_last;                                                    \
12628 +       _last = (void *)                                                \
12629 +               __switch_to(prev, &prev->thread, &next->thread);        \
12630 +       (last) = _last;                                                 \
12631 +})
12632 +
12633 +/*
12634 + * Force strict CPU ordering.
12635 + * Not really required on ubicom32...
12636 + */
12637 +#define nop()  asm volatile ("nop"::)
12638 +#define mb()   asm volatile (""   : : :"memory")
12639 +#define rmb()  asm volatile (""   : : :"memory")
12640 +#define wmb()  asm volatile (""   : : :"memory")
12641 +#define set_mb(var, value)     ({ (var) = (value); wmb(); })
12642 +
12643 +#ifdef CONFIG_SMP
12644 +#define smp_mb()       mb()
12645 +#define smp_rmb()      rmb()
12646 +#define smp_wmb()      wmb()
12647 +#define smp_read_barrier_depends()     read_barrier_depends()
12648 +#else
12649 +#define smp_mb()       mb()
12650 +#define smp_rmb()      rmb()
12651 +#define smp_wmb()      wmb()
12652 +#define smp_read_barrier_depends()     do { } while(0)
12653 +#endif
12654 +
12655 +#define read_barrier_depends()  ((void)0)
12656 +
12657 +/*
12658 + * The following defines change how the scheduler calls the switch_to()
12659 + * macro.
12660 + *
12661 + * 1) The first causes the runqueue to be unlocked on entry to
12662 + * switch_to().  Since our ctx code does not play with the runqueue
12663 + * we do not need it unlocked.
12664 + *
12665 + * 2) The later turns interrupts on during a ctxsw to reduce the latency of
12666 + * interrupts during ctx.  At this point in the port, we believe that this
12667 + * latency is not a problem since we have very little code to perform a ctxsw.
12668 + */
12669 +// #define __ARCH_WANT_UNLOCKED_CTXSW
12670 +// #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
12671 +
12672 +#endif /* _ASM_UBICOM32_SYSTEM_H */
12673 --- /dev/null
12674 +++ b/arch/ubicom32/include/asm/termbits.h
12675 @@ -0,0 +1,227 @@
12676 +/*
12677 + * arch/ubicom32/include/asm/termbits.h
12678 + *   Terminal/serial port definitions for Ubicom32 architecture.
12679 + *
12680 + * (C) Copyright 2009, Ubicom, Inc.
12681 + *
12682 + * This file is part of the Ubicom32 Linux Kernel Port.
12683 + *
12684 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12685 + * it and/or modify it under the terms of the GNU General Public License
12686 + * as published by the Free Software Foundation, either version 2 of the
12687 + * License, or (at your option) any later version.
12688 + *
12689 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12690 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12691 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12692 + * the GNU General Public License for more details.
12693 + *
12694 + * You should have received a copy of the GNU General Public License
12695 + * along with the Ubicom32 Linux Kernel Port.  If not,
12696 + * see <http://www.gnu.org/licenses/>.
12697 + *
12698 + * Ubicom32 implementation derived from (with many thanks):
12699 + *   arch/m68knommu
12700 + *   arch/blackfin
12701 + *   arch/parisc
12702 + */
12703 +#ifndef _ASM_UBICOM32_TERMBITS_H
12704 +#define _ASM_UBICOM32_TERMBITS_H
12705 +
12706 +#include <linux/posix_types.h>
12707 +
12708 +typedef unsigned char  cc_t;
12709 +typedef unsigned int   speed_t;
12710 +typedef unsigned int   tcflag_t;
12711 +
12712 +#define NCCS 19
12713 +struct termios {
12714 +       tcflag_t c_iflag;               /* input mode flags */
12715 +       tcflag_t c_oflag;               /* output mode flags */
12716 +       tcflag_t c_cflag;               /* control mode flags */
12717 +       tcflag_t c_lflag;               /* local mode flags */
12718 +       cc_t c_line;                    /* line discipline */
12719 +       cc_t c_cc[NCCS];                /* control characters */
12720 +};
12721 +
12722 +struct termios2 {
12723 +       tcflag_t c_iflag;               /* input mode flags */
12724 +       tcflag_t c_oflag;               /* output mode flags */
12725 +       tcflag_t c_cflag;               /* control mode flags */
12726 +       tcflag_t c_lflag;               /* local mode flags */
12727 +       cc_t c_line;                    /* line discipline */
12728 +       cc_t c_cc[NCCS];                /* control characters */
12729 +       speed_t c_ispeed;               /* input speed */
12730 +       speed_t c_ospeed;               /* output speed */
12731 +};
12732 +
12733 +struct ktermios {
12734 +       tcflag_t c_iflag;               /* input mode flags */
12735 +       tcflag_t c_oflag;               /* output mode flags */
12736 +       tcflag_t c_cflag;               /* control mode flags */
12737 +       tcflag_t c_lflag;               /* local mode flags */
12738 +       cc_t c_line;                    /* line discipline */
12739 +       cc_t c_cc[NCCS];                /* control characters */
12740 +       speed_t c_ispeed;               /* input speed */
12741 +       speed_t c_ospeed;               /* output speed */
12742 +};
12743 +
12744 +/* c_cc characters */
12745 +#define VINTR 0
12746 +#define VQUIT 1
12747 +#define VERASE 2
12748 +#define VKILL 3
12749 +#define VEOF 4
12750 +#define VTIME 5
12751 +#define VMIN 6
12752 +#define VSWTC 7
12753 +#define VSTART 8
12754 +#define VSTOP 9
12755 +#define VSUSP 10
12756 +#define VEOL 11
12757 +#define VREPRINT 12
12758 +#define VDISCARD 13
12759 +#define VWERASE 14
12760 +#define VLNEXT 15
12761 +#define VEOL2 16
12762 +
12763 +
12764 +/* c_iflag bits */
12765 +#define IGNBRK 0000001
12766 +#define BRKINT 0000002
12767 +#define IGNPAR 0000004
12768 +#define PARMRK 0000010
12769 +#define INPCK  0000020
12770 +#define ISTRIP 0000040
12771 +#define INLCR  0000100
12772 +#define IGNCR  0000200
12773 +#define ICRNL  0000400
12774 +#define IUCLC  0001000
12775 +#define IXON   0002000
12776 +#define IXANY  0004000
12777 +#define IXOFF  0010000
12778 +#define IMAXBEL        0020000
12779 +#define IUTF8  0040000
12780 +
12781 +/* c_oflag bits */
12782 +#define OPOST  0000001
12783 +#define OLCUC  0000002
12784 +#define ONLCR  0000004
12785 +#define OCRNL  0000010
12786 +#define ONOCR  0000020
12787 +#define ONLRET 0000040
12788 +#define OFILL  0000100
12789 +#define OFDEL  0000200
12790 +#define NLDLY  0000400
12791 +#define   NL0  0000000
12792 +#define   NL1  0000400
12793 +#define CRDLY  0003000
12794 +#define   CR0  0000000
12795 +#define   CR1  0001000
12796 +#define   CR2  0002000
12797 +#define   CR3  0003000
12798 +#define TABDLY 0014000
12799 +#define   TAB0 0000000
12800 +#define   TAB1 0004000
12801 +#define   TAB2 0010000
12802 +#define   TAB3 0014000
12803 +#define   XTABS        0014000
12804 +#define BSDLY  0020000
12805 +#define   BS0  0000000
12806 +#define   BS1  0020000
12807 +#define VTDLY  0040000
12808 +#define   VT0  0000000
12809 +#define   VT1  0040000
12810 +#define FFDLY  0100000
12811 +#define   FF0  0000000
12812 +#define   FF1  0100000
12813 +
12814 +/* c_cflag bit meaning */
12815 +#define CBAUD  0010017
12816 +#define  B0    0000000         /* hang up */
12817 +#define  B50   0000001
12818 +#define  B75   0000002
12819 +#define  B110  0000003
12820 +#define  B134  0000004
12821 +#define  B150  0000005
12822 +#define  B200  0000006
12823 +#define  B300  0000007
12824 +#define  B600  0000010
12825 +#define  B1200 0000011
12826 +#define  B1800 0000012
12827 +#define  B2400 0000013
12828 +#define  B4800 0000014
12829 +#define  B9600 0000015
12830 +#define  B19200        0000016
12831 +#define  B38400        0000017
12832 +#define EXTA B19200
12833 +#define EXTB B38400
12834 +#define CSIZE  0000060
12835 +#define   CS5  0000000
12836 +#define   CS6  0000020
12837 +#define   CS7  0000040
12838 +#define   CS8  0000060
12839 +#define CSTOPB 0000100
12840 +#define CREAD  0000200
12841 +#define PARENB 0000400
12842 +#define PARODD 0001000
12843 +#define HUPCL  0002000
12844 +#define CLOCAL 0004000
12845 +#define CBAUDEX 0010000
12846 +#define    BOTHER 0010000
12847 +#define    B57600 0010001
12848 +#define   B115200 0010002
12849 +#define   B230400 0010003
12850 +#define   B460800 0010004
12851 +#define   B500000 0010005
12852 +#define   B576000 0010006
12853 +#define   B921600 0010007
12854 +#define  B1000000 0010010
12855 +#define  B1152000 0010011
12856 +#define  B1500000 0010012
12857 +#define  B2000000 0010013
12858 +#define  B2500000 0010014
12859 +#define  B3000000 0010015
12860 +#define  B3500000 0010016
12861 +#define  B4000000 0010017
12862 +#define CIBAUD   002003600000          /* input baud rate */
12863 +#define CMSPAR   010000000000          /* mark or space (stick) parity */
12864 +#define CRTSCTS          020000000000          /* flow control */
12865 +
12866 +#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
12867 +
12868 +/* c_lflag bits */
12869 +#define ISIG   0000001
12870 +#define ICANON 0000002
12871 +#define XCASE  0000004
12872 +#define ECHO   0000010
12873 +#define ECHOE  0000020
12874 +#define ECHOK  0000040
12875 +#define ECHONL 0000100
12876 +#define NOFLSH 0000200
12877 +#define TOSTOP 0000400
12878 +#define ECHOCTL        0001000
12879 +#define ECHOPRT        0002000
12880 +#define ECHOKE 0004000
12881 +#define FLUSHO 0010000
12882 +#define PENDIN 0040000
12883 +#define IEXTEN 0100000
12884 +
12885 +
12886 +/* tcflow() and TCXONC use these */
12887 +#define        TCOOFF          0
12888 +#define        TCOON           1
12889 +#define        TCIOFF          2
12890 +#define        TCION           3
12891 +
12892 +/* tcflush() and TCFLSH use these */
12893 +#define        TCIFLUSH        0
12894 +#define        TCOFLUSH        1
12895 +#define        TCIOFLUSH       2
12896 +
12897 +/* tcsetattr uses these */
12898 +#define        TCSANOW         0
12899 +#define        TCSADRAIN       1
12900 +#define        TCSAFLUSH       2
12901 +
12902 +#endif /* _ASM_UBICOM32_TERMBITS_H */
12903 --- /dev/null
12904 +++ b/arch/ubicom32/include/asm/termios.h
12905 @@ -0,0 +1,119 @@
12906 +/*
12907 + * arch/ubicom32/include/asm/termios.h
12908 + *   Ubicom32 termio definitions.
12909 + *
12910 + * (C) Copyright 2009, Ubicom, Inc.
12911 + *
12912 + * This file is part of the Ubicom32 Linux Kernel Port.
12913 + *
12914 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12915 + * it and/or modify it under the terms of the GNU General Public License
12916 + * as published by the Free Software Foundation, either version 2 of the
12917 + * License, or (at your option) any later version.
12918 + *
12919 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12920 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12921 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12922 + * the GNU General Public License for more details.
12923 + *
12924 + * You should have received a copy of the GNU General Public License
12925 + * along with the Ubicom32 Linux Kernel Port.  If not,
12926 + * see <http://www.gnu.org/licenses/>.
12927 + *
12928 + * Ubicom32 implementation derived from (with many thanks):
12929 + *   arch/m68knommu
12930 + *   arch/blackfin
12931 + *   arch/parisc
12932 + */
12933 +#ifndef _ASM_UBICOM32_TERMIOS_H
12934 +#define _ASM_UBICOM32_TERMIOS_H
12935 +
12936 +#include <asm/termbits.h>
12937 +#include <asm/ioctls.h>
12938 +
12939 +struct winsize {
12940 +       unsigned short ws_row;
12941 +       unsigned short ws_col;
12942 +       unsigned short ws_xpixel;
12943 +       unsigned short ws_ypixel;
12944 +};
12945 +
12946 +#define NCC 8
12947 +struct termio {
12948 +       unsigned short c_iflag;         /* input mode flags */
12949 +       unsigned short c_oflag;         /* output mode flags */
12950 +       unsigned short c_cflag;         /* control mode flags */
12951 +       unsigned short c_lflag;         /* local mode flags */
12952 +       unsigned char c_line;           /* line discipline */
12953 +       unsigned char c_cc[NCC];        /* control characters */
12954 +};
12955 +
12956 +#ifdef __KERNEL__
12957 +/*     intr=^C         quit=^|         erase=del       kill=^U
12958 +       eof=^D          vtime=\0        vmin=\1         sxtc=\0
12959 +       start=^Q        stop=^S         susp=^Z         eol=\0
12960 +       reprint=^R      discard=^U      werase=^W       lnext=^V
12961 +       eol2=\0
12962 +*/
12963 +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
12964 +#endif
12965 +
12966 +/* modem lines */
12967 +#define TIOCM_LE       0x001
12968 +#define TIOCM_DTR      0x002
12969 +#define TIOCM_RTS      0x004
12970 +#define TIOCM_ST       0x008
12971 +#define TIOCM_SR       0x010
12972 +#define TIOCM_CTS      0x020
12973 +#define TIOCM_CAR      0x040
12974 +#define TIOCM_RNG      0x080
12975 +#define TIOCM_DSR      0x100
12976 +#define TIOCM_CD       TIOCM_CAR
12977 +#define TIOCM_RI       TIOCM_RNG
12978 +#define TIOCM_OUT1     0x2000
12979 +#define TIOCM_OUT2     0x4000
12980 +#define TIOCM_LOOP     0x8000
12981 +
12982 +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
12983 +
12984 +#ifdef __KERNEL__
12985 +
12986 +/*
12987 + * Translate a "termio" structure into a "termios". Ugh.
12988 + */
12989 +#define user_termio_to_kernel_termios(termios, termio) \
12990 +({ \
12991 +       unsigned short tmp; \
12992 +       get_user(tmp, &(termio)->c_iflag); \
12993 +       (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
12994 +       get_user(tmp, &(termio)->c_oflag); \
12995 +       (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
12996 +       get_user(tmp, &(termio)->c_cflag); \
12997 +       (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
12998 +       get_user(tmp, &(termio)->c_lflag); \
12999 +       (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
13000 +       get_user((termios)->c_line, &(termio)->c_line); \
13001 +       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
13002 +})
13003 +
13004 +/*
13005 + * Translate a "termios" structure into a "termio". Ugh.
13006 + */
13007 +#define kernel_termios_to_user_termio(termio, termios) \
13008 +({ \
13009 +       put_user((termios)->c_iflag, &(termio)->c_iflag); \
13010 +       put_user((termios)->c_oflag, &(termio)->c_oflag); \
13011 +       put_user((termios)->c_cflag, &(termio)->c_cflag); \
13012 +       put_user((termios)->c_lflag, &(termio)->c_lflag); \
13013 +       put_user((termios)->c_line,  &(termio)->c_line); \
13014 +       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
13015 +})
13016 +
13017 +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
13018 +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
13019 +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
13020 +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
13021 +
13022 +#endif /* __KERNEL__ */
13023 +
13024 +#endif /* _ASM_UBICOM32_TERMIOS_H */
13025 --- /dev/null
13026 +++ b/arch/ubicom32/include/asm/thread-asm.h
13027 @@ -0,0 +1,51 @@
13028 +/*
13029 + * arch/ubicom32/include/asm/thread-asm.h
13030 + *   Ubicom32 architecture specific thread definitions.
13031 + *
13032 + * (C) Copyright 2009, Ubicom, Inc.
13033 + *
13034 + * This file is part of the Ubicom32 Linux Kernel Port.
13035 + *
13036 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13037 + * it and/or modify it under the terms of the GNU General Public License
13038 + * as published by the Free Software Foundation, either version 2 of the
13039 + * License, or (at your option) any later version.
13040 + *
13041 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13042 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13043 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13044 + * the GNU General Public License for more details.
13045 + *
13046 + * You should have received a copy of the GNU General Public License
13047 + * along with the Ubicom32 Linux Kernel Port.  If not,
13048 + * see <http://www.gnu.org/licenses/>.
13049 + *
13050 + * Ubicom32 implementation derived from (with many thanks):
13051 + *   arch/m68knommu
13052 + *   arch/blackfin
13053 + *   arch/parisc
13054 + */
13055 +#ifndef _ASM_UBICOM32_THREAD_ASM_H
13056 +#define _ASM_UBICOM32_THREAD_ASM_H
13057 +
13058 +/*
13059 + * thread_get_self
13060 + *     Read and shift the current thread into reg
13061 + *
13062 + * Note that we don't need to mask the result as bits 6 through 31 of the
13063 + * ROSR are zeroes.
13064 + */
13065 +.macro thread_get_self reg
13066 +       lsr.4   \reg, ROSR, #2
13067 +.endm
13068 +
13069 +/*
13070 + * thread_get_self_mask
13071 + *     Read and shift the current thread mask into reg
13072 + */
13073 +.macro thread_get_self_mask reg
13074 +       lsr.4   \reg, ROSR, #2
13075 +       lsl.4   \reg, #1, \reg   /* Thread bit */
13076 +.endm
13077 +
13078 +#endif /* _ASM_UBICOM32_THREAD_ASM_H */
13079 --- /dev/null
13080 +++ b/arch/ubicom32/include/asm/thread.h
13081 @@ -0,0 +1,320 @@
13082 +/*
13083 + * arch/ubicom32/include/asm/thread.h
13084 + *   Ubicom32 architecture specific thread definitions.
13085 + *
13086 + * (C) Copyright 2009, Ubicom, Inc.
13087 + *
13088 + * This file is part of the Ubicom32 Linux Kernel Port.
13089 + *
13090 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13091 + * it and/or modify it under the terms of the GNU General Public License
13092 + * as published by the Free Software Foundation, either version 2 of the
13093 + * License, or (at your option) any later version.
13094 + *
13095 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13096 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13097 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13098 + * the GNU General Public License for more details.
13099 + *
13100 + * You should have received a copy of the GNU General Public License
13101 + * along with the Ubicom32 Linux Kernel Port.  If not,
13102 + * see <http://www.gnu.org/licenses/>.
13103 + *
13104 + * Ubicom32 implementation derived from (with many thanks):
13105 + *   arch/m68knommu
13106 + *   arch/blackfin
13107 + *   arch/parisc
13108 + */
13109 +#ifndef _ASM_UBICOM32_THREAD_H
13110 +#define _ASM_UBICOM32_THREAD_H
13111 +
13112 +#if !defined(__ASSEMBLY__)
13113 +
13114 +#include <asm/ptrace.h>
13115 +#include <asm/ubicom32-common.h>
13116 +
13117 +typedef int thread_t;
13118 +typedef unsigned char thread_type_t;
13119 +typedef void (*thread_exec_fn_t)(void *arg);
13120 +
13121 +#define THREAD_NULL 0x40
13122 +#define THREAD_TYPE_HRT (1 << 0)
13123 +#define THREAD_TYPE_SPECIAL 0
13124 +#define THREAD_TYPE_NORMAL 0
13125 +#define THREAD_TYPE_BACKGROUND (1 << 1)
13126 +
13127 +/*
13128 + * This is the upper bound on the maximum hardware threads that one will find
13129 + * on a Ubicom processor. It is used to size per hardware thread data structures.
13130 + */
13131 +#define THREAD_ARCHITECTURAL_MAX 16
13132 +
13133 +/*
13134 + * TODO: Rename this at some point to be thread_
13135 + */
13136 +extern unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
13137 +
13138 +
13139 +/*
13140 + * thread_get_self()
13141 + */
13142 +static inline thread_t thread_get_self(void)
13143 +{
13144 +       thread_t result;
13145 +
13146 +       /*
13147 +        * Note that ROSR has zeroes in bits 6 through 31 and so we don't need
13148 +        * to do any additional bit masking here.
13149 +        */
13150 +       asm (
13151 +               "lsr.4  %0, ROSR, #2    \n\t"
13152 +               : "=d" (result)
13153 +               :
13154 +               : "cc"
13155 +       );
13156 +
13157 +       return result;
13158 +}
13159 +
13160 +/*
13161 + * thread_suspend()
13162 + */
13163 +static inline void thread_suspend(void)
13164 +{
13165 +       asm volatile (
13166 +               "suspend\n\t"
13167 +               :
13168 +               :
13169 +       );
13170 +}
13171 +
13172 +/*
13173 + * thread_resume()
13174 + */
13175 +static inline void thread_resume(thread_t thread)
13176 +{
13177 +       asm volatile (
13178 +               "move.4         MT_ACTIVE_SET, %0       \n\t"
13179 +               "pipe_flush     0                       \n\t"
13180 +               "pipe_flush     0                       \n\t"
13181 +               :
13182 +               : "d" (1 << thread)
13183 +       );
13184 +}
13185 +
13186 +
13187 +
13188 +/*
13189 + * thread_enable_mask()
13190 + *     Enable all threads in the mask.
13191 + *
13192 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13193 + */
13194 +static inline void thread_enable_mask(unsigned int mask)
13195 +{
13196 +       /*
13197 +        * must flush the pipeline twice.
13198 +        * first pipe_flush is to ensure write to MT_EN is completed
13199 +        * second one is to ensure any new instructions from
13200 +        * the targeted thread (the one being disabled), that
13201 +        * are issued while the write to MT_EN is being executed,
13202 +        * are completed.
13203 +        */
13204 +       UBICOM32_LOCK(MT_EN_LOCK_BIT);
13205 +       asm volatile (
13206 +               "or.4           MT_EN, MT_EN, %0        \n\t"
13207 +               "pipe_flush     0                       \n\t"
13208 +               "pipe_flush     0                       \n\t"
13209 +               :
13210 +               : "d" (mask)
13211 +               : "cc"
13212 +       );
13213 +       UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13214 +}
13215 +
13216 +/*
13217 + * thread_enable()
13218 + */
13219 +static inline void thread_enable(thread_t thread)
13220 +{
13221 +       thread_enable_mask(1 << thread);
13222 +}
13223 +
13224 +/*
13225 + * thread_disable_mask()
13226 + *     Disable all threads in the mask.
13227 + *
13228 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13229 + */
13230 +static inline void thread_disable_mask(unsigned int mask)
13231 +{
13232 +       /*
13233 +        * must flush the pipeline twice.
13234 +        * first pipe_flush is to ensure write to MT_EN is completed
13235 +        * second one is to ensure any new instructions from
13236 +        * the targeted thread (the one being disabled), that
13237 +        * are issued while the write to MT_EN is being executed,
13238 +        * are completed.
13239 +        */
13240 +       UBICOM32_LOCK(MT_EN_LOCK_BIT);
13241 +       asm volatile (
13242 +               "and.4          MT_EN, MT_EN, %0        \n\t"
13243 +               "pipe_flush     0                       \n\t"
13244 +               "pipe_flush     0                       \n\t"
13245 +               :
13246 +               : "d" (~mask)
13247 +               : "cc"
13248 +       );
13249 +       UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13250 +}
13251 +
13252 +/*
13253 + * thread_disable()
13254 + */
13255 +static inline void thread_disable(thread_t thread)
13256 +{
13257 +       thread_disable_mask(1 << thread);
13258 +}
13259 +
13260 +/*
13261 + * thread_disable_others()
13262 + *     Disable all other threads
13263 + */
13264 +static inline void thread_disable_others(void)
13265 +{
13266 +       thread_t self = thread_get_self();
13267 +       thread_disable_mask(~(1 << self));
13268 +}
13269 +
13270 +/*
13271 + * thread_is_trapped()
13272 + *     Is the specified tid trapped?
13273 + */
13274 +static inline int thread_is_trapped(thread_t tid)
13275 +{
13276 +       int thread_mask = (1 << tid);
13277 +       int trap_thread;
13278 +
13279 +       asm (
13280 +               "move.4         %0, MT_TRAP             \n\t"
13281 +               : "=d" (trap_thread)
13282 +               :
13283 +       );
13284 +       return (trap_thread & thread_mask);
13285 +}
13286 +
13287 +/*
13288 + * thread_is_enabled()
13289 + *     Is the specified tid enabled?
13290 + */
13291 +static inline int thread_is_enabled(thread_t tid)
13292 +{
13293 +       int thread_mask = (1 << tid);
13294 +       int enabled_threads;
13295 +
13296 +       asm (
13297 +               "move.4         %0, MT_EN               \n\t"
13298 +               : "=d" (enabled_threads)
13299 +               :
13300 +       );
13301 +       return (enabled_threads & thread_mask);
13302 +}
13303 +
13304 +/*
13305 + * thread_get_instruction_count()
13306 + */
13307 +static inline unsigned int thread_get_instruction_count(void)
13308 +{
13309 +       unsigned int result;
13310 +       asm (
13311 +               "move.4         %0, INST_CNT            \n\t"
13312 +               : "=r" (result)
13313 +       );
13314 +       return result;
13315 +}
13316 +
13317 +/*
13318 + * thread_get_pc()
13319 + *     pc could point to a speculative and cancelled instruction unless thread is disabled
13320 + */
13321 +static inline void *thread_get_pc(thread_t thread)
13322 +{
13323 +       void *result;
13324 +       asm (
13325 +               "move.4         csr, %1         \n\t"
13326 +               "setcsr_flush   0               \n\t"
13327 +               "move.4         %0, pc          \n\t"
13328 +               "move.4         csr, #0         \n\t"
13329 +               "setcsr_flush   0               \n\t"
13330 +               : "=r" (result)
13331 +               : "r" ((thread << 9) | (1 << 8))
13332 +       );
13333 +       return result;
13334 +}
13335 +
13336 +/*
13337 + * thread_get_trap_cause()
13338 + *     This should be called only when the thread is not running
13339 + */
13340 +static inline unsigned int thread_get_trap_cause(thread_t thread)
13341 +{
13342 +       unsigned int result;
13343 +       asm (
13344 +               "move.4         csr, %1         \n\t"
13345 +               "setcsr_flush   0               \n\t"
13346 +               "move.4         %0, trap_cause  \n\t"
13347 +               "move.4         csr, #0         \n\t"
13348 +               "setcsr_flush   0               \n\t"
13349 +               : "=r" (result)
13350 +               : "r" ((thread << 9) | (1 << 8))
13351 +       );
13352 +       return result;
13353 +}
13354 +
13355 +/*
13356 + * THREAD_STALL macro.
13357 + */
13358 +#define THREAD_STALL \
13359 +               asm volatile ( \
13360 +                       "move.4 mt_dbg_active_clr, #-1  \n\t" \
13361 +                       "pipe_flush 0                   \n\t" \
13362 +                       : \
13363 +                       : \
13364 +               )
13365 +
13366 +extern unsigned int thread_get_mainline(void);
13367 +extern void thread_set_mainline(thread_t tid);
13368 +extern thread_t thread_alloc(void);
13369 +extern thread_t thread_start(thread_t thread, thread_exec_fn_t exec, void *arg, unsigned int *sp_high, thread_type_t type);
13370 +
13371 +/*
13372 + * asm macros
13373 + */
13374 +asm (
13375 +/*
13376 + * thread_get_self
13377 + *     Read and shift the current thread into reg
13378 + *
13379 + * Note that we don't need to mask the result as bits 6 through 31 of the
13380 + * ROSR are zeroes.
13381 + */
13382 +".macro        thread_get_self reg             \n\t"
13383 +"      lsr.4   \\reg, ROSR, #2         \n\t"
13384 +".endm                                 \n\t"
13385 +
13386 +/*
13387 + * thread_get_self_mask
13388 + *     Read and shift the current thread mask into reg
13389 + */
13390 +".macro        thread_get_self_mask reg        \n\t"
13391 +"      lsr.4   \\reg, ROSR, #2         \n\t"
13392 +"      lsl.4   \\reg, #1, \\reg        \n\t"    /* Thread bit */
13393 +".endm                                 \n\t"
13394 +);
13395 +
13396 +#else /* __ASSEMBLY__ */
13397 +
13398 +#include <asm/thread-asm.h>
13399 +
13400 +#endif /* __ASSEMBLY__ */
13401 +#endif /* _ASM_UBICOM32_THREAD_H */
13402 --- /dev/null
13403 +++ b/arch/ubicom32/include/asm/thread_info.h
13404 @@ -0,0 +1,134 @@
13405 +/*
13406 + * arch/ubicom32/include/asm/thread_info.h
13407 + *   Ubicom32 architecture low-level thread information.
13408 + *
13409 + * (C) Copyright 2009, Ubicom, Inc.
13410 + * Adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
13411 + * Copyright (C) 2002  David Howells (dhowells@redhat.com)
13412 + * - Incorporating suggestions made by Linus Torvalds and Dave Miller
13413 + *
13414 + * This file is part of the Ubicom32 Linux Kernel Port.
13415 + *
13416 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13417 + * it and/or modify it under the terms of the GNU General Public License
13418 + * as published by the Free Software Foundation, either version 2 of the
13419 + * License, or (at your option) any later version.
13420 + *
13421 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13422 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13423 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13424 + * the GNU General Public License for more details.
13425 + *
13426 + * You should have received a copy of the GNU General Public License
13427 + * along with the Ubicom32 Linux Kernel Port.  If not,
13428 + * see <http://www.gnu.org/licenses/>.
13429 + *
13430 + * Ubicom32 implementation derived from (with many thanks):
13431 + *   arch/m68knommu
13432 + *   arch/blackfin
13433 + *   arch/parisc
13434 + */
13435 +
13436 +#ifndef _ASM_UBICOM32_THREAD_INFO_H
13437 +#define _ASM_UBICOM32_THREAD_INFO_H
13438 +
13439 +#include <asm/page.h>
13440 +
13441 +/*
13442 + * Size of kernel stack for each process. This must be a power of 2...
13443 + */
13444 +#ifdef CONFIG_4KSTACKS
13445 +#define THREAD_SIZE_ORDER (0)
13446 +#else
13447 +#define THREAD_SIZE_ORDER (1)
13448 +#endif
13449 +
13450 +/*
13451 + * for asm files, THREAD_SIZE is now generated by asm-offsets.c
13452 + */
13453 +#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
13454 +
13455 +#ifdef __KERNEL__
13456 +
13457 +#ifndef __ASSEMBLY__
13458 +
13459 +/*
13460 + * low level task data.
13461 + */
13462 +struct thread_info {
13463 +       struct task_struct *task;               /* main task structure */
13464 +       struct exec_domain *exec_domain;        /* execution domain */
13465 +       unsigned long      flags;               /* low level flags */
13466 +       int                cpu;                 /* cpu we're on */
13467 +       int                preempt_count;       /* 0 => preemptable, <0 => BUG */
13468 +       int                interrupt_nesting;   /* Interrupt nesting level. */
13469 +       struct restart_block restart_block;
13470 +};
13471 +
13472 +/*
13473 + * macros/functions for gaining access to the thread information structure
13474 + */
13475 +#define INIT_THREAD_INFO(tsk)                  \
13476 +{                                              \
13477 +       .task           = &tsk,                 \
13478 +       .exec_domain    = &default_exec_domain, \
13479 +       .flags          = 0,                    \
13480 +       .cpu            = 0,                    \
13481 +       .interrupt_nesting      = 0,            \
13482 +       .restart_block  = {                     \
13483 +               .fn = do_no_restart_syscall,    \
13484 +       },                                      \
13485 +}
13486 +
13487 +#define init_thread_info       (init_thread_union.thread_info)
13488 +#define init_stack             (init_thread_union.stack)
13489 +
13490 +
13491 +/* how to get the thread information struct from C */
13492 +static inline struct thread_info *current_thread_info(void)
13493 +{
13494 +       struct thread_info *ti;
13495 +
13496 +       asm (
13497 +               "and.4  %0, sp, %1\n\t"
13498 +               : "=&r" (ti)
13499 +               : "d" (~(THREAD_SIZE-1))
13500 +               : "cc"
13501 +       );
13502 +
13503 +       return ti;
13504 +}
13505 +
13506 +#define STACK_WARN (THREAD_SIZE / 8)
13507 +
13508 +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR 1
13509 +
13510 +/* thread information allocation */
13511 +#define alloc_thread_info(tsk) ((struct thread_info *) \
13512 +                               __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
13513 +#define free_thread_info(ti)   free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
13514 +#endif /* __ASSEMBLY__ */
13515 +
13516 +#define        PREEMPT_ACTIVE  0x4000000
13517 +
13518 +/*
13519 + * thread information flag bit numbers
13520 + */
13521 +#define TIF_SYSCALL_TRACE      0       /* syscall trace active */
13522 +#define TIF_SIGPENDING         1       /* signal pending */
13523 +#define TIF_NEED_RESCHED       2       /* rescheduling necessary */
13524 +#define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
13525 +                                          TIF_NEED_RESCHED */
13526 +#define TIF_MEMDIE             4
13527 +
13528 +/* as above, but as bit values */
13529 +#define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
13530 +#define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
13531 +#define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
13532 +#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
13533 +
13534 +#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
13535 +
13536 +#endif /* __KERNEL__ */
13537 +
13538 +#endif /* _ASM_UBICOM32_THREAD_INFO_H */
13539 --- /dev/null
13540 +++ b/arch/ubicom32/include/asm/timex.h
13541 @@ -0,0 +1,56 @@
13542 +/*
13543 + * arch/ubicom32/include/asm/timex.h
13544 + *   Ubicom32 architecture timex specifications.
13545 + *
13546 + * (C) Copyright 2009, Ubicom, Inc.
13547 + *
13548 + * This file is part of the Ubicom32 Linux Kernel Port.
13549 + *
13550 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13551 + * it and/or modify it under the terms of the GNU General Public License
13552 + * as published by the Free Software Foundation, either version 2 of the
13553 + * License, or (at your option) any later version.
13554 + *
13555 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13556 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13557 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13558 + * the GNU General Public License for more details.
13559 + *
13560 + * You should have received a copy of the GNU General Public License
13561 + * along with the Ubicom32 Linux Kernel Port.  If not,
13562 + * see <http://www.gnu.org/licenses/>.
13563 + *
13564 + * Ubicom32 implementation derived from (with many thanks):
13565 + *   arch/m68knommu
13566 + *   arch/blackfin
13567 + *   arch/parisc
13568 + */
13569 +#ifndef _ASM_UBICOM32_TIMEX_H
13570 +#define _ASM_UBICOM32_TIMEX_H
13571 +
13572 +#define CLOCK_TICK_RATE        266000000
13573 +
13574 +// #define ARCH_HAS_READ_CURRENT_TIMER
13575 +
13576 +typedef unsigned long cycles_t;
13577 +
13578 +static inline cycles_t get_cycles(void)
13579 +{
13580 +       return 0;
13581 +}
13582 +
13583 +extern int timer_alloc(void);
13584 +extern void timer_set(int timervector, unsigned int cycles);
13585 +extern int timer_reset(int timervector, unsigned int cycles);
13586 +extern void timer_tick_init(void);
13587 +extern void timer_device_init(void);
13588 +
13589 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13590 +extern void local_timer_interrupt(void);
13591 +#endif
13592 +
13593 +#if defined(CONFIG_LOCAL_TIMERS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13594 +extern int local_timer_setup(unsigned int cpu);
13595 +#endif
13596 +
13597 +#endif /* _ASM_UBICOM32_TIMEX_H */
13598 --- /dev/null
13599 +++ b/arch/ubicom32/include/asm/tlbflush.h
13600 @@ -0,0 +1,79 @@
13601 +/*
13602 + * arch/ubicom32/include/asm/tlbflush.h
13603 + *   TLB operations for Ubicom32 architecture.
13604 + *
13605 + * (C) Copyright 2009, Ubicom, Inc.
13606 + * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
13607 + * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
13608 + *
13609 + * This file is part of the Ubicom32 Linux Kernel Port.
13610 + *
13611 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13612 + * it and/or modify it under the terms of the GNU General Public License
13613 + * as published by the Free Software Foundation, either version 2 of the
13614 + * License, or (at your option) any later version.
13615 + *
13616 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13617 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13618 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13619 + * the GNU General Public License for more details.
13620 + *
13621 + * You should have received a copy of the GNU General Public License
13622 + * along with the Ubicom32 Linux Kernel Port.  If not,
13623 + * see <http://www.gnu.org/licenses/>.
13624 + *
13625 + * Ubicom32 implementation derived from (with many thanks):
13626 + *   arch/m68knommu
13627 + *   arch/blackfin
13628 + *   arch/parisc
13629 + */
13630 +#ifndef _ASM_UBICOM32_TLB_FLUSH_H
13631 +#define _ASM_UBICOM32_TLB_FLUSH_H
13632 +
13633 +#include <asm/setup.h>
13634 +
13635 +/*
13636 + * flush all user-space atc entries.
13637 + */
13638 +static inline void __flush_tlb(void)
13639 +{
13640 +       BUG();
13641 +}
13642 +
13643 +static inline void __flush_tlb_one(unsigned long addr)
13644 +{
13645 +       BUG();
13646 +}
13647 +
13648 +#define flush_tlb() __flush_tlb()
13649 +
13650 +/*
13651 + * flush all atc entries (both kernel and user-space entries).
13652 + */
13653 +static inline void flush_tlb_all(void)
13654 +{
13655 +       BUG();
13656 +}
13657 +
13658 +static inline void flush_tlb_mm(struct mm_struct *mm)
13659 +{
13660 +       BUG();
13661 +}
13662 +
13663 +static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
13664 +{
13665 +       BUG();
13666 +}
13667 +
13668 +static inline void flush_tlb_range(struct mm_struct *mm,
13669 +                                  unsigned long start, unsigned long end)
13670 +{
13671 +       BUG();
13672 +}
13673 +
13674 +static inline void flush_tlb_kernel_page(unsigned long addr)
13675 +{
13676 +       BUG();
13677 +}
13678 +
13679 +#endif /* _ASM_UBICOM32_TLB_FLUSH_H */
13680 --- /dev/null
13681 +++ b/arch/ubicom32/include/asm/tlb.h
13682 @@ -0,0 +1,47 @@
13683 +/*
13684 + * arch/ubicom32/include/asm/tlb.h
13685 + *   Ubicom32 architecture TLB operations.
13686 + *
13687 + * (C) Copyright 2009, Ubicom, Inc.
13688 + *
13689 + * This file is part of the Ubicom32 Linux Kernel Port.
13690 + *
13691 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13692 + * it and/or modify it under the terms of the GNU General Public License
13693 + * as published by the Free Software Foundation, either version 2 of the
13694 + * License, or (at your option) any later version.
13695 + *
13696 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13697 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13698 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13699 + * the GNU General Public License for more details.
13700 + *
13701 + * You should have received a copy of the GNU General Public License
13702 + * along with the Ubicom32 Linux Kernel Port.  If not,
13703 + * see <http://www.gnu.org/licenses/>.
13704 + *
13705 + * Ubicom32 implementation derived from (with many thanks):
13706 + *   arch/m68knommu
13707 + *   arch/blackfin
13708 + *   arch/parisc
13709 + */
13710 +#ifndef _ASM_UBICOM32_TLB_H
13711 +#define _ASM_UBICOM32_TLB_H
13712 +
13713 +/*
13714 + * ubicom32 doesn't need any special per-pte or
13715 + * per-vma handling..
13716 + */
13717 +#define tlb_start_vma(tlb, vma)        do { } while (0)
13718 +#define tlb_end_vma(tlb, vma)  do { } while (0)
13719 +#define __tlb_remove_tlb_entry(tlb, ptep, address)     do { } while (0)
13720 +
13721 +/*
13722 + * .. because we flush the whole mm when it
13723 + * fills up.
13724 + */
13725 +#define tlb_flush(tlb)
13726 +
13727 +#include <asm-generic/tlb.h>
13728 +
13729 +#endif /* _ASM_UBICOM32_TLB_H */
13730 --- /dev/null
13731 +++ b/arch/ubicom32/include/asm/topology.h
13732 @@ -0,0 +1,33 @@
13733 +/*
13734 + * arch/ubicom32/include/asm/topology.h
13735 + *   Generic topology.h definitions for Ubicom32 architecture.
13736 + *
13737 + * (C) Copyright 2009, Ubicom, Inc.
13738 + *
13739 + * This file is part of the Ubicom32 Linux Kernel Port.
13740 + *
13741 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13742 + * it and/or modify it under the terms of the GNU General Public License
13743 + * as published by the Free Software Foundation, either version 2 of the
13744 + * License, or (at your option) any later version.
13745 + *
13746 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13747 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13748 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13749 + * the GNU General Public License for more details.
13750 + *
13751 + * You should have received a copy of the GNU General Public License
13752 + * along with the Ubicom32 Linux Kernel Port.  If not,
13753 + * see <http://www.gnu.org/licenses/>.
13754 + *
13755 + * Ubicom32 implementation derived from (with many thanks):
13756 + *   arch/m68knommu
13757 + *   arch/blackfin
13758 + *   arch/parisc
13759 + */
13760 +#ifndef _ASM_UBICOM32_TOPOLOGY_H
13761 +#define _ASM_UBICOM32_TOPOLOGY_H
13762 +
13763 +#include <asm-generic/topology.h>
13764 +
13765 +#endif /* _ASM_UBICOM32_TOPOLOGY_H */
13766 --- /dev/null
13767 +++ b/arch/ubicom32/include/asm/traps.h
13768 @@ -0,0 +1,55 @@
13769 +/*
13770 + * arch/ubicom32/include/asm/traps.h
13771 + *   Trap related definitions for Ubicom32 architecture.
13772 + *
13773 + * (C) Copyright 2009, Ubicom, Inc.
13774 + *
13775 + * This file is part of the Ubicom32 Linux Kernel Port.
13776 + *
13777 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13778 + * it and/or modify it under the terms of the GNU General Public License
13779 + * as published by the Free Software Foundation, either version 2 of the
13780 + * License, or (at your option) any later version.
13781 + *
13782 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13783 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13784 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13785 + * the GNU General Public License for more details.
13786 + *
13787 + * You should have received a copy of the GNU General Public License
13788 + * along with the Ubicom32 Linux Kernel Port.  If not,
13789 + * see <http://www.gnu.org/licenses/>.
13790 + *
13791 + * Ubicom32 implementation derived from (with many thanks):
13792 + *   arch/m68knommu
13793 + *   arch/blackfin
13794 + *   arch/parisc
13795 + */
13796 +
13797 +#ifndef _ASM_UBICOM32_TRAPS_H
13798 +#define _ASM_UBICOM32_TRAPS_H
13799 +
13800 +/*
13801 + * Trap causes passed from ultra to Host OS
13802 + */
13803 +#define TRAP_CAUSE_TOTAL               13
13804 +#define TRAP_CAUSE_DST_RANGE_ERR       12
13805 +#define TRAP_CAUSE_SRC1_RANGE_ERR      11
13806 +#define TRAP_CAUSE_I_RANGE_ERR         10
13807 +#define TRAP_CAUSE_DCAPT               9
13808 +#define TRAP_CAUSE_DST_SERROR          8
13809 +#define TRAP_CAUSE_SRC1_SERROR         7
13810 +#define TRAP_CAUSE_DST_MISALIGNED      6
13811 +#define TRAP_CAUSE_SRC1_MISALIGNED     5
13812 +#define TRAP_CAUSE_DST_DECODE_ERR      4
13813 +#define TRAP_CAUSE_SRC1_DECODE_ERR     3
13814 +#define TRAP_CAUSE_ILLEGAL_INST                2
13815 +#define TRAP_CAUSE_I_SERROR            1
13816 +#define TRAP_CAUSE_I_DECODE_ERR                0
13817 +
13818 +extern void trap_handler(int irq, struct pt_regs *regs);
13819 +extern void trap_init_interrupt(void);
13820 +extern void unaligned_emulate(unsigned int thread);
13821 +extern int unaligned_only(unsigned int cause);
13822 +
13823 +#endif /* _ASM_UBICOM32_TRAPS_H */
13824 --- /dev/null
13825 +++ b/arch/ubicom32/include/asm/types.h
13826 @@ -0,0 +1,75 @@
13827 +/*
13828 + * arch/ubicom32/include/asm/types.h
13829 + *   Date type definitions for Ubicom32 architecture.
13830 + *
13831 + * (C) Copyright 2009, Ubicom, Inc.
13832 + *
13833 + * This file is part of the Ubicom32 Linux Kernel Port.
13834 + *
13835 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13836 + * it and/or modify it under the terms of the GNU General Public License
13837 + * as published by the Free Software Foundation, either version 2 of the
13838 + * License, or (at your option) any later version.
13839 + *
13840 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13841 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13842 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13843 + * the GNU General Public License for more details.
13844 + *
13845 + * You should have received a copy of the GNU General Public License
13846 + * along with the Ubicom32 Linux Kernel Port.  If not,
13847 + * see <http://www.gnu.org/licenses/>.
13848 + *
13849 + * Ubicom32 implementation derived from (with many thanks):
13850 + *   arch/m68knommu
13851 + *   arch/blackfin
13852 + *   arch/parisc
13853 + */
13854 +#ifndef _ASM_UBICOM32_TYPES_H
13855 +#define _ASM_UBICOM32_TYPES_H
13856 +
13857 +/*
13858 + * This file is never included by application software unless
13859 + * explicitly requested (e.g., via linux/types.h) in which case the
13860 + * application is Linux specific so (user-) name space pollution is
13861 + * not a major issue.  However, for interoperability, libraries still
13862 + * need to be careful to avoid a name clashes.
13863 + */
13864 +
13865 +#include <asm-generic/int-ll64.h>
13866 +
13867 +#ifndef __ASSEMBLY__
13868 +
13869 +typedef unsigned short umode_t;
13870 +
13871 +#endif /* __ASSEMBLY__ */
13872 +
13873 +/*
13874 + * These aren't exported outside the kernel to avoid name space clashes
13875 + */
13876 +#ifdef __KERNEL__
13877 +
13878 +#define BITS_PER_LONG 32
13879 +
13880 +#ifndef __ASSEMBLY__
13881 +
13882 +/* DMA addresses are always 32-bits wide */
13883 +
13884 +typedef u32 dma_addr_t;
13885 +typedef u32 dma64_addr_t;
13886 +
13887 +/*
13888 + * XXX These are "Ubicom style" typedefs. They should be removed in all files used by linux.
13889 + */
13890 +typedef u32 u32_t;
13891 +typedef s32 s32_t;
13892 +typedef u16 u16_t;
13893 +typedef s16 s16_t;
13894 +typedef u8 u8_t;
13895 +typedef s8 s8_t;
13896 +
13897 +#endif /* __ASSEMBLY__ */
13898 +
13899 +#endif /* __KERNEL__ */
13900 +
13901 +#endif /* _ASM_UBICOM32_TYPES_H */
13902 --- /dev/null
13903 +++ b/arch/ubicom32/include/asm/uaccess.h
13904 @@ -0,0 +1,347 @@
13905 +/*
13906 + * arch/ubicom32/include/asm/uaccess.h
13907 + *   User space memory access functions for Ubicom32 architecture.
13908 + *
13909 + * (C) Copyright 2009, Ubicom, Inc.
13910 + *
13911 + * This file is part of the Ubicom32 Linux Kernel Port.
13912 + *
13913 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13914 + * it and/or modify it under the terms of the GNU General Public License
13915 + * as published by the Free Software Foundation, either version 2 of the
13916 + * License, or (at your option) any later version.
13917 + *
13918 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13919 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13920 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13921 + * the GNU General Public License for more details.
13922 + *
13923 + * You should have received a copy of the GNU General Public License
13924 + * along with the Ubicom32 Linux Kernel Port.  If not,
13925 + * see <http://www.gnu.org/licenses/>.
13926 + *
13927 + * Ubicom32 implementation derived from (with many thanks):
13928 + *   arch/m68knommu
13929 + *   arch/blackfin
13930 + *   arch/parisc
13931 + *   arch/alpha
13932 + */
13933 +#ifndef _ASM_UBICOM32_UACCESS_H
13934 +#define _ASM_UBICOM32_UACCESS_H
13935 +
13936 +/*
13937 + * User space memory access functions
13938 + */
13939 +#include <linux/sched.h>
13940 +#include <linux/mm.h>
13941 +#include <linux/string.h>
13942 +
13943 +#include <asm/segment.h>
13944 +
13945 +#define VERIFY_READ    0
13946 +#define VERIFY_WRITE   1
13947 +
13948 +/*
13949 + * The exception table consists of pairs of addresses: the first is the
13950 + * address of an instruction that is allowed to fault, and the second is
13951 + * the address at which the program should continue.  No registers are
13952 + * modified, so it is entirely up to the continuation code to figure out
13953 + * what to do.
13954 + *
13955 + * All the routines below use bits of fixup code that are out of line
13956 + * with the main instruction path.  This means when everything is well,
13957 + * we don't even have to jump over them.  Further, they do not intrude
13958 + * on our cache or tlb entries.
13959 + */
13960 +struct exception_table_entry
13961 +{
13962 +       unsigned long insn, fixup;
13963 +};
13964 +
13965 +/*
13966 + * Ubicom32 does not currently support the exception table handling.
13967 + */
13968 +extern unsigned long search_exception_table(unsigned long);
13969 +
13970 +
13971 +#if defined(CONFIG_ACCESS_OK_CHECKS_ENABLED)
13972 +extern int __access_ok(unsigned long addr, unsigned long size);
13973 +#else
13974 +static inline int __access_ok(unsigned long addr, unsigned long size)
13975 +{
13976 +       return 1;
13977 +}
13978 +#endif
13979 +#define access_ok(type, addr, size) \
13980 +       likely(__access_ok((unsigned long)(addr), (size)))
13981 +
13982 +/*
13983 + * The following functions do not exist.  They keep callers
13984 + * of put_user and get_user from passing unsupported argument
13985 + * types.  They result in a link time error.
13986 + */
13987 +extern int __put_user_bad(void);
13988 +extern int __get_user_bad(void);
13989 +
13990 +/*
13991 + * __put_user_no_check()
13992 + *     Put the requested data into the user space verifying the address
13993 + *
13994 + * Careful to not
13995 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
13996 + * (b) require any knowledge of processes at this stage
13997 + */
13998 +#define __put_user_no_check(x, ptr, size)              \
13999 +({                                                     \
14000 +       int __pu_err = 0;                               \
14001 +       __typeof__(*(ptr)) __user *__pu_addr = (ptr);   \
14002 +       switch (size) {                                 \
14003 +       case 1:                                         \
14004 +       case 2:                                         \
14005 +       case 4:                                         \
14006 +       case 8:                                         \
14007 +               *__pu_addr = (__typeof__(*(ptr)))x;     \
14008 +               break;                                  \
14009 +       default:                                        \
14010 +               __pu_err = __put_user_bad();            \
14011 +               break;                                  \
14012 +       }                                               \
14013 +       __pu_err;                                       \
14014 +})
14015 +
14016 +/*
14017 + * __put_user_check()
14018 + *     Put the requested data into the user space verifying the address
14019 + *
14020 + * Careful to not
14021 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
14022 + * (b) require any knowledge of processes at this stage
14023 + *
14024 + * If requested, access_ok() will verify that ptr is a valid user
14025 + * pointer.
14026 + */
14027 +#define __put_user_check(x, ptr, size)                         \
14028 +({                                                             \
14029 +       int __pu_err = -EFAULT;                                 \
14030 +       __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
14031 +       if (access_ok(VERIFY_WRITE, __pu_addr, size)) {         \
14032 +               __pu_err = 0;                                   \
14033 +               switch (size) {                                 \
14034 +               case 1:                                         \
14035 +               case 2:                                         \
14036 +               case 4:                                         \
14037 +               case 8:                                         \
14038 +                       *__pu_addr = (__typeof__(*(ptr)))x;     \
14039 +                       break;                                  \
14040 +               default:                                        \
14041 +                       __pu_err = __put_user_bad();            \
14042 +                       break;                                  \
14043 +               }                                               \
14044 +       }                                                       \
14045 +       __pu_err;                                               \
14046 +})
14047 +
14048 +/*
14049 + * __get_user_no_check()
14050 + *     Read the value at ptr into x.
14051 + *
14052 + * If requested, access_ok() will verify that ptr is a valid user
14053 + * pointer.  If the caller passes a modifying argument for ptr (e.g. x++)
14054 + * this macro will not work.
14055 + */
14056 +#define __get_user_no_check(x, ptr, size)                      \
14057 +({                                                             \
14058 +       int __gu_err = 0;                                       \
14059 +       __typeof__((x)) __gu_val = 0;                           \
14060 +       const __typeof__(*(ptr)) __user *__gu_addr = (ptr);     \
14061 +       switch (size) {                                         \
14062 +       case 1:                                                 \
14063 +       case 2:                                                 \
14064 +       case 4:                                                 \
14065 +       case 8:                                                 \
14066 +               __gu_val = (__typeof__((x)))*(__gu_addr);       \
14067 +               break;                                          \
14068 +       default:                                                \
14069 +               __gu_err = __get_user_bad();                    \
14070 +               (x) = 0;                                        \
14071 +               break;                                          \
14072 +       }                                                       \
14073 +       (x) = __gu_val;                                         \
14074 +       __gu_err;                                               \
14075 +})
14076 +
14077 +/*
14078 + * __get_user_check()
14079 + *     Read the value at ptr into x.
14080 + *
14081 + * If requested, access_ok() will verify that ptr is a valid user
14082 + * pointer.
14083 + */
14084 +#define __get_user_check(x, ptr, size)                                 \
14085 +({                                                                     \
14086 +       int __gu_err = -EFAULT;                                         \
14087 +       __typeof__(x) __gu_val = 0;                                     \
14088 +       const __typeof__(*(ptr)) __user *__gu_addr = (ptr);             \
14089 +       if (access_ok(VERIFY_READ, __gu_addr, size)) {                  \
14090 +               __gu_err = 0;                                           \
14091 +               switch (size) {                                         \
14092 +               case 1:                                                 \
14093 +               case 2:                                                 \
14094 +               case 4:                                                 \
14095 +               case 8:                                                 \
14096 +                       __gu_val = (__typeof__((x)))*(__gu_addr);       \
14097 +                       break;                                          \
14098 +               default:                                                \
14099 +                       __gu_err = __get_user_bad();                    \
14100 +                       (x) = 0;                                        \
14101 +                       break;                                          \
14102 +               }                                                       \
14103 +       }                                                               \
14104 +       (x) = __gu_val;                                                 \
14105 +       __gu_err;                                                       \
14106 +})
14107 +
14108 +/*
14109 + * The "xxx" versions are allowed to perform some amount of address
14110 + * space checking.  See access_ok().
14111 + */
14112 +#define put_user(x,ptr) \
14113 +       __put_user_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14114 +#define get_user(x,ptr) \
14115 +       __get_user_check((x), (ptr), sizeof(*(ptr)))
14116 +
14117 +/*
14118 + * The "__xxx" versions do not do address space checking, useful when
14119 + * doing multiple accesses to the same area (the programmer has to do the
14120 + * checks by hand with "access_ok()")
14121 + */
14122 +#define __put_user(x,ptr) \
14123 +       __put_user_no_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14124 +#define __get_user(x,ptr) \
14125 +       __get_user_no_check((x), (ptr), sizeof(*(ptr)))
14126 +
14127 +/*
14128 + * __copy_tofrom_user_no_check()
14129 + *     Copy the data either to or from user space.
14130 + *
14131 + * Return the number of bytes NOT copied.
14132 + */
14133 +static inline unsigned long
14134 +__copy_tofrom_user_no_check(void *to, const void *from, unsigned long n)
14135 +{
14136 +       memcpy(to, from, n);
14137 +       return 0;
14138 +}
14139 +
14140 +/*
14141 + * copy_to_user()
14142 + *     Copy the kernel data to user space.
14143 + *
14144 + * Return the number of bytes that were copied.
14145 + */
14146 +static inline unsigned long
14147 +copy_to_user(void __user *to, const void *from, unsigned long n)
14148 +{
14149 +       if (!access_ok(VERIFY_WRITE, to, n)) {
14150 +               return n;
14151 +       }
14152 +       return __copy_tofrom_user_no_check((__force void *)to, from, n);
14153 +}
14154 +
14155 +/*
14156 + * copy_from_user()
14157 + *     Copy the user data to kernel space.
14158 + *
14159 + * Return the number of bytes that were copied.  On error, we zero
14160 + * out the destination.
14161 + */
14162 +static inline unsigned long
14163 +copy_from_user(void *to, const void __user *from, unsigned long n)
14164 +{
14165 +       if (!access_ok(VERIFY_READ, from, n)) {
14166 +               return n;
14167 +       }
14168 +       return __copy_tofrom_user_no_check(to, (__force void *)from, n);
14169 +}
14170 +
14171 +#define __copy_to_user(to, from, n) \
14172 +       __copy_tofrom_user_no_check((__force void *)to, from, n)
14173 +#define __copy_from_user(to, from, n) \
14174 +       __copy_tofrom_user_no_check(to, (__force void *)from, n)
14175 +#define __copy_to_user_inatomic(to, from, n) \
14176 +       __copy_tofrom_user_no_check((__force void *)to, from, n)
14177 +#define __copy_from_user_inatomic(to, from, n) \
14178 +       __copy_tofrom_user_no_check(to, (__force void *)from, n)
14179 +
14180 +#define copy_to_user_ret(to, from, n, retval) \
14181 +       ({ if (copy_to_user(to, from, n)) return retval; })
14182 +
14183 +#define copy_from_user_ret(to, from, n, retval) \
14184 +       ({ if (copy_from_user(to, from, n)) return retval; })
14185 +
14186 +/*
14187 + * strncpy_from_user()
14188 + *     Copy a null terminated string from userspace.
14189 + *
14190 + * dst - Destination in kernel space.  The buffer must be at least count.
14191 + * src - Address of string in user space.
14192 + * count - Maximum number of bytes to copy (including the trailing NULL).
14193 + *
14194 + * Returns the length of the string (not including the trailing NULL.  If
14195 + * count is smaller than the length of the string, we copy count bytes
14196 + * and return count.
14197 + *
14198 + */
14199 +static inline long strncpy_from_user(char *dst, const __user char *src, long count)
14200 +{
14201 +       char *tmp;
14202 +       if (!access_ok(VERIFY_READ, src, 1)) {
14203 +               return -EFAULT;
14204 +       }
14205 +
14206 +       strncpy(dst, src, count);
14207 +       for (tmp = dst; *tmp && count > 0; tmp++, count--) {
14208 +               ;
14209 +       }
14210 +       return(tmp - dst);
14211 +}
14212 +
14213 +/*
14214 + * strnlen_user()
14215 + *     Return the size of a string (including the ending 0)
14216 + *
14217 + * Return -EFAULT on exception, a value greater than <n> if too long
14218 + */
14219 +static inline long strnlen_user(const __user char *src, long n)
14220 +{
14221 +       if (!access_ok(VERIFY_READ, src, 1)) {
14222 +               return -EFAULT;
14223 +       }
14224 +       return(strlen(src) + 1);
14225 +}
14226 +
14227 +#define strlen_user(str) strnlen_user(str, 32767)
14228 +
14229 +/*
14230 + * __clear_user()
14231 + *     Zero Userspace
14232 + */
14233 +static inline unsigned long __clear_user(__user void *to, unsigned long n)
14234 +{
14235 +       memset(to, 0, n);
14236 +       return 0;
14237 +}
14238 +
14239 +/*
14240 + * clear_user()
14241 + *     Zero user space (check for valid addresses)
14242 + */
14243 +static inline unsigned long clear_user(__user void *to, unsigned long n)
14244 +{
14245 +       if (!access_ok(VERIFY_WRITE, to, n)) {
14246 +               return -EFAULT;
14247 +       }
14248 +       return __clear_user(to, n);
14249 +}
14250 +
14251 +#endif /* _ASM_UBICOM32_UACCESS_H */
14252 --- /dev/null
14253 +++ b/arch/ubicom32/include/asm/uart_tio.h
14254 @@ -0,0 +1,126 @@
14255 +/*
14256 + * arch/ubicom32/include/asm/uart_tio.h
14257 + *   Ubicom32 architecture UART TIO definitions.
14258 + *
14259 + * (C) Copyright 2009, Ubicom, Inc.
14260 + *
14261 + * This file is part of the Ubicom32 Linux Kernel Port.
14262 + *
14263 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14264 + * it and/or modify it under the terms of the GNU General Public License
14265 + * as published by the Free Software Foundation, either version 2 of the
14266 + * License, or (at your option) any later version.
14267 + *
14268 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14269 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14270 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14271 + * the GNU General Public License for more details.
14272 + *
14273 + * You should have received a copy of the GNU General Public License
14274 + * along with the Ubicom32 Linux Kernel Port.  If not,
14275 + * see <http://www.gnu.org/licenses/>.
14276 + */
14277 +#ifndef _ASM_UBICOM32_UART_TIO_H
14278 +#define _ASM_UBICOM32_UART_TIO_H
14279 +
14280 +#include <asm/devtree.h>
14281 +
14282 +#define UARTTIO_RX_FIFO_SIZE           16
14283 +#define UARTTIO_TX_FIFO_SIZE           16
14284 +
14285 +/*
14286 + * Interrupt flags
14287 + */
14288 +#define UARTTIO_UART_INT_RX            0x00000001      // set when a character has been recevied (TODO: add watermark)
14289 +#define UARTTIO_UART_INT_RXOVF         0x00000002      // set when the receive buffer has overflowed
14290 +#define UARTTIO_UART_INT_RXFRAME       0x00000004      // set when there has been a framing error
14291 +
14292 +#define UARTTIO_UART_INT_TX            0x00000100      // set every time a character is transmitted
14293 +#define UARTTIO_UART_INT_TXBE          0x00000200      // set when the transmit buffer is empty (TODO: add watermark)
14294 +
14295 +#define UARTTIO_UART_FLAG_ENABLED      0x80000000
14296 +#define UARTTIO_UART_FLAG_SET_RATE      0x00000001      // set to update baud rate
14297 +#define UARTTIO_UART_FLAG_RESET         0x00000002      // set to reset the port
14298 +struct uarttio_uart {
14299 +       volatile u32_t                  flags;
14300 +
14301 +       volatile u32_t                  baud_rate;
14302 +       volatile u32_t                  current_baud_rate;
14303 +       u32_t                           bit_time;
14304 +
14305 +       /*
14306 +        * Modem status register
14307 +        */
14308 +       volatile u32_t                  status;
14309 +
14310 +       /*
14311 +        * Interrupt registers
14312 +        */
14313 +       volatile u32_t                  int_mask;
14314 +       volatile u32_t                  int_flags;
14315 +
14316 +       /*
14317 +        * Ports and pins
14318 +        */
14319 +       u32_t                           rx_port;
14320 +       u32_t                           tx_port;
14321 +
14322 +       u8_t                            rx_pin;
14323 +       u8_t                            tx_pin;
14324 +
14325 +       /*
14326 +        * Configuration Data
14327 +        */
14328 +       u8_t                            rx_bits;
14329 +       u8_t                            rx_stop_bits;
14330 +       u8_t                            tx_bits;
14331 +       u8_t                            tx_stop_bits;
14332 +
14333 +       /*
14334 +        * RX state machine data
14335 +        */
14336 +       u32_t                           rx_timer;
14337 +       u32_t                           rx_bit_pos;
14338 +       u32_t                           rx_byte;
14339 +       u32_t                           rx_fifo_head;
14340 +       u32_t                           rx_fifo_tail;
14341 +       u32_t                           rx_fifo_size;
14342 +
14343 +       /*
14344 +        * TX state machine data
14345 +        */
14346 +       u32_t                           tx_timer;
14347 +       u32_t                           tx_bit_pos;
14348 +       u32_t                           tx_byte;
14349 +       u32_t                           tx_fifo_head;
14350 +       u32_t                           tx_fifo_tail;
14351 +       u32_t                           tx_fifo_size;
14352 +
14353 +       /*
14354 +        * FIFOs
14355 +        */
14356 +       u8_t                            rx_fifo[UARTTIO_RX_FIFO_SIZE];
14357 +       u8_t                            tx_fifo[UARTTIO_TX_FIFO_SIZE];
14358 +};
14359 +
14360 +#define UARTTIO_VP_VERSION             1
14361 +struct uarttio_regs {
14362 +       u32_t                           version;
14363 +
14364 +       u32_t                           thread;
14365 +
14366 +       u32_t                           max_uarts;
14367 +
14368 +       struct uarttio_uart             uarts[0];
14369 +};
14370 +
14371 +#define UARTTIO_NODE_VERSION           1
14372 +struct uarttio_node {
14373 +       struct devtree_node             dn;
14374 +
14375 +       u32_t                           version;
14376 +       struct uarttio_regs             *regs;
14377 +       u32_t                           regs_sz;
14378 +};
14379 +
14380 +#endif /* _ASM_UBICOM32_UART_TIO_H */
14381 --- /dev/null
14382 +++ b/arch/ubicom32/include/asm/ubi32-cs4384.h
14383 @@ -0,0 +1,52 @@
14384 +/*
14385 + * arch/ubicom32/include/asm/ubi32-cs4384.h
14386 + *   Ubicom32 architecture CS4384 driver platform data definitions.
14387 + *
14388 + * (C) Copyright 2009, Ubicom, Inc.
14389 + *
14390 + * This file is part of the Ubicom32 Linux Kernel Port.
14391 + *
14392 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14393 + * it and/or modify it under the terms of the GNU General Public License
14394 + * as published by the Free Software Foundation, either version 2 of the
14395 + * License, or (at your option) any later version.
14396 + *
14397 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14398 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14399 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14400 + * the GNU General Public License for more details.
14401 + *
14402 + * You should have received a copy of the GNU General Public License
14403 + * along with the Ubicom32 Linux Kernel Port.  If not,
14404 + * see <http://www.gnu.org/licenses/>.
14405 + */
14406 +#ifndef _ASM_UBICOM32_UBI32_CS4384_H
14407 +#define _ASM_UBICOM32_UBI32_CS4384_H
14408 +
14409 +enum ubi32_cs4384_mclk_source {
14410 +       UBI32_CS4384_MCLK_PWM_0,
14411 +       UBI32_CS4384_MCLK_PWM_1,
14412 +       UBI32_CS4384_MCLK_PWM_2,
14413 +       UBI32_CS4384_MCLK_CLKDIV_1,
14414 +       UBI32_CS4384_MCLK_OTHER,
14415 +};
14416 +
14417 +struct ubi32_cs4384_mclk_entry {
14418 +       /*
14419 +        * Rate, in Hz, of this entry
14420 +        */
14421 +       int rate;
14422 +
14423 +       /*
14424 +        * The divider to program to get the rate
14425 +        */
14426 +       int div;
14427 +};
14428 +
14429 +struct ubi32_cs4384_platform_data {
14430 +       enum ubi32_cs4384_mclk_source   mclk_src;
14431 +
14432 +       int                             n_mclk;
14433 +       struct ubi32_cs4384_mclk_entry  *mclk_entries;
14434 +};
14435 +#endif /* _ASM_UBICOM32_UBI32_CS4384_H */
14436 --- /dev/null
14437 +++ b/arch/ubicom32/include/asm/ubi32-pcm.h
14438 @@ -0,0 +1,54 @@
14439 +/*
14440 + * arch/ubicom32/include/asm/ubi32-pcm.h
14441 + *   Ubicom32 architecture PCM driver platform data definitions.
14442 + *
14443 + * (C) Copyright 2009, Ubicom, Inc.
14444 + *
14445 + * This file is part of the Ubicom32 Linux Kernel Port.
14446 + *
14447 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14448 + * it and/or modify it under the terms of the GNU General Public License
14449 + * as published by the Free Software Foundation, either version 2 of the
14450 + * License, or (at your option) any later version.
14451 + *
14452 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14453 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14454 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14455 + * the GNU General Public License for more details.
14456 + *
14457 + * You should have received a copy of the GNU General Public License
14458 + * along with the Ubicom32 Linux Kernel Port.  If not,
14459 + * see <http://www.gnu.org/licenses/>.
14460 + */
14461 +#ifndef _ASM_UBICOM32_UBI32_PCM_H
14462 +#define _ASM_UBICOM32_UBI32_PCM_H
14463 +
14464 +/*
14465 + * This function is called when the sample rate has changed
14466 + */
14467 +typedef int (*ubi32_pcm_set_rate_fn_t)(void *appdata, int rate);
14468 +
14469 +struct ubi32pcm_platform_data {
14470 +       /*
14471 +        * Name of the audio node/inst
14472 +        */
14473 +       const char              *node_name;
14474 +       const char              *inst_name;
14475 +       int                     inst_num;
14476 +
14477 +       /*
14478 +        * Application specific data provided when calling functions
14479 +        */
14480 +       void                    *appdata;
14481 +
14482 +       /*
14483 +        * Functions called when various things happen
14484 +        */
14485 +       ubi32_pcm_set_rate_fn_t set_rate;
14486 +
14487 +       /*
14488 +        * Pointer to optional upper layer data (i.e. DAC config, etc)
14489 +        */
14490 +       void                    *priv_data;
14491 +};
14492 +#endif /* _ASM_UBICOM32_UBI32_PCM_H */
14493 --- /dev/null
14494 +++ b/arch/ubicom32/include/asm/ubicom32bl.h
14495 @@ -0,0 +1,84 @@
14496 +/*
14497 + * arch/ubicom32/include/asm/ubicom32bl.h
14498 + *   Ubicom32 architecture backlight driver platform data definitions.
14499 + *
14500 + * (C) Copyright 2009, Ubicom, Inc.
14501 + *
14502 + * This file is part of the Ubicom32 Linux Kernel Port.
14503 + *
14504 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14505 + * it and/or modify it under the terms of the GNU General Public License
14506 + * as published by the Free Software Foundation, either version 2 of the
14507 + * License, or (at your option) any later version.
14508 + *
14509 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14510 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14511 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14512 + * the GNU General Public License for more details.
14513 + *
14514 + * You should have received a copy of the GNU General Public License
14515 + * along with the Ubicom32 Linux Kernel Port.  If not,
14516 + * see <http://www.gnu.org/licenses/>.
14517 + *
14518 + * Ubicom32 implementation derived from (with many thanks):
14519 + *   arch/m68knommu
14520 + *   arch/blackfin
14521 + *   arch/parisc
14522 + */
14523 +#ifndef _ASM_UBICOM32_UBICOM32_BL_H
14524 +#define _ASM_UBICOM32_UBICOM32_BL_H
14525 +
14526 +/*
14527 + * Different backlight control mechanisms
14528 + */
14529 +enum ubicom32bl_pwm_types {
14530 +       /*
14531 +        * PWM controlled backlight
14532 +        */
14533 +       UBICOM32BL_TYPE_PWM,
14534 +
14535 +       /*
14536 +        * HRT based PWM backlight
14537 +        */
14538 +       UBICOM32BL_TYPE_PWM_HRT,
14539 +
14540 +       /*
14541 +        * No dimming, just on or off
14542 +        */
14543 +       UBICOM32BL_TYPE_BINARY,
14544 +};
14545 +
14546 +struct ubicom32bl_platform_data {
14547 +       /*
14548 +        * Default intensity of the backlight 0-255
14549 +        */
14550 +       u8_t                            default_intensity;
14551 +
14552 +       /*
14553 +        * TRUE if the backlight sense is active low. (inverted)
14554 +        * FALSE if the backlight sense is active high.
14555 +        */
14556 +       bool                            invert;
14557 +
14558 +       /*
14559 +        * Type of the backlight
14560 +        */
14561 +       enum ubicom32bl_pwm_types       type;
14562 +
14563 +       /*
14564 +        * GPIO of the backlight if UBICOM32BL_TYPE_PWM_HRT, UBICOM32BL_TYPE_BINARY
14565 +        */
14566 +       unsigned                        gpio;
14567 +
14568 +       /*
14569 +        * PWM channel and parameters of the backlight if UBICOM32BL_TYPE_PWM
14570 +        *      pre_scaler: sets the rate at which the PWM timer is clocked. (clk_core / 2^pre_scaler)
14571 +        *      period: sets the period of the timer in timer cycles
14572 +        * The duty cycle will be directly proportional to the brightness setting.
14573 +        */
14574 +       u32_t                           pwm_channel;
14575 +       u8_t                            pwm_prescale;
14576 +       u16_t                           pwm_period;
14577 +};
14578 +
14579 +#endif /* _ASM_UBICOM32_UBICOM32_BL_H */
14580 --- /dev/null
14581 +++ b/arch/ubicom32/include/asm/ubicom32-common-asm.h
14582 @@ -0,0 +1,49 @@
14583 +/*
14584 + * arch/ubicom32/include/asm/ubicom32-common-asm.h
14585 + *   Ubicom32 atomic lock operations.
14586 + *
14587 + * (C) Copyright 2009, Ubicom, Inc.
14588 + *
14589 + * This file is part of the Ubicom32 Linux Kernel Port.
14590 + *
14591 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14592 + * it and/or modify it under the terms of the GNU General Public License
14593 + * as published by the Free Software Foundation, either version 2 of the
14594 + * License, or (at your option) any later version.
14595 + *
14596 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14597 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14598 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14599 + * the GNU General Public License for more details.
14600 + *
14601 + * You should have received a copy of the GNU General Public License
14602 + * along with the Ubicom32 Linux Kernel Port.  If not,
14603 + * see <http://www.gnu.org/licenses/>.
14604 + *
14605 + * Ubicom32 implementation derived from (with many thanks):
14606 + *   arch/m68knommu
14607 + *   arch/blackfin
14608 + *   arch/parisc
14609 + */
14610 +
14611 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14612 +#define _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14613 +
14614 +/*
14615 + * atomic_lock_acquire macro
14616 + *     Equivalent to __atomic_lock_acquire()
14617 + */
14618 +.macro atomic_lock_acquire
14619 +       bset scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14620 +       jmpne.f .-4
14621 +.endm
14622 +
14623 +/*
14624 + * atomic_lock_release macro
14625 + *     Equivalent to __atomic_lock_release()
14626 + */
14627 +.macro atomic_lock_release
14628 +       bclr scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14629 +.endm
14630 +
14631 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_ASM_H */
14632 --- /dev/null
14633 +++ b/arch/ubicom32/include/asm/ubicom32-common.h
14634 @@ -0,0 +1,128 @@
14635 +/*
14636 + * arch/ubicom32/include/asm/ubicom32-common.h
14637 + *   Ubicom32 atomic lock operations.
14638 + *
14639 + * (C) Copyright 2009, Ubicom, Inc.
14640 + *
14641 + * This file is part of the Ubicom32 Linux Kernel Port.
14642 + *
14643 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14644 + * it and/or modify it under the terms of the GNU General Public License
14645 + * as published by the Free Software Foundation, either version 2 of the
14646 + * License, or (at your option) any later version.
14647 + *
14648 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14649 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14650 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14651 + * the GNU General Public License for more details.
14652 + *
14653 + * You should have received a copy of the GNU General Public License
14654 + * along with the Ubicom32 Linux Kernel Port.  If not,
14655 + * see <http://www.gnu.org/licenses/>.
14656 + *
14657 + * Ubicom32 implementation derived from (with many thanks):
14658 + *   arch/m68knommu
14659 + *   arch/blackfin
14660 + *   arch/parisc
14661 + */
14662 +
14663 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_H
14664 +#define _ASM_UBICOM32_UBICOM32_COMMON_H
14665 +
14666 +#define S(arg) #arg
14667 +#define D(arg) S(arg)
14668 +/*
14669 + * scratchpad1 is owned by the LDSR.
14670 + *
14671 + * The upper bits provide 16 global spinlocks.  Acquiring one of these
14672 + * global spinlocks synchornizes across multiple threads and prevents
14673 + * the LDSR from delivering any interrupts while the lock is held.
14674 + * Use these locks only when absolutely required.
14675 + *
14676 + * The lower 16 bits of scratchpad1 are used as per thread interrupt
14677 + * enable/disable bits.  These bits will prevent a thread from receiving
14678 + * any interrupts.
14679 + *
14680 + * Bit Usage:
14681 + * - MT_EN_LOCK_BIT   - Protects writes to MT_EN, so code can read current value
14682 + *                     then write a new value atomically (profiler for example)
14683 + * - ATOMIC_LOCK_BIT - Used to provide general purpose atomic handling.
14684 + * - LDSR_LOCK_BIT   - Used by the LDSR exclusively to provide protection.
14685 + * - DCCR_LOCK_BIT   - Used to limit access to the DCCR cache control peripheral
14686 + * - ICCR_LOCK_BIT   - Used to limit access to the ICCR cache control peripheral
14687 + * - LSB 16 bits     - Used by the LDSR to represent thread enable/disable bits.
14688 + */
14689 +#define MT_EN_LOCK_BIT 31
14690 +#define ATOMIC_LOCK_BIT 30
14691 +#define LDSR_LOCK_BIT   29
14692 +#define PCI_LOCK_BIT   28
14693 +#define ICCR_LOCK_BIT  27
14694 +#define DCCR_LOCK_BIT  26
14695 +
14696 +#if !defined(__ASSEMBLY__)
14697 +
14698 +#define UBICOM32_TRYLOCK(bit) \
14699 +       asm volatile (                                                \
14700 +       "       move.4 %0, #0                                   \n\t" \
14701 +       "       bset scratchpad1, scratchpad1, #"D(bit)"        \n\t" \
14702 +       "       jmpne.f 1f                                      \n\t" \
14703 +       "       move.4 %0, #1                                   \n\t" \
14704 +       "1:                                                     \n\t" \
14705 +               : "=r" (ret)                                          \
14706 +               :                                                     \
14707 +               : "cc", "memory"                                      \
14708 +       )                                                             \
14709 +
14710 +#define UBICOM32_UNLOCK(bit) \
14711 +       asm volatile (                                                \
14712 +       "       bclr scratchpad1, scratchpad1, #"D(bit)"        \n\t" \
14713 +               :                                                     \
14714 +               :                                                     \
14715 +               : "cc", "memory"                                      \
14716 +       )                                                             \
14717 +
14718 +#define UBICOM32_LOCK(bit) \
14719 +       asm volatile (                                                \
14720 +       "1:     bset scratchpad1, scratchpad1, #"D(bit)"        \n\t" \
14721 +       "       jmpne.f 1b                                      \n\t" \
14722 +               :                                                     \
14723 +               :                                                     \
14724 +               : "cc", "memory"                                      \
14725 +       )                                                             \
14726 +
14727 +/*
14728 + * __atomic_lock_trylock()
14729 + *     Attempt to acquire the lock, return TRUE if acquired.
14730 + */
14731 +static inline int __atomic_lock_trylock(void)
14732 +{
14733 +       int ret;
14734 +       UBICOM32_TRYLOCK(ATOMIC_LOCK_BIT);
14735 +       return ret;
14736 +}
14737 +
14738 +/*
14739 + * __atomic_lock_release()
14740 + *     Release the global atomic lock.
14741 + *
14742 + * Note: no one is suspended waiting since this lock is a spinning lock.
14743 + */
14744 +static inline void __atomic_lock_release(void)
14745 +{
14746 +       UBICOM32_UNLOCK(ATOMIC_LOCK_BIT);
14747 +}
14748 +
14749 +/*
14750 + * __atomic_lock_acquire()
14751 + *     Acquire the global atomic lock, spin if not available.
14752 + */
14753 +static inline void __atomic_lock_acquire(void)
14754 +{
14755 +       UBICOM32_LOCK(ATOMIC_LOCK_BIT);
14756 +}
14757 +#else /* __ASSEMBLY__ */
14758 +
14759 +#include <asm/ubicom32-common-asm.h>
14760 +
14761 +#endif /* __ASSEMBLY__ */
14762 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_H */
14763 --- /dev/null
14764 +++ b/arch/ubicom32/include/asm/ubicom32fb.h
14765 @@ -0,0 +1,56 @@
14766 +/*
14767 + * arch/ubicom32/include/asm/ubicom32fb.h
14768 + *   Ubicom32 architecture video frame buffer definitions.
14769 + *
14770 + * (C) Copyright 2009, Ubicom, Inc.
14771 + *
14772 + * This file is part of the Ubicom32 Linux Kernel Port.
14773 + *
14774 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14775 + * it and/or modify it under the terms of the GNU General Public License
14776 + * as published by the Free Software Foundation, either version 2 of the
14777 + * License, or (at your option) any later version.
14778 + *
14779 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14780 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14781 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14782 + * the GNU General Public License for more details.
14783 + *
14784 + * You should have received a copy of the GNU General Public License
14785 + * along with the Ubicom32 Linux Kernel Port.  If not,
14786 + * see <http://www.gnu.org/licenses/>.
14787 + */
14788 +#ifndef _ASM_UBICOM32_UBICOM32FB_H
14789 +#define _ASM_UBICOM32_UBICOM32FB_H
14790 +
14791 +#include <linux/ioctl.h>
14792 +
14793 +/*
14794 + * Set next frame
14795 + */
14796 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME                _IOW('r',  1, void *)
14797 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC   _IOW('r',  2, void *)
14798 +
14799 +/*
14800 + * Set Mode
14801 + */
14802 +#define UBICOM32FB_IOCTL_SET_MODE              _IOW('r',  3, void *)
14803 +struct ubicom32fb_mode {
14804 +       unsigned long   width;
14805 +       unsigned long   height;
14806 +       unsigned long   flags;
14807 +       void            *next_frame;
14808 +};
14809 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER  (1 << 8)
14810 +
14811 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER (1 << 7)
14812 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV             (1 << 6)
14813 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB            (1 << 5)
14814 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255   (1 << 4)
14815 +
14816 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255    (1 << 3)
14817 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1                (1 << 2)
14818 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1                (1 << 1)
14819 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE    (1 << 0)
14820 +
14821 +#endif /* _ASM_UBICOM32_UBICOM32FB_H */
14822 --- /dev/null
14823 +++ b/arch/ubicom32/include/asm/ubicom32hid.h
14824 @@ -0,0 +1,133 @@
14825 +/*
14826 + * arch/ubicom32/include/asm/ubicom32hid.h
14827 + *   Ubicom32 architecture HID driver platform data definitions.
14828 + *
14829 + * (C) Copyright 2009, Ubicom, Inc.
14830 + *
14831 + * This file is part of the Ubicom32 Linux Kernel Port.
14832 + *
14833 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14834 + * it and/or modify it under the terms of the GNU General Public License
14835 + * as published by the Free Software Foundation, either version 2 of the
14836 + * License, or (at your option) any later version.
14837 + *
14838 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14839 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14840 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14841 + * the GNU General Public License for more details.
14842 + *
14843 + * You should have received a copy of the GNU General Public License
14844 + * along with the Ubicom32 Linux Kernel Port.  If not,
14845 + * see <http://www.gnu.org/licenses/>.
14846 + *
14847 + * Ubicom32 implementation derived from (with many thanks):
14848 + *   arch/m68knommu
14849 + *   arch/blackfin
14850 + *   arch/parisc
14851 + */
14852 +#ifndef _ASM_UBICOM32_UBICOM32_HID_H
14853 +#define _ASM_UBICOM32_UBICOM32_HID_H
14854 +
14855 +enum ubicom32hid_bl_types {
14856 +       /*
14857 +        * On or off, using command SET_BL_EN, PB4
14858 +        */
14859 +       UBICOM32HID_BL_TYPE_BINARY,
14860 +
14861 +       /*
14862 +        * Dimmable, using command SET_PWM, PB3
14863 +        */
14864 +       UBICOM32HID_BL_TYPE_PWM,
14865 +};
14866 +
14867 +/*
14868 + * IR code mapping to event code.
14869 + *     If there are no button mappings and no ir mappings
14870 + *     then no input driver will be registered.
14871 + */
14872 +struct ubicom32hid_ir {
14873 +       /*
14874 +        * Input event code (KEY_*, SW_*, etc)
14875 +        */
14876 +       int             code;
14877 +
14878 +       /*
14879 +        * Input event type (EV_KEY, EV_SW, etc)
14880 +        */
14881 +       int             type;
14882 +
14883 +       /*
14884 +        * The IR code of this button.
14885 +        */
14886 +       uint32_t        ir_code;
14887 +};
14888 +
14889 +/*
14890 + * Button mapping to event code.
14891 + *     If there are no button mappings and no ir mappings
14892 + *     then no input driver will be registered.
14893 + */
14894 +struct ubicom32hid_button {
14895 +       /*
14896 +        * Input event code (KEY_*, SW_*, etc)
14897 +        */
14898 +       int             code;
14899 +
14900 +       /*
14901 +        * Input event type (EV_KEY, EV_SW, etc)
14902 +        */
14903 +       int             type;
14904 +
14905 +       /*
14906 +        * Bit number of this button.
14907 +        */
14908 +       uint8_t         bit;
14909 +};
14910 +
14911 +struct ubicom32hid_platform_data {
14912 +       /*
14913 +        * Default intensity of the backlight 0-255
14914 +        */
14915 +       u8_t                            default_intensity;
14916 +
14917 +       /*
14918 +        * GPIO number of the reset line and its polarity.
14919 +        */
14920 +       unsigned                        gpio_reset;
14921 +       int                             gpio_reset_polarity;
14922 +
14923 +       /*
14924 +        * TRUE if the backlight sense is active low. (inverted)
14925 +        * FALSE if the backlight sense is active high.
14926 +        */
14927 +       bool                            invert;
14928 +
14929 +       /*
14930 +        * Type of the backlight we are controlling
14931 +        */
14932 +       enum ubicom32hid_bl_types       type;
14933 +
14934 +       /*
14935 +        * Optional polling rate for input, in ms, defaults to 100ms
14936 +        */
14937 +       int                             poll_interval;
14938 +
14939 +       /*
14940 +        * Optional name to register as input device
14941 +        */
14942 +       const char                      *input_name;
14943 +
14944 +       /*
14945 +        * Button mapping array
14946 +        */
14947 +       const struct ubicom32hid_button *buttons;
14948 +       int                             nbuttons;
14949 +
14950 +       /*
14951 +        * IR mapping array
14952 +        */
14953 +       const struct ubicom32hid_ir     *ircodes;
14954 +       int                             nircodes;
14955 +};
14956 +
14957 +#endif /* _ASM_UBICOM32_UBICOM32_HID_H */
14958 --- /dev/null
14959 +++ b/arch/ubicom32/include/asm/ubicom32input.h
14960 @@ -0,0 +1,76 @@
14961 +/*
14962 + * arch/ubicom32/include/asm/ubicom32input.h
14963 + *   Ubicom32 Input driver, based on gpio-keys
14964 + *
14965 + * (C) Copyright 2009, Ubicom, Inc.
14966 + *
14967 + * This file is part of the Ubicom32 Linux Kernel Port.
14968 + *
14969 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14970 + * it and/or modify it under the terms of the GNU General Public License
14971 + * as published by the Free Software Foundation, either version 2 of the
14972 + * License, or (at your option) any later version.
14973 + *
14974 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14975 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14976 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14977 + * the GNU General Public License for more details.
14978 + *
14979 + * You should have received a copy of the GNU General Public License
14980 + * along with the Ubicom32 Linux Kernel Port.  If not,
14981 + * see <http://www.gnu.org/licenses/>.
14982 + *
14983 + * Ubicom32 implementation derived from (with many thanks):
14984 + *   arch/m68knommu
14985 + *   arch/blackfin
14986 + *   arch/parisc
14987 + *
14988 + * TODO: add groups for inputs which can be sampled together
14989 + */
14990 +
14991 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_H
14992 +#define _ASM_UBICOM32_UBICOM32_INPUT_H
14993 +
14994 +struct ubicom32input_button {
14995 +       /*
14996 +        * Input event code (KEY_*, SW_*, etc)
14997 +        */
14998 +       int             code;
14999 +
15000 +       /*
15001 +        * Input event type (EV_KEY, EV_SW, etc)
15002 +        */
15003 +       int             type;
15004 +
15005 +       /*
15006 +        * GPIO to poll
15007 +        */
15008 +       int             gpio;
15009 +
15010 +       /*
15011 +        * 1 for active low, 0 for active high
15012 +        */
15013 +       int             active_low;
15014 +
15015 +       /*
15016 +        * Description, used for reserving GPIOs
15017 +        */
15018 +       const char      *desc;
15019 +};
15020 +
15021 +struct ubicom32input_platform_data {
15022 +       struct ubicom32input_button     *buttons;
15023 +       int                             nbuttons;
15024 +
15025 +       /*
15026 +        * Optional poll interval, in ms, defaults to 50ms
15027 +        */
15028 +       int                             poll_interval;
15029 +
15030 +       /*
15031 +        * Option Name of this driver
15032 +        */
15033 +       const char                      *name;
15034 +};
15035 +
15036 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_H */
15037 --- /dev/null
15038 +++ b/arch/ubicom32/include/asm/ubicom32input_i2c.h
15039 @@ -0,0 +1,71 @@
15040 +/*
15041 + * arch/ubicom32/include/asm/ubicom32input_i2c.h
15042 + *   Ubicom32 architecture Input driver over I2C platform data definitions.
15043 + *
15044 + * (C) Copyright 2009, Ubicom, Inc.
15045 + *
15046 + * This file is part of the Ubicom32 Linux Kernel Port.
15047 + *
15048 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15049 + * it and/or modify it under the terms of the GNU General Public License
15050 + * as published by the Free Software Foundation, either version 2 of the
15051 + * License, or (at your option) any later version.
15052 + *
15053 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15054 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15055 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15056 + * the GNU General Public License for more details.
15057 + *
15058 + * You should have received a copy of the GNU General Public License
15059 + * along with the Ubicom32 Linux Kernel Port.  If not,
15060 + * see <http://www.gnu.org/licenses/>.
15061 + *
15062 + * Ubicom32 implementation derived from (with many thanks):
15063 + *   arch/m68knommu
15064 + *   arch/blackfin
15065 + *   arch/parisc
15066 + *
15067 + * TODO: add groups for inputs which can be sampled together
15068 + */
15069 +
15070 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15071 +#define _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15072 +
15073 +struct ubicom32input_i2c_button {
15074 +       /*
15075 +        * Input event code (KEY_*, SW_*, etc)
15076 +        */
15077 +       int             code;
15078 +
15079 +       /*
15080 +        * Input event type (EV_KEY, EV_SW, etc)
15081 +        */
15082 +       int             type;
15083 +
15084 +       /*
15085 +        * Bit number of this button. (0 - ngpio)
15086 +        */
15087 +       int             bit;
15088 +
15089 +       /*
15090 +        * 1 for active low, 0 for active high
15091 +        */
15092 +       int             active_low;
15093 +};
15094 +
15095 +struct ubicom32input_i2c_platform_data {
15096 +       struct ubicom32input_i2c_button *buttons;
15097 +       int                             nbuttons;
15098 +
15099 +       /*
15100 +        * Optional poll interval, in ms, defaults to 100ms
15101 +        */
15102 +       int                             poll_interval;
15103 +
15104 +       /*
15105 +        * Option Name of this driver
15106 +        */
15107 +       const char                      *name;
15108 +};
15109 +
15110 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_I2C_H */
15111 --- /dev/null
15112 +++ b/arch/ubicom32/include/asm/ubicom32lcd.h
15113 @@ -0,0 +1,38 @@
15114 +/*
15115 + * arch/ubicom32/include/asm/ubicom32lcd.h
15116 + *   Ubicom32 architecture LCD driver platform data definitions.
15117 + *
15118 + * (C) Copyright 2009, Ubicom, Inc.
15119 + *
15120 + * This file is part of the Ubicom32 Linux Kernel Port.
15121 + *
15122 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15123 + * it and/or modify it under the terms of the GNU General Public License
15124 + * as published by the Free Software Foundation, either version 2 of the
15125 + * License, or (at your option) any later version.
15126 + *
15127 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15128 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15129 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15130 + * the GNU General Public License for more details.
15131 + *
15132 + * You should have received a copy of the GNU General Public License
15133 + * along with the Ubicom32 Linux Kernel Port.  If not,
15134 + * see <http://www.gnu.org/licenses/>.
15135 + */
15136 +#ifndef _ASM_UBICOM32_UBICOM32_LCD_H
15137 +#define _ASM_UBICOM32_UBICOM32_LCD_H
15138 +
15139 +#include <asm/ip5000.h>
15140 +
15141 +struct ubicom32lcd_platform_data {
15142 +       int                     pin_cs;
15143 +       int                     pin_rs;
15144 +       int                     pin_rd;
15145 +       int                     pin_wr;
15146 +       int                     pin_reset;
15147 +       int                     data_shift;
15148 +       struct ubicom32_io_port *port_data;
15149 +};
15150 +
15151 +#endif /* _ASM_UBICOM32_UBICOM32_LCD_H */
15152 --- /dev/null
15153 +++ b/arch/ubicom32/include/asm/ubicom32lcdpower.h
15154 @@ -0,0 +1,39 @@
15155 +/*
15156 + * arch/ubicom32/include/asm/ubicom32lcdpower.h
15157 + *   Ubicom32 architecture LCD driver platform data definitions.
15158 + *
15159 + * (C) Copyright 2009, Ubicom, Inc.
15160 + *
15161 + * This file is part of the Ubicom32 Linux Kernel Port.
15162 + *
15163 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15164 + * it and/or modify it under the terms of the GNU General Public License
15165 + * as published by the Free Software Foundation, either version 2 of the
15166 + * License, or (at your option) any later version.
15167 + *
15168 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15169 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15170 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15171 + * the GNU General Public License for more details.
15172 + *
15173 + * You should have received a copy of the GNU General Public License
15174 + * along with the Ubicom32 Linux Kernel Port.  If not,
15175 + * see <http://www.gnu.org/licenses/>.
15176 + *
15177 + * Ubicom32 implementation derived from (with many thanks):
15178 + *   arch/m68knommu
15179 + *   arch/blackfin
15180 + *   arch/parisc
15181 + */
15182 +#ifndef _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15183 +#define _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15184 +
15185 +struct ubicom32lcdpower_platform_data {
15186 +       /*
15187 +        * GPIO and polarity for VGH signal.  A FALSE polarity is active low, TRUE is active high.
15188 +        */
15189 +       int             vgh_gpio;
15190 +       bool            vgh_polarity;
15191 +};
15192 +
15193 +#endif /* _ASM_UBICOM32_UBICOM32_LCDPOWER_H */
15194 --- /dev/null
15195 +++ b/arch/ubicom32/include/asm/ubicom32ring.h
15196 @@ -0,0 +1,103 @@
15197 +/*
15198 + * arch/ubicom32/include/asm/ubicom32ring.h
15199 + * Userspace I/O platform driver for Ubicom32 ring buffers
15200 + *
15201 + * (C) Copyright 2009, Ubicom, Inc.
15202 + *
15203 + * This file is part of the Ubicom32 Linux Kernel Port.
15204 + *
15205 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15206 + * it and/or modify it under the terms of the GNU General Public License
15207 + * as published by the Free Software Foundation, either version 2 of the
15208 + * License, or (at your option) any later version.
15209 + *
15210 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15211 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15212 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15213 + * the GNU General Public License for more details.
15214 + *
15215 + * You should have received a copy of the GNU General Public License
15216 + * along with the Ubicom32 Linux Kernel Port.  If not,
15217 + * see <http://www.gnu.org/licenses/>.
15218 + */
15219 +
15220 +#ifndef _ASM_UBICOM32_UBICOM32RING_H
15221 +#define _ASM_UBICOM32_UBICOM32RING_H
15222 +
15223 +#define UIO_UBICOM32RING_REG_VERSION   2
15224 +
15225 +struct uio_ubicom32ring_desc {
15226 +       volatile unsigned int           head;
15227 +       volatile unsigned int           tail;
15228 +       unsigned int                    entries;
15229 +       volatile unsigned int           ring[0];
15230 +};
15231 +
15232 +struct uio_ubicom32ring_regs {
15233 +       unsigned int                    version;
15234 +
15235 +       /*
15236 +        * Magic type used to identify the ring set.  Each driver will
15237 +        * have a different magic value.
15238 +        */
15239 +       unsigned int                    magic;
15240 +
15241 +       /*
15242 +        * Registers defined by the driver
15243 +        */
15244 +       unsigned int                    regs_size;
15245 +       void                            *regs;
15246 +
15247 +       /*
15248 +        * The locations of the rings
15249 +        *
15250 +        * DO NOT ADD ANYTHING BELOW THIS LINE
15251 +        */
15252 +       unsigned int                    num_rings;
15253 +       struct uio_ubicom32ring_desc    *rings[0];
15254 +};
15255 +
15256 +/*
15257 + * ringtio_ring_flush
15258 + */
15259 +static inline void ringtio_ring_flush(struct uio_ubicom32ring_desc *rd)
15260 +{
15261 +       rd->head = rd->tail = 0;
15262 +}
15263 +
15264 +/*
15265 + * ringtio_ring_get
15266 + */
15267 +static inline int ringtio_ring_get(struct uio_ubicom32ring_desc *rd, void **val)
15268 +{
15269 +       if (rd->head == rd->tail) {
15270 +               return 0;
15271 +       }
15272 +
15273 +       *val = (void *)rd->ring[rd->head++];
15274 +       if (rd->head == rd->entries) {
15275 +               rd->head = 0;
15276 +       }
15277 +       return 1;
15278 +}
15279 +
15280 +/*
15281 + * ringtio_ring_put
15282 + */
15283 +static inline int ringtio_ring_put(struct uio_ubicom32ring_desc *rd, void *val)
15284 +{
15285 +       unsigned int newtail = rd->tail + 1;
15286 +       if (newtail == rd->entries) {
15287 +               newtail = 0;
15288 +       }
15289 +
15290 +       if (newtail == rd->head) {
15291 +               return 0;
15292 +       }
15293 +
15294 +       rd->ring[rd->tail] = (unsigned int)val;
15295 +       rd->tail = newtail;
15296 +       return 1;
15297 +}
15298 +
15299 +#endif /* _ASM_UBICOM32_UBICOM32RING_H */
15300 --- /dev/null
15301 +++ b/arch/ubicom32/include/asm/ubicom32sd.h
15302 @@ -0,0 +1,45 @@
15303 +/*
15304 + * arch/ubicom32/include/asm/ubicom32sd.h
15305 + *   Ubicom32SD public include file
15306 + *
15307 + * (C) Copyright 2009, Ubicom, Inc.
15308 + *
15309 + * This file is part of the Ubicom32 Linux Kernel Port.
15310 + *
15311 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15312 + * it and/or modify it under the terms of the GNU General Public License
15313 + * as published by the Free Software Foundation, either version 2 of the
15314 + * License, or (at your option) any later version.
15315 + *
15316 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15317 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15318 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15319 + * the GNU General Public License for more details.
15320 + *
15321 + * You should have received a copy of the GNU General Public License
15322 + * along with the Ubicom32 Linux Kernel Port.  If not,
15323 + * see <http://www.gnu.org/licenses/>.
15324 + */
15325 +#ifndef _ASM_UBICOM32_UBICOM32_SD_H
15326 +#define _ASM_UBICOM32_UBICOM32_SD_H
15327 +
15328 +struct ubicom32sd_card {
15329 +       /*
15330 +        * GPIOs of PWR, WP and CD lines.
15331 +        * Polarity is 1 for active high and 0 for active low
15332 +        */
15333 +       int                             pin_pwr;
15334 +       bool                            pwr_polarity;
15335 +       int                             pin_wp;
15336 +       bool                            wp_polarity;
15337 +       int                             pin_cd;
15338 +       bool                            cd_polarity;
15339 +};
15340 +
15341 +struct ubicom32sd_platform_data {
15342 +       int                     ncards;
15343 +
15344 +       struct ubicom32sd_card  *cards;
15345 +};
15346 +
15347 +#endif /* _ASM_UBICOM32_UBICOM32_SD_H */
15348 --- /dev/null
15349 +++ b/arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15350 @@ -0,0 +1,62 @@
15351 +/*
15352 + * arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15353 + *   Platform driver data definitions for GPIO based SPI driver.
15354 + *
15355 + * (C) Copyright 2009, Ubicom, Inc.
15356 + *
15357 + * This file is part of the Ubicom32 Linux Kernel Port.
15358 + *
15359 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15360 + * it and/or modify it under the terms of the GNU General Public License
15361 + * as published by the Free Software Foundation, either version 2 of the
15362 + * License, or (at your option) any later version.
15363 + *
15364 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15365 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15366 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15367 + * the GNU General Public License for more details.
15368 + *
15369 + * You should have received a copy of the GNU General Public License
15370 + * along with the Ubicom32 Linux Kernel Port.  If not,
15371 + * see <http://www.gnu.org/licenses/>.
15372 + *
15373 + * Ubicom32 implementation derived from (with many thanks):
15374 + *   arch/m68knommu
15375 + *   arch/blackfin
15376 + *   arch/parisc
15377 + */
15378 +#ifndef _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15379 +#define _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15380 +
15381 +struct ubicom32_spi_gpio_platform_data {
15382 +       /*
15383 +        * GPIO to use for MOSI, MISO, CLK
15384 +        */
15385 +       int     pin_mosi;
15386 +       int     pin_miso;
15387 +       int     pin_clk;
15388 +
15389 +       /*
15390 +        * Default state of CLK line
15391 +        */
15392 +       int     clk_default;
15393 +
15394 +       /*
15395 +        * Number of chip selects on this bus
15396 +        */
15397 +       int     num_chipselect;
15398 +
15399 +       /*
15400 +        * The bus number of this chip
15401 +        */
15402 +       int     bus_num;
15403 +};
15404 +
15405 +struct ubicom32_spi_gpio_controller_data {
15406 +       /*
15407 +        * GPIO to use for chip select
15408 +        */
15409 +       int     pin_cs;
15410 +};
15411 +
15412 +#endif /* _ASM_UBICOM32_UBICOM32_SPI_GPIO_H */
15413 --- /dev/null
15414 +++ b/arch/ubicom32/include/asm/ubicom32suart.h
15415 @@ -0,0 +1,36 @@
15416 +/*
15417 + * arch/ubicom32/include/asm/ubicom32suart.h
15418 + *   <TODO: Replace with short file description>
15419 + *
15420 + * (C) Copyright 2009, Ubicom, Inc.
15421 + *
15422 + * This file is part of the Ubicom32 Linux Kernel Port.
15423 + *
15424 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15425 + * it and/or modify it under the terms of the GNU General Public License
15426 + * as published by the Free Software Foundation, either version 2 of the
15427 + * License, or (at your option) any later version.
15428 + *
15429 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15430 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15431 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15432 + * the GNU General Public License for more details.
15433 + *
15434 + * You should have received a copy of the GNU General Public License
15435 + * along with the Ubicom32 Linux Kernel Port.  If not,
15436 + * see <http://www.gnu.org/licenses/>.
15437 + *
15438 + * Ubicom32 implementation derived from (with many thanks):
15439 + *   arch/m68knommu
15440 + *   arch/blackfin
15441 + *   arch/parisc
15442 + */
15443 +#ifndef _ASM_UBICOM32_UBICOM32_SUART_H
15444 +#define _ASM_UBICOM32_UBICOM32_SUART_H
15445 +
15446 +/*
15447 + * Platform resource id for serdes uart clock parameter
15448 + */
15449 +#define UBICOM32_SUART_IORESOURCE_CLOCK                (1)
15450 +
15451 +#endif /* _ASM_UBICOM32_UBICOM32_SUART_H */
15452 --- /dev/null
15453 +++ b/arch/ubicom32/include/asm/ubicom32-tio.h
15454 @@ -0,0 +1,42 @@
15455 +/*
15456 + * arch/ubicom32/include/asm/ubicom32-tio.h
15457 + *   Threaded I/O interface definitions.
15458 + *
15459 + * (C) Copyright 2009, Ubicom, Inc.
15460 + *
15461 + * This file is part of the Ubicom32 Linux Kernel Port.
15462 + *
15463 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15464 + * it and/or modify it under the terms of the GNU General Public License
15465 + * as published by the Free Software Foundation, either version 2 of the
15466 + * License, or (at your option) any later version.
15467 + *
15468 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15469 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15470 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15471 + * the GNU General Public License for more details.
15472 + *
15473 + * You should have received a copy of the GNU General Public License
15474 + * along with the Ubicom32 Linux Kernel Port.  If not,
15475 + * see <http://www.gnu.org/licenses/>.
15476 + *
15477 + * Ubicom32 implementation derived from (with many thanks):
15478 + *   arch/m68knommu
15479 + *   arch/blackfin
15480 + *   arch/parisc
15481 + */
15482 +#ifndef _ASM_UBICOM32_UBICOM32_TIO_H
15483 +#define _ASM_UBICOM32_UBICOM32_TIO_H
15484 +
15485 +extern u8_t usb_tio_read_u16(u32_t address, u16_t *data);
15486 +extern u8_t usb_tio_read_u8(u32_t address, u8_t *data);
15487 +
15488 +extern u8_t usb_tio_write_u16(u32_t address, u16_t data);
15489 +extern u8_t usb_tio_write_u8(u32_t address, u8_t data);
15490 +
15491 +extern u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes);
15492 +extern u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes);
15493 +extern u8_t usb_tio_write_fifo_sync(u32_t address, u32_t buffer, u32_t bytes);
15494 +extern void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx);
15495 +
15496 +#endif /* _ASM_UBICOM32_UBICOM32_TIO_H */
15497 --- /dev/null
15498 +++ b/arch/ubicom32/include/asm/ucontext.h
15499 @@ -0,0 +1,39 @@
15500 +/*
15501 + * arch/ubicom32/include/asm/ucontext.h
15502 + *   Definition of ucontext structure for Ubicom32 architecture.
15503 + *
15504 + * (C) Copyright 2009, Ubicom, Inc.
15505 + *
15506 + * This file is part of the Ubicom32 Linux Kernel Port.
15507 + *
15508 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15509 + * it and/or modify it under the terms of the GNU General Public License
15510 + * as published by the Free Software Foundation, either version 2 of the
15511 + * License, or (at your option) any later version.
15512 + *
15513 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15514 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15515 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15516 + * the GNU General Public License for more details.
15517 + *
15518 + * You should have received a copy of the GNU General Public License
15519 + * along with the Ubicom32 Linux Kernel Port.  If not,
15520 + * see <http://www.gnu.org/licenses/>.
15521 + *
15522 + * Ubicom32 implementation derived from (with many thanks):
15523 + *   arch/m68knommu
15524 + *   arch/blackfin
15525 + *   arch/parisc
15526 + */
15527 +#ifndef _ASM_UBICOM32_UCONTEXT_H
15528 +#define _ASM_UBICOM32_UCONTEXT_H
15529 +
15530 +struct ucontext {
15531 +       unsigned long     uc_flags;
15532 +       struct ucontext  *uc_link;
15533 +       stack_t           uc_stack;
15534 +       struct sigcontext         uc_mcontext;
15535 +       sigset_t          uc_sigmask;   /* mask last for extensibility */
15536 +};
15537 +
15538 +#endif /* _ASM_UBICOM32_UCONTEXT_H */
15539 --- /dev/null
15540 +++ b/arch/ubicom32/include/asm/unaligned.h
15541 @@ -0,0 +1,44 @@
15542 +/*
15543 + * arch/ubicom32/include/asm/unaligned.h
15544 + *   Ubicom32 architecture unaligned memory access definitions.
15545 + *
15546 + * (C) Copyright 2009, Ubicom, Inc.
15547 + *
15548 + * This file is part of the Ubicom32 Linux Kernel Port.
15549 + *
15550 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15551 + * it and/or modify it under the terms of the GNU General Public License
15552 + * as published by the Free Software Foundation, either version 2 of the
15553 + * License, or (at your option) any later version.
15554 + *
15555 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15556 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15557 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15558 + * the GNU General Public License for more details.
15559 + *
15560 + * You should have received a copy of the GNU General Public License
15561 + * along with the Ubicom32 Linux Kernel Port.  If not,
15562 + * see <http://www.gnu.org/licenses/>.
15563 + *
15564 + * Ubicom32 implementation derived from (with many thanks):
15565 + *   arch/m68knommu
15566 + *   arch/blackfin
15567 + *   arch/parisc
15568 + *
15569 + * TODO: This is a copy of arm unaligned handling that probably needs
15570 + * to be optimized for UBICOM32, but it works for now.
15571 + */
15572 +
15573 +#ifndef _ASM_UBICOM32_UNALIGNED_H
15574 +#define _ASM_UBICOM32_UNALIGNED_H
15575 +
15576 +#include <asm/types.h>
15577 +
15578 +#include <linux/unaligned/le_byteshift.h>
15579 +#include <linux/unaligned/be_byteshift.h>
15580 +#include <linux/unaligned/generic.h>
15581 +
15582 +#define get_unaligned  __get_unaligned_be
15583 +#define put_unaligned  __put_unaligned_be
15584 +
15585 +#endif /* _ASM_UBICOM32_UNALIGNED_H */
15586 --- /dev/null
15587 +++ b/arch/ubicom32/include/asm/unistd.h
15588 @@ -0,0 +1,400 @@
15589 +/*
15590 + * arch/ubicom32/include/asm/unistd.h
15591 + *   Ubicom32 architecture syscall definitions.
15592 + *
15593 + * (C) Copyright 2009, Ubicom, Inc.
15594 + *
15595 + * This file is part of the Ubicom32 Linux Kernel Port.
15596 + *
15597 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15598 + * it and/or modify it under the terms of the GNU General Public License
15599 + * as published by the Free Software Foundation, either version 2 of the
15600 + * License, or (at your option) any later version.
15601 + *
15602 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15603 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15604 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15605 + * the GNU General Public License for more details.
15606 + *
15607 + * You should have received a copy of the GNU General Public License
15608 + * along with the Ubicom32 Linux Kernel Port.  If not,
15609 + * see <http://www.gnu.org/licenses/>.
15610 + *
15611 + * Ubicom32 implementation derived from (with many thanks):
15612 + *   arch/m68knommu
15613 + *   arch/blackfin
15614 + *   arch/parisc
15615 + */
15616 +#ifndef _ASM_UBICOM32_UNISTD_H
15617 +#define _ASM_UBICOM32_UNISTD_H
15618 +
15619 +/*
15620 + * This file contains the system call numbers.
15621 + */
15622 +
15623 +#define __NR_restart_syscall      0
15624 +#define __NR_exit                1
15625 +#define __NR_fork                2
15626 +#define __NR_read                3
15627 +#define __NR_write               4
15628 +#define __NR_open                5
15629 +#define __NR_close               6
15630 +#define __NR_waitpid             7
15631 +#define __NR_creat               8
15632 +#define __NR_link                9
15633 +#define __NR_unlink             10
15634 +#define __NR_execve             11
15635 +#define __NR_chdir              12
15636 +#define __NR_time               13
15637 +#define __NR_mknod              14
15638 +#define __NR_chmod              15
15639 +#define __NR_chown              16
15640 +#define __NR_break              17
15641 +#define __NR_oldstat            18
15642 +#define __NR_lseek              19
15643 +#define __NR_getpid             20
15644 +#define __NR_mount              21
15645 +#define __NR_umount             22
15646 +#define __NR_setuid             23
15647 +#define __NR_getuid             24
15648 +#define __NR_stime              25
15649 +#define __NR_ptrace             26
15650 +#define __NR_alarm              27
15651 +#define __NR_oldfstat           28
15652 +#define __NR_pause              29
15653 +#define __NR_utime              30
15654 +#define __NR_stty               31
15655 +#define __NR_gtty               32
15656 +#define __NR_access             33
15657 +#define __NR_nice               34
15658 +#define __NR_ftime              35
15659 +#define __NR_sync               36
15660 +#define __NR_kill               37
15661 +#define __NR_rename             38
15662 +#define __NR_mkdir              39
15663 +#define __NR_rmdir              40
15664 +#define __NR_dup                41
15665 +#define __NR_pipe               42
15666 +#define __NR_times              43
15667 +#define __NR_prof               44
15668 +#define __NR_brk                45
15669 +#define __NR_setgid             46
15670 +#define __NR_getgid             47
15671 +#define __NR_signal             48
15672 +#define __NR_geteuid            49
15673 +#define __NR_getegid            50
15674 +#define __NR_acct               51
15675 +#define __NR_umount2            52
15676 +#define __NR_lock               53
15677 +#define __NR_ioctl              54
15678 +#define __NR_fcntl              55
15679 +#define __NR_mpx                56
15680 +#define __NR_setpgid            57
15681 +#define __NR_ulimit             58
15682 +#define __NR_oldolduname        59
15683 +#define __NR_umask              60
15684 +#define __NR_chroot             61
15685 +#define __NR_ustat              62
15686 +#define __NR_dup2               63
15687 +#define __NR_getppid            64
15688 +#define __NR_getpgrp            65
15689 +#define __NR_setsid             66
15690 +#define __NR_sigaction          67
15691 +#define __NR_sgetmask           68
15692 +#define __NR_ssetmask           69
15693 +#define __NR_setreuid           70
15694 +#define __NR_setregid           71
15695 +#define __NR_sigsuspend                 72
15696 +#define __NR_sigpending                 73
15697 +#define __NR_sethostname        74
15698 +#define __NR_setrlimit          75
15699 +#define __NR_getrlimit          76
15700 +#define __NR_getrusage          77
15701 +#define __NR_gettimeofday       78
15702 +#define __NR_settimeofday       79
15703 +#define __NR_getgroups          80
15704 +#define __NR_setgroups          81
15705 +#define __NR_select             82
15706 +#define __NR_symlink            83
15707 +#define __NR_oldlstat           84
15708 +#define __NR_readlink           85
15709 +#define __NR_uselib             86
15710 +#define __NR_swapon             87
15711 +#define __NR_reboot             88
15712 +#define __NR_readdir            89
15713 +#define __NR_mmap               90
15714 +#define __NR_munmap             91
15715 +#define __NR_truncate           92
15716 +#define __NR_ftruncate          93
15717 +#define __NR_fchmod             94
15718 +#define __NR_fchown             95
15719 +#define __NR_getpriority        96
15720 +#define __NR_setpriority        97
15721 +#define __NR_profil             98
15722 +#define __NR_statfs             99
15723 +#define __NR_fstatfs           100
15724 +#define __NR_ioperm            101
15725 +#define __NR_socketcall                102
15726 +#define __NR_syslog            103
15727 +#define __NR_setitimer         104
15728 +#define __NR_getitimer         105
15729 +#define __NR_stat              106
15730 +#define __NR_lstat             107
15731 +#define __NR_fstat             108
15732 +#define __NR_olduname          109
15733 +#define __NR_iopl              /* 110 */ not supported
15734 +#define __NR_vhangup           111
15735 +#define __NR_idle              /* 112 */ Obsolete
15736 +#define __NR_vm86              /* 113 */ not supported
15737 +#define __NR_wait4             114
15738 +#define __NR_swapoff           115
15739 +#define __NR_sysinfo           116
15740 +#define __NR_ipc               117
15741 +#define __NR_fsync             118
15742 +#define __NR_sigreturn         119
15743 +#define __NR_clone             120
15744 +#define __NR_setdomainname     121
15745 +#define __NR_uname             122
15746 +#define __NR_cacheflush                123
15747 +#define __NR_adjtimex          124
15748 +#define __NR_mprotect          125
15749 +#define __NR_sigprocmask       126
15750 +#define __NR_create_module     127
15751 +#define __NR_init_module       128
15752 +#define __NR_delete_module     129
15753 +#define __NR_get_kernel_syms   130
15754 +#define __NR_quotactl          131
15755 +#define __NR_getpgid           132
15756 +#define __NR_fchdir            133
15757 +#define __NR_bdflush           134
15758 +#define __NR_sysfs             135
15759 +#define __NR_personality       136
15760 +#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
15761 +#define __NR_setfsuid          138
15762 +#define __NR_setfsgid          139
15763 +#define __NR__llseek           140
15764 +#define __NR_getdents          141
15765 +#define __NR__newselect                142
15766 +#define __NR_flock             143
15767 +#define __NR_msync             144
15768 +#define __NR_readv             145
15769 +#define __NR_writev            146
15770 +#define __NR_getsid            147
15771 +#define __NR_fdatasync         148
15772 +#define __NR__sysctl           149
15773 +#define __NR_mlock             150
15774 +#define __NR_munlock           151
15775 +#define __NR_mlockall          152
15776 +#define __NR_munlockall                153
15777 +#define __NR_sched_setparam            154
15778 +#define __NR_sched_getparam            155
15779 +#define __NR_sched_setscheduler                156
15780 +#define __NR_sched_getscheduler                157
15781 +#define __NR_sched_yield               158
15782 +#define __NR_sched_get_priority_max    159
15783 +#define __NR_sched_get_priority_min    160
15784 +#define __NR_sched_rr_get_interval     161
15785 +#define __NR_nanosleep         162
15786 +#define __NR_mremap            163
15787 +#define __NR_setresuid         164
15788 +#define __NR_getresuid         165
15789 +#define __NR_getpagesize       166
15790 +#define __NR_query_module      167
15791 +#define __NR_poll              168
15792 +#define __NR_nfsservctl                169
15793 +#define __NR_setresgid         170
15794 +#define __NR_getresgid         171
15795 +#define __NR_prctl             172
15796 +#define __NR_rt_sigreturn      173
15797 +#define __NR_rt_sigaction      174
15798 +#define __NR_rt_sigprocmask    175
15799 +#define __NR_rt_sigpending     176
15800 +#define __NR_rt_sigtimedwait   177
15801 +#define __NR_rt_sigqueueinfo   178
15802 +#define __NR_rt_sigsuspend     179
15803 +#define __NR_pread64           180
15804 +#define __NR_pwrite64          181
15805 +#define __NR_lchown            182
15806 +#define __NR_getcwd            183
15807 +#define __NR_capget            184
15808 +#define __NR_capset            185
15809 +#define __NR_sigaltstack       186
15810 +#define __NR_sendfile          187
15811 +#define __NR_getpmsg           188     /* some people actually want streams */
15812 +#define __NR_putpmsg           189     /* some people actually want streams */
15813 +#define __NR_vfork             190
15814 +#define __NR_ugetrlimit                191
15815 +#define __NR_mmap2             192
15816 +#define __NR_truncate64                193
15817 +#define __NR_ftruncate64       194
15818 +#define __NR_stat64            195
15819 +#define __NR_lstat64           196
15820 +#define __NR_fstat64           197
15821 +#define __NR_chown32           198
15822 +#define __NR_getuid32          199
15823 +#define __NR_getgid32          200
15824 +#define __NR_geteuid32         201
15825 +#define __NR_getegid32         202
15826 +#define __NR_setreuid32                203
15827 +#define __NR_setregid32                204
15828 +#define __NR_getgroups32       205
15829 +#define __NR_setgroups32       206
15830 +#define __NR_fchown32          207
15831 +#define __NR_setresuid32       208
15832 +#define __NR_getresuid32       209
15833 +#define __NR_setresgid32       210
15834 +#define __NR_getresgid32       211
15835 +#define __NR_lchown32          212
15836 +#define __NR_setuid32          213
15837 +#define __NR_setgid32          214
15838 +#define __NR_setfsuid32                215
15839 +#define __NR_setfsgid32                216
15840 +#define __NR_pivot_root                217
15841 +#define __NR_getdents64                220
15842 +#define __NR_gettid            221
15843 +#define __NR_tkill             222
15844 +#define __NR_setxattr          223
15845 +#define __NR_lsetxattr         224
15846 +#define __NR_fsetxattr         225
15847 +#define __NR_getxattr          226
15848 +#define __NR_lgetxattr         227
15849 +#define __NR_fgetxattr         228
15850 +#define __NR_listxattr         229
15851 +#define __NR_llistxattr                230
15852 +#define __NR_flistxattr                231
15853 +#define __NR_removexattr       232
15854 +#define __NR_lremovexattr      233
15855 +#define __NR_fremovexattr      234
15856 +#define __NR_futex             235
15857 +#define __NR_sendfile64                236
15858 +#define __NR_mincore           237
15859 +#define __NR_madvise           238
15860 +#define __NR_fcntl64           239
15861 +#define __NR_readahead         240
15862 +#define __NR_io_setup          241
15863 +#define __NR_io_destroy                242
15864 +#define __NR_io_getevents      243
15865 +#define __NR_io_submit         244
15866 +#define __NR_io_cancel         245
15867 +#define __NR_fadvise64         246
15868 +#define __NR_exit_group                247
15869 +#define __NR_lookup_dcookie    248
15870 +#define __NR_epoll_create      249
15871 +#define __NR_epoll_ctl         250
15872 +#define __NR_epoll_wait                251
15873 +#define __NR_remap_file_pages  252
15874 +#define __NR_set_tid_address   253
15875 +#define __NR_timer_create      254
15876 +#define __NR_timer_settime     255
15877 +#define __NR_timer_gettime     256
15878 +#define __NR_timer_getoverrun  257
15879 +#define __NR_timer_delete      258
15880 +#define __NR_clock_settime     259
15881 +#define __NR_clock_gettime     260
15882 +#define __NR_clock_getres      261
15883 +#define __NR_clock_nanosleep   262
15884 +#define __NR_statfs64          263
15885 +#define __NR_fstatfs64         264
15886 +#define __NR_tgkill            265
15887 +#define __NR_utimes            266
15888 +#define __NR_fadvise64_64      267
15889 +#define __NR_mbind             268
15890 +#define __NR_get_mempolicy     269
15891 +#define __NR_set_mempolicy     270
15892 +#define __NR_mq_open           271
15893 +#define __NR_mq_unlink         272
15894 +#define __NR_mq_timedsend      273
15895 +#define __NR_mq_timedreceive   274
15896 +#define __NR_mq_notify         275
15897 +#define __NR_mq_getsetattr     276
15898 +#define __NR_waitid            277
15899 +#define __NR_vserver           278
15900 +#define __NR_add_key           279
15901 +#define __NR_request_key       280
15902 +#define __NR_keyctl            281
15903 +#define __NR_ioprio_set                282
15904 +#define __NR_ioprio_get                283
15905 +#define __NR_inotify_init      284
15906 +#define __NR_inotify_add_watch 285
15907 +#define __NR_inotify_rm_watch  286
15908 +#define __NR_migrate_pages     287
15909 +#define __NR_openat            288
15910 +#define __NR_mkdirat           289
15911 +#define __NR_mknodat           290
15912 +#define __NR_fchownat          291
15913 +#define __NR_futimesat         292
15914 +#define __NR_fstatat64         293
15915 +#define __NR_unlinkat          294
15916 +#define __NR_renameat          295
15917 +#define __NR_linkat            296
15918 +#define __NR_symlinkat         297
15919 +#define __NR_readlinkat                298
15920 +#define __NR_fchmodat          299
15921 +#define __NR_faccessat         300
15922 +#define __NR_pselect6          301
15923 +#define __NR_ppoll             302
15924 +#define __NR_unshare           303
15925 +#define __NR_set_robust_list   304
15926 +#define __NR_get_robust_list   305
15927 +#define __NR_splice            306
15928 +#define __NR_sync_file_range   307
15929 +#define __NR_tee               308
15930 +#define __NR_vmsplice          309
15931 +#define __NR_move_pages                310
15932 +#define __NR_sched_setaffinity 311
15933 +#define __NR_sched_getaffinity 312
15934 +#define __NR_kexec_load                313
15935 +#define __NR_getcpu            314
15936 +#define __NR_epoll_pwait       315
15937 +#define __NR_utimensat         316
15938 +#define __NR_signalfd          317
15939 +#define __NR_timerfd_create    318
15940 +#define __NR_eventfd           319
15941 +#define __NR_fallocate         320
15942 +#define __NR_timerfd_settime   321
15943 +#define __NR_timerfd_gettime   322
15944 +#define __NR_signalfd4         323
15945 +#define __NR_eventfd2          324
15946 +#define __NR_epoll_create1     325
15947 +#define __NR_dup3              326
15948 +#define __NR_pipe2             327
15949 +#define __NR_inotify_init1     328
15950 +
15951 +#ifdef __KERNEL__
15952 +
15953 +#define NR_syscalls            329
15954 +
15955 +#define __ARCH_WANT_IPC_PARSE_VERSION
15956 +#define __ARCH_WANT_OLD_READDIR
15957 +#define __ARCH_WANT_OLD_STAT
15958 +#define __ARCH_WANT_STAT64
15959 +#define __ARCH_WANT_SYS_ALARM
15960 +#define __ARCH_WANT_SYS_GETHOSTNAME
15961 +#define __ARCH_WANT_SYS_PAUSE
15962 +#define __ARCH_WANT_SYS_SGETMASK
15963 +#define __ARCH_WANT_SYS_SIGNAL
15964 +#define __ARCH_WANT_SYS_TIME
15965 +#define __ARCH_WANT_SYS_UTIME
15966 +#define __ARCH_WANT_SYS_WAITPID
15967 +#define __ARCH_WANT_SYS_SOCKETCALL
15968 +#define __ARCH_WANT_SYS_FADVISE64
15969 +#define __ARCH_WANT_SYS_GETPGRP
15970 +#define __ARCH_WANT_SYS_LLSEEK
15971 +#define __ARCH_WANT_SYS_NICE
15972 +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
15973 +#define __ARCH_WANT_SYS_OLDUMOUNT
15974 +#define __ARCH_WANT_SYS_SIGPENDING
15975 +#define __ARCH_WANT_SYS_SIGPROCMASK
15976 +#define __ARCH_WANT_SYS_RT_SIGACTION
15977 +
15978 +/*
15979 + * "Conditional" syscalls
15980 + *
15981 + * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
15982 + * but it doesn't work on all toolchains, so we just do it by hand
15983 + */
15984 +//#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
15985 +#define cond_syscall(x) long x(void)  __attribute__((weak,alias("sys_ni_syscall")))
15986 +#endif /* __KERNEL__ */
15987 +
15988 +#endif /* _ASM_UBICOM32_UNISTD_H */
15989 --- /dev/null
15990 +++ b/arch/ubicom32/include/asm/user.h
15991 @@ -0,0 +1,82 @@
15992 +/*
15993 + * arch/ubicom32/include/asm/user.h
15994 + *   Ubicom32 architecture core file definitions.
15995 + *
15996 + * (C) Copyright 2009, Ubicom, Inc.
15997 + *
15998 + * This file is part of the Ubicom32 Linux Kernel Port.
15999 + *
16000 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16001 + * it and/or modify it under the terms of the GNU General Public License
16002 + * as published by the Free Software Foundation, either version 2 of the
16003 + * License, or (at your option) any later version.
16004 + *
16005 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16006 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16007 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16008 + * the GNU General Public License for more details.
16009 + *
16010 + * You should have received a copy of the GNU General Public License
16011 + * along with the Ubicom32 Linux Kernel Port.  If not,
16012 + * see <http://www.gnu.org/licenses/>.
16013 + *
16014 + * Ubicom32 implementation derived from (with many thanks):
16015 + *   arch/m68knommu
16016 + *   arch/blackfin
16017 + *   arch/parisc
16018 + */
16019 +#ifndef _ASM_UBICOM32_USER_H
16020 +#define _ASM_UBICOM32_USER_H
16021 +
16022 +#include <asm/ptrace.h>
16023 +#include <asm/page.h>
16024 +/*
16025 + * Adapted from <asm-powerpc/user.h>
16026 + *
16027 + * Core file format: The core file is written in such a way that gdb
16028 + * can understand it and provide useful information to the user (under
16029 + * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
16030 + * are as follows:
16031 + *
16032 + *  upage: 1 page consisting of a user struct that tells gdb
16033 + *     what is present in the file.  Directly after this is a
16034 + *     copy of the task_struct, which is currently not used by gdb,
16035 + *     but it may come in handy at some point.  All of the registers
16036 + *     are stored as part of the upage.  The upage should always be
16037 + *     only one page long.
16038 + *  data: The data segment follows next.  We use current->end_text to
16039 + *     current->brk to pick up all of the user variables, plus any memory
16040 + *     that may have been sbrk'ed.  No attempt is made to determine if a
16041 + *     page is demand-zero or if a page is totally unused, we just cover
16042 + *     the entire range.  All of the addresses are rounded in such a way
16043 + *     that an integral number of pages is written.
16044 + *  stack: We need the stack information in order to get a meaningful
16045 + *     backtrace.  We need to write the data from usp to
16046 + *     current->start_stack, so we round each of these in order to be able
16047 + *     to write an integer number of pages.
16048 + */
16049 +
16050 +struct user_ubicom32fp_struct {
16051 +};
16052 +
16053 +struct user {
16054 +       struct pt_regs  regs;                   /* entire machine state */
16055 +       size_t          u_tsize;                /* text size (pages) */
16056 +       size_t          u_dsize;                /* data size (pages) */
16057 +       size_t          u_ssize;                /* stack size (pages) */
16058 +       unsigned long   start_code;             /* text starting address */
16059 +       unsigned long   start_data;             /* data starting address */
16060 +       unsigned long   start_stack;            /* stack starting address */
16061 +       long int        signal;                 /* signal causing core dump */
16062 +       unsigned long   u_ar0;                  /* help gdb find registers */
16063 +       unsigned long   magic;                  /* identifies a core file */
16064 +       char            u_comm[32];             /* user command name */
16065 +};
16066 +
16067 +#define NBPG                   PAGE_SIZE
16068 +#define UPAGES                 1
16069 +#define HOST_TEXT_START_ADDR   (u.start_code)
16070 +#define HOST_DATA_START_ADDR   (u.start_data)
16071 +#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
16072 +
16073 +#endif /* _ASM_UBICOM32_USER_H */
16074 --- /dev/null
16075 +++ b/arch/ubicom32/include/asm/vdc_tio.h
16076 @@ -0,0 +1,129 @@
16077 +/*
16078 + * arch/ubicom32/include/asm/vdc_tio.h
16079 + *   Ubicom32 architecture VDC TIO definitions.
16080 + *
16081 + * (C) Copyright 2009, Ubicom, Inc.
16082 + *
16083 + * This file is part of the Ubicom32 Linux Kernel Port.
16084 + *
16085 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16086 + * it and/or modify it under the terms of the GNU General Public License
16087 + * as published by the Free Software Foundation, either version 2 of the
16088 + * License, or (at your option) any later version.
16089 + *
16090 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16091 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16092 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16093 + * the GNU General Public License for more details.
16094 + *
16095 + * You should have received a copy of the GNU General Public License
16096 + * along with the Ubicom32 Linux Kernel Port.  If not,
16097 + * see <http://www.gnu.org/licenses/>.
16098 + *
16099 + * Ubicom32 implementation derived from (with many thanks):
16100 + *   arch/m68knommu
16101 + *   arch/blackfin
16102 + *   arch/parisc
16103 + */
16104 +#ifndef _ASM_UBICOM32_VDC_TIO_H
16105 +#define _ASM_UBICOM32_VDC_TIO_H
16106 +
16107 +#include <asm/devtree.h>
16108 +
16109 +#define VDCTIO_VP_VERSION                      5
16110 +
16111 +#define VDCTIO_SCALE_FLAG_VSUB                 (1 << 9)
16112 +#define VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER       (1 << 8)
16113 +#define VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER      (1 << 7)
16114 +#define VDCTIO_SCALE_FLAG_YUV                  (1 << 6)
16115 +#define VDCTIO_SCALE_FLAG_VRANGE_16_255                (1 << 5)
16116 +#define VDCTIO_SCALE_FLAG_VRANGE_0_255         (1 << 4)
16117 +#define VDCTIO_SCALE_FLAG_HSUB_2_1             (1 << 3)
16118 +#define VDCTIO_SCALE_FLAG_HSUB_1_1             (1 << 2)
16119 +#define VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER     (1 << 1)
16120 +#define VDCTIO_SCALE_FLAG_ENABLE               (1 << 0)
16121 +
16122 +#define VDCTIO_NEXT_FRAME_FLAG_YUV_BIT         0
16123 +#define VDCTIO_NEXT_FRAME_FLAG_YUV             (1 << (VDCTIO_NEXT_FRAME_FLAG_YUV_BIT))
16124 +
16125 +#define VDCTIO_CAPS_SUPPORTS_SCALING           (1 << 0)
16126 +
16127 +#define VDCTIO_COMMAND_START                   (1 << 3)
16128 +#define VDCTIO_COMMAND_SET_COEFF               (1 << 2)
16129 +#define VDCTIO_COMMAND_SET_LUT                 (1 << 1)
16130 +#define VDCTIO_COMMAND_SET_SCALE_MODE          (1 << 0)
16131 +
16132 +/*
16133 + * Command / Data registers to access the VDC
16134 + */
16135 +struct vdc_tio_vp_regs {
16136 +       /*
16137 +        * Version of this TIO register map
16138 +        */
16139 +       u32_t           version;
16140 +
16141 +       volatile u32_t  command;
16142 +
16143 +       /*
16144 +        * Next frame pointer, when the command VDCTIO_COMMAND_SET_FRAME_BUFFER is set,
16145 +        * the vdc will take the pointer here and display it.
16146 +        */
16147 +       void            *next_frame;
16148 +       u32_t           next_frame_flags;
16149 +
16150 +       /*
16151 +        * These map directly into the PIXP registers 0x20-0x80.
16152 +        * DO NOT change the order of these three variables.
16153 +        */
16154 +       u32_t           red_lut[6];
16155 +       u32_t           blue_lut[6];
16156 +       u32_t           green_lut[13];
16157 +
16158 +       /*
16159 +        * These map directly into the PIXP registers 0x04, 0x08
16160 +        */
16161 +       u32_t           coeff0;
16162 +       u32_t           coeff1;
16163 +
16164 +       /*
16165 +        * There are used to set the scaling parameters
16166 +        */
16167 +       u32_t           x_in;
16168 +       u32_t           x_out;
16169 +       u32_t           y_in;
16170 +       u32_t           y_out;
16171 +       u32_t           scale_flags;
16172 +
16173 +       /*
16174 +        * Current frame number, monotonically increasing number
16175 +        */
16176 +       u32_t           frame_number;
16177 +
16178 +       /*
16179 +        * These variables tell the guest OS what the underlying hardware looks like
16180 +        */
16181 +       u32_t           caps;
16182 +       u32_t           xres;
16183 +       u32_t           yres;
16184 +       u32_t           fb_align;
16185 +       u8_t            bpp;
16186 +       u8_t            rbits;
16187 +       u8_t            gbits;
16188 +       u8_t            bbits;
16189 +       u8_t            rshift;
16190 +       u8_t            gshift;
16191 +       u8_t            bshift;
16192 +};
16193 +
16194 +/*
16195 + * Devtree node for VDC
16196 + */
16197 +struct vdc_tio_node {
16198 +       struct devtree_node     dn;
16199 +
16200 +       struct vdc_tio_vp_regs  *regs;
16201 +};
16202 +
16203 +extern void vdc_tio_init(void);
16204 +
16205 +#endif /* _ASM_UBICOM32_VDC_TIO_H */
16206 --- /dev/null
16207 +++ b/arch/ubicom32/include/asm/vga.h
16208 @@ -0,0 +1,71 @@
16209 +/*
16210 + * arch/ubicom32/include/asm/vga.h
16211 + *   Ubicom32 low level  VGA/frame buffer definitions.
16212 + *
16213 + * (C) Copyright 2009, Ubicom, Inc.
16214 + * (c) 1998 Martin Mares <mj@ucw.cz>
16215 + *
16216 + * This file is part of the Ubicom32 Linux Kernel Port.
16217 + *
16218 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16219 + * it and/or modify it under the terms of the GNU General Public License
16220 + * as published by the Free Software Foundation, either version 2 of the
16221 + * License, or (at your option) any later version.
16222 + *
16223 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16224 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16225 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16226 + * the GNU General Public License for more details.
16227 + *
16228 + * You should have received a copy of the GNU General Public License
16229 + * along with the Ubicom32 Linux Kernel Port.  If not,
16230 + * see <http://www.gnu.org/licenses/>.
16231 + *
16232 + * Ubicom32 implementation derived from (with many thanks):
16233 + *   arch/m68knommu
16234 + *   arch/blackfin
16235 + *   arch/parisc
16236 + */
16237 +
16238 +#ifndef _ASM_UBICOM32_VGA_H
16239 +#define _ASM_UBICOM32_VGA_H
16240 +
16241 +#include <asm/byteorder.h>
16242 +
16243 +/*
16244 + *     On the PC, we can just recalculate addresses and then
16245 + *     access the videoram directly without any black magic.
16246 + */
16247 +
16248 +#define VGA_MAP_MEM(x, s)      (0xb0000000L + (unsigned long)(x))
16249 +
16250 +#define vga_readb(x)   (*(x))
16251 +#define vga_writeb(x, y)       (*(y) = (x))
16252 +
16253 +#define VT_BUF_HAVE_RW
16254 +/*
16255 + *  These are only needed for supporting VGA or MDA text mode, which use little
16256 + *  endian byte ordering.
16257 + *  In other cases, we can optimize by using native byte ordering and
16258 + *  <linux/vt_buffer.h> has already done the right job for us.
16259 + */
16260 +
16261 +#undef scr_writew
16262 +#undef scr_readw
16263 +
16264 +static inline void scr_writew(u16 val, volatile u16 *addr)
16265 +{
16266 +       *addr = cpu_to_le16(val);
16267 +}
16268 +
16269 +static inline u16 scr_readw(volatile const u16 *addr)
16270 +{
16271 +       return le16_to_cpu(*addr);
16272 +}
16273 +
16274 +#define scr_memcpyw(d, s, c) memcpy(d, s, c)
16275 +#define scr_memmovew(d, s, c) memmove(d, s, c)
16276 +#define VT_BUF_HAVE_MEMCPYW
16277 +#define VT_BUF_HAVE_MEMMOVEW
16278 +
16279 +#endif /* _ASM_UBICOM32_VGA_H */
16280 --- /dev/null
16281 +++ b/arch/ubicom32/include/asm/xor.h
16282 @@ -0,0 +1,33 @@
16283 +/*
16284 + * arch/ubicom32/include/asm/xor.h
16285 + *   Generic xor.h definitions for Ubicom32 architecture.
16286 + *
16287 + * (C) Copyright 2009, Ubicom, Inc.
16288 + *
16289 + * This file is part of the Ubicom32 Linux Kernel Port.
16290 + *
16291 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16292 + * it and/or modify it under the terms of the GNU General Public License
16293 + * as published by the Free Software Foundation, either version 2 of the
16294 + * License, or (at your option) any later version.
16295 + *
16296 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16297 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16298 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16299 + * the GNU General Public License for more details.
16300 + *
16301 + * You should have received a copy of the GNU General Public License
16302 + * along with the Ubicom32 Linux Kernel Port.  If not,
16303 + * see <http://www.gnu.org/licenses/>.
16304 + *
16305 + * Ubicom32 implementation derived from (with many thanks):
16306 + *   arch/m68knommu
16307 + *   arch/blackfin
16308 + *   arch/parisc
16309 + */
16310 +#ifndef _ASM_UBICOM32_XOR_H
16311 +#define _ASM_UBICOM32_XOR_H
16312 +
16313 +#include <asm-generic/xor.h>
16314 +
16315 +#endif /* _ASM_UBICOM32_XOR_H */
16316 --- /dev/null
16317 +++ b/arch/ubicom32/Kconfig
16318 @@ -0,0 +1,403 @@
16319 +#
16320 +# For a description of the syntax of this configuration file,
16321 +# see Documentation/kbuild/kconfig-language.txt.
16322 +#
16323 +
16324 +mainmenu "uClinux/ubicom32 (w/o MMU) Kernel Configuration"
16325 +
16326 +config UBICOM32
16327 +       bool
16328 +       select HAVE_OPROFILE
16329 +       default y
16330 +
16331 +config RAMKERNEL
16332 +       bool
16333 +       default y
16334 +
16335 +config CPU_BIG_ENDIAN
16336 +       bool
16337 +       default y
16338 +
16339 +config FORCE_MAX_ZONEORDER
16340 +       int
16341 +       default "14"
16342 +
16343 +config HAVE_CLK
16344 +       bool
16345 +       default y
16346 +
16347 +config MMU
16348 +       bool
16349 +       default n
16350 +
16351 +config FPU
16352 +       bool
16353 +       default n
16354 +
16355 +config ZONE_DMA
16356 +       bool
16357 +       default y
16358 +
16359 +config RWSEM_GENERIC_SPINLOCK
16360 +       bool
16361 +       default y
16362 +
16363 +config RWSEM_XCHGADD_ALGORITHM
16364 +       bool
16365 +       default n
16366 +
16367 +config ARCH_HAS_ILOG2_U32
16368 +       bool
16369 +       default n
16370 +
16371 +config ARCH_HAS_ILOG2_U64
16372 +       bool
16373 +       default n
16374 +
16375 +config GENERIC_FIND_NEXT_BIT
16376 +       bool
16377 +       default y
16378 +
16379 +config GENERIC_GPIO
16380 +       bool
16381 +       default y
16382 +
16383 +config GPIOLIB
16384 +       bool
16385 +       default y
16386 +
16387 +config GENERIC_HWEIGHT
16388 +       bool
16389 +       default y
16390 +
16391 +config GENERIC_HARDIRQS
16392 +       bool
16393 +       default y
16394 +
16395 +config STACKTRACE_SUPPORT
16396 +       bool
16397 +       default y
16398 +
16399 +config LOCKDEP_SUPPORT
16400 +       bool
16401 +       default y
16402 +
16403 +config GENERIC_CALIBRATE_DELAY
16404 +       bool
16405 +       default y
16406 +
16407 +config GENERIC_TIME
16408 +       bool
16409 +       default y
16410 +
16411 +config TIME_LOW_RES
16412 +       bool
16413 +       default y
16414 +
16415 +config GENERIC_CLOCKEVENTS
16416 +       bool
16417 +       default y
16418 +
16419 +config GENERIC_CLOCKEVENTS_BROADCAST
16420 +       bool
16421 +       depends on GENERIC_CLOCKEVENTS
16422 +       default y if SMP && !LOCAL_TIMERS
16423 +
16424 +config NO_IOPORT
16425 +       def_bool y
16426 +
16427 +config ARCH_SUPPORTS_AOUT
16428 +       def_bool y
16429 +
16430 +config IRQ_PER_CPU
16431 +       bool
16432 +       default y
16433 +
16434 +config SCHED_NO_NO_OMIT_FRAME_POINTER
16435 +       bool
16436 +       default y
16437 +
16438 +config UBICOM32_PLIO
16439 +       bool
16440 +       default n
16441 +
16442 +menu "Processor type and features"
16443 +
16444 +comment "Processor type will be selected by Board"
16445 +
16446 +config UBICOM32_V3
16447 +       bool
16448 +       help
16449 +         Ubicom IP5xxx series processor support.
16450 +
16451 +config UBICOM32_V4
16452 +       bool
16453 +       help
16454 +         Ubicom IP7xxx series processor support.
16455 +
16456 +comment "Board"
16457 +choice
16458 +       prompt "Board type"
16459 +       help
16460 +               Select your board.
16461 +
16462 +config NOBOARD
16463 +       bool "No board selected"
16464 +       help
16465 +               Default. Don't select any board specific config. Will not build unless you change!
16466 +
16467 +# Add your boards here
16468 +source "arch/ubicom32/mach-ip5k/Kconfig"
16469 +source "arch/ubicom32/mach-ip7k/Kconfig"
16470 +
16471 +endchoice
16472 +
16473 +comment "Kernel Options"
16474 +config SMP
16475 +       bool "Symmetric multi-processing support"
16476 +       select USE_GENERIC_SMP_HELPERS
16477 +       default n
16478 +       help
16479 +         Enables multithreading support.  Enabling SMP support increases
16480 +         the size of system data structures.  SMP support can have either
16481 +         positive or negative impact on performance depending on workloads.
16482 +
16483 +         If you do not know what to do here, say N.
16484 +config OLD_40400010_SYSTEM_CALL
16485 +       bool "Provide old system call interface at 0x40400010"
16486 +       default y
16487 +       help
16488 +         Provides the old system call interface, does not affect the
16489 +         new system_call interface.
16490 +
16491 +config NR_CPUS
16492 +       int "Number of configured CPUs"
16493 +       range 2 32
16494 +       default 2
16495 +       depends on SMP
16496 +       help
16497 +               Upper bound on the number of CPUs. Space is reserved
16498 +               at compile time for this many CPUs.
16499 +
16500 +config LOCAL_TIMERS
16501 +       bool "Use local timer interrupts"
16502 +       depends on SMP
16503 +       default y
16504 +       help
16505 +         Enable support for local timers on SMP platforms, rather then the
16506 +         legacy IPI broadcast method.  Local timers allows the system
16507 +         accounting to be spread across the timer interval, preventing a
16508 +         "thundering herd" at every timer tick.  A physical timer is allocated
16509 +         per cpu.
16510 +
16511 +config TIMER_EXTRA_ALLOC
16512 +       int "Number of additional physical timer events to create"
16513 +       depends on GENERIC_CLOCKEVENTS
16514 +       default 0
16515 +       help
16516 +               The Ubicom32 processor has a number of event timers that can be wrapped
16517 +               in Linux clock event structures (assuming that the timers are not being
16518 +               used for another purpose).  Based on the value of LOCAL_TIMERS, either
16519 +               2 timers will be used or a timer will be used for every CPU.  This value
16520 +               allows the programmer to select additional timers over that amount.
16521 +
16522 +config IRQSTACKS
16523 +       bool "Create separate stacks for interrupt handling"
16524 +       default n
16525 +       help
16526 +               Selecting this causes interrupts to be created on a separate
16527 +               stack instead of nesting the interrupts on the kernel stack.
16528 +
16529 +config IRQSTACKS_USEOCM
16530 +       bool "Use OCM for interrupt stacks"
16531 +       default n
16532 +       depends on IRQSTACKS
16533 +       help
16534 +               Selecting this cause the interrupt stacks to be placed in OCM
16535 +               reducing cache misses at the expense of using the OCM for servicing
16536 +               interrupts.
16537 +
16538 +menu "OCM Instruction Heap"
16539 +
16540 +config OCM_MODULES_RESERVATION
16541 +       int "OCM Instruction heap reservation. 0-192 kB"
16542 +       range 0 192
16543 +       default "0"
16544 +       help
16545 +         The minimum amount of OCM memory to reserve for kernel loadable module
16546 +         code. If you are not using this memory it cannot be used for anything
16547 +         else. Leave it as 0 if you have prebuilt modules that are compiled with
16548 +         OCM support.
16549 +
16550 +config OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
16551 +       bool "Give all unused ocm code space to the ocm instruction heap."
16552 +       default n
16553 +       help
16554 +         Allow the OCM instruction heap allocation to consume any remaining
16555 +         unused OCM code space.  The result of this is that you will not have
16556 +         and deterministic results, but you will not have any waste either.
16557 +
16558 +config OCM_MODULES_FALLBACK_TO_DDR
16559 +       bool "Loadable Modules requiring OCM may fallback to use DDR."
16560 +       default n
16561 +       help
16562 +         If a module cannot get the OCM code it requires allow DDR to
16563 +         be used instead.
16564 +endmenu
16565 +
16566 +config HZ
16567 +       int "Frequency of 'jiffies' (for polling)"
16568 +       default 1000
16569 +       help
16570 +               100 is common for embedded systems, but 1000 allows
16571 +               you to do more drivers without actually having
16572 +               interrupts working properly.
16573 +
16574 +comment "RAM configuration"
16575 +
16576 +config MIN_RAMSIZE
16577 +       hex "Minimum Size of RAM (in bytes)"
16578 +       range 0x01000000 0x08000000
16579 +       default "0x02000000"
16580 +       help
16581 +               Define the minimum acceptable size of the system
16582 +               RAM. Must be at least 16MB (0x01000000)
16583 +
16584 +comment "Build options"
16585 +config LINKER_RELAXATION
16586 +       bool "Linker Relaxation"
16587 +       default y
16588 +       help
16589 +         Turns on linker relaxation that will produce smaller
16590 +         faster code. Increases link time.
16591 +
16592 +comment "Driver options"
16593 +menu "PCI Bus"
16594 +config PCI
16595 +       bool "PCI bus"
16596 +       default true
16597 +       help
16598 +         Enable/Disable PCI bus
16599 +       source "drivers/pci/Kconfig"
16600 +
16601 +
16602 +config PCI_DEV0_IDSEL
16603 +       hex "slot 0 address"
16604 +       depends on PCI
16605 +       default "0x01000000"
16606 +       help
16607 +         Slot 0 address.  This address should correspond to the address line
16608 +         which the IDSEL bit for this slot is connected to.
16609 +
16610 +config PCI_DEV1_IDSEL
16611 +       hex "slot 1 address"
16612 +       depends on PCI
16613 +       default "0x02000000"
16614 +       help
16615 +         Slot 1 address.  This address should correspond to the address line
16616 +         which the IDSEL bit for this slot is connected to.
16617 +endmenu
16618 +# End PCI
16619 +
16620 +menu "Input devices"
16621 +config UBICOM_INPUT
16622 +       bool "Ubicom polled GPIO input driver"
16623 +       select INPUT
16624 +       select INPUT_POLLDEV
16625 +       help
16626 +               Polling input driver, much like the GPIO input driver, except that it doesn't
16627 +               rely on interrupts.  It will report events via the input subsystem.
16628 +       default n
16629 +
16630 +config UBICOM_INPUT_I2C
16631 +       bool "Ubicom polled GPIO input driver over I2C"
16632 +       select INPUT
16633 +       select INPUT_POLLDEV
16634 +       help
16635 +               Polling input driver, much like the PCA953x driver, it can support a variety of
16636 +               different I2C I/O expanders.  This device polls the I2C I/O expander for events
16637 +               and reports them via the input subsystem.
16638 +       default n
16639 +endmenu
16640 +# Input devices
16641 +
16642 +source "arch/ubicom32/mach-common/Kconfig.switch"
16643 +
16644 +menu "Misc devices"
16645 +config UBICOM_HID
16646 +       bool "Ubicom HID driver"
16647 +       select INPUT
16648 +       select INPUT_POLLDEV
16649 +       select LCD_CLASS_DEVICE
16650 +       help
16651 +               Driver for HID chip found on some Ubicom reference designs.  This chip handles
16652 +               PWM, button input, and IR remote control.  It registers as an input device and
16653 +               a backlight device.
16654 +       default n
16655 +endmenu
16656 +# Misc devices
16657 +
16658 +config CMDLINE_BOOL
16659 +       bool "Built-in kernel command line"
16660 +       default n
16661 +       help
16662 +         Allow for specifying boot arguments to the kernel at
16663 +         build time.  On some systems (e.g. embedded ones), it is
16664 +         necessary or convenient to provide some or all of the
16665 +         kernel boot arguments with the kernel itself (that is,
16666 +         to not rely on the boot loader to provide them.)
16667 +
16668 +         To compile command line arguments into the kernel,
16669 +         set this option to 'Y', then fill in the
16670 +         the boot arguments in CONFIG_CMDLINE.
16671 +
16672 +         Systems with fully functional boot loaders (i.e. non-embedded)
16673 +         should leave this option set to 'N'.
16674 +
16675 +config CMDLINE
16676 +       string "Built-in kernel command string"
16677 +       depends on CMDLINE_BOOL
16678 +       default ""
16679 +       help
16680 +         Enter arguments here that should be compiled into the kernel
16681 +         image and used at boot time.  If the boot loader provides a
16682 +         command line at boot time, it is appended to this string to
16683 +         form the full kernel command line, when the system boots.
16684 +
16685 +         However, you can use the CONFIG_CMDLINE_OVERRIDE option to
16686 +         change this behavior.
16687 +
16688 +         In most cases, the command line (whether built-in or provided
16689 +         by the boot loader) should specify the device for the root
16690 +         file system.
16691 +
16692 +config CMDLINE_OVERRIDE
16693 +       bool "Built-in command line overrides boot loader arguments"
16694 +       default n
16695 +       depends on CMDLINE_BOOL
16696 +       help
16697 +         Set this option to 'Y' to have the kernel ignore the boot loader
16698 +         command line, and use ONLY the built-in command line.
16699 +
16700 +         This is used to work around broken boot loaders.  This should
16701 +         be set to 'N' under normal conditions.
16702 +
16703 +endmenu
16704 +# End Processor type and features
16705 +
16706 +source "arch/ubicom32/Kconfig.debug"
16707 +
16708 +menu "Executable file formats"
16709 +source "fs/Kconfig.binfmt"
16710 +endmenu
16711 +
16712 +source "init/Kconfig"
16713 +source "kernel/Kconfig.preempt"
16714 +source "kernel/time/Kconfig"
16715 +source "mm/Kconfig"
16716 +source "net/Kconfig"
16717 +source "drivers/Kconfig"
16718 +source "fs/Kconfig"
16719 +source "security/Kconfig"
16720 +source "crypto/Kconfig"
16721 +source "lib/Kconfig"
16722 --- /dev/null
16723 +++ b/arch/ubicom32/Kconfig.debug
16724 @@ -0,0 +1,129 @@
16725 +menu "Kernel hacking"
16726 +
16727 +config TRACE_IRQFLAGS_SUPPORT
16728 +       def_bool y
16729 +
16730 +config DEBUG_VERBOSE
16731 +        bool "Verbose fault messages"
16732 +        default y
16733 +        select PRINTK
16734 +        help
16735 +          When a program crashes due to an exception, or the kernel detects
16736 +          an internal error, the kernel can print a not so brief message
16737 +          explaining what the problem was. This debugging information is
16738 +          useful to developers and kernel hackers when tracking down problems,
16739 +          but mostly meaningless to other people. This is always helpful for
16740 +          debugging but serves no purpose on a production system.
16741 +          Most people should say N here.
16742 +
16743 +config PROTECT_KERNEL
16744 +       default y
16745 +       bool 'Enable Kernel range register Protection'
16746 +       help
16747 +         Adds code to enable/disable range registers to protect static
16748 +         kernel code/data from userspace.  Currently the ranges covered
16749 +         do no protect kernel loadable modules or dynamically allocated
16750 +         kernel data.
16751 +
16752 +config NO_KERNEL_MSG
16753 +       bool "Suppress Kernel BUG Messages"
16754 +       help
16755 +         Do not output any debug BUG messages within the kernel.
16756 +
16757 +config EARLY_PRINTK
16758 +       bool "Use the driver that you selected as console also for early printk (to debug kernel bootup)."
16759 +       default n
16760 +       help
16761 +         If you want to use the serdes driver (console=ttyUS0) for
16762 +         early printk, you must also supply an additional kernel boot
16763 +         parameter like this:
16764 +
16765 +               serdes=ioportaddr,irq,clockrate,baud
16766 +
16767 +         For an IP7160RGW eval board, you could use this:
16768 +
16769 +               serdes=0x2004000,61,250000000,57600
16770 +
16771 +         which will let you see early printk output at 57600 baud.
16772 +
16773 +config STOP_ON_TRAP
16774 +       bool "Enable stopping at the LDSR for all traps"
16775 +       default n
16776 +       help
16777 +       Cause the LDSR to stop all threads whenever a trap is about to be serviced
16778 +
16779 +config STOP_ON_BUG
16780 +       bool "Enable stopping on failed BUG_ON()"
16781 +       default n
16782 +       help
16783 +       Cause all BUG_ON failures to stop all threads
16784 +
16785 +config DEBUG_IRQMEASURE
16786 +       bool "Enable IRQ handler measurements"
16787 +       default n
16788 +       help
16789 +       When enabled each IRQ's min/avg/max times will be printed.  If the handler
16790 +       re-enables interrupt, the times will show the full time including to service
16791 +       nested interrupts.  See /proc/irq_measurements.
16792 +
16793 +config DEBUG_PCIMEASURE
16794 +       bool "Enable PCI transaction measurements"
16795 +       default n
16796 +       help
16797 +       When enabled the system will measure the min/avg/max timer for each PCI transactions.
16798 +       See /proc/pci_measurements.
16799 +
16800 +config ACCESS_OK_CHECKS_ENABLED
16801 +       bool "Enable user space access checks"
16802 +       default n
16803 +       help
16804 +       Enabling this check causes the kernel to verify that addresses passed
16805 +       to the kernel by the user space code are within the processes
16806 +       address space.  On a no-mmu system, this is done by examining the
16807 +       processes memory data structures (adversly affecting performance) but
16808 +       ensuring that a process does not ask the kernel to violate another
16809 +       processes address space.  Sadly, the kernel uses access_ok() for
16810 +       address that are in the kernel which results in a large volume of
16811 +       false positives.
16812 +
16813 +choice
16814 +       prompt "Unaligned Access Support"
16815 +       default UNALIGNED_ACCESS_ENABLED
16816 +       help
16817 +               Kernel / Userspace unaligned access handling.
16818 +
16819 +config  UNALIGNED_ACCESS_ENABLED
16820 +       bool "Kernel and Userspace"
16821 +       help
16822 +
16823 +config  UNALIGNED_ACCESS_USERSPACE_ONLY
16824 +       bool "Userspace Only"
16825 +       help
16826 +
16827 +config  UNALIGNED_ACCESS_DISABLED
16828 +       bool "Disabled"
16829 +       help
16830 +
16831 +endchoice
16832 +
16833 +config DEBUG_STACKOVERFLOW
16834 +       bool "Check for stack overflows"
16835 +       default n
16836 +       depends on DEBUG_KERNEL
16837 +       help
16838 +         This option will cause messages to be printed if free kernel stack space
16839 +         drops below a certain limit (THREAD_SIZE /8).
16840 +
16841 +config DEBUG_STACK_USAGE
16842 +       bool "Stack utilization instrumentation"
16843 +       default n
16844 +       depends on DEBUG_KERNEL
16845 +       help
16846 +         Enables the display of the minimum amount of free kernel stack which each
16847 +         task has ever had available in the sysrq-T and sysrq-P debug output.
16848 +
16849 +         This option will slow down process creation somewhat.
16850 +
16851 +source "lib/Kconfig.debug"
16852 +
16853 +endmenu
16854 --- /dev/null
16855 +++ b/arch/ubicom32/kernel/asm-offsets.c
16856 @@ -0,0 +1,161 @@
16857 +/*
16858 + * arch/ubicom32/kernel/asm-offsets.c
16859 + *   Ubicom32 architecture definitions needed by assembly language modules.
16860 + *
16861 + * (C) Copyright 2009, Ubicom, Inc.
16862 + *
16863 + * This file is part of the Ubicom32 Linux Kernel Port.
16864 + *
16865 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16866 + * it and/or modify it under the terms of the GNU General Public License
16867 + * as published by the Free Software Foundation, either version 2 of the
16868 + * License, or (at your option) any later version.
16869 + *
16870 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16871 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16872 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16873 + * the GNU General Public License for more details.
16874 + *
16875 + * You should have received a copy of the GNU General Public License
16876 + * along with the Ubicom32 Linux Kernel Port.  If not,
16877 + * see <http://www.gnu.org/licenses/>.
16878 + *
16879 + * Ubicom32 implementation derived from (with many thanks):
16880 + *   arch/m68knommu
16881 + *   arch/blackfin
16882 + *   arch/parisc
16883 + */
16884 +/*
16885 + * This program is used to generate definitions needed by
16886 + * assembly language modules.
16887 + *
16888 + * We use the technique used in the OSF Mach kernel code:
16889 + * generate asm statements containing #defines,
16890 + * compile this file to assembler, and then extract the
16891 + * #defines from the assembly-language output.
16892 + */
16893 +
16894 +#include <linux/module.h>
16895 +#include <linux/stddef.h>
16896 +#include <linux/sched.h>
16897 +#include <linux/kernel_stat.h>
16898 +#include <linux/ptrace.h>
16899 +#include <linux/hardirq.h>
16900 +#include <asm/bootinfo.h>
16901 +#include <asm/irq.h>
16902 +#include <asm/thread_info.h>
16903 +
16904 +#define DEFINE(sym, val) \
16905 +        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
16906 +
16907 +#define BLANK() asm volatile("\n->" : : )
16908 +
16909 +int main(void)
16910 +{
16911 +       /* offsets into the task struct */
16912 +       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
16913 +       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
16914 +       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
16915 +       DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
16916 +       DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
16917 +       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
16918 +       DEFINE(TASK_MM, offsetof(struct task_struct, mm));
16919 +       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
16920 +
16921 +       /* offsets into the kernel_stat struct */
16922 +//     DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
16923 +
16924 +       /* offsets into the irq_cpustat_t struct */
16925 +       DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
16926 +
16927 +       /* offsets into the thread struct */
16928 +       DEFINE(THREAD_D10, offsetof(struct thread_struct, d10));
16929 +       DEFINE(THREAD_D11, offsetof(struct thread_struct, d11));
16930 +       DEFINE(THREAD_D12, offsetof(struct thread_struct, d12));
16931 +       DEFINE(THREAD_D13, offsetof(struct thread_struct, d13));
16932 +       DEFINE(THREAD_A1, offsetof(struct thread_struct, a1));
16933 +       DEFINE(THREAD_A2, offsetof(struct thread_struct, a2));
16934 +       DEFINE(THREAD_A5, offsetof(struct thread_struct, a5));
16935 +       DEFINE(THREAD_A6, offsetof(struct thread_struct, a6));
16936 +       DEFINE(THREAD_SP, offsetof(struct thread_struct, sp));
16937 +
16938 +       /* offsets into the pt_regs */
16939 +       DEFINE(PT_D0, offsetof(struct pt_regs, dn[0]));
16940 +       DEFINE(PT_D1, offsetof(struct pt_regs, dn[1]));
16941 +       DEFINE(PT_D2, offsetof(struct pt_regs, dn[2]));
16942 +       DEFINE(PT_D3, offsetof(struct pt_regs, dn[3]));
16943 +       DEFINE(PT_D4, offsetof(struct pt_regs, dn[4]));
16944 +       DEFINE(PT_D5, offsetof(struct pt_regs, dn[5]));
16945 +       DEFINE(PT_D6, offsetof(struct pt_regs, dn[6]));
16946 +       DEFINE(PT_D7, offsetof(struct pt_regs, dn[7]));
16947 +       DEFINE(PT_D8, offsetof(struct pt_regs, dn[8]));
16948 +       DEFINE(PT_D9, offsetof(struct pt_regs, dn[9]));
16949 +       DEFINE(PT_D10, offsetof(struct pt_regs, dn[10]));
16950 +       DEFINE(PT_D11, offsetof(struct pt_regs, dn[11]));
16951 +       DEFINE(PT_D12, offsetof(struct pt_regs, dn[12]));
16952 +       DEFINE(PT_D13, offsetof(struct pt_regs, dn[13]));
16953 +       DEFINE(PT_D14, offsetof(struct pt_regs, dn[14]));
16954 +       DEFINE(PT_D15, offsetof(struct pt_regs, dn[15]));
16955 +       DEFINE(PT_A0, offsetof(struct pt_regs, an[0]));
16956 +       DEFINE(PT_A1, offsetof(struct pt_regs, an[1]));
16957 +       DEFINE(PT_A2, offsetof(struct pt_regs, an[2]));
16958 +       DEFINE(PT_A3, offsetof(struct pt_regs, an[3]));
16959 +       DEFINE(PT_A4, offsetof(struct pt_regs, an[4]));
16960 +       DEFINE(PT_A5, offsetof(struct pt_regs, an[5]));
16961 +       DEFINE(PT_A6, offsetof(struct pt_regs, an[6]));
16962 +       DEFINE(PT_A7, offsetof(struct pt_regs, an[7]));
16963 +       DEFINE(PT_SP, offsetof(struct pt_regs, an[7]));
16964 +
16965 +       DEFINE(PT_ACC0HI, offsetof(struct pt_regs, acc0[0]));
16966 +       DEFINE(PT_ACC0LO, offsetof(struct pt_regs, acc0[1]));
16967 +       DEFINE(PT_MAC_RC16, offsetof(struct pt_regs, mac_rc16));
16968 +
16969 +       DEFINE(PT_ACC1HI, offsetof(struct pt_regs, acc1[0]));
16970 +       DEFINE(PT_ACC1LO, offsetof(struct pt_regs, acc1[1]));
16971 +
16972 +       DEFINE(PT_SOURCE3, offsetof(struct pt_regs, source3));
16973 +       DEFINE(PT_INST_CNT, offsetof(struct pt_regs, inst_cnt));
16974 +       DEFINE(PT_CSR, offsetof(struct pt_regs, csr));
16975 +       DEFINE(PT_DUMMY_UNUSED, offsetof(struct pt_regs, dummy_unused));
16976 +
16977 +       DEFINE(PT_INT_MASK0, offsetof(struct pt_regs, int_mask0));
16978 +       DEFINE(PT_INT_MASK1, offsetof(struct pt_regs, int_mask1));
16979 +
16980 +       DEFINE(PT_PC, offsetof(struct pt_regs, pc));
16981 +
16982 +       DEFINE(PT_TRAP_CAUSE, offsetof(struct pt_regs, trap_cause));
16983 +
16984 +       DEFINE(PT_SIZE, sizeof(struct pt_regs));
16985 +
16986 +       DEFINE(PT_FRAME_TYPE, offsetof(struct pt_regs, frame_type));
16987 +
16988 +       DEFINE(PT_ORIGINAL_D0, offsetof(struct pt_regs, original_dn_0));
16989 +       DEFINE(PT_PREVIOUS_PC, offsetof(struct pt_regs, previous_pc));
16990 +
16991 +       /* offsets into the kernel_stat struct */
16992 +//     DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
16993 +
16994 +       /* signal defines */
16995 +       DEFINE(SIGSEGV, SIGSEGV);
16996 +       //DEFINE(SEGV_MAPERR, SEGV_MAPERR);
16997 +       DEFINE(SIGTRAP, SIGTRAP);
16998 +       //DEFINE(TRAP_TRACE, TRAP_TRACE);
16999 +
17000 +       DEFINE(PT_PTRACED, PT_PTRACED);
17001 +       DEFINE(PT_DTRACE, PT_DTRACE);
17002 +
17003 +       DEFINE(ASM_THREAD_SIZE, THREAD_SIZE);
17004 +
17005 +       /* Offsets in thread_info structure */
17006 +       DEFINE(TI_TASK, offsetof(struct thread_info, task));
17007 +       DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
17008 +       DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
17009 +       DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
17010 +       DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
17011 +       DEFINE(TI_INTR_NESTING, offsetof(struct thread_info, interrupt_nesting));
17012 +       DEFINE(ASM_TIF_NEED_RESCHED, TIF_NEED_RESCHED);
17013 +       DEFINE(ASM_TIF_SYSCALL_TRACE, TIF_SYSCALL_TRACE);
17014 +       DEFINE(ASM_TIF_SIGPENDING, TIF_SIGPENDING);
17015 +
17016 +       return 0;
17017 +}
17018 --- /dev/null
17019 +++ b/arch/ubicom32/kernel/devtree.c
17020 @@ -0,0 +1,173 @@
17021 +/*
17022 + * arch/ubicom32/kernel/devtree.c
17023 + *   Ubicom32 architecture device tree implementation.
17024 + *
17025 + * (C) Copyright 2009, Ubicom, Inc.
17026 + *
17027 + * This file is part of the Ubicom32 Linux Kernel Port.
17028 + *
17029 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17030 + * it and/or modify it under the terms of the GNU General Public License
17031 + * as published by the Free Software Foundation, either version 2 of the
17032 + * License, or (at your option) any later version.
17033 + *
17034 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17035 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17036 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17037 + * the GNU General Public License for more details.
17038 + *
17039 + * You should have received a copy of the GNU General Public License
17040 + * along with the Ubicom32 Linux Kernel Port.  If not,
17041 + * see <http://www.gnu.org/licenses/>.
17042 + *
17043 + * Ubicom32 implementation derived from (with many thanks):
17044 + *   arch/m68knommu
17045 + *   arch/blackfin
17046 + *   arch/parisc
17047 + */
17048 +
17049 +#include <linux/module.h>
17050 +#include <linux/kernel.h>
17051 +#include <linux/string.h>
17052 +#include <linux/errno.h>
17053 +#include <asm/devtree.h>
17054 +
17055 +/*
17056 + * The device tree.
17057 + */
17058 +struct devtree_node *devtree;
17059 +
17060 +/*
17061 + * devtree_print()
17062 + *     Print the device tree.
17063 + */
17064 +void devtree_print(void)
17065 +{
17066 +       struct devtree_node *p = devtree;
17067 +       printk(KERN_INFO "Device Tree:\n");
17068 +       while (p) {
17069 +               if (p->magic != DEVTREE_NODE_MAGIC) {
17070 +                       printk(KERN_EMERG
17071 +                              "device tree has improper node: %p\n", p);
17072 +                       return;
17073 +               }
17074 +               printk(KERN_INFO "\t%p: sendirq=%03d, recvirq=%03d, "
17075 +                      " name=%s\n", p, p->sendirq, p->recvirq, p->name);
17076 +               p = p->next;
17077 +       }
17078 +}
17079 +EXPORT_SYMBOL(devtree_print);
17080 +
17081 +/*
17082 + * devtree_irq()
17083 + *     Return the IRQ(s) associated with devtree node.
17084 + */
17085 +int devtree_irq(struct devtree_node *dn,
17086 +               unsigned char *sendirq,
17087 +               unsigned char *recvirq)
17088 +{
17089 +       if (dn->magic != DEVTREE_NODE_MAGIC) {
17090 +               printk(KERN_EMERG "improper node: %p\n", dn);
17091 +               if (sendirq) {
17092 +                       *sendirq = DEVTREE_IRQ_NONE;
17093 +               }
17094 +               if (recvirq) {
17095 +                       *recvirq = DEVTREE_IRQ_NONE;
17096 +               }
17097 +               return -EFAULT;
17098 +       }
17099 +
17100 +       /*
17101 +        * Copy the devtree irq(s) to the output parameters.
17102 +        */
17103 +       if (sendirq) {
17104 +               *sendirq = dn->sendirq;
17105 +       }
17106 +       if (recvirq) {
17107 +               *recvirq = dn->recvirq;
17108 +       }
17109 +       return 0;
17110 +}
17111 +EXPORT_SYMBOL(devtree_irq);
17112 +
17113 +/*
17114 + * devtree_find_next()
17115 + *     Provide an iterator for walking the device tree.
17116 + */
17117 +struct devtree_node *devtree_find_next(struct devtree_node **cur)
17118 +{
17119 +       struct devtree_node *p = *cur;
17120 +       if (!p) {
17121 +               *cur = devtree;
17122 +               return devtree;
17123 +       }
17124 +       p = p->next;
17125 +       *cur = p;
17126 +       return p;
17127 +}
17128 +
17129 +/*
17130 + * devtree_find_by_irq()
17131 + *     Return the node associated with a given irq.
17132 + */
17133 +struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq)
17134 +{
17135 +       struct devtree_node *p = devtree;
17136 +
17137 +       if (sendirq == recvirq) {
17138 +               printk(KERN_EMERG "identical request makes no sense sendirq = "
17139 +                      "%d, recvirq= %d\n", sendirq, recvirq);
17140 +               return NULL;
17141 +       }
17142 +
17143 +       while (p) {
17144 +               if (p->magic != DEVTREE_NODE_MAGIC) {
17145 +                       printk(KERN_EMERG
17146 +                              "device tree has improper node: %p\n", p);
17147 +                       return NULL;
17148 +               }
17149 +
17150 +               /*
17151 +                * See if we can find a match on the IRQ(s) specified.
17152 +                */
17153 +               if ((sendirq == p->sendirq) && (recvirq == p->recvirq)) {
17154 +                       return p;
17155 +               }
17156 +
17157 +               if ((sendirq == DEVTREE_IRQ_DONTCARE) &&
17158 +                   (p->recvirq == recvirq)) {
17159 +                       return p;
17160 +               }
17161 +
17162 +               if ((recvirq == DEVTREE_IRQ_DONTCARE) &&
17163 +                   (p->sendirq == sendirq)) {
17164 +                       return p;
17165 +               }
17166 +
17167 +               p = p->next;
17168 +       }
17169 +       return NULL;
17170 +}
17171 +EXPORT_SYMBOL(devtree_find_by_irq);
17172 +
17173 +/*
17174 + * devtree_find_node()
17175 + *     Find a node in the device tree by name.
17176 + */
17177 +struct devtree_node *devtree_find_node(const char *str)
17178 +{
17179 +       struct devtree_node *p = devtree;
17180 +       while (p) {
17181 +               if (p->magic != DEVTREE_NODE_MAGIC) {
17182 +                       printk(KERN_EMERG
17183 +                              "device tree has improper node: %p\n", p);
17184 +                       return NULL;
17185 +               }
17186 +               if (strcmp(p->name, str) == 0) {
17187 +                       return p;
17188 +               }
17189 +               p = p->next;
17190 +       }
17191 +       return NULL;
17192 +}
17193 +EXPORT_SYMBOL(devtree_find_node);
17194 --- /dev/null
17195 +++ b/arch/ubicom32/kernel/dma.c
17196 @@ -0,0 +1,60 @@
17197 +/*
17198 + * arch/ubicom32/kernel/dma.c
17199 + *   Ubicom32 architecture dynamic DMA mapping support.
17200 + *
17201 + * (C) Copyright 2009, Ubicom, Inc.
17202 + *
17203 + * This file is part of the Ubicom32 Linux Kernel Port.
17204 + *
17205 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17206 + * it and/or modify it under the terms of the GNU General Public License
17207 + * as published by the Free Software Foundation, either version 2 of the
17208 + * License, or (at your option) any later version.
17209 + *
17210 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17211 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17212 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17213 + * the GNU General Public License for more details.
17214 + *
17215 + * You should have received a copy of the GNU General Public License
17216 + * along with the Ubicom32 Linux Kernel Port.  If not,
17217 + * see <http://www.gnu.org/licenses/>.
17218 + *
17219 + * Ubicom32 implementation derived from (with many thanks):
17220 + *   arch/m68knommu
17221 + *   arch/blackfin
17222 + *   arch/parisc
17223 + *
17224 + * We never have any address translations to worry about, so this
17225 + * is just alloc/free.
17226 + */
17227 +
17228 +#include <linux/types.h>
17229 +#include <linux/mm.h>
17230 +#include <linux/string.h>
17231 +#include <linux/device.h>
17232 +#include <linux/io.h>
17233 +
17234 +void *dma_alloc_coherent(struct device *dev, size_t size,
17235 +                          dma_addr_t *dma_handle, int gfp)
17236 +{
17237 +       void *ret;
17238 +       /* ignore region specifiers */
17239 +       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
17240 +
17241 +       if (dev == NULL || (*dev->dma_mask < 0xffffffff))
17242 +               gfp |= GFP_DMA;
17243 +       ret = (void *)__get_free_pages(gfp, get_order(size));
17244 +
17245 +       if (ret != NULL) {
17246 +               memset(ret, 0, size);
17247 +               *dma_handle = virt_to_phys(ret);
17248 +       }
17249 +       return ret;
17250 +}
17251 +
17252 +void dma_free_coherent(struct device *dev, size_t size,
17253 +                        void *vaddr, dma_addr_t dma_handle)
17254 +{
17255 +       free_pages((unsigned long)vaddr, get_order(size));
17256 +}
17257 --- /dev/null
17258 +++ b/arch/ubicom32/kernel/flat.c
17259 @@ -0,0 +1,206 @@
17260 +/*
17261 + * arch/ubicom32/kernel/flat.c
17262 + *   Ubicom32 architecture flat executable format support.
17263 + *
17264 + * (C) Copyright 2009, Ubicom, Inc.
17265 + *
17266 + * This file is part of the Ubicom32 Linux Kernel Port.
17267 + *
17268 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17269 + * it and/or modify it under the terms of the GNU General Public License
17270 + * as published by the Free Software Foundation, either version 2 of the
17271 + * License, or (at your option) any later version.
17272 + *
17273 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17274 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17275 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17276 + * the GNU General Public License for more details.
17277 + *
17278 + * You should have received a copy of the GNU General Public License
17279 + * along with the Ubicom32 Linux Kernel Port.  If not,
17280 + * see <http://www.gnu.org/licenses/>.
17281 + *
17282 + * Ubicom32 implementation derived from (with many thanks):
17283 + *   arch/m68knommu
17284 + *   arch/blackfin
17285 + *   arch/parisc
17286 + */
17287 +#include <linux/module.h>
17288 +#include <linux/types.h>
17289 +#include <linux/flat.h>
17290 +
17291 +unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp,
17292 +                                            u32_t relval,
17293 +                                            u32_t flags,
17294 +                                            unsigned long *persistent)
17295 +{
17296 +       u32_t relval_reloc_type = relval >> 27;
17297 +       u32_t insn = *rp;
17298 +
17299 +       if (*persistent) {
17300 +               /*
17301 +                * relval holds the relocation that has to be adjusted.
17302 +                */
17303 +               if (relval == 0) {
17304 +                       *persistent = 0;
17305 +               }
17306 +
17307 +               return relval;
17308 +       }
17309 +
17310 +       if (relval_reloc_type == R_UBICOM32_32) {
17311 +               /*
17312 +                * insn holds the relocation
17313 +                */
17314 +               return insn;
17315 +       }
17316 +
17317 +       /*
17318 +        * We don't know this one.
17319 +        */
17320 +       return 0;
17321 +}
17322 +
17323 +void ubicom32_flat_put_addr_at_rp(unsigned long *rp,
17324 +                                 u32_t val,
17325 +                                 u32_t relval,
17326 +                                 unsigned long *persistent)
17327 +{
17328 +       u32_t reloc_type = (relval >> 27) & 0x1f;
17329 +       u32_t insn = *rp;
17330 +
17331 +       /*
17332 +        * If persistent is set then it contains the relocation type.
17333 +        */
17334 +       if (*persistent) {
17335 +               /*
17336 +                * If persistent is set then it contains the relocation type.
17337 +                */
17338 +               reloc_type = (*persistent >> 27) & 0x1f;
17339 +       }
17340 +
17341 +       switch (reloc_type) {
17342 +       case R_UBICOM32_32:
17343 +               /*
17344 +                * Store the 32 bits as is.
17345 +                */
17346 +               *rp = val;
17347 +               break;
17348 +       case R_UBICOM32_HI24:
17349 +               {
17350 +                       /*
17351 +                        * 24 bit relocation that is part of the MOVEAI
17352 +                        * instruction. The 24 bits come from bits 7 - 30 of the
17353 +                        * relocation. The 24 bits eventually get split into 2
17354 +                        * fields in the instruction encoding.
17355 +                        *
17356 +                        * - Bits 7 - 27 of the relocation are encoded into bits
17357 +                        * 0 - 20 of the instruction.
17358 +                        *
17359 +                        * - Bits 28 - 30 of the relocation are encoded into bit
17360 +                        * 24 - 26 of the instruction.
17361 +                        */
17362 +                       u32_t mask = 0x1fffff | (0x7 << 24);
17363 +                       u32_t valid24bits = (val >> 7) & 0xffffff;
17364 +                       u32_t bot_21 = valid24bits & 0x1fffff;
17365 +                       u32_t upper_3_bits = ((valid24bits & 0xe00000) << 3);
17366 +                       insn &= ~mask;
17367 +
17368 +                       insn |= bot_21;
17369 +                       insn |= upper_3_bits;
17370 +                       *rp = insn;
17371 +               }
17372 +               break;
17373 +       case R_UBICOM32_LO7_S:
17374 +       case R_UBICOM32_LO7_2_S:
17375 +       case R_UBICOM32_LO7_4_S:
17376 +               {
17377 +                       /*
17378 +                        * Bits 0 - 6 of the relocation are encoded into the
17379 +                        * 7bit unsigned immediate fields of the SOURCE-1 field
17380 +                        * of the instruction.  The immediate value is left
17381 +                        * shifted by (0, 1, 2) based on the operand size.
17382 +                        */
17383 +                       u32_t mask = 0x1f | (0x3 << 8);
17384 +                       u32_t bottom, top;
17385 +                       val &= 0x7f;
17386 +                       if (reloc_type == R_UBICOM32_LO7_2_S) {
17387 +                               val >>= 1;
17388 +                       } else if (reloc_type == R_UBICOM32_LO7_4_S) {
17389 +                               val >>= 2;
17390 +                       }
17391 +
17392 +                       bottom  = val & 0x1f;
17393 +                       top = val >> 5;
17394 +                       insn &= ~mask;
17395 +                       insn |= bottom;
17396 +                       insn |= (top << 8);
17397 +                       BUG_ON(*rp != insn);
17398 +                       *rp = insn;
17399 +                       break;
17400 +               }
17401 +       case R_UBICOM32_LO7_D:
17402 +       case R_UBICOM32_LO7_2_D:
17403 +       case R_UBICOM32_LO7_4_D:
17404 +               {
17405 +                       /*
17406 +                        * Bits 0 - 6 of the relocation are encoded into the
17407 +                        * 7bit unsigned immediate fields of the DESTINATION
17408 +                        * field of the instruction.  The immediate value is
17409 +                        * left shifted by (0, 1, 2) based on the operand size.
17410 +                        */
17411 +                       u32_t mask = (0x1f | (0x3 << 8)) << 16;
17412 +                       u32_t bottom, top;
17413 +                       val &= 0x7f;
17414 +                       if (reloc_type == R_UBICOM32_LO7_2_D) {
17415 +                               val >>= 1;
17416 +                       } else if (reloc_type == R_UBICOM32_LO7_4_D) {
17417 +                               val >>= 2;
17418 +                       }
17419 +                       bottom  = (val & 0x1f) << 16;
17420 +                       top = (val >> 5) << 16;
17421 +                       insn &= ~mask;
17422 +                       insn |= bottom;
17423 +                       insn |= (top << 8);
17424 +                       BUG_ON(*rp != insn);
17425 +                       *rp = insn;
17426 +                       break;
17427 +               }
17428 +       case R_UBICOM32_LO7_CALLI:
17429 +       case R_UBICOM32_LO16_CALLI:
17430 +               {
17431 +                       /*
17432 +                        * Extract the offset for a CALLI instruction. The
17433 +                        * offsets can be either 7 bits or 18 bits. Since all
17434 +                        * instructions in ubicom32 architecture are at work
17435 +                        * aligned addresses the truncated offset is right
17436 +                        * shifted by 2 before being encoded in the instruction.
17437 +                        */
17438 +                       if (reloc_type == R_UBICOM32_LO7_CALLI) {
17439 +                               val &= 0x7f;
17440 +                       } else {
17441 +                               val &= 0x3ffff;
17442 +                       }
17443 +
17444 +                       val >>= 2;
17445 +
17446 +                       insn &= ~0x071f071f;
17447 +                       insn |= (val & 0x1f) << 0;
17448 +                       val >>= 5;
17449 +                       insn |= (val & 0x07) << 8;
17450 +                       val >>= 3;
17451 +                       insn |= (val & 0x1f) << 16;
17452 +                       val >>= 5;
17453 +                       insn |= (val & 0x07) << 24;
17454 +                       if (reloc_type == R_UBICOM32_LO7_CALLI) {
17455 +                               BUG_ON(*rp != insn);
17456 +                       }
17457 +                       *rp = insn;
17458 +               }
17459 +               break;
17460 +       }
17461 +
17462 +       if (*persistent) {
17463 +               *persistent = 0;
17464 +       }
17465 +}
17466 --- /dev/null
17467 +++ b/arch/ubicom32/kernel/head.S
17468 @@ -0,0 +1,273 @@
17469 +/*
17470 + * arch/ubicom32/kernel/head.S
17471 + *     <TODO: Replace with short file description>
17472 + *
17473 + * (C) Copyright 2009, Ubicom, Inc.
17474 + *
17475 + * This file is part of the Ubicom32 Linux Kernel Port.
17476 + *
17477 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17478 + * it and/or modify it under the terms of the GNU General Public License
17479 + * as published by the Free Software Foundation, either version 2 of the
17480 + * License, or (at your option) any later version.
17481 + *
17482 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17483 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17484 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17485 + * the GNU General Public License for more details.
17486 + *
17487 + * You should have received a copy of the GNU General Public License
17488 + * along with the Ubicom32 Linux Kernel Port.  If not,
17489 + * see <http://www.gnu.org/licenses/>.
17490 + *
17491 + * Ubicom32 implementation derived from (with many thanks):
17492 + *   arch/m68knommu
17493 + *   arch/blackfin
17494 + *   arch/parisc
17495 + */
17496 +#include <linux/sys.h>
17497 +#include <linux/linkage.h>
17498 +#include <asm/asm-offsets.h>
17499 +#include <asm/page_offset.h>
17500 +#define __ASM__
17501 +#include <asm/ip5000.h>
17502 +
17503 +
17504 +#define SRC_AN A3
17505 +#define DST_AN A4
17506 +
17507 +#define PARAM_DN D0
17508 +#define TMP_DN D15
17509 +#define TMP2_DN D14
17510 +
17511 +/*
17512 + * The following code is placed at the start of the Linux section of memory.
17513 + * This is the primary entry point for Linux.
17514 + *
17515 + * However, we also want the syscall entry/exit code to be at a fixed address.
17516 + * So we take the primary entry point and reserve 16 bytes.  That address is
17517 + * where the system_call entry point exists.  This 16 bytes basically allows
17518 + * us to jump around the system_call entry point code to the actual startup
17519 + * code.
17520 + *
17521 + * Linux Memory Map (see vlinux.lds.S):
17522 + * 0x40400000 - Primary Entry Point for Linux (jump around code below).
17523 + * 0x40400010 - Old syscall Entry Point.
17524 + */
17525 +
17526 +       .sect   .skip_syscall, "ax", @progbits
17527 +       .global __skip_syscall_section
17528 +__skip_syscall_section:
17529 +       moveai          A3, #%hi(_start)
17530 +       lea.1           A3, %lo(_start)(A3)
17531 +       ret             A3
17532 +/*
17533 + * __os_node_offset contains the offset from KERNELBASE to the os_node, it is
17534 + * not intended to be used by anything except the boot code.
17535 + */
17536 +__os_node_offset:
17537 +.long  (_os_node - KERNELSTART)
17538 +
17539 +.text
17540 +.global        _start
17541 +
17542 +/*
17543 + * start()
17544 + *     This is the start of the Linux kernel.
17545 + */
17546 +_start:
17547 +       move.4          SCRATCHPAD1, #0
17548 +
17549 +
17550 +/*
17551 + * Setup the range registers... the loader has setup a few, but we will go ahead
17552 + * and correct them for our own limits. Note that once set these are never
17553 + * changed again.  The ranges are as follows
17554 + *
17555 + *  D_RANGE0 - io block (set up by loaded)
17556 + *
17557 + *  I_RANGE0 and D_RANGE1 - kernel/ultra loader address space bottom of ocm-> top
17558 + *     of ram typically 0x3ffc0000 - 0x440000000
17559 + *  I_RANGE1 - kernel / userspace transition area (aka syscalls, context switches)
17560 + *     typically 0x3FFC0030 - ~0x3FFC0200
17561 + *  I_RANGE2 / D_RANGE2 - slab area
17562 + *     typically 0x40A00000 - ~0x44000000
17563 + *  I_RANGE3
17564 + *     old system call interface if enabled.
17565 + *
17566 + *   D_RANGE3, D_RANGE4 - unused.
17567 + */
17568 +       moveai          SRC_AN, #%hi(PAGE_OFFSET_RAW)
17569 +       lea.4           SRC_AN, %lo(PAGE_OFFSET_RAW)(SRC_AN)
17570 +       move.4          D_RANGE1_LO, SRC_AN
17571 +       move.4          I_RANGE0_LO, SRC_AN
17572 +
17573 +; don't try to calculate I_RANGE_HI, see below
17574 +;      moveai          SRC_AN, #%hi(___init_end-4)
17575 +;      lea.4           SRC_AN, %lo(___init_end-4)(SRC_AN)
17576 +;      move.4          I_RANGE0_HI, SRC_AN
17577 +
17578 +       moveai          SRC_AN, #%hi(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)
17579 +       lea.4           SRC_AN, %lo(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)(SRC_AN)
17580 +       move.4          D_RANGE1_HI, SRC_AN
17581 +
17582 +; for now allow the whole ram to be executable as well so we don't run into problems
17583 +; once we load user more code.
17584 +       move.4          I_RANGE0_HI, SRC_AN
17585 +
17586 +#ifdef CONFIG_PROTECT_KERNEL
17587 +; when kernel protection is enabled, we only open up syscall and non kernel text
17588 +; for userspace apps, for now only irange registers registers 1 and 2 are used for userspace.
17589 +
17590 +       ;; syscall range
17591 +       moveai          SRC_AN, #%hi(__syscall_text_run_begin)
17592 +       lea.4           SRC_AN, %lo(__syscall_text_run_begin)(SRC_AN)
17593 +       move.4          I_RANGE1_LO, SRC_AN
17594 +       moveai          SRC_AN, #%hi(__syscall_text_run_end)
17595 +       lea.4           SRC_AN, %lo(__syscall_text_run_end)(SRC_AN)
17596 +       move.4          I_RANGE1_HI, SRC_AN
17597 +
17598 +       ;; slab instructions
17599 +       moveai          SRC_AN, #%hi(_edata)
17600 +       lea.4           SRC_AN, %lo(_edata)(SRC_AN)
17601 +       move.4          I_RANGE2_LO, SRC_AN
17602 +       ;; End of DDR is already in range0 hi so just copy it.
17603 +       move.4          I_RANGE2_HI, I_RANGE0_HI
17604 +
17605 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17606 +       ;; create a small hole for old syscall location
17607 +       moveai          SRC_AN, #%hi(0x40400000)
17608 +       lea.4           I_RANGE3_LO, 0x10(SRC_AN)
17609 +       lea.4           I_RANGE3_HI, 0x14(SRC_AN)
17610 +#endif
17611 +       ;; slab data (same as slab instructions but starting a little earlier).
17612 +       moveai          SRC_AN, #%hi(_data_protection_end)
17613 +       lea.4           SRC_AN, %lo(_data_protection_end)(SRC_AN)
17614 +       move.4          D_RANGE2_LO, SRC_AN
17615 +       move.4          D_RANGE2_HI, I_RANGE0_HI
17616 +
17617 +;; enable ranges
17618 +       ;; skip I_RANGE0_EN
17619 +       move.4          I_RANGE1_EN, #-1
17620 +       move.4          I_RANGE2_EN, #-1
17621 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17622 +       move.4          I_RANGE3_EN, #-1
17623 +#else
17624 +       move.4          I_RANGE3_EN, #0
17625 +#endif
17626 +       ;; skip D_RANGE0_EN or D_RANGE1_EN
17627 +       move.4          D_RANGE2_EN, #-1
17628 +       move.4          D_RANGE3_EN, #0
17629 +       move.4          D_RANGE4_EN, #0
17630 +#endif
17631 +
17632 +;
17633 +; If __ocm_free_begin is smaller than __ocm_free_end the
17634 +; setup OCM text and data ram banks properly
17635 +;
17636 +       moveai          DST_AN, #%hi(__ocm_free_begin)
17637 +       lea.4           TMP_DN, %lo(__ocm_free_begin)(DST_AN)
17638 +       moveai          DST_AN, #%hi(__ocm_free_end)
17639 +       lea.4           TMP2_DN, %lo(__ocm_free_end)(DST_AN)
17640 +       sub.4           #0, TMP2_DN, TMP_DN
17641 +       jmple.f         2f
17642 +       moveai          DST_AN, #%hi(__data_begin)
17643 +       lea.4           TMP_DN, %lo(__data_begin)(DST_AN)
17644 +       moveai          DST_AN, #%hi(OCMSTART)
17645 +       lea.4           TMP2_DN, %lo(OCMSTART)(DST_AN)
17646 +       sub.4           TMP_DN, TMP_DN, TMP2_DN
17647 +       lsr.4           TMP_DN, TMP_DN, #15
17648 +       lsl.4           TMP_DN, #1, TMP_DN
17649 +       moveai          DST_AN, #%hi(OCMC_BASE)
17650 +       add.4           OCMC_BANK_MASK(DST_AN), #-1, TMP_DN
17651 +       pipe_flush      0
17652 +2:
17653 +;
17654 +; Load .ocm_text
17655 +;
17656 +       moveai          DST_AN, #%hi(__ocm_text_run_end)
17657 +       lea.4           TMP_DN, %lo(__ocm_text_run_end)(DST_AN)
17658 +       moveai          DST_AN, #%hi(__ocm_text_run_begin)
17659 +       lea.4           DST_AN, %lo(__ocm_text_run_begin)(DST_AN)
17660 +       moveai          SRC_AN, #%hi(__ocm_text_load_begin)
17661 +       lea.4           SRC_AN, %lo(__ocm_text_load_begin)(SRC_AN)
17662 +       jmpt.t          2f
17663 +
17664 +1:      move.4          (DST_AN)4++, (SRC_AN)4++
17665 +
17666 +2:      sub.4           #0, DST_AN, TMP_DN
17667 +       jmpne.t         1b
17668 +;
17669 +; Load .syscall_text
17670 +;
17671 +       moveai          DST_AN, #%hi(__syscall_text_run_end)
17672 +       lea.4           TMP_DN, %lo(__syscall_text_run_end)(DST_AN)
17673 +       moveai          DST_AN, #%hi(__syscall_text_run_begin)
17674 +       lea.4           DST_AN, %lo(__syscall_text_run_begin)(DST_AN)
17675 +       moveai          SRC_AN, #%hi(__syscall_text_load_begin)
17676 +       lea.4           SRC_AN, %lo(__syscall_text_load_begin)(SRC_AN)
17677 +       jmpt.t          2f
17678 +
17679 +1:     move.4          (DST_AN)4++, (SRC_AN)4++
17680 +
17681 +2:     sub.4           #0, DST_AN, TMP_DN
17682 +       jmpne.t         1b
17683 +
17684 +;
17685 +; Load .ocm_data
17686 +;
17687 +       moveai          DST_AN, #%hi(__ocm_data_run_end)
17688 +       lea.4           TMP_DN, %lo(__ocm_data_run_end)(DST_AN)
17689 +       moveai          DST_AN, #%hi(__ocm_data_run_begin)
17690 +       lea.4           DST_AN, %lo(__ocm_data_run_begin)(DST_AN)
17691 +       moveai          SRC_AN, #%hi(__ocm_data_load_begin)
17692 +       lea.4           SRC_AN, %lo(__ocm_data_load_begin)(SRC_AN)
17693 +       jmpt.t          2f
17694 +
17695 +1:      move.4          (DST_AN)4++, (SRC_AN)4++
17696 +
17697 +2:      sub.4           #0, DST_AN, TMP_DN
17698 +       jmpne.t         1b
17699 +
17700 +; Clear .bss
17701 +;
17702 +       moveai          SRC_AN, #%hi(_ebss)
17703 +       lea.4           TMP_DN, %lo(_ebss)(SRC_AN)
17704 +       moveai          DST_AN, #%hi(_sbss)
17705 +       lea.4           DST_AN, %lo(_sbss)(DST_AN)
17706 +       jmpt.t          2f
17707 +
17708 +1:     move.4          (DST_AN)4++, #0
17709 +
17710 +2:     sub.4           #0, DST_AN, TMP_DN
17711 +       jmpne.t         1b
17712 +
17713 +; save our parameter to devtree (after clearing .bss)
17714 +       moveai          DST_AN, #%hi(devtree)
17715 +       lea.4           DST_AN, %lo(devtree)(DST_AN)
17716 +       move.4          (DST_AN), PARAM_DN
17717 +
17718 +       moveai          sp, #%hi(init_thread_union)
17719 +       lea.4           sp, %lo(init_thread_union)(sp)
17720 +       movei           TMP_DN, #ASM_THREAD_SIZE
17721 +       add.4           sp, sp, TMP_DN
17722 +       move.4          -4(sp)++, #0 ; nesting level = 0
17723 +       move.4          -4(sp)++, #1 ; KERNEL_THREAD
17724 +
17725 +;; ip3k-elf-gdb backend now sets scratchpad3 to 1 when either continue
17726 +;; or single step commands are issued. scratchpad3 is set to 0 when the
17727 +;; debugger detaches from the board.
17728 +       move.4          TMP_DN, scratchpad3
17729 +       lsl.4           TMP_DN, TMP_DN, #0x0
17730 +       jmpeq.f         _jump_to_start_kernel
17731 +_ok_to_set_break_points_in_linux:
17732 +;; THREAD_STALL
17733 +       move.4          mt_dbg_active_clr,#-1
17734 +;; stalling the threads isn't instantaneous.. need to flush the pipe.
17735 +       pipe_flush      0
17736 +       pipe_flush      0
17737 +
17738 +_jump_to_start_kernel:
17739 +       moveai          SRC_AN, #%hi(start_kernel)
17740 +       lea.4           SRC_AN, %lo(start_kernel)(SRC_AN)
17741 +       ret             SRC_AN
17742 --- /dev/null
17743 +++ b/arch/ubicom32/kernel/init_task.c
17744 @@ -0,0 +1,62 @@
17745 +/*
17746 + * arch/ubicom32/kernel/init_task.c
17747 + *   Ubicom32 architecture task initialization implementation.
17748 + *
17749 + * (C) Copyright 2009, Ubicom, Inc.
17750 + *
17751 + * This file is part of the Ubicom32 Linux Kernel Port.
17752 + *
17753 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17754 + * it and/or modify it under the terms of the GNU General Public License
17755 + * as published by the Free Software Foundation, either version 2 of the
17756 + * License, or (at your option) any later version.
17757 + *
17758 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17759 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17760 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17761 + * the GNU General Public License for more details.
17762 + *
17763 + * You should have received a copy of the GNU General Public License
17764 + * along with the Ubicom32 Linux Kernel Port.  If not,
17765 + * see <http://www.gnu.org/licenses/>.
17766 + *
17767 + * Ubicom32 implementation derived from (with many thanks):
17768 + *   arch/m68knommu
17769 + *   arch/blackfin
17770 + *   arch/parisc
17771 + */
17772 +#include <linux/mm.h>
17773 +#include <linux/module.h>
17774 +#include <linux/sched.h>
17775 +#include <linux/init.h>
17776 +#include <linux/init_task.h>
17777 +#include <linux/fs.h>
17778 +#include <linux/mqueue.h>
17779 +#include <linux/uaccess.h>
17780 +#include <asm/pgtable.h>
17781 +
17782 +///static struct fs_struct init_fs = INIT_FS;
17783 +static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
17784 +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17785 +struct mm_struct init_mm = INIT_MM(init_mm);
17786 +EXPORT_SYMBOL(init_mm);
17787 +
17788 +/*
17789 + * Initial task structure.
17790 + *
17791 + * All other task structs will be allocated on slabs in fork.c
17792 + */
17793 +struct task_struct init_task = INIT_TASK(init_task);
17794 +
17795 +EXPORT_SYMBOL(init_task);
17796 +
17797 +/*
17798 + * Initial thread structure.
17799 + *
17800 + * We need to make sure that this is 8192-byte aligned due to the
17801 + * way process stacks are handled. This is done by having a special
17802 + * "init_task" linker map entry..
17803 + */
17804 +union thread_union init_thread_union
17805 +       __attribute__((__section__(".data.init_task"))) =
17806 +               { INIT_THREAD_INFO(init_task) };
17807 --- /dev/null
17808 +++ b/arch/ubicom32/kernel/irq.c
17809 @@ -0,0 +1,597 @@
17810 +/*
17811 + * arch/ubicom32/kernel/irq.c
17812 + *   Ubicom32 architecture IRQ support.
17813 + *
17814 + * (C) Copyright 2009, Ubicom, Inc.
17815 + * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
17816 + *
17817 + * This file is part of the Ubicom32 Linux Kernel Port.
17818 + *
17819 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17820 + * it and/or modify it under the terms of the GNU General Public License
17821 + * as published by the Free Software Foundation, either version 2 of the
17822 + * License, or (at your option) any later version.
17823 + *
17824 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17825 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17826 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17827 + * the GNU General Public License for more details.
17828 + *
17829 + * You should have received a copy of the GNU General Public License
17830 + * along with the Ubicom32 Linux Kernel Port.  If not,
17831 + * see <http://www.gnu.org/licenses/>.
17832 + *
17833 + * Ubicom32 implementation derived from (with many thanks):
17834 + *   arch/m68knommu
17835 + *   arch/blackfin
17836 + *   arch/parisc
17837 + */
17838 +
17839 +#include <linux/types.h>
17840 +#include <linux/irq.h>
17841 +#include <linux/init.h>
17842 +#include <linux/kernel.h>
17843 +#include <linux/kernel_stat.h>
17844 +#include <linux/module.h>
17845 +#include <linux/seq_file.h>
17846 +#include <linux/proc_fs.h>
17847 +#include <asm/system.h>
17848 +#include <asm/traps.h>
17849 +#include <asm/ldsr.h>
17850 +#include <asm/ip5000.h>
17851 +#include <asm/machdep.h>
17852 +#include <asm/asm-offsets.h>
17853 +#include <asm/thread.h>
17854 +#include <asm/devtree.h>
17855 +
17856 +unsigned int irq_soft_avail;
17857 +static struct irqaction ubicom32_reserve_action[NR_IRQS];
17858 +
17859 +#if !defined(CONFIG_DEBUG_IRQMEASURE)
17860 +#define IRQ_DECLARE_MEASUREMENT
17861 +#define IRQ_MEASUREMENT_START()
17862 +#define IRQ_MEASUREMENT_END(irq)
17863 +#else
17864 +#define IRQ_DECLARE_MEASUREMENT \
17865 +       int __diff;             \
17866 +       unsigned int __tstart;
17867 +
17868 +#define IRQ_MEASUREMENT_START() \
17869 +       __tstart = UBICOM32_IO_TIMER->sysval;
17870 +
17871 +#define IRQ_MEASUREMENT_END(irq) \
17872 +       __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
17873 +       irq_measurement_update((irq), __diff);
17874 +
17875 +/*
17876 + * We keep track of the time spent in both irq_enter()
17877 + * and irq_exit().
17878 + */
17879 +#define IRQ_WEIGHT 32
17880 +
17881 +struct irq_measurement {
17882 +       volatile unsigned int min;
17883 +       volatile unsigned int avg;
17884 +       volatile unsigned int max;
17885 +};
17886 +
17887 +static DEFINE_SPINLOCK(irq_measurement_lock);
17888 +
17889 +/*
17890 + *  Add 1 in for softirq (irq_exit());
17891 + */
17892 +static struct irq_measurement irq_measurements[NR_IRQS + 1];
17893 +
17894 +/*
17895 + * irq_measurement_update()
17896 + *     Update an entry in the measurement array for this irq.
17897 + */
17898 +static void irq_measurement_update(int irq, int sample)
17899 +{
17900 +       struct irq_measurement *im = &irq_measurements[irq];
17901 +       spin_lock(&irq_measurement_lock);
17902 +       if ((im->min == 0) || (im->min > sample)) {
17903 +               im->min = sample;
17904 +       }
17905 +       if (im->max < sample) {
17906 +               im->max = sample;
17907 +       }
17908 +       im->avg = ((im->avg * (IRQ_WEIGHT - 1)) + sample) / IRQ_WEIGHT;
17909 +       spin_unlock(&irq_measurement_lock);
17910 +}
17911 +#endif
17912 +
17913 +/*
17914 + * irq_kernel_stack_check()
17915 + *     See if the kernel stack is within STACK_WARN of the end.
17916 + */
17917 +static void irq_kernel_stack_check(int irq, struct pt_regs *regs)
17918 +{
17919 +#ifdef CONFIG_DEBUG_STACKOVERFLOW
17920 +       unsigned long sp;
17921 +
17922 +       /*
17923 +        * Make sure that we are not close to the top of the stack and thus
17924 +        * can not really service this interrupt.
17925 +        */
17926 +       asm volatile (
17927 +               "and.4          %0, SP, %1 \n\t"
17928 +               : "=d" (sp)
17929 +               : "d" (THREAD_SIZE - 1)
17930 +               : "cc"
17931 +       );
17932 +
17933 +       if (sp < (sizeof(struct thread_info) + STACK_WARN)) {
17934 +               printk(KERN_WARNING
17935 +                       "cpu[%d]: possible overflow detected sp remain: %p, "
17936 +                      "irq: %d, regs: %p\n",
17937 +                       thread_get_self(), (void *)sp, irq, regs);
17938 +               dump_stack();
17939 +       }
17940 +
17941 +       if (sp < (sizeof(struct thread_info) + 16)) {
17942 +               THREAD_STALL;
17943 +       }
17944 +#endif
17945 +}
17946 +
17947 +/*
17948 + * irq_get_lsb()
17949 + *     Get the LSB set in value
17950 + */
17951 +static int irq_get_lsb(unsigned int value)
17952 +{
17953 +       static unsigned char irq_bits[8] = {
17954 +               3, 0, 1, 0, 2, 0, 1, 0
17955 +       };
17956 +       u32_t nextbit = 0;
17957 +
17958 +       value = (value >> nextbit) | (value << ((sizeof(value) * 8) - nextbit));
17959 +
17960 +       /*
17961 +        * It's unlikely that we find that we execute the body of this while
17962 +        * loop.  50% of the time we won't take this at all and then of the
17963 +        * cases where we do about 50% of those we only execute once.
17964 +        */
17965 +       if (!(value & 0xffff)) {
17966 +               nextbit += 0x10;
17967 +               value >>= 16;
17968 +       }
17969 +
17970 +       if (!(value & 0xff)) {
17971 +               nextbit += 0x08;
17972 +               value >>= 8;
17973 +       }
17974 +
17975 +       if (!(value & 0xf)) {
17976 +               nextbit += 0x04;
17977 +               value >>= 4;
17978 +       }
17979 +
17980 +       nextbit += irq_bits[value & 0x7];
17981 +       if (nextbit > 63) {
17982 +               panic("nextbit out of range: %d\n", nextbit);
17983 +       }
17984 +       return nextbit;
17985 +}
17986 +
17987 +/*
17988 + * ubicom32_reserve_handler()
17989 + *     Bogus handler associated with pre-reserved IRQ(s).
17990 + */
17991 +static irqreturn_t ubicom32_reserve_handler(int irq, void *dev_id)
17992 +{
17993 +       BUG();
17994 +       return IRQ_HANDLED;
17995 +}
17996 +
17997 +/*
17998 + * __irq_disable_vector()
17999 + *     Disable the interrupt by clearing the appropriate bit in the
18000 + *     LDSR Mask Register.
18001 + */
18002 +static void __irq_disable_vector(unsigned int irq)
18003 +{
18004 +       ldsr_disable_vector(irq);
18005 +}
18006 +
18007 +/*
18008 + * __irq_ack_vector()
18009 + *     Acknowledge the specific interrupt by clearing the associate bit in
18010 + *     hardware
18011 + */
18012 +static void __irq_ack_vector(unsigned int irq)
18013 +{
18014 +       if (irq < 32) {
18015 +               asm volatile ("move.4 INT_CLR0, %0" : : "d" (1 << irq));
18016 +       } else {
18017 +               asm volatile ("move.4 INT_CLR1, %0" : : "d" (1 << (irq - 32)));
18018 +       }
18019 +}
18020 +
18021 +/*
18022 + * __irq_enable_vector()
18023 + *     Clean and then enable the interrupt by setting the appropriate bit in
18024 + *     the LDSR Mask Register.
18025 + */
18026 +static void __irq_enable_vector(unsigned int irq)
18027 +{
18028 +       /*
18029 +        * Acknowledge, really clear the vector.
18030 +        */
18031 +       __irq_ack_vector(irq);
18032 +       ldsr_enable_vector(irq);
18033 +}
18034 +
18035 +/*
18036 + * __irq_mask_vector()
18037 + */
18038 +static void __irq_mask_vector(unsigned int irq)
18039 +{
18040 +       ldsr_mask_vector(irq);
18041 +}
18042 +
18043 +/*
18044 + * __irq_unmask_vector()
18045 + */
18046 +static void __irq_unmask_vector(unsigned int irq)
18047 +{
18048 +       ldsr_unmask_vector(irq);
18049 +}
18050 +
18051 +/*
18052 + * __irq_end_vector()
18053 + *     Called once an interrupt is completed (reset the LDSR mask).
18054 + */
18055 +static void __irq_end_vector(unsigned int irq)
18056 +{
18057 +       ldsr_unmask_vector(irq);
18058 +}
18059 +
18060 +#if defined(CONFIG_SMP)
18061 +/*
18062 + * __irq_set_affinity()
18063 + *     Set the cpu affinity for this interrupt.
18064 + *     affinity container allocated at boot
18065 + */
18066 +static void __irq_set_affinity(unsigned int irq, const struct cpumask *dest)
18067 +{
18068 +       smp_set_affinity(irq, dest);
18069 +       cpumask_copy(irq_desc[irq].affinity, dest);
18070 +}
18071 +#endif
18072 +
18073 +/*
18074 + * On-Chip Generic Interrupt function handling.
18075 + */
18076 +static struct irq_chip ubicom32_irq_chip = {
18077 +       .name           = "Ubicom32",
18078 +       .startup        = NULL,
18079 +       .shutdown       = NULL,
18080 +       .enable         = __irq_enable_vector,
18081 +       .disable        = __irq_disable_vector,
18082 +       .ack            = __irq_ack_vector,
18083 +       .mask           = __irq_mask_vector,
18084 +       .unmask         = __irq_unmask_vector,
18085 +       .end            = __irq_end_vector,
18086 +#if defined(CONFIG_SMP)
18087 +       .set_affinity   = __irq_set_affinity,
18088 +#endif
18089 +};
18090 +
18091 +/*
18092 + * do_IRQ()
18093 + *     Primary interface for handling IRQ() requests.
18094 + */
18095 +asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
18096 +{
18097 +       struct pt_regs *oldregs;
18098 +       struct thread_info *ti = current_thread_info();
18099 +
18100 +       IRQ_DECLARE_MEASUREMENT;
18101 +
18102 +       /*
18103 +        * Mark that we are inside of an interrupt and
18104 +        * that interrupts are disabled.
18105 +        */
18106 +       oldregs = set_irq_regs(regs);
18107 +       ti->interrupt_nesting++;
18108 +       trace_hardirqs_off();
18109 +       irq_kernel_stack_check(irq, regs);
18110 +
18111 +       /*
18112 +        * Start the interrupt sequence
18113 +        */
18114 +       irq_enter();
18115 +
18116 +       /*
18117 +        * Execute the IRQ handler and any pending SoftIRQ requests.
18118 +        */
18119 +       BUG_ON(!irqs_disabled());
18120 +       IRQ_MEASUREMENT_START();
18121 +       __do_IRQ(irq);
18122 +       IRQ_MEASUREMENT_END(irq);
18123 +       BUG_ON(!irqs_disabled());
18124 +
18125 +       /*
18126 +        * TODO: Since IRQ's are disabled when calling irq_exit()
18127 +        * modify Kconfig to set __ARCH_IRQ_EXIT_IRQS_DISABLED flag.
18128 +        * This will slightly improve performance by enabling
18129 +        * softirq handling to avoid disabling/disabled interrupts.
18130 +        */
18131 +       IRQ_MEASUREMENT_START();
18132 +       irq_exit();
18133 +       IRQ_MEASUREMENT_END(NR_IRQS);
18134 +       BUG_ON(!irqs_disabled());
18135 +
18136 +       /*
18137 +        * Outside of an interrupt (or nested exit).
18138 +        */
18139 +       set_irq_regs(oldregs);
18140 +       trace_hardirqs_on();
18141 +       ti->interrupt_nesting--;
18142 +}
18143 +
18144 +/*
18145 + * irq_soft_alloc()
18146 + *     Allocate a soft IRQ.
18147 + */
18148 +int irq_soft_alloc(unsigned int *soft)
18149 +{
18150 +       if (irq_soft_avail == 0) {
18151 +               printk(KERN_NOTICE "no soft irqs to allocate\n");
18152 +               return -EFAULT;
18153 +       }
18154 +
18155 +       *soft = irq_get_lsb(irq_soft_avail);
18156 +       irq_soft_avail &= ~(1 << *soft);
18157 +       return 0;
18158 +}
18159 +
18160 +/*
18161 + * ack_bad_irq()
18162 + *     Called to handle an bad irq request.
18163 + */
18164 +void ack_bad_irq(unsigned int irq)
18165 +{
18166 +       printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
18167 +       __irq_end_vector(irq);
18168 +}
18169 +
18170 +/*
18171 + * show_interrupts()
18172 + *     Return a string that displays the state of each of the interrupts.
18173 + */
18174 +int show_interrupts(struct seq_file *p, void *v)
18175 +{
18176 +       struct irqaction *ap;
18177 +       int irq = *((loff_t *) v);
18178 +       int j;
18179 +
18180 +       if (irq >= NR_IRQS) {
18181 +               return 0;
18182 +       }
18183 +
18184 +       if (irq == 0) {
18185 +               seq_puts(p, "           ");
18186 +               for_each_online_cpu(j) {
18187 +                       seq_printf(p, "CPU%d       ", j);
18188 +               }
18189 +               seq_putc(p, '\n');
18190 +       }
18191 +
18192 +       ap = irq_desc[irq].action;
18193 +       if (ap) {
18194 +               seq_printf(p, "%3d: ", irq);
18195 +               for_each_online_cpu(j) {
18196 +                       seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
18197 +               }
18198 +               seq_printf(p, "%14s  ", irq_desc[irq].chip->name);
18199 +               seq_printf(p, "%s", ap->name);
18200 +               for (ap = ap->next; ap; ap = ap->next) {
18201 +                       seq_printf(p, ", %s", ap->name);
18202 +               }
18203 +               seq_putc(p, '\n');
18204 +       }
18205 +       return 0;
18206 +}
18207 +
18208 +#if defined(CONFIG_DEBUG_IRQMEASURE)
18209 +static unsigned int irq_cycles_to_micro(unsigned int cycles, unsigned int frequency)
18210 +{
18211 +       unsigned int micro = (cycles / (frequency / 1000000));
18212 +       return micro;
18213 +}
18214 +
18215 +/*
18216 + * irq_measurement_show()
18217 + *     Print out the min, avg, max values for each IRQ
18218 + *
18219 + * By request, the max value is reset after each dump.
18220 + */
18221 +static int irq_measurement_show(struct seq_file *p, void *v)
18222 +{
18223 +       struct irqaction *ap;
18224 +       unsigned int freq = processor_frequency();
18225 +       int irq = *((loff_t *) v);
18226 +
18227 +
18228 +       if (irq == 0) {
18229 +               seq_puts(p, "\tmin\tavg\tmax\t(micro-seconds)\n");
18230 +       }
18231 +
18232 +       if (irq > NR_IRQS) {
18233 +               return 0;
18234 +       }
18235 +
18236 +       if (irq == NR_IRQS) {
18237 +               unsigned int min, avg, max;
18238 +               spin_lock(&irq_measurement_lock);
18239 +               min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18240 +               avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18241 +               max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18242 +               irq_measurements[irq].max = 0;
18243 +               spin_unlock(&irq_measurement_lock);
18244 +               seq_printf(p, "   \t%u\t%u\t%u\tsoftirq\n", min, avg, max);
18245 +               return 0;
18246 +       }
18247 +
18248 +       ap = irq_desc[irq].action;
18249 +       if (ap) {
18250 +               unsigned int min, avg, max;
18251 +               spin_lock(&irq_measurement_lock);
18252 +               min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18253 +               avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18254 +               max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18255 +               irq_measurements[irq].max = 0;
18256 +               spin_unlock(&irq_measurement_lock);
18257 +               seq_printf(p, "%2u:\t%u\t%u\t%u\t%s\n", irq, min, avg, max, ap->name);
18258 +       }
18259 +       return 0;
18260 +}
18261 +
18262 +static void *irq_measurement_start(struct seq_file *f, loff_t *pos)
18263 +{
18264 +       return (*pos <= NR_IRQS) ? pos : NULL;
18265 +}
18266 +
18267 +static void *irq_measurement_next(struct seq_file *f, void *v, loff_t *pos)
18268 +{
18269 +       (*pos)++;
18270 +       if (*pos > NR_IRQS)
18271 +               return NULL;
18272 +       return pos;
18273 +}
18274 +
18275 +static void irq_measurement_stop(struct seq_file *f, void *v)
18276 +{
18277 +       /* Nothing to do */
18278 +}
18279 +
18280 +static const struct seq_operations irq_measurement_seq_ops = {
18281 +       .start = irq_measurement_start,
18282 +       .next  = irq_measurement_next,
18283 +       .stop  = irq_measurement_stop,
18284 +       .show  = irq_measurement_show,
18285 +};
18286 +
18287 +static int irq_measurement_open(struct inode *inode, struct file *filp)
18288 +{
18289 +       return seq_open(filp, &irq_measurement_seq_ops);
18290 +}
18291 +
18292 +static const struct file_operations irq_measurement_fops = {
18293 +       .open           = irq_measurement_open,
18294 +       .read           = seq_read,
18295 +       .llseek         = seq_lseek,
18296 +       .release        = seq_release,
18297 +};
18298 +
18299 +static int __init irq_measurement_init(void)
18300 +{
18301 +       proc_create("irq_measurements", 0, NULL, &irq_measurement_fops);
18302 +       return 0;
18303 +}
18304 +module_init(irq_measurement_init);
18305 +#endif
18306 +
18307 +/*
18308 + * init_IRQ(void)
18309 + *     Initialize the on-chip IRQ subsystem.
18310 + */
18311 +void __init init_IRQ(void)
18312 +{
18313 +       int irq;
18314 +       struct devtree_node *p = NULL;
18315 +       struct devtree_node *iter = NULL;
18316 +       unsigned int mask = 0;
18317 +       unsigned int reserved = 0;
18318 +
18319 +       /*
18320 +        * Pull out the list of software interrupts that are avialable to
18321 +        * Linux and provide an allocation function for them.  The first
18322 +        * 24 interrupts of INT0 are software interrupts.
18323 +        */
18324 +       irq_soft_avail = 0;
18325 +       if (processor_interrupts(&irq_soft_avail, NULL) < 0) {
18326 +               printk(KERN_WARNING "No Soft IRQ(s) available\n");
18327 +       }
18328 +       irq_soft_avail &= ((1 << 24) - 1);
18329 +
18330 +       /*
18331 +        * Initialize all of the on-chip interrupt handling
18332 +        * to use a common set of interrupt functions.
18333 +        */
18334 +       for (irq = 0; irq < NR_IRQS; irq++) {
18335 +               irq_desc[irq].status = IRQ_DISABLED;
18336 +               irq_desc[irq].action = NULL;
18337 +               irq_desc[irq].depth = 1;
18338 +               set_irq_chip(irq, &ubicom32_irq_chip);
18339 +       }
18340 +
18341 +       /*
18342 +        * The sendirq of a devnode is not registered within Linux but instead
18343 +        * is used by the software I/O thread.  These interrupts are reserved.
18344 +        * The recvirq is used by Linux and registered by a device driver, these
18345 +        * are not reserved.
18346 +        *
18347 +        * recvirq(s) that are in the software interrupt range are not supposed
18348 +        * to be marked as reserved.  We track this while we scan the device
18349 +        * nodes.
18350 +        */
18351 +       p = devtree_find_next(&iter);
18352 +       while (p) {
18353 +               unsigned char sendirq, recvirq;
18354 +               devtree_irq(p, &sendirq, &recvirq);
18355 +
18356 +               /*
18357 +                * If the sendirq is valid, mark that irq as taken by the
18358 +                * devtree node.
18359 +                */
18360 +               if (sendirq < NR_IRQS) {
18361 +                       ubicom32_reserve_action[sendirq].handler =
18362 +                               ubicom32_reserve_handler;
18363 +                       ubicom32_reserve_action[sendirq].name = p->name;
18364 +                       irq_desc[sendirq].action =
18365 +                               &ubicom32_reserve_action[sendirq];
18366 +                       mask |= (1 << sendirq);
18367 +               }
18368 +
18369 +               /*
18370 +                * Track the relevant recieve IRQ(s)
18371 +                */
18372 +               if (recvirq < 24) {
18373 +                       mask |= (1 << recvirq);
18374 +               }
18375 +
18376 +               /*
18377 +                * Move to the next node.
18378 +                */
18379 +               p = devtree_find_next(&iter);
18380 +       }
18381 +
18382 +       /*
18383 +        * Remove these bits from the irq_soft_avail list and then use the
18384 +        * result as the list of pre-reserved IRQ(s).
18385 +        */
18386 +       reserved = ~irq_soft_avail & ~mask;
18387 +       for (irq = 0; irq < 24; irq++) {
18388 +               if ((reserved & (1 << irq))) {
18389 +                       ubicom32_reserve_action[irq].handler =
18390 +                               ubicom32_reserve_handler;
18391 +                       ubicom32_reserve_action[irq].name = "reserved";
18392 +                       irq_desc[irq].action = &ubicom32_reserve_action[irq];
18393 +               }
18394 +       }
18395 +
18396 +       /*
18397 +        * Initialize the LDSR which is the Ubicom32 programmable
18398 +        * interrupt controller.
18399 +        */
18400 +       ldsr_init();
18401 +
18402 +       /*
18403 +        * The Ubicom trap code needs a 2nd init after IRQ(s) are setup.
18404 +        */
18405 +       trap_init_interrupt();
18406 +}
18407 --- /dev/null
18408 +++ b/arch/ubicom32/kernel/ldsr.c
18409 @@ -0,0 +1,1185 @@
18410 +/*
18411 + * arch/ubicom32/kernel/ldsr.c
18412 + *   Ubicom32 architecture Linux Device Services Driver Interface
18413 + *
18414 + * (C) Copyright 2009, Ubicom, Inc.
18415 + *
18416 + * This file is part of the Ubicom32 Linux Kernel Port.
18417 + *
18418 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
18419 + * it and/or modify it under the terms of the GNU General Public License
18420 + * as published by the Free Software Foundation, either version 2 of the
18421 + * License, or (at your option) any later version.
18422 + *
18423 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18424 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18425 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
18426 + * the GNU General Public License for more details.
18427 + *
18428 + * You should have received a copy of the GNU General Public License
18429 + * along with the Ubicom32 Linux Kernel Port.  If not,
18430 + * see <http://www.gnu.org/licenses/>.
18431 + *
18432 + * Ubicom32 implementation derived from (with many thanks):
18433 + *   arch/m68knommu
18434 + *   arch/blackfin
18435 + *   arch/parisc
18436 + *
18437 + * NOTES:
18438 + *
18439 + * The LDSR is a programmable interrupt controller that is written in software.
18440 + * It emulates the behavior of an pic by fielding the interrupts, choosing a
18441 + * victim thread to take the interrupt and forcing that thread to take a context
18442 + * switch to the appropriate interrupt handler.
18443 + *
18444 + * Because traps are treated as just a special class of interrupts, the LDSR
18445 + * also handles the processing of traps.
18446 + *
18447 + * Because we compile Linux both UP and SMP, we need the LDSR to use
18448 + * architectural locking that is not "compiled out" when compiling UP.  For now,
18449 + * we use the single atomic bit lock.
18450 + */
18451 +#include <linux/kernel.h>
18452 +#include <linux/init.h>
18453 +#include <linux/sched.h>
18454 +#include <linux/interrupt.h>
18455 +#include <linux/irq.h>
18456 +#include <linux/profile.h>
18457 +#include <linux/clocksource.h>
18458 +#include <linux/types.h>
18459 +#include <linux/module.h>
18460 +#include <linux/cpumask.h>
18461 +#include <linux/bug.h>
18462 +#include <linux/delay.h>
18463 +#include <asm/ip5000.h>
18464 +#include <asm/atomic.h>
18465 +#include <asm/machdep.h>
18466 +#include <asm/asm-offsets.h>
18467 +#include <asm/traps.h>
18468 +#include <asm/thread.h>
18469 +#include <asm/range-protect.h>
18470 +
18471 +/*
18472 + * One can not print from the LDSR so the best we can do is
18473 + * check a condition and stall all of the threads.
18474 + */
18475 +
18476 +// #define DEBUG_LDSR 1
18477 +#if defined(DEBUG_LDSR)
18478 +#define DEBUG_ASSERT(cond) \
18479 +       if (!(cond)) { \
18480 +               THREAD_STALL; \
18481 +       }
18482 +#else
18483 +#define DEBUG_ASSERT(cond)
18484 +#endif
18485 +
18486 +/*
18487 + * Make global so that we can use it in the RFI code in assembly.
18488 + */
18489 +unsigned int ldsr_soft_irq_mask;
18490 +EXPORT_SYMBOL(ldsr_soft_irq_mask);
18491 +
18492 +static unsigned int ldsr_suspend_mask;
18493 +static unsigned int ldsr_soft_irq;
18494 +static unsigned int ldsr_stack_space[1024];
18495 +
18496 +static struct ldsr_register_bank {
18497 +       volatile unsigned int enabled0;
18498 +       volatile unsigned int enabled1;
18499 +       volatile unsigned int mask0;
18500 +       volatile unsigned int mask1;
18501 +       unsigned int total;
18502 +       unsigned int retry;
18503 +       unsigned int backout;
18504 +} ldsr_interrupt;
18505 +
18506 +/*
18507 + * Which thread/cpu are we?
18508 + */
18509 +static int ldsr_tid = -1;
18510 +
18511 +#if defined(CONFIG_IRQSTACKS)
18512 +/*
18513 + * per-CPU IRQ stacks (thread information and stack)
18514 + *
18515 + * NOTE: Do not use DEFINE_PER_CPU() as it makes it harder
18516 + * to find the location of ctx from assembly language.
18517 + */
18518 +union irq_ctx {
18519 +       struct thread_info      tinfo;
18520 +       u32                     stack[THREAD_SIZE/sizeof(u32)];
18521 +};
18522 +static union irq_ctx *percpu_irq_ctxs[NR_CPUS];
18523 +
18524 +/*
18525 + *  Storage for the interrupt stack.
18526 + */
18527 +#if !defined(CONFIG_IRQSTACKS_USEOCM)
18528 +static char percpu_irq_stacks[(NR_CPUS * THREAD_SIZE) + (THREAD_SIZE - 1)];
18529 +#else
18530 +/*
18531 + *  For OCM, the linker will ensure that space is allocated for the stack
18532 + *  see (vmlinux.lds.S)
18533 + */
18534 +static char percpu_irq_stacks[];
18535 +#endif
18536 +
18537 +#endif
18538 +
18539 +/*
18540 + * Save trap IRQ because we need to un-suspend if it gets set.
18541 + */
18542 +static unsigned int ldsr_trap_irq_mask;
18543 +static unsigned int ldsr_trap_irq;
18544 +
18545 +/*
18546 + * ret_from_interrupt_to_kernel
18547 + *     Just restore the context and do nothing else.
18548 + */
18549 +asmlinkage void ret_from_interrupt_to_kernel(void)__attribute__((naked));
18550 +
18551 +/*
18552 + * ret_from_interrupt_to_user
18553 + *     Call scheduler if needed. Just restore the context.
18554 + */
18555 +asmlinkage void ret_from_interrupt_to_user(void)__attribute__((naked));
18556 +
18557 +#ifdef DEBUG_LDSR
18558 +u32_t old_sp, old_pc, old_a0, old_a5, old_a3;
18559 +struct pt_regs copy_regs, *copy_save_area;
18560 +#endif
18561 +
18562 +int __user_mode(unsigned long sp)
18563 +{
18564 +
18565 +       u32_t saved_stack_base = sp & ~(ASM_THREAD_SIZE - 1);
18566 +#if defined(CONFIG_IRQSTACKS_USEOCM)
18567 +       if ((union irq_ctx *)saved_stack_base == percpu_irq_ctxs[smp_processor_id()]) {
18568 +               /*
18569 +                *  On the interrupt stack.
18570 +                */
18571 +               return 0;
18572 +       }
18573 +#endif
18574 +
18575 +       if (!(u32_t)current) {
18576 +               return 0;
18577 +       }
18578 +       return saved_stack_base != ((u32_t)current->stack);
18579 +}
18580 +
18581 +/*
18582 + * ldsr_lock_release()
18583 + *     Release the LDSR lock.
18584 + */
18585 +static void ldsr_lock_release(void)
18586 +{
18587 +       UBICOM32_UNLOCK(LDSR_LOCK_BIT);
18588 +}
18589 +
18590 +/*
18591 + * ldsr_lock_acquire()
18592 + *     Acquire the LDSR lock, spin if not available.
18593 + */
18594 +static void ldsr_lock_acquire(void)
18595 +{
18596 +       UBICOM32_LOCK(LDSR_LOCK_BIT);
18597 +}
18598 +
18599 +/*
18600 + * ldsr_thread_irq_disable()
18601 + *     Disable interrupts for the specified thread.
18602 + */
18603 +static void ldsr_thread_irq_disable(unsigned int tid)
18604 +{
18605 +       unsigned int mask = (1 << tid);
18606 +
18607 +       asm volatile (
18608 +       "       or.4    scratchpad1, scratchpad1, %0    \n\t"
18609 +               :
18610 +               : "d"(mask)
18611 +               : "cc"
18612 +       );
18613 +}
18614 +
18615 +/*
18616 + * ldsr_thread_get_interrupts()
18617 + *     Get the interrupt state for all threads.
18618 + */
18619 +static unsigned long ldsr_thread_get_interrupts(void)
18620 +{
18621 +       unsigned long ret = 0;
18622 +       asm volatile (
18623 +       "       move.4  %0, scratchpad1 \n\t"
18624 +               : "=r" (ret)
18625 +               :
18626 +       );
18627 +       return ret;
18628 +}
18629 +
18630 +/*
18631 + * ldsr_emulate_and_run()
18632 + *     Emulate the instruction and then set the thread to run.
18633 + */
18634 +static void ldsr_emulate_and_run(unsigned int tid)
18635 +{
18636 +       unsigned int thread_mask = (1 << tid);
18637 +       u32_t write_csr = (tid << 15) | (1 << 14);
18638 +
18639 +       /*
18640 +        * Emulate the unaligned access.
18641 +        */
18642 +       unaligned_emulate(tid);
18643 +
18644 +       /*
18645 +        * Get the thread back in a running state.
18646 +        */
18647 +       asm volatile (
18648 +       "       setcsr  %0                      \n\t"
18649 +       "       setcsr_flush 0                  \n\t"
18650 +       "       move.4  trap_cause, #0          \n\t" /* Clear the trap cause
18651 +                                                      * register */
18652 +       "       setcsr  #0                      \n\t"
18653 +       "       setcsr_flush 0                  \n\t"
18654 +       "       move.4  mt_dbg_active_set, %1   \n\t" /* Activate thread even if
18655 +                                                      * in dbg/fault state */
18656 +       "       move.4  mt_active_set, %1       \n\t" /* Restart target
18657 +                                                      * thread. */
18658 +               :
18659 +               : "r" (write_csr), "d" (thread_mask)
18660 +               : "cc"
18661 +       );
18662 +       thread_enable_mask(thread_mask);
18663 +}
18664 +
18665 +/*
18666 + * ldsr_preemptive_context_save()
18667 + *     save thread context from another hardware thread.  The other thread must
18668 + *     be stalled.
18669 + */
18670 +static inline void ldsr_preemptive_context_save(u32_t thread,
18671 +                                               struct pt_regs *regs)
18672 +{
18673 +       /*
18674 +        * Save the current state of the specified thread
18675 +        */
18676 +       asm volatile (
18677 +       "       move.4  a3, %0                                  \n\t"
18678 +
18679 +               /* set src1 from the target thread */
18680 +       "       move.4  csr, %1                                 \n\t"
18681 +       "       setcsr_flush 0                                  \n\t"
18682 +       "       setcsr_flush 0                                  \n\t"
18683 +
18684 +               /* copy state from the other thread */
18685 +       "       move.4  "D(PT_D0)"(a3), d0                      \n\t"
18686 +       "       move.4  "D(PT_D1)"(a3), d1                      \n\t"
18687 +       "       move.4  "D(PT_D2)"(a3), d2                      \n\t"
18688 +       "       move.4  "D(PT_D3)"(a3), d3                      \n\t"
18689 +       "       move.4  "D(PT_D4)"(a3), d4                      \n\t"
18690 +       "       move.4  "D(PT_D5)"(a3), d5                      \n\t"
18691 +       "       move.4  "D(PT_D6)"(a3), d6                      \n\t"
18692 +       "       move.4  "D(PT_D7)"(a3), d7                      \n\t"
18693 +       "       move.4  "D(PT_D8)"(a3), d8                      \n\t"
18694 +       "       move.4  "D(PT_D9)"(a3), d9                      \n\t"
18695 +       "       move.4  "D(PT_D10)"(a3), d10                    \n\t"
18696 +       "       move.4  "D(PT_D11)"(a3), d11                    \n\t"
18697 +       "       move.4  "D(PT_D12)"(a3), d12                    \n\t"
18698 +       "       move.4  "D(PT_D13)"(a3), d13                    \n\t"
18699 +       "       move.4  "D(PT_D14)"(a3), d14                    \n\t"
18700 +       "       move.4  "D(PT_D15)"(a3), d15                    \n\t"
18701 +       "       move.4  "D(PT_A0)"(a3), a0                      \n\t"
18702 +       "       move.4  "D(PT_A1)"(a3), a1                      \n\t"
18703 +       "       move.4  "D(PT_A2)"(a3), a2                      \n\t"
18704 +       "       move.4  "D(PT_A3)"(a3), a3                      \n\t"
18705 +       "       move.4  "D(PT_A4)"(a3), a4                      \n\t"
18706 +       "       move.4  "D(PT_A5)"(a3), a5                      \n\t"
18707 +       "       move.4  "D(PT_A6)"(a3), a6                      \n\t"
18708 +       "       move.4  "D(PT_SP)"(a3), a7                      \n\t"
18709 +       "       move.4  "D(PT_ACC0HI)"(a3), acc0_hi             \n\t"
18710 +       "       move.4  "D(PT_ACC0LO)"(a3), acc0_lo             \n\t"
18711 +       "       move.4  "D(PT_MAC_RC16)"(a3), mac_rc16          \n\t"
18712 +       "       move.4  "D(PT_ACC1HI)"(a3), acc1_hi             \n\t"
18713 +       "       move.4  "D(PT_ACC1LO)"(a3), acc1_lo             \n\t"
18714 +       "       move.4  "D(PT_SOURCE3)"(a3), source3            \n\t"
18715 +       "       move.4  "D(PT_INST_CNT)"(a3), inst_cnt          \n\t"
18716 +       "       move.4  "D(PT_CSR)"(a3), csr                    \n\t"
18717 +       "       move.4  "D(PT_DUMMY_UNUSED)"(a3), #0            \n\t"
18718 +       "       move.4  "D(PT_INT_MASK0)"(a3), int_mask0        \n\t"
18719 +       "       move.4  "D(PT_INT_MASK1)"(a3), int_mask1        \n\t"
18720 +       "       move.4  "D(PT_TRAP_CAUSE)"(a3), trap_cause      \n\t"
18721 +       "       move.4  "D(PT_PC)"(a3), pc                      \n\t"
18722 +       "       move.4  "D(PT_PREVIOUS_PC)"(a3), previous_pc    \n\t"
18723 +               /* disable csr thread select */
18724 +       "       movei   csr, #0                                 \n\t"
18725 +       "       setcsr_flush 0                                  \n\t"
18726 +       :
18727 +       : "r" (regs->dn), "d" ((thread << 9) | (1 << 8))
18728 +       : "a3"
18729 +       );
18730 +}
18731 +
18732 +/*
18733 + * ldsr_rotate_threads()
18734 + *     Simple round robin algorithm for choosing the next cpu
18735 + */
18736 +static int ldsr_rotate_threads(unsigned long cpus)
18737 +{
18738 +       static unsigned char ldsr_bits[8] = {
18739 +               3, 0, 1, 0, 2, 0, 1, 0
18740 +       };
18741 +
18742 +       static int nextbit;
18743 +       int thisbit;
18744 +
18745 +       /*
18746 +        * Move the interrupts down so that we consider interrupts from where
18747 +        * we left off, then take the interrupts we would lose and move them
18748 +        * to the top half of the interrupts value.
18749 +        */
18750 +       cpus = (cpus >> nextbit) | (cpus << ((sizeof(cpus) * 8) - nextbit));
18751 +
18752 +       /*
18753 +        * 50% of the time we won't take this at all and then of the cases where
18754 +        * we do about 50% of those we only execute once.
18755 +        */
18756 +       if (!(cpus & 0xffff)) {
18757 +               nextbit += 16;
18758 +               cpus >>= 16;
18759 +       }
18760 +
18761 +       if (!(cpus & 0xff)) {
18762 +               nextbit += 8;
18763 +               cpus >>= 8;
18764 +       }
18765 +
18766 +       if (!(cpus & 0xf)) {
18767 +               nextbit += 4;
18768 +               cpus >>= 4;
18769 +       }
18770 +
18771 +       nextbit += ldsr_bits[cpus & 0x7];
18772 +       thisbit = (nextbit & ((sizeof(cpus) * 8) - 1));
18773 +       nextbit = (thisbit + 1) & ((sizeof(cpus) * 8) - 1);
18774 +       DEBUG_ASSERT(thisbit < THREAD_ARCHITECTURAL_MAX);
18775 +       return thisbit;
18776 +}
18777 +
18778 +/*
18779 + * ldsr_rotate_interrupts()
18780 + *     Get rotating next set bit value.
18781 + */
18782 +static int ldsr_rotate_interrupts(unsigned long long interrupts)
18783 +{
18784 +       static unsigned char ldsr_bits[8] = {
18785 +               3, 0, 1, 0, 2, 0, 1, 0
18786 +       };
18787 +
18788 +       static int nextbit;
18789 +       int thisbit;
18790 +
18791 +       /*
18792 +        * Move the interrupts down so that we consider interrupts from where
18793 +        * we left off, then take the interrupts we would lose and move them
18794 +        * to the top half of the interrupts value.
18795 +        */
18796 +       interrupts = (interrupts >> nextbit) |
18797 +               (interrupts << ((sizeof(interrupts) * 8) - nextbit));
18798 +
18799 +       /*
18800 +        * 50% of the time we won't take this at all and then of the cases where
18801 +        * we do about 50% of those we only execute once.
18802 +        */
18803 +       if (!(interrupts & 0xffffffff)) {
18804 +               nextbit += 32;
18805 +               interrupts >>= 32;
18806 +       }
18807 +
18808 +       if (!(interrupts & 0xffff)) {
18809 +               nextbit += 16;
18810 +               interrupts >>= 16;
18811 +       }
18812 +
18813 +       if (!(interrupts & 0xff)) {
18814 +               nextbit += 8;
18815 +               interrupts >>= 8;
18816 +       }
18817 +
18818 +       if (!(interrupts & 0xf)) {
18819 +               nextbit += 4;
18820 +               interrupts >>= 4;
18821 +       }
18822 +
18823 +       nextbit += ldsr_bits[interrupts & 0x7];
18824 +       thisbit = (nextbit & ((sizeof(interrupts) * 8) - 1));
18825 +       nextbit = (thisbit + 1) & ((sizeof(interrupts) * 8) - 1);
18826 +
18827 +       DEBUG_ASSERT(thisbit < (sizeof(interrupts) * 8));
18828 +       return thisbit;
18829 +}
18830 +
18831 +/*
18832 + * ldsr_backout_or_irq()
18833 + *
18834 + * One way or the other this interrupt is not being
18835 + * processed, make sure that it is reset.  We are
18836 + * not going to call irq_end_vector() so unmask the
18837 + * interrupt.
18838 + */
18839 +static void ldsr_backout_of_irq(int vector, unsigned long tid_mask)
18840 +{
18841 +#if defined(CONFIG_SMP)
18842 +       if (unlikely(vector == smp_ipi_irq)) {
18843 +               smp_reset_ipi(tid_mask);
18844 +       }
18845 +#endif
18846 +       ldsr_unmask_vector(vector);
18847 +       ldsr_interrupt.backout++;
18848 +}
18849 +
18850 +#if defined(CONFIG_IRQSTACKS)
18851 +/*
18852 + * ldsr_choose_savearea_and_returnvec()
18853 + *     Test our current state (user, kernel, interrupt) and set things up.
18854 + *
18855 + * This version of the function uses 3 stacks and nests interrupts
18856 + * on the interrupt stack.
18857 + */
18858 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
18859 +{
18860 +       struct pt_regs *save_area;
18861 +       u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
18862 +       struct thread_info * ti= (struct thread_info *)sw_ksp[tid];
18863 +
18864 +#if defined(CONFIG_SMP)
18865 +       union irq_ctx *icp = percpu_irq_ctxs[tid];
18866 +#else
18867 +       union irq_ctx *icp = percpu_irq_ctxs[0];
18868 +#endif
18869 +
18870 +       if (masked_linux_sp == (u32_t)icp) {
18871 +               /*
18872 +                * Fault/Interrupt occurred while on the interrupt stack.
18873 +                */
18874 +               save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
18875 +               *pvec = (u32_t)(&ret_from_interrupt_to_kernel);
18876 +       } else {
18877 +               /*
18878 +                *  Fault/Interrupt occurred while on user/kernel stack.  This is a new
18879 +                *  first use of the interrupt stack.
18880 +                */
18881 +               save_area = (struct pt_regs *) ((char *)icp + sizeof(icp->stack) - sizeof(struct pt_regs) - 8);
18882 +               if (masked_linux_sp == (u32_t)ti) {
18883 +                       *pvec  = (u32_t)(&ret_from_interrupt_to_kernel);
18884 +               } else {
18885 +                       *pvec  = (u32_t)(&ret_from_interrupt_to_user);
18886 +               }
18887 +
18888 +               /*
18889 +                * Because the softirq code will execute on the "interrupt" stack, we
18890 +                * need to maintain the knowledge of what "task" was executing on the
18891 +                * cpu.  This is done by copying the thread_info->task from the cpu
18892 +                * we are about to context switch into the interrupt contexts thread_info
18893 +                * structure.
18894 +                */
18895 +               icp->tinfo.task = ti->task;
18896 +               icp->tinfo.preempt_count =
18897 +                               (icp->tinfo.preempt_count & ~SOFTIRQ_MASK) |
18898 +                               (ti->preempt_count & SOFTIRQ_MASK);
18899 +               icp->tinfo.interrupt_nesting = 0;
18900 +       }
18901 +       save_area->nesting_level = icp->tinfo.interrupt_nesting;
18902 +       return save_area;
18903 +}
18904 +
18905 +#else
18906 +/*
18907 + * ldsr_choose_savearea_and_returnvec()
18908 + *     Test our current state (user, kernel, interrupt) and set things up.
18909 + *
18910 + * The version of the function uses just the user & kernel stack and
18911 + * nests interrupts on the existing kernel stack.
18912 + */
18913 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
18914 +{
18915 +       struct pt_regs *save_area;
18916 +       u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
18917 +       struct thread_info *ti = (struct thread_info *)sw_ksp[tid];
18918 +
18919 +       if (masked_linux_sp == (u32_t)ti) {
18920 +               /*
18921 +                * Fault/Interrupt occurred while on the kernel stack.
18922 +                */
18923 +               save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
18924 +               *pvec = (u32_t) (&ret_from_interrupt_to_kernel);
18925 +       } else {
18926 +               /*
18927 +                *  Fault/Interrupt occurred while on user stack.
18928 +                */
18929 +               ti->interrupt_nesting = 0;
18930 +               save_area = (struct pt_regs *)((u32_t)ti + THREAD_SIZE - sizeof(struct pt_regs) - 8);
18931 +               *pvec  = (u32_t) (&ret_from_interrupt_to_user);
18932 +       }
18933 +       save_area->nesting_level = ti->interrupt_nesting;
18934 +       return save_area;
18935 +}
18936 +#endif
18937 +
18938 +/*
18939 + * ldsr_ctxsw_thread()
18940 + *     Context switch a mainline thread to execute do_IRQ() for the specified
18941 + *     vector.
18942 + */
18943 +static void ldsr_ctxsw_thread(int vector, thread_t tid)
18944 +{
18945 +       u32_t linux_sp;
18946 +       u32_t return_vector;
18947 +       struct pt_regs *save_area, *regs;
18948 +       u32_t thread_mask = (1 << tid);
18949 +       u32_t read_csr = ((tid << 9) | (1 << 8));
18950 +       u32_t write_csr = (tid << 15) | (1 << 14);
18951 +       u32_t interrupt_vector = (u32_t)(&do_IRQ);
18952 +
18953 +       unsigned int frame_type = UBICOM32_FRAME_TYPE_INTERRUPT;
18954 +
18955 +
18956 +       DEBUG_ASSERT(!thread_is_enabled(tid));
18957 +
18958 +       /*
18959 +        * Acquire the necessary global and per thread locks for tid.
18960 +        * As a side effect, we ensure that the thread has not trapped
18961 +        * and return true if it has.
18962 +        */
18963 +       if (unlikely(thread_is_trapped(tid))) {
18964 +               /*
18965 +                * Read the trap cause, the sp and clear the MT_TRAP bits.
18966 +                */
18967 +               unsigned int cause;
18968 +               asm volatile (
18969 +               "       setcsr  %3              \n\t"
18970 +               "       setcsr_flush 0          \n\t"
18971 +               "       setcsr_flush 0          \n\t"
18972 +               "       move.4  %0, TRAP_CAUSE  \n\t"
18973 +               "       move.4  %1, SP          \n\t"
18974 +               "       setcsr  #0              \n\t"
18975 +               "       setcsr_flush 0          \n\t"
18976 +               "       move.4  MT_BREAK_CLR, %2\n\t"
18977 +               "       move.4  MT_TRAP_CLR, %2 \n\t"
18978 +                       : "=&r" (cause), "=&r" (linux_sp)
18979 +                       : "r" (thread_mask), "m" (read_csr)
18980 +               );
18981 +
18982 +               ldsr_backout_of_irq(vector, (1 << tid));
18983 +
18984 +#if !defined(CONFIG_UNALIGNED_ACCESS_DISABLED)
18985 +               /*
18986 +                * See if the unaligned trap handler can deal with this.
18987 +                * If so, emulate the instruction and then just restart
18988 +                * the thread.
18989 +                */
18990 +               if (unaligned_only(cause)) {
18991 +#if defined(CONFIG_UNALIGNED_ACCESS_USERSPACE_ONLY)
18992 +                       /*
18993 +                        * Check if this is a kernel stack if so we will not
18994 +                        * handle the trap
18995 +                        */
18996 +                       u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
18997 +                       if ((masked_linux_sp != (u32_t)sw_ksp[tid]) &&
18998 +                           unaligned_only(cause)) {
18999 +                               ldsr_emulate_and_run(tid);
19000 +                               return;
19001 +                       }
19002 +#else
19003 +                       ldsr_emulate_and_run(tid);
19004 +                       return;
19005 +#endif
19006 +
19007 +               }
19008 +#endif
19009 +
19010 +               interrupt_vector = (u32_t)(&trap_handler);
19011 +               frame_type = UBICOM32_FRAME_TYPE_TRAP;
19012 +       } else {
19013 +               /*
19014 +                * Read the target thread's SP
19015 +                */
19016 +               asm volatile (
19017 +               "       setcsr  %1              \n\t"
19018 +               "       setcsr_flush 0          \n\t"
19019 +               "       setcsr_flush 0          \n\t"
19020 +               "       move.4  %0, SP          \n\t"
19021 +               "       setcsr  #0              \n\t"
19022 +               "       setcsr_flush 0          \n\t"
19023 +                       : "=m" (linux_sp)
19024 +                       : "m" (read_csr)
19025 +               );
19026 +       }
19027 +
19028 +       /*
19029 +        * We are delivering an interrupt, count it.
19030 +        */
19031 +       ldsr_interrupt.total++;
19032 +
19033 +       /*
19034 +        * At this point, we will definitely force this thread to
19035 +        * a new context, show its interrupts as disabled.
19036 +        */
19037 +       ldsr_thread_irq_disable(tid);
19038 +
19039 +       /*
19040 +        * Test our current state (user, kernel, interrupt).  Save the
19041 +        * appropriate data and setup for the return.
19042 +        */
19043 +       save_area = ldsr_choose_savearea_and_returnvec(tid, linux_sp, &return_vector);
19044 +
19045 +       /*
19046 +        *  The pt_regs (save_area) contains the type of thread that we are dealing
19047 +        *  with (KERNEL/NORMAL) and is copied into each pt_regs area.  We get this
19048 +        *  from the current tasks kernel pt_regs area that always exists at the
19049 +        *  top of the kernel stack.
19050 +        */
19051 +       regs = (struct pt_regs *)((u32_t)sw_ksp[tid] + THREAD_SIZE - sizeof(struct pt_regs) - 8);
19052 +       save_area->thread_type = regs->thread_type;
19053 +
19054 +       /*
19055 +        * Preserve the context of the Linux thread.
19056 +        */
19057 +       ldsr_preemptive_context_save(tid, save_area);
19058 +
19059 +       /*
19060 +        * Load the fram_type into the save_area.
19061 +        */
19062 +       save_area->frame_type = frame_type;
19063 +
19064 +#ifdef CONFIG_STOP_ON_TRAP
19065 +       /*
19066 +        * Before we get backtrace and showing stacks working well, it sometimes
19067 +        * helps to enter the debugger when a trap occurs before we change the
19068 +        * thread to handle the fault.  This optional code causes all threads to
19069 +        * stop on every trap frame.  One assumes that GDB connected via the
19070 +        * mailbox interface will be used to recover from this state.
19071 +        */
19072 +       if (frame_type == UBICOM32_FRAME_TYPE_TRAP) {
19073 +               THREAD_STALL;
19074 +       }
19075 +#endif
19076 +
19077 +#ifdef DEBUG_LDSR
19078 +       copy_regs = *save_area;
19079 +       copy_save_area = save_area;
19080 +
19081 +       old_a0 = save_area->an[0];
19082 +       old_a3 = save_area->an[3];
19083 +       old_sp = save_area->an[7];
19084 +       old_a5 = save_area->an[5];
19085 +       old_pc = save_area->pc;
19086 +#endif
19087 +
19088 +       /*
19089 +        * Now we have to switch the kernel thread to run do_IRQ function.
19090 +        *      Set pc to do_IRQ
19091 +        *      Set d0 to vector
19092 +        *      Set d1 to save_area.
19093 +        *      Set a5 to the proper return vector.
19094 +        */
19095 +       asm volatile (
19096 +       "       setcsr  %0                      \n\t"
19097 +       "       setcsr_flush 0                  \n\t"
19098 +       "       move.4  d0, %5                  \n\t" /* d0 = 0 vector # */
19099 +       "       move.4  d1, %1                  \n\t" /* d1 = save_area */
19100 +       "       move.4  sp, %1                  \n\t" /* sp = save_area */
19101 +       "       move.4  a5, %2                  \n\t" /* a5 = return_vector */
19102 +       "       move.4  pc, %3                  \n\t" /* pc = do_IRQ routine. */
19103 +       "       move.4  trap_cause, #0          \n\t" /* Clear the trap cause
19104 +                                                      * register */
19105 +       "       setcsr  #0                      \n\t"
19106 +       "       setcsr_flush 0                  \n\t"
19107 +       "       enable_kernel_ranges %4         \n\t"
19108 +       "       move.4  mt_dbg_active_set, %4   \n\t" /* Activate thread even if
19109 +                                                      * in dbg/fault state */
19110 +       "       move.4  mt_active_set, %4       \n\t" /* Restart target
19111 +                                                      * thread. */
19112 +               :
19113 +               : "r" (write_csr), "r" (save_area),
19114 +                 "r" (return_vector), "r" (interrupt_vector),
19115 +                 "d" (thread_mask), "r" (vector)
19116 +               : "cc"
19117 +       );
19118 +       thread_enable_mask(thread_mask);
19119 +}
19120 +
19121 +/*
19122 + * ldsr_deliver_interrupt()
19123 + *     Deliver the interrupt to one of the threads or all of the threads.
19124 + */
19125 +static void ldsr_deliver_interrupt(int vector,
19126 +                                  unsigned long deliver_to,
19127 +                                  int all)
19128 +{
19129 +       unsigned long disabled_threads;
19130 +       unsigned long possible_threads;
19131 +       unsigned long trapped_threads;
19132 +       unsigned long global_locks;
19133 +
19134 +       /*
19135 +        * Disable all of the threads that we might want to send
19136 +        * this interrupt to.
19137 +        */
19138 +retry:
19139 +       DEBUG_ASSERT(deliver_to);
19140 +       thread_disable_mask(deliver_to);
19141 +
19142 +       /*
19143 +        * If any threads are in the trap state, we have to service the
19144 +        * trap for those threads first.
19145 +        */
19146 +       asm volatile (
19147 +               "move.4 %0, MT_TRAP             \n\t"
19148 +               : "=r" (trapped_threads)
19149 +               :
19150 +       );
19151 +
19152 +       trapped_threads &= deliver_to;
19153 +       if (unlikely(trapped_threads)) {
19154 +               /*
19155 +                * all traps will be handled, so clear the trap bit before restarting any threads
19156 +                */
19157 +               ubicom32_clear_interrupt(ldsr_trap_irq);
19158 +
19159 +               /*
19160 +                * Let the remaining untrapped threads, continue.
19161 +                */
19162 +               deliver_to &= ~trapped_threads;
19163 +               if (deliver_to) {
19164 +                       thread_enable_mask(deliver_to);
19165 +               }
19166 +
19167 +               /*
19168 +                * For the trapped threads force them to handle
19169 +                * a trap.
19170 +                */
19171 +               while (trapped_threads) {
19172 +                       unsigned long which = ffz(~trapped_threads);
19173 +                       trapped_threads &= ~(1 << which);
19174 +                       ldsr_ctxsw_thread(vector, which);
19175 +               }
19176 +               return;
19177 +       }
19178 +
19179 +       /*
19180 +        * Can we deliver an interrupt to any of the threads?
19181 +        */
19182 +       disabled_threads = ldsr_thread_get_interrupts();
19183 +       possible_threads = deliver_to & ~disabled_threads;
19184 +       if (unlikely(!possible_threads)) {
19185 +#if defined(CONFIG_SMP)
19186 +               /*
19187 +                * In the SMP case, we can not wait because 1 cpu might be
19188 +                * sending an IPI to another cpu which is currently blocked.
19189 +                * The only way to ensure IPI delivery is to backout and
19190 +                * keep trying.  For SMP, we don't sleep until the interrupts
19191 +                * are delivered.
19192 +                */
19193 +               thread_enable_mask(deliver_to);
19194 +               ldsr_backout_of_irq(vector, deliver_to);
19195 +               return;
19196 +#else
19197 +               /*
19198 +                * In the UP case, we have nothing to do so we should wait.
19199 +                *
19200 +                * Since the INT_MASK0 and INT_MASK1 are "re-loaded" before we
19201 +                * suspend in the outer loop, we do not need to save them here.
19202 +                *
19203 +                * We test that we were awakened for our specific interrupts
19204 +                * because the ldsr mask/unmask operations will force the ldsr
19205 +                * awake even if the interrupt on the mainline thread is not
19206 +                * completed.
19207 +                */
19208 +               unsigned int scratch = 0;
19209 +               thread_enable_mask(deliver_to);
19210 +               asm volatile (
19211 +               "       move.4  INT_MASK0, %1           \n\t"
19212 +               "       move.4  INT_MASK1, #0           \n\t"
19213 +
19214 +               "1:     suspend                         \n\t"
19215 +               "       move.4  %0, INT_STAT0           \n\t"
19216 +               "       and.4   %0, %0, %1              \n\t"
19217 +               "       jmpeq.f 1b                      \n\t"
19218 +
19219 +               "       move.4  INT_CLR0, %2            \n\t"
19220 +                       : "+r" (scratch)
19221 +                       : "d" (ldsr_suspend_mask), "r" (ldsr_soft_irq_mask)
19222 +                       : "cc"
19223 +               );
19224 +
19225 +               /*
19226 +                * This delay is sized to coincide with the time it takes a
19227 +                * thread to complete the exit (see return_from_interrupt).
19228 +                */
19229 +               ldsr_interrupt.retry++;
19230 +               __delay(10);
19231 +               goto retry;
19232 +#endif
19233 +       }
19234 +
19235 +       /*
19236 +        * If any of the global locks are held, we can not deliver any
19237 +        * interrupts, we spin delay(10) and then try again.  If our
19238 +        * spinning becomes a bottle neck, we will need to suspend but for
19239 +        * now lets just spin.
19240 +        */
19241 +       asm volatile (
19242 +               "move.4 %0, scratchpad1         \n\t"
19243 +               : "=r" (global_locks)
19244 +               :
19245 +       );
19246 +       if (unlikely(global_locks & 0xffff0000)) {
19247 +               thread_enable_mask(deliver_to);
19248 +
19249 +               /*
19250 +                * This delay is sized to coincide with the average time it
19251 +                * takes a thread to release a global lock.
19252 +                */
19253 +               ldsr_interrupt.retry++;
19254 +               __delay(10);
19255 +               goto retry;
19256 +       }
19257 +
19258 +       /*
19259 +        * Deliver to one cpu.
19260 +        */
19261 +       if (!all) {
19262 +               /*
19263 +                * Find our victim and then enable everyone else.
19264 +                */
19265 +               unsigned long victim = ldsr_rotate_threads(possible_threads);
19266 +               DEBUG_ASSERT((deliver_to & (1 << victim)));
19267 +               DEBUG_ASSERT((possible_threads & (1 << victim)));
19268 +
19269 +               deliver_to &= ~(1 << victim);
19270 +               if (deliver_to) {
19271 +                       thread_enable_mask(deliver_to);
19272 +               }
19273 +               ldsr_ctxsw_thread(vector, victim);
19274 +               return;
19275 +       }
19276 +
19277 +       /*
19278 +        * If we can't deliver to some threads, wake them
19279 +        * back up and reset things to deliver to them.
19280 +        */
19281 +       deliver_to &= ~possible_threads;
19282 +       if (unlikely(deliver_to)) {
19283 +               thread_enable_mask(deliver_to);
19284 +               ldsr_backout_of_irq(vector, deliver_to);
19285 +       }
19286 +
19287 +       /*
19288 +        * Deliver to all possible threads(s).
19289 +        */
19290 +       while (possible_threads) {
19291 +               unsigned long victim = ffz(~possible_threads);
19292 +               possible_threads &= ~(1 << victim);
19293 +               ldsr_ctxsw_thread(vector, victim);
19294 +       }
19295 +}
19296 +
19297 +/*
19298 + * ldsr_thread()
19299 + *     This thread acts as the interrupt controller for Linux.
19300 + */
19301 +static void ldsr_thread(void *arg)
19302 +{
19303 +       int stat0;
19304 +       int stat1;
19305 +       int interrupt0;
19306 +       int interrupt1;
19307 +       long long interrupts;
19308 +       unsigned long cpus;
19309 +
19310 +#if !defined(CONFIG_SMP)
19311 +       /*
19312 +        * In a non-smp configuration, we can not use the cpu(s) arrays because
19313 +        * there is not a 1-1 correspondence between cpus(s) and our threads.
19314 +        * Thus we must get a local idea of the mainline threads and use the
19315 +        * one and only 1 set as the victim.  We do this once before the ldsr
19316 +        * loop.
19317 +        *
19318 +        * In the SMP case, we will use the cpu(s) map to determine which cpu(s)
19319 +        * are valid to send interrupts to.
19320 +        */
19321 +       int victim = 0;
19322 +       unsigned int mainline = thread_get_mainline();
19323 +       if (mainline == 0) {
19324 +               panic("no mainline Linux threads to interrupt");
19325 +               return;
19326 +       }
19327 +       victim = ffz(~mainline);
19328 +       cpus = (1 << victim);
19329 +#endif
19330 +
19331 +       while (1) {
19332 +               /*
19333 +                * If one changes this code not to reload the INT_MASK(s), you
19334 +                * need to know that code in the lock waiting above does not
19335 +                * reset the MASK registers back; so that code will need to be
19336 +                * changed.
19337 +                */
19338 +               ldsr_lock_acquire();
19339 +               asm volatile (
19340 +               "       move.4 INT_MASK0, %0    \n\t"
19341 +               "       move.4 INT_MASK1, %1    \n\t"
19342 +                       :
19343 +                       : "U4" (ldsr_interrupt.mask0), "U4" (ldsr_interrupt.mask1)
19344 +               );
19345 +               ldsr_lock_release();
19346 +               thread_suspend();
19347 +
19348 +               /*
19349 +                * Read the interrupt status registers
19350 +                */
19351 +               asm volatile (
19352 +                       "move.4 %0, INT_STAT0   \n\t"
19353 +                       "move.4 %1, INT_STAT1   \n\t"
19354 +                       : "=r" (stat0), "=r" (stat1)
19355 +                       :
19356 +               );
19357 +
19358 +               /*
19359 +                * We only care about interrupts that we have been told to care
19360 +                * about.  The interrupt must be enabled, unmasked, and have
19361 +                * occurred in the hardware.
19362 +                */
19363 +               ldsr_lock_acquire();
19364 +               interrupt0 = ldsr_interrupt.enabled0 &
19365 +                       ldsr_interrupt.mask0 & stat0;
19366 +               interrupt1 = ldsr_interrupt.enabled1 &
19367 +                       ldsr_interrupt.mask1 & stat1;
19368 +               ldsr_lock_release();
19369 +
19370 +               /*
19371 +                * For each interrupt in the "snapshot" we will mask the
19372 +                * interrupt handle the interrupt (typically calling do_IRQ()).
19373 +                *
19374 +                * The interrupt is unmasked by desc->chip->end() function in
19375 +                * the per chip generic interrupt handling code
19376 +                * (arch/ubicom32/kernel/irq.c).8
19377 +                */
19378 +               interrupts = ((unsigned long long)interrupt1 << 32) |
19379 +                       interrupt0;
19380 +               while (interrupts) {
19381 +                       int all = 0;
19382 +                       int vector = ldsr_rotate_interrupts(interrupts);
19383 +                       interrupts &= ~((unsigned long long)1 << vector);
19384 +
19385 +                       /*
19386 +                        * Now mask off this vector so that the LDSR ignores
19387 +                        * it until it is acknowledged.
19388 +                        */
19389 +                       ldsr_mask_vector(vector);
19390 +#if !defined(CONFIG_SMP)
19391 +                       ldsr_deliver_interrupt(vector, cpus, all);
19392 +#else
19393 +                       cpus = smp_get_affinity(vector, &all);
19394 +                       if (!cpus) {
19395 +                               /*
19396 +                                * No CPU to deliver to so just leave
19397 +                                * the interrupt unmasked and increase
19398 +                                * the backout count.  We will eventually
19399 +                                * return and deliver it again.
19400 +                                */
19401 +                               ldsr_unmask_vector(vector);
19402 +                               ldsr_interrupt.backout++;
19403 +                               continue;
19404 +                       }
19405 +                       ldsr_deliver_interrupt(vector, cpus, all);
19406 +#endif
19407 +               }
19408 +       }
19409 +
19410 +       /* NOTREACHED */
19411 +}
19412 +
19413 +/*
19414 + * ldsr_mask_vector()
19415 + *     Temporarily mask the interrupt vector, turn off the bit in the mask
19416 + *     register.
19417 + */
19418 +void ldsr_mask_vector(unsigned int vector)
19419 +{
19420 +       unsigned int mask;
19421 +       if (vector < 32) {
19422 +               mask = ~(1 << vector);
19423 +               ldsr_lock_acquire();
19424 +               ldsr_interrupt.mask0 &= mask;
19425 +               ldsr_lock_release();
19426 +               thread_resume(ldsr_tid);
19427 +               return;
19428 +       }
19429 +
19430 +       mask = ~(1 << (vector - 32));
19431 +       ldsr_lock_acquire();
19432 +       ldsr_interrupt.mask1 &= mask;
19433 +       ldsr_lock_release();
19434 +       thread_resume(ldsr_tid);
19435 +}
19436 +
19437 +/*
19438 + * ldsr_unmask_vector()
19439 + *     Unmask the interrupt vector so that it can be used, turn on the bit in
19440 + *     the mask register.
19441 + *
19442 + * Because it is legal for the interrupt path to disable an interrupt,
19443 + * the unmasking code must ensure that disabled interrupts are not
19444 + * unmasked.
19445 + */
19446 +void ldsr_unmask_vector(unsigned int vector)
19447 +{
19448 +       unsigned int mask;
19449 +       if (vector < 32) {
19450 +               mask = (1 << vector);
19451 +               ldsr_lock_acquire();
19452 +               ldsr_interrupt.mask0 |= (mask & ldsr_interrupt.enabled0);
19453 +               ldsr_lock_release();
19454 +               thread_resume(ldsr_tid);
19455 +               return;
19456 +       }
19457 +
19458 +       mask = (1 << (vector - 32));
19459 +       ldsr_lock_acquire();
19460 +       ldsr_interrupt.mask1 |= (mask & ldsr_interrupt.enabled1);
19461 +       ldsr_lock_release();
19462 +       thread_resume(ldsr_tid);
19463 +}
19464 +
19465 +/*
19466 + * ldsr_enable_vector()
19467 + *     The LDSR implements an interrupt controller and has a local (to the
19468 + *     LDSR) copy of its interrupt mask.
19469 + */
19470 +void ldsr_enable_vector(unsigned int vector)
19471 +{
19472 +       unsigned int mask;
19473 +       if (vector < 32) {
19474 +               mask = (1 << vector);
19475 +               ldsr_lock_acquire();
19476 +               ldsr_interrupt.enabled0 |= mask;
19477 +               ldsr_interrupt.mask0 |= mask;
19478 +               ldsr_lock_release();
19479 +               thread_resume(ldsr_tid);
19480 +               return;
19481 +       }
19482 +
19483 +       mask = (1 << (vector - 32));
19484 +       ldsr_lock_acquire();
19485 +       ldsr_interrupt.enabled1 |= mask;
19486 +       ldsr_interrupt.mask1 |= mask;
19487 +       ldsr_lock_release();
19488 +       thread_resume(ldsr_tid);
19489 +}
19490 +
19491 +/*
19492 + * ldsr_disable_vector()
19493 + *     The LDSR implements an interrupt controller and has a local (to the
19494 + *     LDSR) copy of its interrupt mask.
19495 + */
19496 +void ldsr_disable_vector(unsigned int vector)
19497 +{
19498 +       unsigned int mask;
19499 +
19500 +       if (vector < 32) {
19501 +               mask = ~(1 << vector);
19502 +               ldsr_lock_acquire();
19503 +               ldsr_interrupt.enabled0 &= mask;
19504 +               ldsr_interrupt.mask0 &= mask;
19505 +               ldsr_lock_release();
19506 +               thread_resume(ldsr_tid);
19507 +               return;
19508 +       }
19509 +
19510 +       mask = ~(1 << (vector - 32));
19511 +       ldsr_lock_acquire();
19512 +       ldsr_interrupt.enabled1 &= mask;
19513 +       ldsr_interrupt.mask1 &= mask;
19514 +       ldsr_lock_release();
19515 +       thread_resume(ldsr_tid);
19516 +}
19517 +
19518 +/*
19519 + * ldsr_get_threadid()
19520 + *     Return the threadid of the LDSR thread.
19521 + */
19522 +thread_t ldsr_get_threadid(void)
19523 +{
19524 +       return ldsr_tid;
19525 +}
19526 +
19527 +/*
19528 + * ldsr_set_trap_irq()
19529 + *     Save away the trap Soft IRQ
19530 + *
19531 + * See the per thread lock suspend code above for an explination.
19532 + */
19533 +void ldsr_set_trap_irq(unsigned int irq)
19534 +{
19535 +       ldsr_trap_irq = irq;
19536 +       ldsr_trap_irq_mask = (1 << irq);
19537 +       ldsr_suspend_mask |= ldsr_trap_irq_mask;
19538 +}
19539 +
19540 +/*
19541 + * ldsr_init()
19542 + *     Initialize the LDSR (Interrupt Controller)
19543 + */
19544 +void ldsr_init(void)
19545 +{
19546 +#if defined(CONFIG_IRQSTACKS)
19547 +       int i;
19548 +       union irq_ctx *icp;
19549 +#endif
19550 +
19551 +       void *stack_high = (void *)ldsr_stack_space;
19552 +       stack_high += sizeof(ldsr_stack_space);
19553 +       stack_high -= 8;
19554 +
19555 +
19556 +       /*
19557 +        * Obtain a soft IRQ to use
19558 +        */
19559 +       if (irq_soft_alloc(&ldsr_soft_irq) < 0) {
19560 +               panic("no software IRQ is available\n");
19561 +               return;
19562 +       }
19563 +       ldsr_soft_irq_mask |= (1 << ldsr_soft_irq);
19564 +       ldsr_suspend_mask |= ldsr_soft_irq_mask;
19565 +
19566 +       /*
19567 +        * Now allocate and start the LDSR thread.
19568 +        */
19569 +       ldsr_tid = thread_alloc();
19570 +       if (ldsr_tid < 0) {
19571 +               panic("no thread available to run LDSR");
19572 +               return;
19573 +       }
19574 +
19575 +#if defined(CONFIG_IRQSTACKS)
19576 +       /*
19577 +        * Initialize the per-cpu irq thread_info structure that
19578 +        * is at the top of each per-cpu irq stack.
19579 +        */
19580 +       icp = (union irq_ctx *)
19581 +               (((unsigned long)percpu_irq_stacks + (THREAD_SIZE - 1)) & ~(THREAD_SIZE - 1));
19582 +       for (i = 0; i < NR_CPUS; i++) {
19583 +               struct thread_info *ti = &(icp->tinfo);
19584 +               ti->task = NULL;
19585 +               ti->exec_domain = NULL;
19586 +               ti->cpu = i;
19587 +               ti->preempt_count = 0;
19588 +               ti->interrupt_nesting = 0;
19589 +               percpu_irq_ctxs[i] = icp++;
19590 +       }
19591 +#endif
19592 +       thread_start(ldsr_tid, ldsr_thread, NULL,
19593 +                    stack_high, THREAD_TYPE_NORMAL);
19594 +}
19595 --- /dev/null
19596 +++ b/arch/ubicom32/kernel/Makefile
19597 @@ -0,0 +1,64 @@
19598 +#
19599 +# arch/ubicom32/kernel/Makefile
19600 +#      Main Makefile for the Ubicom32 arch directory.
19601 +#
19602 +# (C) Copyright 2009, Ubicom, Inc.
19603 +#
19604 +# This file is part of the Ubicom32 Linux Kernel Port.
19605 +#
19606 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
19607 +# it and/or modify it under the terms of the GNU General Public License
19608 +# as published by the Free Software Foundation, either version 2 of the
19609 +# License, or (at your option) any later version.
19610 +#
19611 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
19612 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
19613 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
19614 +# the GNU General Public License for more details.
19615 +#
19616 +# You should have received a copy of the GNU General Public License
19617 +# along with the Ubicom32 Linux Kernel Port.  If not,
19618 +# see <http://www.gnu.org/licenses/>.
19619 +#
19620 +# Ubicom32 implementation derived from (with many thanks):
19621 +#   arch/m68knommu
19622 +#   arch/blackfin
19623 +#   arch/parisc
19624 +#
19625 +
19626 +extra-y := head.o vmlinux.lds
19627 +
19628 +obj-y += \
19629 +       devtree.o \
19630 +       dma.o \
19631 +       flat.o \
19632 +       init_task.o \
19633 +       irq.o \
19634 +       ldsr.o \
19635 +       os_node.o \
19636 +       process.o \
19637 +       processor.o \
19638 +       ptrace.o \
19639 +       setup.o \
19640 +       signal.o \
19641 +       stacktrace.o \
19642 +       sys_ubicom32.o \
19643 +       syscalltable.o \
19644 +       thread.o \
19645 +       time.o \
19646 +       traps.o \
19647 +       ubicom32_context_switch.o \
19648 +       ubicom32_ksyms.o \
19649 +       ubicom32_syscall.o \
19650 +       unaligned_trap.o
19651 +
19652 +obj-$(CONFIG_MODULES)                          += module.o
19653 +obj-$(CONFIG_COMEMPCI)                         += comempci.o
19654 +obj-$(CONFIG_SMP)                              += smp.o topology.o
19655 +obj-$(CONFIG_ACCESS_OK_CHECKS_ENABLED)         += uaccess.o
19656 +obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += timer_device.o
19657 +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += timer_broadcast.o
19658 +
19659 +ifndef CONFIG_GENERIC_CLOCKEVENTS
19660 +obj-y                  += timer_tick.o
19661 +endif
19662 --- /dev/null
19663 +++ b/arch/ubicom32/kernel/module.c
19664 @@ -0,0 +1,463 @@
19665 +/*
19666 + * arch/ubicom32/kernel/module.c
19667 + *   Ubicom32 architecture loadable module support.
19668 + *
19669 + * (C) Copyright 2009, Ubicom, Inc.
19670 + *
19671 + * This file is part of the Ubicom32 Linux Kernel Port.
19672 + *
19673 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
19674 + * it and/or modify it under the terms of the GNU General Public License
19675 + * as published by the Free Software Foundation, either version 2 of the
19676 + * License, or (at your option) any later version.
19677 + *
19678 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19679 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19680 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
19681 + * the GNU General Public License for more details.
19682 + *
19683 + * You should have received a copy of the GNU General Public License
19684 + * along with the Ubicom32 Linux Kernel Port.  If not,
19685 + * see <http://www.gnu.org/licenses/>.
19686 + *
19687 + * Ubicom32 implementation derived from (with many thanks):
19688 + *   arch/m68knommu
19689 + *   arch/blackfin
19690 + *   arch/parisc
19691 + */
19692 +#include <linux/moduleloader.h>
19693 +#include <linux/bug.h>
19694 +#include <linux/elf.h>
19695 +#include <linux/vmalloc.h>
19696 +#include <linux/fs.h>
19697 +#include <linux/string.h>
19698 +#include <linux/kernel.h>
19699 +#include <asm/ocm-alloc.h>
19700 +
19701 +#if 0
19702 +#define DEBUGP printk
19703 +#else
19704 +#define DEBUGP(fmt...)
19705 +#endif
19706 +
19707 +static void _module_free_ocm(struct module *mod)
19708 +{
19709 +       printk(KERN_INFO "module arch cleanup %s: OCM instruction memory free "
19710 +              " of %d @%p\n", mod->name, mod->arch.ocm_inst_size,
19711 +              mod->arch.ocm_inst);
19712 +
19713 +       if (mod->arch.ocm_inst) {
19714 +               ocm_inst_free(mod->arch.ocm_inst);
19715 +               mod->arch.ocm_inst = 0;
19716 +               mod->arch.ocm_inst_size = 0;
19717 +       }
19718 +}
19719 +
19720 +void *module_alloc(unsigned long size)
19721 +{
19722 +       if (size == 0)
19723 +               return NULL;
19724 +       return vmalloc(size);
19725 +}
19726 +
19727 +
19728 +/* Free memory returned from module_alloc */
19729 +void module_free(struct module *mod, void *module_region)
19730 +{
19731 +       vfree(module_region);
19732 +       /* FIXME: If module_region == mod->init_region, trim exception
19733 +          table entries. */
19734 +
19735 +       /*
19736 +        * This is expected to be final module free, use this to prune the
19737 +        * ocm
19738 +        */
19739 +       if (module_region && module_region == mod->module_core)
19740 +               _module_free_ocm(mod);
19741 +
19742 +}
19743 +
19744 +/*
19745 + * module_frob_arch_sections()
19746 + *     Called from kernel/module.c allowing arch specific handling of
19747 + *     sections/headers.
19748 + */
19749 +int module_frob_arch_sections(Elf_Ehdr *hdr,
19750 +                             Elf_Shdr *sechdrs,
19751 +                             char *secstrings,
19752 +                             struct module *mod)
19753 +{
19754 +       Elf_Shdr *s, *sechdrs_end;
19755 +       void *ocm_inst = NULL;
19756 +       int ocm_inst_size = 0;
19757 +
19758 +       /*
19759 +        * Ubicom32 v3 and v4 are almost binary compatible but not completely.
19760 +        * To be safe check that the module was compiled with the correct -march
19761 +        * which is flags.
19762 +        */
19763 +#ifdef CONFIG_UBICOM32_V4
19764 +       if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V4) {
19765 +               printk(KERN_WARNING "Module %s was not compiled for "
19766 +                      "ubicom32v4, elf_flags:%x,\n",
19767 +                      mod->name, hdr->e_flags);
19768 +               return -ENOEXEC;
19769 +       }
19770 +#elif defined CONFIG_UBICOM32_V3
19771 +       if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V3) {
19772 +               printk(KERN_WARNING "Module %s was not compiled for "
19773 +                      "ubicom32v3, elf_flags:%x\n",
19774 +                      mod->name, hdr->e_flags);
19775 +               return -ENOEXEC;
19776 +       }
19777 +#else
19778 +#error Unknown/Unsupported ubicom32 architecture.
19779 +#endif
19780 +
19781 +       /*
19782 +        * XXX: sechdrs are vmalloced in kernel/module.c
19783 +        * and would be vfreed just after module is loaded,
19784 +        * so we hack to keep the only information we needed
19785 +        * in mod->arch to correctly free L1 I/D sram later.
19786 +        * NOTE: this breaks the semantic of mod->arch structure.
19787 +        */
19788 +       sechdrs_end = sechdrs + hdr->e_shnum;
19789 +       for (s = sechdrs; s < sechdrs_end; ++s) {
19790 +               if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0)
19791 +                       ocm_inst_size += s->sh_size;
19792 +       }
19793 +
19794 +       if (!ocm_inst_size)
19795 +               return 0;
19796 +
19797 +       ocm_inst = ocm_inst_alloc(ocm_inst_size, 0 /* internal */);
19798 +       if (ocm_inst == NULL) {
19799 +#ifdef CONFIG_OCM_MODULES_FALLBACK_TO_DDR
19800 +               printk(KERN_WARNING
19801 +                      "module %s: OCM instruction memory allocation of %d"
19802 +                      "failed, fallback to DDR\n", mod->name, ocm_inst_size);
19803 +               return 0;
19804 +#else
19805 +               printk(KERN_ERR
19806 +                      "module %s: OCM instruction memory allocation of %d"
19807 +                      "failed.\n", mod->name, ocm_inst_size);
19808 +               return -ENOMEM;
19809 +#endif
19810 +       }
19811 +
19812 +       mod->arch.ocm_inst = ocm_inst;
19813 +       mod->arch.ocm_inst_size = ocm_inst_size;
19814 +
19815 +       printk(KERN_INFO
19816 +              "module %s: OCM instruction memory allocation of %d @%p\n",
19817 +              mod->name, mod->arch.ocm_inst_size, mod->arch.ocm_inst);
19818 +
19819 +       for (s = sechdrs; s < sechdrs_end; ++s) {
19820 +               if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0) {
19821 +                       memcpy(ocm_inst, (void *)s->sh_addr, s->sh_size);
19822 +                       s->sh_flags &= ~SHF_ALLOC;
19823 +                       s->sh_addr = (unsigned long)ocm_inst;
19824 +                       ocm_inst += s->sh_size;
19825 +               }
19826 +       }
19827 +
19828 +       return 0;
19829 +}
19830 +
19831 +int apply_relocate(Elf32_Shdr *sechdrs,
19832 +                  const char *strtab,
19833 +                  unsigned int symindex,
19834 +                  unsigned int relsec,
19835 +                  struct module *me)
19836 +{
19837 +       DEBUGP("Invalid Applying relocate section %u to %u\n", relsec,
19838 +              sechdrs[relsec].sh_info);
19839 +       return -EINVAL;
19840 +}
19841 +
19842 +int apply_relocate_add(Elf32_Shdr *sechdrs,
19843 +                      const char *strtab,
19844 +                      unsigned int symindex,
19845 +                      unsigned int relsec,
19846 +                      struct module *me)
19847 +{
19848 +       unsigned int i;
19849 +       Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
19850 +       Elf32_Sym *sym;
19851 +       uint32_t *location;
19852 +       uint32_t insn;
19853 +
19854 +       DEBUGP("Applying relocate_add section %u to %u\n", relsec,
19855 +              sechdrs[relsec].sh_info);
19856 +       for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
19857 +               uint32_t v;
19858 +               const int elf32_rtype = ELF32_R_TYPE(rel[i].r_info);
19859 +
19860 +               /* This is where to make the change */
19861 +               location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
19862 +                       + rel[i].r_offset;
19863 +               /* This is the symbol it is referring to.  Note that all
19864 +                  undefined symbols have been resolved.  */
19865 +               sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
19866 +                       + ELF32_R_SYM(rel[i].r_info);
19867 +
19868 +               v = rel[i].r_addend + sym->st_value;
19869 +
19870 +
19871 +               switch (elf32_rtype) {
19872 +               case R_UBICOM32_32:
19873 +               {
19874 +                       /*
19875 +                        * Store the 32 bit relocation as is.
19876 +                        */
19877 +                       *location = v;
19878 +                       break;
19879 +               }
19880 +               case R_UBICOM32_HI24:
19881 +               {
19882 +                       /*
19883 +                        * 24 bit relocation that is part of the MOVEAI
19884 +                        * instruction. The 24 bits come from bits 7 - 30 of the
19885 +                        * relocation. Theses bits eventually get split into 2
19886 +                        * fields in the instruction encoding.
19887 +                        *
19888 +                        * - Bits 7 - 27 of the relocation are encoded into bits
19889 +                        * 0 - 20 of the instruction.
19890 +                        *
19891 +                        *  - Bits 28 - 30 of the relocation are encoded into
19892 +                        *  bit 24 - 26 of the instruction.
19893 +                        */
19894 +                       uint32_t valid24 = (v >> 7) & 0xffffff;
19895 +                       insn = *location;
19896 +
19897 +                       insn &= ~(0x1fffff | (0x7 << 24));
19898 +                       insn |= (valid24 & 0x1fffff);
19899 +                       insn |= ((valid24 & 0xe00000) << 3);
19900 +                       *location = insn;
19901 +               }
19902 +               break;
19903 +               case R_UBICOM32_LO7_S:
19904 +               case R_UBICOM32_LO7_2_S:
19905 +               case R_UBICOM32_LO7_4_S:
19906 +               {
19907 +                       /*
19908 +                        * Bits 0 - 6 of the relocation are encoded into the
19909 +                        * 7bit unsigned immediate fields of the SOURCE-1 field
19910 +                        * of the instruction.  The immediate value is left
19911 +                        * shifted by (0, 1, 2) based on the operand size.
19912 +                        */
19913 +                       uint32_t valid7 = v & 0x7f;
19914 +                       insn = *location;
19915 +
19916 +                       if (elf32_rtype == R_UBICOM32_LO7_2_S) {
19917 +                               valid7 >>= 1;
19918 +                       } else if (elf32_rtype == R_UBICOM32_LO7_4_S) {
19919 +                               valid7 >>= 2;
19920 +                       }
19921 +
19922 +                       insn &= ~(0x1f | (0x3 << 8));
19923 +                       insn |= (valid7 & 0x1f);
19924 +                       insn |= ((valid7 & 0x60) << 3);
19925 +                       *location = insn;
19926 +               }
19927 +               break;
19928 +               case R_UBICOM32_LO7_D:
19929 +               case R_UBICOM32_LO7_2_D:
19930 +               case R_UBICOM32_LO7_4_D:
19931 +               {
19932 +                       /*
19933 +                        * Bits 0 - 6 of the relocation are encoded into the
19934 +                        * 7bit unsigned immediate fields of the DESTINATION
19935 +                        * field of the instruction.  The immediate value is
19936 +                        * left shifted by (0, 1, 2) based on the operand size.
19937 +                        */
19938 +                       uint32_t valid7 = v & 0x7f;
19939 +                       insn = *location;
19940 +
19941 +                       if (elf32_rtype == R_UBICOM32_LO7_2_D) {
19942 +                               valid7 >>= 1;
19943 +                       } else if (elf32_rtype == R_UBICOM32_LO7_4_D) {
19944 +                               valid7 >>= 2;
19945 +                       }
19946 +
19947 +                       insn &= ~((0x1f | (0x3 << 8)) << 16);
19948 +                       insn |= ((valid7 & 0x1f) << 16);
19949 +                       insn |= ((valid7 & 0x60) << 19);
19950 +                       *location = insn;
19951 +               }
19952 +               break;
19953 +               case R_UBICOM32_LO7_CALLI:
19954 +               case R_UBICOM32_LO16_CALLI:
19955 +               {
19956 +                       /*
19957 +                        * Extract the offset for a CALLI instruction. The
19958 +                        * offsets can be either 7 bits or 18 bits. Since all
19959 +                        * instructions in ubicom32 architecture are at work
19960 +                        * aligned addresses the truncated offset is right
19961 +                        * shifted by 2 before being encoded in the instruction.
19962 +                        */
19963 +                       uint32_t val;
19964 +                       if (elf32_rtype == R_UBICOM32_LO7_CALLI) {
19965 +                               val  = v & 0x7f;
19966 +                       } else {
19967 +                               val  = v & 0x3ffff;
19968 +                       }
19969 +
19970 +                       val >>= 2;
19971 +
19972 +                       insn = *location;
19973 +
19974 +                       insn &= ~0x071f071f;
19975 +                       insn |= (val & 0x1f) << 0;
19976 +                       val >>= 5;
19977 +                       insn |= (val & 0x07) << 8;
19978 +                       val >>= 3;
19979 +                       insn |= (val & 0x1f) << 16;
19980 +                       val >>= 5;
19981 +                       insn |= (val & 0x07) << 24;
19982 +                       *location = insn;
19983 +               }
19984 +               break;
19985 +               case R_UBICOM32_24_PCREL:
19986 +               {
19987 +                       /*
19988 +                        * Extract 26 bit signed PC relative offset for CALL
19989 +                        * instructions. Since instruction addresses are word
19990 +                        * aligned the offset is right shited by 2 before
19991 +                        * encoding into instruction.
19992 +                        */
19993 +                       int32_t val = v - (int32_t)location;
19994 +
19995 +                       /*
19996 +                        * Check that the top 7 bits are all equal to the sign
19997 +                        * bit (26), i.e all 0's or all 1's.  If they are not then
19998 +                        * the absolute difference is greater than 25 bits.
19999 +                        */
20000 +                       if (((uint32_t)val & 0xFE000000) != 0xFE000000 &&
20001 +                               ((uint32_t)val & 0xFE000000) != 0x0) {
20002 +                               /*
20003 +                                * The relocation is beyond our addressable
20004 +                                * range with a 26 bit call.
20005 +                                */
20006 +                               printk(KERN_ERR "module %s: PC Relative "
20007 +                                       "relocation out of range: "
20008 +                                       "%u (%x->%x, %x)\n",
20009 +                                       me->name, elf32_rtype,
20010 +                                       v, (uint32_t) location, val);
20011 +                               return -ENOEXEC;
20012 +                       }
20013 +
20014 +                       val = (val & 0x3ffffff) >> 2;
20015 +                       insn = *location;
20016 +                       insn = insn & 0xf8e00000;
20017 +
20018 +                       insn |= (val >> 21) << 24;
20019 +                       insn |= (val & 0x1fffff);
20020 +                       *location = insn;
20021 +               }
20022 +               break;
20023 +               case R_UBICOM32_LO16:
20024 +               case R_UBICOM32_HI16:
20025 +               {
20026 +                       /*
20027 +                        * 16 bit immediate value that is encoded into bit 0 -
20028 +                        * 15 of the instruction.
20029 +                        */
20030 +                       uint32_t val;
20031 +
20032 +                       if (elf32_rtype == R_UBICOM32_LO16) {
20033 +                               val  = v & 0xffff;
20034 +                       } else {
20035 +                               val  = (v >> 16) & 0xffff;
20036 +                       }
20037 +
20038 +                       insn = *location;
20039 +                       insn &= 0xffff0000;
20040 +
20041 +                       insn |= val;
20042 +                       *location = insn;
20043 +               }
20044 +               break;
20045 +               case R_UBICOM32_21_PCREL:
20046 +               {
20047 +                       /*
20048 +                        * Extract 23 bit signed PC relative offset for JMP<cc>
20049 +                        * instructions. Since instruction addresses are word
20050 +                        * aligned the offset is right shited by 2 before
20051 +                        * encoding into instruction.
20052 +                        */
20053 +                       int32_t val = v - (int32_t)location;
20054 +
20055 +                       val = (val & 0x7fffff) >> 2;
20056 +                       insn = *location;
20057 +                       insn = insn & 0xffe00000;
20058 +
20059 +                       insn |= (val >> 21) << 24;
20060 +                       insn |= val;
20061 +                       *location = insn;
20062 +               }
20063 +               break;
20064 +               default:
20065 +                       BUG();
20066 +                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
20067 +                              me->name, elf32_rtype);
20068 +                       return -ENOEXEC;
20069 +               }
20070 +       }
20071 +       return 0;
20072 +}
20073 +
20074 +int module_finalize(const Elf_Ehdr *hdr,
20075 +                   const Elf_Shdr *sechdrs,
20076 +                   struct module *mod)
20077 +{
20078 +       unsigned int i, strindex = 0, symindex = 0;
20079 +       char *secstrings;
20080 +       int err;
20081 +
20082 +       err = module_bug_finalize(hdr, sechdrs, mod);
20083 +       if (err)
20084 +               return err;
20085 +
20086 +       if (!mod->arch.ocm_inst) {
20087 +               /*
20088 +                * No OCM code, so nothing more to do.
20089 +                */
20090 +               return 0;
20091 +       }
20092 +
20093 +       secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
20094 +
20095 +       for (i = 1; i < hdr->e_shnum; i++) {
20096 +               /* Internal symbols and strings. */
20097 +               if (sechdrs[i].sh_type == SHT_SYMTAB) {
20098 +                       symindex = i;
20099 +                       strindex = sechdrs[i].sh_link;
20100 +               }
20101 +       }
20102 +
20103 +       for (i = 1; i < hdr->e_shnum; i++) {
20104 +               const char *strtab = (char *)sechdrs[strindex].sh_addr;
20105 +               unsigned int info = sechdrs[i].sh_info;
20106 +
20107 +               /* Not a valid relocation section? */
20108 +               if (info >= hdr->e_shnum)
20109 +                       continue;
20110 +
20111 +               if ((sechdrs[i].sh_type == SHT_RELA) &&
20112 +                   (strncmp(".rela.ocm_text",
20113 +                            secstrings + sechdrs[i].sh_name, 5 + 9) == 0)) {
20114 +                       err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
20115 +                                                symindex, i, mod);
20116 +                       if (err)
20117 +                               return err;
20118 +               }
20119 +       }
20120 +
20121 +       return 0;
20122 +}
20123 +
20124 +void module_arch_cleanup(struct module *mod)
20125 +{
20126 +       module_bug_cleanup(mod);
20127 +}
20128 --- /dev/null
20129 +++ b/arch/ubicom32/kernel/os_node.c
20130 @@ -0,0 +1,88 @@
20131 +/*
20132 + * arch/ubicom32/kernel/os_node.c
20133 + *   <TODO: Replace with short file description>
20134 + *
20135 + * (C) Copyright 2009, Ubicom, Inc.
20136 + *
20137 + * This file is part of the Ubicom32 Linux Kernel Port.
20138 + *
20139 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20140 + * it and/or modify it under the terms of the GNU General Public License
20141 + * as published by the Free Software Foundation, either version 2 of the
20142 + * License, or (at your option) any later version.
20143 + *
20144 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20145 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20146 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
20147 + * the GNU General Public License for more details.
20148 + *
20149 + * You should have received a copy of the GNU General Public License
20150 + * along with the Ubicom32 Linux Kernel Port.  If not,
20151 + * see <http://www.gnu.org/licenses/>.
20152 + *
20153 + */
20154 +#include "linux/types.h"
20155 +#include "linux/linkage.h"
20156 +#include "linux/uts.h"
20157 +#include "linux/utsrelease.h"
20158 +#include "linux/version.h"
20159 +#include <asm/ocm_size.h>
20160 +#include <asm/devtree.h>
20161 +#include <asm/ip5000.h>
20162 +
20163 +extern asmlinkage void *_start;
20164 +
20165 +/*
20166 + * This file provides static information to the boot code allowing it to decide
20167 + * if the os is compatible. Thus hopefully enabling the boot code to prevent
20168 + * accidentally booting a kernel that has no hope of running.
20169 + */
20170 +struct os_node {
20171 +       struct devtree_node node;
20172 +       unsigned long version; /* Always 1 */
20173 +       unsigned long entry_point;
20174 +       const char    os_name[32]; /* For diagnostic purposes only */
20175 +       const char    os_version_str[32];
20176 +       unsigned long os_version_num;
20177 +       unsigned long expected_ocm_code_start;/* OS Code */
20178 +       unsigned long expected_ocm_data_end;  /* OS Data */
20179 +       unsigned long expected_ram_start;
20180 +       unsigned long expected_ram_end;
20181 +       unsigned long arch_version;
20182 +       unsigned long expected_os_syscall_begin;
20183 +       unsigned long expected_os_syscall_end;
20184 +};
20185 +
20186 +
20187 +extern void __os_syscall_begin;
20188 +extern void __os_syscall_end;
20189 +/*
20190 + * The os_node is only referenced by head.S and should never be modified at
20191 + * run-time.
20192 + */
20193 +asmlinkage const struct os_node _os_node = {
20194 +       .node = {
20195 +               .next = NULL,
20196 +               .name = { "OS" },
20197 +               .magic = 0x10203040,
20198 +       },
20199 +       .version = 0x10002,
20200 +       .entry_point = (unsigned long)&_start,
20201 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
20202 +       .expected_ocm_code_start = OCMSTART + APP_OCM_CODE_SIZE,
20203 +       .expected_ocm_data_end   = OCMEND   - APP_OCM_DATA_SIZE,
20204 +#else
20205 +       .expected_ocm_code_start = OCMEND,
20206 +       .expected_ocm_data_end   = OCMEND,
20207 +#endif
20208 +       .os_name = { UTS_SYSNAME },
20209 +       .os_version_str = { UTS_RELEASE },
20210 +       .os_version_num = LINUX_VERSION_CODE,
20211 +       .expected_ram_start = KERNELSTART,
20212 +       .expected_ram_end = SDRAMSTART + CONFIG_MIN_RAMSIZE,
20213 +       .arch_version = UBICOM32_ARCH_VERSION,
20214 +       .expected_os_syscall_begin = (unsigned long)&__os_syscall_begin,
20215 +       .expected_os_syscall_end = (unsigned long)&__os_syscall_end,
20216 +
20217 +
20218 +};
20219 --- /dev/null
20220 +++ b/arch/ubicom32/kernel/process.c
20221 @@ -0,0 +1,634 @@
20222 +/*
20223 + * arch/ubicom32/kernel/process.c
20224 + *   Ubicom32 architecture-dependent process handling.
20225 + *
20226 + * (C) Copyright 2009, Ubicom, Inc.
20227 + * Copyright (C) 1995  Hamish Macdonald
20228 + *
20229 + * 68060 fixes by Jesper Skov
20230 + *
20231 + * uClinux changes
20232 + * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
20233 + *
20234 + * This file is part of the Ubicom32 Linux Kernel Port.
20235 + *
20236 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20237 + * it and/or modify it under the terms of the GNU General Public License
20238 + * as published by the Free Software Foundation, either version 2 of the
20239 + * License, or (at your option) any later version.
20240 + *
20241 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20242 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20243 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
20244 + * the GNU General Public License for more details.
20245 + *
20246 + * You should have received a copy of the GNU General Public License
20247 + * along with the Ubicom32 Linux Kernel Port.  If not,
20248 + * see <http://www.gnu.org/licenses/>.
20249 + *
20250 + * Ubicom32 implementation derived from (with many thanks):
20251 + *   arch/m68knommu
20252 + *   arch/blackfin
20253 + *   arch/parisc
20254 + */
20255 +
20256 +/*
20257 + * This file handles the architecture-dependent parts of process handling..
20258 + */
20259 +
20260 +#include <linux/module.h>
20261 +#include <linux/errno.h>
20262 +#include <linux/sched.h>
20263 +#include <linux/kernel.h>
20264 +#include <linux/mm.h>
20265 +#include <linux/smp.h>
20266 +#include <linux/smp_lock.h>
20267 +#include <linux/stddef.h>
20268 +#include <linux/unistd.h>
20269 +#include <linux/ptrace.h>
20270 +#include <linux/slab.h>
20271 +#include <linux/user.h>
20272 +#include <linux/a.out.h>
20273 +#include <linux/interrupt.h>
20274 +#include <linux/reboot.h>
20275 +#include <linux/fs.h>
20276 +#include <linux/pm.h>
20277 +
20278 +#include <linux/uaccess.h>
20279 +#include <asm/system.h>
20280 +#include <asm/traps.h>
20281 +#include <asm/machdep.h>
20282 +#include <asm/setup.h>
20283 +#include <asm/pgtable.h>
20284 +#include <asm/ip5000.h>
20285 +#include <asm/range-protect.h>
20286 +
20287 +#define DUMP_RANGE_REGISTER(REG, IDX) asm volatile ( \
20288 +        "       move.4          %0, "REG"_RANGE"IDX"_EN \n\t" \
20289 +        "       move.4          %1, "REG"_RANGE"IDX"_LO \n\t" \
20290 +        "       move.4          %2, "REG"_RANGE"IDX"_HI \n\t" \
20291 +                : "=d"(en), "=d"(lo), "=d"(hi) \
20292 +        ); \
20293 +        printk(KERN_NOTICE REG"Range"IDX": en:%08x, range: %08x-%08x\n", \
20294 +                (unsigned int)en, \
20295 +                (unsigned int)lo, \
20296 +                (unsigned int)hi)
20297 +
20298 +asmlinkage void ret_from_fork(void);
20299 +
20300 +void (*pm_power_off)(void) = machine_power_off;
20301 +EXPORT_SYMBOL(pm_power_off);
20302 +
20303 +/* machine-dependent / hardware-specific power functions */
20304 +void (*mach_reset)(void);
20305 +void (*mach_halt)(void);
20306 +void (*mach_power_off)(void);
20307 +
20308 +/*
20309 + * cpu_idle()
20310 + *     The idle thread.
20311 + *
20312 + * Our idle loop suspends and is woken up by a timer interrupt.
20313 + */
20314 +void cpu_idle(void)
20315 +{
20316 +       while (1) {
20317 +               local_irq_disable();
20318 +               while (!need_resched()) {
20319 +                       local_irq_enable();
20320 +                       thread_suspend();
20321 +                       local_irq_disable();
20322 +               }
20323 +               local_irq_enable();
20324 +               preempt_enable_no_resched();
20325 +               schedule();
20326 +               preempt_disable();
20327 +       }
20328 +}
20329 +
20330 +/*
20331 + * dump_fpu()
20332 + *
20333 + *     Fill in the fpu structure for a core dump. (just a stub as we don't have
20334 + *     an fpu)
20335 + */
20336 +int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
20337 +{
20338 +       return 1;
20339 +}
20340 +
20341 +/*
20342 + * machine_restart()
20343 + *     Resets the system.
20344 + */
20345 +void machine_restart(char *__unused)
20346 +{
20347 +       /*
20348 +        * Disable all threads except myself. We can do this
20349 +        * directly without needing to call smp_send_stop
20350 +        * because we have a unique architecture where
20351 +        * one thread can disable one or more other threads.
20352 +        */
20353 +       thread_disable_others();
20354 +
20355 +       /*
20356 +        * Call the hardware-specific machine reset function.
20357 +        */
20358 +       if (mach_reset) {
20359 +               mach_reset();
20360 +       }
20361 +
20362 +       printk(KERN_EMERG "System Restarting\n");
20363 +
20364 +       /*
20365 +        * Set watchdog to trigger (after 1ms delay) (12 Mhz is the fixed OSC)
20366 +        */
20367 +       UBICOM32_IO_TIMER->tkey = TIMER_TKEYVAL;
20368 +       UBICOM32_IO_TIMER->wdcom = UBICOM32_IO_TIMER->mptval +
20369 +               (12000000 / 1000);
20370 +       UBICOM32_IO_TIMER->wdcfg = 0;
20371 +       UBICOM32_IO_TIMER->tkey = 0;
20372 +
20373 +       /*
20374 +        * Wait for watchdog
20375 +        */
20376 +       asm volatile (
20377 +               "       move.4          MT_EN, #0               \n\t"
20378 +               "       pipe_flush      0                       \n\t"
20379 +       );
20380 +
20381 +       local_irq_disable();
20382 +       for (;;) {
20383 +               thread_suspend();
20384 +       }
20385 +}
20386 +
20387 +/*
20388 + * machine_halt()
20389 + *     Halt the machine.
20390 + *
20391 + * Similar to machine_power_off, but don't shut off power.  Add code
20392 + * here to freeze the system for e.g. post-mortem debug purpose when
20393 + * possible.  This halt has nothing to do with the idle halt.
20394 + */
20395 +void machine_halt(void)
20396 +{
20397 +       /*
20398 +        * Disable all threads except myself. We can do this
20399 +        * directly without needing to call smp_send_stop
20400 +        * because we have a unique architecture where
20401 +        * one thread can disable one or more other threads.
20402 +        */
20403 +       thread_disable_others();
20404 +
20405 +       /*
20406 +        * Call the hardware-specific machine halt function.
20407 +        */
20408 +       if (mach_halt) {
20409 +               mach_halt();
20410 +       }
20411 +
20412 +       printk(KERN_EMERG "System Halted, OK to turn off power\n");
20413 +       local_irq_disable();
20414 +       for (;;) {
20415 +               thread_suspend();
20416 +       }
20417 +}
20418 +
20419 +/*
20420 + * machine_power_off()
20421 + *     Turn the power off, if a power off handler is defined, otherwise, spin
20422 + *     endlessly.
20423 + */
20424 +void machine_power_off(void)
20425 +{
20426 +       /*
20427 +        * Disable all threads except myself. We can do this
20428 +        * directly without needing to call smp_send_stop
20429 +        * because we have a unique architecture where
20430 +        * one thread can disable one or more other threads.
20431 +        */
20432 +       thread_disable_others();
20433 +
20434 +       /*
20435 +        * Call the hardware-specific machine power off function.
20436 +        */
20437 +       if (mach_power_off) {
20438 +               mach_power_off();
20439 +       }
20440 +
20441 +       printk(KERN_EMERG "System Halted, OK to turn off power\n");
20442 +       local_irq_disable();
20443 +       for (;;) {
20444 +               thread_suspend();
20445 +       }
20446 +}
20447 +
20448 +/*
20449 + * address_is_valid()
20450 + *     check if an address is valid -- (for read access)
20451 + */
20452 +static bool address_is_valid(const void *address)
20453 +{
20454 +       int addr = (int)address;
20455 +       unsigned long socm, eocm, sdram, edram;
20456 +
20457 +       if (addr & 3)
20458 +               return false;
20459 +
20460 +       processor_ocm(&socm, &eocm);
20461 +       processor_dram(&sdram, &edram);
20462 +       if (addr >= socm && addr < eocm)
20463 +               return true;
20464 +
20465 +       if (addr >= sdram && addr < edram)
20466 +               return true;
20467 +
20468 +       return false;
20469 +}
20470 +
20471 +/*
20472 + * vma_path_name_is_valid()
20473 + *     check if path_name of a vma is a valid string
20474 + */
20475 +static bool vma_path_name_is_valid(const char *str)
20476 +{
20477 +#define MAX_NAME_LEN 256
20478 +       int i = 0;
20479 +       if (!address_is_valid(str))
20480 +               return false;
20481 +
20482 +       for (; i < MAX_NAME_LEN; i++, str++) {
20483 +               if (*str == '\0')
20484 +                       return true;
20485 +       }
20486 +
20487 +       return false;
20488 +}
20489 +
20490 +/*
20491 + * show_vmas()
20492 + *     show vma info of a process
20493 + */
20494 +void show_vmas(struct task_struct *task)
20495 +{
20496 +#ifdef CONFIG_DEBUG_VERBOSE
20497 +#define UBICOM32_MAX_VMA_COUNT 1024
20498 +
20499 +       struct vm_area_struct *vma;
20500 +       struct file *file;
20501 +       char *name = "";
20502 +       int flags, loop = 0;
20503 +
20504 +       printk(KERN_NOTICE "Start of vma list\n");
20505 +
20506 +       if (!address_is_valid(task) || !address_is_valid(task->mm))
20507 +               goto error;
20508 +
20509 +       vma = task->mm->mmap;
20510 +       while (vma) {
20511 +               if (!address_is_valid(vma))
20512 +                       goto error;
20513 +
20514 +               flags = vma->vm_flags;
20515 +               file = vma->vm_file;
20516 +
20517 +               if (file) {
20518 +                       /* seems better to use dentry op here, but sanity check is easier this way */
20519 +                       if (!address_is_valid(file) || !address_is_valid(file->f_path.dentry) || !vma_path_name_is_valid(file->f_path.dentry->d_name.name))
20520 +                               goto error;
20521 +
20522 +                       name = (char *)file->f_path.dentry->d_name.name;
20523 +               }
20524 +
20525 +               /* Similar to /proc/pid/maps format */
20526 +               printk(KERN_NOTICE "%08lx-%08lx %c%c%c%c %08lx %s\n",
20527 +                       vma->vm_start,
20528 +                       vma->vm_end,
20529 +                       flags & VM_READ ? 'r' : '-',
20530 +                       flags & VM_WRITE ? 'w' : '-',
20531 +                       flags & VM_EXEC ? 'x' : '-',
20532 +                       flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
20533 +                       vma->vm_pgoff << PAGE_SHIFT,
20534 +                       name);
20535 +
20536 +               vma = vma->vm_next;
20537 +
20538 +               if (loop++ > UBICOM32_MAX_VMA_COUNT)
20539 +                       goto error;
20540 +       }
20541 +
20542 +       printk(KERN_NOTICE "End of vma list\n");
20543 +       return;
20544 +
20545 +error:
20546 +       printk(KERN_NOTICE "\nCorrupted vma list, abort!\n");
20547 +#endif
20548 +}
20549 +
20550 +/*
20551 + * show_regs()
20552 + *     Print out all of the registers.
20553 + */
20554 +void show_regs(struct pt_regs *regs)
20555 +{
20556 +       unsigned int i;
20557 +       unsigned int en, lo, hi;
20558 +
20559 +       printk(KERN_NOTICE "regs: %p, tid: %d\n",
20560 +               (void *)regs,
20561 +               thread_get_self());
20562 +
20563 +       printk(KERN_NOTICE "pc: %08x, previous_pc: %08x\n\n",
20564 +               (unsigned int)regs->pc,
20565 +               (unsigned int)regs->previous_pc);
20566 +
20567 +       printk(KERN_NOTICE "Data registers\n");
20568 +       for (i = 0; i < 16; i++) {
20569 +               printk("D%02d: %08x, ", i, (unsigned int)regs->dn[i]);
20570 +               if ((i % 4) == 3) {
20571 +                       printk("\n");
20572 +               }
20573 +       }
20574 +       printk("\n");
20575 +
20576 +       printk(KERN_NOTICE "Address registers\n");
20577 +       for (i = 0; i < 8; i++) {
20578 +               printk("A%02d: %08x, ", i, (unsigned int)regs->an[i]);
20579 +               if ((i % 4) == 3) {
20580 +                       printk("\n");
20581 +               }
20582 +       }
20583 +       printk("\n");
20584 +
20585 +       printk(KERN_NOTICE "acc0: %08x-%08x, acc1: %08x-%08x\n",
20586 +               (unsigned int)regs->acc0[1],
20587 +               (unsigned int)regs->acc0[0],
20588 +               (unsigned int)regs->acc1[1],
20589 +               (unsigned int)regs->acc1[0]);
20590 +
20591 +       printk(KERN_NOTICE "mac_rc16: %08x, source3: %08x\n",
20592 +               (unsigned int)regs->mac_rc16,
20593 +               (unsigned int)regs->source3);
20594 +
20595 +       printk(KERN_NOTICE "inst_cnt: %08x, csr: %08x\n",
20596 +               (unsigned int)regs->inst_cnt,
20597 +               (unsigned int)regs->csr);
20598 +
20599 +       printk(KERN_NOTICE "int_mask0: %08x, int_mask1: %08x\n",
20600 +               (unsigned int)regs->int_mask0,
20601 +               (unsigned int)regs->int_mask1);
20602 +
20603 +       /*
20604 +        * Dump range registers
20605 +        */
20606 +       DUMP_RANGE_REGISTER("I", "0");
20607 +       DUMP_RANGE_REGISTER("I", "1");
20608 +       DUMP_RANGE_REGISTER("I", "2");
20609 +       DUMP_RANGE_REGISTER("I", "3");
20610 +       DUMP_RANGE_REGISTER("D", "0");
20611 +       DUMP_RANGE_REGISTER("D", "1");
20612 +       DUMP_RANGE_REGISTER("D", "2");
20613 +       DUMP_RANGE_REGISTER("D", "3");
20614 +       DUMP_RANGE_REGISTER("D", "4");
20615 +
20616 +       printk(KERN_NOTICE "frame_type: %d, nesting_level: %d, thread_type %d\n\n",
20617 +               (int)regs->frame_type,
20618 +               (int)regs->nesting_level,
20619 +               (int)regs->thread_type);
20620 +}
20621 +
20622 +/*
20623 + * kernel_thread_helper()
20624 + *     On execution d0 will be 0, d1 will be the argument to be passed to the
20625 + *     kernel function.  d2 contains the kernel function that needs to get
20626 + *     called. d3 will contain address to do_exit which need to get moved
20627 + *     into a5. On return from fork the child thread d0 will be 0. We call
20628 + *     this dummy function which in turn loads the argument
20629 + */
20630 +asmlinkage void kernel_thread_helper(void);
20631 +
20632 +/*
20633 + * kernel_thread()
20634 + *     Create a kernel thread
20635 + */
20636 +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
20637 +{
20638 +       struct pt_regs regs;
20639 +
20640 +       memset(&regs, 0, sizeof(regs));
20641 +
20642 +       regs.dn[1] = (unsigned long)arg;
20643 +       regs.dn[2] = (unsigned long)fn;
20644 +       regs.dn[3] = (unsigned long)do_exit;
20645 +       regs.an[5] = (unsigned long)kernel_thread_helper;
20646 +       regs.pc = (unsigned long)kernel_thread_helper;
20647 +       regs.nesting_level = 0;
20648 +       regs.thread_type = KERNEL_THREAD;
20649 +
20650 +       return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
20651 +                      0, &regs, 0, NULL, NULL);
20652 +}
20653 +EXPORT_SYMBOL(kernel_thread);
20654 +
20655 +/*
20656 + * flush_thread()
20657 + *     XXX todo
20658 + */
20659 +void flush_thread(void)
20660 +{
20661 +       /* XXX todo */
20662 +}
20663 +
20664 +/*
20665 + * sys_fork()
20666 + *     Not implemented on no-mmu.
20667 + */
20668 +asmlinkage int sys_fork(struct pt_regs *regs)
20669 +{
20670 +       /* fork almost works, enough to trick you into looking elsewhere :-( */
20671 +       return -EINVAL;
20672 +}
20673 +
20674 +/*
20675 + * sys_vfork()
20676 + *     By the time we get here, the non-volatile registers have also been saved
20677 + *     on the stack. We do some ugly pointer stuff here.. (see also copy_thread
20678 + *     which does context copy).
20679 + */
20680 +asmlinkage int sys_vfork(struct pt_regs *regs)
20681 +{
20682 +       unsigned long old_sp = regs->an[7];
20683 +       unsigned long old_a5 = regs->an[5];
20684 +       unsigned long old_return_address;
20685 +       long do_fork_return;
20686 +
20687 +       /*
20688 +        * Read the old retrun address from the stack.
20689 +        */
20690 +       if (copy_from_user(&old_return_address,
20691 +                          (void *)old_sp, sizeof(unsigned long))) {
20692 +               force_sig(SIGSEGV, current);
20693 +               return 0;
20694 +       }
20695 +
20696 +       /*
20697 +        * Pop the vfork call frame by setting a5 and pc to the old_return
20698 +        * address and incrementing the stack pointer by 4.
20699 +        */
20700 +       regs->an[5] = old_return_address;
20701 +       regs->pc = old_return_address;
20702 +       regs->an[7] += 4;
20703 +
20704 +       do_fork_return = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
20705 +                                regs->an[7], regs, 0, NULL, NULL);
20706 +
20707 +       /*
20708 +        * Now we have to test if the return code is an error. If it is an error
20709 +        * then restore the frame and we will execute error processing in user
20710 +        * space. Other wise the child and the parent will return to the correct
20711 +        * places.
20712 +        */
20713 +       if ((unsigned long)(do_fork_return) >= (unsigned long)(-125)) {
20714 +               /*
20715 +                * Error case. We need to restore the frame.
20716 +                */
20717 +               regs->an[5] = old_a5;
20718 +               regs->pc = old_a5;
20719 +               regs->an[7] = old_sp;
20720 +       }
20721 +
20722 +       return do_fork_return;
20723 +}
20724 +
20725 +/*
20726 + * sys_clone()
20727 + *     creates a child thread.
20728 + */
20729 +asmlinkage int sys_clone(unsigned long clone_flags,
20730 +                        unsigned long newsp,
20731 +                        struct pt_regs *regs)
20732 +{
20733 +       if (!newsp)
20734 +               newsp = regs->an[7];
20735 +       return do_fork(clone_flags, newsp, regs, 0,
20736 +                      NULL, NULL);
20737 +}
20738 +
20739 +/*
20740 + * copy_thread()
20741 + *     low level thread copy, only used by do_fork in kernel/fork.c
20742 + */
20743 +int copy_thread(unsigned long clone_flags,
20744 +               unsigned long usp, unsigned long topstk,
20745 +               struct task_struct *p, struct pt_regs *regs)
20746 +
20747 +{
20748 +       struct pt_regs *childregs;
20749 +
20750 +       childregs = (struct pt_regs *)
20751 +               (task_stack_page(p) + THREAD_SIZE - 8) - 1;
20752 +
20753 +       *childregs = *regs;
20754 +
20755 +       /*
20756 +        * Set return value for child to be 0.
20757 +        */
20758 +       childregs->dn[0] = 0;
20759 +
20760 +       if (usp)
20761 +               childregs->an[7] = usp;
20762 +       else
20763 +               childregs->an[7] = (unsigned long)task_stack_page(p) +
20764 +                       THREAD_SIZE - 8;
20765 +
20766 +       /*
20767 +        * Set up the switch_to frame to return to "ret_from_fork"
20768 +        */
20769 +       p->thread.a5 = (unsigned long)ret_from_fork;
20770 +       p->thread.sp = (unsigned long)childregs;
20771 +
20772 +       return 0;
20773 +}
20774 +
20775 +/*
20776 + * sys_execve()
20777 + *     executes a new program.
20778 + */
20779 +asmlinkage int sys_execve(char *name, char **argv,
20780 +                         char **envp, struct pt_regs *regs)
20781 +{
20782 +       int error;
20783 +       char *filename;
20784 +
20785 +       lock_kernel();
20786 +       filename = getname(name);
20787 +       error = PTR_ERR(filename);
20788 +       if (IS_ERR(filename))
20789 +               goto out;
20790 +       error = do_execve(filename, argv, envp, regs);
20791 +       putname(filename);
20792 +       asm ("       .global sys_execve_complete\n"
20793 +            "       sys_execve_complete:");
20794 +out:
20795 +       unlock_kernel();
20796 +       return error;
20797 +}
20798 +
20799 +/*
20800 + * Return saved PC of a blocked thread.
20801 + */
20802 +unsigned long thread_saved_pc(struct task_struct *tsk)
20803 +{
20804 +       return tsk->thread.a5;
20805 +}
20806 +
20807 +
20808 +unsigned long get_wchan(struct task_struct *p)
20809 +{
20810 +       unsigned long pc;
20811 +
20812 +       /*
20813 +        * If we don't have a process, or it is not the current
20814 +        * one or not RUNNING, it makes no sense to ask for a
20815 +        * wchan.
20816 +        */
20817 +       if (!p || p == current || p->state == TASK_RUNNING)
20818 +               return 0;
20819 +
20820 +       /*
20821 +        * TODO: If the process is in the middle of schedule, we
20822 +        * are supposed to do something different but for now we
20823 +        * will return the same thing in both situations.
20824 +        */
20825 +       pc = thread_saved_pc(p);
20826 +       if (in_sched_functions(pc))
20827 +               return pc;
20828 +       return pc;
20829 +}
20830 +
20831 +
20832 +/*
20833 + * Infrequently used interface to dump task registers to core files.
20834 + */
20835 +int dump_task_regs(struct task_struct *task, elf_gregset_t *elfregs)
20836 +{
20837 +       struct pt_regs *regs = task_pt_regs(task);
20838 +       *(struct pt_regs *)elfregs = *regs;
20839 +
20840 +       return 1;
20841 +}
20842 +
20843 +/*
20844 + * __switch_to is the function that implements the contex save and
20845 + * switch within the kernel. Since this is a function call very few
20846 + * registers have to be saved to pull this off. d0 holds prev and we
20847 + * want to preserve it. prev_switch is a pointer to task->thread
20848 + * structure. This is where we will save the register state. next_switch
20849 + * is pointer to the next task's thread structure that holds the
20850 + * registers.
20851 + */
20852 +asmlinkage void *__switch_to(struct task_struct *prev,
20853 +                            struct thread_struct *prev_switch,
20854 +                            struct thread_struct *next_switch)
20855 +       __attribute__((naked));
20856 --- /dev/null
20857 +++ b/arch/ubicom32/kernel/processor.c
20858 @@ -0,0 +1,348 @@
20859 +/*
20860 + * arch/ubicom32/kernel/processor.c
20861 + *   Ubicom32 architecture processor info implementation.
20862 + *
20863 + * (C) Copyright 2009, Ubicom, Inc.
20864 + *
20865 + * This file is part of the Ubicom32 Linux Kernel Port.
20866 + *
20867 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20868 + * it and/or modify it under the terms of the GNU General Public License
20869 + * as published by the Free Software Foundation, either version 2 of the
20870 + * License, or (at your option) any later version.
20871 + *
20872 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20873 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20874 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
20875 + * the GNU General Public License for more details.
20876 + *
20877 + * You should have received a copy of the GNU General Public License
20878 + * along with the Ubicom32 Linux Kernel Port.  If not,
20879 + * see <http://www.gnu.org/licenses/>.
20880 + *
20881 + * Ubicom32 implementation derived from (with many thanks):
20882 + *   arch/m68knommu
20883 + *   arch/blackfin
20884 + *   arch/parisc
20885 + */
20886 +#include <linux/module.h>
20887 +#include <linux/kernel.h>
20888 +#include <linux/init.h>
20889 +#include <linux/sched.h>
20890 +#include <linux/interrupt.h>
20891 +#include <linux/irq.h>
20892 +#include <linux/profile.h>
20893 +#include <linux/clocksource.h>
20894 +#include <linux/types.h>
20895 +#include <linux/seq_file.h>
20896 +#include <linux/delay.h>
20897 +#include <linux/cpu.h>
20898 +#include <asm/devtree.h>
20899 +#include <asm/processor.h>
20900 +#include <asm/cpu.h>
20901 +#include <asm/ocm_size.h>
20902 +
20903 +struct procnode {
20904 +       struct devtree_node dn;
20905 +       unsigned int threads;
20906 +       unsigned int timers;
20907 +       unsigned int frequency;
20908 +       unsigned int ddr_frequency;
20909 +       unsigned int interrupt0;
20910 +       unsigned int interrupt1;
20911 +       void *socm;
20912 +       void *eocm;
20913 +       void *sdram;
20914 +       void *edram;
20915 +       unsigned int arch_version;
20916 +       void *os_syscall_begin;
20917 +       void *os_syscall_end;
20918 +};
20919 +
20920 +struct procnode *pn;
20921 +
20922 +/*
20923 + * show_processorinfo()
20924 + *     Print the actual processor information.
20925 + */
20926 +static void show_processorinfo(struct seq_file *m)
20927 +{
20928 +       char *cpu, *mmu, *fpu;
20929 +       unsigned int clockfreq;
20930 +       unsigned int chipid;
20931 +
20932 +       cpu = CPU;
20933 +       mmu = "none";
20934 +       fpu = "none";
20935 +
20936 +       asm volatile (
20937 +       "move.4         %0, CHIP_ID     \n\t"
20938 +       : "=r" (chipid)
20939 +       );
20940 +
20941 +       /*
20942 +        * General Processor Information.
20943 +        */
20944 +       seq_printf(m, "Vendor:\t\t%s\n", "Ubicom");
20945 +       seq_printf(m, "CPU:\t\t%s\n", cpu);
20946 +       seq_printf(m, "MMU:\t\t%s\n", mmu);
20947 +       seq_printf(m, "FPU:\t\t%s\n", fpu);
20948 +       seq_printf(m, "Arch:\t\t%hx\n", chipid >> 16);
20949 +       seq_printf(m, "Rev:\t\t%hx\n", (chipid & 0xffff));
20950 +
20951 +       /*
20952 +        * Now compute the clock frequency in Mhz.
20953 +        */
20954 +       clockfreq = processor_frequency();
20955 +       seq_printf(m, "Clock Freq:\t%u.0 MHz\n",
20956 +                  clockfreq / 1000000);
20957 +       seq_printf(m, "DDR Freq:\t%u.0 MHz\n",
20958 +                  pn ? pn->ddr_frequency / 1000000 : 0);
20959 +       seq_printf(m, "BogoMips:\t%lu.%02lu\n",
20960 +                  (loops_per_jiffy * HZ) / 500000,
20961 +                  ((loops_per_jiffy * HZ) / 5000) % 100);
20962 +       seq_printf(m, "Calibration:\t%lu loops\n", (loops_per_jiffy * HZ));
20963 +}
20964 +
20965 +/*
20966 + * show_cpuinfo()
20967 + *     Get CPU information for use by the procfs.
20968 + */
20969 +static int show_cpuinfo(struct seq_file *m, void *v)
20970 +{
20971 +       unsigned long n = (unsigned long)v - 1;
20972 +
20973 +#if defined(CONFIG_SMP)
20974 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, n);
20975 +#endif
20976 +
20977 +       /*
20978 +        * Print the general processor information on the first
20979 +        * call.
20980 +        */
20981 +       if (n == 0) {
20982 +               show_processorinfo(m);
20983 +       }
20984 +
20985 +#if defined(CONFIG_SMP)
20986 +       /*
20987 +        * For each hwthread, print if this hwthread is running Linux
20988 +        * or is an I/O thread.
20989 +        */
20990 +       if (cpu_isset(n, cpu_online_map)) {
20991 +               seq_printf(m, "cpu[%02lu]:\tthread id - %lu\n", n, p->tid);
20992 +       } else {
20993 +               seq_printf(m, "cpu[%02lu]:\toff-line\n", n);
20994 +       }
20995 +#endif
20996 +       return 0;
20997 +
20998 +}
20999 +
21000 +static void *c_start(struct seq_file *m, loff_t *pos)
21001 +{
21002 +       unsigned long i = *pos;
21003 +
21004 +       return i < NR_CPUS ? (void *)(i + 1) : NULL;
21005 +}
21006 +
21007 +static void *c_next(struct seq_file *m, void *v, loff_t *pos)
21008 +{
21009 +       ++*pos;
21010 +       return c_start(m, pos);
21011 +}
21012 +
21013 +static void c_stop(struct seq_file *m, void *v)
21014 +{
21015 +}
21016 +
21017 +const struct seq_operations cpuinfo_op = {
21018 +       .start  = c_start,
21019 +       .next   = c_next,
21020 +       .stop   = c_stop,
21021 +       .show   = show_cpuinfo,
21022 +};
21023 +
21024 +/*
21025 + * processor_timers()
21026 + *     Returns the timers available to Linux.
21027 + */
21028 +unsigned int processor_timers(void)
21029 +{
21030 +       if (!pn) {
21031 +               return 0;
21032 +       }
21033 +       return pn->timers;
21034 +}
21035 +
21036 +/*
21037 + * processor_threads()
21038 + *     Returns the threads available to Linux.
21039 + */
21040 +unsigned int processor_threads(void)
21041 +{
21042 +       if (!pn) {
21043 +               return 0;
21044 +       }
21045 +       return pn->threads;
21046 +}
21047 +
21048 +/*
21049 + * processor_frequency()
21050 + *     Returns the frequency of the system clock.
21051 + */
21052 +unsigned int processor_frequency(void)
21053 +{
21054 +       if (!pn) {
21055 +               return 0;
21056 +       }
21057 +       return pn->frequency;
21058 +}
21059 +EXPORT_SYMBOL(processor_frequency);
21060 +
21061 +/*
21062 + * processor_interrupts()
21063 + *     Return the interrupts that are setup at boot time.
21064 + */
21065 +int processor_interrupts(unsigned int *int0, unsigned int *int1)
21066 +{
21067 +       if (!pn) {
21068 +               return -EFAULT;
21069 +       }
21070 +
21071 +       if (int0) {
21072 +               *int0 = pn->interrupt0;
21073 +       }
21074 +
21075 +       if (int1) {
21076 +               *int1 = pn->interrupt1;
21077 +       }
21078 +       return 0;
21079 +}
21080 +
21081 +/*
21082 + * processor_ocm()
21083 + *     Returns the start and end of OCM available to Linux.
21084 + */
21085 +void processor_ocm(unsigned long *socm, unsigned long *eocm)
21086 +{
21087 +       *socm = (unsigned long)pn->socm;
21088 +       *eocm = (unsigned long)pn->eocm;
21089 +}
21090 +
21091 +/*
21092 + * processor_dram()
21093 + *     Returns the start and end of dram available to Linux.
21094 + */
21095 +void processor_dram(unsigned long *sdram, unsigned long *edram)
21096 +{
21097 +       *sdram = (unsigned long)pn->sdram;
21098 +       *edram = (unsigned long)pn->edram;
21099 +}
21100 +
21101 +/*
21102 + * processor_validate_failed()
21103 + *     Returns the dram available to Linux.
21104 + */
21105 +static noinline void processor_validate_failed(void)
21106 +{
21107 +       while (1)
21108 +               THREAD_STALL;
21109 +}
21110 +
21111 +/*
21112 + * processor_validate()
21113 + *     Validates the procnode against limitations of this link/built.
21114 + */
21115 +static void processor_validate(void)
21116 +{
21117 +       void *dram_start = (void *)(KERNELSTART);
21118 +       void *dram_end   = (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE);
21119 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21120 +       void *ocm_code_start = (void *)(OCMSTART + APP_OCM_CODE_SIZE);
21121 +       void *ocm_data_end   = (void *)(OCMEND   - APP_OCM_DATA_SIZE);
21122 +#endif
21123 +       extern void __os_syscall_begin;
21124 +       extern void __os_syscall_end;
21125 +       int proc_node_valid = 1;
21126 +
21127 +       if (!pn) {
21128 +               printk(KERN_ERR "ERROR: processor node not found\n");
21129 +               goto error;
21130 +       }
21131 +
21132 +
21133 +       if (dram_start < pn->sdram || dram_end > pn->edram) {
21134 +               printk(KERN_ERR "ERROR: processor dram mismatch %p-%p "
21135 +                      "available but we are expecting %p-%p\n",
21136 +                      pn->sdram, pn->edram, dram_start, dram_end);
21137 +               proc_node_valid = 0;
21138 +       } else {
21139 +               printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21140 +                      pn->sdram, pn->edram, dram_start, dram_end);
21141 +       }
21142 +       if (&__os_syscall_begin < pn->os_syscall_begin ||
21143 +           &__os_syscall_end > pn->os_syscall_end) {
21144 +               printk(KERN_ERR "ERROR: processor syscall area mismatch "
21145 +                      "%p-%p available but we are expecting %p-%p\n",
21146 +                      pn->os_syscall_begin, pn->os_syscall_end,
21147 +                      &__os_syscall_begin, &__os_syscall_end);
21148 +               proc_node_valid = 0;
21149 +       } else {
21150 +               printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21151 +                      pn->sdram, pn->edram, dram_start, dram_end);
21152 +       }
21153 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21154 +       if (ocm_code_start < pn->socm ||  ocm_data_end > pn->eocm) {
21155 +               printk(KERN_ERR "ERROR: processor ocm mismatch %p-%p "
21156 +                      "available but we are expecting %p-%p\n",
21157 +                      pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21158 +               proc_node_valid = 0;
21159 +       } else {
21160 +               printk(KERN_INFO "processor ocm %p-%p, expecting %p-%p\n",
21161 +                      pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21162 +
21163 +       }
21164 +#endif
21165 +
21166 +       if (UBICOM32_ARCH_VERSION != pn->arch_version) {
21167 +               printk(KERN_ERR "ERROR: processor arch mismatch, kernel"
21168 +                      "compiled for %d found %d\n",
21169 +                      UBICOM32_ARCH_VERSION, pn->arch_version);
21170 +               proc_node_valid = 0;
21171 +       }
21172 +
21173 +       if (proc_node_valid)
21174 +               return;
21175 +error:
21176 +       processor_validate_failed();
21177 +}
21178 +
21179 +void __init processor_init(void)
21180 +{
21181 +       /*
21182 +        * If we do not have a trap node in the device tree, we leave the fault
21183 +        * handling to the underlying hardware.
21184 +        */
21185 +       pn = (struct procnode *)devtree_find_node("processor");
21186 +
21187 +       processor_validate();
21188 +
21189 +       /*
21190 +        * If necessary correct the initial range registers to cover the
21191 +        * complete physical space
21192 +        */
21193 +       if (pn->edram > (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE)) {
21194 +               printk(KERN_INFO "updating range registers for expanded dram\n");
21195 +               asm volatile (
21196 +                       "       move.4 D_RANGE1_HI, %0          \t\n"
21197 +                       "       move.4 I_RANGE0_HI, %0          \t\n"
21198 +#ifdef CONFIG_PROTECT_KERNEL
21199 +                       "       move.4 D_RANGE2_HI, %0          \t\n"
21200 +                       "       move.4 I_RANGE2_HI, %0          \t\n"
21201 +#endif
21202 +               : : "a"((unsigned long)pn->edram - 4)
21203 +                       );
21204 +       }
21205 +
21206 +}
21207 --- /dev/null
21208 +++ b/arch/ubicom32/kernel/ptrace.c
21209 @@ -0,0 +1,275 @@
21210 +/*
21211 + * arch/ubicom32/kernel/ptrace.c
21212 + *   Ubicom32 architecture ptrace implementation.
21213 + *
21214 + * (C) Copyright 2009, Ubicom, Inc.
21215 + * (C) 1994 by Hamish Macdonald
21216 + * Taken from linux/kernel/ptrace.c and modified for M680x0.
21217 + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
21218 + *
21219 + * This file is part of the Ubicom32 Linux Kernel Port.
21220 + *
21221 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21222 + * it and/or modify it under the terms of the GNU General Public License
21223 + * as published by the Free Software Foundation, either version 2 of the
21224 + * License, or (at your option) any later version.
21225 + *
21226 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21227 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21228 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21229 + * the GNU General Public License for more details.
21230 + *
21231 + * You should have received a copy of the GNU General Public License
21232 + * along with the Ubicom32 Linux Kernel Port.  If not,
21233 + * see <http://www.gnu.org/licenses/>.
21234 + *
21235 + * Ubicom32 implementation derived from (with many thanks):
21236 + *   arch/m68knommu
21237 + *   arch/blackfin
21238 + *   arch/parisc
21239 + */
21240 +
21241 +#include <linux/module.h>
21242 +#include <linux/kernel.h>
21243 +#include <linux/sched.h>
21244 +#include <linux/mm.h>
21245 +#include <linux/smp.h>
21246 +#include <linux/errno.h>
21247 +#include <linux/ptrace.h>
21248 +#include <linux/user.h>
21249 +#include <linux/signal.h>
21250 +#include <linux/uaccess.h>
21251 +
21252 +#include <asm/page.h>
21253 +#include <asm/pgtable.h>
21254 +#include <asm/system.h>
21255 +#include <asm/cacheflush.h>
21256 +#include <asm/processor.h>
21257 +
21258 +/*
21259 + * ptrace_getregs()
21260 + *
21261 + *     Get all user integer registers.
21262 + */
21263 +static inline int ptrace_getregs(struct task_struct *task, void __user *uregs)
21264 +{
21265 +       struct pt_regs *regs = task_pt_regs(task);
21266 +       return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
21267 +}
21268 +
21269 +/*
21270 + * ptrace_get_reg()
21271 + *
21272 + *     Get contents of register REGNO in task TASK.
21273 + */
21274 +static unsigned long ptrace_get_reg(struct task_struct *task, int regno)
21275 +{
21276 +       if (regno < sizeof(struct pt_regs)) {
21277 +               struct pt_regs *pt_regs = task_pt_regs(task);
21278 +               return *(unsigned long *)((long) pt_regs + regno);
21279 +       }
21280 +
21281 +       return -EIO;
21282 +}
21283 +
21284 +/*
21285 + * ptrace_put_reg()
21286 + *     Write contents of register REGNO in task TASK.
21287 + */
21288 +static int ptrace_put_reg(struct task_struct *task, int regno,
21289 +                         unsigned long data)
21290 +{
21291 +       if (regno <= sizeof(struct pt_regs) && regno != PT_FRAME_TYPE) {
21292 +               struct pt_regs *pt_regs = task_pt_regs(task);
21293 +               *(unsigned long *)((long) pt_regs + regno) = data;
21294 +               return 0;
21295 +       }
21296 +       return -EIO;
21297 +}
21298 +
21299 +/*
21300 + * ptrace_disable_single_step()
21301 + *     Disable Single Step
21302 + */
21303 +static int ptrace_disable_single_step(struct task_struct *task)
21304 +{
21305 +       /*
21306 +        * Single Step not yet implemented, so must always be disabled
21307 +        */
21308 +       return 0;
21309 +}
21310 +
21311 +/*
21312 + * ptrace_disable()
21313 + *     Make sure the single step bit is not set.
21314 + * Called by kernel/ptrace.c when detaching..
21315 + */
21316 +void ptrace_disable(struct task_struct *child)
21317 +{
21318 +       ptrace_disable_single_step(child);
21319 +}
21320 +
21321 +/*
21322 + * arch_ptrace()
21323 + *     architecture specific ptrace routine.
21324 + */
21325 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
21326 +{
21327 +       int ret;
21328 +       switch (request) {
21329 +       /* when I and D space are separate, these will need to be fixed. */
21330 +       case PTRACE_PEEKTEXT: /* read word at location addr. */
21331 +       case PTRACE_PEEKDATA:
21332 +               ret = generic_ptrace_peekdata(child, addr, data);
21333 +               break;
21334 +
21335 +       /* read the word at location addr in the USER area. */
21336 +       case PTRACE_PEEKUSR: {
21337 +               unsigned long tmp;
21338 +
21339 +               ret = -EIO;
21340 +               if (((unsigned long) addr > PT_INTERP_FDPIC_LOADMAP)
21341 +                   || (addr & 3))
21342 +                       break;
21343 +
21344 +               tmp = 0;  /* Default return condition */
21345 +
21346 +               ret = -EIO;
21347 +               if (addr < sizeof(struct pt_regs)) {
21348 +                       tmp = ptrace_get_reg(child, addr);
21349 +               } else if (addr == PT_TEXT_ADDR) {
21350 +                       tmp = child->mm->start_code;
21351 +               } else if (addr == PT_TEXT_END_ADDR) {
21352 +                       tmp = child->mm->end_code;
21353 +               } else if (addr == PT_DATA_ADDR) {
21354 +                       tmp = child->mm->start_data;
21355 +               } else if (addr == PT_EXEC_FDPIC_LOADMAP) {
21356 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21357 +                       tmp = child->mm->context.exec_fdpic_loadmap;
21358 +#endif
21359 +               } else if (addr == PT_INTERP_FDPIC_LOADMAP) {
21360 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21361 +                       tmp = child->mm->context.interp_fdpic_loadmap;
21362 +#endif
21363 +               } else {
21364 +                       break;
21365 +               }
21366 +
21367 +               ret = put_user(tmp, (unsigned long *)data);
21368 +               break;
21369 +       }
21370 +
21371 +       case PTRACE_POKETEXT: /* write the word at location addr. */
21372 +       case PTRACE_POKEDATA:
21373 +               ret = generic_ptrace_pokedata(child, addr, data);
21374 +
21375 +               /*
21376 +                * If we just changed some code so we need to
21377 +                * correct the caches
21378 +                */
21379 +               if (request == PTRACE_POKETEXT && ret == 0) {
21380 +                       flush_icache_range(addr, addr + 4);
21381 +               }
21382 +               break;
21383 +
21384 +       case PTRACE_POKEUSR: /* write the word at location addr
21385 +                             * in the USER area */
21386 +               ret = -EIO;
21387 +
21388 +               if (((unsigned long) addr > PT_DATA_ADDR) || (addr & 3))
21389 +                       break;
21390 +
21391 +               if (addr < sizeof(struct pt_regs)) {
21392 +                       ret = ptrace_put_reg(child, addr, data);
21393 +               }
21394 +               break;
21395 +
21396 +       case PTRACE_SYSCALL: /* continue and stop at next (return from)
21397 +                             * syscall */
21398 +       case PTRACE_CONT: { /* restart after signal. */
21399 +
21400 +               ret = -EIO;
21401 +               if (!valid_signal(data))
21402 +                       break;
21403 +               if (request == PTRACE_SYSCALL)
21404 +                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21405 +               else
21406 +                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21407 +               child->exit_code = data;
21408 +               /* make sure the single step bit is not set. */
21409 +               ptrace_disable_single_step(child);
21410 +               wake_up_process(child);
21411 +               ret = 0;
21412 +               break;
21413 +       }
21414 +
21415 +       /*
21416 +        * make the child exit.  Best I can do is send it a sigkill.
21417 +        * perhaps it should be put in the status that it wants to exit.
21418 +        */
21419 +       case PTRACE_KILL: {
21420 +               ret = 0;
21421 +               if (child->exit_state == EXIT_ZOMBIE) /* already dead */
21422 +                       break;
21423 +               child->exit_code = SIGKILL;
21424 +               /* make sure the single step bit is not set. */
21425 +               ptrace_disable_single_step(child);
21426 +               wake_up_process(child);
21427 +               break;
21428 +       }
21429 +
21430 +       case PTRACE_DETACH:     /* detach a process that was attached. */
21431 +               ret = ptrace_detach(child, data);
21432 +               break;
21433 +
21434 +       case PTRACE_GETREGS:    /* Get all gp regs from the child. */
21435 +               ptrace_getregs(child, (unsigned long *)data);
21436 +               ret = 0;
21437 +               break;
21438 +
21439 +       case PTRACE_SETREGS: { /* Set all gp regs in the child. */
21440 +               int i;
21441 +               unsigned long tmp;
21442 +               int count = sizeof(struct pt_regs) / sizeof(unsigned long);
21443 +               for (i = 0; i < count; i++) {
21444 +                       if (get_user(tmp, (unsigned long *) data)) {
21445 +                               ret = -EFAULT;
21446 +                               break;
21447 +                       }
21448 +                       ptrace_put_reg(child, sizeof(unsigned long) * i, tmp);
21449 +                       data += sizeof(long);
21450 +               }
21451 +               ret = 0;
21452 +               break;
21453 +       }
21454 +
21455 +       default:
21456 +               return ptrace_request(child, request, addr, data);
21457 +               break;
21458 +       }
21459 +       return ret;
21460 +}
21461 +/*
21462 + * syscall_trace
21463 + *
21464 + * called by syscall enter/exit when the TIF_SYSCALL_TRACE bit is set.
21465 + */
21466 +asmlinkage void syscall_trace(void)
21467 +{
21468 +       struct task_struct *cur = current;
21469 +       if (!test_thread_flag(TIF_SYSCALL_TRACE))
21470 +               return;
21471 +       if (!(cur->ptrace & PT_PTRACED))
21472 +               return;
21473 +       ptrace_notify(SIGTRAP | ((cur->ptrace & PT_TRACESYSGOOD)
21474 +                                ? 0x80 : 0));
21475 +       /*
21476 +        * this isn't the same as continuing with a signal, but it will do
21477 +        * for normal use.  strace only continues with a signal if the
21478 +        * stopping signal is not SIGTRAP.  -brl
21479 +        */
21480 +       if (cur->exit_code) {
21481 +               send_sig(cur->exit_code, current, 1);
21482 +               current->exit_code = 0;
21483 +       }
21484 +}
21485 --- /dev/null
21486 +++ b/arch/ubicom32/kernel/semaphore.c
21487 @@ -0,0 +1,159 @@
21488 +/*
21489 + * arch/ubicom32/kernel/semaphore.c
21490 + *   Ubicom32 architecture semaphore implementation.
21491 + *
21492 + * (C) Copyright 2009, Ubicom, Inc.
21493 + *
21494 + * This file is part of the Ubicom32 Linux Kernel Port.
21495 + *
21496 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21497 + * it and/or modify it under the terms of the GNU General Public License
21498 + * as published by the Free Software Foundation, either version 2 of the
21499 + * License, or (at your option) any later version.
21500 + *
21501 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21502 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21503 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21504 + * the GNU General Public License for more details.
21505 + *
21506 + * You should have received a copy of the GNU General Public License
21507 + * along with the Ubicom32 Linux Kernel Port.  If not,
21508 + * see <http://www.gnu.org/licenses/>.
21509 + *
21510 + * Ubicom32 implementation derived from (with many thanks):
21511 + *   arch/m68knommu
21512 + *   arch/blackfin
21513 + *   arch/parisc
21514 + */
21515 +/*
21516 + *  Generic semaphore code. Buyer beware. Do your own
21517 + * specific changes in <asm/semaphore-helper.h>
21518 + */
21519 +
21520 +#include <linux/sched.h>
21521 +#include <linux/err.h>
21522 +#include <linux/init.h>
21523 +#include <asm/semaphore-helper.h>
21524 +
21525 +#ifndef CONFIG_RMW_INSNS
21526 +spinlock_t semaphore_wake_lock;
21527 +#endif
21528 +
21529 +/*
21530 + * Semaphores are implemented using a two-way counter:
21531 + * The "count" variable is decremented for each process
21532 + * that tries to sleep, while the "waking" variable is
21533 + * incremented when the "up()" code goes to wake up waiting
21534 + * processes.
21535 + *
21536 + * Notably, the inline "up()" and "down()" functions can
21537 + * efficiently test if they need to do any extra work (up
21538 + * needs to do something only if count was negative before
21539 + * the increment operation.
21540 + *
21541 + * waking_non_zero() (from asm/semaphore.h) must execute
21542 + * atomically.
21543 + *
21544 + * When __up() is called, the count was negative before
21545 + * incrementing it, and we need to wake up somebody.
21546 + *
21547 + * This routine adds one to the count of processes that need to
21548 + * wake up and exit.  ALL waiting processes actually wake up but
21549 + * only the one that gets to the "waking" field first will gate
21550 + * through and acquire the semaphore.  The others will go back
21551 + * to sleep.
21552 + *
21553 + * Note that these functions are only called when there is
21554 + * contention on the lock, and as such all this is the
21555 + * "non-critical" part of the whole semaphore business. The
21556 + * critical part is the inline stuff in <asm/semaphore.h>
21557 + * where we want to avoid any extra jumps and calls.
21558 + */
21559 +void __up(struct semaphore *sem)
21560 +{
21561 +       wake_one_more(sem);
21562 +       wake_up(&sem->wait);
21563 +}
21564 +
21565 +/*
21566 + * Perform the "down" function.  Return zero for semaphore acquired,
21567 + * return negative for signalled out of the function.
21568 + *
21569 + * If called from __down, the return is ignored and the wait loop is
21570 + * not interruptible.  This means that a task waiting on a semaphore
21571 + * using "down()" cannot be killed until someone does an "up()" on
21572 + * the semaphore.
21573 + *
21574 + * If called from __down_interruptible, the return value gets checked
21575 + * upon return.  If the return value is negative then the task continues
21576 + * with the negative value in the return register (it can be tested by
21577 + * the caller).
21578 + *
21579 + * Either form may be used in conjunction with "up()".
21580 + *
21581 + */
21582 +
21583 +
21584 +#define DOWN_HEAD(task_state)                                          \
21585 +                                                                       \
21586 +                                                                       \
21587 +       current->state = (task_state);                                  \
21588 +       add_wait_queue(&sem->wait, &wait);                              \
21589 +                                                                       \
21590 +       /*                                                              \
21591 +        * Ok, we're set up.  sem->count is known to be less than zero  \
21592 +        * so we must wait.                                             \
21593 +        *                                                              \
21594 +        * We can let go the lock for purposes of waiting.              \
21595 +        * We re-acquire it after awaking so as to protect              \
21596 +        * all semaphore operations.                                    \
21597 +        *                                                              \
21598 +        * If "up()" is called before we call waking_non_zero() then    \
21599 +        * we will catch it right away.  If it is called later then     \
21600 +        * we will have to go through a wakeup cycle to catch it.       \
21601 +        *                                                              \
21602 +        * Multiple waiters contend for the semaphore lock to see       \
21603 +        * who gets to gate through and who has to wait some more.      \
21604 +        */                                                             \
21605 +       for (;;) {
21606 +
21607 +#define DOWN_TAIL(task_state)                  \
21608 +               current->state = (task_state);  \
21609 +       }                                       \
21610 +       current->state = TASK_RUNNING;          \
21611 +       remove_wait_queue(&sem->wait, &wait);
21612 +
21613 +void __sched __down(struct semaphore *sem)
21614 +{
21615 +       DECLARE_WAITQUEUE(wait, current);
21616 +
21617 +       DOWN_HEAD(TASK_UNINTERRUPTIBLE)
21618 +       if (waking_non_zero(sem))
21619 +               break;
21620 +       schedule();
21621 +       DOWN_TAIL(TASK_UNINTERRUPTIBLE)
21622 +}
21623 +
21624 +int __sched __down_interruptible(struct semaphore *sem)
21625 +{
21626 +       DECLARE_WAITQUEUE(wait, current);
21627 +       int ret = 0;
21628 +
21629 +       DOWN_HEAD(TASK_INTERRUPTIBLE)
21630 +
21631 +       ret = waking_non_zero_interruptible(sem, current);
21632 +       if (ret) {
21633 +               if (ret == 1)
21634 +                       /* ret != 0 only if we get interrupted -arca */
21635 +                       ret = 0;
21636 +               break;
21637 +       }
21638 +       schedule();
21639 +       DOWN_TAIL(TASK_INTERRUPTIBLE)
21640 +       return ret;
21641 +}
21642 +
21643 +int __down_trylock(struct semaphore *sem)
21644 +{
21645 +       return waking_non_zero_trylock(sem);
21646 +}
21647 --- /dev/null
21648 +++ b/arch/ubicom32/kernel/setup.c
21649 @@ -0,0 +1,194 @@
21650 +/*
21651 + * arch/ubicom32/kernel/setup.c
21652 + *   Ubicom32 architecture-dependent parts of system setup.
21653 + *
21654 + * (C) Copyright 2009, Ubicom, Inc.
21655 + * Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com)
21656 + * Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org>
21657 + * Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
21658 + * Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
21659 + * Copyright (C) 1995       Hamish Macdonald
21660 + * Copyright (C) 2000       Lineo Inc. (www.lineo.com)
21661 + * Copyright (C) 2001      Lineo, Inc. <www.lineo.com>
21662 + * 68VZ328 Fixes/support    Evan Stawnyczy <e@lineo.ca>
21663 + *
21664 + * This file is part of the Ubicom32 Linux Kernel Port.
21665 + *
21666 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21667 + * it and/or modify it under the terms of the GNU General Public License
21668 + * as published by the Free Software Foundation, either version 2 of the
21669 + * License, or (at your option) any later version.
21670 + *
21671 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21672 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21673 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21674 + * the GNU General Public License for more details.
21675 + *
21676 + * You should have received a copy of the GNU General Public License
21677 + * along with the Ubicom32 Linux Kernel Port.  If not,
21678 + * see <http://www.gnu.org/licenses/>.
21679 + *
21680 + * Ubicom32 implementation derived from (with many thanks):
21681 + *   arch/m68knommu
21682 + *   arch/blackfin
21683 + *   arch/parisc
21684 + */
21685 +
21686 +#include <linux/kernel.h>
21687 +#include <linux/sched.h>
21688 +#include <linux/delay.h>
21689 +#include <linux/interrupt.h>
21690 +#include <linux/fb.h>
21691 +#include <linux/module.h>
21692 +#include <linux/console.h>
21693 +#include <linux/errno.h>
21694 +#include <linux/string.h>
21695 +#include <linux/bootmem.h>
21696 +#include <linux/seq_file.h>
21697 +#include <linux/init.h>
21698 +
21699 +#include <asm/devtree.h>
21700 +#include <asm/setup.h>
21701 +#include <asm/irq.h>
21702 +#include <asm/machdep.h>
21703 +#include <asm/pgtable.h>
21704 +#include <asm/pgalloc.h>
21705 +#include <asm/ubicom32-common.h>
21706 +#include <asm/processor.h>
21707 +#include <asm/bootargs.h>
21708 +#include <asm/thread.h>
21709 +
21710 +unsigned long memory_start;
21711 +EXPORT_SYMBOL(memory_start);
21712 +
21713 +unsigned long memory_end;
21714 +EXPORT_SYMBOL(memory_end);
21715 +
21716 +static char __initdata command_line[COMMAND_LINE_SIZE];
21717 +#ifdef CONFIG_CMDLINE_BOOL
21718 +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
21719 +#endif
21720 +
21721 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
21722 +
21723 +/*
21724 + * setup_arch()
21725 + *     Setup the architecture dependent portions of the system.
21726 + */
21727 +void __init setup_arch(char **cmdline_p)
21728 +{
21729 +       int bootmap_size;
21730 +       unsigned long ram_start;
21731 +
21732 +       processor_init();
21733 +       bootargs_init();
21734 +
21735 +       /*
21736 +        * Use the link for memory_start from the link and the processor
21737 +        * node for memory_end.
21738 +        */
21739 +       memory_start = PAGE_ALIGN(((unsigned long)&_end));
21740 +       processor_dram(&ram_start, &memory_end);
21741 +
21742 +       init_mm.start_code = (unsigned long) &_stext;
21743 +       init_mm.end_code = (unsigned long) &_etext;
21744 +       init_mm.end_data = (unsigned long) &_edata;
21745 +       init_mm.brk = (unsigned long) 0;
21746 +
21747 +       /*
21748 +        * bootexec copies the original default command line to end of memory.
21749 +        * u-boot can modify it there (i.e. to enable network boot) and the
21750 +        * kernel picks up the modified version.
21751 +        *
21752 +        * mainexec creates a `new default' command_line which is in the
21753 +        * bootargs devnode. It is updated on every firmware update but
21754 +        * not used at the moment.
21755 +        */
21756 +       strlcpy(boot_command_line, (char *)(memory_end - COMMAND_LINE_SIZE), COMMAND_LINE_SIZE);
21757 +
21758 +#ifdef CONFIG_CMDLINE_BOOL
21759 +#ifdef CONFIG_CMDLINE_OVERRIDE
21760 +       strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21761 +#else
21762 +       if (builtin_cmdline[0]) {
21763 +               /* append boot loader cmdline to builtin */
21764 +               strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
21765 +               strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
21766 +               strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21767 +       }
21768 +#endif
21769 +#endif
21770 +
21771 +       strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
21772 +       *cmdline_p = command_line;
21773 +
21774 +       parse_early_param();
21775 +
21776 +       printk(KERN_INFO "%s Processor, Ubicom, Inc. <www.ubicom.com>\n", CPU);
21777 +
21778 +#if defined(DEBUG)
21779 +       printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
21780 +               "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
21781 +               (int) &_sdata, (int) &_edata,
21782 +               (int) &_sbss, (int) &_ebss);
21783 +       printk(KERN_DEBUG "MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
21784 +               (int) &_ebss, (int) memory_start,
21785 +               (int) memory_start, (int) memory_end);
21786 +#endif
21787 +
21788 +#ifdef DEBUG
21789 +       if (strlen(*cmdline_p))
21790 +               printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
21791 +#endif
21792 +
21793 +#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
21794 +       conswitchp = &dummy_con;
21795 +#endif
21796 +
21797 +       /*
21798 +        * If we have a device tree, see if we have the nodes we need.
21799 +        */
21800 +       if (devtree) {
21801 +               devtree_print();
21802 +       }
21803 +
21804 +       /*
21805 +        * From the arm initialization comment:
21806 +        *
21807 +        * This doesn't seem to be used by the Linux memory manager any
21808 +        * more, but is used by ll_rw_block.  If we can get rid of it, we
21809 +        * also get rid of some of the stuff above as well.
21810 +        *
21811 +        * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
21812 +        * the system, not the maximum PFN.
21813 +        */
21814 +       max_pfn = max_low_pfn = (memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
21815 +
21816 +       /*
21817 +        * Give all the memory to the bootmap allocator, tell it to put the
21818 +        * boot mem_map at the start of memory.
21819 +        */
21820 +       bootmap_size = init_bootmem_node(
21821 +                       NODE_DATA(0),
21822 +                       memory_start >> PAGE_SHIFT,     /* map goes here */
21823 +                       PAGE_OFFSET >> PAGE_SHIFT,      /* 0 on coldfire */
21824 +                       memory_end >> PAGE_SHIFT);
21825 +       /*
21826 +        * Free the usable memory, we have to make sure we do not free
21827 +        * the bootmem bitmap so we then reserve it after freeing it :-)
21828 +        */
21829 +       free_bootmem(memory_start, memory_end - memory_start);
21830 +       reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
21831 +
21832 +       /*
21833 +        * Get kmalloc into gear.
21834 +        */
21835 +       paging_init();
21836 +
21837 +       /*
21838 +        * Fix up the thread_info structure, indicate this is a mainline Linux
21839 +        * thread and setup the sw_ksp().
21840 +        */
21841 +       sw_ksp[thread_get_self()] = (unsigned int) current_thread_info();
21842 +       thread_set_mainline(thread_get_self());
21843 +}
21844 --- /dev/null
21845 +++ b/arch/ubicom32/kernel/signal.c
21846 @@ -0,0 +1,458 @@
21847 +/*
21848 + * arch/ubicom32/kernel/signal.c
21849 + *   Ubicom32 architecture signal handling implementation.
21850 + *
21851 + * (C) Copyright 2009, Ubicom, Inc.
21852 + * Copyright (C) 1991, 1992  Linus Torvalds
21853 + * Linux/m68k support by Hamish Macdonald
21854 + * 68060 fixes by Jesper Skov
21855 + * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
21856 + * mathemu support by Roman Zippel
21857 + * ++roman (07/09/96): implemented signal stacks
21858 + *
21859 + * This file is part of the Ubicom32 Linux Kernel Port.
21860 + *
21861 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21862 + * it and/or modify it under the terms of the GNU General Public License
21863 + * as published by the Free Software Foundation, either version 2 of the
21864 + * License, or (at your option) any later version.
21865 + *
21866 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21867 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21868 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21869 + * the GNU General Public License for more details.
21870 + *
21871 + * You should have received a copy of the GNU General Public License
21872 + * along with the Ubicom32 Linux Kernel Port.  If not,
21873 + * see <http://www.gnu.org/licenses/>.
21874 + *
21875 + * Ubicom32 implementation derived from (with many thanks):
21876 + *   arch/m68knommu
21877 + *   arch/blackfin
21878 + *   arch/parisc
21879 + *
21880 + * mathemu support by Roman Zippel
21881 + *  (Note: fpstate in the signal context is completely ignored for the emulator
21882 + *         and the internal floating point format is put on stack)
21883 + *
21884 + * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
21885 + * Atari :-) Current limitation: Only one sigstack can be active at one time.
21886 + * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
21887 + * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
21888 + * signal handlers!
21889 + */
21890 +
21891 +#include <linux/module.h>
21892 +#include <linux/sched.h>
21893 +#include <linux/mm.h>
21894 +#include <linux/kernel.h>
21895 +#include <linux/signal.h>
21896 +#include <linux/syscalls.h>
21897 +#include <linux/errno.h>
21898 +#include <linux/wait.h>
21899 +#include <linux/ptrace.h>
21900 +#include <linux/unistd.h>
21901 +#include <linux/stddef.h>
21902 +#include <linux/highuid.h>
21903 +#include <linux/tty.h>
21904 +#include <linux/personality.h>
21905 +#include <linux/binfmts.h>
21906 +
21907 +#include <asm/setup.h>
21908 +#include <asm/uaccess.h>
21909 +#include <asm/pgtable.h>
21910 +#include <asm/traps.h>
21911 +#include <asm/ucontext.h>
21912 +
21913 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
21914 +
21915 +/*
21916 + * asm signal return handlers.
21917 + */
21918 +void ret_from_user_signal(void);
21919 +void ret_from_user_rt_signal(void);
21920 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
21921 +
21922 +/*
21923 + * Common signal suspend implementation
21924 + */
21925 +static int signal_suspend(sigset_t *saveset, struct pt_regs *regs)
21926 +{
21927 +       regs->dn[0] = -EINTR;
21928 +       while (1) {
21929 +               current->state = TASK_INTERRUPTIBLE;
21930 +               schedule();
21931 +               if (!do_signal(saveset, regs)) {
21932 +                       continue;
21933 +               }
21934 +               /*
21935 +                * If the current frame type is a signal trampoline we are
21936 +                * actually going to call the signal handler so we return the
21937 +                * desired d0 as the return value.
21938 +                */
21939 +               if (regs->frame_type == UBICOM32_FRAME_TYPE_SIGTRAMP) {
21940 +                       return regs->dn[0];
21941 +               }
21942 +               return -EINTR;
21943 +       }
21944 +       /*
21945 +        * Should never get here
21946 +        */
21947 +       BUG();
21948 +       return 0;
21949 +}
21950 +
21951 +/*
21952 + * Atomically swap in the new signal mask, and wait for a signal.
21953 + */
21954 +asmlinkage int do_sigsuspend(struct pt_regs *regs)
21955 +{
21956 +       old_sigset_t mask = regs->dn[0];
21957 +       sigset_t saveset;
21958 +
21959 +       mask &= _BLOCKABLE;
21960 +       spin_lock_irq(&current->sighand->siglock);
21961 +       saveset = current->blocked;
21962 +       siginitset(&current->blocked, mask);
21963 +       recalc_sigpending();
21964 +       spin_unlock_irq(&current->sighand->siglock);
21965 +
21966 +       /*
21967 +        * Call common handler
21968 +        */
21969 +       return signal_suspend(&saveset, regs);
21970 +}
21971 +
21972 +asmlinkage int
21973 +do_rt_sigsuspend(struct pt_regs *regs)
21974 +{
21975 +       sigset_t *unewset = (sigset_t *)regs->dn[0];
21976 +       size_t sigsetsize = (size_t)regs->dn[1];
21977 +       sigset_t saveset, newset;
21978 +
21979 +       /* XXX: Don't preclude handling different sized sigset_t's.  */
21980 +       if (sigsetsize != sizeof(sigset_t))
21981 +               return -EINVAL;
21982 +
21983 +       if (copy_from_user(&newset, unewset, sizeof(newset)))
21984 +               return -EFAULT;
21985 +       sigdelsetmask(&newset, ~_BLOCKABLE);
21986 +
21987 +       spin_lock_irq(&current->sighand->siglock);
21988 +       saveset = current->blocked;
21989 +       current->blocked = newset;
21990 +       recalc_sigpending();
21991 +       spin_unlock_irq(&current->sighand->siglock);
21992 +
21993 +       /*
21994 +        * Call common handler
21995 +        */
21996 +       return signal_suspend(&saveset, regs);
21997 +}
21998 +
21999 +asmlinkage int
22000 +sys_sigaction(int sig, const struct old_sigaction *act,
22001 +             struct old_sigaction *oact)
22002 +{
22003 +       struct k_sigaction new_ka, old_ka;
22004 +       int ret;
22005 +
22006 +       if (act) {
22007 +               old_sigset_t mask;
22008 +               if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
22009 +                   __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
22010 +                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
22011 +                       return -EFAULT;
22012 +               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
22013 +               __get_user(mask, &act->sa_mask);
22014 +               siginitset(&new_ka.sa.sa_mask, mask);
22015 +       }
22016 +
22017 +       ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
22018 +
22019 +       if (!ret && oact) {
22020 +               if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
22021 +                   __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
22022 +                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
22023 +                       return -EFAULT;
22024 +               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
22025 +               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
22026 +       }
22027 +
22028 +       return ret;
22029 +}
22030 +
22031 +asmlinkage int
22032 +do_sys_sigaltstack(struct pt_regs *regs)
22033 +{
22034 +       const stack_t *uss = (stack_t *) regs->dn[0];
22035 +       stack_t *uoss = (stack_t *)regs->dn[1];
22036 +       return do_sigaltstack(uss, uoss, regs->an[7]);
22037 +}
22038 +
22039 +/*
22040 + * fdpic_func_descriptor describes sa_handler when the application is FDPIC
22041 + */
22042 +struct fdpic_func_descriptor {
22043 +       unsigned long   text;
22044 +       unsigned long   GOT;
22045 +};
22046 +
22047 +/*
22048 + * rt_sigframe is stored on the user stack immediately before (above)
22049 + * the signal handlers stack.
22050 + */
22051 +struct rt_sigframe
22052 +{
22053 +       unsigned long syscall_number;   /* This holds __NR_rt_sigreturn. */
22054 +       unsigned long restore_all_regs; /* This field gets set to 1 if the frame
22055 +                                        * type is TRAP or INTERRUPT. */
22056 +       siginfo_t *info;
22057 +       struct ucontext uc;
22058 +       int sig;
22059 +       void *pretcode;
22060 +};
22061 +
22062 +/*
22063 + * Do a signal return; undo the signal stack.
22064 + */
22065 +asmlinkage int do_sigreturn(unsigned long __unused)
22066 +{
22067 +       BUG();
22068 +       return 0;
22069 +}
22070 +
22071 +asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
22072 +{
22073 +       unsigned long usp = regs->an[7];
22074 +       struct rt_sigframe *frame = (struct rt_sigframe *)(usp);
22075 +       sigset_t set;
22076 +
22077 +       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
22078 +               goto badframe;
22079 +       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
22080 +               goto badframe;
22081 +
22082 +       sigdelsetmask(&set, ~_BLOCKABLE);
22083 +       spin_lock_irq(&current->sighand->siglock);
22084 +       current->blocked = set;
22085 +       recalc_sigpending();
22086 +       spin_unlock_irq(&current->sighand->siglock);
22087 +
22088 +       if (copy_from_user(regs, &frame->uc.uc_mcontext, sizeof(struct pt_regs)))
22089 +               goto badframe;
22090 +       return regs->dn[0];
22091 +
22092 +badframe:
22093 +       force_sig(SIGSEGV, current);
22094 +       return 0;
22095 +}
22096 +
22097 +static inline void *
22098 +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
22099 +{
22100 +       unsigned long usp;
22101 +
22102 +       /* Default to using normal stack.  */
22103 +       usp = regs->an[7];
22104 +
22105 +       /* This is the X/Open sanctioned signal stack switching.  */
22106 +       if (ka->sa.sa_flags & SA_ONSTACK) {
22107 +               if (!sas_ss_flags(usp))
22108 +                       usp = current->sas_ss_sp + current->sas_ss_size;
22109 +       }
22110 +       return (void *)((usp - frame_size) & ~0x3);
22111 +}
22112 +
22113 +/*
22114 + * signal_trampoline:  Defined in ubicom32_syscall.S
22115 + */
22116 +asmlinkage void signal_trampoline(void)__attribute__((naked));
22117 +
22118 +static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
22119 +                           sigset_t *set, struct pt_regs *regs)
22120 +{
22121 +       struct rt_sigframe *frame;
22122 +       int err = 0;
22123 +
22124 +       frame = (struct rt_sigframe *) get_sigframe(ka, regs, sizeof(*frame));
22125 +
22126 +       /*
22127 +        * The 'err |=' have been may criticized as bad code style, but I
22128 +        * strongly suspect that we want this code to be fast.  So for
22129 +        * now it stays as is.
22130 +        */
22131 +       err |= __put_user( (  (current_thread_info()->exec_domain)
22132 +                          && (current_thread_info()->exec_domain->signal_invmap)
22133 +                          && (sig < 32) )
22134 +                          ? current_thread_info()->exec_domain->signal_invmap[sig]
22135 +                          : sig, &frame->sig);
22136 +       err |= __put_user(info, &frame->info);
22137 +
22138 +       /* Create the ucontext.  */
22139 +       err |= __put_user(0, &frame->uc.uc_flags);
22140 +       err |= __put_user(0, &frame->uc.uc_link);
22141 +       err |= __put_user((void *)current->sas_ss_sp,
22142 +                         &frame->uc.uc_stack.ss_sp);
22143 +       err |= __put_user(sas_ss_flags(regs->an[7]),
22144 +                         &frame->uc.uc_stack.ss_flags);
22145 +       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
22146 +       err |= __put_user(__NR_rt_sigreturn, &frame->syscall_number);
22147 +       if ((regs->frame_type == UBICOM32_FRAME_TYPE_TRAP) ||
22148 +           (regs->frame_type == UBICOM32_FRAME_TYPE_INTERRUPT)) {
22149 +               err |= __put_user(1, &frame->restore_all_regs);
22150 +       } else {
22151 +               err |= __put_user(0, &frame->restore_all_regs);
22152 +       }
22153 +       err |= copy_to_user (&frame->uc.uc_mcontext.sc_regs, regs, sizeof(struct pt_regs));
22154 +       err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
22155 +
22156 +       if (err)
22157 +               goto give_sigsegv;
22158 +
22159 +       /*
22160 +        * Set up registers for signal handler NOTE: Do not modify dn[14], it
22161 +        * contains the userspace tls pointer, so it important that it carries
22162 +        * over to the signal handler.
22163 +        */
22164 +       regs->an[7] = (unsigned long)frame;
22165 +       regs->pc = (unsigned long) signal_trampoline;
22166 +       regs->an[5] = (unsigned long) signal_trampoline;
22167 +       regs->dn[0] = sig;
22168 +       regs->dn[1] = (unsigned long) frame->info;
22169 +       regs->dn[2] = (unsigned int) &frame->uc;
22170 +
22171 +       /*
22172 +        * If this is FDPIC then the signal handler is actually a function
22173 +        * descriptor.
22174 +        */
22175 +       if (current->personality & FDPIC_FUNCPTRS) {
22176 +               struct fdpic_func_descriptor __user *funcptr =
22177 +                       (struct fdpic_func_descriptor *) ka->sa.sa_handler;
22178 +               err |= __get_user(regs->dn[3], &funcptr->text);
22179 +               err |= __get_user(regs->an[0], &funcptr->GOT);
22180 +               if (err)
22181 +                       goto give_sigsegv;
22182 +
22183 +               /*
22184 +                * The funcdesc must be in a3 as this is required for the lazy
22185 +                * resolver in ld.so, if the application is not FDPIC a3 is not
22186 +                * used.
22187 +                */
22188 +               regs->an[3] = (unsigned long) funcptr;
22189 +
22190 +       } else {
22191 +               regs->dn[3] = (unsigned long)ka->sa.sa_handler;
22192 +               regs->an[0] = 0;
22193 +       }
22194 +
22195 +       regs->frame_type =  UBICOM32_FRAME_TYPE_SIGTRAMP;
22196 +
22197 +       return;
22198 +
22199 +give_sigsegv:
22200 +       /* user space exception */
22201 +       force_sigsegv(sig, current);
22202 +}
22203 +
22204 +static inline void
22205 +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
22206 +{
22207 +       switch (regs->dn[0]) {
22208 +       case -ERESTARTNOHAND:
22209 +               if (!has_handler)
22210 +                       goto do_restart;
22211 +               regs->dn[0] = -EINTR;
22212 +               break;
22213 +
22214 +       case -ERESTARTSYS:
22215 +               if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
22216 +                       regs->dn[0] = -EINTR;
22217 +                       break;
22218 +               }
22219 +       /* fallthrough */
22220 +       case -ERESTARTNOINTR:
22221 +       do_restart:
22222 +               regs->dn[0] = regs->original_dn_0;
22223 +               regs->pc -= 8;
22224 +               regs->an[5] -= 8;
22225 +               break;
22226 +       }
22227 +}
22228 +
22229 +/*
22230 + * OK, we're invoking a handler
22231 + */
22232 +static void
22233 +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
22234 +             sigset_t *oldset, struct pt_regs *regs)
22235 +{
22236 +       /* are we from a system call? */
22237 +       if (regs->frame_type == -1)
22238 +               /* If so, check system call restarting.. */
22239 +               handle_restart(regs, ka, 1);
22240 +
22241 +       /* set up the stack frame */
22242 +       setup_rt_frame(sig, ka, info, oldset, regs);
22243 +
22244 +       if (ka->sa.sa_flags & SA_ONESHOT)
22245 +               ka->sa.sa_handler = SIG_DFL;
22246 +
22247 +       spin_lock_irq(&current->sighand->siglock);
22248 +       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
22249 +       if (!(ka->sa.sa_flags & SA_NODEFER))
22250 +               sigaddset(&current->blocked,sig);
22251 +       recalc_sigpending();
22252 +       spin_unlock_irq(&current->sighand->siglock);
22253 +}
22254 +
22255 +/*
22256 + * Note that 'init' is a special process: it doesn't get signals it doesn't
22257 + * want to handle. Thus you cannot kill init even with a SIGKILL even by
22258 + * mistake.
22259 + */
22260 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
22261 +{
22262 +       struct k_sigaction ka;
22263 +       siginfo_t info;
22264 +       int signr;
22265 +
22266 +       /*
22267 +        * We want the common case to go fast, which
22268 +        * is why we may in certain cases get here from
22269 +        * kernel mode. Just return without doing anything
22270 +        * if so.
22271 +        */
22272 +       if (!user_mode(regs))
22273 +               return 1;
22274 +
22275 +       if (!oldset)
22276 +               oldset = &current->blocked;
22277 +
22278 +       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
22279 +       if (signr > 0) {
22280 +               /* Whee!  Actually deliver the signal.  */
22281 +               handle_signal(signr, &ka, &info, oldset, regs);
22282 +               return 1;
22283 +       }
22284 +
22285 +       /* Did we come from a system call? */
22286 +       if (regs->frame_type == -1) {
22287 +               /* Restart the system call - no handlers present */
22288 +               handle_restart(regs, NULL, 0);
22289 +       }
22290 +
22291 +       return 0;
22292 +}
22293 +
22294 +/*
22295 + * sys_sigreturn()
22296 + *     Return handler for signal clean-up.
22297 + *
22298 + * NOTE: Ubicom32 does not use this syscall.  Instead we rely
22299 + * on do_rt_sigreturn().
22300 + */
22301 +asmlinkage long sys_sigreturn(void)
22302 +{
22303 +       return -ENOSYS;
22304 +}
22305 --- /dev/null
22306 +++ b/arch/ubicom32/kernel/smp.c
22307 @@ -0,0 +1,806 @@
22308 +/*
22309 + * arch/ubicom32/kernel/smp.c
22310 + *   SMP implementation for Ubicom32 processors.
22311 + *
22312 + * (C) Copyright 2009, Ubicom, Inc.
22313 + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
22314 + * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
22315 + * Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org>
22316 + *
22317 + * This file is part of the Ubicom32 Linux Kernel Port.
22318 + *
22319 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
22320 + * it and/or modify it under the terms of the GNU General Public License
22321 + * as published by the Free Software Foundation, either version 2 of the
22322 + * License, or (at your option) any later version.
22323 + *
22324 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
22325 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22326 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
22327 + * the GNU General Public License for more details.
22328 + *
22329 + * You should have received a copy of the GNU General Public License
22330 + * along with the Ubicom32 Linux Kernel Port.  If not,
22331 + * see <http://www.gnu.org/licenses/>.
22332 + *
22333 + * Ubicom32 implementation derived from (with many thanks):
22334 + *   arch/m68knommu
22335 + *   arch/blackfin
22336 + *   arch/parisc
22337 + */
22338 +
22339 +#include <linux/types.h>
22340 +#include <linux/spinlock.h>
22341 +#include <linux/slab.h>
22342 +
22343 +#include <linux/kernel.h>
22344 +#include <linux/bootmem.h>
22345 +#include <linux/module.h>
22346 +#include <linux/sched.h>
22347 +#include <linux/init.h>
22348 +#include <linux/interrupt.h>
22349 +#include <linux/smp.h>
22350 +#include <linux/kernel_stat.h>
22351 +#include <linux/mm.h>
22352 +#include <linux/err.h>
22353 +#include <linux/delay.h>
22354 +#include <linux/bitops.h>
22355 +#include <linux/cpu.h>
22356 +#include <linux/profile.h>
22357 +#include <linux/delay.h>
22358 +#include <linux/io.h>
22359 +#include <linux/ptrace.h>
22360 +#include <linux/unistd.h>
22361 +#include <linux/irq.h>
22362 +
22363 +#include <asm/system.h>
22364 +#include <asm/atomic.h>
22365 +#include <asm/current.h>
22366 +#include <asm/tlbflush.h>
22367 +#include <asm/timex.h>
22368 +#include <asm/cpu.h>
22369 +#include <asm/irq.h>
22370 +#include <asm/processor.h>
22371 +#include <asm/thread.h>
22372 +#include <asm/sections.h>
22373 +#include <asm/ip5000.h>
22374 +
22375 +/*
22376 + * Mask the debug printout for IPI because they are too verbose
22377 + * for regular debugging.
22378 + */
22379 +
22380 +// #define DEBUG_SMP 1
22381 +#if !defined(DEBUG_SMP)
22382 +#define smp_debug(lvl, ...)
22383 +#else
22384 +static unsigned int smp_debug_lvl = 50;
22385 +#define smp_debug(lvl, printargs...)           \
22386 +       if (lvl >= smp_debug_lvl) {             \
22387 +                       printk(printargs);      \
22388 +       }
22389 +#endif
22390 +
22391 +#if !defined(DEBUG_SMP)
22392 +#define DEBUG_ASSERT(cond)
22393 +#else
22394 +#define DEBUG_ASSERT(cond) \
22395 +       if (!(cond)) { \
22396 +               THREAD_STALL; \
22397 +       }
22398 +#endif
22399 +
22400 +/*
22401 + * List of IPI Commands (more than one can be set at a time).
22402 + */
22403 +enum ipi_message_type {
22404 +       IPI_NOP,
22405 +       IPI_RESCHEDULE,
22406 +       IPI_CALL_FUNC,
22407 +       IPI_CALL_FUNC_SINGLE,
22408 +       IPI_CPU_STOP,
22409 +       IPI_CPU_TIMER,
22410 +};
22411 +
22412 +/*
22413 + * We maintain a hardware thread oriented view of online threads
22414 + * and those involved or needing IPI.
22415 + */
22416 +static volatile unsigned long smp_online_threads = 0;
22417 +static volatile unsigned long smp_needs_ipi = 0;
22418 +static volatile unsigned long smp_inside_ipi = 0;
22419 +static unsigned long smp_irq_affinity[NR_IRQS];
22420 +
22421 +/*
22422 + * What do we need to track on a per cpu/thread basis?
22423 + */
22424 +DEFINE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
22425 +
22426 +/*
22427 + * Each thread cpuinfo IPI information is guarded by a lock
22428 + * that is kept local to this file.
22429 + */
22430 +DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
22431 +
22432 +/*
22433 + * The IPI(s) are based on a software IRQ through the LDSR.
22434 + */
22435 +unsigned int smp_ipi_irq;
22436 +
22437 +/*
22438 + * Define a spinlock so that only one cpu is able to modify the
22439 + * smp_needs_ipi and to set/clear the IRQ at a time.
22440 + */
22441 +DEFINE_SPINLOCK(smp_ipi_lock);
22442 +
22443 +/*
22444 + * smp_halt_processor()
22445 + *     Halt this hardware thread.
22446 + */
22447 +static void smp_halt_processor(void)
22448 +{
22449 +       int cpuid = thread_get_self();
22450 +       cpu_clear(smp_processor_id(), cpu_online_map);
22451 +       local_irq_disable();
22452 +       printk(KERN_EMERG "cpu[%d] has halted. It is not OK to turn off power \
22453 +               until all cpu's are off.\n", cpuid);
22454 +       for (;;) {
22455 +               thread_suspend();
22456 +       }
22457 +}
22458 +
22459 +/*
22460 + * ipi_interrupt()
22461 + *     Handle an Interprocessor Interrupt.
22462 + */
22463 +static irqreturn_t ipi_interrupt(int irq, void *dev_id)
22464 +{
22465 +       int cpuid = smp_processor_id();
22466 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22467 +       unsigned long ops;
22468 +
22469 +       /*
22470 +        * Count this now; we may make a call that never returns.
22471 +        */
22472 +       p->ipi_count++;
22473 +
22474 +       /*
22475 +        * We are about to process all ops.  If another cpu has stated
22476 +        * that we need an IPI, we will have already processed it.  By
22477 +        * clearing our smp_needs_ipi, and processing all ops,
22478 +        * we reduce the number of IPI interrupts.  However, this introduces
22479 +        * the possibility that smp_needs_ipi will be clear and the soft irq
22480 +        * will have gone off; so we need to make the get_affinity() path
22481 +        * tolerant of spurious interrupts.
22482 +        */
22483 +       spin_lock(&smp_ipi_lock);
22484 +       smp_needs_ipi &= ~(1 << p->tid);
22485 +       spin_unlock(&smp_ipi_lock);
22486 +
22487 +       for (;;) {
22488 +               /*
22489 +                * Read the set of IPI commands we should handle.
22490 +                */
22491 +               spinlock_t *lock = &per_cpu(ipi_lock, cpuid);
22492 +               spin_lock(lock);
22493 +               ops = p->ipi_pending;
22494 +               p->ipi_pending = 0;
22495 +               spin_unlock(lock);
22496 +
22497 +               /*
22498 +                * If we have no IPI commands to execute, break out.
22499 +                */
22500 +               if (!ops) {
22501 +                       break;
22502 +               }
22503 +
22504 +               /*
22505 +                * Execute the set of commands in the ops word, one command
22506 +                * at a time in no particular order.  Strip of each command
22507 +                * as we execute it.
22508 +                */
22509 +               while (ops) {
22510 +                       unsigned long which = ffz(~ops);
22511 +                       ops &= ~(1 << which);
22512 +
22513 +                       BUG_ON(!irqs_disabled());
22514 +                       switch (which) {
22515 +                       case IPI_NOP:
22516 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22517 +                                         "IPI_NOP\n", cpuid);
22518 +                               break;
22519 +
22520 +                       case IPI_RESCHEDULE:
22521 +                               /*
22522 +                                * Reschedule callback.  Everything to be
22523 +                                * done is done by the interrupt return path.
22524 +                                */
22525 +                               smp_debug(200, KERN_INFO "cpu[%d]: "
22526 +                                         "IPI_RESCHEDULE\n", cpuid);
22527 +                               break;
22528 +
22529 +                       case IPI_CALL_FUNC:
22530 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22531 +                                         "IPI_CALL_FUNC\n", cpuid);
22532 +                               generic_smp_call_function_interrupt();
22533 +                               break;
22534 +
22535 +                       case IPI_CALL_FUNC_SINGLE:
22536 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22537 +                                         "IPI_CALL_FUNC_SINGLE\n", cpuid);
22538 +                               generic_smp_call_function_single_interrupt();
22539 +                               break;
22540 +
22541 +                       case IPI_CPU_STOP:
22542 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22543 +                                         "IPI_CPU_STOP\n", cpuid);
22544 +                               smp_halt_processor();
22545 +                               break;
22546 +
22547 +#if !defined(CONFIG_LOCAL_TIMERS)
22548 +                       case IPI_CPU_TIMER:
22549 +                               smp_debug(100, KERN_INFO "cpu[%d]: "
22550 +                                         "IPI_CPU_TIMER\n", cpuid);
22551 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
22552 +                               local_timer_interrupt();
22553 +#else
22554 +                               update_process_times(user_mode(get_irq_regs()));
22555 +                               profile_tick(CPU_PROFILING);
22556 +#endif
22557 +#endif
22558 +                               break;
22559 +
22560 +                       default:
22561 +                               printk(KERN_CRIT "cpu[%d]: "
22562 +                                         "Unknown IPI: %lu\n", cpuid, which);
22563 +
22564 +                               return IRQ_NONE;
22565 +                       }
22566 +
22567 +                       /*
22568 +                        * Let in any pending interrupts
22569 +                        */
22570 +                       BUG_ON(!irqs_disabled());
22571 +                       local_irq_enable();
22572 +                       local_irq_disable();
22573 +               }
22574 +       }
22575 +       return IRQ_HANDLED;
22576 +}
22577 +
22578 +/*
22579 + * ipi_send()
22580 + *     Send an Interprocessor Interrupt.
22581 + */
22582 +static void ipi_send(int cpu, enum ipi_message_type op)
22583 +{
22584 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
22585 +       spinlock_t *lock = &per_cpu(ipi_lock, cpu);
22586 +       unsigned long flags;
22587 +
22588 +       /*
22589 +        * We protect the setting of the ipi_pending field and ensure
22590 +        * that the ipi delivery mechanism and interrupt are atomically
22591 +        * handled.
22592 +        */
22593 +       spin_lock_irqsave(lock, flags);
22594 +       p->ipi_pending |= 1 << op;
22595 +       spin_unlock_irqrestore(lock, flags);
22596 +
22597 +       spin_lock_irqsave(&smp_ipi_lock, flags);
22598 +       smp_needs_ipi |= (1 << p->tid);
22599 +       ubicom32_set_interrupt(smp_ipi_irq);
22600 +       spin_unlock_irqrestore(&smp_ipi_lock, flags);
22601 +       smp_debug(100, KERN_INFO "cpu[%d]: send: %d\n", cpu, op);
22602 +}
22603 +
22604 +/*
22605 + * ipi_send_mask
22606 + *     Send an IPI to each cpu in mask.
22607 + */
22608 +static inline void ipi_send_mask(unsigned int op, const struct cpumask mask)
22609 +{
22610 +       int cpu;
22611 +       for_each_cpu_mask(cpu, mask) {
22612 +               ipi_send(cpu, op);
22613 +       }
22614 +}
22615 +
22616 +/*
22617 + * ipi_send_allbutself()
22618 + *     Send an IPI to all threads but ourselves.
22619 + */
22620 +static inline void ipi_send_allbutself(unsigned int op)
22621 +{
22622 +       int self = smp_processor_id();
22623 +       struct cpumask result;
22624 +       cpumask_copy(&result, &cpu_online_map);
22625 +       cpu_clear(self, result);
22626 +       ipi_send_mask(op, result);
22627 +}
22628 +
22629 +/*
22630 + * smp_enable_vector()
22631 + */
22632 +static void smp_enable_vector(unsigned int irq)
22633 +{
22634 +       ubicom32_clear_interrupt(smp_ipi_irq);
22635 +       ldsr_enable_vector(irq);
22636 +}
22637 +
22638 +/*
22639 + * smp_disable_vector()
22640 + *     Disable the interrupt by clearing the appropriate bit in the
22641 + *     LDSR Mask Register.
22642 + */
22643 +static void smp_disable_vector(unsigned int irq)
22644 +{
22645 +       ldsr_disable_vector(irq);
22646 +}
22647 +
22648 +/*
22649 + * smp_mask_vector()
22650 + */
22651 +static void smp_mask_vector(unsigned int irq)
22652 +{
22653 +       ldsr_mask_vector(irq);
22654 +}
22655 +
22656 +/*
22657 + * smp_unmask_vector()
22658 + */
22659 +static void smp_unmask_vector(unsigned int irq)
22660 +{
22661 +       ldsr_unmask_vector(irq);
22662 +}
22663 +
22664 +/*
22665 + * smp_end_vector()
22666 + *     Called once an interrupt is completed (reset the LDSR mask).
22667 + */
22668 +static void smp_end_vector(unsigned int irq)
22669 +{
22670 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, smp_processor_id());
22671 +       spin_lock(&smp_ipi_lock);
22672 +       smp_inside_ipi &= ~(1 << p->tid);
22673 +       if (smp_inside_ipi) {
22674 +               spin_unlock(&smp_ipi_lock);
22675 +               return;
22676 +       }
22677 +       spin_unlock(&smp_ipi_lock);
22678 +       ldsr_unmask_vector(irq);
22679 +       smp_debug(100, KERN_INFO "cpu[%d]: unamesk vector\n", smp_processor_id());
22680 +}
22681 +
22682 +/*
22683 + * Special hanlder functions for SMP.
22684 + */
22685 +static struct irq_chip ubicom32_smp_chip = {
22686 +       .name           = "UbicoIPI",
22687 +       .startup        = NULL,
22688 +       .shutdown       = NULL,
22689 +       .enable         = smp_enable_vector,
22690 +       .disable        = smp_disable_vector,
22691 +       .ack            = NULL,
22692 +       .mask           = smp_mask_vector,
22693 +       .unmask         = smp_unmask_vector,
22694 +       .end            = smp_end_vector,
22695 +};
22696 +
22697 +/*
22698 + * smp_reset_ipi()
22699 + *     None of these cpu(s) got their IPI, turn it back on.
22700 + *
22701 + * Note: This is called by the LDSR which is not a full
22702 + * Linux cpu.  Thus you must use the raw form of locks
22703 + * because lock debugging will not work on the partial
22704 + * cpu nature of the LDSR.
22705 + */
22706 +void smp_reset_ipi(unsigned long mask)
22707 +{
22708 +       __raw_spin_lock(&smp_ipi_lock.raw_lock);
22709 +       smp_needs_ipi |= mask;
22710 +       smp_inside_ipi &= ~mask;
22711 +       ubicom32_set_interrupt(smp_ipi_irq);
22712 +       __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22713 +       smp_debug(100, KERN_INFO "smp: reset IPIs for: 0x%x\n", mask);
22714 +}
22715 +
22716 +/*
22717 + * smp_get_affinity()
22718 + *     Choose the thread affinity for this interrupt.
22719 + *
22720 + * Note: This is called by the LDSR which is not a full
22721 + * Linux cpu.  Thus you must use the raw form of locks
22722 + * because lock debugging will not work on the partial
22723 + * cpu nature of the LDSR.
22724 + */
22725 +unsigned long smp_get_affinity(unsigned int irq, int *all)
22726 +{
22727 +       unsigned long mask = 0;
22728 +
22729 +       /*
22730 +        * Most IRQ(s) are delivered in a round robin fashion.
22731 +        */
22732 +       if (irq != smp_ipi_irq) {
22733 +               unsigned long result = smp_irq_affinity[irq] & smp_online_threads;
22734 +               DEBUG_ASSERT(result);
22735 +               *all = 0;
22736 +               return result;
22737 +       }
22738 +
22739 +       /*
22740 +        * This is an IPI request.  Return all cpu(s) scheduled for an IPI.
22741 +        * We also track those cpu(s) that are going to be "receiving" IPI this
22742 +        * round.  When all CPU(s) have called smp_end_vector(),
22743 +        * we will unmask the IPI interrupt.
22744 +        */
22745 +       __raw_spin_lock(&smp_ipi_lock.raw_lock);
22746 +       ubicom32_clear_interrupt(smp_ipi_irq);
22747 +       if (smp_needs_ipi) {
22748 +               mask = smp_needs_ipi;
22749 +               smp_inside_ipi |= smp_needs_ipi;
22750 +               smp_needs_ipi = 0;
22751 +       }
22752 +       __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22753 +       *all = 1;
22754 +       return mask;
22755 +}
22756 +
22757 +/*
22758 + *  smp_set_affinity()
22759 + *     Set the affinity for this irq but store the value in tid(s).
22760 + */
22761 +void smp_set_affinity(unsigned int irq, const struct cpumask *dest)
22762 +{
22763 +       int cpuid;
22764 +       unsigned long *paffinity = &smp_irq_affinity[irq];
22765 +
22766 +       /*
22767 +        *  If none specified, all cpus are allowed.
22768 +        */
22769 +       if (cpus_empty(*dest)) {
22770 +               *paffinity = 0xffffffff;
22771 +               return;
22772 +       }
22773 +
22774 +       /*
22775 +        * Make sure to clear the old value before setting up the
22776 +        * list.
22777 +        */
22778 +       *paffinity = 0;
22779 +       for_each_cpu_mask(cpuid, *dest) {
22780 +               struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22781 +               *paffinity |= (1 << p->tid);
22782 +       }
22783 +}
22784 +
22785 +/*
22786 + * smp_send_stop()
22787 + *     Send a stop request to all CPU but this one.
22788 + */
22789 +void smp_send_stop(void)
22790 +{
22791 +       ipi_send_allbutself(IPI_CPU_STOP);
22792 +}
22793 +
22794 +/*
22795 + * smp_send_timer_all()
22796 + *     Send all cpu(s) but this one, a request to update times.
22797 + */
22798 +void smp_send_timer_all(void)
22799 +{
22800 +       ipi_send_allbutself(IPI_CPU_TIMER);
22801 +}
22802 +
22803 +/*
22804 + * smp_timer_broadcast()
22805 + *     Use an IPI to broadcast a timer message
22806 + */
22807 +void smp_timer_broadcast(const struct cpumask *mask)
22808 +{
22809 +       ipi_send_mask(IPI_CPU_TIMER, *mask);
22810 +}
22811 +
22812 +/*
22813 + * smp_send_reschedule()
22814 + *     Send a reschedule request to the specified cpu.
22815 + */
22816 +void smp_send_reschedule(int cpu)
22817 +{
22818 +       ipi_send(cpu, IPI_RESCHEDULE);
22819 +}
22820 +
22821 +/*
22822 + * arch_send_call_function_ipi()
22823 + *     Cause each cpu in the mask to call the generic function handler.
22824 + */
22825 +void arch_send_call_function_ipi_mask(const struct cpumask *mask)
22826 +{
22827 +       int cpu;
22828 +       for_each_cpu_mask(cpu, *mask) {
22829 +               ipi_send(cpu, IPI_CALL_FUNC);
22830 +       }
22831 +}
22832 +
22833 +/*
22834 + * arch_send_call_function_single_ipi()
22835 + *     Cause the specified cpu to call the generic function handler.
22836 + */
22837 +void arch_send_call_function_single_ipi(int cpu)
22838 +{
22839 +       ipi_send(cpu, IPI_CALL_FUNC_SINGLE);
22840 +}
22841 +
22842 +/*
22843 + * setup_profiling_timer()
22844 + *     Dummy function created to keep Oprofile happy in the SMP case.
22845 + */
22846 +int setup_profiling_timer(unsigned int multiplier)
22847 +{
22848 +       return 0;
22849 +}
22850 +
22851 +/*
22852 + * smp_mainline_start()
22853 + *     Start a slave thread executing a mainline Linux context.
22854 + */
22855 +static void __init smp_mainline_start(void *arg)
22856 +{
22857 +       int cpuid = smp_processor_id();
22858 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22859 +
22860 +       BUG_ON(p->tid != thread_get_self());
22861 +
22862 +       /*
22863 +        * Well, support 2.4 linux scheme as well.
22864 +        */
22865 +       if (cpu_test_and_set(cpuid, cpu_online_map)) {
22866 +               printk(KERN_CRIT "cpu[%d]: already initialized!\n", cpuid);
22867 +               smp_halt_processor();
22868 +               return;
22869 +       }
22870 +
22871 +       /*
22872 +        * Initialise the idle task for this CPU
22873 +        */
22874 +       atomic_inc(&init_mm.mm_count);
22875 +       current->active_mm = &init_mm;
22876 +       if (current->mm) {
22877 +               printk(KERN_CRIT "cpu[%d]: idle task already has memory "
22878 +                      "management\n", cpuid);
22879 +               smp_halt_processor();
22880 +               return;
22881 +       }
22882 +
22883 +       /*
22884 +        * TODO: X86 does this prior to calling notify, try to understand why?
22885 +        */
22886 +       preempt_disable();
22887 +
22888 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
22889 +       /*
22890 +        * Setup a local timer event so that this cpu will get timer interrupts
22891 +        */
22892 +       if (local_timer_setup(cpuid) == -1) {
22893 +               printk(KERN_CRIT "cpu[%d]: timer alloc failed\n", cpuid);
22894 +               smp_halt_processor();
22895 +               return;
22896 +       }
22897 +#endif
22898 +
22899 +       /*
22900 +        * Notify those interested that we are up and alive.  This must
22901 +        * be done before interrupts are enabled.  It must also be completed
22902 +        * before the bootstrap cpu returns from __cpu_up() (see comment
22903 +        * above cpu_set() of the cpu_online_map).
22904 +        */
22905 +       notify_cpu_starting(cpuid);
22906 +
22907 +       /*
22908 +        * Indicate that this thread is now online and present.   Setting
22909 +        * cpu_online_map has the side effect of allowing the bootstrap
22910 +        * cpu to continue along; so anything that MUST be done prior to the
22911 +        * bootstrap cpu returning from __cpu_up() needs to go above here.
22912 +        */
22913 +       cpu_set(cpuid, cpu_online_map);
22914 +       cpu_set(cpuid, cpu_present_map);
22915 +
22916 +       /*
22917 +        * Maintain a thread mapping in addition to the cpu mapping.
22918 +        */
22919 +       smp_online_threads |= (1 << p->tid);
22920 +
22921 +       /*
22922 +        * Enable interrupts for this thread.
22923 +        */
22924 +       local_irq_enable();
22925 +
22926 +       /*
22927 +        * Enter the idle loop and wait for a timer to schedule some work.
22928 +        */
22929 +       printk(KERN_INFO "cpu[%d]: entering cpu_idle()\n", cpuid);
22930 +       cpu_idle();
22931 +
22932 +       /* Not Reached */
22933 +}
22934 +
22935 +/*
22936 + * smp_cpus_done()
22937 + *     Called once the kernel_init() has brought up all cpu(s).
22938 + */
22939 +void smp_cpus_done(unsigned int cpu_max)
22940 +{
22941 +       /* Do Nothing */
22942 +}
22943 +
22944 +/*
22945 + * __cpu_up()
22946 + *     Called to startup a sepcific cpu.
22947 + */
22948 +int __cpuinit __cpu_up(unsigned int cpu)
22949 +{
22950 +       struct task_struct *idle;
22951 +       unsigned int *stack;
22952 +       long timeout;
22953 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
22954 +
22955 +       /*
22956 +        * Create an idle task for this CPU.
22957 +        */
22958 +       idle = fork_idle(cpu);
22959 +       if (IS_ERR(idle)) {
22960 +               panic("cpu[%d]: fork failed\n", cpu);
22961 +               return -ENOSYS;
22962 +       }
22963 +       task_thread_info(idle)->cpu = cpu;
22964 +
22965 +       /*
22966 +        * Setup the sw_ksp[] to point to this new task.
22967 +        */
22968 +       sw_ksp[p->tid] = (unsigned int)idle->stack;
22969 +       stack = (unsigned int *)(sw_ksp[p->tid] + PAGE_SIZE - 8);
22970 +
22971 +       /*
22972 +        * Cause the specified thread to execute our smp_mainline_start
22973 +        * function as a TYPE_NORMAL thread.
22974 +        */
22975 +       printk(KERN_INFO "cpu[%d]: launching mainline Linux thread\n", cpu);
22976 +       if (thread_start(p->tid, smp_mainline_start, (void *)NULL, stack,
22977 +                        THREAD_TYPE_NORMAL) == -1) {
22978 +               printk(KERN_WARNING "cpu[%d]: failed thread_start\n", cpu);
22979 +               return -ENOSYS;
22980 +       }
22981 +
22982 +       /*
22983 +        * Wait for the thread to start up.  The thread will set
22984 +        * the online bit when it is running.  Our caller execpts the
22985 +        * cpu to be online if we return 0.
22986 +        */
22987 +       for (timeout = 0; timeout < 10000; timeout++) {
22988 +               if (cpu_online(cpu)) {
22989 +                       break;
22990 +               }
22991 +
22992 +               udelay(100);
22993 +               barrier();
22994 +               continue;
22995 +       }
22996 +
22997 +       if (!cpu_online(cpu)) {
22998 +               printk(KERN_CRIT "cpu[%d]: failed to live after %ld us\n",
22999 +                      cpu, timeout * 100);
23000 +               return -ENOSYS;
23001 +       }
23002 +
23003 +       printk(KERN_INFO "cpu[%d]: came alive after %ld us\n",
23004 +              cpu, timeout * 100);
23005 +       return 0;
23006 +}
23007 +
23008 +/*
23009 + * Data used by setup_irq for the IPI.
23010 + */
23011 +static struct irqaction ipi_irq = {
23012 +       .name    = "ipi",
23013 +       .flags   = IRQF_DISABLED | IRQF_PERCPU,
23014 +       .handler = ipi_interrupt,
23015 +};
23016 +
23017 +/*
23018 + * smp_prepare_cpus()
23019 + *     Mark threads that are available to Linux as possible cpus(s).
23020 + */
23021 +void __init smp_prepare_cpus(unsigned int max_cpus)
23022 +{
23023 +       int i;
23024 +
23025 +       /*
23026 +        * We will need a software IRQ to send IPI(s).  We will use
23027 +        * a single software IRQ for all IPI(s).
23028 +        */
23029 +       if (irq_soft_alloc(&smp_ipi_irq) < 0) {
23030 +               panic("no software IRQ is available\n");
23031 +               return;
23032 +       }
23033 +
23034 +       /*
23035 +        * For the IPI interrupt, we want to use our own chip definition.
23036 +        * This allows us to define what happens in SMP IPI without affecting
23037 +        * the performance of the other interrupts.
23038 +        *
23039 +        * Next, Register the IPI interrupt function against the soft IRQ.
23040 +        */
23041 +       set_irq_chip(smp_ipi_irq, &ubicom32_smp_chip);
23042 +       setup_irq(smp_ipi_irq, &ipi_irq);
23043 +
23044 +       /*
23045 +        * We use the device tree node to determine how many
23046 +        * free cpus we will have (up to NR_CPUS) and we indicate
23047 +        * that those cpus are present.
23048 +        *
23049 +        * We need to do this very early in the SMP case
23050 +        * because the Linux init code uses the cpu_present_map.
23051 +        */
23052 +       for_each_possible_cpu(i) {
23053 +               thread_t tid;
23054 +               struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, i);
23055 +
23056 +               /*
23057 +                *  Skip the bootstrap cpu
23058 +                */
23059 +               if (i == 0) {
23060 +                       continue;
23061 +               }
23062 +
23063 +               /*
23064 +                * If we have a free thread left in the mask,
23065 +                * indicate that the cpu is present.
23066 +                */
23067 +               tid = thread_alloc();
23068 +               if (tid == (thread_t)-1) {
23069 +                       break;
23070 +               }
23071 +
23072 +               /*
23073 +                * Save the hardware thread id for this cpu.
23074 +                */
23075 +               p->tid = tid;
23076 +               cpu_set(i, cpu_present_map);
23077 +               printk(KERN_INFO "cpu[%d]: added to cpu_present_map - tid: %d\n", i, tid);
23078 +       }
23079 +}
23080 +
23081 +/*
23082 + * smp_prepare_boot_cpu()
23083 + *     Copy the per_cpu data into the appropriate spot for the bootstrap cpu.
23084 + *
23085 + * The code in boot_cpu_init() has already set the boot cpu's
23086 + * state in the possible, present, and online maps.
23087 + */
23088 +void __devinit smp_prepare_boot_cpu(void)
23089 +{
23090 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23091 +
23092 +       smp_online_threads |= (1 << p->tid);
23093 +       printk(KERN_INFO "cpu[%d]: bootstrap CPU online - tid: %ld\n",
23094 +                       current_thread_info()->cpu, p->tid);
23095 +}
23096 +
23097 +/*
23098 + * smp_setup_processor_id()
23099 + *     Set the current_thread_info() structure cpu value.
23100 + *
23101 + * We set the value to the true hardware thread value that we are running on.
23102 + * NOTE: this function overrides the weak alias function in main.c
23103 + */
23104 +void __init smp_setup_processor_id(void)
23105 +{
23106 +       struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23107 +       int i;
23108 +       for_each_cpu_mask(i, CPU_MASK_ALL)
23109 +               set_cpu_possible(i, true);
23110 +
23111 +       current_thread_info()->cpu = 0;
23112 +       p->tid = thread_get_self();
23113 +}
23114 --- /dev/null
23115 +++ b/arch/ubicom32/kernel/stacktrace.c
23116 @@ -0,0 +1,244 @@
23117 +/*
23118 + * arch/ubicom32/kernel/stacktrace.c
23119 + *   Ubicom32 architecture stack back trace implementation.
23120 + *
23121 + * (C) Copyright 2009, Ubicom, Inc.
23122 + *
23123 + * This file is part of the Ubicom32 Linux Kernel Port.
23124 + *
23125 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23126 + * it and/or modify it under the terms of the GNU General Public License
23127 + * as published by the Free Software Foundation, either version 2 of the
23128 + * License, or (at your option) any later version.
23129 + *
23130 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23131 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23132 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23133 + * the GNU General Public License for more details.
23134 + *
23135 + * You should have received a copy of the GNU General Public License
23136 + * along with the Ubicom32 Linux Kernel Port.  If not,
23137 + * see <http://www.gnu.org/licenses/>.
23138 + *
23139 + * Ubicom32 implementation derived from (with many thanks):
23140 + *   arch/m68knommu
23141 + *   arch/blackfin
23142 + *   arch/parisc
23143 + */
23144 +#include <linux/sched.h>
23145 +#include <linux/stacktrace.h>
23146 +#include <linux/module.h>
23147 +#include <asm/stacktrace.h>
23148 +#include <asm/thread.h>
23149 +#include <asm/ip5000.h>
23150 +
23151 +/*
23152 + * These symbols are filled in by the linker.
23153 + */
23154 +extern unsigned long _stext;
23155 +extern unsigned long _etext;
23156 +
23157 +extern unsigned long __ocm_text_run_begin;
23158 +extern unsigned long __data_begin;
23159 +
23160 +/*
23161 + * stacktrace_iterate()
23162 + *     Walk the stack looking for call and calli instructions on an aligned
23163 + *     boundary.
23164 + *
23165 + * Trace must point to the top of the current stack frame.
23166 + */
23167 +unsigned long stacktrace_iterate(unsigned long **trace,
23168 +                                unsigned long stext,
23169 +                                unsigned long etext,
23170 +                                unsigned long ocm_stext,
23171 +                                unsigned long ocm_etext,
23172 +                                unsigned long sstack,
23173 +                                unsigned long estack)
23174 +{
23175 +       unsigned int thread_trap_en, instruction;
23176 +       unsigned long address;
23177 +       unsigned int limit = 0;
23178 +       unsigned long result = 0;
23179 +       unsigned long *sp = *trace;
23180 +
23181 +       /*
23182 +        * Exclude the current thread from being monitored for traps.
23183 +        */
23184 +       asm volatile(
23185 +               "       thread_get_self_mask d15                \n\t"
23186 +                       /* save current trap status */
23187 +               "       and.4   %0, MT_TRAP_EN, d15             \n\t"
23188 +               "       not.4   d15, d15                        \n\t"
23189 +                       /* disable trap */
23190 +               "       and.4   MT_TRAP_EN, MT_TRAP_EN, d15     \n\t"
23191 +               "       pipe_flush 0                            \n\t"
23192 +               : "=r" (thread_trap_en)
23193 +               :
23194 +               : "d15", "cc"
23195 +       );
23196 +
23197 +       while (limit++ < 256) {
23198 +               /*
23199 +                * See if we have a valid stack.
23200 +                */
23201 +               if (!between((unsigned long)sp, sstack, estack)) {
23202 +#ifdef TRAP_DEBUG_STACK_TRACE
23203 +                       printk(KERN_EMERG "stack address is out of range - "
23204 +                              "sp: %x, sstack: %x, estack: %x\n",
23205 +                              (unsigned int)sp, (unsigned int)sstack,
23206 +                              (unsigned int)estack);
23207 +#endif
23208 +                       result = 0;
23209 +                       *trace = 0;
23210 +                       break;
23211 +               }
23212 +
23213 +               /*
23214 +                * Get the value off the stack and back up 4 bytes to what
23215 +                * should be the address of a call or calli.
23216 +                */
23217 +               address = (*sp++) - 4;
23218 +
23219 +               /*
23220 +                * If the address is not within the text segment, skip this
23221 +                * value.
23222 +                */
23223 +               if (!between(address, stext, etext) &&
23224 +                   !between(address, ocm_stext, ocm_etext)) {
23225 +#ifdef TRAP_DEBUG_STACK_TRACE
23226 +                       printk(KERN_EMERG "not a text address - "
23227 +                              "address: %08x, stext: %08x, etext: %08x\n"
23228 +                              "ocm_stext: %08x, ocm_etext: %08x\n",
23229 +                              (unsigned int)address,
23230 +                              (unsigned int)stext,
23231 +                              (unsigned int)etext,
23232 +                              (unsigned int)ocm_stext,
23233 +                              (unsigned int)ocm_etext);
23234 +#endif
23235 +                       continue;
23236 +
23237 +               }
23238 +
23239 +               /*
23240 +                * If the address is not on an aligned boundary it can not be a
23241 +                * return address.
23242 +                */
23243 +               if (address & 0x3) {
23244 +                       continue;
23245 +               }
23246 +
23247 +               /*
23248 +                * Read the probable instruction.
23249 +                */
23250 +               instruction = *(unsigned int *)address;
23251 +
23252 +               /*
23253 +                * Is this a call instruction?
23254 +                */
23255 +               if ((instruction & 0xF8000000) == (u32_t)(0x1B << 27)) {
23256 +#ifdef TRAP_DEBUG_STACK_TRACE
23257 +                       printk(KERN_EMERG "call inst. result: %x, "
23258 +                              "test: %x\n", (unsigned int)address,
23259 +                              (unsigned int)instruction);
23260 +#endif
23261 +                       *trace = sp;
23262 +                       result = address;
23263 +                       break;
23264 +               }
23265 +
23266 +               /*
23267 +                * Is this a calli instruction?
23268 +                */
23269 +               if ((instruction & 0xF8000000) == (u32_t)(0x1E << 27)) {
23270 +#ifdef TRAP_DEBUG_STACK_TRACE
23271 +                       printk(KERN_EMERG "calli inst. result: %x, "
23272 +                              "test: %x\n", (unsigned int)address,
23273 +                              (unsigned int)instruction);
23274 +#endif
23275 +                       *trace = sp;
23276 +                       result = address;
23277 +                       break;
23278 +               }
23279 +       }
23280 +
23281 +       /*
23282 +        * Restore the current thread to be monitored for traps.
23283 +        */
23284 +       if (thread_trap_en) {
23285 +               asm volatile(
23286 +               "       thread_get_self_mask d15                \n\t"
23287 +               "       or.4    MT_TRAP_EN, MT_TRAP_EN, d15     \n\t"
23288 +                       :
23289 +                       :
23290 +                       : "d15", "cc"
23291 +               );
23292 +       }
23293 +       return result;
23294 +}
23295 +
23296 +#ifdef CONFIG_STACKTRACE
23297 +/*
23298 + * stacktrace_save_entries()
23299 + *     Save stack back trace information into the provided trace structure.
23300 + */
23301 +void stacktrace_save_entries(struct task_struct *tsk,
23302 +                            struct stack_trace *trace,
23303 +                            unsigned long sp)
23304 +{
23305 +       unsigned long code_start = (unsigned long)&_stext;
23306 +       unsigned long code_end = (unsigned long)&_etext;
23307 +       unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
23308 +       unsigned long ocm_code_end = (unsigned long)&__data_begin;
23309 +       unsigned long stack_end = (unsigned long)(tsk->stack + THREAD_SIZE - 8);
23310 +       unsigned long stack = (unsigned long)sp;
23311 +       unsigned int idx = 0;
23312 +       unsigned long *handle;
23313 +       int skip = trace->skip;
23314 +
23315 +       handle = (unsigned long *)stack;
23316 +       while (idx < trace->max_entries) {
23317 +               if (skip) {
23318 +                       skip--;
23319 +                       continue;
23320 +               }
23321 +               trace->entries[idx] = stacktrace_iterate(&handle,
23322 +                                       code_start, code_end,
23323 +                                       ocm_code_start, ocm_code_end,
23324 +                                       (unsigned long)stack, stack_end);
23325 +               if (trace->entries[idx] == 0) {
23326 +                       break;
23327 +               }
23328 +               idx++;
23329 +       }
23330 +}
23331 +
23332 +/*
23333 + * save_stack_trace()
23334 + *     Save the specified amount of the kernel stack trace information
23335 + *     for the current task.
23336 + */
23337 +void save_stack_trace(struct stack_trace *trace)
23338 +{
23339 +       unsigned long sp = 0;
23340 +       asm volatile (
23341 +       "       move.4  %0, SP          \n\t"
23342 +               : "=r" (sp)
23343 +       );
23344 +       stacktrace_save_entries(current, trace, sp);
23345 +}
23346 +EXPORT_SYMBOL_GPL(save_stack_trace);
23347 +
23348 +/*
23349 + * save_stack_trace_tsk()
23350 + *     Save the specified amount of the kernel stack trace information
23351 + *     for the specified task.
23352 + *
23353 + * Note: We assume the specified task is not currently running.
23354 + */
23355 +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
23356 +{
23357 +       stacktrace_save_entries(tsk, trace, tsk->thread.sp);
23358 +}
23359 +EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
23360 +#endif /* CONFIG_STACKTRACE */
23361 --- /dev/null
23362 +++ b/arch/ubicom32/kernel/syscalltable.S
23363 @@ -0,0 +1,376 @@
23364 +/*
23365 + * arch/ubicom32/kernel/syscalltable.S
23366 + *     <TODO: Replace with short file description>
23367 + *
23368 + * (C) Copyright 2009, Ubicom, Inc.
23369 + *
23370 + * This file is part of the Ubicom32 Linux Kernel Port.
23371 + *
23372 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23373 + * it and/or modify it under the terms of the GNU General Public License
23374 + * as published by the Free Software Foundation, either version 2 of the
23375 + * License, or (at your option) any later version.
23376 + *
23377 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23378 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23379 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23380 + * the GNU General Public License for more details.
23381 + *
23382 + * You should have received a copy of the GNU General Public License
23383 + * along with the Ubicom32 Linux Kernel Port.  If not,
23384 + * see <http://www.gnu.org/licenses/>.
23385 + *
23386 + * Ubicom32 implementation derived from (with many thanks):
23387 + *   arch/m68knommu
23388 + *   arch/blackfin
23389 + *   arch/parisc
23390 + */
23391 +/*
23392 + *
23393 + *  Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
23394 + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>, Kenneth Albanowski <kjahds@kjahds.com>,
23395 + *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
23396 + *  Copyright (C) 1991, 1992  Linus Torvalds
23397 + */
23398 +
23399 +#include <linux/sys.h>
23400 +#include <linux/linkage.h>
23401 +#include <asm/unistd.h>
23402 +
23403 +.text
23404 +ALIGN
23405 +       .global sys_call_table
23406 +sys_call_table:
23407 +       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
23408 +       .long sys_exit
23409 +       .long sys_fork
23410 +       .long sys_read
23411 +       .long sys_write
23412 +       .long sys_open          /* 5 */
23413 +       .long sys_close
23414 +       .long sys_waitpid
23415 +       .long sys_creat
23416 +       .long sys_link
23417 +       .long sys_unlink        /* 10 */
23418 +       .long execve_intercept
23419 +       .long sys_chdir
23420 +       .long sys_time
23421 +       .long sys_mknod
23422 +       .long sys_chmod         /* 15 */
23423 +       .long sys_chown16
23424 +       .long sys_ni_syscall    /* old break syscall holder */
23425 +       .long sys_stat
23426 +       .long sys_lseek
23427 +       .long sys_getpid        /* 20 */
23428 +       .long sys_mount
23429 +       .long sys_oldumount
23430 +       .long sys_setuid16
23431 +       .long sys_getuid16
23432 +       .long sys_stime         /* 25 */
23433 +       .long sys_ptrace
23434 +       .long sys_alarm
23435 +       .long sys_fstat
23436 +       .long sys_pause
23437 +       .long sys_utime         /* 30 */
23438 +       .long sys_ni_syscall    /* old stty syscall holder */
23439 +       .long sys_ni_syscall    /* old gtty syscall holder */
23440 +       .long sys_access
23441 +       .long sys_nice
23442 +       .long sys_ni_syscall    /* 35 */ /* old ftime syscall holder */
23443 +       .long sys_sync
23444 +       .long sys_kill
23445 +       .long sys_rename
23446 +       .long sys_mkdir
23447 +       .long sys_rmdir         /* 40 */
23448 +       .long sys_dup
23449 +       .long sys_pipe
23450 +       .long sys_times
23451 +       .long sys_ni_syscall    /* old prof syscall holder */
23452 +       .long sys_brk           /* 45 */
23453 +       .long sys_setgid16
23454 +       .long sys_getgid16
23455 +       .long sys_signal
23456 +       .long sys_geteuid16
23457 +       .long sys_getegid16     /* 50 */
23458 +       .long sys_acct
23459 +       .long sys_umount        /* recycled never used phys() */
23460 +       .long sys_ni_syscall    /* old lock syscall holder */
23461 +       .long sys_ioctl
23462 +       .long sys_fcntl         /* 55 */
23463 +       .long sys_ni_syscall    /* old mpx syscall holder */
23464 +       .long sys_setpgid
23465 +       .long sys_ni_syscall    /* old ulimit syscall holder */
23466 +       .long sys_ni_syscall
23467 +       .long sys_umask         /* 60 */
23468 +       .long sys_chroot
23469 +       .long sys_ustat
23470 +       .long sys_dup2
23471 +       .long sys_getppid
23472 +       .long sys_getpgrp       /* 65 */
23473 +       .long sys_setsid
23474 +       .long sys_sigaction
23475 +       .long sys_sgetmask
23476 +       .long sys_ssetmask
23477 +       .long sys_setreuid16    /* 70 */
23478 +       .long sys_setregid16
23479 +       .long sys_sigsuspend
23480 +       .long sys_sigpending
23481 +       .long sys_sethostname
23482 +       .long sys_setrlimit     /* 75 */
23483 +       .long sys_old_getrlimit
23484 +       .long sys_getrusage
23485 +       .long sys_gettimeofday
23486 +       .long sys_settimeofday
23487 +       .long sys_getgroups16   /* 80 */
23488 +       .long sys_setgroups16
23489 +       .long old_select
23490 +       .long sys_symlink
23491 +       .long sys_lstat
23492 +       .long sys_readlink      /* 85 */
23493 +       .long sys_uselib
23494 +       .long sys_ni_syscall    /* _sys_swapon */
23495 +       .long sys_reboot
23496 +       .long sys_old_readdir
23497 +       .long old_mmap          /* 90 */
23498 +       .long sys_munmap
23499 +       .long sys_truncate
23500 +       .long sys_ftruncate
23501 +       .long sys_fchmod
23502 +       .long sys_fchown16      /* 95 */
23503 +       .long sys_getpriority
23504 +       .long sys_setpriority
23505 +       .long sys_ni_syscall    /* old profil syscall holder */
23506 +       .long sys_statfs
23507 +       .long sys_fstatfs       /* 100 */
23508 +       .long sys_ni_syscall    /* ioperm for i386 */
23509 +       .long sys_socketcall
23510 +       .long sys_syslog
23511 +       .long sys_setitimer
23512 +       .long sys_getitimer     /* 105 */
23513 +       .long sys_newstat
23514 +       .long sys_newlstat
23515 +       .long sys_newfstat
23516 +       .long sys_ni_syscall
23517 +       .long sys_ni_syscall    /* iopl for i386 */ /* 110 */
23518 +       .long sys_vhangup
23519 +       .long sys_ni_syscall    /* obsolete idle() syscall */
23520 +       .long sys_ni_syscall    /* vm86old for i386 */
23521 +       .long sys_wait4
23522 +       .long sys_ni_syscall    /* 115 */ /* _sys_swapoff */
23523 +       .long sys_sysinfo
23524 +       .long sys_ipc
23525 +       .long sys_fsync
23526 +       .long sys_sigreturn
23527 +       .long clone_intercept   /* 120 */
23528 +       .long sys_setdomainname
23529 +       .long sys_newuname
23530 +       .long sys_cacheflush    /* modify_ldt for i386 */
23531 +       .long sys_adjtimex
23532 +       .long sys_ni_syscall    /* 125 */ /* _sys_mprotect */
23533 +       .long sys_sigprocmask
23534 +       .long sys_ni_syscall    /* old "creat_module" */
23535 +       .long sys_init_module
23536 +       .long sys_delete_module
23537 +       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
23538 +       .long sys_quotactl
23539 +       .long sys_getpgid
23540 +       .long sys_fchdir
23541 +       .long sys_bdflush
23542 +       .long sys_sysfs         /* 135 */
23543 +       .long sys_personality
23544 +       .long sys_ni_syscall    /* for afs_syscall */
23545 +       .long sys_setfsuid16
23546 +       .long sys_setfsgid16
23547 +       .long sys_llseek        /* 140 */
23548 +       .long sys_getdents
23549 +       .long sys_select
23550 +       .long sys_flock
23551 +       .long sys_ni_syscall    /* _sys_msync */
23552 +       .long sys_readv         /* 145 */
23553 +       .long sys_writev
23554 +       .long sys_getsid
23555 +       .long sys_fdatasync
23556 +       .long sys_sysctl
23557 +       .long sys_ni_syscall    /* 150 */ /* _sys_mlock */
23558 +       .long sys_ni_syscall    /* _sys_munlock */
23559 +       .long sys_ni_syscall    /* _sys_mlockall */
23560 +       .long sys_ni_syscall    /* _sys_munlockall */
23561 +       .long sys_sched_setparam
23562 +       .long sys_sched_getparam /* 155 */
23563 +       .long sys_sched_setscheduler
23564 +       .long sys_sched_getscheduler
23565 +       .long sys_sched_yield
23566 +       .long sys_sched_get_priority_max
23567 +       .long sys_sched_get_priority_min  /* 160 */
23568 +       .long sys_sched_rr_get_interval
23569 +       .long sys_nanosleep
23570 +       .long sys_ni_syscall    /* _sys_mremap */
23571 +       .long sys_setresuid16
23572 +       .long sys_getresuid16   /* 165 */
23573 +       .long sys_getpagesize   /* _sys_getpagesize */
23574 +       .long sys_ni_syscall    /* old "query_module" */
23575 +       .long sys_poll
23576 +       .long sys_ni_syscall    /* _sys_nfsservctl */
23577 +       .long sys_setresgid16   /* 170 */
23578 +       .long sys_getresgid16
23579 +       .long sys_prctl
23580 +       .long sys_rt_sigreturn
23581 +       .long sys_rt_sigaction
23582 +       .long sys_rt_sigprocmask /* 175 */
23583 +       .long sys_rt_sigpending
23584 +       .long sys_rt_sigtimedwait
23585 +       .long sys_rt_sigqueueinfo
23586 +       .long sys_rt_sigsuspend
23587 +       .long sys_pread64       /* 180 */
23588 +       .long sys_pwrite64
23589 +       .long sys_lchown16
23590 +       .long sys_getcwd
23591 +       .long sys_capget
23592 +       .long sys_capset        /* 185 */
23593 +       .long sys_sigaltstack
23594 +       .long sys_sendfile
23595 +       .long sys_ni_syscall    /* streams1 */
23596 +       .long sys_ni_syscall    /* streams2 */
23597 +       .long vfork_intercept           /* 190 */
23598 +       .long sys_getrlimit
23599 +       .long sys_mmap2
23600 +       .long sys_truncate64
23601 +       .long sys_ftruncate64
23602 +       .long sys_stat64        /* 195 */
23603 +       .long sys_lstat64
23604 +       .long sys_fstat64
23605 +       .long sys_chown
23606 +       .long sys_getuid
23607 +       .long sys_getgid        /* 200 */
23608 +       .long sys_geteuid
23609 +       .long sys_getegid
23610 +       .long sys_setreuid
23611 +       .long sys_setregid
23612 +       .long sys_getgroups     /* 205 */
23613 +       .long sys_setgroups
23614 +       .long sys_fchown
23615 +       .long sys_setresuid
23616 +       .long sys_getresuid
23617 +       .long sys_setresgid     /* 210 */
23618 +       .long sys_getresgid
23619 +       .long sys_lchown
23620 +       .long sys_setuid
23621 +       .long sys_setgid
23622 +       .long sys_setfsuid      /* 215 */
23623 +       .long sys_setfsgid
23624 +       .long sys_pivot_root
23625 +       .long sys_ni_syscall
23626 +       .long sys_ni_syscall
23627 +       .long sys_getdents64    /* 220 */
23628 +       .long sys_gettid
23629 +       .long sys_tkill
23630 +       .long sys_setxattr
23631 +       .long sys_lsetxattr
23632 +       .long sys_fsetxattr     /* 225 */
23633 +       .long sys_getxattr
23634 +       .long sys_lgetxattr
23635 +       .long sys_fgetxattr
23636 +       .long sys_listxattr
23637 +       .long sys_llistxattr    /* 230 */
23638 +       .long sys_flistxattr
23639 +       .long sys_removexattr
23640 +       .long sys_lremovexattr
23641 +       .long sys_fremovexattr
23642 +       .long sys_futex         /* 235 */
23643 +       .long sys_sendfile64
23644 +       .long sys_ni_syscall    /* _sys_mincore */
23645 +       .long sys_ni_syscall    /* _sys_madvise */
23646 +       .long sys_fcntl64
23647 +       .long sys_readahead     /* 240 */
23648 +       .long sys_io_setup
23649 +       .long sys_io_destroy
23650 +       .long sys_io_getevents
23651 +       .long sys_io_submit
23652 +       .long sys_io_cancel     /* 245 */
23653 +       .long sys_fadvise64
23654 +       .long sys_exit_group
23655 +       .long sys_lookup_dcookie
23656 +       .long sys_epoll_create
23657 +       .long sys_epoll_ctl     /* 250 */
23658 +       .long sys_epoll_wait
23659 +       .long sys_ni_syscall    /* _sys_remap_file_pages */
23660 +       .long sys_set_tid_address
23661 +       .long sys_timer_create
23662 +       .long sys_timer_settime /* 255 */
23663 +       .long sys_timer_gettime
23664 +       .long sys_timer_getoverrun
23665 +       .long sys_timer_delete
23666 +       .long sys_clock_settime
23667 +       .long sys_clock_gettime /* 260 */
23668 +       .long sys_clock_getres
23669 +       .long sys_clock_nanosleep
23670 +       .long sys_statfs64
23671 +       .long sys_fstatfs64
23672 +       .long sys_tgkill        /* 265 */
23673 +       .long sys_utimes
23674 +       .long sys_fadvise64_64
23675 +       .long sys_mbind
23676 +       .long sys_get_mempolicy
23677 +       .long sys_set_mempolicy /* 270 */
23678 +       .long sys_mq_open
23679 +       .long sys_mq_unlink
23680 +       .long sys_mq_timedsend
23681 +       .long sys_mq_timedreceive
23682 +       .long sys_mq_notify     /* 275 */
23683 +       .long sys_mq_getsetattr
23684 +       .long sys_waitid
23685 +       .long sys_ni_syscall    /* for _sys_vserver */
23686 +       .long sys_add_key
23687 +       .long sys_request_key   /* 280 */
23688 +       .long sys_keyctl
23689 +       .long sys_ioprio_set
23690 +       .long sys_ioprio_get
23691 +       .long sys_inotify_init
23692 +       .long sys_inotify_add_watch     /* 285 */
23693 +       .long sys_inotify_rm_watch
23694 +       .long sys_migrate_pages
23695 +       .long sys_openat
23696 +       .long sys_mkdirat
23697 +       .long sys_mknodat               /* 290 */
23698 +       .long sys_fchownat
23699 +       .long sys_futimesat
23700 +       .long sys_fstatat64
23701 +       .long sys_unlinkat
23702 +       .long sys_renameat              /* 295 */
23703 +       .long sys_linkat
23704 +       .long sys_symlinkat
23705 +       .long sys_readlinkat
23706 +       .long sys_fchmodat
23707 +       .long sys_faccessat             /* 300 */
23708 +       .long sys_ni_syscall            /* Reserved for pselect6 */
23709 +       .long sys_ni_syscall            /* Reserved for ppoll */
23710 +       .long sys_unshare
23711 +       .long sys_set_robust_list
23712 +       .long sys_get_robust_list       /* 305 */
23713 +       .long sys_splice
23714 +       .long sys_sync_file_range
23715 +       .long sys_tee
23716 +       .long sys_vmsplice
23717 +       .long sys_move_pages            /* 310 */
23718 +       .long sys_sched_setaffinity
23719 +       .long sys_sched_getaffinity
23720 +       .long sys_kexec_load
23721 +       .long sys_getcpu
23722 +       .long sys_epoll_pwait           /* 315 */
23723 +       .long sys_utimensat
23724 +       .long sys_signalfd
23725 +       .long sys_timerfd_create
23726 +       .long sys_eventfd
23727 +       .long sys_fallocate             /* 320 */
23728 +       .long sys_timerfd_settime
23729 +       .long sys_timerfd_gettime
23730 +       .long sys_ni_syscall            /* sys_signalfd4 */
23731 +       .long sys_ni_syscall            /* sys_eventfd2 */
23732 +       .long sys_ni_syscall            /* sys_epoll_create1 */
23733 +                                       /* 325 */
23734 +       .long sys_ni_syscall            /* sys_dup3 */
23735 +       .long sys_ni_syscall            /* sys_pipe2 */
23736 +       .long sys_ni_syscall            /* sys_inotify_init1 */
23737 +       .rept NR_syscalls-(.-sys_call_table)/4
23738 +               .long sys_ni_syscall
23739 +       .endr
23740 --- /dev/null
23741 +++ b/arch/ubicom32/kernel/sys_ubicom32.c
23742 @@ -0,0 +1,237 @@
23743 +/*
23744 + * arch/ubicom32/kernel/sys_ubicom32.c
23745 + *   Ubicom32 architecture system call support implementation.
23746 + *
23747 + * (C) Copyright 2009, Ubicom, Inc.
23748 + *
23749 + * This file is part of the Ubicom32 Linux Kernel Port.
23750 + *
23751 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23752 + * it and/or modify it under the terms of the GNU General Public License
23753 + * as published by the Free Software Foundation, either version 2 of the
23754 + * License, or (at your option) any later version.
23755 + *
23756 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23757 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23758 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23759 + * the GNU General Public License for more details.
23760 + *
23761 + * You should have received a copy of the GNU General Public License
23762 + * along with the Ubicom32 Linux Kernel Port.  If not,
23763 + * see <http://www.gnu.org/licenses/>.
23764 + *
23765 + * Ubicom32 implementation derived from (with many thanks):
23766 + *   arch/m68knommu
23767 + *   arch/blackfin
23768 + *   arch/parisc
23769 + *
23770 + * This file contains various random system calls that
23771 + * have a non-standard calling sequence on the Linux/ubicom32
23772 + * platform.
23773 + */
23774 +
23775 +#include <linux/module.h>
23776 +#include <linux/errno.h>
23777 +#include <linux/sched.h>
23778 +#include <linux/mm.h>
23779 +#include <linux/smp.h>
23780 +#include <linux/sem.h>
23781 +#include <linux/msg.h>
23782 +#include <linux/shm.h>
23783 +#include <linux/stat.h>
23784 +#include <linux/syscalls.h>
23785 +#include <linux/mman.h>
23786 +#include <linux/file.h>
23787 +#include <linux/utsname.h>
23788 +#include <linux/ipc.h>
23789 +#include <linux/fs.h>
23790 +#include <linux/uaccess.h>
23791 +#include <linux/unistd.h>
23792 +
23793 +#include <asm/setup.h>
23794 +#include <asm/traps.h>
23795 +#include <asm/cacheflush.h>
23796 +
23797 +/* common code for old and new mmaps */
23798 +static inline long do_mmap2(
23799 +       unsigned long addr, unsigned long len,
23800 +       unsigned long prot, unsigned long flags,
23801 +       unsigned long fd, unsigned long pgoff)
23802 +{
23803 +       int error = -EBADF;
23804 +       struct file *file = NULL;
23805 +
23806 +       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
23807 +       if (!(flags & MAP_ANONYMOUS)) {
23808 +               file = fget(fd);
23809 +               if (!file)
23810 +                       goto out;
23811 +       }
23812 +
23813 +       down_write(&current->mm->mmap_sem);
23814 +       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
23815 +       up_write(&current->mm->mmap_sem);
23816 +
23817 +       if (file)
23818 +               fput(file);
23819 +out:
23820 +       return error;
23821 +}
23822 +
23823 +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
23824 +       unsigned long prot, unsigned long flags,
23825 +       unsigned long fd, unsigned long pgoff)
23826 +{
23827 +       return do_mmap2(addr, len, prot, flags, fd, pgoff);
23828 +}
23829 +
23830 +/*
23831 + * Perform the select(nd, in, out, ex, tv) and mmap() system
23832 + * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
23833 + * handle more than 4 system call parameters, so these system calls
23834 + * used a memory block for parameter passing..
23835 + */
23836 +
23837 +struct mmap_arg_struct {
23838 +       unsigned long addr;
23839 +       unsigned long len;
23840 +       unsigned long prot;
23841 +       unsigned long flags;
23842 +       unsigned long fd;
23843 +       unsigned long offset;
23844 +};
23845 +
23846 +asmlinkage int old_mmap(struct mmap_arg_struct *arg)
23847 +{
23848 +       struct mmap_arg_struct a;
23849 +       int error = -EFAULT;
23850 +
23851 +       if (copy_from_user(&a, arg, sizeof(a)))
23852 +               goto out;
23853 +
23854 +       error = -EINVAL;
23855 +       if (a.offset & ~PAGE_MASK)
23856 +               goto out;
23857 +
23858 +       a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
23859 +
23860 +       error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd,
23861 +                        a.offset >> PAGE_SHIFT);
23862 +out:
23863 +       return error;
23864 +}
23865 +
23866 +struct sel_arg_struct {
23867 +       unsigned long n;
23868 +       fd_set *inp, *outp, *exp;
23869 +       struct timeval *tvp;
23870 +};
23871 +
23872 +asmlinkage int old_select(struct sel_arg_struct *arg)
23873 +{
23874 +       struct sel_arg_struct a;
23875 +
23876 +       if (copy_from_user(&a, arg, sizeof(a)))
23877 +               return -EFAULT;
23878 +       /* sys_select() does the appropriate kernel locking */
23879 +       return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
23880 +}
23881 +
23882 +/*
23883 + * sys_ipc() is the de-multiplexer for the SysV IPC calls..
23884 + *
23885 + * This is really horribly ugly.
23886 + */
23887 +asmlinkage int sys_ipc(uint call, int first, int second,
23888 +                       int third, void *ptr, long fifth)
23889 +{
23890 +       int version, ret;
23891 +
23892 +       version = call >> 16; /* hack for backward compatibility */
23893 +       call &= 0xffff;
23894 +
23895 +       if (call <= SEMCTL)
23896 +               switch (call) {
23897 +               case SEMOP:
23898 +                       return sys_semop(first, (struct sembuf *)ptr, second);
23899 +               case SEMGET:
23900 +                       return sys_semget(first, second, third);
23901 +               case SEMCTL: {
23902 +                       union semun fourth;
23903 +                       if (!ptr)
23904 +                               return -EINVAL;
23905 +                       if (get_user(fourth.__pad, (void **) ptr))
23906 +                               return -EFAULT;
23907 +                       return sys_semctl(first, second, third, fourth);
23908 +                       }
23909 +               default:
23910 +                       return -EINVAL;
23911 +               }
23912 +       if (call <= MSGCTL)
23913 +               switch (call) {
23914 +               case MSGSND:
23915 +                       return sys_msgsnd(first, (struct msgbuf *) ptr,
23916 +                                         second, third);
23917 +               case MSGRCV:
23918 +                       switch (version) {
23919 +                       case 0: {
23920 +                               struct ipc_kludge tmp;
23921 +                               if (!ptr)
23922 +                                       return -EINVAL;
23923 +                               if (copy_from_user(&tmp,
23924 +                                                  (struct ipc_kludge *)ptr,
23925 +                                                  sizeof(tmp)))
23926 +                                       return -EFAULT;
23927 +                               return sys_msgrcv(first, tmp.msgp, second,
23928 +                                                  tmp.msgtyp, third);
23929 +                               }
23930 +                       default:
23931 +                               return sys_msgrcv(first,
23932 +                                                 (struct msgbuf *) ptr,
23933 +                                                 second, fifth, third);
23934 +                       }
23935 +               case MSGGET:
23936 +                       return sys_msgget((key_t) first, second);
23937 +               case MSGCTL:
23938 +                       return sys_msgctl(first, second,
23939 +                                          (struct msqid_ds *) ptr);
23940 +               default:
23941 +                       return -EINVAL;
23942 +               }
23943 +       if (call <= SHMCTL)
23944 +               switch (call) {
23945 +               case SHMAT:
23946 +                       switch (version) {
23947 +                       default: {
23948 +                               ulong raddr;
23949 +                               ret = do_shmat(first, ptr, second, &raddr);
23950 +                               if (ret)
23951 +                                       return ret;
23952 +                               return put_user(raddr, (ulong __user *) third);
23953 +                       }
23954 +                       }
23955 +               case SHMDT:
23956 +                       return sys_shmdt(ptr);
23957 +               case SHMGET:
23958 +                       return sys_shmget(first, second, third);
23959 +               case SHMCTL:
23960 +                       return sys_shmctl(first, second, ptr);
23961 +               default:
23962 +                       return -ENOSYS;
23963 +               }
23964 +
23965 +       return -EINVAL;
23966 +}
23967 +
23968 +/* sys_cacheflush -- flush (part of) the processor cache.  */
23969 +asmlinkage int
23970 +sys_cacheflush(unsigned long addr, int scope, int cache, unsigned long len)
23971 +{
23972 +       flush_cache_all();
23973 +       return 0;
23974 +}
23975 +
23976 +asmlinkage int sys_getpagesize(void)
23977 +{
23978 +       return PAGE_SIZE;
23979 +}
23980 --- /dev/null
23981 +++ b/arch/ubicom32/kernel/thread.c
23982 @@ -0,0 +1,228 @@
23983 +/*
23984 + * arch/ubicom32/kernel/thread.c
23985 + *   Ubicom32 architecture hardware thread support.
23986 + *
23987 + * (C) Copyright 2009, Ubicom, Inc.
23988 + *
23989 + * This file is part of the Ubicom32 Linux Kernel Port.
23990 + *
23991 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23992 + * it and/or modify it under the terms of the GNU General Public License
23993 + * as published by the Free Software Foundation, either version 2 of the
23994 + * License, or (at your option) any later version.
23995 + *
23996 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23997 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23998 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23999 + * the GNU General Public License for more details.
24000 + *
24001 + * You should have received a copy of the GNU General Public License
24002 + * along with the Ubicom32 Linux Kernel Port.  If not,
24003 + * see <http://www.gnu.org/licenses/>.
24004 + *
24005 + * Ubicom32 implementation derived from (with many thanks):
24006 + *   arch/m68knommu
24007 + *   arch/blackfin
24008 + *   arch/parisc
24009 + */
24010 +
24011 +#include <linux/module.h>
24012 +#include <linux/kernel.h>
24013 +#include <linux/init.h>
24014 +#include <linux/sched.h>
24015 +#include <linux/interrupt.h>
24016 +#include <linux/irq.h>
24017 +#include <linux/profile.h>
24018 +#include <linux/clocksource.h>
24019 +#include <linux/types.h>
24020 +#include <asm/ip5000.h>
24021 +#include <asm/machdep.h>
24022 +#include <asm/asm-offsets.h>
24023 +#include <asm/thread.h>
24024 +
24025 +/*
24026 + * TODO: At some point change the name here to be thread_ksp
24027 + */
24028 +unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
24029 +
24030 +static unsigned int thread_mask = -1;
24031 +static unsigned int thread_mainline_mask;
24032 +
24033 +/*
24034 + * thread_entry()
24035 + *     Returning from the called function will disable the thread.
24036 + *
24037 + * This could be a naked call to allow for hwthreads that do not have stacks.
24038 + * However, with -O0, the code still writes to thex stack, and this was
24039 + * corrupting memory just after the callers stack.
24040 + */
24041 +static void thread_entry(void *arg, thread_exec_fn_t exec)
24042 +{
24043 +       /*
24044 +        * Call thread function
24045 +        */
24046 +       exec(arg);
24047 +
24048 +       /*
24049 +        * Complete => Disable self
24050 +        */
24051 +       thread_disable(thread_get_self());
24052 +}
24053 +
24054 +/*
24055 + * thread_start()
24056 + *     Start the specified function on the specified hardware thread.
24057 + */
24058 +thread_t thread_start(thread_t thread,
24059 +                     thread_exec_fn_t exec,
24060 +                     void *arg,
24061 +                     unsigned int *sp_high,
24062 +                     thread_type_t type)
24063 +{
24064 +       /*
24065 +        * Sanity check
24066 +        */
24067 +       unsigned int enabled, mask, csr;
24068 +       asm volatile (
24069 +               "move.4         %0, MT_EN\n\t"
24070 +               : "=m" (enabled)
24071 +       );
24072 +
24073 +       mask = 1 << thread;
24074 +       if (enabled & mask) {
24075 +               printk(KERN_WARNING "request to enable a previously enabled thread\n");
24076 +               return (thread_t)-1;
24077 +       }
24078 +
24079 +       /*
24080 +        * Update thread state
24081 +        */
24082 +       csr = (thread << 15) | (1 << 14);
24083 +       asm volatile (
24084 +               "setcsr         %0              \n\t"
24085 +               "setcsr_flush   0               \n\t"
24086 +
24087 +               "move.4         A0, #0          \n\t"
24088 +               "move.4         A1, #0          \n\t"
24089 +               "move.4         A2, #0          \n\t"
24090 +               "move.4         A3, #0          \n\t"
24091 +               "move.4         A4, #0          \n\t"
24092 +               "move.4         A5, #0          \n\t"
24093 +               "move.4         A6, #0          \n\t"
24094 +               "move.4         SP, %4          \n\t"   /* A7 is SP */
24095 +
24096 +               "move.4         D0, %3          \n\t"
24097 +               "move.4         D1, %2          \n\t"
24098 +               "move.4         D2, #0          \n\t"
24099 +               "move.4         D3, #0          \n\t"
24100 +               "move.4         D4, #0          \n\t"
24101 +               "move.4         D5, #0          \n\t"
24102 +               "move.4         D6, #0          \n\t"
24103 +               "move.4         D7, #0          \n\t"
24104 +               "move.4         D8, #0          \n\t"
24105 +               "move.4         D9, #0          \n\t"
24106 +               "move.4         D10, #0         \n\t"
24107 +               "move.4         D11, #0         \n\t"
24108 +               "move.4         D12, #0         \n\t"
24109 +               "move.4         D13, #0         \n\t"
24110 +               "move.4         D14, #0         \n\t"
24111 +               "move.4         D15, #0         \n\t"
24112 +
24113 +               "move.4         INT_MASK0, #0   \n\t"
24114 +               "move.4         INT_MASK1, #0   \n\t"
24115 +               "move.4         PC, %1          \n\t"
24116 +               "setcsr         #0              \n\t"
24117 +               "setcsr_flush   0               \n\t"
24118 +               :
24119 +               : "r" (csr), "r" (thread_entry), "r" (exec),
24120 +                 "r" (arg), "r" (sp_high)
24121 +       );
24122 +
24123 +       /*
24124 +        * Apply HRT state
24125 +        */
24126 +       if (type & THREAD_TYPE_HRT) {
24127 +               asm volatile (
24128 +                       "or.4           MT_HRT, MT_HRT, %0\n\t"
24129 +                       :
24130 +                       : "d" (mask)
24131 +                       : "cc"
24132 +               );
24133 +       } else {
24134 +               asm volatile (
24135 +                       "and.4          MT_HRT, MT_HRT, %0\n\t"
24136 +                       :
24137 +                       : "d" (~mask)
24138 +                       : "cc"
24139 +               );
24140 +       }
24141 +
24142 +       /*
24143 +        * Set priority
24144 +        */
24145 +       asm volatile (
24146 +               "or.4           MT_HPRI, MT_HPRI, %0\n\t"
24147 +               :
24148 +               : "d" (mask)
24149 +               : "cc"
24150 +       );
24151 +
24152 +       /*
24153 +        * Enable thread
24154 +        */
24155 +       asm volatile (
24156 +               "move.4         MT_ACTIVE_SET, %0       \n\t"
24157 +               :
24158 +               : "d" (mask)
24159 +       );
24160 +       thread_enable_mask(mask);
24161 +       return thread;
24162 +}
24163 +
24164 +/*
24165 + * thread_get_mainline()
24166 + *     Return a mask of those threads that are Linux mainline threads.
24167 + */
24168 +unsigned int thread_get_mainline(void)
24169 +{
24170 +       return thread_mainline_mask;
24171 +}
24172 +
24173 +/*
24174 + * thread_set_mainline()
24175 + *     Indicate that the specified thread is a Linux mainline thread.
24176 + */
24177 +void thread_set_mainline(thread_t tid)
24178 +{
24179 +       thread_mainline_mask |= (1 << tid);
24180 +}
24181 +
24182 +/*
24183 + * thread_alloc()
24184 + *     Allocate an unused hardware thread.
24185 + */
24186 +thread_t thread_alloc(void)
24187 +{
24188 +       thread_t tid;
24189 +
24190 +       /*
24191 +        * If this is the first time we are here get the list of unused
24192 +        * threads from the processor device tree node.
24193 +        */
24194 +       if (thread_mask == -1) {
24195 +               thread_mask = processor_threads();
24196 +       }
24197 +
24198 +       if (!thread_mask) {
24199 +               return (thread_t)-1;
24200 +       }
24201 +
24202 +       tid = ffs(thread_mask);
24203 +       if (tid != 0) {
24204 +               tid--;
24205 +               thread_mask &= ~(1 << tid);
24206 +               return tid;
24207 +       }
24208 +
24209 +       return (thread_t)-1;
24210 +}
24211 --- /dev/null
24212 +++ b/arch/ubicom32/kernel/time.c
24213 @@ -0,0 +1,212 @@
24214 +/*
24215 + * arch/ubicom32/kernel/time.c
24216 + *     Initialize the timer list and start the appropriate timers.
24217 + *
24218 + * (C) Copyright 2009, Ubicom, Inc.
24219 + * Copyright (C) 1991, 1992, 1995  Linus Torvalds
24220 + *
24221 + * This file is part of the Ubicom32 Linux Kernel Port.
24222 + *
24223 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24224 + * it and/or modify it under the terms of the GNU General Public License
24225 + * as published by the Free Software Foundation, either version 2 of the
24226 + * License, or (at your option) any later version.
24227 + *
24228 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24229 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24230 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24231 + * the GNU General Public License for more details.
24232 + *
24233 + * You should have received a copy of the GNU General Public License
24234 + * along with the Ubicom32 Linux Kernel Port.  If not,
24235 + * see <http://www.gnu.org/licenses/>.
24236 + *
24237 + * Ubicom32 implementation derived from (with many thanks):
24238 + *   arch/m68knommu
24239 + *   arch/blackfin
24240 + *   arch/parisc
24241 + */
24242 +
24243 +#include <linux/profile.h>
24244 +#include <linux/smp.h>
24245 +#include <asm/ip5000.h>
24246 +#include <asm/machdep.h>
24247 +
24248 +/*
24249 + * A bitmap of the timers on the processor indicates
24250 + * that the timer is free or in-use.
24251 + */
24252 +static unsigned int timers;
24253 +
24254 +/*
24255 + * timer_set()
24256 + *     Init the specified compare register to go off <n> cycles from now.
24257 + */
24258 +void timer_set(int timervector, unsigned int cycles)
24259 +{
24260 +       int idx = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24261 +       UBICOM32_IO_TIMER->syscom[idx] =
24262 +                       UBICOM32_IO_TIMER->sysval + cycles;
24263 +       ldsr_enable_vector(timervector);
24264 +}
24265 +
24266 +/*
24267 + * timer_reset()
24268 + *     Set/reset the timer to go off again.
24269 + *
24270 + * Because sysval is a continuous timer, this function is able
24271 + * to ensure that we do not have clock sku by using the previous
24272 + * value in syscom to set the next value for syscom.
24273 + *
24274 + * Returns the number of ticks that transpired since the last event.
24275 + */
24276 +int timer_reset(int timervector, unsigned int cycles)
24277 +{
24278 +       /*
24279 +        * Reset the timer in the LDSR thread to go off appropriately.
24280 +        *
24281 +        * Use the previous value of the timer to calculate the new stop
24282 +        * time.  This allows us to account for it taking an
24283 +        * indeterminate amount of time to get here.
24284 +        */
24285 +       const int timer_index = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24286 +       unsigned int prev = UBICOM32_IO_TIMER->syscom[timer_index];
24287 +       unsigned int next = prev + cycles;
24288 +       int scratchpad3;
24289 +       int diff;
24290 +       int ticks = 1;
24291 +
24292 +       /*
24293 +        * If the difference is negative, we have missed at least one
24294 +        * timer tick.
24295 +        *
24296 +        * TODO: Decide if we want to "ignore" time (as done below) or
24297 +        * if we want to process time (unevenly) by calling timer_tick()
24298 +        * lost_ticks times.
24299 +        */
24300 +       while (1) {
24301 +               /*
24302 +                * Set our future time first.
24303 +                */
24304 +               UBICOM32_IO_TIMER->syscom[timer_index] = next;
24305 +
24306 +               /*
24307 +                * Then check if we are really set time in the futrue.
24308 +                */
24309 +               diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24310 +               if (diff >= 0) {
24311 +                       break;
24312 +               }
24313 +
24314 +               /*
24315 +                * Oops, we are too slow. Playing catch up.
24316 +                *
24317 +                * If the debugger is connected the there is a good
24318 +                * chance that we lost time because we were in a
24319 +                * break-point, so in this case we do not print out
24320 +                * diagnostics.
24321 +                */
24322 +               asm volatile ("move.4 %0, scratchpad3"
24323 +                             : "=r" (scratchpad3));
24324 +               if ((scratchpad3 & 0x1) == 0) {
24325 +                       /*
24326 +                        * No debugger attached, print to the console
24327 +                        */
24328 +                       printk(KERN_EMERG "diff: %d, timer has lost %u "
24329 +                              "ticks [rounded up]\n",
24330 +                              -diff,
24331 +                              (unsigned int)((-diff + cycles - 1) / cycles));
24332 +               }
24333 +
24334 +               do {
24335 +                       next += cycles;
24336 +                       diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24337 +                       ticks++;
24338 +               } while (diff < 0);
24339 +       }
24340 +       return ticks;
24341 +}
24342 +
24343 +/*
24344 + * sched_clock()
24345 + *     Returns current time in nano-second units.
24346 + *
24347 + * Notes:
24348 + * 1) This is an override for the weak alias in
24349 + * kernel/sched_clock.c.
24350 + * 2) Do not use xtime_lock as this function is
24351 + * sometimes called with xtime_lock held.
24352 + * 3) We use a retry algorithm to ensure that
24353 + * we get a consistent value.
24354 + * 4) sched_clock must be overwritten if IRQ tracing
24355 + * is enabled because the default implementation uses
24356 + * the xtime_lock sequence while holding xtime_lock.
24357 + */
24358 +unsigned long long sched_clock(void)
24359 +{
24360 +       unsigned long long my_jiffies;
24361 +       unsigned long jiffies_top;
24362 +       unsigned long jiffies_bottom;
24363 +
24364 +       do {
24365 +               jiffies_top = jiffies_64 >> 32;
24366 +               jiffies_bottom = jiffies_64 & 0xffffffff;
24367 +       } while (unlikely(jiffies_top != (unsigned long)(jiffies_64 >> 32)));
24368 +
24369 +       my_jiffies = ((unsigned long long)jiffies_top << 32) | (jiffies_bottom);
24370 +       return (my_jiffies - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
24371 +}
24372 +
24373 +/*
24374 + * timer_free()
24375 + *     Free a hardware timer.
24376 + */
24377 +void timer_free(int interrupt)
24378 +{
24379 +       unsigned int bit = interrupt - TIMER_INT(0);
24380 +
24381 +       /*
24382 +        * The timer had not been allocated.
24383 +        */
24384 +       BUG_ON(timers & (1 << bit));
24385 +       timers |= (1 << bit);
24386 +}
24387 +
24388 +/*
24389 + * timer_alloc()
24390 + *     Allocate a hardware timer.
24391 + */
24392 +int timer_alloc(void)
24393 +{
24394 +       unsigned int bit = find_first_bit((unsigned long *)&timers, 32);
24395 +       if (!bit) {
24396 +               printk(KERN_WARNING "no more free timers\n");
24397 +               return -1;
24398 +       }
24399 +
24400 +       timers &= ~(1 << bit);
24401 +       return bit + TIMER_INT(0);
24402 +}
24403 +
24404 +/*
24405 + * time_init()
24406 + *     Time init function.
24407 + */
24408 +void time_init(void)
24409 +{
24410 +       /*
24411 +        * Find the processor node and determine what timers are
24412 +        * available for us.
24413 +        */
24414 +       timers = processor_timers();
24415 +       if (timers == 0) {
24416 +               printk(KERN_WARNING "no timers are available for Linux\n");
24417 +               return;
24418 +       }
24419 +
24420 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
24421 +       timer_device_init();
24422 +#else
24423 +       timer_tick_init();
24424 +#endif
24425 +}
24426 --- /dev/null
24427 +++ b/arch/ubicom32/kernel/timer_broadcast.c
24428 @@ -0,0 +1,102 @@
24429 +/*
24430 + * arch/ubicom32/kernel/timer_broadcast.c
24431 + *   Implements a dummy clock event for each cpu.
24432 + *
24433 + * Copyright (C) 2008  Paul Mundt
24434 + * (C) Copyright 2009, Ubicom, Inc.
24435 + *
24436 + * This file is part of the Ubicom32 Linux Kernel Port.
24437 + *
24438 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24439 + * it and/or modify it under the terms of the GNU General Public License
24440 + * as published by the Free Software Foundation, either version 2 of the
24441 + * License, or (at your option) any later version.
24442 + *
24443 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24444 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24445 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24446 + * the GNU General Public License for more details.
24447 + *
24448 + * You should have received a copy of the GNU General Public License
24449 + * along with the Ubicom32 Linux Kernel Port.  If not,
24450 + * see <http://www.gnu.org/licenses/>.
24451 + *
24452 + * Ubicom32 implementation derived from (with many thanks):
24453 + *   arch/m68knommu
24454 + *   arch/blackfin
24455 + *   arch/parisc
24456 + *   arch/arm
24457 + *   arch/sh
24458 + */
24459 +#include <linux/init.h>
24460 +#include <linux/kernel.h>
24461 +#include <linux/delay.h>
24462 +#include <linux/device.h>
24463 +#include <linux/smp.h>
24464 +#include <linux/jiffies.h>
24465 +#include <linux/percpu.h>
24466 +#include <linux/clockchips.h>
24467 +#include <linux/irq.h>
24468 +
24469 +static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
24470 +
24471 +/*
24472 + *  The broadcast trick only works when the timer will be used in a periodic mode.
24473 + *  If the user has configured either NO_HZ or HIGH_RES_TIMERS they must have
24474 + *  a per cpu timer.
24475 + */
24476 +#if defined(CONFIG_NO_HZ) || defined(CONFIG_HIGH_RES_TIMERS)
24477 +#error "Tickless and High Resolution Timers require per-CPU local timers: CONFIG_LOCAL_TIMERS"
24478 +#endif
24479 +
24480 +/*
24481 + * local_timer_interrupt()
24482 + *     Used on SMP for local timer interrupt sent via an IPI.
24483 + */
24484 +void local_timer_interrupt(void)
24485 +{
24486 +       struct clock_event_device *dev = &__get_cpu_var(local_clockevent);
24487 +
24488 +       dev->event_handler(dev);
24489 +}
24490 +
24491 +/*
24492 + * dummy_timer_set_next_event()
24493 + *     Cause the timer to go off "cycles" from now.
24494 + */
24495 +static int dummy_timer_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24496 +{
24497 +       return 0;
24498 +}
24499 +
24500 +/*
24501 + * dummy_timer_set_mode()
24502 + *     Do Nothing.
24503 + */
24504 +static void dummy_timer_set_mode(enum clock_event_mode mode,
24505 +                                struct clock_event_device *clk)
24506 +{
24507 +}
24508 +
24509 +/*
24510 + * local_timer_setup()
24511 + *     Adds a clock event for the specified cpu.
24512 + */
24513 +int __cpuinit local_timer_setup(unsigned int cpu)
24514 +{
24515 +       struct clock_event_device *dev = &per_cpu(local_clockevent, cpu);
24516 +
24517 +       dev->name               = "timer-dummy";
24518 +       dev->features           = CLOCK_EVT_FEAT_DUMMY;
24519 +       dev->rating             = 200;
24520 +       dev->mult               = 1;
24521 +       dev->set_mode           = dummy_timer_set_mode;
24522 +       dev->set_next_event     = dummy_timer_set_next_event;
24523 +       dev->broadcast          = smp_timer_broadcast;
24524 +       dev->cpumask            = cpumask_of_cpu(cpu);
24525 +       dev->irq                = -1;
24526 +       printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24527 +
24528 +       clockevents_register_device(dev);
24529 +       return 0;
24530 +}
24531 --- /dev/null
24532 +++ b/arch/ubicom32/kernel/timer_device.c
24533 @@ -0,0 +1,301 @@
24534 +/*
24535 + * arch/ubicom32/kernel/timer_device.c
24536 + *   Implements a Ubicom32 clock device and event devices.
24537 + *
24538 + * (C) Copyright 2009, Ubicom, Inc.
24539 + *
24540 + * This file is part of the Ubicom32 Linux Kernel Port.
24541 + *
24542 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24543 + * it and/or modify it under the terms of the GNU General Public License
24544 + * as published by the Free Software Foundation, either version 2 of the
24545 + * License, or (at your option) any later version.
24546 + *
24547 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24548 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24549 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24550 + * the GNU General Public License for more details.
24551 + *
24552 + * You should have received a copy of the GNU General Public License
24553 + * along with the Ubicom32 Linux Kernel Port.  If not,
24554 + * see <http://www.gnu.org/licenses/>.
24555 + *
24556 + * Ubicom32 implementation derived from (with many thanks):
24557 + *   arch/m68knommu
24558 + *   arch/blackfin
24559 + *   arch/parisc
24560 + */
24561 +#include <linux/types.h>
24562 +#include <linux/clockchips.h>
24563 +#include <linux/clocksource.h>
24564 +#include <linux/spinlock.h>
24565 +#include <asm/ip5000.h>
24566 +#include <asm/machdep.h>
24567 +
24568 +#if defined(CONFIG_SMP)
24569 +#include <asm/smp.h>
24570 +#endif
24571 +
24572 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
24573 +#define MAX_TIMERS (2 + CONFIG_TIMER_EXTRA_ALLOC)
24574 +#else
24575 +#define MAX_TIMERS (NR_CPUS + CONFIG_TIMER_EXTRA_ALLOC)
24576 +#endif
24577 +
24578 +#if (MAX_TIMERS > 10)
24579 +#error "Ubicom32 only has 10 timers"
24580 +#endif
24581 +
24582 +static unsigned int frequency;
24583 +static struct clock_event_device timer_device_devs[MAX_TIMERS];
24584 +static struct irqaction timer_device_irqs[MAX_TIMERS];
24585 +static int timer_device_next_timer = 0;
24586 +
24587 +DEFINE_SPINLOCK(timer_device_lock);
24588 +
24589 +/*
24590 + * timer_device_set_next_event()
24591 + *     Cause the timer to go off "cycles" from now.
24592 + */
24593 +static int timer_device_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24594 +{
24595 +       timer_set(dev->irq, cycles);
24596 +       return 0;
24597 +}
24598 +
24599 +/*
24600 + * timer_device_set_mode()
24601 + *     Handle the mode switch for a clock event device.
24602 + */
24603 +static void timer_device_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
24604 +{
24605 +       switch (mode) {
24606 +       case CLOCK_EVT_MODE_SHUTDOWN:
24607 +               /*
24608 +                * Make sure the vector is disabled
24609 +                * until the next event is set.
24610 +                */
24611 +               printk(KERN_NOTICE "timer[%d]: shutdown\n", dev->irq);
24612 +               ldsr_disable_vector(dev->irq);
24613 +               break;
24614 +
24615 +       case CLOCK_EVT_MODE_ONESHOT:
24616 +               /*
24617 +                * Make sure the vector is disabled
24618 +                * until the next event is set.
24619 +                */
24620 +               printk(KERN_NOTICE "timer[%d]: oneshot\n", dev->irq);
24621 +               ldsr_disable_vector(dev->irq);
24622 +               break;
24623 +
24624 +       case CLOCK_EVT_MODE_PERIODIC:
24625 +               /*
24626 +                * The periodic request is 1 per jiffies
24627 +                */
24628 +               printk(KERN_NOTICE "timer[%d]: periodic: %d cycles\n",
24629 +                       dev->irq, frequency / CONFIG_HZ);
24630 +               timer_set(dev->irq, frequency / CONFIG_HZ);
24631 +               break;
24632 +
24633 +       case CLOCK_EVT_MODE_UNUSED:
24634 +       case CLOCK_EVT_MODE_RESUME:
24635 +               printk(KERN_WARNING "timer[%d]: unimplemented mode: %d\n",
24636 +                       dev->irq, mode);
24637 +               break;
24638 +       };
24639 +}
24640 +
24641 +/*
24642 + * timer_device_event()
24643 + *     Call the device's event handler.
24644 + *
24645 + * The pointer is initialized by the generic Linux code
24646 + * to the function to be called.
24647 + */
24648 +static irqreturn_t timer_device_event(int irq, void *dev_id)
24649 +{
24650 +       struct clock_event_device *dev = (struct clock_event_device *)dev_id;
24651 +
24652 +       if (dev->mode == CLOCK_EVT_MODE_PERIODIC) {
24653 +               /*
24654 +                * The periodic request is 1 per jiffies
24655 +                */
24656 +               timer_reset(dev->irq, frequency / CONFIG_HZ);
24657 +       } else {
24658 +               /*
24659 +                * The timer will go off again at the rollover
24660 +                * point.  We must disable the IRQ to prevent
24661 +                * getting a spurious interrupt.
24662 +                */
24663 +               ldsr_disable_vector(dev->irq);
24664 +       }
24665 +
24666 +       if (!dev->event_handler) {
24667 +               printk(KERN_CRIT "no registered event handler\n");
24668 +               return IRQ_HANDLED;
24669 +       }
24670 +
24671 +       dev->event_handler(dev);
24672 +       return IRQ_HANDLED;
24673 +}
24674 +
24675 +/*
24676 + * timer_device_clockbase_read()
24677 + *     Provide a primary clocksource around the sysval timer.
24678 + */
24679 +static cycle_t timer_device_clockbase_read(void)
24680 +{
24681 +       return (cycle_t)UBICOM32_IO_TIMER->sysval;
24682 +}
24683 +
24684 +/*
24685 + * Primary Clock Source Description
24686 + *
24687 + * We use 24 for the shift factor because we want
24688 + * to ensure there are less than 2^24 clocks
24689 + * in a jiffie of 10 ms.
24690 + */
24691 +static struct clocksource timer_device_clockbase = {
24692 +       .name   = "sysval",
24693 +       .rating = 400,
24694 +       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
24695 +       .mask   = CLOCKSOURCE_MASK(32),
24696 +       .shift  = 24,
24697 +       .mult   = 0,
24698 +       .read   = timer_device_clockbase_read,
24699 +};
24700 +
24701 +/*
24702 + * timer_device_alloc_event()
24703 + *     Allocate a timer device event.
24704 + */
24705 +static int timer_device_alloc_event(const char *name, int cpuid, const cpumask_t *mask)
24706 +{
24707 +       struct clock_event_device *dev;
24708 +       struct irqaction *action;
24709 +
24710 +       /*
24711 +        * Are we out of configured timers?
24712 +        */
24713 +       spin_lock(&timer_device_lock);
24714 +       if (timer_device_next_timer >= MAX_TIMERS) {
24715 +               spin_unlock(&timer_device_lock);
24716 +               printk(KERN_WARNING "out of timer event entries\n");
24717 +               return -1;
24718 +       }
24719 +       dev = &timer_device_devs[timer_device_next_timer];
24720 +       action = &timer_device_irqs[timer_device_next_timer];
24721 +       timer_device_next_timer++;
24722 +       spin_unlock(&timer_device_lock);
24723 +
24724 +       /*
24725 +        * Now allocate a timer to ourselves.
24726 +        */
24727 +       dev->irq = timer_alloc();
24728 +       if (dev->irq == -1) {
24729 +               spin_lock(&timer_device_lock);
24730 +               timer_device_next_timer--;
24731 +               spin_unlock(&timer_device_lock);
24732 +               printk(KERN_WARNING "out of hardware timers\n");
24733 +               return -1;
24734 +       }
24735 +
24736 +       /*
24737 +        * Init the IRQ action structure.  Make sure
24738 +        * this in place before you register the clock
24739 +        * event device.
24740 +        */
24741 +       action->name = name;
24742 +       action->flags = IRQF_DISABLED | IRQF_TIMER;
24743 +       action->handler = timer_device_event;
24744 +       cpumask_copy(&action->mask, mask);
24745 +       action->dev_id = dev;
24746 +       setup_irq(dev->irq, action);
24747 +       irq_set_affinity(dev->irq, mask);
24748 +       ldsr_disable_vector(dev->irq);
24749 +
24750 +       /*
24751 +        * init clock dev structure.
24752 +        *
24753 +        * The min_delta_ns is chosen to ensure that setting next
24754 +        * event will never be requested with too small of value.
24755 +        */
24756 +       dev->name = name;
24757 +       dev->rating = timer_device_clockbase.rating;
24758 +       dev->shift = timer_device_clockbase.shift;
24759 +       dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
24760 +       dev->set_mode = timer_device_set_mode;
24761 +       dev->set_next_event = timer_device_set_next_event;
24762 +       dev->mult = div_sc(frequency, NSEC_PER_SEC, dev->shift);
24763 +       dev->max_delta_ns = clockevent_delta2ns(0xffffffff, dev);
24764 +       dev->min_delta_ns = clockevent_delta2ns(100, dev);
24765 +       dev->cpumask = mask;
24766 +       printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24767 +
24768 +       /*
24769 +        * Now register the device.
24770 +        */
24771 +       clockevents_register_device(dev);
24772 +       return dev->irq;
24773 +}
24774 +
24775 +#if defined(CONFIG_LOCAL_TIMERS)
24776 +/*
24777 + * local_timer_setup()
24778 + *     Allocation function for creating a per cpu local timer.
24779 + */
24780 +int __cpuinit local_timer_setup(unsigned int cpu)
24781 +{
24782 +       return timer_device_alloc_event("timer-cpu", cpu, cpumask_of(cpu));
24783 +}
24784 +#endif
24785 +
24786 +/*
24787 + * timer_device_init()
24788 + *     Create and init a generic clock driver for Ubicom32.
24789 + */
24790 +void timer_device_init(void)
24791 +{
24792 +       int i;
24793 +
24794 +       /*
24795 +        * Get the frequency from the processor device tree node or use
24796 +        * the default if not available. We will store this as the frequency
24797 +        * of the timer to avoid future calculations.
24798 +        */
24799 +       frequency = processor_frequency();
24800 +       if (frequency == 0) {
24801 +               frequency = CLOCK_TICK_RATE;
24802 +       }
24803 +
24804 +       /*
24805 +        * Setup the primary clock source around sysval.  Linux does not
24806 +        * supply a Mhz multiplier so convert down to khz.
24807 +        */
24808 +       timer_device_clockbase.mult =
24809 +               clocksource_khz2mult(frequency / 1000,
24810 +                       timer_device_clockbase.shift);
24811 +       if (clocksource_register(&timer_device_clockbase)) {
24812 +               printk(KERN_ERR "timer: clocksource failed to register\n");
24813 +               return;
24814 +       }
24815 +
24816 +       /*
24817 +        * Always allocate a primary timer.
24818 +        */
24819 +       timer_device_alloc_event("timer-primary", -1, CPU_MASK_ALL_PTR);
24820 +
24821 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
24822 +       /*
24823 +        * If BROADCAST is selected we need to add a broadcast timer.
24824 +        */
24825 +       timer_device_alloc_event("timer-broadcast", -1, CPU_MASK_ALL_PTR);
24826 +#endif
24827 +
24828 +       /*
24829 +        * Allocate extra timers that are requested.
24830 +        */
24831 +       for (i = 0; i < CONFIG_TIMER_EXTRA_ALLOC; i++) {
24832 +               timer_device_alloc_event("timer-extra", -1, CPU_MASK_ALL_PTR);
24833 +       }
24834 +}
24835 --- /dev/null
24836 +++ b/arch/ubicom32/kernel/timer_tick.c
24837 @@ -0,0 +1,109 @@
24838 +/*
24839 + * arch/ubicom32/kernel/timer_tick.c
24840 + *     Impelemets a perodic timer.
24841 + *
24842 + * (C) Copyright 2009, Ubicom, Inc.
24843 + * Copyright (C) 1991, 1992, 1995  Linus Torvalds
24844 + *
24845 + * This file is part of the Ubicom32 Linux Kernel Port.
24846 + *
24847 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24848 + * it and/or modify it under the terms of the GNU General Public License
24849 + * as published by the Free Software Foundation, either version 2 of the
24850 + * License, or (at your option) any later version.
24851 + *
24852 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24853 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24854 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24855 + * the GNU General Public License for more details.
24856 + *
24857 + * You should have received a copy of the GNU General Public License
24858 + * along with the Ubicom32 Linux Kernel Port.  If not,
24859 + * see <http://www.gnu.org/licenses/>.
24860 + *
24861 + * Ubicom32 implementation derived from (with many thanks):
24862 + *   arch/m68knommu
24863 + *   arch/blackfin
24864 + *   arch/parisc
24865 + */
24866 +
24867 +#include <linux/profile.h>
24868 +
24869 +#include <asm/ip5000.h>
24870 +#include <asm/machdep.h>
24871 +#if defined(CONFIG_SMP)
24872 +#include <asm/smp.h>
24873 +#endif
24874 +
24875 +static unsigned int timervector;
24876 +static unsigned int frequency;
24877 +
24878 +/*
24879 + * timer_tick()
24880 + *     Kernel system timer support. Needs to keep up the real-time clock,
24881 + *     as well as call the "do_timer()" routine every clocktick.
24882 + */
24883 +static irqreturn_t timer_tick(int irq, void *dummy)
24884 +{
24885 +       int ticks;
24886 +
24887 +       BUG_ON(!irqs_disabled());
24888 +       ticks = timer_reset(timervector, frequency);
24889 +
24890 +       write_seqlock(&xtime_lock);
24891 +       do_timer(ticks);
24892 +       write_sequnlock(&xtime_lock);
24893 +
24894 +       update_process_times(user_mode(get_irq_regs()));
24895 +       profile_tick(CPU_PROFILING);
24896 +
24897 +#if defined(CONFIG_SMP)
24898 +       smp_send_timer_all();
24899 +#endif
24900 +       return(IRQ_HANDLED);
24901 +}
24902 +
24903 +/*
24904 + * Data used by setup_irq for the timer.
24905 + */
24906 +static struct irqaction timer_irq = {
24907 +       .name    = "timer",
24908 +       .flags   = IRQF_DISABLED | IRQF_TIMER,
24909 +       .handler = timer_tick,
24910 +};
24911 +
24912 +/*
24913 + * timer_tick_init()
24914 + *     Implements a periodic timer
24915 + *
24916 + * This implementation directly calls the timer_tick() and move
24917 + * the Linux kernel forward.  This is used when the user has not
24918 + * selected GENERIC_CLOCKEVENTS.
24919 + */
24920 +void timer_tick_init(void)
24921 +{
24922 +       /*
24923 +        * Now allocate a timer to ourselves.
24924 +        */
24925 +       timervector = timer_alloc();
24926 +       if (timervector == -1) {
24927 +               printk(KERN_WARNING "where did the timer go?\n");
24928 +               return;
24929 +       }
24930 +
24931 +       setup_irq(timervector, &timer_irq);
24932 +
24933 +       /*
24934 +        * Get the frequency from the processor device tree node or use
24935 +        * the default if not available. We will store this as the frequency
24936 +        * of the timer to avoid future calculations.
24937 +        */
24938 +       frequency = processor_frequency();
24939 +       if (frequency == 0) {
24940 +               frequency = CLOCK_TICK_RATE;
24941 +       }
24942 +       frequency /= CONFIG_HZ;
24943 +
24944 +       printk(KERN_NOTICE "timer will interrupt every: %d cycles\n", frequency);
24945 +       timer_set(timervector, frequency);
24946 +}
24947 --- /dev/null
24948 +++ b/arch/ubicom32/kernel/topology.c
24949 @@ -0,0 +1,47 @@
24950 +/*
24951 + * arch/ubicom32/kernel/topology.c
24952 + *   Ubicom32 architecture sysfs topology information.
24953 + *
24954 + * (C) Copyright 2009, Ubicom, Inc.
24955 + *
24956 + * This file is part of the Ubicom32 Linux Kernel Port.
24957 + *
24958 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24959 + * it and/or modify it under the terms of the GNU General Public License
24960 + * as published by the Free Software Foundation, either version 2 of the
24961 + * License, or (at your option) any later version.
24962 + *
24963 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24964 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24965 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
24966 + * the GNU General Public License for more details.
24967 + *
24968 + * You should have received a copy of the GNU General Public License
24969 + * along with the Ubicom32 Linux Kernel Port.  If not,
24970 + * see <http://www.gnu.org/licenses/>.
24971 + *
24972 + * Ubicom32 implementation derived from (with many thanks):
24973 + *   arch/m68knommu
24974 + *   arch/blackfin
24975 + *   arch/parisc
24976 + */
24977 +
24978 +#include <linux/init.h>
24979 +#include <linux/smp.h>
24980 +#include <linux/cpu.h>
24981 +#include <linux/cache.h>
24982 +
24983 +static struct cpu cpu_devices[NR_CPUS] __read_mostly;
24984 +
24985 +static int __init topology_init(void)
24986 +{
24987 +       int num;
24988 +
24989 +       for_each_present_cpu(num) {
24990 +               cpu_devices[num].hotpluggable = 0;
24991 +               register_cpu(&cpu_devices[num], num);
24992 +       }
24993 +       return 0;
24994 +}
24995 +
24996 +subsys_initcall(topology_init);
24997 --- /dev/null
24998 +++ b/arch/ubicom32/kernel/traps.c
24999 @@ -0,0 +1,514 @@
25000 +/*
25001 + * arch/ubicom32/kernel/traps.c
25002 + *   Ubicom32 architecture trap handling support.
25003 + *
25004 + * (C) Copyright 2009, Ubicom, Inc.
25005 + *
25006 + * This file is part of the Ubicom32 Linux Kernel Port.
25007 + *
25008 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25009 + * it and/or modify it under the terms of the GNU General Public License
25010 + * as published by the Free Software Foundation, either version 2 of the
25011 + * License, or (at your option) any later version.
25012 + *
25013 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25014 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25015 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25016 + * the GNU General Public License for more details.
25017 + *
25018 + * You should have received a copy of the GNU General Public License
25019 + * along with the Ubicom32 Linux Kernel Port.  If not,
25020 + * see <http://www.gnu.org/licenses/>.
25021 + *
25022 + * Ubicom32 implementation derived from (with many thanks):
25023 + *   arch/m68knommu
25024 + *   arch/blackfin
25025 + *   arch/parisc
25026 + */
25027 +
25028 +/*
25029 + * Sets up all exception vectors
25030 + */
25031 +#include <linux/sched.h>
25032 +#include <linux/signal.h>
25033 +#include <linux/kernel.h>
25034 +#include <linux/mm.h>
25035 +#include <linux/module.h>
25036 +#include <linux/types.h>
25037 +#include <linux/a.out.h>
25038 +#include <linux/user.h>
25039 +#include <linux/string.h>
25040 +#include <linux/linkage.h>
25041 +#include <linux/init.h>
25042 +#include <linux/ptrace.h>
25043 +#include <linux/kallsyms.h>
25044 +#include <linux/compiler.h>
25045 +#include <linux/stacktrace.h>
25046 +#include <linux/personality.h>
25047 +
25048 +#include <asm/uaccess.h>
25049 +#include <asm/stacktrace.h>
25050 +#include <asm/devtree.h>
25051 +#include <asm/setup.h>
25052 +#include <asm/fpu.h>
25053 +#include <asm/system.h>
25054 +#include <asm/traps.h>
25055 +#include <asm/pgtable.h>
25056 +#include <asm/processor.h>
25057 +#include <asm/machdep.h>
25058 +#include <asm/siginfo.h>
25059 +#include <asm/ip5000.h>
25060 +#include <asm/thread.h>
25061 +
25062 +#define TRAP_MAX_STACK_DEPTH 20
25063 +
25064 +/*
25065 + * These symbols are filled in by the linker.
25066 + */
25067 +extern unsigned long _stext;
25068 +extern unsigned long _etext;
25069 +
25070 +extern unsigned long __ocm_text_run_begin;
25071 +extern unsigned long __data_begin;
25072 +
25073 +extern void show_vmas(struct task_struct *task);
25074 +
25075 +const char *trap_cause_strings[] = {
25076 +       /*0*/   "inst address decode error",
25077 +       /*1*/   "inst sync error",
25078 +       /*2*/   "inst illegal",
25079 +       /*3*/   "src1 address decode error",
25080 +       /*4*/   "dst address decode error",
25081 +       /*5*/   "src1 alignment error",
25082 +       /*6*/   "dst alignment error",
25083 +       /*7*/   "src1 sync error",
25084 +       /*8*/   "dst sync error",
25085 +       /*9*/   "DCAPT error",
25086 +       /*10*/  "inst range error",
25087 +       /*11*/  "src1 range error",
25088 +       /*12*/  "dst range error",
25089 +};
25090 +
25091 +/*
25092 + * The device tree trap node definition.
25093 + */
25094 +struct trapnode {
25095 +       struct devtree_node dn;
25096 +       unsigned int intthread;
25097 +};
25098 +
25099 +static struct trapnode *tn;;
25100 +
25101 +/*
25102 + * trap_interrupt_handler()
25103 + *     Software Interrupt to ensure that a trap is serviced.
25104 + */
25105 +static irqreturn_t trap_interrupt_handler(int irq, void *dummy)
25106 +{
25107 +       /* Do Nothing */
25108 +       return IRQ_HANDLED;
25109 +}
25110 +
25111 +/*
25112 + * Data used by setup_irq for the timer.
25113 + */
25114 +static struct irqaction trap_irq = {
25115 +       .name    = "trap",
25116 +       .flags   = IRQF_DISABLED,
25117 +       .handler = trap_interrupt_handler,
25118 +};
25119 +
25120 +/*
25121 + * trap_cause_to_str()
25122 + *     Convert a trap_cause into a series of printk
25123 + */
25124 +static void trap_cause_to_str(long status)
25125 +{
25126 +       int bit;
25127 +
25128 +       if ((status & ((1 << TRAP_CAUSE_TOTAL) - 1)) == 0) {
25129 +               printk(KERN_NOTICE "decode: UNKNOWN CAUSES\n");
25130 +               return;
25131 +       }
25132 +
25133 +       for (bit = 0; bit < TRAP_CAUSE_TOTAL; bit++) {
25134 +               if (status & (1 << bit)) {
25135 +                       printk(KERN_NOTICE "\tdecode: %08x %s\n",
25136 +                              1 << bit, trap_cause_strings[bit]);
25137 +               }
25138 +       }
25139 +}
25140 +
25141 +/*
25142 + * trap_print_information()
25143 + *     Print the cause of the trap and additional info.
25144 + */
25145 +static void trap_print_information(const char *str, struct pt_regs *regs)
25146 +{
25147 +       printk(KERN_WARNING "\n");
25148 +
25149 +       if (current) {
25150 +               printk(KERN_WARNING "Process %s (pid: %d)\n",
25151 +                       current->comm, current->pid);
25152 +       }
25153 +
25154 +       if (current && current->mm) {
25155 +               printk(KERN_NOTICE "text = 0x%p-0x%p  data = 0x%p-0x%p\n"
25156 +                       KERN_NOTICE "bss = 0x%p-0x%p   user-stack = 0x%p\n"
25157 +                       KERN_NOTICE "\n",
25158 +                       (void *)current->mm->start_code,
25159 +                       (void *)current->mm->end_code,
25160 +                       (void *)current->mm->start_data,
25161 +                       (void *)current->mm->end_data,
25162 +                       (void *)current->mm->end_data,
25163 +                       (void *)current->mm->brk,
25164 +                       (void *)current->mm->start_stack);
25165 +       }
25166 +
25167 +       printk(KERN_WARNING "%s: Causes: 0x%08x\n", str,
25168 +                       (unsigned int)regs->trap_cause);
25169 +       trap_cause_to_str(regs->trap_cause);
25170 +       show_regs(regs);
25171 +       show_stack(NULL, (unsigned long *)regs->an[7]);
25172 +       printk(KERN_NOTICE "--- End Trap --- \n");
25173 +}
25174 +
25175 +/*
25176 + * dump_stack()
25177 + *     Dump the stack of the current task.
25178 + */
25179 +void dump_stack(void)
25180 +{
25181 +       show_stack(NULL, NULL);
25182 +}
25183 +EXPORT_SYMBOL(dump_stack);
25184 +
25185 +/*
25186 + * show_stack()
25187 + *     Print out information from the current stack.
25188 + */
25189 +void show_stack(struct task_struct *task, unsigned long *sp)
25190 +{
25191 +       /*
25192 +        *  Allocate just enough entries on the stack.
25193 +        */
25194 +       unsigned int calls[TRAP_MAX_STACK_DEPTH];
25195 +       unsigned long code_start;
25196 +       unsigned long code_end;
25197 +       unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
25198 +       unsigned long ocm_code_end = (unsigned long)&__data_begin;
25199 +       unsigned long stack_end = (unsigned long)(current->stack + THREAD_SIZE - 8);
25200 +       unsigned long stack = (unsigned long)sp;
25201 +       int kernel_stack = 1;
25202 +
25203 +       processor_dram(&code_start, &code_end);
25204 +
25205 +       /*
25206 +        * Which task are we talking about.
25207 +        */
25208 +       if (!task) {
25209 +               task = current;
25210 +       }
25211 +
25212 +       /*
25213 +        * Find the stack for the task if one was not specified.  Otherwise
25214 +        * use the specified stack.
25215 +        */
25216 +       if (!stack) {
25217 +               if (task != current) {
25218 +                       stack = task->thread.sp;
25219 +                       stack_end = (unsigned long)task->stack + THREAD_SIZE - 8;
25220 +               } else {
25221 +                       asm volatile (
25222 +                               "move.4         %0, SP          \n\t"
25223 +                               : "=r" (stack)
25224 +                       );
25225 +               }
25226 +       }
25227 +
25228 +       printk(KERN_NOTICE "Starting backtrace: PID %d '%s'\n",
25229 +                       task->pid, task->comm);
25230 +
25231 +       /*
25232 +        * We do 2 passes the first pass is Kernel stack is the second
25233 +        * User stack.
25234 +        */
25235 +       while (kernel_stack) {
25236 +               unsigned long *handle;
25237 +               unsigned int i, idx = 0;
25238 +               struct pt_regs *pt = task_pt_regs(task);
25239 +
25240 +               /*
25241 +                * If the task is in user mode, reset the start
25242 +                * and end values for text.
25243 +                */
25244 +               if (__user_mode(stack)) {
25245 +                       if (!(task->personality & FDPIC_FUNCPTRS)) {
25246 +                               printk(KERN_NOTICE "  User Stack:\n");
25247 +                               code_start = task->mm->start_code;
25248 +                               code_end = task->mm->end_code;
25249 +                       } else {
25250 +                               printk(KERN_NOTICE "  User Stack (fdpic):\n");
25251 +                               show_vmas(task);
25252 +                       }
25253 +                       stack_end = task->mm->start_stack;
25254 +                       ocm_code_end = ocm_code_start = 0;
25255 +                       kernel_stack = 0;
25256 +               } else {
25257 +                       printk(KERN_NOTICE "  Kernel Stack:\n");
25258 +               }
25259 +
25260 +               /*
25261 +                * Collect the stack back trace information.
25262 +                */
25263 +               printk("    code[0x%lx-0x%lx]", code_start, code_end);
25264 +               if (ocm_code_start) {
25265 +                       printk(" ocm_code[0x%lx-0x%lx]",
25266 +                              ocm_code_start, ocm_code_end);
25267 +               }
25268 +               printk("\n    stack[0x%lx-0x%lx]\n", stack, stack_end);
25269 +
25270 +               handle = (unsigned long*)stack;
25271 +               while (idx < TRAP_MAX_STACK_DEPTH) {
25272 +                       calls[idx] = stacktrace_iterate(&handle,
25273 +                                       code_start, code_end,
25274 +                                       ocm_code_start, ocm_code_end,
25275 +                                       (unsigned long)stack, stack_end);
25276 +                       if (calls[idx] == 0) {
25277 +                               break;
25278 +                       }
25279 +                       idx++;
25280 +               }
25281 +
25282 +               /*
25283 +                * Now print out the data.
25284 +                */
25285 +               printk(KERN_NOTICE "  CALL && CALLI on stack:");
25286 +               for (i = 0; i < idx; i++) {
25287 +                       printk("%s0x%x, ", (i & 0x3) == 0 ?  "\n    " : "",
25288 +                                       calls[i]);
25289 +               }
25290 +               printk(idx == TRAP_MAX_STACK_DEPTH ? "...\n" : "\n");
25291 +
25292 +               /*
25293 +                * If we are doing user stack we are done
25294 +                */
25295 +               if (!kernel_stack) {
25296 +                       break;
25297 +               }
25298 +
25299 +               /*
25300 +                * Does this kernel stack have a mm (i.e. is it user)
25301 +                */
25302 +               if (!task->mm) {
25303 +                       printk("No mm for userspace stack.\n");
25304 +                       break;
25305 +               }
25306 +               /*
25307 +                * Get the user-mode stack (if any)
25308 +                */
25309 +               stack = pt->an[7];
25310 +               printk(KERN_NOTICE "Userspace stack at 0x%lx frame type %d\n",
25311 +                               stack, (int)pt->frame_type);
25312 +               if (!__user_mode(stack)) {
25313 +                       break;
25314 +               }
25315 +       }
25316 +}
25317 +
25318 +/*
25319 + * die_if_kernel()
25320 + *     Determine if we are in kernel mode and if so print stuff out and die.
25321 + */
25322 +void die_if_kernel(char *str, struct pt_regs *regs, long trap_cause)
25323 +{
25324 +       unsigned int s3value;
25325 +
25326 +       if (user_mode(regs)) {
25327 +               return;
25328 +       }
25329 +
25330 +       console_verbose();
25331 +       trap_print_information(str, regs);
25332 +
25333 +       /*
25334 +        * If the debugger is attached via the hardware mailbox protocol,
25335 +        * go into an infinite loop and the debugger will figure things out.
25336 +        */
25337 +       asm volatile (
25338 +             "move.4 %0, scratchpad3"
25339 +             : "=r" (s3value)
25340 +       );
25341 +       if (s3value) {
25342 +               asm volatile("1:        jmpt.t 1b");
25343 +       }
25344 +
25345 +       /*
25346 +        * Set the debug taint value.
25347 +        */
25348 +       add_taint(TAINT_DIE);
25349 +       do_exit(SIGSEGV);
25350 +}
25351 +
25352 +/*
25353 + * trap_handler()
25354 + *     Handle traps.
25355 + *
25356 + * Traps are treated as interrupts and registered with the LDSR.  When
25357 + * the LDSR takes the interrupt, it will determine if a trap has occurred
25358 + * and service the trap prior to servicing the interrupt.
25359 + *
25360 + * This function is directly called by the LDSR.
25361 + */
25362 +void trap_handler(int irq, struct pt_regs *regs)
25363 +{
25364 +       int sig = SIGSEGV;
25365 +       siginfo_t info;
25366 +       unsigned int trap_cause = regs->trap_cause;
25367 +
25368 +       BUG_ON(!irqs_disabled());
25369 +
25370 +       /*
25371 +        * test if in kernel and die.
25372 +        */
25373 +       die_if_kernel("Kernel Trap", regs, trap_cause);
25374 +
25375 +       /*
25376 +        * User process problem, setup a signal for this process
25377 +        */
25378 +       if ((trap_cause & (1 << TRAP_CAUSE_DST_RANGE_ERR)) ||
25379 +           (trap_cause & (1 << TRAP_CAUSE_SRC1_RANGE_ERR)) ||
25380 +           (trap_cause & (1 << TRAP_CAUSE_I_RANGE_ERR))) {
25381 +               sig = SIGSEGV;
25382 +               info.si_code = SEGV_MAPERR;
25383 +       } else if ((trap_cause & (1 << TRAP_CAUSE_DST_MISALIGNED)) ||
25384 +                  (trap_cause & (1 << TRAP_CAUSE_SRC1_MISALIGNED))) {
25385 +               sig = SIGBUS;
25386 +               info.si_code = BUS_ADRALN;
25387 +       } else if ((trap_cause & (1 << TRAP_CAUSE_DST_DECODE_ERR)) ||
25388 +                  (trap_cause & (1 << TRAP_CAUSE_SRC1_DECODE_ERR))) {
25389 +               sig = SIGILL;
25390 +               info.si_code = ILL_ILLOPN;
25391 +       } else if ((trap_cause & (1 << TRAP_CAUSE_ILLEGAL_INST))) {
25392 +               /*
25393 +                * Check for software break point and if found signal trap
25394 +                * not illegal instruction.
25395 +                */
25396 +               unsigned long instruction;
25397 +               if (between(regs->pc, KERNELSTART, memory_end) &&
25398 +                       (regs->pc & 3) == 0 &&
25399 +                       get_user(instruction, (unsigned long *)regs->pc) == 0) {
25400 +
25401 +                       /*
25402 +                        * This used to be 0xaabbccdd but it turns out
25403 +                        * that is now valid in ubicom32v4 isa so we
25404 +                        * have switched to 0xfabbccdd
25405 +                        */
25406 +                       if ((instruction == 0xfabbccdd) ||
25407 +                           (instruction == 0xaabbccdd)) {
25408 +                               sig = SIGTRAP;
25409 +                               info.si_code = TRAP_BRKPT;
25410 +                               goto send_signal;
25411 +                       }
25412 +               }
25413 +               sig = SIGILL;
25414 +               info.si_code = ILL_ILLOPC;
25415 +       } else if ((trap_cause & (1 << TRAP_CAUSE_I_DECODE_ERR))) {
25416 +               sig = SIGILL;
25417 +               info.si_code = ILL_ILLOPC;
25418 +       } else if ((trap_cause & (1 << TRAP_CAUSE_DCAPT))) {
25419 +               sig = SIGTRAP;
25420 +               info.si_code = TRAP_TRACE;
25421 +       }
25422 +
25423 +       /*
25424 +        * Print a trap information block to the console, do not
25425 +        * print this above the case because we don't want it
25426 +        * printed for software break points.
25427 +        */
25428 +       trap_print_information("User Trap", regs);
25429 +
25430 +send_signal:
25431 +
25432 +       force_sig_info(sig, &info, current);
25433 +
25434 +       /*
25435 +        * Interrupts are disabled, re-enable them now.
25436 +        */
25437 +       if (!irqs_disabled()) {
25438 +               printk(KERN_EMERG "interrupts enabled on exit, irq=%d, regs=%p",
25439 +                               irq, regs);
25440 +               BUG();
25441 +       }
25442 +}
25443 +
25444 +/*
25445 + * trap_init_interrupt()
25446 + *     We need a 2nd trap handling init that will occur after init_IRQ().
25447 + */
25448 +void __init trap_init_interrupt(void)
25449 +{
25450 +       int err;
25451 +       unsigned char tirq;
25452 +       struct devtree_node *dn = (struct devtree_node *)tn;
25453 +
25454 +       /*
25455 +        * Now setup the Software IRQ so that if a trap occurs the LDSR
25456 +        * is started.  The irq is there just to "force" the LDSR to run.
25457 +        */
25458 +       if (!tn) {
25459 +               printk(KERN_WARNING "trap_init_interrupt skipped.\n");
25460 +               return;
25461 +       }
25462 +
25463 +       err = devtree_irq(dn, NULL, &tirq);
25464 +       if (err) {
25465 +               printk(KERN_WARNING "error obtaining trap irq value: %d\n",
25466 +                       err);
25467 +               return;
25468 +       }
25469 +
25470 +       if (tirq == DEVTREE_IRQ_NONE) {
25471 +               printk(KERN_WARNING "trap irq not available: %d\n", tirq);
25472 +               return;
25473 +       }
25474 +
25475 +       err = setup_irq(tirq, &trap_irq);
25476 +       if (err) {
25477 +               printk(KERN_WARNING "trap irq setup failed: %d\n", err);
25478 +               return;
25479 +       }
25480 +
25481 +       /*
25482 +        * Let ultra know which thread is handling the traps and
25483 +        * what the interrupt to use is.
25484 +        */
25485 +       tn->intthread = ldsr_get_threadid();
25486 +
25487 +       /*
25488 +        * Tell the LDSR about our IRQ so that it will unsuspend
25489 +        * if one occurs while waiting for the per thread lock.
25490 +        */
25491 +       ldsr_set_trap_irq(tirq);
25492 +}
25493 +
25494 +/*
25495 + * trap_init()
25496 + *     init trap handling
25497 + *
25498 + * Trap handling is done through the ldsr.  Every time an interrupt
25499 + * occurs, the LDSR looks for threads that are listed in the TRAP
25500 + * register and forces a call to the trap handler.
25501 + */
25502 +void __init trap_init(void)
25503 +{
25504 +       /*
25505 +        * If we do not have a trap node in the device tree, we leave the fault
25506 +        * handling to the underlying hardware.
25507 +        */
25508 +       tn = (struct trapnode *)devtree_find_node("traps");
25509 +       if (!tn) {
25510 +               printk(KERN_WARNING "traps are not handled by linux\n");
25511 +               return;
25512 +       }
25513 +}
25514 --- /dev/null
25515 +++ b/arch/ubicom32/kernel/uaccess.c
25516 @@ -0,0 +1,109 @@
25517 +/*
25518 + * arch/ubicom32/include/asm/uaccess.c
25519 + *   User space memory access functions for Ubicom32 architecture.
25520 + *
25521 + * (C) Copyright 2009, Ubicom, Inc.
25522 + *
25523 + * This file is part of the Ubicom32 Linux Kernel Port.
25524 + *
25525 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25526 + * it and/or modify it under the terms of the GNU General Public License
25527 + * as published by the Free Software Foundation, either version 2 of the
25528 + * License, or (at your option) any later version.
25529 + *
25530 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25531 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25532 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25533 + * the GNU General Public License for more details.
25534 + *
25535 + * You should have received a copy of the GNU General Public License
25536 + * along with the Ubicom32 Linux Kernel Port.  If not,
25537 + * see <http://www.gnu.org/licenses/>.
25538 + *
25539 + * Ubicom32 implementation derived from (with many thanks):
25540 + *   arch/m68knommu
25541 + *   arch/blackfin
25542 + *   arch/parisc
25543 + */
25544 +
25545 +#include <linux/sched.h>
25546 +#include <linux/mm.h>
25547 +#include <linux/string.h>
25548 +#include <linux/module.h>
25549 +
25550 +#include <asm/segment.h>
25551 +#include <asm/uaccess.h>
25552 +
25553 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
25554 +
25555 +/*
25556 + * __access_ok()
25557 + *     Check that the address is in the current processes.
25558 + *
25559 + * NOTE: The kernel uses "pretend" user addresses that wind
25560 + * up calling access_ok() so this approach has only marginal
25561 + * value because you wind up with lots of false positives.
25562 + */
25563 +int __access_ok(unsigned long addr, unsigned long size)
25564 +{
25565 +       // struct vm_area_struct *vma;
25566 +
25567 +       /*
25568 +        * Don't do anything if we are not a running system yet.
25569 +        */
25570 +       if (system_state != SYSTEM_RUNNING) {
25571 +               return 1;
25572 +       }
25573 +
25574 +       /*
25575 +        * It appears that Linux will call this function even when we are not
25576 +        * in the context of a user space application that has a VM address
25577 +        * space.  So we must check that current and mm are valid before
25578 +        * performing the check.
25579 +        */
25580 +       if ((!current) || (!current->mm)) {
25581 +               return 1;
25582 +       }
25583 +
25584 +       /*
25585 +        * We perform some basic checks on the address to ensure that it
25586 +        * is at least within the range of DRAM.
25587 +        */
25588 +       if ((addr < (int)&_etext) || (addr > memory_end)) {
25589 +               printk(KERN_WARNING "pid=%d[%s]: range [%lx - %lx] not in memory area: [%lx - %lx]\n",
25590 +                       current->pid, current->comm,
25591 +                       addr, addr + size,
25592 +                       memory_start, memory_end);
25593 +               return 0;
25594 +       }
25595 +
25596 +       /*
25597 +        * For nommu Linux we can check this by looking at the allowed
25598 +        * memory map for the process.
25599 +        *
25600 +        * TODO: Since the kernel passes addresses in it's own space as though
25601 +        * they were user address, we can not validate the addresses this way.
25602 +        */
25603 +#if 0
25604 +       if (!down_read_trylock(&current->mm->mmap_sem)) {
25605 +               return 1;
25606 +       }
25607 +       vma = find_vma(current->mm, addr);
25608 +       if (!vma) {
25609 +               up_read(&current->mm->mmap_sem);
25610 +               printk(KERN_WARNING "pid=%d[%s]: possible invalid acesss on range: [%lx - %lx]\n",
25611 +                               current->pid, current->comm, addr, addr + size);
25612 +               return 1;
25613 +       }
25614 +       if ((addr + size) > vma->vm_end) {
25615 +               up_read(&current->mm->mmap_sem);
25616 +               printk(KERN_WARNING "pid=%d[%s]: possible invalid length on range: [%lx - %lx]\n",
25617 +                               current->pid, current->comm, addr, addr + size);
25618 +               return 1;
25619 +       }
25620 +       up_read(&current->mm->mmap_sem);
25621 +#endif
25622 +       return 1;
25623 +}
25624 +
25625 +EXPORT_SYMBOL(__access_ok);
25626 --- /dev/null
25627 +++ b/arch/ubicom32/kernel/ubicom32_context_switch.S
25628 @@ -0,0 +1,359 @@
25629 +/*
25630 + * arch/ubicom32/kernel/ubicom32_context_switch.S
25631 + *     Implements context switch and return functions.
25632 + *
25633 + * (C) Copyright 2009, Ubicom, Inc.
25634 + *
25635 + * This file is part of the Ubicom32 Linux Kernel Port.
25636 + *
25637 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25638 + * it and/or modify it under the terms of the GNU General Public License
25639 + * as published by the Free Software Foundation, either version 2 of the
25640 + * License, or (at your option) any later version.
25641 + *
25642 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25643 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25644 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
25645 + * the GNU General Public License for more details.
25646 + *
25647 + * You should have received a copy of the GNU General Public License
25648 + * along with the Ubicom32 Linux Kernel Port.  If not,
25649 + * see <http://www.gnu.org/licenses/>.
25650 + *
25651 + * Ubicom32 implementation derived from (with many thanks):
25652 + *   arch/m68knommu
25653 + *   arch/blackfin
25654 + *   arch/parisc
25655 + */
25656 +#include <linux/sys.h>
25657 +#include <linux/linkage.h>
25658 +#include <asm/asm-offsets.h>
25659 +#include <asm/ubicom32-common.h>
25660 +#include <asm/ip5000.h>
25661 +#include <asm/range-protect.h>
25662 +
25663 +/*
25664 + * begin_restore_context()
25665 + *     Restore most of the context from sp (struct pt_reg *)
25666 + *
25667 + * This *can* be called without the global atomic lock. (because sp is
25668 + * not restored!)  Only d15 and a3 are allowed to be used after this
25669 + * before calling complete_restore_context
25670 + */
25671 +.macro begin_restore_context
25672 +       move.4  d0, PT_D0(sp)
25673 +       move.4  d1, PT_D1(sp)
25674 +       move.4  d2, PT_D2(sp)
25675 +       move.4  d3, PT_D3(sp)
25676 +       move.4  d4, PT_D4(sp)
25677 +       move.4  d5, PT_D5(sp)
25678 +       move.4  d6, PT_D6(sp)
25679 +       move.4  d7, PT_D7(sp)
25680 +       move.4  d8, PT_D8(sp)
25681 +       move.4  d9, PT_D9(sp)
25682 +       move.4  d10, PT_D10(sp)
25683 +       move.4  d11, PT_D11(sp)
25684 +       move.4  d12, PT_D12(sp)
25685 +       move.4  d13, PT_D13(sp)
25686 +       move.4  d14, PT_D14(sp)
25687 +;;     move.4  d15, PT_D15(sp)
25688 +       move.4  a0, PT_A0(sp)
25689 +       move.4  a1, PT_A1(sp)
25690 +       move.4  a2, PT_A2(sp)
25691 +;;     move.4  a3, PT_A3(sp)
25692 +       move.4  a4, PT_A4(sp)
25693 +       move.4  a5, PT_A5(sp)
25694 +       move.4  a6, PT_A6(sp)
25695 +       move.4  acc0_hi, PT_ACC0HI(sp)
25696 +       move.4  acc0_lo, PT_ACC0LO(sp)
25697 +       move.4  mac_rc16, PT_MAC_RC16(sp)
25698 +       move.4  acc1_hi, PT_ACC1HI(sp)
25699 +       move.4  acc1_lo, PT_ACC1LO(sp)
25700 +       move.4  source3, PT_SOURCE3(sp)
25701 +       move.4  int_mask0, PT_INT_MASK0(sp)
25702 +       move.4  int_mask1, PT_INT_MASK1(sp)
25703 +.endm
25704 +
25705 +/*
25706 + * complete_restore_context()
25707 + *     Completely restore the context from sp (struct pt_reg *)
25708 + *
25709 + * Note: Recovered PC and CSR are saved on the stack and are to be
25710 + * popped off before returning.
25711 + */
25712 +.macro complete_restore_context
25713 +       move.4  a3, sp
25714 +       move.4  d15, PT_D15(sp)
25715 +       move.4  sp, PT_SP(a3)           ; Recover Stack pointer from save area
25716 +       move.4  -4(sp)++, PT_PC(a3)     ; Recover saved PC and save to stack
25717 +       move.4  -4(sp)++, PT_CSR(a3)    ; Recover saved csr and save to stack
25718 +       move.4  a3, PT_A3(a3)
25719 +.endm
25720 +
25721 +/*
25722 + * old restore_context macro
25723 + */
25724 +.macro restore_context
25725 +       begin_restore_context
25726 +       complete_restore_context
25727 +.endm
25728 +
25729 +/*
25730 + * ldsr_thread_enable_interrupts()
25731 + *     An assembly version of the enable interrupts function.
25732 + *
25733 + * The stack is fair game but all registers MUST be preserved.
25734 + *
25735 + */
25736 +.macro ldsr_thread_enable_interrupts
25737 +       move.4  -4(sp)++, d3    ; Push d3
25738 +       move.4  -4(sp)++, a3    ; Push a3
25739 +
25740 +       /*
25741 +        * Read the ROSR and obtain ~(1 << tid)
25742 +        */
25743 +       lsr.4   d3, rosr, #0x2  ; Move the thread portion of ROSR into d3
25744 +       lsl.4   d3, #1, d3      ; perform a (1 << tid)
25745 +       not.4   d3, d3          ; Negate the value of d3 == ~(1 << threadid)
25746 +
25747 +       /*
25748 +        * Get the value of the ldsr_soft_irq_mask
25749 +        */
25750 +       moveai  a3, #%hi(ldsr_soft_irq_mask)
25751 +       move.4  a3, %lo(ldsr_soft_irq_mask)(a3)
25752 +
25753 +       /*
25754 +        * Now re-enable interrupts for this thread and then
25755 +        * wakeup the LDSR.
25756 +        */
25757 +       and.4   scratchpad1, scratchpad1, d3
25758 +       move.4  int_set0, a3
25759 +
25760 +       /*
25761 +        * Restore the registers.
25762 +        */
25763 +       move.4  a3, (sp)4++
25764 +       move.4  d3, (sp)4++
25765 +.endm
25766 +
25767 +/*
25768 + * ret_from_interrupt_to_kernel()
25769 + *     RFI function that is where do_IRQ() returns to if the thread was
25770 + *     in kernel space.
25771 + */
25772 +       .section .text.ret_from_interrupt_to_kernel, "ax", @progbits
25773 +       .global ret_from_interrupt_to_kernel
25774 +ret_from_interrupt_to_kernel:
25775 +       begin_restore_context           ; Restore the thread context
25776 +       atomic_lock_acquire             ; Enter critical section
25777 +       complete_restore_context        ; Restore the thread context
25778 +       atomic_lock_release             ; Leave critical section
25779 +       ldsr_thread_enable_interrupts   ; enable the threads interrupts
25780 +       move.4  csr, (sp)4++            ; Restore csr from the stack
25781 +       ret     (sp)4++
25782 +
25783 +/*
25784 + * ret_from_interrupt_to_user()
25785 + *     RFI function that is where do_IRQ() returns to if the thread was
25786 + *     in user space.
25787 + *
25788 + * TODO: Do we really need the critical section handling in this code?
25789 + *
25790 + */
25791 +       .section .text.ret_from_interrupt_to_user, "ax", @progbits
25792 +       .global ret_from_interrupt_to_user
25793 +ret_from_interrupt_to_user:
25794 +       ldsr_thread_enable_interrupts                   ; enable the threads interrupts
25795 +       /*
25796 +        * Set a1 to the thread info pointer, no need to save it as we are
25797 +        * restoring userspace and will never return
25798 +        */
25799 +       movei   d0, #(~(ASM_THREAD_SIZE-1))
25800 +       and.4   a1, sp, d0
25801 +
25802 +       /*
25803 +        * Test if the scheduler needs to be called.
25804 +        */
25805 +       btst    TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
25806 +       jmpeq.t 2f
25807 +       call    a5, schedule                    ; Call the scheduler. I will come back here.
25808 +
25809 +       /*
25810 +        * See if we have pending signals and call do_signal
25811 +        * if needed.
25812 +        */
25813 +2:
25814 +       btst    TI_FLAGS(a1), #ASM_TIF_SIGPENDING       ; Any signals needed?
25815 +       jmpeq.t 1f
25816 +
25817 +       /*
25818 +        * Now call do_signal()
25819 +        */
25820 +       move.4  d0, #0                                  ; oldset pointer is NULL
25821 +       move.4  d1, sp                                  ; d1 is the regs pointer
25822 +       call    a5, do_signal                           ; Call do_signal()
25823 +
25824 +       /*
25825 +        * Back from do_signal(), re-enter critical section.
25826 +        */
25827 +1:
25828 +       begin_restore_context                           ; Restore the thread context
25829 +       atomic_lock_acquire                             ; Enter critical section
25830 +       call a3, __complete_and_return_to_userspace     ; jump to unprotected section
25831 +
25832 +/*
25833 + * restore_all_registers()
25834 + *
25835 + * restore_all_registers will be the alternate exit route for
25836 + * preempted processes that have called a signal handler
25837 + * and are returning back to user space.
25838 + */
25839 +       .section .text.restore_all_registers, "ax", @progbits
25840 +       .global restore_all_registers
25841 +restore_all_registers:
25842 +       begin_restore_context                   ; Restore the thread context
25843 +       atomic_lock_acquire                     ; Enter critical section
25844 +       call a3, __complete_and_return_to_userspace
25845 +
25846 +/*
25847 + * __complete_and_return_to_userspace
25848 + *
25849 + * restores the second half of the context and returns
25850 + * You must have the atomic lock when you call this function
25851 + */
25852 +       .section .kernel_unprotected, "ax", @progbits
25853 +__complete_and_return_to_userspace:
25854 +       disable_kernel_ranges_for_current d15   ; disable kernel ranges
25855 +       complete_restore_context                ; restore previous context
25856 +       atomic_lock_release                     ; Leave critical section
25857 +       move.4  csr, (sp)4++                    ; Restore csr from the stack
25858 +       ret     (sp)4++
25859 +
25860 +/*
25861 + * ret_from_fork()
25862 + *     Called on the child's return from fork system call.
25863 + */
25864 +       .section .text.ret_from_fork, "ax", @progbits
25865 +       .global ret_from_fork
25866 +ret_from_fork:
25867 +       ;;;  d0 contains the arg for schedule_tail
25868 +       ;;;  the others we don't care about as they are in PT_REGS (sp)
25869 +       call   a5, schedule_tail
25870 +
25871 +       atomic_lock_acquire             ; Enter critical section
25872 +
25873 +       move.4  a3, sp
25874 +       move.4  d0, PT_D0(a3)           ; Restore D0
25875 +       move.4  d1, PT_D1(a3)           ; Restore D1
25876 +       move.4  d2, PT_D2(a3)           ; Restore D2
25877 +       move.4  d3, PT_D3(a3)           ; Restore D3
25878 +       move.4  d10, PT_D10(a3)         ; Restore D10
25879 +       move.4  d11, PT_D11(a3)         ; Restore D11
25880 +       move.4  d12, PT_D12(a3)         ; Restore D12
25881 +       move.4  d13, PT_D13(a3)         ; Restore D13
25882 +       move.4  a1, PT_A1(a3)           ; Restore A1
25883 +       move.4  a2, PT_A2(a3)           ; Restore A2
25884 +       move.4  a5, PT_A5(a3)           ; Restore A5
25885 +       move.4  a6, PT_A6(a3)           ; Restore A6
25886 +       ;;  I think atomic_lock_acquire could be moved here..
25887 +       move.4  sp, PT_SP(a3)           ; Restore sp
25888 +       move.4  a4, PT_PC(a3)           ; Restore pc in register a4
25889 +       move.4  PT_FRAME_TYPE(a3), #0   ; Clear frame_type to indicate it is invalid.
25890 +
25891 +#ifdef CONFIG_PROTECT_KERNEL
25892 +       call a3, __ret_from_fork_bottom_half
25893 +       .section .kernel_unprotected, "ax", @progbits
25894 +__ret_from_fork_bottom_half:
25895 +       disable_kernel_ranges_for_current d15
25896 +#endif
25897 +       atomic_lock_release             ; Leave critical section
25898 +       calli   a4, 0(a4)               ; Return.
25899 +
25900 +/*
25901 + * __switch_to()
25902 + *
25903 + * Call with:
25904 + *     void *__switch_to(struct task_struct *prev, struct thread_struct *prev_switch,
25905 + *                             struct thread_struct *next_switch)
25906 + */
25907 +       .section .text.__switch_to, "ax", @progbits
25908 +       .global __switch_to
25909 +__switch_to:
25910 +
25911 +       /*
25912 +        * Set up register a3 to point to save area.
25913 +        */
25914 +       movea   a3, d1                  ; a3 now holds prev_switch
25915 +       move.4  (a3)4++, d10
25916 +       move.4  (a3)4++, d11
25917 +       move.4  (a3)4++, d12
25918 +       move.4  (a3)4++, d13
25919 +       move.4  (a3)4++, a1
25920 +       move.4  (a3)4++, a2
25921 +       move.4  (a3)4++, a5
25922 +       move.4  (a3)4++, a6
25923 +       move.4  (a3)4++, a7
25924 +
25925 +       /*
25926 +        * Set up register a3 to point to restore area.
25927 +        */
25928 +       movea   a3, d2                  ; a3 now holds next_switch
25929 +       move.4  d10 , (a3)4++
25930 +       move.4  d11 , (a3)4++
25931 +       move.4  d12 , (a3)4++
25932 +       move.4  d13 , (a3)4++
25933 +       move.4  a1 , (a3)4++
25934 +       move.4  a2 , (a3)4++
25935 +       move.4  a5 , (a3)4++
25936 +       move.4  a6 , (a3)4++
25937 +       move.4  a7 , (a3)4++
25938 +
25939 +       /*
25940 +        * Load the sw_ksp with the proper thread_info pointer.
25941 +        */
25942 +       movei   d15, #(~(ASM_THREAD_SIZE-1))
25943 +       and.4   a3, sp, d15             ; a3 now has the thread info pointer
25944 +       moveai  a4, #%hi(sw_ksp)
25945 +       lea.1   a4, %lo(sw_ksp)(a4)     ; a4 now has the base address of sw_ksp array
25946 +       lsr.4   d15, ROSR, #2           ; Thread number - bit's 6 through 31 are zeroes anyway.
25947 +       move.4  (a4, d15), a3           ; Load the thread info pointer into the hw_ksp array..
25948 +
25949 +       /*
25950 +        * We are done with context switch. Time to return..
25951 +        */
25952 +       calli   a5, 0(a5)
25953 +       .size __switch_to, . - __switch_to
25954 +
25955 +/*
25956 + * ubicom32_emulate_insn()
25957 + *     Emulates the instruction.
25958 + *
25959 + * Call with:
25960 + *     unsigned int ubicom32_emulate_insn(int source1, int source2, int source3, int *save_acc, int *save_csr);
25961 + */
25962 +       .section .text.ubicom32_emulate_insn, "ax", @progbits
25963 +       .global ubicom32_emulate_insn
25964 +       .global trap_emulate
25965 +ubicom32_emulate_insn:
25966 +       movea   a3, d3          ; a3 holds save_acc pointer
25967 +       movea   a4, d4          ; a4 hods save_csr pointer
25968 +       move.4  source3, d2
25969 +       move.4  acc0_lo, (a3)
25970 +       move.4  acc0_hi, 4(a3)
25971 +       move.4  acc1_lo, 8(a3)
25972 +       move.4  acc1_hi, 12(a3)
25973 +       move.4  mac_rc16, 16(a3)
25974 +       move.4  CSR, (a4)
25975 +       setcsr_flush 0
25976 +
25977 +trap_emulate:
25978 +       move.4  d0, d1
25979 +       setcsr_flush 0
25980 +       move.4  (a4), CSR       ; Save csr
25981 +       move.4  (a3), acc0_lo
25982 +       move.4  4(a3), acc0_hi
25983 +       move.4  8(a3), acc1_lo
25984 +       move.4  12(a3), acc1_hi
25985 +       move.4  16(a3), mac_rc16
25986 +       ret     a5
25987 +       .size ubicom32_emulate_insn, . - ubicom32_emulate_insn
25988 --- /dev/null
25989 +++ b/arch/ubicom32/kernel/ubicom32_ksyms.c
25990 @@ -0,0 +1,98 @@
25991 +/*
25992 + * arch/ubicom32/kernel/ubicom32_ksyms.c
25993 + *   Ubicom32 architecture compiler support and misc symbols.
25994 + *
25995 + * (C) Copyright 2009, Ubicom, Inc.
25996 + *
25997 + * This file is part of the Ubicom32 Linux Kernel Port.
25998 + *
25999 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26000 + * it and/or modify it under the terms of the GNU General Public License
26001 + * as published by the Free Software Foundation, either version 2 of the
26002 + * License, or (at your option) any later version.
26003 + *
26004 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26005 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26006 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26007 + * the GNU General Public License for more details.
26008 + *
26009 + * You should have received a copy of the GNU General Public License
26010 + * along with the Ubicom32 Linux Kernel Port.  If not,
26011 + * see <http://www.gnu.org/licenses/>.
26012 + *
26013 + * Ubicom32 implementation derived from (with many thanks):
26014 + *   arch/m68knommu
26015 + *   arch/blackfin
26016 + *   arch/parisc
26017 + */
26018 +#include <linux/module.h>
26019 +#include <linux/linkage.h>
26020 +#include <linux/sched.h>
26021 +#include <linux/string.h>
26022 +#include <linux/mm.h>
26023 +#include <linux/user.h>
26024 +#include <linux/elfcore.h>
26025 +#include <linux/in6.h>
26026 +#include <linux/interrupt.h>
26027 +#include <linux/io.h>
26028 +#include <linux/semaphore.h>
26029 +
26030 +#include <asm/setup.h>
26031 +#include <asm/machdep.h>
26032 +#include <asm/pgalloc.h>
26033 +#include <asm/irq.h>
26034 +#include <asm/checksum.h>
26035 +#include <asm/current.h>
26036 +
26037 +/* platform dependent support */
26038 +
26039 +EXPORT_SYMBOL(__ioremap);
26040 +EXPORT_SYMBOL(iounmap);
26041 +
26042 +EXPORT_SYMBOL(ip_fast_csum);
26043 +
26044 +
26045 +/* Networking helper routines. */
26046 +EXPORT_SYMBOL(csum_partial_copy_nocheck);
26047 +
26048 +/* The following are special because they're not called
26049 +   explicitly (the C compiler generates them).  Fortunately,
26050 +   their interface isn't gonna change any time soon now, so
26051 +   it's OK to leave it out of version control.  */
26052 +EXPORT_SYMBOL(memcpy);
26053 +EXPORT_SYMBOL(memset);
26054 +EXPORT_SYMBOL(memmove);
26055 +
26056 +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4
26057 +/*
26058 + * libgcc functions - functions that are used internally by the
26059 + * compiler...  (prototypes are not correct though, but that
26060 + * doesn't really matter since they're not versioned).
26061 + */
26062 +extern void __ashldi3(void);
26063 +extern void __ashrdi3(void);
26064 +extern void __divsi3(void);
26065 +extern void __divdi3(void);
26066 +extern void __lshrdi3(void);
26067 +extern void __modsi3(void);
26068 +extern void __muldi3(void);
26069 +extern void __udivsi3(void);
26070 +extern void __umodsi3(void);
26071 +
26072 +/* gcc lib functions */
26073 +EXPORT_SYMBOL(__ashldi3);
26074 +EXPORT_SYMBOL(__ashrdi3);
26075 +EXPORT_SYMBOL(__divsi3);
26076 +EXPORT_SYMBOL(__divdi3);
26077 +EXPORT_SYMBOL(__lshrdi3);
26078 +EXPORT_SYMBOL(__modsi3);
26079 +EXPORT_SYMBOL(__muldi3);
26080 +EXPORT_SYMBOL(__udivsi3);
26081 +EXPORT_SYMBOL(__umodsi3);
26082 +#else
26083 +extern void __libgcc_udivmodsi(void);
26084 +extern void __libgcc_divmodsi(void);
26085 +
26086 +EXPORT_SYMBOL(__libgcc_udivmodsi);
26087 +EXPORT_SYMBOL(__libgcc_divmodsi);
26088 +#endif
26089 --- /dev/null
26090 +++ b/arch/ubicom32/kernel/ubicom32_syscall.S
26091 @@ -0,0 +1,694 @@
26092 +/*
26093 + * arch/ubicom32/kernel/ubicom32_syscall.S
26094 + *     <TODO: Replace with short file description>
26095 + *
26096 + * (C) Copyright 2009, Ubicom, Inc.
26097 + *
26098 + * This file is part of the Ubicom32 Linux Kernel Port.
26099 + *
26100 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26101 + * it and/or modify it under the terms of the GNU General Public License
26102 + * as published by the Free Software Foundation, either version 2 of the
26103 + * License, or (at your option) any later version.
26104 + *
26105 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26106 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26107 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26108 + * the GNU General Public License for more details.
26109 + *
26110 + * You should have received a copy of the GNU General Public License
26111 + * along with the Ubicom32 Linux Kernel Port.  If not,
26112 + * see <http://www.gnu.org/licenses/>.
26113 + *
26114 + * Ubicom32 implementation derived from (with many thanks):
26115 + *   arch/m68knommu
26116 + *   arch/blackfin
26117 + *   arch/parisc
26118 + */
26119 +#include <linux/sys.h>
26120 +#include <linux/linkage.h>
26121 +#include <linux/unistd.h>
26122 +
26123 +#include <asm/ubicom32-common.h>
26124 +#include <asm/thread_info.h>
26125 +#include <asm/asm-offsets.h>
26126 +#include <asm/range-protect.h>
26127 +
26128 +/*
26129 + * __old_system_call()
26130 + */
26131 +       .section .old_syscall_entry.text, "ax", @progbits
26132 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
26133 +__old_system_call:
26134 +       call a3, system_call
26135 +       .size __old_system_call, . - __old_system_call ;
26136 +#else
26137 +       /*
26138 +        * something that will crash the userspace application, but
26139 +        * should not take down the kernel, if protection is enabled
26140 +        * this will never even get executed.
26141 +        */
26142 +       .long   0xFABBCCDE                      ; illegal instruction
26143 +       bkpt #-1                                ; we will never get here
26144 +#endif
26145 +
26146 +/*
26147 + * system_call()
26148 + */
26149 +       .section .syscall_entry.text, "ax", @progbits
26150 +       .global system_call
26151 +system_call:
26152 +       /*
26153 +        * Regular ABI rules for function calls apply for syscall.  d8 holds
26154 +        * the syscall number. We will use that to index into the syscall table.
26155 +        * d0 - d5 hold the parameters.
26156 +        *
26157 +        * First we get the current thread_info and swap to the kernel stack.
26158 +        * This is done by reading the current thread and looking up the ksp
26159 +        * from the sw_ksp array and storing it in a3.
26160 +        *
26161 +        * Then we reserve space for the syscall context a struct pt_regs and
26162 +        * save it using a4 initially and later as sp.
26163 +        * Once sp is set to the kernel sp we can leave the critical section.
26164 +        *
26165 +        * For the user case the kernel stack will have the following layout.
26166 +        *
26167 +        *  a3           ksp[0] +-----------------------+
26168 +        *                      | Thread info area      |
26169 +        *                      | struct thread_info    |
26170 +        *                      +-----------------------+
26171 +        *                      :                       :
26172 +        *                      |   Kernel Stack Area   |
26173 +        *                      |                       |
26174 +        *  a4 / sp >>>         +-----------------------+
26175 +        *                      | Context save area     |
26176 +        *                      | struct pt_reg         |
26177 +        *  ksp[THREAD_SIZE-8]  +-----------------------+
26178 +        *                      | 8 Byte Buffer Zone    |
26179 +        *  ksp[THREAD_SIZE]    +-----------------------+
26180 +
26181 +        *
26182 +        * For kernel syscalls the layout is as follows.
26183 +        *
26184 +        *  a3           ksp[0] +-----------------------+
26185 +        *                      | Thread info area      |
26186 +        *                      | struct thread_info    |
26187 +        *                      +-----------------------+
26188 +        *                      :                       :
26189 +        *                      |   Kernel Stack Area   |
26190 +        *                      |                       |
26191 +        *  a4 / sp >>>         +-----------------------+
26192 +        *                      | Context save area     |
26193 +        *                      | struct pt_reg         |
26194 +        * sp at syscall entry  +-----------------------+
26195 +        *                      | Callers Kernel Stack  |
26196 +        *                      :                       :
26197 +        *
26198 +        * Once the context is saved we optionally call syscall_trace and setup
26199 +        * the exit routine and jump to the syscall.
26200 +        */
26201 +
26202 +       /*
26203 +        * load the base address for sw_ksp into a3
26204 +        * Note.. we cannot access it just yet as protection is still on.
26205 +        */
26206 +       moveai  a3, #%hi(sw_ksp)
26207 +       lea.1   a3, %lo(sw_ksp)(a3)
26208 +
26209 +       /*
26210 +        * Enter critical section .
26211 +        *
26212 +        * The 'critical' aspects here are the switching the to the ksp and
26213 +        * changing the protection registers, these both use per thread
26214 +        * information so we need to protect from a context switch. For now this
26215 +        * is done using the global atomic lock.
26216 +        */
26217 +       atomic_lock_acquire
26218 +
26219 +       thread_get_self d15                     ; Load current thread number
26220 +#ifdef CONFIG_PROTECT_KERNEL
26221 +       lsl.4   d9, #1, d15                     ; Convert to thread bit
26222 +       enable_kernel_ranges d9
26223 +#endif
26224 +       /*
26225 +        * in order to reduce the size of code in the syscall section we get
26226 +        * out of it right now
26227 +        */
26228 +       call a4, __system_call_bottom_half
26229 +       .size system_call, . - system_call
26230 +
26231 +       .section .text.__system_call_bottom_half, "ax", @progbits
26232 +__system_call_bottom_half:
26233 +
26234 +       /*
26235 +        * We need to Determine if this is a kernel syscall or user syscall.
26236 +        * Start by loading the pointer for the thread_info structure for the
26237 +        * current process in to a3.
26238 +        */
26239 +       move.4  a3, (a3, d15)                   ; a3 = sw_ksp[d15]
26240 +
26241 +       /*
26242 +        * Now if this is a kernel thread the same value can be a acheived by
26243 +        * masking off the lower bits on the current stack pointer.
26244 +        */
26245 +       movei   d9, #(~(ASM_THREAD_SIZE-1))     ; load mask
26246 +       and.4   d9, sp, d9                      ; apply mask
26247 +
26248 +       /*
26249 +        * d9 now has the masked version of the sp. If this is identical to
26250 +        * what is in a3 then don't switch to ksp as we are already in the
26251 +        * kernel.
26252 +        */
26253 +       sub.4   #0, a3, d9
26254 +
26255 +       /*
26256 +        * if d9 and a3 are not equal. We are usespace and have to shift to
26257 +        * ksp.
26258 +        */
26259 +       jmpne.t 1f
26260 +
26261 +       /*
26262 +        * Kernel Syscall.
26263 +        *
26264 +        * The kernel has called this routine. We have to pdec space for pt_regs
26265 +        * from sp.
26266 +        */
26267 +       pdec    a4, PT_SIZE(sp)                 ; a4 = ksp - PT_SIZE
26268 +       jmpt.t  2f
26269 +
26270 +       /*
26271 +        * Userspace Syscall.
26272 +        *
26273 +        * Add THREAD_SIZE and subtract PT_SIZE to create the proper ksp
26274 +        */
26275 +1:     movei   d15, #(ASM_THREAD_SIZE - 8 - PT_SIZE)
26276 +       lea.1   a4, (a3, d15)                   ; a4 = ksp + d15
26277 +
26278 +       /*
26279 +        * Replace user stack pointer with kernel stack pointer (a4)
26280 +        * Load -1 into frame_type in save area to indicate this is system call
26281 +        * frame.
26282 +        */
26283 +2:     move.4  PT_A7(a4), a7                   ; Save old sp/A7 on kernel stack
26284 +       move.4  PT_FRAME_TYPE(a4), #-1          ; Set the frame type.
26285 +       move.4  sp, a4                          ; Change to ksp.
26286 +       /*
26287 +        * We are now officially back in the kernel!
26288 +        */
26289 +
26290 +       /*
26291 +        * Now that we are on the ksp we can leave the critical section
26292 +        */
26293 +       atomic_lock_release
26294 +
26295 +       /*
26296 +        * We need to save a0 because we need to be able to restore it in
26297 +        * the event that we need to handle a signal.  It's not generally
26298 +        * a callee-saved register but is the GOT pointer.
26299 +        */
26300 +       move.4  PT_A0(sp), a0                   ; Save A0 on kernel stack
26301 +
26302 +       /*
26303 +        * We still need to save d10-d13, a1, a2, a5, a6 in the kernel frame
26304 +        * for this process, we also save the system call params in the case of
26305 +        * syscall restart. (note a7 was saved above)
26306 +        */
26307 +       move.4  PT_A1(sp), a1                   ; Save A1 on kernel stack
26308 +       move.4  PT_A2(sp), a2                   ; Save A2 on kernel stack
26309 +       move.4  PT_A5(sp), a5                   ; Save A5 on kernel stack
26310 +       move.4  PT_A6(sp), a6                   ; Save A6 on kernel stack
26311 +       move.4  PT_PC(sp), a5                   ; Save A5 at the PC location
26312 +       move.4  PT_D10(sp), d10                 ; Save D10 on kernel stack
26313 +       move.4  PT_D11(sp), d11                 ; Save D11 on kernel stack
26314 +       move.4  PT_D12(sp), d12                 ; Save D12 on kernel stack
26315 +       move.4  PT_D13(sp), d13                 ; Save D13 on kernel stack
26316 +
26317 +       /*
26318 +        * Now save the syscall parameters
26319 +        */
26320 +       move.4  PT_D0(sp), d0                   ; Save d0 on kernel stack
26321 +       move.4  PT_ORIGINAL_D0(sp), d0          ; Save d0 on kernel stack
26322 +       move.4  PT_D1(sp), d1                   ; Save d1 on kernel stack
26323 +       move.4  PT_D2(sp), d2                   ; Save d2 on kernel stack
26324 +       move.4  PT_D3(sp), d3                   ; Save d3 on kernel stack
26325 +       move.4  PT_D4(sp), d4                   ; Save d4 on kernel stack
26326 +       move.4  PT_D5(sp), d5                   ; Save d5 on kernel stack
26327 +       move.4  PT_D8(sp), d8                   ; Save d8 on kernel stack
26328 +
26329 +       /*
26330 +        * Test if syscalls are being traced and if they are jump to syscall
26331 +        * trace (it will comeback here)
26332 +        */
26333 +       btst    TI_FLAGS(a3), #ASM_TIF_SYSCALL_TRACE
26334 +       jmpne.f .Lsystem_call__trace
26335 +.Lsystem_call__trace_complete:
26336 +       /*
26337 +        * Check for a valid call number [ 0 <= syscall_number < NR_syscalls ]
26338 +        */
26339 +       cmpi    d8, #0
26340 +       jmplt.f 3f
26341 +       cmpi    d8, #NR_syscalls
26342 +       jmplt.t 4f
26343 +
26344 +       /*
26345 +        * They have passed an invalid number. Call sys_ni_syscall staring by
26346 +        * load a4 with the base address of sys_ni_syscall
26347 +        */
26348 +3:     moveai  a4, #%hi(sys_ni_syscall)
26349 +       lea.1   a4, %lo(sys_ni_syscall)(a4)
26350 +       jmpt.t  5f                              ; Jump to regular processing
26351 +
26352 +       /*
26353 +        * Validated syscall, load the syscall table base address into a3 and
26354 +        * read the syscall ptr out.
26355 +        */
26356 +4:     moveai  a3, #%hi(sys_call_table)
26357 +       lea.1   a3, %lo(sys_call_table)(a3)     ; a3 = sys_call_table
26358 +       move.4  a4, (a3, d8)                    ; a4 = sys_call_table[d8]
26359 +
26360 +       /*
26361 +        * Before calling the syscall, setup a5 so that syscall_exit is called
26362 +        * on return from syscall
26363 +        */
26364 +5:     moveai  a5, #%hi(syscall_exit)          ; Setup return address
26365 +       lea.1   a5, %lo(syscall_exit)(a5)       ; from system call
26366 +
26367 +       /*
26368 +        * If the syscall is __NR_rt_rigreturn then we have to test d1 to
26369 +        * figure out if we have to change change the return routine to restore
26370 +        * all registers.
26371 +        */
26372 +       cmpi    d8, #__NR_rt_sigreturn
26373 +       jmpeq.f 6f
26374 +
26375 +       /*
26376 +        * Launch system call (it will return through a5 - syscall_exit)
26377 +        */
26378 +       calli   a3, 0(a4)
26379 +
26380 +       /*
26381 +        * System call is rt_sigreturn. Test d1. If it is 1 we have to
26382 +        * change the return address to restore_all_registers
26383 +        */
26384 +6:     cmpi    d1, #1
26385 +       jmpne.t 7f
26386 +
26387 +       moveai  a5, #%hi(restore_all_registers)  ; Setup return address
26388 +       lea.1   a5, %lo(restore_all_registers)(a5) ; to restore_all_registers.
26389 +
26390 +       /*
26391 +        * Launch system call  (it will return through a5)
26392 +        */
26393 +7:     calli   a3, 0(a4)                        ; Launch system call
26394 +
26395 +.Lsystem_call__trace:
26396 +       /*
26397 +        * Syscalls are being traced.
26398 +        * Call syscall_trace, (return here)
26399 +        */
26400 +       call    a5, syscall_trace
26401 +
26402 +       /*
26403 +        * Restore syscall state (it would have been discarded during the
26404 +        * syscall trace)
26405 +        */
26406 +       move.4  d0, PT_D0(sp)                   ; Restore d0 from kernel stack
26407 +       move.4  d1, PT_D1(sp)                   ; Restore d1 from kernel stack
26408 +       move.4  d2, PT_D2(sp)                   ; Restore d2 from kernel stack
26409 +       move.4  d3, PT_D3(sp)                   ; Restore d3 from kernel stack
26410 +       move.4  d4, PT_D4(sp)                   ; Restore d4 from kernel stack
26411 +       move.4  d5, PT_D5(sp)                   ; Restore d5 from kernel stack
26412 +       /* add this back if we ever have a syscall with 7 args */
26413 +       move.4  d8, PT_D8(sp)                   ; Restore d8 from kernel stack
26414 +
26415 +       /*
26416 +        * return to syscall
26417 +        */
26418 +       jmpt.t .Lsystem_call__trace_complete
26419 +       .size __system_call_bottom_half, . - __system_call_bottom_half
26420 +
26421 +/*
26422 + * syscall_exit()
26423 + */
26424 +       .section .text.syscall_exit
26425 +       .global syscall_exit
26426 +syscall_exit:
26427 +       /*
26428 +        * d0 contains the return value. We should move that into the kernel
26429 +        * stack d0 location.  We will be transitioning from kernel to user
26430 +        * mode. Test the flags and see if we have to call schedule. If we are
26431 +        * going to truly exit then all that has to be done is that from the
26432 +        * kernel stack we have to restore d0, a0, a1, a2, a5, a6 and sp (a7)bb
26433 +        * and then return via a5.
26434 +        */
26435 +
26436 +       /*
26437 +        * Save d0 to pt_regs
26438 +        */
26439 +       move.4  PT_D0(sp), d0                   ; Save d0 into the kernel stack
26440 +
26441 +       /*
26442 +        * load the thread_info structure by masking off the THREAD_SIZE
26443 +        * bits.
26444 +        *
26445 +        * Note: we used to push a1, but now we don't as we are going
26446 +        * to eventually restore it to the userspace a1.
26447 +        */
26448 +       movei   d9, #(~(ASM_THREAD_SIZE-1))
26449 +       and.4   a1, sp, d9
26450 +
26451 +       /*
26452 +        * Are any interesting bits set on TI flags, if there are jump
26453 +        * aside to post_processing.
26454 +        */
26455 +       move.4  d9, #(_TIF_SYSCALL_TRACE | _TIF_NEED_RESCHED | _TIF_SIGPENDING)
26456 +       and.4   #0, TI_FLAGS(a1), d9
26457 +       jmpne.f .Lsyscall_exit__post_processing ; jump to handler
26458 +.Lsyscall_exit__post_processing_complete:
26459 +
26460 +       move.4  d0, PT_D0(sp)                   ; Restore D0 from kernel stack
26461 +       move.4  d1, PT_D1(sp)                   ; Restore d1 from kernel stack
26462 +       move.4  d2, PT_D2(sp)                   ; Restore d2 from kernel stack
26463 +       move.4  d3, PT_D3(sp)                   ; Restore d3 from kernel stack
26464 +       move.4  d4, PT_D4(sp)                   ; Restore d4 from kernel stack
26465 +       move.4  d5, PT_D5(sp)                   ; Restore d5 from kernel stack
26466 +       move.4  d8, PT_D8(sp)                   ; Restore d8 from kernel stack
26467 +       move.4  d10, PT_D10(sp)                 ; Restore d10 from kernel stack
26468 +       move.4  d11, PT_D11(sp)                 ; Restore d11 from kernel stack
26469 +       move.4  d12, PT_D12(sp)                 ; Restore d12 from kernel stack
26470 +       move.4  d13, PT_D13(sp)                 ; Restore d13 from kernel stack
26471 +       move.4  a1, PT_A1(sp)                   ; Restore A1 from kernel stack
26472 +       move.4  a2, PT_A2(sp)                   ; Restore A2 from kernel stack
26473 +       move.4  a5, PT_A5(sp)                   ; Restore A5 from kernel stack
26474 +       move.4  a6, PT_A6(sp)                   ; Restore A6 from kernel stack
26475 +       move.4  a0, PT_A0(sp)                   ; Restore A6 from kernel stack
26476 +
26477 +       /*
26478 +        * this is only for debug, and could be removed for production builds
26479 +        */
26480 +       move.4  PT_FRAME_TYPE(sp), #0           ; invalidate frame_type
26481 +
26482 +#ifdef CONFIG_PROTECT_KERNEL
26483 +
26484 +       call a4, __syscall_exit_bottom_half
26485 +
26486 +       .section .kernel_unprotected, "ax", @progbits
26487 +__syscall_exit_bottom_half:
26488 +       /*
26489 +        * Enter critical section
26490 +        */
26491 +       atomic_lock_acquire
26492 +       disable_kernel_ranges_for_current d15
26493 +#endif
26494 +       /*
26495 +        * Lastly restore userspace stack ptr
26496 +        *
26497 +        * Note: that when protection is on we need to hold the lock around the
26498 +        * stack swap as well because otherwise the protection could get
26499 +        * inadvertently disabled again at the end of a context switch.
26500 +        */
26501 +       move.4  a7, PT_A7(sp)                   ; Restore A7 from kernel stack
26502 +
26503 +       /*
26504 +        * We are now officially back in userspace!
26505 +        */
26506 +
26507 +#ifdef CONFIG_PROTECT_KERNEL
26508 +       /*
26509 +        * Leave critical section and return to user space.
26510 +        */
26511 +       atomic_lock_release
26512 +#endif
26513 +       calli   a5, 0(a5)                       ; Back to userspace code.
26514 +
26515 +       bkpt #-1                                ; we will never get here
26516 +
26517 +       /*
26518 +        * Post syscall processing. (unlikely part of syscall_exit)
26519 +        *
26520 +        * Are we tracing syscalls. If TIF_SYSCALL_TRACE is set, call
26521 +        * syscall_trace routine and return here.
26522 +        */
26523 +       .section .text.syscall_exit, "ax", @progbits
26524 +.Lsyscall_exit__post_processing:
26525 +       btst    TI_FLAGS(a1), #ASM_TIF_SYSCALL_TRACE
26526 +       jmpeq.t 1f
26527 +       call    a5, syscall_trace
26528 +
26529 +       /*
26530 +        * Do we need to resched ie call schedule. If TIF_NEED_RESCHED is set,
26531 +        * call the scheduler, it will come back here.
26532 +        */
26533 +1:     btst    TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
26534 +       jmpeq.t 2f
26535 +       call    a5, schedule
26536 +
26537 +       /*
26538 +        * Do we need to post a signal, if TIF_SIGPENDING is set call the
26539 +        * do_signal.
26540 +        */
26541 +2:     btst    TI_FLAGS(a1), #ASM_TIF_SIGPENDING
26542 +       jmpeq.t .Lsyscall_exit__post_processing_complete
26543 +
26544 +       /*
26545 +        * setup the do signal call
26546 +        */
26547 +       move.4  d0, #0                          ; oldset pointer is NULL
26548 +       lea.1   d1, (sp)                        ; d1 is the regs pointer.
26549 +       call    a5, do_signal
26550 +
26551 +       jmpt.t  .Lsyscall_exit__post_processing_complete
26552 +
26553 +/*     .size syscall_exit, . - syscall_exit */
26554 +
26555 +/*
26556 + * kernel_execve()
26557 + *     kernel_execv is called when we the kernel is starting a
26558 + *     userspace application.
26559 + */
26560 +       .section .kernel_unprotected, "ax", @progbits
26561 +       .global kernel_execve
26562 +kernel_execve:
26563 +       move.4  -4(sp)++, a5                    ; Save return address
26564 +       /*
26565 +        * Call execve
26566 +        */
26567 +       movei   d8, #__NR_execve                ; call execve
26568 +       call    a5, system_call
26569 +       move.4  a5, (sp)4++
26570 +
26571 +       /*
26572 +        * protection was enabled again at syscall exit, but we want
26573 +        * to return to kernel so we enable it again.
26574 +        */
26575 +#ifdef CONFIG_PROTECT_KERNEL
26576 +       /*
26577 +        * We are entering the kernel so we need to disable the protection.
26578 +        * Enter critical section, disable ranges and leave critical section.
26579 +        */
26580 +       call a3, __enable_kernel_ranges ;  and jump back to kernel
26581 +#else
26582 +       ret a5                                  ; jump back to the kernel
26583 +#endif
26584 +
26585 +       .size kernel_execve, . - kernel_execve
26586 +
26587 +/*
26588 + * signal_trampoline()
26589 + *
26590 + *     Deals with transitioning from to userspace signal handlers and returning
26591 + *     to userspace, only called from the kernel.
26592 + *
26593 + */
26594 +       .section .kernel_unprotected, "ax", @progbits
26595 +       .global signal_trampoline
26596 +signal_trampoline:
26597 +       /*
26598 +        * signal_trampoline is called when we are jumping from the kernel to
26599 +        * the userspace signal handler.
26600 +        *
26601 +        * The following registers are relevant. (set setup_rt_frame)
26602 +        *   sp is the user space stack not the kernel stack
26603 +        *  d0 = signal number
26604 +        *  d1 = siginfo_t *
26605 +        *  d2 = ucontext *
26606 +        *  d3 = the user space signal handler
26607 +        *  a0 is set to the GOT if userspace application is FDPIC, otherwise 0
26608 +        *  a3 is set to the FD for the signal if userspace application is FDPIC
26609 +        */
26610 +#ifdef CONFIG_PROTECT_KERNEL
26611 +       /*
26612 +        * We are leaving the kernel so we need to enable the protection.
26613 +        * Enter critical section, disable ranges and leave critical section.
26614 +        */
26615 +       atomic_lock_acquire                     ; Enter critical section
26616 +       disable_kernel_ranges_for_current d15   ; disable kernel ranges
26617 +       atomic_lock_release                     ; Leave critical section
26618 +#endif
26619 +       /*
26620 +        * The signal handler pointer is in register d3 so tranfer it to a4 and
26621 +        * call it
26622 +        */
26623 +       movea   a4, d3                          ; signal handler
26624 +       calli   a5, 0(a4)
26625 +
26626 +       /*
26627 +        * Return to userspace through rt_syscall which is stored on top of the
26628 +        * stack d1 contains ret_via_interrupt status.
26629 +        */
26630 +       move.4  d8, (sp)                        ; d8 (syscall #) = rt_syscall
26631 +       move.4  d1, 4(sp)                       ; d1 = ret_via_interrupt
26632 +       call    a5, system_call         ; as we are 'in' the kernel
26633 +                                               ; we can call kernel_syscall
26634 +
26635 +       bkpt #-1                                ; will never get here.
26636 +       .size signal_trampoline, . - signal_trampoline
26637 +
26638 +/*
26639 + * kernel_thread_helper()
26640 + *
26641 + *     Entry point for kernel threads (only referenced by kernel_thread()).
26642 + *
26643 + *     On execution d0 will be 0, d1 will be the argument to be passed to the
26644 + *     kernel function.
26645 + *     d2 contains the kernel function that needs to get called.
26646 + *     d3 will contain address to do_exit which needs to get moved into a5.
26647 + *
26648 + *     On return from fork the child thread d0 will be 0. We call this dummy
26649 + *     function which in turn loads the argument
26650 + */
26651 +       .section .kernel_unprotected, "ax", @progbits
26652 +       .global kernel_thread_helper
26653 +kernel_thread_helper:
26654 +       /*
26655 +        * Create a kernel thread. This is called from ret_from_vfork (a
26656 +        * userspace return routine) so we need to put it in an unprotected
26657 +        * section and re-enable protection before calling the vector in d2.
26658 +        */
26659 +
26660 +#ifdef CONFIG_PROTECT_KERNEL
26661 +       /*
26662 +        * We are entering the kernel so we need to disable the protection.
26663 +        * Enter critical section, disable ranges and leave critical section.
26664 +        */
26665 +       call a5, __enable_kernel_ranges
26666 +#endif
26667 +       /*
26668 +        * Move argument for kernel function into d0, and set a5 return address
26669 +        * (a5) to do_exit and return through a2
26670 +        */
26671 +       move.4  d0, d1                          ; d0 = arg
26672 +       move.4  a5, d3                          ; a5 = do_exit
26673 +       ret     d2                              ; call function ptr in d2
26674 +       .size kernel_thread_helper, . - kernel_thread_helper
26675 +
26676 +#ifdef CONFIG_PROTECT_KERNEL
26677 +       .section .kernel_unprotected, "ax", @progbits
26678 +__enable_kernel_ranges:
26679 +       atomic_lock_acquire                     ; Enter critical section
26680 +       enable_kernel_ranges_for_current d15
26681 +       atomic_lock_release                     ; Leave critical section
26682 +       calli a5, 0(a5)
26683 +       .size __enable_kernel_ranges, . - __enable_kernel_ranges
26684 +
26685 +#endif
26686 +
26687 +/*
26688 + * The following system call intercept functions where we setup the
26689 + * input to the real system call.  In all cases these are just taking
26690 + * the current sp which is pointing to pt_regs and pushing it into the
26691 + * last arg of the system call.
26692 + *
26693 + * i.e. the public definition of sys_execv is
26694 + *     sys_execve(     char *name,
26695 + *                     char **argv,
26696 + *                     char **envp )
26697 + * but process.c defines it as
26698 + *     sys_execve(     char *name,
26699 + *                     char **argv,
26700 + *                     char **envp,
26701 + *                     struct pt_regs *regs )
26702 + *
26703 + * so execve_intercept needs to populate the 4th arg with pt_regs*,
26704 + * which is the stack pointer as we know we must be coming out of
26705 + * system_call
26706 + *
26707 + * The intercept vectors are referenced by syscalltable.S
26708 + */
26709 +
26710 +/*
26711 + * execve_intercept()
26712 + */
26713 +       .section .text.execve_intercept, "ax", @progbits
26714 +       .global execve_intercept
26715 +execve_intercept:
26716 +       move.4  d3, sp  ; Save pt_regs address
26717 +       call    a3, sys_execve
26718 +
26719 +       .size execve_intercept, . - execve_intercept
26720 +
26721 +/*
26722 + * vfork_intercept()
26723 + */
26724 +       .section .text.vfork_intercept, "ax", @progbits
26725 +       .global vfork_intercept
26726 +vfork_intercept:
26727 +       move.4  d0, sp  ; Save pt_regs address
26728 +       call    a3, sys_vfork
26729 +
26730 +       .size vfork_intercept, . - vfork_intercept
26731 +
26732 +/*
26733 + * clone_intercept()
26734 + */
26735 +       .section .text.clone_intercept, "ax", @progbits
26736 +       .global clone_intercept
26737 +clone_intercept:
26738 +       move.4  d2, sp  ; Save pt_regs address
26739 +       call    a3, sys_clone
26740 +
26741 +       .size clone_intercept, . - clone_intercept
26742 +
26743 +/*
26744 + * sys_sigsuspend()
26745 + */
26746 +       .section .text.sigclone_intercept, "ax", @progbits
26747 +       .global sys_sigsuspend
26748 +sys_sigsuspend:
26749 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26750 +       call    a3, do_sigsuspend
26751 +
26752 +       .size sys_sigsuspend, . - sys_sigsuspend
26753 +
26754 +/*
26755 + * sys_rt_sigsuspend()
26756 + */
26757 +       .section .text.sys_rt_sigsuspend, "ax", @progbits
26758 +       .global sys_rt_sigsuspend
26759 +sys_rt_sigsuspend:
26760 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26761 +       call    a3, do_rt_sigsuspend
26762 +
26763 +       .size sys_rt_sigsuspend, . - sys_rt_sigsuspend
26764 +
26765 +/*
26766 + * sys_rt_sigreturn()
26767 + */
26768 +       .section .text.sys_rt_sigreturn, "ax", @progbits
26769 +       .global sys_rt_sigreturn
26770 +sys_rt_sigreturn:
26771 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26772 +       call    a3, do_rt_sigreturn
26773 +
26774 +       .size sys_rt_sigreturn, . - sys_rt_sigreturn
26775 +
26776 +/*
26777 + * sys_sigaltstack()
26778 + */
26779 +       .section .text.sys_sigaltstack, "ax", @progbits
26780 +       .global sys_sigaltstack
26781 +sys_sigaltstack:
26782 +       move.4  d0, sp  ; Pass pointer to pt_regs in d0
26783 +       call    a3, do_sys_sigaltstack
26784 +
26785 +       .size sys_sigaltstack, . - sys_sigaltstack
26786 --- /dev/null
26787 +++ b/arch/ubicom32/kernel/unaligned_trap.c
26788 @@ -0,0 +1,698 @@
26789 +/*
26790 + * arch/ubicom32/kernel/unaligned_trap.c
26791 + *   Handle unaligned traps in both user or kernel space.
26792 + *
26793 + * (C) Copyright 2009, Ubicom, Inc.
26794 + *
26795 + * This file is part of the Ubicom32 Linux Kernel Port.
26796 + *
26797 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26798 + * it and/or modify it under the terms of the GNU General Public License
26799 + * as published by the Free Software Foundation, either version 2 of the
26800 + * License, or (at your option) any later version.
26801 + *
26802 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26803 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26804 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
26805 + * the GNU General Public License for more details.
26806 + *
26807 + * You should have received a copy of the GNU General Public License
26808 + * along with the Ubicom32 Linux Kernel Port.  If not,
26809 + * see <http://www.gnu.org/licenses/>.
26810 + *
26811 + * Ubicom32 implementation derived from (with many thanks):
26812 + *   arch/m68knommu
26813 + *   arch/blackfin
26814 + *   arch/parisc
26815 + */
26816 +
26817 +#include <linux/types.h>
26818 +#include <linux/kernel.h>
26819 +#include <asm/cacheflush.h>
26820 +#include <asm/traps.h>
26821 +
26822 +#define FALSE 0
26823 +#define TRUE 1
26824 +
26825 +/* no possible trap */
26826 +#define UNUSED 0
26827 +/* possible source operand trap */
26828 +#define SRC 1
26829 +#define SRC_2 2
26830 +/* possible destination operand trap */
26831 +#define DEST 3
26832 +#define DEST_2 4
26833 +/* can be either source or destination or both */
26834 +#define TWO_OP 5
26835 +#define TWO_OP_2 6
26836 +
26837 +/* TODO: What is the real value here, put something in to make it compile for
26838 + * now */
26839 +#define MOVE_2 0x0d
26840 +#define LSL_2  0x11
26841 +#define LSR_2  0x13
26842 +#define MOVEI  0x19
26843 +#define CMPI   0x18
26844 +
26845 +static int op_format[32] =
26846 +{
26847 +       TWO_OP,         /* 0x00 */
26848 +       UNUSED,
26849 +       SRC,
26850 +       UNUSED,
26851 +       TWO_OP,         /* 0x04 */
26852 +       TWO_OP,
26853 +       SRC,
26854 +       UNUSED,
26855 +       TWO_OP_2,       /* 0x08 */
26856 +       TWO_OP,
26857 +       TWO_OP_2,
26858 +       TWO_OP,
26859 +       TWO_OP_2,       /* 0x0C */
26860 +       TWO_OP,
26861 +       TWO_OP_2,
26862 +       TWO_OP,
26863 +       TWO_OP,         /* 0x10 */
26864 +       TWO_OP_2,
26865 +       TWO_OP,
26866 +       TWO_OP,
26867 +       UNUSED,         /* 0x14 */
26868 +       UNUSED,
26869 +       UNUSED,
26870 +       UNUSED,
26871 +       SRC_2,          /* 0x18 */
26872 +       DEST_2,
26873 +       UNUSED,
26874 +       UNUSED,
26875 +       UNUSED,         /* 0x1C */
26876 +       UNUSED,
26877 +       UNUSED,         /* unaligned CALLI will not be fixed. */
26878 +       UNUSED
26879 +};
26880 +
26881 +static int op_0_format[32] =
26882 +{
26883 +       UNUSED,         /* 0x00 */
26884 +       UNUSED,
26885 +       UNUSED,
26886 +       UNUSED,
26887 +       UNUSED,         /* 0x04 - ret don't fix - bad ret is always wrong */
26888 +       UNUSED,
26889 +       UNUSED,
26890 +       UNUSED,
26891 +       UNUSED,         /* 0x08 */
26892 +       UNUSED,
26893 +       TWO_OP,
26894 +       TWO_OP_2,
26895 +       TWO_OP,         /* 0x0c */
26896 +       TWO_OP_2,
26897 +       TWO_OP,
26898 +       UNUSED,         /* .1 can't trap */
26899 +       UNUSED,         /* 0x10 */
26900 +       UNUSED,
26901 +       SRC,
26902 +       UNUSED,
26903 +       UNUSED,         /* 0x14 */
26904 +       TWO_OP_2,
26905 +       UNUSED,
26906 +       UNUSED,
26907 +       UNUSED,         /* 0x18 */
26908 +       UNUSED,
26909 +       UNUSED,
26910 +       UNUSED,
26911 +       DEST,           /* 0x1c */
26912 +       DEST,
26913 +       DEST,
26914 +       DEST,           /* all lea have 32-bit destination */
26915 +};
26916 +
26917 +static int op_2_format[32] =
26918 +{
26919 +       UNUSED,         /* 0x00 */
26920 +       UNUSED,
26921 +       UNUSED,
26922 +       UNUSED,
26923 +       UNUSED,         /* 0x04 */
26924 +       UNUSED,
26925 +       SRC,
26926 +       UNUSED,
26927 +       UNUSED,         /* 0x08 crcgen is .1 */
26928 +       UNUSED,
26929 +       UNUSED,
26930 +       UNUSED,
26931 +       UNUSED,         /* 0x0c */
26932 +       UNUSED,
26933 +       UNUSED,
26934 +       UNUSED,
26935 +       SRC,            /* 0x10 */
26936 +       SRC_2,
26937 +       SRC,
26938 +       SRC_2,
26939 +       SRC,            /* 0x14 */
26940 +       SRC_2,
26941 +       SRC,
26942 +       UNUSED,
26943 +       UNUSED,         /* 0x18 */
26944 +       UNUSED,
26945 +       SRC,
26946 +       UNUSED,
26947 +       SRC,            /* 0x1c */
26948 +       UNUSED,
26949 +       SRC_2,
26950 +       UNUSED,
26951 +};
26952 +
26953 +static int op_6_format[32] =
26954 +{
26955 +       SRC_2,          /* 0x00 */
26956 +       SRC_2,
26957 +       SRC_2,
26958 +       SRC_2,
26959 +       SRC_2,          /* 0x04 */
26960 +       SRC_2,
26961 +       UNUSED,
26962 +       SRC_2,
26963 +       SRC,            /* 0x08 MULS.4 */
26964 +       SRC_2,
26965 +       SRC,
26966 +       UNUSED,
26967 +       UNUSED,         /* 0x0c */
26968 +       UNUSED,
26969 +       UNUSED,
26970 +       UNUSED,
26971 +       SRC,            /* 0x10 */
26972 +       SRC_2,
26973 +       SRC,
26974 +       SRC_2,
26975 +       UNUSED,         /* 0x14 */
26976 +       UNUSED,
26977 +       UNUSED,
26978 +       UNUSED,
26979 +       UNUSED,         /* 0x18 */
26980 +       UNUSED,
26981 +       UNUSED,
26982 +       UNUSED,
26983 +       UNUSED,         /* 0x1c */
26984 +       UNUSED,
26985 +       UNUSED,
26986 +       UNUSED,
26987 +};
26988 +
26989 +/*
26990 + * unaligned_get_address()
26991 + *     get an address using save_an and save_dn registers, and updates save_an
26992 + *     with side effects
26993 + */
26994 +unsigned char *unaligned_get_address(int thread, int specifier, int four_byte,
26995 +                                    unsigned int save_an[],
26996 +                                    unsigned int save_dn[], int *write_back_an)
26997 +{
26998 +       unsigned char *address;
26999 +
27000 +       int areg = (specifier >> 5) & 7;
27001 +       if ((specifier >> 8) == 2) {
27002 +               int offset = specifier & 0xf;
27003 +               offset = ((offset << 28) >> 28);
27004 +               if (likely(four_byte)) {
27005 +                       offset <<= 2;
27006 +               } else {
27007 +                       offset <<= 1;
27008 +               }
27009 +               if (specifier & 0x10) {
27010 +                       address = (unsigned char *)(save_an[areg] + offset);
27011 +               } else {
27012 +                       address = (unsigned char *)save_an[areg];
27013 +               }
27014 +               save_an[areg] = save_an[areg] + offset;
27015 +
27016 +               /*
27017 +                * Let caller know An registers have been modified.
27018 +                */
27019 +               *write_back_an = 1;
27020 +       } else if ((specifier >> 8) == 3) {
27021 +               int dreg = specifier & 0xf;
27022 +               if (likely(four_byte)) {
27023 +                       address = (unsigned char *)(save_an[areg] +
27024 +                                                   (save_dn[dreg] << 2));
27025 +               } else {
27026 +                       address = (unsigned char *)(save_an[areg] +
27027 +                                                   (save_dn[dreg] << 1));
27028 +               }
27029 +       } else {
27030 +               int offset = ((specifier >> 3) & 0x60) | (specifier & 0x1f);
27031 +               if (likely(four_byte)) {
27032 +                       address = (unsigned char *)(save_an[areg] +
27033 +                                                   (offset << 2));
27034 +               } else {
27035 +                       address = (unsigned char *)(save_an[areg] +
27036 +                                                   (offset << 1));
27037 +               }
27038 +       }
27039 +
27040 +       return address;
27041 +}
27042 +
27043 +static int save_dn[16];
27044 +static int save_an[8];
27045 +static int save_acc[5];
27046 +
27047 +/*
27048 + * unaligned_emulate()
27049 + *     emulate the instruction at thread's pc that has taken an unaligned data
27050 + *     trap.
27051 + *
27052 + * source or destination or both might be unaligned
27053 + * the instruction must have a memory source or destination or both
27054 + * the emulated instruction is copied and executed in this thread
27055 + *
27056 + *     TODO: Protection is handled outside of this function
27057 + *     TODO: handling simultaneous unaligned and memory protection traps
27058 + *
27059 + *     Get thread state
27060 + *             the PC and instruction (and local copy, emulate_inst), and An
27061 + *             and Dn registers
27062 + *             All implicit soruce state (source3, CSR, accumulators)
27063 +
27064 + *     if the instruction has a memory source
27065 + *             Use the instruction, An and Dn registers to form src_address
27066 + *             get unaligned source data from src_address (usually sign
27067 + *             extended)
27068 + *                     (2 bytes, with or without sign extension, or 4 bytes)
27069 + *             modify emulate_inst to use d0 as source
27070 + *     else
27071 + *             get the soure operand from one of thread's registers
27072 + *     if instruction has a memory destination
27073 + *             Use the instruction, An and Dn registers to form dest_address
27074 + *             modify emulate_inst to use d0 as destination
27075 + *     if there was a memory source
27076 + *             put the source data in thread's d0
27077 + *     get the source-2 Dn operand and source 3 operand from thread
27078 + *     execute modified inst
27079 + *             (save it, flush caches, set up local values for implicit
27080 + *             sources, execute, save explicit and implicit results)
27081 + *     if inst has destination address
27082 + *             copy result to dest_address, possibly unaligned, 1, 2, or 4
27083 + *             bytes
27084 + *     restore thread's implicit results (modified address registers, CSR,
27085 + *     accumulators) add 4 to thread's pc
27086 + */
27087 +void unaligned_emulate(unsigned int thread)
27088 +{
27089 +       unsigned int pc;
27090 +       unsigned int inst;
27091 +       unsigned int op;
27092 +       unsigned int subop;
27093 +       int format;
27094 +       unsigned int emulate_inst;
27095 +       int four_byte;
27096 +       int src_operand, dest_operand;
27097 +       int save_csr;
27098 +       int source3;
27099 +       unsigned int source1;
27100 +       unsigned int source_data;
27101 +       unsigned char *dest_address = NULL;
27102 +       int source2 = 0;
27103 +       unsigned int result;
27104 +       unsigned int write_back_an = 0;
27105 +       unsigned int chip_id_copy;
27106 +
27107 +       extern unsigned int trap_emulate;
27108 +       extern unsigned int ubicom32_emulate_insn(int source1, int source2,
27109 +                                                 int source3, int *save_acc,
27110 +                                                 int *save_csr);
27111 +
27112 +       /*
27113 +        * get the chip_id
27114 +        */
27115 +       asm volatile (
27116 +       "       move.4          %0, chip_id             \n\t" /* get chip_id. */
27117 +               : "=r"(chip_id_copy)
27118 +               :
27119 +       );
27120 +
27121 +       /*
27122 +        * get the pc
27123 +        */
27124 +       asm volatile (
27125 +       "       move.4          CSR, %1         \n\t" /* set source thread in
27126 +                                                      * CSR */
27127 +       "       setcsr_flush    0               \n\t"
27128 +       "       move.4          %0, pc          \n\t"
27129 +       "       move.4          CSR, #0         \n\t" /* restore CSR */
27130 +       "       setcsr_flush    0               \n\t"
27131 +               : "=a"(pc)
27132 +               : "d" ((1 << 8) | (thread << 9))
27133 +               : "cc"
27134 +       );
27135 +
27136 +       inst = *((unsigned int *)pc);
27137 +       op = inst >> 27;
27138 +       if (unlikely(op == 2 || op == 6)) {
27139 +               subop = (inst >> 21) & 0x1f;
27140 +       } else {
27141 +               subop = (inst >> 11) & 0x1f;
27142 +       }
27143 +       format = op_format[op];
27144 +       emulate_inst = inst;
27145 +
27146 +       if (op == 0) {
27147 +               format = op_0_format[subop];
27148 +       } else if (op == 2) {
27149 +               format = op_2_format[subop];
27150 +       } else if (op == 6) {
27151 +               format = op_6_format[subop];
27152 +       }
27153 +
27154 +       if (unlikely(format == UNUSED)) {
27155 +               /*
27156 +                * We are not going to emulate this. Bump PC by 4 and move on.
27157 +                */
27158 +               asm volatile (
27159 +               "       move.4          CSR, %0                 \n\t"
27160 +               "       setcsr_flush    0                       \n\t"
27161 +               "       move.4          pc, %1                  \n\t"
27162 +               "       setcsr          #0                      \n\t"
27163 +               "       setcsr_flush    0                       \n\t"
27164 +                       :
27165 +                       : "d"((1 << 14) | (thread << 15)), "d"(pc + 4)
27166 +                       : "cc"
27167 +               );
27168 +               return;
27169 +       }
27170 +
27171 +       four_byte = (format == TWO_OP || format == DEST || format == SRC);
27172 +
27173 +       /*
27174 +        * source or destination memory operand needs emulation
27175 +        */
27176 +       src_operand = (format == SRC ||
27177 +                      format == SRC_2 ||
27178 +                      format == TWO_OP ||
27179 +                      format == TWO_OP_2) &&
27180 +               ((inst >> 8) & 7) > 1;
27181 +
27182 +       dest_operand = (format == DEST ||
27183 +                       format == DEST_2 ||
27184 +                       format == TWO_OP ||
27185 +                       format == TWO_OP_2) &&
27186 +               ((inst >> 24) & 7) > 1;
27187 +
27188 +       /*
27189 +        * get thread's implicit sources (not covered by source context select).
27190 +        * data and address registers and CSR (for flag bits) and src3 and
27191 +        * accumulators
27192 +        */
27193 +       asm volatile (
27194 +       "       move.4          CSR, %2         \n\t"   /* set source thread in
27195 +                                                        * CSR */
27196 +       "       setcsr_flush    0               \n\t"
27197 +       "       move.4          (%3), d0        \n\t"   /* get dn registers */
27198 +       "       move.4          4(%3), d1       \n\t"
27199 +       "       move.4          8(%3), d2       \n\t"
27200 +       "       move.4          12(%3), d3      \n\t"
27201 +       "       move.4          16(%3), d4      \n\t"
27202 +       "       move.4          20(%3), d5      \n\t"
27203 +       "       move.4          24(%3), d6      \n\t"
27204 +       "       move.4          28(%3), d7      \n\t"
27205 +       "       move.4          32(%3), d8      \n\t"
27206 +       "       move.4          36(%3), d9      \n\t"
27207 +       "       move.4          40(%3), d10     \n\t"
27208 +       "       move.4          44(%3), d11     \n\t"
27209 +       "       move.4          48(%3), d12     \n\t"
27210 +       "       move.4          52(%3), d13     \n\t"
27211 +       "       move.4          56(%3), d14     \n\t"
27212 +       "       move.4          60(%3), d15     \n\t"
27213 +       "       move.4          (%4), a0        \n\t"   /* get an registers */
27214 +       "       move.4          4(%4), a1       \n\t"
27215 +       "       move.4          8(%4), a2       \n\t"
27216 +       "       move.4          12(%4), a3      \n\t"
27217 +       "       move.4          16(%4), a4      \n\t"
27218 +       "       move.4          20(%4), a5      \n\t"
27219 +       "       move.4          24(%4), a6      \n\t"
27220 +       "       move.4          28(%4), a7      \n\t"
27221 +       "       move.4          %0, CSR         \n\t"   /* get csr and source3
27222 +                                                        * implicit operands */
27223 +       "       move.4          %1, source3     \n\t"
27224 +       "       move.4          (%5), acc0_lo   \n\t"   /* get accumulators */
27225 +       "       move.4          4(%5), acc0_hi  \n\t"
27226 +       "       move.4          8(%5), acc1_lo  \n\t"
27227 +       "       move.4          12(%5), acc1_hi \n\t"
27228 +       "       move.4          16(%5), mac_rc16        \n\t"
27229 +       "       move.4          CSR, #0         \n\t"   /* restore CSR */
27230 +       "       setcsr_flush    0               \n\t"
27231 +               : "=m"(save_csr), "=m"(source3)
27232 +               : "d"((1 << 8) | (thread << 9)),
27233 +                 "a"(save_dn), "a"(save_an), "a"(save_acc)
27234 +               : "cc"
27235 +       );
27236 +
27237 +       /*
27238 +        * turn off thread select bits if they were on
27239 +        */
27240 +       BUG_ON((save_csr & 0x04100) != 0);
27241 +       if (unlikely(save_csr & 0x04100)) {
27242 +               /*
27243 +                * Things are in funny state as thread select bits are on in
27244 +                * csr. PANIC.
27245 +                */
27246 +               panic("In unaligned trap handler. Trap thread CSR has thread "
27247 +                     "select bits on.\n");
27248 +       }
27249 +
27250 +       save_csr = save_csr & 0x1000ff;
27251 +
27252 +       /*
27253 +        * get the source1 operand
27254 +        */
27255 +       source1 = 0;
27256 +       if (src_operand) {
27257 +               unsigned char *src_address;
27258 +
27259 +               /*
27260 +                * source1 comes from memory
27261 +                */
27262 +               BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27263 +                        format == SRC || format == SRC_2));
27264 +               src_address = unaligned_get_address(thread, inst & 0x7ff,
27265 +                                                   four_byte, save_an,
27266 +                                                   save_dn, &write_back_an);
27267 +
27268 +               /*
27269 +                * get data (possibly unaligned)
27270 +                */
27271 +               if (likely(four_byte)) {
27272 +                       source_data = (*src_address << 24) |
27273 +                               (*(src_address + 1) << 16) |
27274 +                               (*(src_address + 2) << 8) |
27275 +                               *(src_address + 3);
27276 +                       source1 = source_data;
27277 +               } else {
27278 +                       source1 = *src_address << 8 |
27279 +                               *(src_address + 1);
27280 +
27281 +                       /*
27282 +                        * Source is not extended if the instrution is MOVE.2 or
27283 +                        * if the cpu CHIP_ID >= 0x30000 and the instruction is
27284 +                        * either LSL.2 or LSR.2.  All other cases have to be
27285 +                        * sign extended.
27286 +                        */
27287 +                       if ((!(op == 2 && subop == MOVE_2)) &&
27288 +                           (!((chip_id_copy >= 0x30000) &&
27289 +                              (subop == LSL_2 || subop == LSR_2)))) {
27290 +                               /*
27291 +                                * Have to sign extend the .2 entry.
27292 +                                */
27293 +                               source1 = ((unsigned int)
27294 +                                          ((signed int)
27295 +                                           ((signed short) source1)));
27296 +                       }
27297 +               }
27298 +       } else if (likely(op != MOVEI)) {
27299 +               /*
27300 +                * source1 comes from a register, using move.4 d0, src1
27301 +                * unaligned_emulate_get_source is pointer to code to insert remulated instruction
27302 +                */
27303 +               extern unsigned int unaligned_emulate_get_src;
27304 +               *((int *)&unaligned_emulate_get_src) &= ~(0x7ff);
27305 +               *((int *)&unaligned_emulate_get_src) |= (inst & 0x7ff);
27306 +               flush_dcache_range((unsigned long)(&unaligned_emulate_get_src),
27307 +                                  (unsigned long)(&unaligned_emulate_get_src) + 4);
27308 +
27309 +               asm volatile (
27310 +                       /* source1 uses thread's registers */
27311 +               "       move.4          CSR, %1                 \n\t"
27312 +               "       setcsr_flush 0                          \n\t"
27313 +               "unaligned_emulate_get_src:                     \n\t"
27314 +               "       move.4  %0, #0                          \n\t"
27315 +               "       setcsr          #0                      \n\t"
27316 +               "       setcsr_flush    0                       \n\t"
27317 +                       : "=d" (source1)
27318 +                       : "d" ((1 << 8) | (thread << 9))
27319 +                       : "cc"
27320 +               );
27321 +       }
27322 +
27323 +       /*
27324 +        * get the destination address
27325 +        */
27326 +       if (dest_operand) {
27327 +               BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27328 +                        format == DEST || format == DEST_2));
27329 +               dest_address = unaligned_get_address(thread,
27330 +                                                    ((inst >> 16) & 0x7ff),
27331 +                                                    four_byte, save_an,
27332 +                                                    save_dn, &write_back_an);
27333 +       }
27334 +
27335 +       if (write_back_an) {
27336 +               /*
27337 +                * restore any modified An registers
27338 +                */
27339 +               asm volatile (
27340 +               "       move.4          CSR, %0                 \n\t"
27341 +               "       setcsr_flush    0                       \n\t"
27342 +               "       move.4          a0, (%1)                \n\t"
27343 +               "       move.4          a1, 4(%1)               \n\t"
27344 +               "       move.4          a2, 8(%1)               \n\t"
27345 +               "       move.4          a3, 12(%1)              \n\t"
27346 +               "       move.4          a4, 16(%1)              \n\t"
27347 +               "       move.4          a5, 20(%1)              \n\t"
27348 +               "       move.4          a6, 24(%1)              \n\t"
27349 +               "       move.4          a7, 28(%1)              \n\t"
27350 +               "       setcsr          #0                      \n\t"
27351 +               "       setcsr_flush    0                       \n\t"
27352 +                       :
27353 +                       : "d" ((1 << 14) | (thread << 15)), "a" (save_an)
27354 +                       : "cc"
27355 +               );
27356 +       }
27357 +
27358 +       /*
27359 +        * get source 2 register if needed, and modify inst to use d1 for
27360 +        * source-2 source-2 will come from this thread, not the trapping thread
27361 +        */
27362 +       source2 = 0;
27363 +       if ((op >= 8 && op <= 0x17) ||
27364 +           ((op == 2 || op == 6) && (inst & 0x4000000))) {
27365 +               int src_dn = (inst >> 11) & 0xf;
27366 +               source2 = save_dn[src_dn];
27367 +               /*
27368 +                * force the emulated instruction to use d1 for source2 operand
27369 +                */
27370 +               emulate_inst = (emulate_inst & 0xffff07ff) | 0x800;
27371 +       }
27372 +
27373 +       if (likely(op != MOVEI)) {
27374 +               /*
27375 +                * change emulated instruction source1 to d0
27376 +                */
27377 +               emulate_inst &= ~0x7ff;
27378 +               emulate_inst |= 1 << 8;
27379 +       }
27380 +
27381 +       if (unlikely(op == 6 || op == 2)) {
27382 +               /*
27383 +                * Set destination to d0
27384 +                */
27385 +               emulate_inst &= ~(0xf << 16);
27386 +       } else if (likely(op != CMPI)) {
27387 +               /*
27388 +                * Set general destination field to d0.
27389 +                */
27390 +               emulate_inst &= ~(0x7ff << 16);
27391 +               emulate_inst |= 1 << 24;
27392 +       }
27393 +
27394 +       /*
27395 +        * execute emulated instruction d0, to d0, no memory access
27396 +        * source2 if needed will be in d1
27397 +        * source3, CSR, and accumulators are set up before execution
27398 +        */
27399 +       *((unsigned int *)&trap_emulate) = emulate_inst;
27400 +       flush_dcache_range((unsigned long)(&trap_emulate),
27401 +                          (unsigned long)(&trap_emulate) + 4);
27402 +
27403 +       result = ubicom32_emulate_insn(source1, source2, source3,
27404 +                                      save_acc, &save_csr);
27405 +
27406 +       /*
27407 +        * set the result value
27408 +        */
27409 +       if (dest_operand) {
27410 +               /*
27411 +                * copy result to memory
27412 +                */
27413 +               if (four_byte) {
27414 +                       *dest_address++ =
27415 +                               (unsigned char)((result >> 24) & 0xff);
27416 +                       *dest_address++ =
27417 +                               (unsigned char)((result >> 16) & 0xff);
27418 +               }
27419 +               *dest_address++ = (unsigned char)((result >> 8) & 0xff);
27420 +               *dest_address = (unsigned char)(result & 0xff);
27421 +       } else if (likely(op != CMPI)) {
27422 +               /*
27423 +                * copy result to a register, using move.4 dest, result
27424 +                */
27425 +               extern unsigned int unaligned_trap_set_result;
27426 +               *((unsigned int *)&unaligned_trap_set_result) &= ~0x7ff0000;
27427 +
27428 +               if (op == 2 || op == 6) {
27429 +                       *((unsigned int *)&unaligned_trap_set_result) |=
27430 +                               ((inst & 0x000f0000) | 0x01000000);
27431 +               } else {
27432 +                       *((unsigned int *)&unaligned_trap_set_result) |=
27433 +                               (inst & 0x7ff0000);
27434 +               }
27435 +               flush_dcache_range((unsigned long)&unaligned_trap_set_result,
27436 +                                  ((unsigned long)(&unaligned_trap_set_result) + 4));
27437 +
27438 +               asm volatile (
27439 +                       /* result uses thread's registers */
27440 +               "       move.4          CSR, %1                 \n\t"
27441 +               "       setcsr_flush 0                          \n\t"
27442 +               "unaligned_trap_set_result:                     \n\t"
27443 +               "       move.4 #0, %0                           \n\t"
27444 +               "       setcsr          #0                      \n\t"
27445 +               "       setcsr_flush    0                       \n\t"
27446 +                       :
27447 +                       : "d"(result), "d" ((1 << 14) | (thread << 15))
27448 +                       : "cc"
27449 +               );
27450 +       }
27451 +
27452 +       /*
27453 +        * bump PC in thread and restore implicit register changes
27454 +        */
27455 +       asm volatile (
27456 +       "       move.4          CSR, %0                 \n\t"
27457 +       "       setcsr_flush    0                       \n\t"
27458 +       "       move.4          pc, %1                  \n\t"
27459 +       "       move.4          acc0_lo, (%3)           \n\t"
27460 +       "       move.4          acc0_hi, 4(%3)          \n\t"
27461 +       "       move.4          acc1_lo, 8(%3)          \n\t"
27462 +       "       move.4          acc1_hi, 12(%3)         \n\t"
27463 +       "       move.4          mac_rc16, 16(%3)        \n\t"
27464 +       "       move.4          CSR, %2                 \n\t"
27465 +       "       setcsr          #0                      \n\t"
27466 +       "       setcsr_flush    0                       \n\t"
27467 +               :
27468 +               : "d"((1 << 14) | (thread << 15)),
27469 +                 "d"(pc + 4), "d"(save_csr), "a"(save_acc)
27470 +               : "cc"
27471 +       );
27472 +}
27473 +
27474 +/*
27475 + * unaligned_only()
27476 + *     Return true if either of the unaligned causes are set (and no others).
27477 + */
27478 +int unaligned_only(unsigned int cause)
27479 +{
27480 +       unsigned int unaligned_cause_mask =
27481 +               (1 << TRAP_CAUSE_DST_MISALIGNED) |
27482 +               (1 << TRAP_CAUSE_SRC1_MISALIGNED);
27483 +
27484 +       BUG_ON(cause == 0);
27485 +       return (cause & unaligned_cause_mask) == cause;
27486 +}
27487 --- /dev/null
27488 +++ b/arch/ubicom32/kernel/vmlinux.lds.S
27489 @@ -0,0 +1,370 @@
27490 +/*
27491 + * arch/ubicom32/kernel/vmlinux.lds.S
27492 + *     vmlinux primary linker script
27493 + *
27494 + * (C) Copyright 2009, Ubicom, Inc.
27495 + *
27496 + * This file is part of the Ubicom32 Linux Kernel Port.
27497 + *
27498 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
27499 + * it and/or modify it under the terms of the GNU General Public License
27500 + * as published by the Free Software Foundation, either version 2 of the
27501 + * License, or (at your option) any later version.
27502 + *
27503 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
27504 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
27505 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
27506 + * the GNU General Public License for more details.
27507 + *
27508 + * You should have received a copy of the GNU General Public License
27509 + * along with the Ubicom32 Linux Kernel Port.  If not,
27510 + * see <http://www.gnu.org/licenses/>.
27511 + *
27512 + * Ubicom32 implementation derived from (with many thanks):
27513 + *   arch/m68knommu
27514 + *   arch/blackfin
27515 + *   arch/parisc
27516 + */
27517 +#include <asm-generic/vmlinux.lds.h>
27518 +#include <asm/ocm_size.h>
27519 +#include <asm/memory_map.h>
27520 +#include <asm/thread_info.h>
27521 +#include <linux/threads.h>
27522 +
27523 +/*
27524 + * Sanity checks to prevent errors later on that are much harder to understand
27525 + */
27526 +#if !defined APP_OCM_CODE_SIZE
27527 +#error APP_OCM_CODE_SIZE has not been defined in ocm_size.h
27528 +#endif
27529 +
27530 +#if !defined APP_OCM_DATA_SIZE
27531 +#error APP_OCM_DATA_SIZE has not been defined in ocm_size.h
27532 +#endif
27533 +
27534 +/*
27535 + * The `free' ocm area that ultra does not use.
27536 + */
27537 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
27538 +#define OCM_FREE_START (OCMSTART + APP_OCM_CODE_SIZE)
27539 +#define OCM_FREE_LENGTH        (OCMSIZE - APP_OCM_CODE_SIZE - APP_OCM_DATA_SIZE)
27540 +#else
27541 +#define OCM_FREE_START OCMEND
27542 +#define OCM_FREE_LENGTH 0
27543 +#endif
27544 +
27545 +/*
27546 + * If you want to limit OCM use for text/data or completely disable it
27547 + * you can change these values.
27548 + */
27549 +#define OCM_TEXT_LENGTH        OCM_FREE_LENGTH
27550 +#define OCM_DATA_LENGTH        OCM_FREE_LENGTH
27551 +
27552 +#define        RAM_START       KERNELSTART
27553 +#define        RAM_LENGTH      ((SDRAMSTART + CONFIG_MIN_RAMSIZE) - RAM_START)
27554 +#define        TEXT            ram
27555 +#define        DATA            ram
27556 +#define        INIT            ram
27557 +#define        BSS             ram
27558 +
27559 +#ifndef DATA_ADDR
27560 +#define        DATA_ADDR
27561 +#endif
27562 +
27563 +#include <asm-generic/vmlinux.lds.h>
27564 +
27565 +OUTPUT_ARCH(ubicom32)
27566 +ENTRY(_start)
27567 +
27568 +MEMORY {
27569 +       ram             : ORIGIN = RAM_START, LENGTH = RAM_LENGTH
27570 +       syscall         : ORIGIN = OS_SYSCALL_BEGIN, LENGTH = (OS_SYSCALL_END - OS_SYSCALL_BEGIN)
27571 +       ocm             : ORIGIN = OCM_FREE_START, LENGTH = OCM_FREE_LENGTH
27572 +}
27573 +
27574 +jiffies = jiffies_64 + 4;
27575 +
27576 +/*
27577 + * Fixed locations required by gdb coredumps.
27578 + *
27579 + * Note that the names are what gdb is expecting so renaming will break
27580 + * the toolchain.
27581 + */
27582 +__ocm_begin            = OCMSTART;
27583 +__ocm_limit            = __ocm_begin + OCMSIZE;
27584 +__sdram_begin          = SDRAMSTART;
27585 +__sdram_limit          = __sdram_begin + CONFIG_MIN_RAMSIZE;
27586 +__filemedia_begin_addr = FLASHSTART;
27587 +__filemedia_end_addr   = __filemedia_begin_addr + 0x00800000;
27588 +
27589 +/*
27590 + * For internal diagnostics
27591 + */
27592 +__os_syscall_begin     = OS_SYSCALL_BEGIN;
27593 +__os_syscall_end       = OS_SYSCALL_END;
27594 +
27595 +SECTIONS {
27596 +
27597 +       .fixed_text : {
27598 +               _begin = .;
27599 +               *(.skip_syscall)
27600 +               *(.old_syscall_entry.text)
27601 +               __fixed_text_end = .;
27602 +       } > TEXT
27603 +       . = _begin + SIZEOF(.fixed_text) ;
27604 +
27605 +       /*
27606 +        * System call text in lower ocm (fixed location, can never change)
27607 +        */
27608 +       __syscall_text_load_begin = .;
27609 +       __syscall_text_run_begin = OS_SYSCALL_BEGIN;
27610 +
27611 +       .syscall_text __syscall_text_run_begin : AT(__syscall_text_load_begin) {
27612 +               *(.syscall_entry.text) /* Must be at OS_SYSCALL_BEGIN 0x3ffc0040 */
27613 +               *(.kernel_unprotected)
27614 +               . = ALIGN(4);
27615 +               __syscall_text_run_end = .;
27616 +       } > syscall /* .syscall_text */
27617 +       . = __syscall_text_load_begin + __syscall_text_run_end - __syscall_text_run_begin ;
27618 +       __ocm_text_load_begin = .;
27619 +       __ocm_text_run_begin = OCM_FREE_START ;
27620 +       .ocm_text __ocm_text_run_begin : AT(__ocm_text_load_begin) {
27621 +#if OCM_TEXT_LENGTH
27622 +               *(.ocm_text)
27623 +               *(.sched.text)
27624 +               *(.spinlock.text)
27625 +#include <asm/ocm_text.lds.inc>
27626 +               . = ALIGN(4);
27627 +#endif
27628 +               __ocm_text_run_end = .;
27629 +               __data_begin = ALIGN(OCM_SECTOR_SIZE);
27630 +       } > ocm /* .ocm_text */
27631 +
27632 +       .ocm_module_text __ocm_text_run_end (NOLOAD) : AT(__ocm_text_run_end) {
27633 +               __ocm_inst_heap_begin = .;
27634 +               /* Reserve the min requested */
27635 +               . += (CONFIG_OCM_MODULES_RESERVATION) * 1024;
27636 +#ifdef CONFIG_OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
27637 +               /* Round up to OCM sector size (we cannot use it for data) */
27638 +               . = ALIGN(OCM_SECTOR_SIZE);
27639 +#endif
27640 +               __ocm_inst_heap_end = .;
27641 +               /* update __data_begin */
27642 +               __data_begin = ALIGN(OCM_SECTOR_SIZE);
27643 +       } > ocm  /* .ocm_module_text */
27644 +
27645 +       . = __ocm_text_load_begin + __ocm_text_run_end - __ocm_text_run_begin ;
27646 +       __ocm_text_load_end = .;
27647 +
27648 +       __ocm_data_load_begin = .;
27649 +       __ocm_data_run_begin = __data_begin ;
27650 +#if OCM_DATA_LENGTH
27651 +       .ocm_data __ocm_data_run_begin : AT(__ocm_data_load_begin) {
27652 +#if defined(CONFIG_IRQSTACKS_USEOCM)
27653 +               percpu_irq_stacks = .;
27654 +               . += NR_CPUS * THREAD_SIZE;
27655 +#endif
27656 +               *(.ocm_data)
27657 +               . = ALIGN(4) ;
27658 +               __ocm_data_run_end = .;
27659 +       } > ocm
27660 +       . = __ocm_data_load_begin + __ocm_data_run_end - __ocm_data_run_begin ;
27661 +#else
27662 +       __ocm_data_run_end = __ocm_data_run_begin;
27663 +#endif
27664 +       __ocm_data_load_end = .;
27665 +
27666 +       __ocm_free_begin = __ocm_data_run_end;
27667 +       __ocm_free_end = OCM_FREE_START + OCM_FREE_LENGTH;
27668 +
27669 +       .text __ocm_data_load_end : AT(__ocm_data_load_end) {
27670 +               . = ALIGN(4);
27671 +               _stext = .;
27672 +               _text = .;
27673 +               TEXT_TEXT
27674 +               SCHED_TEXT
27675 +               LOCK_TEXT
27676 +               *(.text.lock)
27677 +               *(.text.__libgcc_udivmodsi)
27678 +               *(.text.__libgcc_divmodsi)
27679 +               *(.text.__libgcc_muldi3)
27680 +               *(.text.__libgcc_udivmoddi)
27681 +               *(.text.__libgcc_divmoddi)
27682 +               *(.text.*)
27683 +#if OCM_TEXT_LENGTH == 0
27684 +               *(.ocm_text)
27685 +               *(.sched.text)
27686 +               *(.spinlock.text)
27687 +#endif
27688 +               . = ALIGN(16);          /* Exception table              */
27689 +               __start___ex_table = .;
27690 +               *(__ex_table)
27691 +               __stop___ex_table = .;
27692 +
27693 +               *(.rodata) *(.rodata.*)
27694 +               *(__vermagic)           /* Kernel version magic */
27695 +               *(__markers_strings)
27696 +               *(.rodata1)
27697 +               *(.rodata.str1.1)
27698 +               *(__tracepoints_strings)
27699 +
27700 +                /* PCI quirks */
27701 +               __start_pci_fixups_early = . ;
27702 +                       *(.pci_fixup_early)
27703 +               __end_pci_fixups_early = . ;
27704 +               __start_pci_fixups_header = . ;
27705 +                       *(.pci_fixup_header)
27706 +               __end_pci_fixups_header = . ;
27707 +               __start_pci_fixups_final = . ;
27708 +                       *(.pci_fixup_final)
27709 +               __end_pci_fixups_final = . ;
27710 +               __start_pci_fixups_enable = . ;
27711 +                       *(.pci_fixup_enable)
27712 +               __end_pci_fixups_enable = . ;
27713 +               __start_pci_fixups_resume = . ;
27714 +                      *(.pci_fixup_resume)
27715 +               __end_pci_fixups_resume = . ;
27716 +               __start_pci_fixups_resume_early = . ;
27717 +                      *(.pci_fixup_resume_early)
27718 +               __end_pci_fixups_resume_early = . ;
27719 +               __start_pci_fixups_suspend  = . ;
27720 +                      *(.pci_fixup_suspend)
27721 +               __end_pci_fixups_suspend = . ;
27722 +
27723 +               __start_builtin_fw = . ;
27724 +                       *(.builtin_fw)
27725 +               __end_builtin_fw = . ;
27726 +
27727 +
27728 +               /* Kernel symbol table: Normal symbols */
27729 +               . = ALIGN(4);
27730 +               __start___ksymtab = .;
27731 +               *(__ksymtab)
27732 +               __stop___ksymtab = .;
27733 +
27734 +               /* Kernel symbol table: GPL-only symbols */
27735 +               __start___ksymtab_gpl = .;
27736 +               *(__ksymtab_gpl)
27737 +               __stop___ksymtab_gpl = .;
27738 +
27739 +               /* Kernel symbol table: Normal unused symbols */
27740 +               __start___ksymtab_unused = .;
27741 +               *(__ksymtab_unused)
27742 +               __stop___ksymtab_unused = .;
27743 +
27744 +               /* Kernel symbol table: GPL-only unused symbols */
27745 +               __start___ksymtab_unused_gpl = .;
27746 +               *(__ksymtab_unused_gpl)
27747 +               __stop___ksymtab_unused_gpl = .;
27748 +
27749 +               /* Kernel symbol table: GPL-future symbols */
27750 +               __start___ksymtab_gpl_future = .;
27751 +               *(__ksymtab_gpl_future)
27752 +               __stop___ksymtab_gpl_future = .;
27753 +
27754 +               /* Kernel symbol table: Normal symbols */
27755 +               __start___kcrctab = .;
27756 +               *(__kcrctab)
27757 +               __stop___kcrctab = .;
27758 +
27759 +               /* Kernel symbol table: GPL-only symbols */
27760 +               __start___kcrctab_gpl = .;
27761 +               *(__kcrctab_gpl)
27762 +               __stop___kcrctab_gpl = .;
27763 +
27764 +               /* Kernel symbol table: GPL-future symbols */
27765 +               __start___kcrctab_gpl_future = .;
27766 +               *(__kcrctab_gpl_future)
27767 +               __stop___kcrctab_gpl_future = .;
27768 +
27769 +               /* Kernel symbol table: strings */
27770 +               *(__ksymtab_strings)
27771 +
27772 +               /* Built-in module parameters */
27773 +               . = ALIGN(4) ;
27774 +               __start___param = .;
27775 +               *(__param)
27776 +               __stop___param = .;
27777 +
27778 +               . = ALIGN(4) ;
27779 +               _etext = . ;
27780 +       } > TEXT
27781 +
27782 +       .data DATA_ADDR : {
27783 +               . = ALIGN(4);
27784 +               _sdata = . ;
27785 +               DATA_DATA
27786 +#if OCM_DATA_LENGTH == 0
27787 +               *(.ocm_data)
27788 +#endif
27789 +               . = ALIGN(8192) ;
27790 +               _data_protection_end = .;
27791 +               *(.data.init_task)
27792 +               . = ALIGN(4);
27793 +               _edata = . ;
27794 +       } > DATA
27795 +
27796 +       .init : {
27797 +               . = ALIGN(4096);
27798 +               __init_begin = .;
27799 +               _sinittext = .;
27800 +               INIT_TEXT
27801 +               _einittext = .;
27802 +               *(.init.rodata)
27803 +               INIT_DATA
27804 +               . = ALIGN(16);
27805 +               __setup_start = .;
27806 +               *(.init.setup)
27807 +               __setup_end = .;
27808 +               __initcall_start = .;
27809 +               INITCALLS
27810 +               __initcall_end = .;
27811 +               __con_initcall_start = .;
27812 +               *(.con_initcall.init)
27813 +               __con_initcall_end = .;
27814 +               ___security_initcall_start = .;
27815 +               *(.security_initcall.init)
27816 +               ___security_initcall_end = .;
27817 +#ifdef CONFIG_BLK_DEV_INITRD
27818 +               . = ALIGN(4);
27819 +               __initramfs_start = .;
27820 +               *(.init.ramfs)
27821 +               __initramfs_end = .;
27822 +#endif
27823 +               . = ALIGN(4096);
27824 +               __per_cpu_start = .;
27825 +                       *(.data.percpu)
27826 +                       *(.data.percpu.shared_aligned)
27827 +               __per_cpu_end = .;
27828 +
27829 +               . = ALIGN(4096);
27830 +               __init_end = .;
27831 +       } > INIT
27832 +
27833 +         .eh_frame   :
27834 +         {
27835 +           PROVIDE (___eh_frame_begin = .);
27836 +           *(.eh_frame)
27837 +           LONG (0);
27838 +           PROVIDE (___eh_frame_end = .);
27839 +         } > INIT
27840 +
27841 +       /DISCARD/ : {
27842 +               EXIT_TEXT
27843 +               EXIT_DATA
27844 +               *(.exitcall.exit)
27845 +       }
27846 +
27847 +       .bss : {
27848 +               . = ALIGN(4);
27849 +               _sbss = . ;
27850 +               *(.bss)
27851 +               *(COMMON)
27852 +               . = ALIGN(4) ;
27853 +               _ebss = . ;
27854 +               _end = . ;
27855 +       } > BSS
27856 +
27857 +       NOTES > BSS
27858 +
27859 +}
27860 --- /dev/null
27861 +++ b/arch/ubicom32/lib/checksum.c
27862 @@ -0,0 +1,250 @@
27863 +/*
27864 + * arch/ubicom32/lib/checksum.c
27865 + *   Optimized checksum utilities for IP.
27866 + *
27867 + * (C) Copyright 2009, Ubicom, Inc.
27868 + *
27869 + * This file is part of the Ubicom32 Linux Kernel Port.
27870 + *
27871 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
27872 + * it and/or modify it under the terms of the GNU General Public License
27873 + * as published by the Free Software Foundation, either version 2 of the
27874 + * License, or (at your option) any later version.
27875 + *
27876 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
27877 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
27878 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
27879 + * the GNU General Public License for more details.
27880 + *
27881 + * You should have received a copy of the GNU General Public License
27882 + * along with the Ubicom32 Linux Kernel Port.  If not,
27883 + * see <http://www.gnu.org/licenses/>.
27884 + *
27885 + * Ubicom32 implementation derived from (with many thanks):
27886 + *   arch/m68knommu
27887 + *   arch/blackfin
27888 + *   arch/parisc
27889 + */
27890 +/*
27891 + * INET                An implementation of the TCP/IP protocol suite for the LINUX
27892 + *             operating system.  INET is implemented using the  BSD Socket
27893 + *             interface as the means of communication with the user level.
27894 + *
27895 + *             IP/TCP/UDP checksumming routines
27896 + *
27897 + * Authors:    Jorge Cwik, <jorge@laser.satlink.net>
27898 + *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
27899 + *             Tom May, <ftom@netcom.com>
27900 + *             Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
27901 + *             Lots of code moved from tcp.c and ip.c; see those files
27902 + *             for more names.
27903 + *
27904 + * 03/02/96    Jes Sorensen, Andreas Schwab, Roman Hodek:
27905 + *             Fixed some nasty bugs, causing some horrible crashes.
27906 + *             A: At some points, the sum (%0) was used as
27907 + *             length-counter instead of the length counter
27908 + *             (%1). Thanks to Roman Hodek for pointing this out.
27909 + *             B: GCC seems to mess up if one uses too many
27910 + *             data-registers to hold input values and one tries to
27911 + *             specify d0 and d1 as scratch registers. Letting gcc choose these
27912 + *             registers itself solves the problem.
27913 + *
27914 + *             This program is free software; you can redistribute it and/or
27915 + *             modify it under the terms of the GNU General Public License
27916 + *             as published by the Free Software Foundation; either version
27917 + *             2 of the License, or (at your option) any later version.
27918 + */
27919 +
27920 +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
27921 +   of the assembly has to go. */
27922 +
27923 +#include <linux/module.h>
27924 +#include <net/checksum.h>
27925 +
27926 +static unsigned long do_csum(const unsigned char * buff, int len)
27927 +{
27928 +       int count;
27929 +       unsigned long result = 0;
27930 +
27931 +       /*
27932 +        * The following optimized assembly code cannot handle data length less than 7 bytes!
27933 +        */
27934 +       if (likely(len >= 7)) {
27935 +               len -= (4 - (int)buff) & 3;
27936 +               count = len >> 2;
27937 +               asm (
27938 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
27939 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
27940 +
27941 +               "       bfextu          d14, %0, #2             \n\t"   // test 2 LSB of buff
27942 +               "       jmpne.w.f       100f                    \n\t"
27943 +               "       add.4           %1, #0, %1              \n\t"   // clear C
27944 +               "       moveai          a3, #%%hi(1f)           \n\t"   // table jump
27945 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
27946 +               "       lea.4           a3, (a3,d15)            \n\t"
27947 +               "       calli           a3, 0(a3)               \n\t"
27948 +
27949 +               "100:   sub.4           %0, %0, d14             \n\t"
27950 +               "       sub.4           d14, #4, d14            \n\t"
27951 +               "       lsl.4           d14, d14, #3            \n\t"
27952 +               "       add.4           %1, #0, %1              \n\t"   // clear C
27953 +               "       moveai          a3, #%%hi(1f)           \n\t"   // table jump
27954 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
27955 +               "       lea.4           a3, (a3,d15)            \n\t"
27956 +               "       bfextu          %1, (%0)4++, d14        \n\t"   // read first partial word
27957 +               "       calli           a3, 0(a3)               \n\t"
27958 +#if 1
27959 +               "200:   lsl.4           %3, %3, #3              \n\t"
27960 +               "       bfrvrs          d15, (%0), #0           \n\t"   // read last word (partial)
27961 +               "       bfextu          d15, d15, %3            \n\t"
27962 +               "       bfrvrs          d15, d15, #0            \n\t"
27963 +               "       add.4           %1, d15, %1             \n\t"
27964 +               "       addc            %1, #0, %1              \n\t"   // sample C again
27965 +               "       jmpt.w.t        2f                      \n\t"
27966 +#else
27967 +               "200:   move.1          d15, 0(%0)              \n\t"
27968 +               "       lsl.4           d15, d15, #8            \n\t"
27969 +               "       add.4           %1, d15, %1             \n\t"
27970 +               "       addc            %1, #0, %1              \n\t"   // sample C again
27971 +               "       add.4           %3, #-1, %3             \n\t"
27972 +               "       jmpeq.w.t       2f                      \n\t"
27973 +
27974 +               "       move.1          d15, 1(%0)              \n\t"
27975 +               "       add.4           %1, d15, %1             \n\t"
27976 +               "       addc            %1, #0, %1              \n\t"   // sample C again
27977 +               "       add.4           %3, #-1, %3             \n\t"
27978 +               "       jmpeq.w.t       2f                      \n\t"
27979 +
27980 +               "       move.1          d15, 2(%0)              \n\t"
27981 +               "       lsl.4           d15, d15, #8            \n\t"
27982 +               "       add.4           %1, d15, %1             \n\t"
27983 +               "       addc            %1, #0, %1              \n\t"   // sample C again
27984 +               "       jmpt.w.t        2f                      \n\t"
27985 +#endif
27986 +#if defined(IP7000) || defined(IP7000_REV2)
27987 +               "300:   swapb.2         %1, %1                  \n\t"
27988 +#else
27989 +               "300:   shmrg.2         %1, %1, %1              \n\t"
27990 +               "       lsr.4           %1, %1, #8              \n\t"
27991 +               "       bfextu          %1, %1, #16             \n\t"
27992 +#endif
27993 +               "       jmpt.w.t        3f                      \n\t"
27994 +
27995 +               "1:     add.4           %1, (%0)4++, %1         \n\t"   // first add without C
27996 +               "       .rept           31                      \n\t"
27997 +               "       addc            %1, (%0)4++, %1         \n\t"
27998 +               "       .endr                                   \n\t"
27999 +               "       addc            %1, #0, %1              \n\t"   // sample C again
28000 +               "       add.4           %2, #-32, %2            \n\t"
28001 +               "       jmpgt.w.t       1b                      \n\t"
28002 +
28003 +               "       and.4           %3, #3, %3              \n\t"   // check n
28004 +               "       jmpne.w.f       200b                    \n\t"
28005 +
28006 +               "2:     .rept           2                       \n\t"
28007 +               "       lsr.4           d15, %1, #16            \n\t"
28008 +               "       bfextu          %1, %1, #16             \n\t"
28009 +               "       add.4           %1, d15, %1             \n\t"
28010 +               "       .endr                                   \n\t"
28011 +               "       btst            d14, #3                 \n\t"   // start from odd address (<< 3)?
28012 +               "       jmpne.w.f       300b                    \n\t"
28013 +               "3:                                             \n\t"
28014 +
28015 +                       : "+a"(buff), "+d"(result), "+d"(count), "+d"(len)
28016 +                       :
28017 +                       : "d15", "d14", "a3", "cc"
28018 +               );
28019 +
28020 +               return result;
28021 +       }
28022 +
28023 +       /*
28024 +        * handle a few bytes and fold result into 16-bit
28025 +        */
28026 +       while (len-- > 0) {
28027 +               result += (*buff++ << 8);
28028 +               if (len) {
28029 +                       result += *buff++;
28030 +                       len--;
28031 +               }
28032 +       }
28033 +       asm (
28034 +       "       .rept           2                       \n\t"
28035 +       "       lsr.4           d15, %0, #16            \n\t"
28036 +       "       bfextu          %0, %0, #16             \n\t"
28037 +       "       add.4           %0, d15, %0             \n\t"
28038 +       "       .endr                                   \n\t"
28039 +               : "+d" (result)
28040 +               :
28041 +               : "d15", "cc"
28042 +       );
28043 +
28044 +       return result;
28045 +}
28046 +
28047 +/*
28048 + *     This is a version of ip_compute_csum() optimized for IP headers,
28049 + *     which always checksum on 4 octet boundaries.
28050 + */
28051 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
28052 +{
28053 +       return (__force __sum16)~do_csum(iph,ihl*4);
28054 +}
28055 +
28056 +/*
28057 + * computes the checksum of a memory block at buff, length len,
28058 + * and adds in "sum" (32-bit)
28059 + *
28060 + * returns a 32-bit number suitable for feeding into itself
28061 + * or csum_tcpudp_magic
28062 + *
28063 + * this function must be called with even lengths, except
28064 + * for the last fragment, which may be odd
28065 + *
28066 + * it's best to have buff aligned on a 32-bit boundary
28067 + */
28068 +__wsum csum_partial(const void *buff, int len, __wsum sum)
28069 +{
28070 +       unsigned int result = do_csum(buff, len);
28071 +
28072 +       /* add in old sum, and carry.. */
28073 +       result += (__force u32)sum;
28074 +       if ((__force u32)sum > result)
28075 +               result += 1;
28076 +       return (__force __wsum)result;
28077 +}
28078 +
28079 +EXPORT_SYMBOL(csum_partial);
28080 +
28081 +/*
28082 + * this routine is used for miscellaneous IP-like checksums, mainly
28083 + * in icmp.c
28084 + */
28085 +__sum16 ip_compute_csum(const void *buff, int len)
28086 +{
28087 +       return (__force __sum16)~do_csum(buff,len);
28088 +}
28089 +
28090 +/*
28091 + * copy from fs while checksumming, otherwise like csum_partial
28092 + */
28093 +
28094 +__wsum
28095 +csum_partial_copy_from_user(const void __user *src, void *dst,
28096 +                           int len, __wsum sum, int *csum_err)
28097 +{
28098 +       if (csum_err) *csum_err = 0;
28099 +       memcpy(dst, (__force const void *)src, len);
28100 +       return csum_partial(dst, len, sum);
28101 +}
28102 +
28103 +/*
28104 + * copy from ds while checksumming, otherwise like csum_partial
28105 + */
28106 +
28107 +__wsum
28108 +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
28109 +{
28110 +       memcpy(dst, src, len);
28111 +       return csum_partial(dst, len, sum);
28112 +}
28113 --- /dev/null
28114 +++ b/arch/ubicom32/lib/delay.c
28115 @@ -0,0 +1,49 @@
28116 +/*
28117 + * arch/ubicom32/lib/delay.c
28118 + *   Ubicom32 implementation of udelay()
28119 + *
28120 + * (C) Copyright 2009, Ubicom, Inc.
28121 + *
28122 + * This file is part of the Ubicom32 Linux Kernel Port.
28123 + *
28124 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28125 + * it and/or modify it under the terms of the GNU General Public License
28126 + * as published by the Free Software Foundation, either version 2 of the
28127 + * License, or (at your option) any later version.
28128 + *
28129 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28130 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28131 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28132 + * the GNU General Public License for more details.
28133 + *
28134 + * You should have received a copy of the GNU General Public License
28135 + * along with the Ubicom32 Linux Kernel Port.  If not,
28136 + * see <http://www.gnu.org/licenses/>.
28137 + *
28138 + * Ubicom32 implementation derived from (with many thanks):
28139 + *   arch/m68knommu
28140 + *   arch/blackfin
28141 + *   arch/parisc
28142 + */
28143 +
28144 +#include <linux/module.h>
28145 +#include <asm/param.h>
28146 +#include <asm/delay.h>
28147 +#include <asm/ip5000.h>
28148 +
28149 +/*
28150 + * read_current_timer()
28151 + *     Return the current value of sysval.
28152 + */
28153 +int __devinit read_current_timer(unsigned long *timer_val)
28154 +{
28155 +       *timer_val = (long)(UBICOM32_IO_TIMER->sysval);
28156 +       return 0;
28157 +}
28158 +
28159 +
28160 +void udelay(unsigned long usecs)
28161 +{
28162 +       _udelay(usecs);
28163 +}
28164 +EXPORT_SYMBOL(udelay);
28165 --- /dev/null
28166 +++ b/arch/ubicom32/lib/Makefile
28167 @@ -0,0 +1,32 @@
28168 +#
28169 +# arch/ubicom32/lib/Makefile
28170 +#      <TODO: Replace with short file description>
28171 +#
28172 +# (C) Copyright 2009, Ubicom, Inc.
28173 +#
28174 +# This file is part of the Ubicom32 Linux Kernel Port.
28175 +#
28176 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
28177 +# it and/or modify it under the terms of the GNU General Public License
28178 +# as published by the Free Software Foundation, either version 2 of the
28179 +# License, or (at your option) any later version.
28180 +#
28181 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
28182 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
28183 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28184 +# the GNU General Public License for more details.
28185 +#
28186 +# You should have received a copy of the GNU General Public License
28187 +# along with the Ubicom32 Linux Kernel Port.  If not,
28188 +# see <http://www.gnu.org/licenses/>.
28189 +#
28190 +# Ubicom32 implementation derived from (with many thanks):
28191 +#   arch/m68knommu
28192 +#   arch/blackfin
28193 +#   arch/parisc
28194 +#
28195 +#
28196 +# Makefile for m68knommu specific library files..
28197 +#
28198 +
28199 +lib-y  := checksum.o delay.o mem_ubicom32.o
28200 --- /dev/null
28201 +++ b/arch/ubicom32/lib/mem_ubicom32.c
28202 @@ -0,0 +1,343 @@
28203 +/*
28204 + * arch/ubicom32/lib/mem_ubicom32.c
28205 + *   String functions.
28206 + *
28207 + * (C) Copyright 2009, Ubicom, Inc.
28208 + *
28209 + * This file is part of the Ubicom32 Linux Kernel Port.
28210 + *
28211 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28212 + * it and/or modify it under the terms of the GNU General Public License
28213 + * as published by the Free Software Foundation, either version 2 of the
28214 + * License, or (at your option) any later version.
28215 + *
28216 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28217 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28218 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28219 + * the GNU General Public License for more details.
28220 + *
28221 + * You should have received a copy of the GNU General Public License
28222 + * along with the Ubicom32 Linux Kernel Port.  If not,
28223 + * see <http://www.gnu.org/licenses/>.
28224 + *
28225 + * Ubicom32 implementation derived from (with many thanks):
28226 + *   arch/m68knommu
28227 + *   arch/blackfin
28228 + *   arch/parisc
28229 + */
28230 +
28231 +#include <linux/module.h>
28232 +#include <linux/types.h>
28233 +#include <linux/compiler.h>
28234 +
28235 +#define LIKELY likely
28236 +#define UNLIKELY unlikely
28237 +
28238 +typedef u32_t addr_t;
28239 +
28240 +/*
28241 + * memcpy()
28242 + */
28243 +void *memcpy(void *dest, const void *src, size_t n)
28244 +{
28245 +       void *dest_ret = dest;
28246 +
28247 +       if (LIKELY((((addr_t)dest ^ (addr_t)src) & 3) == 0) && LIKELY(n > 6)) {
28248 +               size_t m;
28249 +               n -= (4 - (addr_t)dest) & 0x03;
28250 +               m = n >> 2;
28251 +               asm volatile (
28252 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28253 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28254 +               "       moveai          a3, #%%hi(1f)           \n\t"
28255 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28256 +               "       lea.4           a3, (a3,d15)            \n\t"
28257 +
28258 +               "       bfextu          d15, %0, #2             \n\t"   // d15 = (dest & 3)
28259 +               "       jmpne.w.f       100f                    \n\t"
28260 +               "       calli           a3, 0(a3)               \n\t"   // 4-byte alignment
28261 +
28262 +               "100:   cmpi            d15, #2                 \n\t"
28263 +               "       jmpne.s.f       101f                    \n\t"
28264 +               "       move.2          (%0)2++, (%1)2++        \n\t"
28265 +               "       calli           a3, 0(a3)               \n\t"   // 2-byte alignment
28266 +
28267 +               "101:   move.1          (%0)1++, (%1)1++        \n\t"
28268 +               "       jmpgt.s.f       102f                    \n\t"   // 3-byte alignment
28269 +               "       move.2          (%0)2++, (%1)2++        \n\t"   // 1-byte alignment
28270 +               "102:   calli           a3, 0(a3)               \n\t"
28271 +
28272 +               "200:   cmpi            %3, #2                  \n\t"
28273 +               "       jmplt.s.f       201f                    \n\t"
28274 +               "       move.2          (%0)2++, (%1)2++        \n\t"
28275 +               "       jmpeq.s.t       2f                      \n\t"
28276 +               "201:   move.1          (%0)1++, (%1)1++        \n\t"
28277 +               "       jmpt.w.t        2f                      \n\t"
28278 +
28279 +               "1:     .rept           25                      \n\t"
28280 +               "       movea           (%0)4++, (%1)4++        \n\t"
28281 +               "       .endr                                   \n\t"
28282 +               "       .rept           7                       \n\t"
28283 +               "       move.4          (%0)4++, (%1)4++        \n\t"
28284 +               "       .endr                                   \n\t"
28285 +               "       add.4           %2, #-32, %2            \n\t"
28286 +               "       jmpgt.w.f       1b                      \n\t"
28287 +
28288 +               "       and.4           %3, #3, %3              \n\t"   // check n
28289 +               "       jmpne.w.f       200b                    \n\t"
28290 +               "2:                                             \n\t"
28291 +                       : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28292 +                       :
28293 +                       : "d15", "a3", "memory", "cc"
28294 +               );
28295 +
28296 +               return dest_ret;
28297 +       }
28298 +
28299 +       if (LIKELY((((addr_t)dest ^ (addr_t)src) & 1) == 0) && LIKELY(n > 2)) {
28300 +               size_t m;
28301 +               n -= (addr_t)dest & 0x01;
28302 +               m = n >> 1;
28303 +               asm volatile (
28304 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28305 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28306 +               "       moveai          a3, #%%hi(1f)           \n\t"
28307 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28308 +               "       lea.4           a3, (a3,d15)            \n\t"
28309 +
28310 +               "       btst            %0, #0                  \n\t"   // check bit 0
28311 +               "       jmpne.w.f       100f                    \n\t"
28312 +               "       calli           a3, 0(a3)               \n\t"   // 4-byte alignment
28313 +
28314 +               "100:   move.1          (%0)1++, (%1)1++        \n\t"
28315 +               "       calli           a3, 0(a3)               \n\t"
28316 +
28317 +               "200:   move.1          (%0)1++, (%1)1++        \n\t"
28318 +               "       jmpt.w.t        2f                      \n\t"
28319 +
28320 +               "1:     .rept           32                      \n\t"
28321 +               "       move.2          (%0)2++, (%1)2++        \n\t"
28322 +               "       .endr                                   \n\t"
28323 +               "       add.4           %2, #-32, %2            \n\t"
28324 +               "       jmpgt.w.f       1b                      \n\t"
28325 +
28326 +               "       and.4           %3, #1, %3              \n\t"   // check n
28327 +               "       jmpne.w.f       200b                    \n\t"
28328 +               "2:                                             \n\t"
28329 +
28330 +                       : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28331 +                       :
28332 +                       : "d15", "a3", "memory", "cc"
28333 +               );
28334 +
28335 +               return dest_ret;
28336 +       }
28337 +
28338 +       asm volatile (
28339 +       "       sub.4           d15, #0, %2             \n\t"
28340 +       "       jmpeq.w.f       2f                      \n\t"
28341 +       "       and.4           d15, #(16-1), d15       \n\t"   // d15 = (-n) & (16 - 1)
28342 +       "       moveai          a3, #%%hi(1f)           \n\t"
28343 +       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28344 +       "       lea.4           a3, (a3,d15)            \n\t"
28345 +       "       calli           a3, 0(a3)               \n\t"
28346 +
28347 +       "1:     .rept           16                      \n\t"
28348 +       "       move.1          (%0)1++, (%1)1++        \n\t"
28349 +       "       .endr                                   \n\t"
28350 +       "       add.4           %2, #-16, %2            \n\t"
28351 +       "       jmpgt.w.f       1b                      \n\t"
28352 +       "2:                                             \n\t"
28353 +
28354 +               : "+a" (dest), "+a" (src), "+d" (n)
28355 +               :
28356 +               : "d15", "a3", "memory", "cc"
28357 +       );
28358 +
28359 +       return dest_ret;
28360 +}
28361 +
28362 +/*
28363 + * memset()
28364 + */
28365 +void *memset(void *s, int c, size_t n)
28366 +{
28367 +       void *s_ret = s;
28368 +
28369 +       if (LIKELY(n > 6)) {
28370 +               size_t m;
28371 +               n -= (4 - (addr_t)s) & 0x03;
28372 +               m = n >> 2;
28373 +               asm volatile (
28374 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28375 +               "       and.4           d15, #(32-1), d15       \n\t"   // d15 = (-m) & (32 - 1)
28376 +               "       shmrg.1         %1, %1, %1              \n\t"
28377 +               "       shmrg.2         %1, %1, %1              \n\t"   // %1 = (c<<24)|(c<<16)|(c<<8)|c
28378 +               "       moveai          a3, #%%hi(1f)           \n\t"
28379 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28380 +               "       lea.4           a3, (a3,d15)            \n\t"
28381 +
28382 +               "       bfextu          d15, %0, #2             \n\t"   // d15 = (s & 3)
28383 +               "       jmpne.w.f       100f                    \n\t"
28384 +               "       calli           a3, 0(a3)               \n\t"   // 4-byte alignment
28385 +
28386 +               "100:   cmpi            d15, #2                 \n\t"
28387 +               "       jmpne.s.f       101f                    \n\t"
28388 +               "       move.2          (%0)2++, %1             \n\t"
28389 +               "       calli           a3, 0(a3)               \n\t"   // 2-byte alignment
28390 +
28391 +               "101:   move.1          (%0)1++, %1             \n\t"
28392 +               "       jmpgt.s.f       102f                    \n\t"   // 3-byte alignment
28393 +               "       move.2          (%0)2++, %1             \n\t"   // 1-byte alignment
28394 +               "102:   calli           a3, 0(a3)               \n\t"
28395 +
28396 +               "200:   cmpi            %3, #2                  \n\t"
28397 +               "       jmplt.s.f       201f                    \n\t"
28398 +               "       move.2          (%0)2++, %1             \n\t"
28399 +               "       jmpeq.s.t       2f                      \n\t"
28400 +               "201:   move.1          (%0)1++, %1             \n\t"
28401 +               "       jmpt.w.t        2f                      \n\t"
28402 +
28403 +               "1:     .rept           25                      \n\t"
28404 +               "       movea           (%0)4++, %1             \n\t"
28405 +               "       .endr                                   \n\t"
28406 +               "       .rept           7                       \n\t"
28407 +               "       move.4          (%0)4++, %1             \n\t"
28408 +               "       .endr                                   \n\t"
28409 +               "       add.4           %2, #-32, %2            \n\t"
28410 +               "       jmpgt.w.f       1b                      \n\t"
28411 +
28412 +               "       and.4           %3, #3, %3              \n\t"   // test bit 1 of n
28413 +               "       jmpne.w.f       200b                    \n\t"
28414 +               "2:                                             \n\t"
28415 +
28416 +                       : "+a" (s), "+d" (c), "+d" (m), "+d" (n)
28417 +                       :
28418 +                       : "d15", "a3", "memory", "cc"
28419 +               );
28420 +
28421 +               return s_ret;
28422 +       }
28423 +
28424 +       asm volatile (
28425 +       "       sub.4           d15, #0, %2             \n\t"
28426 +       "       jmpeq.w.f       2f                      \n\t"
28427 +       "       and.4           d15, #(8-1), d15        \n\t"   // d15 = (-%2) & (16 - 1)
28428 +       "       moveai          a3, #%%hi(1f)           \n\t"
28429 +       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28430 +       "       lea.4           a3, (a3,d15)            \n\t"
28431 +       "       calli           a3, 0(a3)               \n\t"
28432 +
28433 +       "1:     .rept           8                       \n\t"
28434 +       "       move.1          (%0)1++, %1             \n\t"
28435 +       "       .endr                                   \n\t"
28436 +       "2:                                             \n\t"
28437 +
28438 +               : "+a" (s), "+d" (c), "+d" (n)
28439 +               :
28440 +               : "d15", "a3", "memory", "cc"
28441 +       );
28442 +
28443 +       return s_ret;
28444 +}
28445 +
28446 +void *memmove(void *dest, const void *src, size_t n)
28447 +{
28448 +       char *tmp;
28449 +       const char *s;
28450 +
28451 +       if (n == 0)
28452 +               return dest;
28453 +
28454 +       tmp = dest;
28455 +       s = src;
28456 +
28457 +       /*
28458 +        * Will perform 16-bit move if possible
28459 +        */
28460 +       if (likely((((u32)dest | (u32)src | n) & 1) == 0)) {
28461 +               if (dest <= src) {
28462 +                       asm volatile (
28463 +                       "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28464 +                       "       and.4           d15, #(32-2), d15       \n\t"   // d15 = (- count) & (32 - 2)
28465 +                       "       moveai          a3, #%%hi(1f)           \n\t"
28466 +                       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28467 +                       "       lea.2           a3, (a3,d15)            \n\t"
28468 +                       "       calli           a3, 0(a3)               \n\t"
28469 +
28470 +                       "1:     .rept           16                      \n\t"
28471 +                       "       move.2          (%0)2++, (%1)2++        \n\t"
28472 +                       "       .endr                                   \n\t"
28473 +                       "       add.4           %2, #-32, %2            \n\t"
28474 +                       "       jmpgt.w.f       1b                      \n\t"
28475 +
28476 +                       : "+a" (tmp), "+a" (s), "+d" (n)
28477 +                       :
28478 +                       : "d15", "a3", "memory", "cc"
28479 +                       );
28480 +               } else {
28481 +                       tmp += n;
28482 +                       s += n;
28483 +                       asm volatile (
28484 +                       "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28485 +                       "       and.4           d15, #(32-2), d15       \n\t"   // d15 = (- count) & (32 - 2)
28486 +                       "       moveai          a3, #%%hi(1f)           \n\t"
28487 +                       "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28488 +                       "       lea.2           a3, (a3,d15)            \n\t"
28489 +                       "       calli           a3, 0(a3)               \n\t"
28490 +
28491 +                       "1:     .rept           16                      \n\t"
28492 +                       "       move.2          -2(%0)++, -2(%1)++      \n\t"
28493 +                       "       .endr                                   \n\t"
28494 +                       "       add.4           %2, #-32, %2            \n\t"
28495 +                       "       jmpgt.w.f       1b                      \n\t"
28496 +
28497 +                       : "+a" (tmp), "+a" (s), "+d" (n)
28498 +                       :
28499 +                       : "d15", "a3", "memory", "cc"
28500 +                       );
28501 +               }
28502 +               return dest;
28503 +       }
28504 +
28505 +       if (dest <= src) {
28506 +               asm volatile (
28507 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28508 +               "       and.4           d15, #(16-1), d15       \n\t"   // d15 = (- count) & (16 - 1)
28509 +               "       moveai          a3, #%%hi(1f)           \n\t"
28510 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28511 +               "       lea.4           a3, (a3,d15)            \n\t"
28512 +               "       calli           a3, 0(a3)               \n\t"
28513 +
28514 +               "1:     .rept           16                      \n\t"
28515 +               "       move.1          (%0)1++, (%1)1++        \n\t"
28516 +               "       .endr                                   \n\t"
28517 +               "       add.4           %2, #-16, %2            \n\t"
28518 +               "       jmpgt.w.f       1b                      \n\t"
28519 +               : "+a" (tmp), "+a" (s), "+d" (n)
28520 +               :
28521 +               : "d15", "a3", "memory", "cc"
28522 +               );
28523 +       } else {
28524 +               tmp += n;
28525 +               s += n;
28526 +               asm volatile (
28527 +               "       sub.4           d15, #0, %2             \n\t"   // set up for jump table
28528 +               "       and.4           d15, #(16-1), d15       \n\t"   // d15 = (- count) & (16 - 1)
28529 +               "       moveai          a3, #%%hi(1f)           \n\t"
28530 +               "       lea.1           a3, %%lo(1f)(a3)        \n\t"
28531 +               "       lea.4           a3, (a3,d15)            \n\t"
28532 +               "       calli           a3, 0(a3)               \n\t"
28533 +
28534 +               "1:     .rept           16                      \n\t"
28535 +               "       move.1          -1(%0)++, -1(%1)++      \n\t"
28536 +               "       .endr                                   \n\t"
28537 +               "       add.4           %2, #-16, %2            \n\t"
28538 +               "       jmpgt.w.f       1b                      \n\t"
28539 +               : "+a" (tmp), "+a" (s), "+d" (n)
28540 +               :
28541 +               : "d15", "a3", "memory", "cc"
28542 +               );
28543 +       }
28544 +       return dest;
28545 +}
28546 --- /dev/null
28547 +++ b/arch/ubicom32/mach-common/audio.c
28548 @@ -0,0 +1,134 @@
28549 +/*
28550 + * arch/ubicom32/mach-common/audio.c
28551 + *   Generic initialization for Ubicom32 Audio
28552 + *
28553 + * (C) Copyright 2009, Ubicom, Inc.
28554 + *
28555 + * This file is part of the Ubicom32 Linux Kernel Port.
28556 + *
28557 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28558 + * it and/or modify it under the terms of the GNU General Public License
28559 + * as published by the Free Software Foundation, either version 2 of the
28560 + * License, or (at your option) any later version.
28561 + *
28562 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28563 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28564 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28565 + * the GNU General Public License for more details.
28566 + *
28567 + * You should have received a copy of the GNU General Public License
28568 + * along with the Ubicom32 Linux Kernel Port.  If not,
28569 + * see <http://www.gnu.org/licenses/>.
28570 + */
28571 +
28572 +#include <linux/platform_device.h>
28573 +#include <linux/types.h>
28574 +
28575 +#include <asm/devtree.h>
28576 +#include <asm/audio.h>
28577 +#include <asm/ubi32-pcm.h>
28578 +
28579 +/*
28580 + * The number of audio devices currently allocated, used for .id
28581 + */
28582 +static int __initdata audio_device_count;
28583 +
28584 +/*
28585 + * The maximum number of resources (cards) that the audio will have.
28586 + * Currently 3, a register space, and up to 2 interrupts.
28587 + */
28588 +#define AUDIO_MAX_RESOURCES    3
28589 +
28590 +/*
28591 + * audio_device_alloc
28592 + *     Checks the device tree and allocates a platform_device if found
28593 + */
28594 +struct platform_device * __init audio_device_alloc(const char *driver_name,
28595 +               const char *node_name, const char *inst_name, int priv_bytes)
28596 +{
28597 +       struct platform_device *pdev;
28598 +       struct resource *res;
28599 +       struct audio_node *audio_node;
28600 +       struct ubi32pcm_platform_data *pdata;
28601 +       struct audio_dev_regs *adr;
28602 +       int idx;
28603 +
28604 +       /*
28605 +        * Check the device tree for the audio node
28606 +        */
28607 +       audio_node = (struct audio_node *)devtree_find_node(node_name);
28608 +       if (!audio_node) {
28609 +               printk(KERN_WARNING "audio device '%s' not found\n", node_name);
28610 +               return NULL;
28611 +       }
28612 +
28613 +       if (audio_node->version != AUDIONODE_VERSION) {
28614 +               printk(KERN_WARNING "audio node not compatible\n");
28615 +               return NULL;
28616 +       }
28617 +
28618 +       /*
28619 +        * Find the instance in this node
28620 +        */
28621 +       adr = audio_node->regs->adr;
28622 +       for (idx = 0; idx < audio_node->regs->max_devs; idx++) {
28623 +               if ((adr->version == AUDIO_DEV_REGS_VERSION) &&
28624 +                  (strcmp(adr->name, inst_name) == 0)) {
28625 +                       break;
28626 +               }
28627 +               adr++;
28628 +       }
28629 +       if (idx == audio_node->regs->max_devs) {
28630 +               printk(KERN_WARNING "audio inst '%s' not found in device '%s'\n", inst_name, node_name);
28631 +               return NULL;
28632 +       }
28633 +
28634 +       /*
28635 +        * Dynamically create the platform_device structure and resources
28636 +        */
28637 +       pdev = kzalloc(sizeof(struct platform_device) +
28638 +                      sizeof(struct ubi32pcm_platform_data) +
28639 +                      priv_bytes , GFP_KERNEL);
28640 +       if (!pdev) {
28641 +               printk(KERN_WARNING "audio could not alloc pdev\n");
28642 +               return NULL;
28643 +       }
28644 +
28645 +       res = kzalloc(sizeof(struct resource) * AUDIO_MAX_RESOURCES,
28646 +                       GFP_KERNEL);
28647 +       if (!res) {
28648 +               kfree(pdev);
28649 +               printk(KERN_WARNING "audio could not alloc res\n");
28650 +               return NULL;
28651 +       }
28652 +
28653 +       pdev->name = driver_name;
28654 +       pdev->id = audio_device_count++;
28655 +       pdev->resource = res;
28656 +
28657 +       /*
28658 +        * Fill in the resources and platform data from devtree information
28659 +        */
28660 +       res[0].start = (u32_t)(audio_node->regs);
28661 +       res[0].end = (u32_t)(audio_node->regs);
28662 +       res[0].flags = IORESOURCE_MEM;
28663 +       res[1 + AUDIO_TX_IRQ_RESOURCE].start = audio_node->dn.sendirq;
28664 +       res[1 + AUDIO_TX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28665 +       res[1 + AUDIO_RX_IRQ_RESOURCE].start = audio_node->dn.recvirq;
28666 +       res[1 + AUDIO_RX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28667 +       pdev->num_resources = 3;
28668 +
28669 +       printk(KERN_INFO "Audio.%d '%s':'%s' found irq=%d/%d.%d regs=%p pdev=%p/%p\n",
28670 +               pdev->id, node_name, inst_name, audio_node->dn.sendirq,
28671 +               audio_node->dn.recvirq, idx, audio_node->regs, pdev, res);
28672 +       pdata = (struct ubi32pcm_platform_data *)(pdev + 1);
28673 +       pdev->dev.platform_data = pdata;
28674 +       pdata->node_name = node_name;
28675 +       pdata->inst_name = inst_name;
28676 +       pdata->inst_num = idx;
28677 +       if (priv_bytes) {
28678 +               pdata->priv_data = pdata + 1;
28679 +       }
28680 +
28681 +       return pdev;
28682 +}
28683 --- /dev/null
28684 +++ b/arch/ubicom32/mach-common/board.c
28685 @@ -0,0 +1,63 @@
28686 +/*
28687 + * arch/ubicom32/mach-common/board.c
28688 + *   Board init and support code.
28689 + *
28690 + * (C) Copyright 2009, Ubicom, Inc.
28691 + *
28692 + * This file is part of the Ubicom32 Linux Kernel Port.
28693 + *
28694 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28695 + * it and/or modify it under the terms of the GNU General Public License
28696 + * as published by the Free Software Foundation, either version 2 of the
28697 + * License, or (at your option) any later version.
28698 + *
28699 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28700 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28701 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28702 + * the GNU General Public License for more details.
28703 + *
28704 + * You should have received a copy of the GNU General Public License
28705 + * along with the Ubicom32 Linux Kernel Port.  If not,
28706 + * see <http://www.gnu.org/licenses/>.
28707 + *
28708 + * Ubicom32 implementation derived from (with many thanks):
28709 + *   arch/m68knommu
28710 + *   arch/blackfin
28711 + *   arch/parisc
28712 + */
28713 +#include <linux/module.h>
28714 +#include <linux/types.h>
28715 +#include <linux/cpu.h>
28716 +#include <asm/devtree.h>
28717 +
28718 +struct boardnode {
28719 +       struct devtree_node dn;
28720 +       const char *revision;
28721 +};
28722 +
28723 +static const struct boardnode *bn;
28724 +
28725 +/*
28726 + * board_get_revision()
28727 + *     Returns revision string of the board.
28728 + */
28729 +const char *board_get_revision(void)
28730 +{
28731 +       if (!bn) {
28732 +               return "NULL";
28733 +       }
28734 +
28735 +       return bn->revision;
28736 +}
28737 +
28738 +/*
28739 + * board_init
28740 + */
28741 +void __init board_init(void)
28742 +{
28743 +       bn = (struct boardnode *)devtree_find_node("board");
28744 +       if (!bn) {
28745 +               printk(KERN_WARNING "board node not found\n");
28746 +               return;
28747 +       }
28748 +}
28749 --- /dev/null
28750 +++ b/arch/ubicom32/mach-common/bootargs.c
28751 @@ -0,0 +1,63 @@
28752 +/*
28753 + * arch/ubicom32/mach-common/bootargs.c
28754 + *   Board init and support code.
28755 + *
28756 + * (C) Copyright 2009, Ubicom, Inc.
28757 + *
28758 + * This file is part of the Ubicom32 Linux Kernel Port.
28759 + *
28760 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28761 + * it and/or modify it under the terms of the GNU General Public License
28762 + * as published by the Free Software Foundation, either version 2 of the
28763 + * License, or (at your option) any later version.
28764 + *
28765 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28766 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28767 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28768 + * the GNU General Public License for more details.
28769 + *
28770 + * You should have received a copy of the GNU General Public License
28771 + * along with the Ubicom32 Linux Kernel Port.  If not,
28772 + * see <http://www.gnu.org/licenses/>.
28773 + *
28774 + * Ubicom32 implementation derived from (with many thanks):
28775 + *   arch/m68knommu
28776 + *   arch/blackfin
28777 + *   arch/parisc
28778 + */
28779 +#include <linux/module.h>
28780 +#include <linux/types.h>
28781 +#include <linux/cpu.h>
28782 +#include <asm/devtree.h>
28783 +
28784 +struct bootargsnode {
28785 +       struct devtree_node dn;
28786 +       const char cmdline[512];
28787 +};
28788 +
28789 +static const struct bootargsnode *ban;
28790 +
28791 +/*
28792 + * bootargs_get_cmdline()
28793 + *     Returns kernel boot arguments set by the bootloader.
28794 + */
28795 +const char *bootargs_get_cmdline(void)
28796 +{
28797 +       if (!ban) {
28798 +               return "";
28799 +       }
28800 +
28801 +       return ban->cmdline;
28802 +}
28803 +
28804 +/*
28805 + * bootargs_init
28806 + */
28807 +void __init bootargs_init(void)
28808 +{
28809 +       ban = (struct bootargsnode *)devtree_find_node("bootargs");
28810 +       if (!ban) {
28811 +               printk(KERN_WARNING "bootargs node not found\n");
28812 +               return;
28813 +       }
28814 +}
28815 --- /dev/null
28816 +++ b/arch/ubicom32/mach-common/cachectl.c
28817 @@ -0,0 +1,136 @@
28818 +/*
28819 + * arch/ubicom32/mach-common/cachectl.c
28820 + *   Architecture cache control support
28821 + *
28822 + * (C) Copyright 2009, Ubicom, Inc.
28823 + *
28824 + * This file is part of the Ubicom32 Linux Kernel Port.
28825 + *
28826 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28827 + * it and/or modify it under the terms of the GNU General Public License
28828 + * as published by the Free Software Foundation, either version 2 of the
28829 + * License, or (at your option) any later version.
28830 + *
28831 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28832 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28833 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28834 + * the GNU General Public License for more details.
28835 + *
28836 + * You should have received a copy of the GNU General Public License
28837 + * along with the Ubicom32 Linux Kernel Port.  If not,
28838 + * see <http://www.gnu.org/licenses/>.
28839 + *
28840 + * Ubicom32 implementation derived from (with many thanks):
28841 + *   arch/m68knommu
28842 + *   arch/blackfin
28843 + *   arch/parisc
28844 + */
28845 +
28846 +#include <linux/types.h>
28847 +#include <linux/module.h>
28848 +#include <asm/cachectl.h>
28849 +
28850 +/*
28851 + * The write queue flush procedure in mem_cache_control needs to make
28852 + * DCACHE_WRITE_QUEUE_LENGTH writes to DDR (not OCM). Here we reserve some
28853 + * memory for this operation.
28854 + * Allocate array of cache lines of least DCACHE_WRITE_QUEUE_LENGTH + 1 words in
28855 + * length rounded up to the nearest cache line.
28856 + */
28857 +#define CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE \
28858 +       ALIGN(sizeof(int) * (DCACHE_WRITE_QUEUE_LENGTH + 1), CACHE_LINE_SIZE)
28859 +
28860 +static char cache_write_queue_flush_area[CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE]
28861 +       __attribute__((aligned(CACHE_LINE_SIZE)));
28862 +
28863 +/*
28864 + * ONE_CCR_ADDR_OP is a helper macro that executes a single CCR operation.
28865 + */
28866 +#define ONE_CCR_ADDR_OP(cc, op_addr, op)                               \
28867 +       do {                                                            \
28868 +               asm volatile (                                          \
28869 +               "       btst    "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)"                         \n\t" \
28870 +               "       jmpne.f .-4                                                             \n\t" \
28871 +               "       move.4  "D(CCR_ADDR)"(%0), %1                                           \n\t" \
28872 +               "       move.1  "D(CCR_CTRL+3)"(%0), %2                                         \n\t" \
28873 +               "       bset    "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)"      \n\t" \
28874 +               "       cycles  2                                                               \n\t" \
28875 +               "       btst    "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_DONE)"                          \n\t" \
28876 +               "       jmpeq.f .-4                                                             \n\t" \
28877 +                       :                                               \
28878 +                       : "a"(cc), "r"(op_addr), "r"(op & 0xff)         \
28879 +                       : "cc"                                          \
28880 +               );                                                      \
28881 +       } while (0)
28882 +
28883 +/*
28884 + * mem_cache_control()
28885 + *     Special cache control operation
28886 + */
28887 +void mem_cache_control(unsigned long cc, unsigned long begin_addr,
28888 +                      unsigned long end_addr, unsigned long op)
28889 +{
28890 +       unsigned long op_addr;
28891 +       int dccr = cc == DCCR_BASE;
28892 +       if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
28893 +               /*
28894 +                * We ensure all previous writes have left the data cache write
28895 +                * queue by sending DCACHE_WRITE_QUEUE_LENGTH writes (to
28896 +                * different words) down the queue.  If this is not done it's
28897 +                * possible that the data we are trying to flush hasn't even
28898 +                * entered the data cache.
28899 +                * The +1 ensure that the final 'flush' is actually a flush.
28900 +                */
28901 +               int *flush_area = (int *)cache_write_queue_flush_area;
28902 +               asm volatile(
28903 +                       "       .rept "D(DCACHE_WRITE_QUEUE_LENGTH + 1)"        \n\t"
28904 +                       "       move.4 (%0)4++, d0                              \n\t"
28905 +                       "       .endr                                           \n\t"
28906 +                       : "+a"(flush_area)
28907 +                       );
28908 +       }
28909 +
28910 +       if (dccr)
28911 +               UBICOM32_LOCK(DCCR_LOCK_BIT);
28912 +       else
28913 +               UBICOM32_LOCK(ICCR_LOCK_BIT);
28914 +
28915 +       /*
28916 +        * Calculate the cache lines we need to operate on that include
28917 +        * begin_addr though end_addr.
28918 +        */
28919 +       begin_addr = begin_addr & ~(CACHE_LINE_SIZE - 1);
28920 +       end_addr = (end_addr + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
28921 +       op_addr = begin_addr;
28922 +
28923 +       do {
28924 +               ONE_CCR_ADDR_OP(cc, op_addr, op);
28925 +               op_addr += CACHE_LINE_SIZE;
28926 +       } while (likely(op_addr < end_addr));
28927 +
28928 +       if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
28929 +               /*
28930 +                * It turns out that when flushing the data cache the last flush
28931 +                * isn't actually complete at this point. This is because there
28932 +                * is another write buffer on the DDR side of the cache that is
28933 +                * arbitrated with the I-Cache.
28934 +                *
28935 +                * The only foolproof method that ensures that the last data
28936 +                * cache flush *actually* completed is to do another flush on a
28937 +                * dirty cache line. This flush will block until the DDR write
28938 +                * buffer is empty.
28939 +                *
28940 +                * Rather than creating a another dirty cache line, we use the
28941 +                * flush_area above as we know that it is dirty from previous
28942 +                * writes.
28943 +                */
28944 +               ONE_CCR_ADDR_OP(cc, cache_write_queue_flush_area, op);
28945 +       }
28946 +
28947 +       if (dccr)
28948 +               UBICOM32_UNLOCK(DCCR_LOCK_BIT);
28949 +       else
28950 +               UBICOM32_UNLOCK(ICCR_LOCK_BIT);
28951 +
28952 +}
28953 +EXPORT_SYMBOL(mem_cache_control);
28954 --- /dev/null
28955 +++ b/arch/ubicom32/mach-common/common.c
28956 @@ -0,0 +1,64 @@
28957 +/*
28958 + * arch/ubicom32/mach-common/common.c
28959 + *   Common platform support.
28960 + *
28961 + * (C) Copyright 2009, Ubicom, Inc.
28962 + *
28963 + * This file is part of the Ubicom32 Linux Kernel Port.
28964 + *
28965 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28966 + * it and/or modify it under the terms of the GNU General Public License
28967 + * as published by the Free Software Foundation, either version 2 of the
28968 + * License, or (at your option) any later version.
28969 + *
28970 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28971 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28972 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
28973 + * the GNU General Public License for more details.
28974 + *
28975 + * You should have received a copy of the GNU General Public License
28976 + * along with the Ubicom32 Linux Kernel Port.  If not,
28977 + * see <http://www.gnu.org/licenses/>.
28978 + *
28979 + * Ubicom32 implementation derived from (with many thanks):
28980 + *   arch/m68knommu
28981 + *   arch/blackfin
28982 + *   arch/parisc
28983 + */
28984 +#include <linux/version.h>
28985 +#include <linux/kernel.h>
28986 +#include <linux/init.h>
28987 +#include <linux/module.h>
28988 +#include <linux/list.h>
28989 +#include <linux/errno.h>
28990 +#include <linux/err.h>
28991 +#include <linux/string.h>
28992 +#include <linux/clk.h>
28993 +#include <linux/mutex.h>
28994 +#include <linux/platform_device.h>
28995 +
28996 +
28997 +/* Minimum CLK support */
28998 +
28999 +struct clk *clk_get(struct device *dev, const char *id)
29000 +{
29001 +       return ERR_PTR(-ENOENT);
29002 +}
29003 +EXPORT_SYMBOL(clk_get);
29004 +
29005 +void clk_put(struct clk *clk)
29006 +{
29007 +}
29008 +EXPORT_SYMBOL(clk_put);
29009 +
29010 +int clk_enable(struct clk *clk)
29011 +{
29012 +       return 0;
29013 +}
29014 +EXPORT_SYMBOL(clk_enable);
29015 +
29016 +
29017 +void clk_disable(struct clk *clk)
29018 +{
29019 +}
29020 +EXPORT_SYMBOL(clk_disable);
29021 --- /dev/null
29022 +++ b/arch/ubicom32/mach-common/io.c
29023 @@ -0,0 +1,250 @@
29024 +/*
29025 + * arch/ubicom32/mach-common/io.c
29026 + *   PCI I/O memory read/write support functions.
29027 + *
29028 + * (C) Copyright 2009, Ubicom, Inc.
29029 + *
29030 + * This file is part of the Ubicom32 Linux Kernel Port.
29031 + *
29032 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29033 + * it and/or modify it under the terms of the GNU General Public License
29034 + * as published by the Free Software Foundation, either version 2 of the
29035 + * License, or (at your option) any later version.
29036 + *
29037 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29038 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29039 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29040 + * the GNU General Public License for more details.
29041 + *
29042 + * You should have received a copy of the GNU General Public License
29043 + * along with the Ubicom32 Linux Kernel Port.  If not,
29044 + * see <http://www.gnu.org/licenses/>.
29045 + *
29046 + * Ubicom32 implementation derived from (with many thanks):
29047 + *   arch/m68knommu
29048 + *   arch/blackfin
29049 + *   arch/parisc
29050 + */
29051 +#include <linux/module.h>
29052 +#include <linux/kernel.h>
29053 +#include <linux/io.h>
29054 +
29055 +#ifdef CONFIG_PCI
29056 +unsigned char  ioread8(void __iomem *addr)
29057 +{
29058 +       if (IS_PCI_ADDRESS(addr))
29059 +               return ubi32_pci_read_u8(addr);
29060 +       else
29061 +               return (unsigned char)(*(volatile unsigned char *)addr);
29062 +}
29063 +EXPORT_SYMBOL(ioread8);
29064 +
29065 +unsigned short  ioread16(void __iomem *addr)
29066 +{
29067 +       if (IS_PCI_ADDRESS(addr))
29068 +               return ubi32_pci_read_u16(addr);
29069 +       else
29070 +               return (unsigned short)(*(volatile unsigned short *)addr);
29071 +}
29072 +EXPORT_SYMBOL(ioread16);
29073 +
29074 +unsigned int  ioread32(void __iomem *addr)
29075 +{
29076 +       if (IS_PCI_ADDRESS(addr))
29077 +               return ubi32_pci_read_u32(addr);
29078 +       else
29079 +               return (unsigned int)(*(volatile unsigned int *)addr);
29080 +}
29081 +EXPORT_SYMBOL(ioread32);
29082 +
29083 +void iowrite32(unsigned int val, void __iomem *addr)
29084 +{
29085 +       if (IS_PCI_ADDRESS(addr))
29086 +               ubi32_pci_write_u32(val, addr);
29087 +       else
29088 +               *(volatile unsigned int *)addr = val;
29089 +}
29090 +EXPORT_SYMBOL(iowrite32);
29091 +
29092 +void iowrite16(unsigned short val, void __iomem *addr)
29093 +{
29094 +       if (IS_PCI_ADDRESS(addr))
29095 +               ubi32_pci_write_u16(val, addr);
29096 +       else
29097 +               *(volatile unsigned short *)addr = val;
29098 +}
29099 +EXPORT_SYMBOL(iowrite16);
29100 +
29101 +void iowrite8(unsigned char val, void __iomem *addr)
29102 +{
29103 +       if (IS_PCI_ADDRESS(addr))
29104 +               ubi32_pci_write_u8(val, addr);
29105 +       else
29106 +               *(volatile unsigned char *)addr = val;
29107 +}
29108 +EXPORT_SYMBOL(iowrite8);
29109 +
29110 +void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len)
29111 +{
29112 +       if (IS_PCI_ADDRESS(from)) {
29113 +               if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29114 +                       while ((int)len >= 4) {
29115 +                               *(u32_t *)to = ubi32_pci_read_u32(from);
29116 +                               to += 4;
29117 +                               from += 4;
29118 +                               len -= 4;
29119 +                       }
29120 +               } else if ((((u32_t)from & 0x1) == 0) &&
29121 +                          (((u32_t)to & 0x1) == 0)) {
29122 +                       while ((int)len >= 2) {
29123 +                                *(u16_t *)to = ubi32_pci_read_u16(from);
29124 +                                to += 2;
29125 +                                from += 2;
29126 +                                len -= 2;
29127 +                       }
29128 +               }
29129 +
29130 +               while (len) {
29131 +                       *(u8_t *)to = ubi32_pci_read_u8(from);
29132 +                       to++;
29133 +                       from++;
29134 +                       len--;
29135 +               }
29136 +       } else
29137 +               memcpy(to, (void *)from, len);
29138 +}
29139 +EXPORT_SYMBOL(memcpy_fromio);
29140 +
29141 +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len)
29142 +{
29143 +       if (IS_PCI_ADDRESS(to)) {
29144 +               if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29145 +                       while ((int)len >= 4) {
29146 +                               ubi32_pci_write_u32(*(u32_t *)from, to);
29147 +                               to += 4;
29148 +                               from += 4;
29149 +                               len -= 4;
29150 +                       }
29151 +               } else if ((((u32_t)from & 0x1) == 0) &&
29152 +                          (((u32_t)to & 0x1) == 0)) {
29153 +                       while ((int)len >= 2) {
29154 +                               ubi32_pci_write_u16(*(u16_t *)from, to);
29155 +                               to += 2;
29156 +                               from += 2;
29157 +                               len -= 2;
29158 +                       }
29159 +               }
29160 +
29161 +               while (len) {
29162 +                       ubi32_pci_write_u8(*(u8_t *)from, to);
29163 +                       from++;
29164 +                       to++;
29165 +                       len--;
29166 +               }
29167 +       } else
29168 +               memcpy((void *)to, from, len);
29169 +
29170 +}
29171 +EXPORT_SYMBOL(memcpy_toio);
29172 +
29173 +void memset_io(volatile void __iomem *addr, int val, size_t len)
29174 +{
29175 +       if (IS_PCI_ADDRESS(addr)) {
29176 +               while (len) {
29177 +                       ubi32_pci_write_u8((unsigned char)val, addr);
29178 +                       addr++;
29179 +                       len--;
29180 +               }
29181 +       } else
29182 +               memset((void *)addr, val, len);
29183 +
29184 +}
29185 +EXPORT_SYMBOL(memset_io);
29186 +
29187 +void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
29188 +{
29189 +       if (IS_PCI_ADDRESS(port)) {
29190 +               while (count) {
29191 +                       *(u8_t *)buf = ioread8(port);
29192 +                       buf++;
29193 +                       count--;
29194 +               }
29195 +       } else {
29196 +               insb((unsigned int)port, buf, count);
29197 +       }
29198 +
29199 +}
29200 +EXPORT_SYMBOL(ioread8_rep);
29201 +
29202 +void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
29203 +{
29204 +       if (IS_PCI_ADDRESS(port)) {
29205 +               while (count) {
29206 +                       *(u16_t *)buf = ioread16(port);
29207 +                       buf += 2;
29208 +                       count--;
29209 +               }
29210 +       } else {
29211 +               insw((unsigned int)port, buf, count);
29212 +       }
29213 +}
29214 +EXPORT_SYMBOL(ioread16_rep);
29215 +
29216 +void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
29217 +{
29218 +        if (IS_PCI_ADDRESS(port)) {
29219 +               while (count) {
29220 +                       *(u32_t *)buf = ioread32(port);
29221 +                       buf += 4;
29222 +                       count--;
29223 +               }
29224 +       } else {
29225 +               insl((unsigned int)port, buf, count);
29226 +       }
29227 +}
29228 +EXPORT_SYMBOL(ioread32_rep);
29229 +
29230 +void  iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
29231 +{
29232 +         if (IS_PCI_ADDRESS(port)) {
29233 +               while (count) {
29234 +                       iowrite8(*(u8_t *)buf, port);
29235 +                       buf++;
29236 +                       count--;
29237 +               }
29238 +       } else {
29239 +               outsb((unsigned int)port, buf, count);
29240 +       }
29241 +
29242 +}
29243 +EXPORT_SYMBOL(iowrite8_rep);
29244 +
29245 +void  iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
29246 +{
29247 +       if (IS_PCI_ADDRESS(port)) {
29248 +               while (count) {
29249 +                       iowrite16(*(u16_t *)buf, port);
29250 +                       buf += 2;
29251 +                       count--;
29252 +               }
29253 +       } else {
29254 +               outsw((unsigned int)port, buf, count);
29255 +       }
29256 +}
29257 +EXPORT_SYMBOL(iowrite16_rep);
29258 +
29259 +void  iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
29260 +{
29261 +       if (IS_PCI_ADDRESS(port)) {
29262 +               while (count) {
29263 +                       iowrite32(*(u32_t *)buf, port);
29264 +                       buf += 4;
29265 +                       count--;
29266 +               }
29267 +       } else {
29268 +               outsl((unsigned int)port, buf, count);
29269 +       }
29270 +}
29271 +EXPORT_SYMBOL(iowrite32_rep);
29272 +
29273 +#endif /* CONFIG_PCI */
29274 --- /dev/null
29275 +++ b/arch/ubicom32/mach-common/Kconfig.switch
29276 @@ -0,0 +1,12 @@
29277 +menuconfig UBICOM_SWITCH
29278 +       tristate "Switch devices"
29279 +       help
29280 +               This option provides Ethernet switch management options via proc fs
29281 +
29282 +if UBICOM_SWITCH
29283 +config UBICOM_SWITCH_BCM539X
29284 +       tristate "Broadcom BCM539X series (SPI)"
29285 +       depends on SPI_MASTER
29286 +       help
29287 +               Supports Broadcom BCM539X Gigabit Ethernet Switches over SPI
29288 +endif
29289 --- /dev/null
29290 +++ b/arch/ubicom32/mach-common/Makefile
29291 @@ -0,0 +1,41 @@
29292 +#
29293 +# arch/ubicom32/mach-common/Makefile
29294 +#      Makefile for Ubicom32 generic drivers/code.
29295 +#
29296 +# (C) Copyright 2009, Ubicom, Inc.
29297 +#
29298 +# This file is part of the Ubicom32 Linux Kernel Port.
29299 +#
29300 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
29301 +# it and/or modify it under the terms of the GNU General Public License
29302 +# as published by the Free Software Foundation, either version 2 of the
29303 +# License, or (at your option) any later version.
29304 +#
29305 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
29306 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
29307 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29308 +# the GNU General Public License for more details.
29309 +#
29310 +# You should have received a copy of the GNU General Public License
29311 +# along with the Ubicom32 Linux Kernel Port.  If not,
29312 +# see <http://www.gnu.org/licenses/>.
29313 +#
29314 +# Ubicom32 implementation derived from (with many thanks):
29315 +#   arch/m68knommu
29316 +#   arch/blackfin
29317 +#   arch/parisc
29318 +#
29319 +
29320 +obj-y += cachectl.o common.o usb_tio.o usb.o ubi32-gpio.o board.o bootargs.o profile.o
29321 +obj-$(CONFIG_PCI) += pci.o io.o
29322 +
29323 +obj-$(CONFIG_FB_UBICOM32) += vdc_tio.o
29324 +obj-$(CONFIG_UBICOM_HID) += ubicom32hid.o
29325 +obj-$(CONFIG_UBICOM_INPUT) += ubicom32input.o
29326 +obj-$(CONFIG_UBICOM_INPUT_I2C) += ubicom32input_i2c.o
29327 +obj-$(CONFIG_UBICOM_SWITCH) += switch-core.o
29328 +obj-$(CONFIG_UBICOM_SWITCH_BCM539X) += switch-bcm539x.o
29329 +obj-$(CONFIG_UIO_UBICOM32RING) += ring_tio.o
29330 +obj-$(CONFIG_SND_UBI32) += audio.o
29331 +obj-$(CONFIG_UBICOM32_PLIO) += plio.o
29332 +
29333 --- /dev/null
29334 +++ b/arch/ubicom32/mach-common/pci.c
29335 @@ -0,0 +1,1157 @@
29336 +/*
29337 + * arch/ubicom32/mach-common/pci.c
29338 + *     PCI interface management.
29339 + *
29340 + * (C) Copyright 2009, Ubicom, Inc.
29341 + *
29342 + * This file is part of the Ubicom32 Linux Kernel Port.
29343 + *
29344 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29345 + * it and/or modify it under the terms of the GNU General Public License
29346 + * as published by the Free Software Foundation, either version 2 of the
29347 + * License, or (at your option) any later version.
29348 + *
29349 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29350 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29351 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
29352 + * the GNU General Public License for more details.
29353 + *
29354 + * You should have received a copy of the GNU General Public License
29355 + * along with the Ubicom32 Linux Kernel Port.  If not,
29356 + * see <http://www.gnu.org/licenses/>.
29357 + *
29358 + * Ubicom32 implementation derived from (with many thanks):
29359 + *   arch/m68knommu
29360 + *   arch/blackfin
29361 + *   arch/parisc
29362 + */
29363 +
29364 +#include <linux/module.h>
29365 +#include <linux/kernel.h>
29366 +#include <linux/pci.h>
29367 +#include <linux/slab.h>
29368 +#include <linux/init.h>
29369 +#include <linux/io.h>
29370 +#include <linux/seq_file.h>
29371 +#include <linux/proc_fs.h>
29372 +
29373 +#include <asm/devtree.h>
29374 +#include <asm/ip5000.h>
29375 +#include <asm/ubicom32-common.h>
29376 +
29377 +static int debug_pci = 1 ;
29378 +
29379 +/* #define PCI_USE_INTERNAL_LOCK 1 */
29380 +
29381 +#ifdef PCI_USE_INTERNAL_LOCK
29382 +#define PCI_LOCK(lock, irqflag)        pci_lock_acquire(irqflag)
29383 +#define PCI_UNLOCK(lock, irqflag) pci_lock_release(irqflag)
29384 +#elif defined(CONFIG_SMP)
29385 +static DEFINE_SPINLOCK(pci_master_lock);
29386 +#define PCI_LOCK(lock, irqflag)        spin_lock_irqsave(lock, irqflag)
29387 +#define PCI_UNLOCK(lock, irqflag) spin_unlock_irqrestore(lock, irqflag)
29388 +#else
29389 +#define PCI_LOCK(lock, irqflag)                local_irq_save(irqflag)
29390 +#define PCI_UNLOCK(lock, irqflag)      local_irq_restore(irqflag)
29391 +#endif
29392 +
29393 +#define PCI_DEV0_IDSEL CONFIG_PCI_DEV0_IDSEL
29394 +#define PCI_DEV1_IDSEL CONFIG_PCI_DEV1_IDSEL
29395 +
29396 +/*
29397 + * PCI commands
29398 + */
29399 +#define PCI_CMD_INT_ACK                0x00    /* not supported */
29400 +#define PCI_CMD_SPECIAL                0x01    /* not supported */
29401 +#define PCI_CMD_IO_READ                0x02
29402 +#define PCI_CMD_IO_WRITE       0x03
29403 +#define PCI_CMD_MEM_READ       0x06
29404 +#define PCI_CMD_MEM_WRITE      0x07
29405 +#define PCI_CMD_CFG_READ       0x0a
29406 +#define PCI_CMD_CFG_WRITE      0x0b
29407 +#define PCI_CMD_MEM_READ_MULT  0x0c    /* not supported */
29408 +#define PCI_CMD_DUAL_ADDR      0x0d    /* not supported */
29409 +#define PCI_CMD_MEM_READ_LINE  0x0e    /* not supported */
29410 +#define PCI_CMD_MEM_WRITE_INVAL        0x0f    /* not supported */
29411 +/*
29412 + * Status codes, returned by pci_read_u32() and pci_write_u32()
29413 + */
29414 +#define PCI_RESP_IN_PROGRESS   0xff  /* request still in queue */
29415 +#define PCI_RESP_OK            0
29416 +/*
29417 + * The following codes indicate that the request has completed
29418 + */
29419 +#define PCI_RESP_NO_DEVSEL             1  /* timeout before target asserted
29420 +                                           * DEVSEL! */
29421 +#define PCI_RESP_LOST_DEVSEL           2  /* had DEVSEL, but went away before
29422 +                                           * transfer completed! */
29423 +#define PCI_RESP_BAD_TRDY              3  /* target asserted TRDY without
29424 +                                           * DEVSEL! */
29425 +#define PCI_RESP_NO_TRDY               4  /* timeout before target asserted
29426 +                                           * TRDY! */
29427 +#define PCI_RESP_BAD_STOP              5  /* target asserted STOP and TRDY
29428 +                                           * without DEVSEL! */
29429 +#define PCI_RESP_TARGET_ABORT          6
29430 +#define PCI_RESP_TARGET_RETRY          7
29431 +#define        PCI_RESP_TARGET_DISCONNECT      8
29432 +#define PCI_RESP_MISMATCH              9  /* data read back doesn't match data
29433 +                                           * written - debug only, the core PCI
29434 +                                           * routines never return this */
29435 +#define PCI_RESP_DET_SERR              10
29436 +#define PCI_RESP_DET_PERR              11
29437 +#define PCI_RESP_MALFORMED_REQ         12 /* Could be due to misaligned
29438 +                                           * requests or invalid address */
29439 +#define PCI_RESP_NO_RESOURCE           13 /* Could be memory or other resourse
29440 +                                           * like queue space */
29441 +#define PCI_RESP_ERROR                 14 /* All emcompassing error */
29442 +
29443 +/* registers in PCI config space */
29444 +#define PCI_DEVICE_VENDOR_ID_REG       0x00
29445 +#define PCI_STATUS_COMMAND_REG         0x04
29446 +#define PCI_CLASS_REVISION_REG         0x08
29447 +#define PCI_BHLC_REG                   0x0c  /* BIST, Header type, Latency
29448 +                                              * timer, Cache line size */
29449 +#define PCI_BASE_ADDR_REG              0x10
29450 +#define PCI_BASE_REG_COUNT             6
29451 +#define CARDBUS_CIS_PTR_REG            0x28
29452 +#define PCI_SUB_SYSTEM_ID_REG          0x2c
29453 +#define PCI_EXP_ROM_ADDR_REG           0x30
29454 +#define PCI_CAP_PTR_REG                        0x34
29455 +#define PCI_LGPL_REG                   0x3C  /* max Latency, min Gnt, interrupt
29456 +                                              * Pin, interrupt Line */
29457 +
29458 +struct pci_master_request {
29459 +       volatile u32_t pci_address;     /* must be 4-byte aligned */
29460 +       volatile u32_t data;            /* must be 4-byte aligned */
29461 +       volatile u8_t cmd;
29462 +       volatile u8_t byte_valid;
29463 +       volatile u8_t status;
29464 +};
29465 +
29466 +struct pci_devnode {
29467 +       struct devtree_node dn;
29468 +       u32_t pci_idsel_0;
29469 +       u32_t pci_idsel_1;
29470 +       u32_t pci_cpu_address;
29471 +       struct pci_master_request volatile *volatile req;
29472 +};
29473 +
29474 +static struct pci_master_request req;  /* globally used for faster master write
29475 +                                        * (discarding result when possible) */
29476 +static struct pci_devnode *pci_node;
29477 +
29478 +#if !defined(CONFIG_DEBUG_PCIMEASURE)
29479 +#define PCI_DECLARE_MEASUREMENT
29480 +#define PCI_MEASUREMENT_START()
29481 +#define PCI_MEASUREMENT_END(idx)
29482 +#else
29483 +#define PCI_DECLARE_MEASUREMENT \
29484 +       int __diff;             \
29485 +       unsigned int __tstart;
29486 +
29487 +#define PCI_MEASUREMENT_START() \
29488 +       __tstart = UBICOM32_IO_TIMER->sysval;
29489 +
29490 +#define PCI_MEASUREMENT_END(idx) \
29491 +       __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
29492 +       pci_measurement_update((idx), __diff);
29493 +
29494 +#define PCI_WEIGHT 32
29495 +
29496 +struct pci_measurement {
29497 +       volatile unsigned int min;
29498 +       volatile unsigned int avg;
29499 +       volatile unsigned int max;
29500 +};
29501 +
29502 +enum pci_measurement_list {
29503 +       PCI_MEASUREMENT_READ32,
29504 +       PCI_MEASUREMENT_WRITE32,
29505 +       PCI_MEASUREMENT_READ16,
29506 +       PCI_MEASUREMENT_WRITE16,
29507 +       PCI_MEASUREMENT_READ8,
29508 +       PCI_MEASUREMENT_WRITE8,
29509 +       PCI_MEASUREMENT_LAST,
29510 +};
29511 +
29512 +static const char *pci_measurement_name_list[PCI_MEASUREMENT_LAST] = {
29513 +       "READ32",
29514 +       "WRITE32",
29515 +       "READ16",
29516 +       "WRITE16",
29517 +       "READ8",
29518 +       "WRITE8"
29519 +};
29520 +static struct pci_measurement pci_measurements[PCI_MEASUREMENT_LAST];
29521 +
29522 +/*
29523 + * pci_measurement_update()
29524 + *     Update an entry in the measurement array for this idx.
29525 + */
29526 +static void pci_measurement_update(int idx, int sample)
29527 +{
29528 +       struct pci_measurement *pm = &pci_measurements[idx];
29529 +       if ((pm->min == 0) || (pm->min > sample)) {
29530 +               pm->min = sample;
29531 +       }
29532 +       if (pm->max < sample) {
29533 +               pm->max = sample;
29534 +       }
29535 +       pm->avg = ((pm->avg * (PCI_WEIGHT - 1)) + sample) / PCI_WEIGHT;
29536 +}
29537 +#endif
29538 +
29539 +#if defined(PCI_USE_INTERNAL_LOCK)
29540 +/*
29541 + * pci_lock_release()
29542 + *     Release the PCI lock.
29543 + */
29544 +static void pci_lock_release(unsigned long irqflag)
29545 +{
29546 +       UBICOM32_UNLOCK(PCI_LOCK_BIT);
29547 +}
29548 +
29549 +/*
29550 + * pci_lock_acquire()
29551 + *     Acquire the PCI lock, spin if not available.
29552 + */
29553 +static void pci_lock_acquire(unsigned long irqflag)
29554 +{
29555 +       UBICOM32_LOCK(PCI_LOCK_BIT);
29556 +}
29557 +#endif
29558 +
29559 +/*
29560 + * pci_set_hrt_interrupt()
29561 + */
29562 +static inline void pci_set_hrt_interrupt(struct pci_devnode *pci_node)
29563 +{
29564 +       ubicom32_set_interrupt(pci_node->dn.sendirq);
29565 +}
29566 +
29567 +/*
29568 + * pci_read_u32()
29569 + *     Synchronously read 32 bits from PCI space.
29570 + */
29571 +u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data)
29572 +{
29573 +       u8 status;
29574 +       unsigned long irqflag;
29575 +
29576 +
29577 +       /*
29578 +        * Fill in the request.
29579 +        */
29580 +       volatile struct pci_master_request lreq;
29581 +       PCI_DECLARE_MEASUREMENT;
29582 +
29583 +       lreq.pci_address = address;
29584 +       lreq.cmd = pci_cmd;
29585 +       lreq.byte_valid = 0xf;          /* enable all bytes */
29586 +
29587 +       /*
29588 +        * Wait for any previous request to complete and then make this request.
29589 +        */
29590 +       PCI_MEASUREMENT_START();
29591 +       PCI_LOCK(&pci_master_lock, irqflag);
29592 +       while (unlikely(pci_node->req == &req))
29593 +               ;
29594 +       pci_node->req = &lreq;
29595 +       pci_set_hrt_interrupt(pci_node);
29596 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29597 +
29598 +       /*
29599 +        * Wait for the result to show up.
29600 +        */
29601 +       while (unlikely(pci_node->req == &lreq))
29602 +               ;
29603 +       status = lreq.status;
29604 +       if (likely(status == PCI_RESP_OK))
29605 +               *data = le32_to_cpu(lreq.data);
29606 +       else
29607 +               *data = 0;
29608 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ32);
29609 +       return status;
29610 +}
29611 +
29612 +/*
29613 + * pci_write_u32()
29614 + *     Asyncrhnously or synchronously write 32 bits to PCI master space.
29615 + */
29616 +u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data)
29617 +{
29618 +       unsigned long irqflag;
29619 +       PCI_DECLARE_MEASUREMENT;
29620 +
29621 +       /*
29622 +        * Wait for any previous write or pending read to complete.
29623 +        *
29624 +        * We use a global data block because once we write the request
29625 +        * we do not wait for it to complete before exiting.
29626 +        */
29627 +       PCI_MEASUREMENT_START();
29628 +       PCI_LOCK(&pci_master_lock, irqflag);
29629 +       while (unlikely(pci_node->req == &req))
29630 +               ;
29631 +       req.pci_address = address;
29632 +       req.data = cpu_to_le32(data);
29633 +       req.cmd = pci_cmd;
29634 +       req.byte_valid = 0xf;           /* enable all bytes */
29635 +       pci_node->req = &req;
29636 +       pci_set_hrt_interrupt(pci_node);
29637 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29638 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE32);
29639 +       return PCI_RESP_OK;
29640 +}
29641 +
29642 +/*
29643 + * pci_read_u16()
29644 + *     Synchronously read 16 bits from PCI space.
29645 + */
29646 +u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data)
29647 +{
29648 +       u8 status;
29649 +       unsigned long irqflag;
29650 +
29651 +       /*
29652 +        * Fill in the request.
29653 +        */
29654 +       volatile struct pci_master_request lreq;
29655 +       PCI_DECLARE_MEASUREMENT;
29656 +
29657 +       lreq.pci_address = address & ~2;
29658 +       lreq.cmd = pci_cmd;
29659 +       lreq.byte_valid = (address & 2) ? 0xc : 0x3;
29660 +
29661 +       /*
29662 +        * Wait for any previous request to complete and then make this request.
29663 +        */
29664 +       PCI_MEASUREMENT_START();
29665 +       PCI_LOCK(&pci_master_lock, irqflag);
29666 +       while (unlikely(pci_node->req == &req))
29667 +               ;
29668 +       pci_node->req = &lreq;
29669 +       pci_set_hrt_interrupt(pci_node);
29670 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29671 +
29672 +       /*
29673 +        * Wait for the result to show up.
29674 +        */
29675 +       while (unlikely(pci_node->req == &lreq))
29676 +               ;
29677 +       status = lreq.status;
29678 +       if (likely(status == PCI_RESP_OK)) {
29679 +               lreq.data = le32_to_cpu(lreq.data);
29680 +               *data = (u16)((address & 2) ? (lreq.data >> 16) : lreq.data);
29681 +       } else
29682 +               *data = 0;
29683 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ16);
29684 +       return status;
29685 +}
29686 +
29687 +/*
29688 + * pci_write_u16()
29689 + *     Asyncrhnously or synchronously write 16 bits to PCI master space.
29690 + */
29691 +u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data)
29692 +{
29693 +       unsigned long irqflag;
29694 +       PCI_DECLARE_MEASUREMENT;
29695 +
29696 +       /*
29697 +        * Wait for any previous write or pending read to complete.
29698 +        *
29699 +        * We use a global data block because once we write the request
29700 +        * we do not wait for it to complete before exiting.
29701 +        */
29702 +       PCI_MEASUREMENT_START();
29703 +       PCI_LOCK(&pci_master_lock, irqflag);
29704 +       while (unlikely(pci_node->req == &req))
29705 +               ;
29706 +       req.pci_address = address & ~2;
29707 +       req.data = (u32)data;
29708 +       req.data = cpu_to_le32((address & 2) ? (req.data << 16) : req.data);
29709 +       req.cmd = pci_cmd;
29710 +       req.byte_valid = (address & 2) ? 0xc : 0x3;
29711 +       pci_node->req = &req;
29712 +       pci_set_hrt_interrupt(pci_node);
29713 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29714 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE16);
29715 +       return PCI_RESP_OK;
29716 +}
29717 +
29718 +/*
29719 + * pci_read_u8()
29720 + *     Synchronously read 8 bits from PCI space.
29721 + */
29722 +u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data)
29723 +{
29724 +       u8 status;
29725 +       unsigned long irqflag;
29726 +
29727 +       /*
29728 +        * Fill in the request.
29729 +        */
29730 +       volatile struct pci_master_request lreq;
29731 +       PCI_DECLARE_MEASUREMENT;
29732 +
29733 +       lreq.pci_address = address & ~3;
29734 +       lreq.cmd = pci_cmd;
29735 +       lreq.byte_valid = 1 << (address & 0x3);
29736 +
29737 +       /*
29738 +        * Wait for any previous request to complete and then make this request.
29739 +        */
29740 +       PCI_MEASUREMENT_START();
29741 +       PCI_LOCK(&pci_master_lock, irqflag);
29742 +       while (unlikely(pci_node->req == &req))
29743 +               ;
29744 +       pci_node->req = &lreq;
29745 +       pci_set_hrt_interrupt(pci_node);
29746 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29747 +
29748 +       /*
29749 +        * Wait for the result to show up.
29750 +        */
29751 +       while (unlikely(pci_node->req == &lreq))
29752 +               ;
29753 +       status = lreq.status;
29754 +       if (likely(status == PCI_RESP_OK)) {
29755 +               *data = (u8)(lreq.data >> (24 - ((address & 0x3) << 3)));
29756 +       } else
29757 +               *data = 0;
29758 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ8);
29759 +       return status;
29760 +}
29761 +
29762 +/*
29763 + * pci_write_u8()
29764 + *     Asyncrhnously or synchronously write 8 bits to PCI master space.
29765 + */
29766 +u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data)
29767 +{
29768 +       unsigned long irqflag;
29769 +       PCI_DECLARE_MEASUREMENT;
29770 +
29771 +       /*
29772 +        * Wait for any previous write or pending read to complete.
29773 +        *
29774 +        * We use a global data block because once we write the request
29775 +        * we do not wait for it to complete before exiting.
29776 +        */
29777 +       PCI_MEASUREMENT_START();
29778 +       PCI_LOCK(&pci_master_lock, irqflag);
29779 +       while (unlikely(pci_node->req == &req))
29780 +               ;
29781 +       req.pci_address = address & ~3;
29782 +       req.data = ((u32)data << (24 - ((address & 0x3) << 3)));
29783 +       req.cmd = pci_cmd;
29784 +       req.byte_valid = 1 << (address & 0x3);
29785 +       pci_node->req = &req;
29786 +       pci_set_hrt_interrupt(pci_node);
29787 +       PCI_UNLOCK(&pci_master_lock, irqflag);
29788 +       PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE8);
29789 +       return PCI_RESP_OK;
29790 +}
29791 +
29792 +unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr)
29793 +{
29794 +       unsigned int data;
29795 +       pci_read_u32(PCI_CMD_MEM_READ, (u32)addr, &data);
29796 +       return data;
29797 +}
29798 +EXPORT_SYMBOL(ubi32_pci_read_u32);
29799 +
29800 +unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr)
29801 +{
29802 +       unsigned short data;
29803 +       pci_read_u16(PCI_CMD_MEM_READ, (u32)addr, &data);
29804 +       return data;
29805 +}
29806 +EXPORT_SYMBOL(ubi32_pci_read_u16);
29807 +
29808 +unsigned char  ubi32_pci_read_u8(const volatile void __iomem *addr)
29809 +{
29810 +       unsigned char  data;
29811 +       pci_read_u8(PCI_CMD_MEM_READ, (u32)addr, &data);
29812 +       return data;
29813 +}
29814 +EXPORT_SYMBOL(ubi32_pci_read_u8);
29815 +
29816 +void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr)
29817 +{
29818 +       pci_write_u32(PCI_CMD_MEM_WRITE, (u32)addr, val);
29819 +}
29820 +EXPORT_SYMBOL(ubi32_pci_write_u32);
29821 +
29822 +void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr)
29823 +{
29824 +       pci_write_u16(PCI_CMD_MEM_WRITE, (u32)addr, val);
29825 +}
29826 +EXPORT_SYMBOL(ubi32_pci_write_u16);
29827 +
29828 +void ubi32_pci_write_u8(unsigned char val, const void volatile __iomem *addr)
29829 +{
29830 +       pci_write_u8(PCI_CMD_MEM_WRITE, (u32)addr, val);
29831 +}
29832 +EXPORT_SYMBOL(ubi32_pci_write_u8);
29833 +
29834 +#if defined(CONFIG_DEBUG_PCIMEASURE)
29835 +static unsigned int pci_cycles_to_nano(unsigned int cycles, unsigned int frequency)
29836 +{
29837 +       unsigned int nano = ((cycles * 1000) / (frequency / 1000000));
29838 +       return nano;
29839 +}
29840 +
29841 +/*
29842 + * pci_measurement_show()
29843 + *     Print out the min, avg, max values for each PCI transaction type.
29844 + *
29845 + * By request, the max value is reset after each dump.
29846 + */
29847 +static int pci_measurement_show(struct seq_file *p, void *v)
29848 +{
29849 +       unsigned int min, avg, max;
29850 +       unsigned int freq = processor_frequency();
29851 +       int trans = *((loff_t *) v);
29852 +
29853 +       if (trans == 0) {
29854 +               seq_puts(p, "min\tavg\tmax\t(nano-seconds)\n");
29855 +       }
29856 +
29857 +       if (trans >= PCI_MEASUREMENT_LAST) {
29858 +               return 0;
29859 +       }
29860 +
29861 +       min = pci_cycles_to_nano(pci_measurements[trans].min, freq);
29862 +       avg = pci_cycles_to_nano(pci_measurements[trans].avg, freq);
29863 +       max = pci_cycles_to_nano(pci_measurements[trans].max, freq);
29864 +       pci_measurements[trans].max = 0;
29865 +       seq_printf(p, "%u\t%u\t%u\t%s\n", min, avg, max, pci_measurement_name_list[trans]);
29866 +       return 0;
29867 +}
29868 +
29869 +static void *pci_measurement_start(struct seq_file *f, loff_t *pos)
29870 +{
29871 +       return (*pos < PCI_MEASUREMENT_LAST) ? pos : NULL;
29872 +}
29873 +
29874 +static void *pci_measurement_next(struct seq_file *f, void *v, loff_t *pos)
29875 +{
29876 +       (*pos)++;
29877 +       if (*pos >= PCI_MEASUREMENT_LAST)
29878 +               return NULL;
29879 +       return pos;
29880 +}
29881 +
29882 +static void pci_measurement_stop(struct seq_file *f, void *v)
29883 +{
29884 +       /* Nothing to do */
29885 +}
29886 +
29887 +static const struct seq_operations pci_measurement_seq_ops = {
29888 +       .start = pci_measurement_start,
29889 +       .next  = pci_measurement_next,
29890 +       .stop  = pci_measurement_stop,
29891 +       .show  = pci_measurement_show,
29892 +};
29893 +
29894 +static int pci_measurement_open(struct inode *inode, struct file *filp)
29895 +{
29896 +       return seq_open(filp, &pci_measurement_seq_ops);
29897 +}
29898 +
29899 +static const struct file_operations pci_measurement_fops = {
29900 +       .open           = pci_measurement_open,
29901 +       .read           = seq_read,
29902 +       .llseek         = seq_lseek,
29903 +       .release        = seq_release,
29904 +};
29905 +
29906 +static int __init pci_measurement_init(void)
29907 +{
29908 +       proc_create("pci_measurements", 0, NULL, &pci_measurement_fops);
29909 +       return 0;
29910 +}
29911 +module_init(pci_measurement_init);
29912 +#endif
29913 +
29914 +static int ubi32_pci_read_config(struct pci_bus *bus, unsigned int devfn,
29915 +                                int where, int size, u32 *value)
29916 +{
29917 +       u8 cmd;
29918 +       u32 addr;
29919 +       u8  data8;
29920 +       u16 data16;
29921 +
29922 +       u8 slot = PCI_SLOT(devfn);
29923 +       u8 fn = PCI_FUNC(devfn);
29924 +
29925 +       if (slot > 1) {
29926 +               return PCIBIOS_DEVICE_NOT_FOUND;
29927 +       } else if (slot == 0) {
29928 +               addr = PCI_DEV0_IDSEL + where;
29929 +       } else {
29930 +               addr = PCI_DEV1_IDSEL + where;
29931 +       }
29932 +
29933 +       addr += (fn << 8);
29934 +
29935 +       cmd = PCI_CMD_CFG_READ;
29936 +       if (size == 1) {
29937 +               pci_read_u8(cmd, addr, &data8);
29938 +               *value = (u32)data8;
29939 +       } else if (size == 2) {
29940 +               pci_read_u16(cmd, addr, &data16);
29941 +               *value = (u32)data16;
29942 +       } else {
29943 +               pci_read_u32(cmd, addr, value);
29944 +       }
29945 +
29946 +       return PCIBIOS_SUCCESSFUL;
29947 +}
29948 +
29949 +static int ubi32_pci_write_config(struct pci_bus *bus, unsigned int devfn,
29950 +                                 int where, int size, u32 value)
29951 +{
29952 +       u8 cmd;
29953 +       u32 addr;
29954 +       u8 slot = PCI_SLOT(devfn);
29955 +       u8 fn = PCI_FUNC(devfn);
29956 +
29957 +       if (slot > 1) {
29958 +               return PCIBIOS_DEVICE_NOT_FOUND;
29959 +       } else if (slot == 0) {
29960 +               addr = PCI_DEV0_IDSEL + where;
29961 +       } else {
29962 +               addr = PCI_DEV1_IDSEL + where;
29963 +       }
29964 +
29965 +       addr += (fn << 8);
29966 +
29967 +       cmd = PCI_CMD_CFG_WRITE;
29968 +       if (size == 1) {
29969 +               pci_write_u8(cmd, addr, (u8)value);
29970 +       } else if (size == 2) {
29971 +               pci_write_u16(cmd, addr, (u16)value);
29972 +       } else {
29973 +               pci_write_u32(cmd, addr, value);
29974 +       }
29975 +
29976 +       return PCIBIOS_SUCCESSFUL;
29977 +}
29978 +
29979 +int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
29980 +{
29981 +       return -EIO;
29982 +}
29983 +EXPORT_SYMBOL(pci_set_dma_max_seg_size);
29984 +
29985 +int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
29986 +{
29987 +       return -EIO;
29988 +}
29989 +EXPORT_SYMBOL(pci_set_dma_seg_boundary);
29990 +
29991 +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
29992 +{
29993 +       resource_size_t start = pci_resource_start(dev, bar);
29994 +       resource_size_t len   = pci_resource_len(dev, bar);
29995 +       unsigned long flags = pci_resource_flags(dev, bar);
29996 +
29997 +       if (!len || !start) {
29998 +               return NULL;
29999 +       }
30000 +
30001 +       if (maxlen && len > maxlen) {
30002 +               len = maxlen;
30003 +       }
30004 +
30005 +       if (flags & IORESOURCE_IO) {
30006 +               return ioport_map(start, len);
30007 +       }
30008 +
30009 +       if (flags & IORESOURCE_MEM) {
30010 +               if (flags & IORESOURCE_CACHEABLE) {
30011 +                       return ioremap(start, len);
30012 +               }
30013 +               return ioremap_nocache(start, len);
30014 +       }
30015 +       return NULL;
30016 +}
30017 +EXPORT_SYMBOL(pci_iomap);
30018 +
30019 +void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
30020 +{
30021 +       if ((unsigned long)addr >= VMALLOC_START &&
30022 +           (unsigned long)addr < VMALLOC_END) {
30023 +               iounmap(addr);
30024 +       }
30025 +}
30026 +EXPORT_SYMBOL(pci_iounmap);
30027 +
30028 +/*
30029 + *  From arch/arm/kernel/bios32.c
30030 + *
30031 + *  PCI bios-type initialisation for PCI machines
30032 + *
30033 + *  Bits taken from various places.
30034 + */
30035 +static void __init pcibios_init_hw(struct hw_pci *hw)
30036 +{
30037 +       struct pci_sys_data *sys = NULL;
30038 +       int ret;
30039 +       int nr, busnr;
30040 +
30041 +       for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
30042 +               sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
30043 +               if (!sys)
30044 +                       panic("PCI: unable to allocate sys data!");
30045 +
30046 +               sys->hw      = hw;
30047 +               sys->busnr   = busnr;
30048 +               sys->map_irq = hw->map_irq;
30049 +               sys->resource[0] = &ioport_resource;
30050 +               sys->resource[1] = &iomem_resource;
30051 +
30052 +               ret = hw->setup(nr, sys);
30053 +
30054 +               if (ret > 0) {
30055 +                       sys->bus = hw->scan(nr, sys);
30056 +
30057 +                       if (!sys->bus)
30058 +                               panic("PCI: unable to scan bus!");
30059 +
30060 +                       busnr = sys->bus->subordinate + 1;
30061 +
30062 +                       list_add(&sys->node, &hw->buses);
30063 +               } else {
30064 +                       kfree(sys);
30065 +                       if (ret < 0)
30066 +                               break;
30067 +               }
30068 +       }
30069 +}
30070 +
30071 +/*
30072 + * Swizzle the device pin each time we cross a bridge.
30073 + * This might update pin and returns the slot number.
30074 + */
30075 +static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
30076 +{
30077 +       struct pci_sys_data *sys = dev->sysdata;
30078 +       int slot = 0, oldpin = *pin;
30079 +
30080 +       if (sys->swizzle)
30081 +               slot = sys->swizzle(dev, pin);
30082 +
30083 +       if (debug_pci)
30084 +               printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
30085 +                       pci_name(dev), oldpin, *pin, slot);
30086 +       return slot;
30087 +}
30088 +
30089 +/*
30090 + * Map a slot/pin to an IRQ.
30091 + */
30092 +static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30093 +{
30094 +       struct pci_sys_data *sys = dev->sysdata;
30095 +       int irq = -1;
30096 +
30097 +       if (sys->map_irq)
30098 +               irq = sys->map_irq(dev, slot, pin);
30099 +
30100 +       if (debug_pci)
30101 +               printk("PCI: %s mapping slot %d pin %d => irq %d\n",
30102 +                       pci_name(dev), slot, pin, irq);
30103 +
30104 +       return irq;
30105 +}
30106 +
30107 +void __init pci_common_init(struct hw_pci *hw)
30108 +{
30109 +       struct pci_sys_data *sys;
30110 +
30111 +       INIT_LIST_HEAD(&hw->buses);
30112 +
30113 +       if (hw->preinit)
30114 +               hw->preinit();
30115 +       pcibios_init_hw(hw);
30116 +       if (hw->postinit)
30117 +               hw->postinit();
30118 +
30119 +       pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
30120 +       list_for_each_entry(sys, &hw->buses, node) {
30121 +               struct pci_bus *bus = sys->bus;
30122 +               /*
30123 +                * Size the bridge windows.
30124 +                */
30125 +               pci_bus_size_bridges(bus);
30126 +               /*
30127 +                * Assign resources.
30128 +                */
30129 +               pci_bus_assign_resources(bus);
30130 +
30131 +               /*
30132 +                * Tell drivers about devices found.
30133 +                */
30134 +               pci_bus_add_devices(bus);
30135 +       }
30136 +}
30137 +
30138 +char * __init pcibios_setup(char *str)
30139 +{
30140 +       if (!strcmp(str, "debug")) {
30141 +               debug_pci = 1;
30142 +               return NULL;
30143 +       }
30144 +       return str;
30145 +}
30146 +
30147 +/*
30148 + * From arch/i386/kernel/pci-i386.c:
30149 + *
30150 + * We need to avoid collisions with `mirrored' VGA ports
30151 + * and other strange ISA hardware, so we always want the
30152 + * addresses to be allocated in the 0x000-0x0ff region
30153 + * modulo 0x400.
30154 + *
30155 + * Why? Because some silly external IO cards only decode
30156 + * the low 10 bits of the IO address. The 0x00-0xff region
30157 + * is reserved for motherboard devices that decode all 16
30158 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
30159 + * but we want to try to avoid allocating at 0x2900-0x2bff
30160 + * which might be mirrored at 0x0100-0x03ff..
30161 + */
30162 +void pcibios_align_resource(void *data, struct resource *res,
30163 +                           resource_size_t size, resource_size_t align)
30164 +{
30165 +       resource_size_t start = res->start;
30166 +
30167 +       if (res->flags & IORESOURCE_IO && start & 0x300)
30168 +               start = (start + 0x3ff) & ~0x3ff;
30169 +
30170 +       res->start = (start + align - 1) & ~(align - 1);
30171 +}
30172 +
30173 +
30174 +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
30175 +{
30176 +       if (debug_pci)
30177 +               printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
30178 +       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
30179 +}
30180 +
30181 +/*
30182 + * If the bus contains any of these devices, then we must not turn on
30183 + * parity checking of any kind.  Currently this is CyberPro 20x0 only.
30184 + */
30185 +static inline int pdev_bad_for_parity(struct pci_dev *dev)
30186 +{
30187 +       return (dev->vendor == PCI_VENDOR_ID_INTERG &&
30188 +               (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
30189 +                dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
30190 +               (dev->vendor == PCI_VENDOR_ID_ITE &&
30191 +                dev->device == PCI_DEVICE_ID_ITE_8152);
30192 +
30193 +}
30194 +
30195 +/*
30196 + * Adjust the device resources from bus-centric to Linux-centric.
30197 + */
30198 +static void __devinit
30199 +pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
30200 +{
30201 +       resource_size_t offset;
30202 +       int i;
30203 +
30204 +       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
30205 +               if (dev->resource[i].start == 0)
30206 +                       continue;
30207 +               if (dev->resource[i].flags & IORESOURCE_MEM)
30208 +                       offset = root->mem_offset;
30209 +               else
30210 +                       offset = root->io_offset;
30211 +
30212 +               dev->resource[i].start += offset;
30213 +               dev->resource[i].end   += offset;
30214 +       }
30215 +}
30216 +
30217 +static void __devinit
30218 +pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
30219 +{
30220 +       struct pci_dev *dev = bus->self;
30221 +       int i;
30222 +
30223 +       if (!dev) {
30224 +               /*
30225 +                * Assign root bus resources.
30226 +                */
30227 +               for (i = 0; i < 3; i++)
30228 +                       bus->resource[i] = root->resource[i];
30229 +       }
30230 +}
30231 +
30232 +/*
30233 + * pcibios_fixup_bus - Called after each bus is probed,
30234 + * but before its children are examined.
30235 + */
30236 +void pcibios_fixup_bus(struct pci_bus *bus)
30237 +{
30238 +       struct pci_sys_data *root = bus->sysdata;
30239 +       struct pci_dev *dev;
30240 +       u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
30241 +               PCI_COMMAND_FAST_BACK;
30242 +
30243 +       pbus_assign_bus_resources(bus, root);
30244 +
30245 +       /*
30246 +        * Walk the devices on this bus, working out what we can
30247 +        * and can't support.
30248 +        */
30249 +       list_for_each_entry(dev, &bus->devices, bus_list) {
30250 +               u16 status;
30251 +
30252 +               pdev_fixup_device_resources(root, dev);
30253 +
30254 +               pci_read_config_word(dev, PCI_STATUS, &status);
30255 +
30256 +               /*
30257 +                * If any device on this bus does not support fast back
30258 +                * to back transfers, then the bus as a whole is not able
30259 +                * to support them.  Having fast back to back transfers
30260 +                * on saves us one PCI cycle per transaction.
30261 +                */
30262 +               if (!(status & PCI_STATUS_FAST_BACK))
30263 +                       features &= ~PCI_COMMAND_FAST_BACK;
30264 +
30265 +               if (pdev_bad_for_parity(dev))
30266 +                       features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
30267 +
30268 +               switch (dev->class >> 8) {
30269 +               case PCI_CLASS_BRIDGE_PCI:
30270 +                       pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
30271 +                       status |= PCI_BRIDGE_CTL_PARITY |
30272 +                               PCI_BRIDGE_CTL_MASTER_ABORT;
30273 +                       status &= ~(PCI_BRIDGE_CTL_BUS_RESET |
30274 +                                   PCI_BRIDGE_CTL_FAST_BACK);
30275 +                       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
30276 +                       break;
30277 +
30278 +               case PCI_CLASS_BRIDGE_CARDBUS:
30279 +                       pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30280 +                                            &status);
30281 +                       status |= PCI_CB_BRIDGE_CTL_PARITY |
30282 +                               PCI_CB_BRIDGE_CTL_MASTER_ABORT;
30283 +                       pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30284 +                                             status);
30285 +                       break;
30286 +               }
30287 +       }
30288 +
30289 +       /*
30290 +        * Now walk the devices again, this time setting them up.
30291 +        */
30292 +       list_for_each_entry(dev, &bus->devices, bus_list) {
30293 +               u16 cmd;
30294 +
30295 +               pci_read_config_word(dev, PCI_COMMAND, &cmd);
30296 +               cmd |= features;
30297 +               pci_write_config_word(dev, PCI_COMMAND, cmd);
30298 +
30299 +               pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
30300 +                                     L1_CACHE_BYTES >> 2);
30301 +       }
30302 +
30303 +       /*
30304 +        * Propagate the flags to the PCI bridge.
30305 +        */
30306 +       if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
30307 +               if (features & PCI_COMMAND_FAST_BACK)
30308 +                       bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
30309 +               if (features & PCI_COMMAND_PARITY)
30310 +                       bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
30311 +       }
30312 +
30313 +       /*
30314 +        * Report what we did for this bus
30315 +        */
30316 +       printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
30317 +               bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
30318 +}
30319 +/*
30320 + * Convert from Linux-centric to bus-centric addresses for bridge devices.
30321 + */
30322 +void
30323 +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
30324 +                        struct resource *res)
30325 +{
30326 +       struct pci_sys_data *root = dev->sysdata;
30327 +       unsigned long offset = 0;
30328 +
30329 +       if (res->flags & IORESOURCE_IO)
30330 +               offset = root->io_offset;
30331 +       if (res->flags & IORESOURCE_MEM)
30332 +               offset = root->mem_offset;
30333 +
30334 +       region->start = res->start - offset;
30335 +       region->end   = res->end - offset;
30336 +}
30337 +
30338 +void __devinit
30339 +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
30340 +                       struct pci_bus_region *region)
30341 +{
30342 +       struct pci_sys_data *root = dev->sysdata;
30343 +       unsigned long offset = 0;
30344 +
30345 +       if (res->flags & IORESOURCE_IO)
30346 +               offset = root->io_offset;
30347 +       if (res->flags & IORESOURCE_MEM)
30348 +               offset = root->mem_offset;
30349 +
30350 +       res->start = region->start + offset;
30351 +       res->end   = region->end + offset;
30352 +}
30353 +
30354 +#ifdef CONFIG_HOTPLUG
30355 +EXPORT_SYMBOL(pcibios_fixup_bus);
30356 +EXPORT_SYMBOL(pcibios_resource_to_bus);
30357 +EXPORT_SYMBOL(pcibios_bus_to_resource);
30358 +#endif
30359 +
30360 +/**
30361 + * pcibios_enable_device - Enable I/O and memory.
30362 + * @dev: PCI device to be enabled
30363 + */
30364 +int pcibios_enable_device(struct pci_dev *dev, int mask)
30365 +{
30366 +       u16 cmd, old_cmd;
30367 +       int idx;
30368 +       struct resource *r;
30369 +
30370 +       pci_read_config_word(dev, PCI_COMMAND, &cmd);
30371 +       old_cmd = cmd;
30372 +       for (idx = 0; idx < 6; idx++) {
30373 +               /* Only set up the requested stuff */
30374 +               if (!(mask & (1 << idx)))
30375 +                       continue;
30376 +
30377 +               r = dev->resource + idx;
30378 +               if (!r->start && r->end) {
30379 +                       printk(KERN_ERR "PCI: Device %s not available because"
30380 +                              " of resource collisions\n", pci_name(dev));
30381 +                       return -EINVAL;
30382 +               }
30383 +               if (r->flags & IORESOURCE_IO)
30384 +                       cmd |= PCI_COMMAND_IO;
30385 +               if (r->flags & IORESOURCE_MEM)
30386 +                       cmd |= PCI_COMMAND_MEMORY;
30387 +       }
30388 +
30389 +       /*
30390 +        * Bridges (eg, cardbus bridges) need to be fully enabled
30391 +        */
30392 +       if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
30393 +               cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
30394 +
30395 +       if (cmd != old_cmd) {
30396 +               printk("PCI: enabling device %s (%04x -> %04x)\n",
30397 +                      pci_name(dev), old_cmd, cmd);
30398 +               pci_write_config_word(dev, PCI_COMMAND, cmd);
30399 +       }
30400 +       return 0;
30401 +}
30402 +
30403 +
30404 +struct pci_ops ubi32_pci_ops = {
30405 +       .read   = ubi32_pci_read_config,
30406 +       .write  = ubi32_pci_write_config,
30407 +};
30408 +
30409 +static struct pci_bus *ubi32_pci_scan_bus(int nr, struct pci_sys_data *sys)
30410 +{
30411 +       return pci_scan_bus(sys->busnr, &ubi32_pci_ops, sys);
30412 +}
30413 +
30414 +#define UBI32_PCI_MEM_BASE PCI_DEV_REG_BASE
30415 +#define UBI32_PCI_MEM_LEN  0x80000000
30416 +
30417 +#define UBI32_PCI_IO_BASE 0x0
30418 +#define UBI32_PCI_IO_END  0x0
30419 +
30420 +static struct resource ubi32_pci_mem = {
30421 +       .name   = "PCI memory space",
30422 +       .start  = UBI32_PCI_MEM_BASE,
30423 +       .end    = UBI32_PCI_MEM_BASE + UBI32_PCI_MEM_LEN - 1,
30424 +       .flags  = IORESOURCE_MEM,
30425 +};
30426 +
30427 +static struct resource ubi32_pci_io = {
30428 +       .name   = "PCI IO space",
30429 +       .start  = UBI32_PCI_IO_BASE,
30430 +       .end    = UBI32_PCI_IO_END,
30431 +       .flags  = IORESOURCE_IO,
30432 +};
30433 +
30434 +static int __init ubi32_pci_setup(int nr, struct pci_sys_data *sys)
30435 +{
30436 +       if (nr > 0)
30437 +               return 0;
30438 +
30439 +       request_resource(&iomem_resource, &ubi32_pci_mem);
30440 +       request_resource(&ioport_resource, &ubi32_pci_io);
30441 +
30442 +       sys->resource[0] = &ubi32_pci_io;
30443 +       sys->resource[1] = &ubi32_pci_mem;
30444 +       sys->resource[2] = NULL;
30445 +
30446 +       return 1;
30447 +}
30448 +
30449 +static void __init ubi32_pci_preinit(void)
30450 +{
30451 +}
30452 +
30453 +static int __init ubi32_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30454 +{
30455 +       return pci_node->dn.recvirq;
30456 +}
30457 +
30458 +struct hw_pci ubi32_pci __initdata = {
30459 +       .nr_controllers = 1,
30460 +       .preinit        = ubi32_pci_preinit,
30461 +       .setup          = ubi32_pci_setup,
30462 +       .scan           = ubi32_pci_scan_bus,
30463 +       .map_irq        = ubi32_pci_map_irq,
30464 +};
30465 +
30466 +static int __init ubi32_pci_init(void)
30467 +{
30468 +       pci_node = (struct pci_devnode *)devtree_find_node("pci");
30469 +       if (pci_node == NULL) {
30470 +               printk(KERN_WARNING "PCI init failed\n");
30471 +               return -ENOSYS;
30472 +       }
30473 +       pci_common_init(&ubi32_pci);
30474 +       return 0;
30475 +}
30476 +
30477 +subsys_initcall(ubi32_pci_init);
30478 +
30479 +/*
30480 + * workaround for dual PCI card interrupt
30481 + */
30482 +#define PCI_COMMON_INT_BIT (1 << 19)
30483 +void ubi32_pci_int_wr(void)
30484 +{
30485 +       volatile unsigned int pci_int_line;
30486 +       pci_int_line = UBICOM32_IO_PORT(RB)->gpio_in;
30487 +       if (!(pci_int_line & PCI_COMMON_INT_BIT))
30488 +       {
30489 +               ubicom32_set_interrupt(pci_node->dn.recvirq);
30490 +       }
30491 +}
30492 +EXPORT_SYMBOL(ubi32_pci_int_wr);
30493 --- /dev/null
30494 +++ b/arch/ubicom32/mach-common/plio.c
30495 @@ -0,0 +1,92 @@
30496 +/*
30497 + * plio.c
30498 + *     PLIO state machine support functions
30499 + *
30500 + * Copyright Â© 2009 Ubicom Inc. <www.ubicom.com>.  All rights reserved.
30501 + *
30502 + * This file is part of the Ubicom32 Linux Kernel Port.
30503 + *
30504 + * The Ubicom32 Linux Kernel Port is free software: you can
30505 + * redistribute it and/or modify it under the terms of the GNU General
30506 + * Public License as published by the Free Software Foundation, either
30507 + * version 2 of the License, or (at your option) any later version.
30508 + *
30509 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30510 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30511 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30512 + * See the GNU General Public License for more details.
30513 + *
30514 + * You should have received a copy of the GNU General Public License
30515 + * along with the Ubicom32 Linux Kernel Port.  If not,
30516 + * see <http://www.gnu.org/licenses/>.
30517 + */
30518 +
30519 +#include <linux/types.h>
30520 +#include <linux/string.h>
30521 +#include <linux/delay.h>
30522 +#include <asm/plio.h>
30523 +
30524 +/*
30525 + * plio_reset
30526 + *     Select and reset PLIO function
30527 + */
30528 +static void plio_reset(const plio_fctl_t *plio_fctl) {
30529 +       plio_io_function_t plio_function = {
30530 +               .fn_sel         = PLIO_FN,
30531 +               .fn_reset       = 1,
30532 +       };
30533 +
30534 +       /*
30535 +        * enable extension port
30536 +        */
30537 +       PEXT_NBR->function = plio_function;
30538 +
30539 +       /*
30540 +        * program clock dividers
30541 +        */
30542 +       PLIO_NBR->fctl2 = plio_fctl->fctl2;
30543 +
30544 +       /*
30545 +        * select plio function and assert function reset
30546 +        */
30547 +       plio_function.br_thread = thread_get_self();
30548 +       plio_function.fn_reset = 1;
30549 +       PLIO_NBR->function = plio_function;
30550 +
30551 +       /*
30552 +        * program plio controls
30553 +        */
30554 +       PLIO_NBR->fctl0 = plio_fctl->fctl0;
30555 +       PLIO_NBR->fctl1 = plio_fctl->fctl1;
30556 +
30557 +       /*
30558 +        * deassert function reset
30559 +        */
30560 +       plio_function.fn_reset = 0;
30561 +       PLIO_NBR->function = plio_function;
30562 +}
30563 +
30564 +/*
30565 + * plio_init
30566 + *     configure and initialize PLIO.
30567 + */
30568 +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){
30569 +       /*
30570 +        * first reset to start plio clock
30571 +        */
30572 +       plio_reset(plio_fctl);
30573 +
30574 +       udelay(1);
30575 +
30576 +       /*
30577 +        * configure pfsm
30578 +        */
30579 +       PLIO_NBR->fctl0.pfsm_prog = 1;
30580 +       memcpy(PLIO_BR->pfsm_sram, plio_sram_cfg, sram_cfg_size);
30581 +       PLIO_NBR->fctl0.pfsm_prog = 0;
30582 +
30583 +       /*
30584 +        * program rest of plio
30585 +        */
30586 +       memcpy(&PLIO_BR->config, plio_config, sizeof(plio_config_t));
30587 +}
30588 --- /dev/null
30589 +++ b/arch/ubicom32/mach-common/profile.c
30590 @@ -0,0 +1,549 @@
30591 +/*
30592 + * arch/ubicom32/mach-common/profile.c
30593 + *   Implementation for Ubicom32 Profiler
30594 + *
30595 + * (C) Copyright 2009, Ubicom, Inc.
30596 + *
30597 + * This file is part of the Ubicom32 Linux Kernel Port.
30598 + *
30599 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
30600 + * it and/or modify it under the terms of the GNU General Public License
30601 + * as published by the Free Software Foundation, either version 2 of the
30602 + * License, or (at your option) any later version.
30603 + *
30604 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30605 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30606 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
30607 + * the GNU General Public License for more details.
30608 + *
30609 + * You should have received a copy of the GNU General Public License
30610 + * along with the Ubicom32 Linux Kernel Port.  If not,
30611 + * see <http://www.gnu.org/licenses/>.
30612 + */
30613 +
30614 +#include <linux/platform_device.h>
30615 +#include "profile.h"
30616 +#include <linux/seq_file.h>
30617 +#include <linux/proc_fs.h>
30618 +#include <linux/mm.h>
30619 +#include <linux/mmzone.h>
30620 +#include <linux/fs.h>
30621 +#include <linux/page-flags.h>
30622 +#include <asm/uaccess.h>
30623 +#include <asm/devtree.h>
30624 +#include <asm/profilesample.h>
30625 +#include <asm/memory_map.h>
30626 +#include <asm/page.h>
30627 +#include <asm/ip5000.h>
30628 +
30629 +/*
30630 + * spacs for all memory blocks so we can hold locks for short time when walking tables
30631 + */
30632 +#define PROFILE_NUM_MAPS 5000
30633 +static struct profile_map profile_pm[PROFILE_NUM_MAPS];
30634 +
30635 +static struct profilenode *node = NULL;
30636 +static int profile_first_packet = 1;
30637 +
30638 +static int profile_open(struct inode *inode, struct file *filp)
30639 +{
30640 +       if (!node) {
30641 +               return -ENOENT;
30642 +       }
30643 +       node->busy = 1;
30644 +       if (!node->enabled) {
30645 +               node->enabled = 1;
30646 +               node->busy = 0;
30647 +               profile_first_packet = 1;
30648 +               return 0;
30649 +       }
30650 +       node->busy = 0;
30651 +       return -EBUSY;
30652 +}
30653 +
30654 +static int profile_sequence_num;
30655 +
30656 +/*
30657 + * make a packet full of sample data
30658 + */
30659 +static int profile_make_data_packet(char *buf, int count)
30660 +{
30661 +       int samples;            /* number of samples requested */
30662 +       int i;
30663 +       struct profile_header ph;
30664 +       char *ptr;
30665 +
30666 +       if (count < sizeof(struct profile_header) + sizeof(struct profile_sample)) {
30667 +               return -EINVAL;
30668 +       }
30669 +
30670 +       /*
30671 +        * fill in the packet header
30672 +        */
30673 +       memset(&ph, 0, sizeof(struct profile_header));
30674 +       ph.magic = PROF_MAGIC + PROFILE_VERSION;
30675 +       ph.header_size = sizeof(struct profile_header);
30676 +       ph.clocks = node->clocks;
30677 +       for (i = 0; i < PROFILE_MAX_THREADS; ++i) {
30678 +               ph.instruction_count[i] = node->inst_count[i];
30679 +       }
30680 +       ph.profile_instructions = 0;
30681 +       ph.enabled = node->enabled_threads;
30682 +       ph.hrt = node->hrt;
30683 +       ph.high = 0;
30684 +       ph.profiler_thread = node->profiler_thread;
30685 +       ph.clock_freq = node->clock_freq;
30686 +       ph.seq_num = profile_sequence_num++;
30687 +       ph.cpu_id = node->cpu_id;
30688 +       ph.perf_counters[0] = node->stats[0];
30689 +       ph.perf_counters[1] = node->stats[1];
30690 +       ph.perf_counters[2] = node->stats[2];
30691 +       ph.perf_counters[3] = node->stats[3];
30692 +       ph.ddr_freq = node->ddr_freq;
30693 +
30694 +       ptr = buf + sizeof(struct profile_header);
30695 +
30696 +       samples = (count - sizeof(struct profile_header)) / sizeof(struct profile_sample);
30697 +       for (i = 0; i < samples && node->count; ++i) {
30698 +               if (copy_to_user(ptr, &node->samples[node->tail], sizeof(struct profile_sample)) != 0) {
30699 +                       return -EFAULT;
30700 +               }
30701 +               node->count--;
30702 +               node->tail++;
30703 +               if (node->tail >= node->max_samples) {
30704 +                       node->tail = 0;
30705 +               }
30706 +               ptr += sizeof(struct profile_sample);
30707 +       }
30708 +       ph.sample_count = i;
30709 +       if (copy_to_user(buf, &ph, sizeof(struct profile_header)) != 0) {
30710 +               return -EFAULT;
30711 +       }
30712 +       if (ph.sample_count == 0)
30713 +               return 0;
30714 +       else
30715 +               return sizeof(struct profile_header) + ph.sample_count * sizeof(struct profile_sample);
30716 +}
30717 +
30718 +static void profile_get_memory_stats(unsigned int *total_free, unsigned int *max_free)
30719 +{
30720 +       struct list_head *p;
30721 +       struct zone *zone;
30722 +       unsigned int size;
30723 +
30724 +       *total_free = 0;
30725 +       *max_free = 0;
30726 +
30727 +       /*
30728 +        * 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
30729 +        */
30730 +       for_each_zone(zone) {
30731 +               unsigned long order, flags, i;
30732 +
30733 +               if (!populated_zone(zone))
30734 +                       continue;
30735 +
30736 +               if (!is_normal(zone))
30737 +                       continue;
30738 +
30739 +               spin_lock_irqsave(&zone->lock, flags);
30740 +               for_each_migratetype_order(order, i) {
30741 +                       size = ((1 << order) << PAGE_SHIFT) >> 10;
30742 +                       list_for_each(p, &(zone->free_area[order].free_list[i])) {
30743 +                               if (size > *max_free) {
30744 +                                       *max_free = size;
30745 +                               }
30746 +                               *total_free += size;
30747 +                       }
30748 +               }
30749 +               spin_unlock_irqrestore(&zone->lock, flags);
30750 +       }
30751 +}
30752 +
30753 +struct profile_counter_pkt profile_builtin_stats[] =
30754 +{
30755 +       {
30756 +       "Free memory(KB)", 0
30757 +       },
30758 +       {
30759 +       "Max free Block(KB)", 0
30760 +       }
30761 +};
30762 +
30763 +/*
30764 + * make a packet full of performance counters
30765 + */
30766 +static char prof_pkt[PROFILE_MAX_PACKET_SIZE];
30767 +static int profile_make_stats_packet(char *buf, int count)
30768 +{
30769 +       char *ptr = prof_pkt;
30770 +       struct profile_header_counters hdr;
30771 +       int stat_count = 0;
30772 +       int i;
30773 +       unsigned int total_free, max_free;
30774 +       int builtin_count = sizeof(profile_builtin_stats) / sizeof(struct profile_counter_pkt);
30775 +
30776 +       if (count > PROFILE_MAX_PACKET_SIZE) {
30777 +               count = PROFILE_MAX_PACKET_SIZE;
30778 +       }
30779 +       stat_count = (count - sizeof(struct profile_header_counters)) / sizeof (struct profile_counter_pkt);
30780 +       stat_count -= builtin_count;
30781 +
30782 +       if (stat_count <= 0) {
30783 +               return 0;
30784 +       }
30785 +
30786 +       if (stat_count > node->num_counters) {
30787 +               stat_count = node->num_counters;
30788 +       }
30789 +
30790 +       hdr.magic = PROF_MAGIC_COUNTERS;
30791 +       hdr.ultra_sample_time = node->clocks;
30792 +       hdr.ultra_count = stat_count;
30793 +       hdr.linux_sample_time = UBICOM32_IO_TIMER->sysval;
30794 +       hdr.linux_count = builtin_count;
30795 +       memcpy(ptr, (void *)&hdr, sizeof(struct profile_header_counters));
30796 +       ptr += sizeof(struct profile_header_counters);
30797 +
30798 +
30799 +       for (i = 0; i < stat_count; ++i) {
30800 +               memcpy(ptr, (void *)(&(node->counters[i])), sizeof(struct profile_counter));
30801 +               ptr += sizeof(struct profile_counter);
30802 +       }
30803 +
30804 +       /*
30805 +        * built in statistics
30806 +        */
30807 +       profile_get_memory_stats(&total_free, &max_free);
30808 +       profile_builtin_stats[0].value = total_free;
30809 +       profile_builtin_stats[1].value = max_free;
30810 +       memcpy(ptr, (void *)profile_builtin_stats, sizeof(profile_builtin_stats));
30811 +       ptr += sizeof(profile_builtin_stats);
30812 +
30813 +       if (copy_to_user(buf, prof_pkt, ptr - prof_pkt) != 0) {
30814 +               return -EFAULT;
30815 +       }
30816 +       return ptr - prof_pkt;
30817 +}
30818 +
30819 +/*
30820 + * return a udp packet ready to send to the profiler tool
30821 + * when there are no packets left to make, return 0
30822 + */
30823 +static int profile_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
30824 +{
30825 +       int result = 0;
30826 +       if (!node) {
30827 +               return -ENOENT;
30828 +       }
30829 +       node->busy = 1;
30830 +       if (!node->enabled) {
30831 +               node->busy = 0;
30832 +               return -EPERM;
30833 +       }
30834 +       if (!node->samples) {
30835 +               node->busy = 0;
30836 +               return -ENOMEM;
30837 +       }
30838 +
30839 +       if (profile_first_packet) {
30840 +               result = profile_make_stats_packet(buf, count);
30841 +               profile_first_packet = 0;
30842 +       }
30843 +       if (result == 0) {
30844 +               result = profile_make_data_packet(buf, count);
30845 +               if (result == 0) {
30846 +                       profile_first_packet = 1;
30847 +               }
30848 +       }
30849 +       node->busy = 0;
30850 +       return result;
30851 +
30852 +}
30853 +
30854 +static int profile_release(struct inode *inode, struct file *filp)
30855 +{
30856 +       if (!node) {
30857 +               return -ENOENT;
30858 +       }
30859 +       node->busy = 1;
30860 +       if (node->enabled) {
30861 +               node->enabled = 0;
30862 +               node->count = 0;
30863 +               node->tail = node->head;
30864 +               node->busy = 0;
30865 +               return 0;
30866 +       }
30867 +       node->busy = 0;
30868 +       profile_first_packet = 1;
30869 +       return -EBADF;
30870 +}
30871 +
30872 +static const struct file_operations profile_fops = {
30873 +       .open           = profile_open,
30874 +       .read           = profile_read,
30875 +       .release        = profile_release,
30876 +};
30877 +
30878 +static int page_aligned(void *x)
30879 +{
30880 +       return !((unsigned int)x & ((1 << PAGE_SHIFT) - 1));
30881 +}
30882 +
30883 +static int profile_maps_open(struct inode *inode, struct file *filp)
30884 +{
30885 +       struct rb_node *rb;
30886 +       int num = 0;
30887 +       int slab_start;
30888 +       struct vm_area_struct *vma;
30889 +       int type = PROFILE_MAP_TYPE_UNKNOWN;
30890 +       int flags, i;
30891 +       struct list_head *p;
30892 +       struct zone *zone;
30893 +
30894 +       /*
30895 +        * get the slab data (first so dups will show up as vmas)
30896 +        */
30897 +       slab_start = num;
30898 +       num += kmem_cache_block_info("size-512", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30899 +       num += kmem_cache_block_info("size-1024", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30900 +       num += kmem_cache_block_info("size-2048", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30901 +       num += kmem_cache_block_info("size-4096", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30902 +       num += kmem_cache_block_info("size-8192", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30903 +
30904 +       for (i = slab_start; i < num; ++i) {
30905 +               profile_pm[i].type_size |= PROFILE_MAP_TYPE_SMALL << PROFILE_MAP_TYPE_SHIFT;
30906 +       }
30907 +
30908 +       slab_start = num;
30909 +       num += kmem_cache_block_info("dentry", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30910 +       num += kmem_cache_block_info("inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30911 +       num += kmem_cache_block_info("sysfs_dir_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30912 +       num += kmem_cache_block_info("proc_inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30913 +
30914 +       for (i = slab_start; i < num; ++i) {
30915 +               profile_pm[i].type_size |= PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT;
30916 +       }
30917 +
30918 +       /*
30919 +        * get all the vma regions (allocated by mmap, most likely
30920 +        */
30921 +#if 0
30922 +       down_read(&nommu_vma_sem);
30923 +       for (rb = rb_first(&nommu_vma_tree); rb && num < PROFILE_NUM_MAPS; rb = rb_next(rb)) {
30924 +               vma = rb_entry(rb, struct vm_area_struct, vm_rb);
30925 +               profile_pm[num].start = (vma->vm_start - SDRAMSTART) >> PAGE_SHIFT;
30926 +               profile_pm[num].type_size = (vma->vm_end - vma->vm_start + (1 << PAGE_SHIFT) - 1) >> PAGE_SHIFT;
30927 +               flags = vma->vm_flags & 0xf;
30928 +               if (flags == (VM_READ | VM_EXEC)) {
30929 +                       type = PROFILE_MAP_TYPE_TEXT;
30930 +               } else if (flags == (VM_READ | VM_WRITE | VM_EXEC)) {
30931 +                       type = PROFILE_MAP_TYPE_STACK;
30932 +               } else if (flags == (VM_READ | VM_WRITE)) {
30933 +                       type = PROFILE_MAP_TYPE_APP_DATA;
30934 +               }
30935 +               profile_pm[num].type_size |= type << PROFILE_MAP_TYPE_SHIFT;
30936 +               num++;
30937 +       }
30938 +       up_read(&nommu_vma_sem);
30939 +       if (rb) {
30940 +               return -ENOMEM;
30941 +       }
30942 +#endif
30943 +
30944 +       /*
30945 +        * 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
30946 +        */
30947 +       for_each_zone(zone) {
30948 +               unsigned long order, flags, i;
30949 +               struct page *page;
30950 +
30951 +               if (!populated_zone(zone))
30952 +                       continue;
30953 +
30954 +               if (!is_normal(zone))
30955 +                       continue;
30956 +
30957 +               spin_lock_irqsave(&zone->lock, flags);
30958 +               for_each_migratetype_order(order, i) {
30959 +                       list_for_each(p, &(zone->free_area[order].free_list[i])) {
30960 +                               page = list_entry(p, struct page, lru);
30961 +                               profile_pm[num].start = ((page_to_phys(page) - SDRAMSTART) >> PAGE_SHIFT) - 0x40;
30962 +                               profile_pm[num].type_size = (PROFILE_MAP_TYPE_FREE << PROFILE_MAP_TYPE_SHIFT) | order;
30963 +                               num++;
30964 +                               if (num >= PROFILE_NUM_MAPS) {
30965 +                                       spin_unlock_irqrestore(&zone->lock, flags);
30966 +                                       return -ENOMEM;
30967 +                               }
30968 +                       }
30969 +               }
30970 +               spin_unlock_irqrestore(&zone->lock, flags);
30971 +       }
30972 +
30973 +       /*
30974 +        * get the filesystem inodes
30975 +        */
30976 +       list_for_each(p, &(super_blocks)) {
30977 +               struct super_block *sb;
30978 +               struct list_head *q;
30979 +               if (num >= PROFILE_NUM_MAPS)
30980 +                       break;
30981 +               sb = list_entry(p, struct super_block, s_list);
30982 +               if (page_aligned(sb)) {
30983 +                       profile_pm[num].start = ((unsigned int)sb - SDRAMSTART) >> PAGE_SHIFT;
30984 +                       profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
30985 +                       num++;
30986 +               }
30987 +               list_for_each(q, &(sb->s_inodes)) {
30988 +                       struct inode *in;
30989 +                       if (num >= PROFILE_NUM_MAPS)
30990 +                               break;
30991 +                       in = list_entry(q, struct inode, i_sb_list);
30992 +                       if (page_aligned(in)) {
30993 +                               profile_pm[num].start = ((unsigned int)in - SDRAMSTART) >> PAGE_SHIFT;
30994 +                               profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
30995 +                               num++;
30996 +                       }
30997 +               }
30998 +       }
30999 +
31000 +       /*
31001 +        * get the buffer cache pages
31002 +        */
31003 +       for (i = 0; i < num_physpages && num < PROFILE_NUM_MAPS; ++i) {
31004 +               if ((mem_map + i)->flags & (1 << PG_lru)) {
31005 +                       int start = i;
31006 +                       while ((mem_map + i)->flags & (1 << PG_lru) && i < num_physpages)
31007 +                               i++;
31008 +                       profile_pm[num].start = start;
31009 +                       profile_pm[num].type_size = (i - start) | (PROFILE_MAP_TYPE_CACHE << PROFILE_MAP_TYPE_SHIFT);
31010 +                       num++;
31011 +               }
31012 +       }
31013 +
31014 +       filp->private_data = (void *)num;
31015 +       return 0;
31016 +}
31017 +
31018 +/*
31019 + * return one packet of map data, or 0 if all maps have been returned already
31020 + */
31021 +static int profile_maps_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
31022 +{
31023 +       struct profile_header_maps header;
31024 +       char *p = buf + sizeof(header);
31025 +       int total = (int)filp->private_data;
31026 +
31027 +       header.count = (count - sizeof(header)) / sizeof(struct profile_map);
31028 +       if (header.count > PROFILE_MAX_MAPS) {
31029 +               header.count = PROFILE_MAX_MAPS;;
31030 +       }
31031 +       if (header.count > total - *f_pos) {
31032 +               header.count = total - *f_pos;
31033 +       }
31034 +
31035 +       if (header.count == 0) {
31036 +               return 0;
31037 +       }
31038 +
31039 +       header.magic = PROF_MAGIC_MAPS;
31040 +       header.page_shift = PAGE_SHIFT;
31041 +
31042 +       if (copy_to_user(buf, &header, sizeof(header)) != 0) {
31043 +               return -EFAULT;
31044 +       }
31045 +       if (copy_to_user(p, (void *)&profile_pm[*f_pos], sizeof(struct profile_map) * header.count) != 0) {
31046 +               return -EFAULT;
31047 +       }
31048 +       *f_pos += header.count;
31049 +
31050 +       return sizeof(header) + sizeof(struct profile_map) * header.count;
31051 +}
31052 +
31053 +static int profile_maps_release(struct inode *inode, struct file *filp)
31054 +{
31055 +       return 0;
31056 +}
31057 +
31058 +static const struct file_operations profile_maps_fops = {
31059 +       .open           = profile_maps_open,
31060 +       .read           = profile_maps_read,
31061 +       .release        = profile_maps_release,
31062 +};
31063 +
31064 +static int profile_rate_show(struct seq_file *m, void *v)
31065 +{
31066 +       if (node) {
31067 +               seq_printf(m, "%d samples per second.  %d virtual counters.\n", node->rate, node->num_counters);
31068 +       } else {
31069 +               seq_printf(m, "Profiler is not initialized.\n");
31070 +       }
31071 +       return 0;
31072 +}
31073 +
31074 +static int profile_rate_open(struct inode *inode, struct file *filp)
31075 +{
31076 +       return single_open(filp, profile_rate_show, NULL);
31077 +}
31078 +
31079 +static int profile_rate_write(struct file *filp, const char *buf, size_t len, loff_t *off)
31080 +{
31081 +       *off = 0;
31082 +       return 0;
31083 +}
31084 +
31085 +static const struct file_operations profile_rate_fops = {
31086 +       .open           = profile_rate_open,
31087 +       .read           = seq_read,
31088 +       .llseek         = seq_lseek,
31089 +       .release        = single_release,
31090 +       .write          = profile_rate_write,
31091 +};
31092 +
31093 +int ubi32_profile_init_module(void)
31094 +{
31095 +       struct proc_dir_entry *pdir;
31096 +
31097 +       /*
31098 +        * find the device
31099 +        */
31100 +       node = (struct profilenode *)devtree_find_node("profiler");
31101 +       if (!node) {
31102 +               printk(KERN_INFO "Profiler does not exist.\n");
31103 +               return -ENODEV;
31104 +       }
31105 +
31106 +       /*
31107 +        * allocate the sample buffer
31108 +        */
31109 +       node->max_samples = PROFILE_MAX_SAMPLES;
31110 +       node->samples = kmalloc(node->max_samples * sizeof(struct profile_sample), GFP_KERNEL);
31111 +       if (!node->samples) {
31112 +               printk(KERN_INFO "Profiler sample buffer kmalloc failed.\n");
31113 +               return -ENOMEM;
31114 +       }
31115 +
31116 +       /*
31117 +        * connect to the file system
31118 +        */
31119 +       pdir = proc_mkdir("profile", NULL);
31120 +       if (!pdir) {
31121 +               return -ENOMEM;
31122 +       }
31123 +       if (!proc_create("data", 0, pdir, &profile_fops)) {
31124 +               return -ENOMEM;
31125 +       }
31126 +       if (!proc_create("rate", 0, pdir, &profile_rate_fops)) {
31127 +               return -ENOMEM;
31128 +       }
31129 +       if (!proc_create("maps", 0, pdir, &profile_maps_fops)) {
31130 +               return -ENOMEM;
31131 +       }
31132 +       return 0;
31133 +}
31134 +
31135 +
31136 +module_init(ubi32_profile_init_module);
31137 +
31138 +MODULE_AUTHOR("David Fotland");
31139 +MODULE_LICENSE("GPL");
31140 --- /dev/null
31141 +++ b/arch/ubicom32/mach-common/profile.h
31142 @@ -0,0 +1,82 @@
31143 +/*
31144 + * arch/ubicom32/mach-common/profile.h
31145 + *   Private data for the profile module
31146 + *
31147 + * (C) Copyright 2009, Ubicom, Inc.
31148 + *
31149 + * This file is part of the Ubicom32 Linux Kernel Port.
31150 + *
31151 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31152 + * it and/or modify it under the terms of the GNU General Public License
31153 + * as published by the Free Software Foundation, either version 2 of the
31154 + * License, or (at your option) any later version.
31155 + *
31156 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31157 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31158 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31159 + * the GNU General Public License for more details.
31160 + *
31161 + * You should have received a copy of the GNU General Public License
31162 + * along with the Ubicom32 Linux Kernel Port.  If not,
31163 + * see <http://www.gnu.org/licenses/>.
31164 + *
31165 + * Ubicom32 implementation derived from (with many thanks):
31166 + *   arch/m68knommu
31167 + *   arch/blackfin
31168 + *   arch/parisc
31169 + */
31170 +
31171 +#include <linux/types.h>
31172 +#include <asm/devtree.h>
31173 +#include "profpkt.h"
31174 +
31175 +#ifndef _PROFILE_H_
31176 +#define _PROFILE_H_
31177 +
31178 +#define PROFILE_MAX_THREADS 16
31179 +#define PROFILE_MAX_SAMPLES 1024
31180 +
31181 +struct profile_sample;
31182 +struct oprofile_sample;
31183 +
31184 +/*
31185 + * values chosen so all counter values fit in a single UDP packet
31186 + */
31187 +#define PROFILE_NODE_MAX_COUNTERS 32
31188 +
31189 +struct profile_counter {
31190 +       char name[PROFILE_COUNTER_NAME_LENGTH];
31191 +       unsigned int value;
31192 +};
31193 +
31194 +struct profilenode {
31195 +       struct devtree_node dn;
31196 +       volatile u32_t enabled;                 /* Is the profiler enabled to take samples? */
31197 +       volatile u32_t busy;                    /* set when the samples are being read by the driver */
31198 +       volatile u32_t rate;                    /* What is the sampling rate? */
31199 +       volatile u32_t enabled_threads;         /* which threads were enabled at the last sample time */
31200 +       volatile u32_t hrt;                     /* HRT threads */
31201 +       volatile u32_t profiler_thread;         /* thread running the profile sampler */
31202 +       volatile u32_t clocks;                  /* system clock timer at last sample */
31203 +       volatile u32_t clock_freq;              /* clock frequency in Hz */
31204 +       volatile u32_t ddr_freq;                /* memory frequency */
31205 +       volatile u32_t cpu_id;                  /* chip_id register */
31206 +       volatile u32_t inst_count[PROFILE_MAX_THREADS];         /* sampled instruction counts at most recent sample */
31207 +       volatile u32_t stats[4];                                /* contents of the cache statistics counters */
31208 +       volatile u16_t head;                    /* sample taker puts samples here */
31209 +       volatile u16_t tail;                    /* packet filler takes samples here */
31210 +       volatile u16_t count;                   /* number of valid samples */
31211 +       volatile u16_t max_samples;             /* how many samples can be in the samples array */
31212 +       struct profile_sample *samples;         /* samples array allocated by the linux driver */
31213 +       volatile u32_t num_counters;            /* how many registered performance counters */
31214 +       volatile struct profile_counter counters[PROFILE_NODE_MAX_COUNTERS];
31215 +
31216 +       /* unimplemented interface for future oprofile work */
31217 +       volatile u16_t oprofile_head;           /* sample taker puts samples here */
31218 +       volatile u16_t oprofile_tail;           /* packet filler takes samples here */
31219 +       volatile u16_t oprofile_count;          /* how many oprofile sampels are are in use */
31220 +       volatile u16_t oprofile_max_samples;    /* samples array size for oprofile samples */
31221 +       struct oprofile_sample *oprofile_samples;       /* oprofile sample buffer */
31222 +};
31223 +
31224 +#endif
31225 --- /dev/null
31226 +++ b/arch/ubicom32/mach-common/profpkt.h
31227 @@ -0,0 +1,158 @@
31228 +
31229 +/*
31230 + * arch/ubicom32/mach-common/profpkt.c
31231 + *   Ubicom32 Profiler packet formats for communication between the linux proc driver and the profiler display tool
31232 + *
31233 + * (C) Copyright 2009, Ubicom, Inc.
31234 + *
31235 + * This file is part of the Ubicom32 Linux Kernel Port.
31236 + *
31237 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31238 + * it and/or modify it under the terms of the GNU General Public License
31239 + * as published by the Free Software Foundation, either version 2 of the
31240 + * License, or (at your option) any later version.
31241 + *
31242 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31243 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31244 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31245 + * the GNU General Public License for more details.
31246 + *
31247 + * You should have received a copy of the GNU General Public License
31248 + * along with the Ubicom32 Linux Kernel Port.  If not,
31249 + * see <http://www.gnu.org/licenses/>.
31250 + */
31251 +
31252 +#define PROFILE_PORT 51080
31253 +#define PROFILE_POSIX_NAME_LENGTH 32
31254 +
31255 +/*
31256 + * profile UDP packet format for communicating between ip3k and host
31257 + *
31258 + * every packet starts with a header, followed by samples.
31259 + * samples are only taken for non-hrt threads that are
31260 + * active
31261 + */
31262 +#define PROF_MAGIC 0x3ea0
31263 +#define PROF_MAGIC_COUNTERS 0x9ea0
31264 +#define PROF_MAGIC_MAPS 0xaea0
31265 +
31266 +/*
31267 + * Versions (31 max):
31268 + * 1 to 4 were before 6.0 release,  development versions
31269 + * 5 was forward compatible version, shipped with 6.0 and 6.1
31270 + * 6 adds heap packets, and clock_freq to header, shipped with 6.2
31271 + * 7 adds a sequence numbers to check for dropped packets, shipped with 6.3.5
31272 + * 8 adds mqueue timing information, shipped with 6.3.5
31273 + * 9 adds sdram heap size information, shipped with 6.4
31274 + * 10 adds heapmem heap callers and long latency stack traces.  shipped with 6.4
31275 + * 11 adds support for Mars (IP5K).  shipped with 6.10
31276 + * 12 adds more support for Mars.  Shipped with 7.0
31277 + * 13 adds per sample latency measurement.  Shipped with 7.2
31278 + * 14 changes the heap format and adds a string packet.  Shipped with 7.4
31279 + * 15 adds dsr stats and posix.  shipped with 7.6
31280 + * 16 corrects maximum packet count for Ares.  ships with 7.9
31281 + * 17 adds a5 register value to sample
31282 + */
31283 +
31284 +#define PROFILE_VERSION 17
31285 +#define PROFILE_MAX_PACKET_SIZE 1440
31286 +
31287 +#define PROFILE_MAX_THREADS 16
31288 +
31289 +/*
31290 + * each packet starts with a profile_header, then sample_count samples
31291 + * samples are gprof samples of pc, the return address, condition codes, and
31292 + * active threads
31293 + */
31294 +struct profile_header {
31295 +       u16_t magic;                    /* magic number and version */
31296 +       u8_t header_size;               /* number of bytes in profile header */
31297 +       u8_t sample_count;              /* number of samples in the packet */
31298 +       u32_t clocks;                   /* clock counter value */
31299 +       u32_t instruction_count[PROFILE_MAX_THREADS];
31300 +                                       /* instructions executed per thread */
31301 +       u32_t profile_instructions;     /* instructions executed by profiler mainline */
31302 +       u16_t enabled;                  /* which threads are enabled */
31303 +       u16_t hrt;                      /* which threads are hrt */
31304 +       u16_t high;                     /* which threads are high priority */
31305 +       u16_t profiler_thread;          /* which thread runs the profiler */
31306 +       u32_t heap_free;                /* current free on-cihp heap space in bytes */
31307 +       u32_t heap_low_water;           /* on-chip heap low water mark */
31308 +       u32_t netpage_free;             /* number of free on-chip net pages */
31309 +       u32_t netpage_low_water;        /* low water mark on free on-chip netpages */
31310 +       u32_t min_sp[PROFILE_MAX_THREADS];
31311 +                                       /* stack pointer values per thread */
31312 +       u32_t clock_freq;               /* clock frequency (Hz) of system being analyzed */
31313 +       u32_t seq_num;                  /* to detect dropped profiler packets */
31314 +       u32_t timing_sequence;          /* sample number since boot */
31315 +       u32_t timing_interval;          /* second per sample timing interval */
31316 +       u32_t timing_worst_time;        /* duration of longest finction called, in core clocks */
31317 +       u32_t timing_function;          /* address of longest function */
31318 +       u32_t timing_average;           /* average time of all functions in last interval */
31319 +       u32_t timing_count;             /* number of functions called in last interval */
31320 +       u32_t extheap_free;             /* current free extmem heap space in bytes */
31321 +       u32_t extheap_low_water;        /* extmem heap low water mark */
31322 +       u32_t cpu_id;                   /* CHIP_ID register contents */
31323 +       u32_t perf_counters[4];         /* contents of the CPU performance counters */
31324 +       u8_t perf_config[4];            /* what is being counted */
31325 +       u32_t ddr_freq;                 /* DDR clock frequency */
31326 +       u32_t extnetpage_free;          /* number of free off chip net pages */
31327 +       u32_t extnetpage_low_water;     /* low water mark on off-chip free netpages */
31328 +       u32_t dsr_max_latency;          /* max time to process a dsr interrupt, in clocks, since last packet */
31329 +       u32_t dsr_ave_latency;          /* average dsr latency over last DSR_STATS_RECENT_COUNT interrupts */
31330 +       u32_t dsr_count;                /* number of dsr interrupts since last packet */
31331 +};
31332 +
31333 +struct profile_header_counters {
31334 +       u16_t magic;
31335 +       u16_t ultra_count;              /* how many ultra counters follow this */
31336 +       u32_t ultra_sample_time;        /* in chip clocks */
31337 +       u32_t linux_count;              /* how many linux counters follow this */
31338 +       u32_t linux_sample_time;
31339 +};
31340 +
31341 +/*
31342 + * values chosen so all counter values fit in a single 1400 byte UDP packet
31343 + */
31344 +#define PROFILE_COUNTER_NAME_LENGTH 20
31345 +#define PROFILE_MAX_COUNTERS ((PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_counters)) / (PROFILE_COUNTER_NAME_LENGTH + 4))
31346 +
31347 +struct profile_counter_pkt {
31348 +       char name[PROFILE_COUNTER_NAME_LENGTH];
31349 +       unsigned int value;
31350 +};
31351 +
31352 +/*
31353 + * send memory maps from linux to profiler tool
31354 + */
31355 +
31356 +struct profile_header_maps {
31357 +       u16_t magic;
31358 +       u16_t count;
31359 +       u32_t page_shift;
31360 +};
31361 +
31362 +#define PROFILE_MAP_NUM_TYPES 32
31363 +
31364 +/* types 0-15: size field is order.  True size is 2^order */
31365 +#define PROFILE_MAP_TYPE_UNKNOWN 0
31366 +#define PROFILE_MAP_TYPE_FREE 1
31367 +#define PROFILE_MAP_TYPE_SMALL 2
31368 +#define PROFILE_MAP_TYPE_FS 3
31369 +/* types 16-31: size field is pages.  True size is (1 << PAGE_SHIFT) * size */
31370 +#define PROFILE_MAP_SIZE_TYPE 16
31371 +#define PROFILE_MAP_TYPE_TEXT 16
31372 +#define PROFILE_MAP_TYPE_STACK 17
31373 +#define PROFILE_MAP_TYPE_APP_DATA 18
31374 +#define PROFILE_MAP_TYPE_CACHE 19
31375 +#define PROFILE_MAP_RESERVED 24
31376 +
31377 +#define PROFILE_MAP_TYPE_SHIFT 11
31378 +#define PROFILE_MAP_SIZE_MASK 0x7ff
31379 +
31380 +struct profile_map {
31381 +       u16_t start;            /* start page number of segment, relative to start of DRAM */
31382 +       u16_t type_size;        /* type (4 bits) of the segment and size in pages (12 bits) */
31383 +};
31384 +
31385 +#define PROFILE_MAX_MAPS (PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_maps)) / sizeof(struct profile_map)
31386 --- /dev/null
31387 +++ b/arch/ubicom32/mach-common/ring_tio.c
31388 @@ -0,0 +1,123 @@
31389 +/*
31390 + * arch/ubicom32/mach-common/ring_tio.c
31391 + *   Generic initialization for UIO Ubicom32 Ring
31392 + *
31393 + * (C) Copyright 2009, Ubicom, Inc.
31394 + *
31395 + * This file is part of the Ubicom32 Linux Kernel Port.
31396 + *
31397 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31398 + * it and/or modify it under the terms of the GNU General Public License
31399 + * as published by the Free Software Foundation, either version 2 of the
31400 + * License, or (at your option) any later version.
31401 + *
31402 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31403 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31404 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31405 + * the GNU General Public License for more details.
31406 + *
31407 + * You should have received a copy of the GNU General Public License
31408 + * along with the Ubicom32 Linux Kernel Port.  If not,
31409 + * see <http://www.gnu.org/licenses/>.
31410 + */
31411 +
31412 +#include <linux/platform_device.h>
31413 +#include <linux/types.h>
31414 +
31415 +#include <asm/devtree.h>
31416 +#include <asm/ring_tio.h>
31417 +
31418 +static const char *ring_tio_driver_name = "uio_ubicom32ring";
31419 +
31420 +/*
31421 + * The number of ring_tio's currently allocated, used for .id
31422 + */
31423 +static int __initdata ring_tio_count;
31424 +
31425 +/*
31426 + * The maximum number of resources that the ring_tio will have.
31427 + * Currently 3, a register space, and up to 2 interrupts.
31428 + */
31429 +#define RING_TIO_MAX_RESOURCES 3
31430 +
31431 +/*
31432 + * ring_tio_init
31433 + *     Checks the device tree and instantiates the driver if found
31434 + */
31435 +void __init ring_tio_init(const char *node_name)
31436 +{
31437 +       struct platform_device *pdev;
31438 +       struct resource *res;
31439 +       int resource_idx = 0;
31440 +       struct ring_tio_node *ring_node;
31441 +
31442 +       /*
31443 +        * Check the device tree for the ring_tio
31444 +        */
31445 +       ring_node = (struct ring_tio_node *)devtree_find_node(node_name);
31446 +       if (!ring_node) {
31447 +               printk(KERN_WARNING "Ring TIO '%s' not found\n", node_name);
31448 +               return;
31449 +       }
31450 +
31451 +       if (ring_node->version != RING_TIO_NODE_VERSION) {
31452 +               printk(KERN_WARNING "ring_tio not compatible\n");
31453 +               return;
31454 +       }
31455 +
31456 +       /*
31457 +        * Dynamically create the platform_device structure and resources
31458 +        */
31459 +       pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
31460 +       if (!pdev) {
31461 +               printk(KERN_WARNING "ring_tio could not alloc pdev\n");
31462 +               return;
31463 +       }
31464 +
31465 +       res = kzalloc(sizeof(struct resource) * RING_TIO_MAX_RESOURCES,
31466 +                       GFP_KERNEL);
31467 +       if (!res) {
31468 +               kfree(pdev);
31469 +               printk(KERN_WARNING "ring_tio could not alloc res\n");
31470 +               return;
31471 +       }
31472 +
31473 +       pdev->name = ring_tio_driver_name;
31474 +       pdev->id = ring_tio_count++;
31475 +       pdev->resource = res;
31476 +
31477 +       /*
31478 +        * Fill in the resources and platform data from devtree information
31479 +        */
31480 +       res[resource_idx].start = (u32_t)(ring_node->regs);
31481 +       res[resource_idx].end = (u32_t)(ring_node->regs);
31482 +       res[resource_idx].flags = IORESOURCE_MEM;
31483 +       resource_idx++;
31484 +
31485 +       if (ring_node->dn.sendirq != 0xFF) {
31486 +               res[resource_idx].start = ring_node->dn.sendirq;
31487 +               res[resource_idx].flags = IORESOURCE_IRQ;
31488 +               resource_idx++;
31489 +       }
31490 +
31491 +       if (ring_node->dn.recvirq != 0xFF) {
31492 +               res[resource_idx].start = ring_node->dn.recvirq;
31493 +               res[resource_idx].flags = IORESOURCE_IRQ;
31494 +               resource_idx++;
31495 +       }
31496 +       pdev->num_resources = resource_idx;
31497 +
31498 +       printk(KERN_INFO "RingTIO.%d '%s' found irq=%d/%d regs=%p pdev=%p/%p\n",
31499 +               ring_tio_count - 1, node_name, ring_node->dn.sendirq,
31500 +               ring_node->dn.recvirq, ring_node->regs, pdev, res);
31501 +
31502 +       /*
31503 +        * Try to get the device registered
31504 +        */
31505 +       pdev->dev.platform_data = (void *)node_name;
31506 +       if (platform_device_register(pdev) < 0) {
31507 +               printk(KERN_WARNING "Ring failed to register\n");
31508 +               kfree(pdev);
31509 +               kfree(res);
31510 +       }
31511 +}
31512 --- /dev/null
31513 +++ b/arch/ubicom32/mach-common/switch-bcm539x.c
31514 @@ -0,0 +1,1195 @@
31515 +/*
31516 + * arch/ubicom32/mach-common/switch-bcm539x.c
31517 + *   BCM539X switch driver, SPI mode
31518 + *
31519 + * (C) Copyright 2009, Ubicom, Inc.
31520 + *
31521 + * This file is part of the Ubicom32 Linux Kernel Port.
31522 + *
31523 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31524 + * it and/or modify it under the terms of the GNU General Public License
31525 + * as published by the Free Software Foundation, either version 2 of the
31526 + * License, or (at your option) any later version.
31527 + *
31528 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31529 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31530 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
31531 + * the GNU General Public License for more details.
31532 + *
31533 + * You should have received a copy of the GNU General Public License
31534 + * along with the Ubicom32 Linux Kernel Port.  If not,
31535 + * see <http://www.gnu.org/licenses/>.
31536 + *
31537 + * Ubicom32 implementation derived from (with many thanks):
31538 + *   arch/m68knommu
31539 + *   arch/blackfin
31540 + *   arch/parisc
31541 + */
31542 +
31543 +#include <linux/platform_device.h>
31544 +#include <linux/spi/spi.h>
31545 +#include <linux/gpio.h>
31546 +#include <linux/delay.h>
31547 +#include <linux/mii.h>
31548 +
31549 +#include <asm/switch-dev.h>
31550 +#include <asm/ubicom32-spi-gpio.h>
31551 +#include "switch-core.h"
31552 +#include "switch-bcm539x-reg.h"
31553 +
31554 +#define DRIVER_NAME "bcm539x-spi"
31555 +#define DRIVER_VERSION "1.0"
31556 +
31557 +#undef BCM539X_DEBUG
31558 +#define BCM539X_SPI_RETRIES    100
31559 +
31560 +struct bcm539x_data {
31561 +       struct switch_device                    *switch_dev;
31562 +
31563 +       /*
31564 +        * Our private data
31565 +        */
31566 +       struct spi_device                       *spi;
31567 +       struct switch_core_platform_data        *pdata;
31568 +
31569 +       /*
31570 +        * Last page we accessed
31571 +        */
31572 +       u8_t                                    last_page;
31573 +
31574 +       /*
31575 +        * 539x Device ID
31576 +        */
31577 +       u8_t                                    device_id;
31578 +};
31579 +
31580 +/*
31581 + * bcm539x_wait_status
31582 + *     Waits for the specified bit in the status register to be set/cleared.
31583 + */
31584 +static int bcm539x_wait_status(struct bcm539x_data *bd, u8_t mask, int set)
31585 +{
31586 +       u8_t txbuf[2];
31587 +       u8_t rxbuf;
31588 +       int i;
31589 +       int ret;
31590 +
31591 +       txbuf[0] = BCM539X_CMD_READ;
31592 +       txbuf[1] = BCM539X_GLOBAL_SPI_STATUS;
31593 +       for (i = 0; i < BCM539X_SPI_RETRIES; i++) {
31594 +               ret = spi_write_then_read(bd->spi, txbuf, 2, &rxbuf, 1);
31595 +               rxbuf &= mask;
31596 +               if ((set && rxbuf) || (!set && !rxbuf)) {
31597 +                       return 0;
31598 +               }
31599 +               udelay(1);
31600 +       }
31601 +
31602 +       return -EIO;
31603 +}
31604 +
31605 +/*
31606 + * bcm539x_set_page
31607 + *     Sets the register page for access (only if necessary)
31608 + */
31609 +static int bcm539x_set_page(struct bcm539x_data *bd, u8_t page)
31610 +{
31611 +       u8_t txbuf[3];
31612 +
31613 +       if (page == bd->last_page) {
31614 +               return 0;
31615 +       }
31616 +
31617 +       bd->last_page = page;
31618 +
31619 +       txbuf[0] = BCM539X_CMD_WRITE;
31620 +       txbuf[1] = BCM539X_GLOBAL_PAGE;
31621 +       txbuf[2] = page;
31622 +
31623 +       return spi_write(bd->spi, txbuf, 3);
31624 +}
31625 +
31626 +/*
31627 + * bcm539x_write_bytes
31628 + *     Writes a number of bytes to a given page and register
31629 + */
31630 +static int bcm539x_write_bytes(struct bcm539x_data *bd, u8_t page,
31631 +                              u8_t reg, void *buf, u8_t len)
31632 +{
31633 +       int ret;
31634 +       u8_t *txbuf;
31635 +
31636 +       txbuf = kmalloc(2 + len, GFP_KERNEL);
31637 +       if (!txbuf) {
31638 +               return -ENOMEM;
31639 +       }
31640 +
31641 +       /*
31642 +        * Make sure the chip has finished processing our previous request
31643 +        */
31644 +       ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31645 +       if (ret) {
31646 +               goto done;
31647 +       }
31648 +
31649 +       /*
31650 +        * Set the page
31651 +        */
31652 +       ret = bcm539x_set_page(bd, page);
31653 +       if (ret) {
31654 +               goto done;
31655 +       }
31656 +
31657 +       /*
31658 +        * Read the data
31659 +        */
31660 +       txbuf[0] = BCM539X_CMD_WRITE;
31661 +       txbuf[1] = reg;
31662 +       memcpy(&txbuf[2], buf, len);
31663 +
31664 +#ifdef BCM539X_DEBUG
31665 +       {
31666 +               int i;
31667 +               printk("write page %02x reg %02x len=%d buf=", page, reg, len);
31668 +               for (i = 0; i < len + 2; i++) {
31669 +                       printk("%02x ", txbuf[i]);
31670 +               }
31671 +               printk("\n");
31672 +       }
31673 +#endif
31674 +
31675 +       ret = spi_write(bd->spi, txbuf, 2 + len);
31676 +
31677 +done:
31678 +       kfree(txbuf);
31679 +       return ret;
31680 +}
31681 +
31682 +/*
31683 + * bcm539x_write_32
31684 + *     Writes 32 bits of data to the given page and register
31685 + */
31686 +static inline int bcm539x_write_32(struct bcm539x_data *bd, u8_t page,
31687 +                                  u8_t reg, u32_t data)
31688 +{
31689 +       data = cpu_to_le32(data);
31690 +       return bcm539x_write_bytes(bd, page, reg, &data, 4);
31691 +}
31692 +
31693 +/*
31694 + * bcm539x_write_16
31695 + *     Writes 16 bits of data to the given page and register
31696 + */
31697 +static inline int bcm539x_write_16(struct bcm539x_data *bd, u8_t page,
31698 +                                  u8_t reg, u16_t data)
31699 +{
31700 +       data = cpu_to_le16(data);
31701 +       return bcm539x_write_bytes(bd, page, reg, &data, 2);
31702 +}
31703 +
31704 +/*
31705 + * bcm539x_write_8
31706 + *     Writes 8 bits of data to the given page and register
31707 + */
31708 +static inline int bcm539x_write_8(struct bcm539x_data *bd, u8_t page,
31709 +                                 u8_t reg, u8_t data)
31710 +{
31711 +       return bcm539x_write_bytes(bd, page, reg, &data, 1);
31712 +}
31713 +
31714 +/*
31715 + * bcm539x_read_bytes
31716 + *     Reads a number of bytes from a given page and register
31717 + */
31718 +static int bcm539x_read_bytes(struct bcm539x_data *bd, u8_t page,
31719 +                             u8_t reg, void *buf, u8_t len)
31720 +{
31721 +       u8_t txbuf[2];
31722 +       int ret;
31723 +
31724 +       /*
31725 +        * (1) Make sure the chip has finished processing our previous request
31726 +        */
31727 +       ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31728 +       if (ret) {
31729 +               return ret;
31730 +       }
31731 +
31732 +       /*
31733 +        * (2) Set the page
31734 +        */
31735 +       ret = bcm539x_set_page(bd, page);
31736 +       if (ret) {
31737 +               return ret;
31738 +       }
31739 +
31740 +       /*
31741 +        * (3) Kick off the register read
31742 +        */
31743 +       txbuf[0] = BCM539X_CMD_READ;
31744 +       txbuf[1] = reg;
31745 +       ret = spi_write_then_read(bd->spi, txbuf, 2, txbuf, 1);
31746 +       if (ret) {
31747 +               return ret;
31748 +       }
31749 +
31750 +       /*
31751 +        * (4) Wait for RACK
31752 +        */
31753 +       ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_RACK, 1);
31754 +       if (ret) {
31755 +               return ret;
31756 +       }
31757 +
31758 +       /*
31759 +        * (5) Read the data
31760 +        */
31761 +       txbuf[0] = BCM539X_CMD_READ;
31762 +       txbuf[1] = BCM539X_GLOBAL_SPI_DATA0;
31763 +
31764 +       ret = spi_write_then_read(bd->spi, txbuf, 2, buf, len);
31765 +
31766 +#ifdef BCM539X_DEBUG
31767 +       {
31768 +               int i;
31769 +               printk("read page %02x reg %02x len=%d rxbuf=",
31770 +                      page, reg, len);
31771 +               for (i = 0; i < len; i++) {
31772 +                       printk("%02x ", ((u8_t *)buf)[i]);
31773 +               }
31774 +               printk("\n");
31775 +       }
31776 +#endif
31777 +
31778 +       return ret;
31779 +}
31780 +
31781 +/*
31782 + * bcm539x_read_32
31783 + *     Reads an 32 bit number from a given page and register
31784 + */
31785 +static int bcm539x_read_32(struct bcm539x_data *bd, u8_t page,
31786 +                          u8_t reg, u32_t *buf)
31787 +{
31788 +       int ret = bcm539x_read_bytes(bd, page, reg, buf, 4);
31789 +       *buf = le32_to_cpu(*buf);
31790 +       return ret;
31791 +}
31792 +
31793 +/*
31794 + * bcm539x_read_16
31795 + *     Reads an 16 bit number from a given page and register
31796 + */
31797 +static int bcm539x_read_16(struct bcm539x_data *bd, u8_t page,
31798 +                          u8_t reg, u16_t *buf)
31799 +{
31800 +       int ret = bcm539x_read_bytes(bd, page, reg, buf, 2);
31801 +       *buf = le16_to_cpu(*buf);
31802 +       return ret;
31803 +}
31804 +
31805 +/*
31806 + * bcm539x_read_8
31807 + *     Reads an 8 bit number from a given page and register
31808 + */
31809 +static int bcm539x_read_8(struct bcm539x_data *bd, u8_t page,
31810 +                         u8_t reg, u8_t *buf)
31811 +{
31812 +       return bcm539x_read_bytes(bd, page, reg, buf, 1);
31813 +}
31814 +
31815 +/*
31816 + * bcm539x_set_mode
31817 + */
31818 +static int bcm539x_set_mode(struct bcm539x_data *bd, int state)
31819 +{
31820 +       u8_t buf;
31821 +       int ret;
31822 +
31823 +       ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &buf);
31824 +       if (ret) {
31825 +               return ret;
31826 +       }
31827 +
31828 +       buf &= ~(1 << 1);
31829 +       buf |= state ? (1 << 1) : 0;
31830 +
31831 +       ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, buf);
31832 +       return ret;
31833 +}
31834 +
31835 +/*
31836 + * bcm539x_handle_reset
31837 + */
31838 +static int bcm539x_handle_reset(struct switch_device *dev, char *buf, int inst)
31839 +{
31840 +       struct bcm539x_data *bd =
31841 +               (struct bcm539x_data *)switch_get_drvdata(dev);
31842 +       int ret;
31843 +
31844 +       ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST,
31845 +                             (1 << 7) | (1 << 4));
31846 +       if (ret) {
31847 +               return ret;
31848 +       }
31849 +
31850 +       udelay(20);
31851 +
31852 +       ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST, 0);
31853 +       return ret;
31854 +}
31855 +
31856 +/*
31857 + * bcm539x_handle_vlan_ports_read
31858 + */
31859 +static int bcm539x_handle_vlan_ports_read(struct switch_device *dev,
31860 +                                         char *buf, int inst)
31861 +{
31862 +       struct bcm539x_data *bd =
31863 +               (struct bcm539x_data *)switch_get_drvdata(dev);
31864 +       int j;
31865 +       int len = 0;
31866 +       u8_t rxbuf8;
31867 +       u32_t rxbuf32;
31868 +       int ret;
31869 +
31870 +       ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
31871 +       if (ret) {
31872 +               return ret;
31873 +       }
31874 +
31875 +       ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
31876 +                             (1 << 7) | 1);
31877 +       if (ret) {
31878 +               return ret;
31879 +       }
31880 +
31881 +       /*
31882 +        * Wait for completion
31883 +        */
31884 +       for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
31885 +               ret = bcm539x_read_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
31886 +                                    &rxbuf8);
31887 +               if (ret) {
31888 +                       return ret;
31889 +               }
31890 +               if (!(rxbuf8 & (1 << 7))) {
31891 +                       break;
31892 +               }
31893 +       }
31894 +
31895 +       if (j == BCM539X_SPI_RETRIES) {
31896 +               return -EIO;
31897 +       }
31898 +
31899 +       /*
31900 +        * Read the table entry
31901 +        */
31902 +       ret = bcm539x_read_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, &rxbuf32);
31903 +       if (ret) {
31904 +               return ret;
31905 +       }
31906 +
31907 +       for (j = 0; j < 9; j++) {
31908 +               if (rxbuf32 & (1 << j)) {
31909 +                       u16_t rxbuf16;
31910 +                       len += sprintf(buf + len, "%d", j);
31911 +                       if (rxbuf32 & (1 << (j + 9))) {
31912 +                               buf[len++] = 'u';
31913 +                       } else {
31914 +                               buf[len++] = 't';
31915 +                       }
31916 +                       ret = bcm539x_read_16(bd, PAGE_VLAN,
31917 +                                             REG_VLAN_PTAG0 + (j << 1),
31918 +                                             &rxbuf16);
31919 +                       if (ret) {
31920 +                               return ret;
31921 +                       }
31922 +                       if (rxbuf16 == inst) {
31923 +                               buf[len++] = '*';
31924 +                       }
31925 +                       buf[len++] = '\t';
31926 +               }
31927 +       }
31928 +
31929 +       len += sprintf(buf + len, "\n");
31930 +       buf[len] = '\0';
31931 +
31932 +       return len;
31933 +}
31934 +
31935 +/*
31936 + * bcm539x_handle_vlan_ports_write
31937 + */
31938 +static int bcm539x_handle_vlan_ports_write(struct switch_device *dev,
31939 +                                          char *buf, int inst)
31940 +{
31941 +       struct bcm539x_data *bd =
31942 +               (struct bcm539x_data *)switch_get_drvdata(dev);
31943 +       int j;
31944 +       u32_t untag;
31945 +       u32_t ports;
31946 +       u32_t def;
31947 +
31948 +       u8_t rxbuf8;
31949 +       u16_t rxbuf16;
31950 +       int ret;
31951 +
31952 +       switch_parse_vlan_ports(dev, buf, &untag, &ports, &def);
31953 +
31954 +#ifdef BCM539X_DEBUG
31955 +       printk(KERN_DEBUG "'%s' inst=%d untag=%08x ports=%08x def=%08x\n",
31956 +               buf, inst, untag, ports, def);
31957 +#endif
31958 +
31959 +       if (!ports) {
31960 +               return 0;
31961 +       }
31962 +
31963 +       /*
31964 +        * Change default vlan tag
31965 +        */
31966 +       for (j = 0; j < 9; j++) {
31967 +               if ((untag | def) & (1 << j)) {
31968 +                       ret = bcm539x_write_16(bd, PAGE_VLAN,
31969 +                                              REG_VLAN_PTAG0 + (j << 1),
31970 +                                              inst);
31971 +                       if (ret) {
31972 +                               return ret;
31973 +                       }
31974 +                       continue;
31975 +               }
31976 +
31977 +               if (!(dev->port_mask[0] & (1 << j))) {
31978 +                       continue;
31979 +               }
31980 +
31981 +               /*
31982 +                * Remove any ports which are not listed anymore as members of
31983 +                * this vlan
31984 +                */
31985 +               ret = bcm539x_read_16(bd, PAGE_VLAN,
31986 +                                     REG_VLAN_PTAG0 + (j << 1), &rxbuf16);
31987 +               if (ret) {
31988 +                       return ret;
31989 +               }
31990 +               if (rxbuf16 == inst) {
31991 +                       ret = bcm539x_write_16(bd, PAGE_VLAN,
31992 +                                              REG_VLAN_PTAG0 + (j << 1), 0);
31993 +                       if (ret) {
31994 +                               return ret;
31995 +                       }
31996 +               }
31997 +       }
31998 +
31999 +       /*
32000 +        * Write the VLAN table
32001 +        */
32002 +       ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
32003 +       if (ret) {
32004 +               return ret;
32005 +       }
32006 +
32007 +       ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395,
32008 +                              (untag << 9) | ports);
32009 +       if (ret) {
32010 +               return ret;
32011 +       }
32012 +
32013 +       ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32014 +                             (1 << 7) | 0);
32015 +       if (ret) {
32016 +               return ret;
32017 +       }
32018 +
32019 +       /*
32020 +        * Wait for completion
32021 +        */
32022 +       for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32023 +               ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32024 +                                        &rxbuf8, 1);
32025 +               if (ret) {
32026 +                       return ret;
32027 +               }
32028 +               if (!(rxbuf8 & (1 << 7))) {
32029 +                       break;
32030 +               }
32031 +       }
32032 +
32033 +       return (j < BCM539X_SPI_RETRIES) ? 0 : -EIO;
32034 +}
32035 +
32036 +/*
32037 + * Handlers for <this_driver>/vlan/<vlan_id>
32038 + */
32039 +static const struct switch_handler bcm539x_switch_handlers_vlan_dir[] = {
32040 +       {
32041 +               .name   = "ports",
32042 +               .read   = bcm539x_handle_vlan_ports_read,
32043 +               .write  = bcm539x_handle_vlan_ports_write,
32044 +       },
32045 +       {
32046 +       },
32047 +};
32048 +
32049 +/*
32050 + * bcm539x_handle_vlan_delete_write
32051 + */
32052 +static int bcm539x_handle_vlan_delete_write(struct switch_device *dev,
32053 +                                           char *buf, int inst)
32054 +{
32055 +       struct bcm539x_data *bd =
32056 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32057 +       int vid;
32058 +       u8_t rxbuf8;
32059 +       u32_t txbuf;
32060 +       int j;
32061 +       int ret;
32062 +
32063 +       vid = simple_strtoul(buf, NULL, 0);
32064 +       if (!vid) {
32065 +               return -EINVAL;
32066 +       }
32067 +
32068 +       /*
32069 +        * Disable this VLAN
32070 +        *
32071 +        * Go through the port-based vlan registers and clear the appropriate
32072 +        * ones out
32073 +        */
32074 +       for (j = 0; j < 9; j++) {
32075 +               u16_t rxbuf16;
32076 +               ret = bcm539x_read_16(bd, PAGE_VLAN, REG_VLAN_PTAG0 + (j << 1),
32077 +                                     &rxbuf16);
32078 +               if (ret) {
32079 +                       return ret;
32080 +               }
32081 +               if (rxbuf16 == vid) {
32082 +                       txbuf = 0;
32083 +                       ret = bcm539x_write_16(bd, PAGE_VLAN,
32084 +                                              REG_VLAN_PTAG0 + (j << 1),
32085 +                                              txbuf);
32086 +                       if (ret) {
32087 +                               return ret;
32088 +                       }
32089 +               }
32090 +       }
32091 +
32092 +       /*
32093 +        * Write the VLAN table
32094 +        */
32095 +       txbuf = vid;
32096 +       ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, txbuf);
32097 +       if (ret) {
32098 +               return ret;
32099 +       }
32100 +
32101 +       txbuf = 0;
32102 +       ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, txbuf);
32103 +       if (ret) {
32104 +               return ret;
32105 +       }
32106 +
32107 +       txbuf = (1 << 7) | (0);
32108 +       ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395, txbuf);
32109 +       if (ret) {
32110 +               return ret;
32111 +       }
32112 +
32113 +       /*
32114 +        * Wait for completion
32115 +        */
32116 +       for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32117 +               ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32118 +                                        &rxbuf8, 1);
32119 +               if (ret) {
32120 +                       return ret;
32121 +               }
32122 +               if (!(rxbuf8 & (1 << 7))) {
32123 +                       break;
32124 +               }
32125 +       }
32126 +
32127 +       if (j == BCM539X_SPI_RETRIES) {
32128 +               return -EIO;
32129 +       }
32130 +
32131 +       return switch_remove_vlan_dir(dev, vid);
32132 +}
32133 +
32134 +/*
32135 + * bcm539x_handle_vlan_create_write
32136 + */
32137 +static int bcm539x_handle_vlan_create_write(struct switch_device *dev,
32138 +                                           char *buf, int inst)
32139 +{
32140 +       int vid;
32141 +
32142 +       vid = simple_strtoul(buf, NULL, 0);
32143 +       if (!vid) {
32144 +               return -EINVAL;
32145 +       }
32146 +
32147 +       return switch_create_vlan_dir(dev, vid,
32148 +                                     bcm539x_switch_handlers_vlan_dir);
32149 +}
32150 +
32151 +/*
32152 + * bcm539x_handle_enable_read
32153 + */
32154 +static int bcm539x_handle_enable_read(struct switch_device *dev,
32155 +                                     char *buf, int inst)
32156 +{
32157 +       struct bcm539x_data *bd =
32158 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32159 +       u8_t rxbuf;
32160 +       int ret;
32161 +
32162 +       ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &rxbuf);
32163 +       if (ret) {
32164 +               return ret;
32165 +       }
32166 +       rxbuf = (rxbuf & (1 << 1)) ? 1 : 0;
32167 +
32168 +       return sprintf(buf, "%d\n", rxbuf);
32169 +}
32170 +
32171 +/*
32172 + * bcm539x_handle_enable_write
32173 + */
32174 +static int bcm539x_handle_enable_write(struct switch_device *dev,
32175 +                                      char *buf, int inst)
32176 +{
32177 +       struct bcm539x_data *bd =
32178 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32179 +
32180 +       return bcm539x_set_mode(bd, buf[0] == '1');
32181 +}
32182 +
32183 +/*
32184 + * bcm539x_handle_enable_vlan_read
32185 + */
32186 +static int bcm539x_handle_enable_vlan_read(struct switch_device *dev,
32187 +                                          char *buf, int inst)
32188 +{
32189 +       struct bcm539x_data *bd =
32190 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32191 +       u8_t rxbuf;
32192 +       int ret;
32193 +
32194 +       ret = bcm539x_read_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, &rxbuf);
32195 +       if (ret) {
32196 +               return ret;
32197 +       }
32198 +       rxbuf = (rxbuf & (1 << 7)) ? 1 : 0;
32199 +
32200 +       return sprintf(buf, "%d\n", rxbuf);
32201 +}
32202 +
32203 +/*
32204 + * bcm539x_handle_enable_vlan_write
32205 + */
32206 +static int bcm539x_handle_enable_vlan_write(struct switch_device *dev,
32207 +                                           char *buf, int inst)
32208 +{
32209 +       struct bcm539x_data *bd =
32210 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32211 +       int ret;
32212 +
32213 +       /*
32214 +        * disable 802.1Q VLANs
32215 +        */
32216 +       if (buf[0] != '1') {
32217 +               ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, 0);
32218 +               return ret;
32219 +       }
32220 +
32221 +       /*
32222 +        * enable 802.1Q VLANs
32223 +        *
32224 +        * Enable 802.1Q | IVL learning
32225 +        */
32226 +       ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0,
32227 +                             (1 << 7) | (3 << 5));
32228 +       if (ret) {
32229 +               return ret;
32230 +       }
32231 +
32232 +       /*
32233 +        * RSV multicast fwd | RSV multicast chk
32234 +        */
32235 +       ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL1,
32236 +                             (1 << 2) | (1 << 3));
32237 +       if (ret) {
32238 +               return ret;
32239 +       }
32240 +#if 0
32241 +       /*
32242 +        * Drop invalid VID
32243 +        */
32244 +       ret = bcm539x_write_16(bd, PAGE_VLAN, REG_VLAN_CTRL3, 0x00FF);
32245 +       if (ret) {
32246 +               return ret;
32247 +       }
32248 +#endif
32249 +       return 0;
32250 +}
32251 +
32252 +/*
32253 + * bcm539x_handle_port_enable_read
32254 + */
32255 +static int bcm539x_handle_port_enable_read(struct switch_device *dev,
32256 +                                          char *buf, int inst)
32257 +{
32258 +       return sprintf(buf, "%d\n", 1);
32259 +}
32260 +
32261 +/*
32262 + * bcm539x_handle_port_enable_write
32263 + */
32264 +static int bcm539x_handle_port_enable_write(struct switch_device *dev,
32265 +                                           char *buf, int inst)
32266 +{
32267 +       /*
32268 +        * validate port
32269 +        */
32270 +       if (!(dev->port_mask[0] & (1 << inst))) {
32271 +               return -EIO;
32272 +       }
32273 +
32274 +       if (buf[0] != '1') {
32275 +               printk(KERN_WARNING "switch port[%d] disabling is not supported\n", inst);
32276 +       }
32277 +       return 0;
32278 +}
32279 +
32280 +/*
32281 + * bcm539x_handle_port_state_read
32282 + */
32283 +static int bcm539x_handle_port_state_read(struct switch_device *dev,
32284 +                                          char *buf, int inst)
32285 +{
32286 +       struct bcm539x_data *bd =
32287 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32288 +       int ret;
32289 +       u16_t link;
32290 +
32291 +       /*
32292 +        * validate port
32293 +        */
32294 +       if (!(dev->port_mask[0] & (1 << inst))) {
32295 +               return -EIO;
32296 +       }
32297 +
32298 +       /*
32299 +        * check PHY link state - CPU port (port 8) is always up
32300 +        */
32301 +       ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32302 +       if (ret) {
32303 +               return ret;
32304 +       }
32305 +       link |= (1 << 8);
32306 +
32307 +       return sprintf(buf, "%d\n", (link & (1 << inst)) ? 1 : 0);
32308 +}
32309 +
32310 +/*
32311 + * bcm539x_handle_port_media_read
32312 + */
32313 +static int bcm539x_handle_port_media_read(struct switch_device *dev,
32314 +                                          char *buf, int inst)
32315 +{
32316 +       struct bcm539x_data *bd =
32317 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32318 +       int ret;
32319 +       u16_t link, duplex;
32320 +       u32_t speed;
32321 +
32322 +       /*
32323 +        * validate port
32324 +        */
32325 +       if (!(dev->port_mask[0] & (1 << inst))) {
32326 +               return -EIO;
32327 +       }
32328 +
32329 +       /*
32330 +        * check PHY link state first - CPU port (port 8) is always up
32331 +        */
32332 +       ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32333 +       if (ret) {
32334 +               return ret;
32335 +       }
32336 +       link |= (1 << 8);
32337 +
32338 +       if (!(link & (1 << inst))) {
32339 +               return sprintf(buf, "UNKNOWN\n");
32340 +       }
32341 +
32342 +       /*
32343 +        * get link speeda dn duplex - CPU port (port 8) is 1000/full
32344 +        */
32345 +       ret = bcm539x_read_32(bd, PAGE_STATUS, 4, &speed);
32346 +       if (ret) {
32347 +               return ret;
32348 +       }
32349 +       speed |= (2 << 16);
32350 +       speed = (speed >> (2 * inst)) & 3;
32351 +
32352 +       ret = bcm539x_read_16(bd, PAGE_STATUS, 8, &duplex);
32353 +       if (ret) {
32354 +               return ret;
32355 +       }
32356 +       duplex |= (1 << 8);
32357 +       duplex = (duplex >> inst) & 1;
32358 +
32359 +       return sprintf(buf, "%d%cD\n",
32360 +               (speed == 0) ? 10 : ((speed == 1) ? 100 : 1000),
32361 +               duplex ? 'F' : 'H');
32362 +}
32363 +
32364 +/*
32365 + * bcm539x_handle_port_meida_write
32366 + */
32367 +static int bcm539x_handle_port_meida_write(struct switch_device *dev,
32368 +                                           char *buf, int inst)
32369 +{
32370 +       struct bcm539x_data *bd =
32371 +               (struct bcm539x_data *)switch_get_drvdata(dev);
32372 +       int ret;
32373 +       u16_t ctrl_word, local_cap, local_giga_cap;
32374 +
32375 +       /*
32376 +        * validate port (not for CPU port)
32377 +        */
32378 +       if (!(dev->port_mask[0] & (1 << inst) & ~(1 << 8))) {
32379 +               return -EIO;
32380 +       }
32381 +
32382 +       /*
32383 +        * Get the maximum capability from status
32384 +        *      SPI reg[0x00] = PHY[0x0] --- MII control
32385 +        *      SPI reg[0x08] = PHY[0x4] --- MII local capability
32386 +        *      SPI reg[0x12] = PHY[0x9] --- GMII control
32387 +        */
32388 +       ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), &local_cap);
32389 +       if (ret) {
32390 +               return ret;
32391 +       }
32392 +       ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), &local_giga_cap);
32393 +       if (ret) {
32394 +               return ret;
32395 +       }
32396 +
32397 +       /* Configure to the requested speed */
32398 +       if (strncmp(buf, "1000FD", 6) == 0) {
32399 +               /* speed */
32400 +               local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32401 +               local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32402 +               local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32403 +               /* duplex */
32404 +       } else if (strncmp(buf, "100FD", 5) == 0) {
32405 +               /* speed */
32406 +               local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32407 +               local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32408 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32409 +               /* duplex */
32410 +               local_cap &= ~(ADVERTISE_100HALF);
32411 +       } else if (strncmp(buf, "100HD", 5) == 0) {
32412 +               /* speed */
32413 +               local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32414 +               local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32415 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32416 +               /* duplex */
32417 +               local_cap &= ~(ADVERTISE_100FULL);
32418 +       } else if (strncmp(buf, "10FD", 4) == 0) {
32419 +               /* speed */
32420 +               local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32421 +               local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32422 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32423 +               /* duplex */
32424 +               local_cap &= ~(ADVERTISE_10HALF);
32425 +       } else if (strncmp(buf, "10HD", 4) == 0) {
32426 +               /* speed */
32427 +               local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32428 +               local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32429 +               local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32430 +               /* duplex */
32431 +               local_cap &= ~(ADVERTISE_10FULL);
32432 +       } else if (strncmp(buf, "AUTO", 4) == 0) {
32433 +               /* speed */
32434 +               local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32435 +               local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32436 +               local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32437 +       } else {
32438 +               return -EINVAL;
32439 +       }
32440 +
32441 +       /* Active PHY with the requested speed for auto-negotiation */
32442 +       ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), local_cap);
32443 +       if (ret) {
32444 +               return ret;
32445 +       }
32446 +       ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), local_giga_cap);
32447 +       if (ret) {
32448 +               return ret;
32449 +       }
32450 +
32451 +       ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), &ctrl_word);
32452 +       if (ret) {
32453 +               return ret;
32454 +       }
32455 +       ctrl_word |= (BMCR_ANENABLE | BMCR_ANRESTART);
32456 +       ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), ctrl_word);
32457 +       if (ret) {
32458 +               return ret;
32459 +       }
32460 +
32461 +       return 0;
32462 +}
32463 +
32464 +/*
32465 + * proc_fs entries for this switch
32466 + */
32467 +static const struct switch_handler bcm539x_switch_handlers[] = {
32468 +       {
32469 +               .name   = "enable",
32470 +               .read   = bcm539x_handle_enable_read,
32471 +               .write  = bcm539x_handle_enable_write,
32472 +       },
32473 +       {
32474 +               .name   = "enable_vlan",
32475 +               .read   = bcm539x_handle_enable_vlan_read,
32476 +               .write  = bcm539x_handle_enable_vlan_write,
32477 +       },
32478 +       {
32479 +               .name   = "reset",
32480 +               .write  = bcm539x_handle_reset,
32481 +       },
32482 +       {
32483 +       },
32484 +};
32485 +
32486 +/*
32487 + * Handlers for <this_driver>/vlan
32488 + */
32489 +static const struct switch_handler bcm539x_switch_handlers_vlan[] = {
32490 +       {
32491 +               .name   = "delete",
32492 +               .write  = bcm539x_handle_vlan_delete_write,
32493 +       },
32494 +       {
32495 +               .name   = "create",
32496 +               .write  = bcm539x_handle_vlan_create_write,
32497 +       },
32498 +       {
32499 +       },
32500 +};
32501 +
32502 +/*
32503 + * Handlers for <this_driver>/port/<port number>
32504 + */
32505 +static const struct switch_handler bcm539x_switch_handlers_port[] = {
32506 +       {
32507 +               .name   = "enable",
32508 +               .read   = bcm539x_handle_port_enable_read,
32509 +               .write  = bcm539x_handle_port_enable_write,
32510 +       },
32511 +       {
32512 +               .name   = "state",
32513 +               .read   = bcm539x_handle_port_state_read,
32514 +       },
32515 +       {
32516 +               .name   = "media",
32517 +               .read   = bcm539x_handle_port_media_read,
32518 +               .write  = bcm539x_handle_port_meida_write,
32519 +       },
32520 +       {
32521 +       },
32522 +};
32523 +
32524 +/*
32525 + * bcm539x_probe
32526 + */
32527 +static int __devinit bcm539x_probe(struct spi_device *spi)
32528 +{
32529 +       struct bcm539x_data *bd;
32530 +       struct switch_core_platform_data *pdata;
32531 +       struct switch_device *switch_dev = NULL;
32532 +       int i, ret;
32533 +       u8_t txbuf[2];
32534 +
32535 +       pdata = spi->dev.platform_data;
32536 +       if (!pdata) {
32537 +               return -EINVAL;
32538 +       }
32539 +
32540 +       ret = spi_setup(spi);
32541 +       if (ret < 0) {
32542 +               return ret;
32543 +       }
32544 +
32545 +       /*
32546 +        * Reset the chip if requested
32547 +        */
32548 +       if (pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32549 +               ret = gpio_request(pdata->pin_reset, "switch-bcm539x-reset");
32550 +               if (ret) {
32551 +                       printk(KERN_WARNING "Could not request reset\n");
32552 +                       return -EINVAL;
32553 +               }
32554 +
32555 +               gpio_direction_output(pdata->pin_reset, 0);
32556 +               udelay(10);
32557 +               gpio_set_value(pdata->pin_reset, 1);
32558 +               udelay(20);
32559 +       }
32560 +
32561 +       /*
32562 +        * Allocate our private data structure
32563 +        */
32564 +       bd = kzalloc(sizeof(struct bcm539x_data), GFP_KERNEL);
32565 +       if (!bd) {
32566 +               return -ENOMEM;
32567 +       }
32568 +
32569 +       dev_set_drvdata(&spi->dev, bd);
32570 +       bd->pdata = pdata;
32571 +       bd->spi = spi;
32572 +       bd->last_page = 0xFF;
32573 +
32574 +       /*
32575 +        * First perform SW reset if needed
32576 +        */
32577 +       if (pdata->flags & SWITCH_DEV_FLAG_SW_RESET) {
32578 +               txbuf[0] = (1 << 7) | (1 << 4);
32579 +               ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32580 +                                         REG_CTRL_SRST, txbuf, 1);
32581 +               if (ret) {
32582 +                       goto fail;
32583 +               }
32584 +
32585 +               udelay(20);
32586 +
32587 +               txbuf[0] = 0;
32588 +               ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32589 +                                         REG_CTRL_SRST, txbuf, 1);
32590 +               if (ret) {
32591 +                       goto fail;
32592 +               }
32593 +       }
32594 +
32595 +       /*
32596 +        * See if we can see the chip
32597 +        */
32598 +       for (i = 0; i < 10; i++) {
32599 +               ret = bcm539x_read_bytes(bd, PAGE_MMR, REG_DEVICE_ID,
32600 +                                        &bd->device_id, 1);
32601 +               if (!ret) {
32602 +                       break;
32603 +               }
32604 +       }
32605 +       if (ret) {
32606 +               goto fail;
32607 +       }
32608 +
32609 +       /*
32610 +        * We only support 5395, 5397, 5398
32611 +        */
32612 +       if ((bd->device_id != 0x95) && (bd->device_id != 0x97) &&
32613 +           (bd->device_id != 0x98)) {
32614 +               ret = -ENODEV;
32615 +               goto fail;
32616 +       }
32617 +
32618 +       /*
32619 +        *  Override CPU port config: fixed link @1000 with flow control
32620 +        */
32621 +       ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, txbuf);
32622 +       bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, 0xbb);        // Override IMP port config
32623 +       printk("Broadcom SW CPU port setting: 0x%x -> 0xbb\n", txbuf[0]);
32624 +
32625 +       /*
32626 +        * Setup the switch driver structure
32627 +        */
32628 +       switch_dev = switch_alloc();
32629 +       if (!switch_dev) {
32630 +               ret = -ENOMEM;
32631 +               goto fail;
32632 +       }
32633 +       switch_dev->name = pdata->name;
32634 +
32635 +       switch_dev->ports = (bd->device_id == 0x98) ? 9 : 6;
32636 +       switch_dev->port_mask[0] = (bd->device_id == 0x98) ? 0x1FF : 0x11F;
32637 +       switch_dev->driver_handlers = bcm539x_switch_handlers;
32638 +       switch_dev->reg_handlers = NULL;
32639 +       switch_dev->vlan_handlers = bcm539x_switch_handlers_vlan;
32640 +       switch_dev->port_handlers = bcm539x_switch_handlers_port;
32641 +
32642 +       bd->switch_dev = switch_dev;
32643 +       switch_set_drvdata(switch_dev, (void *)bd);
32644 +
32645 +       ret = switch_register(bd->switch_dev);
32646 +       if (ret < 0) {
32647 +               goto fail;
32648 +       }
32649 +
32650 +       printk(KERN_INFO "bcm53%02x switch chip initialized\n", bd->device_id);
32651 +
32652 +       return ret;
32653 +
32654 +fail:
32655 +       if (switch_dev) {
32656 +               switch_release(switch_dev);
32657 +       }
32658 +       dev_set_drvdata(&spi->dev, NULL);
32659 +       kfree(bd);
32660 +       return ret;
32661 +}
32662 +
32663 +static int __attribute__((unused)) bcm539x_remove(struct spi_device *spi)
32664 +{
32665 +       struct bcm539x_data *bd;
32666 +
32667 +       bd = dev_get_drvdata(&spi->dev);
32668 +
32669 +       if (bd->pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32670 +               gpio_free(bd->pdata->pin_reset);
32671 +       }
32672 +
32673 +       if (bd->switch_dev) {
32674 +               switch_unregister(bd->switch_dev);
32675 +               switch_release(bd->switch_dev);
32676 +       }
32677 +
32678 +       dev_set_drvdata(&spi->dev, NULL);
32679 +
32680 +       kfree(bd);
32681 +
32682 +       return 0;
32683 +}
32684 +
32685 +static struct spi_driver bcm539x_driver = {
32686 +       .driver = {
32687 +               .name           = DRIVER_NAME,
32688 +               .owner          = THIS_MODULE,
32689 +       },
32690 +       .probe          = bcm539x_probe,
32691 +       .remove         = __devexit_p(bcm539x_remove),
32692 +};
32693 +
32694 +static int __init bcm539x_init(void)
32695 +{
32696 +       return spi_register_driver(&bcm539x_driver);
32697 +}
32698 +
32699 +module_init(bcm539x_init);
32700 +
32701 +static void __exit bcm539x_exit(void)
32702 +{
32703 +       spi_unregister_driver(&bcm539x_driver);
32704 +}
32705 +module_exit(bcm539x_exit);
32706 +
32707 +MODULE_AUTHOR("Pat Tjin");
32708 +MODULE_LICENSE("GPL v2");
32709 +MODULE_DESCRIPTION("bcm539x SPI switch chip driver");
32710 --- /dev/null
32711 +++ b/arch/ubicom32/mach-common/switch-bcm539x-reg.h
32712 @@ -0,0 +1,221 @@
32713 +/*
32714 + * arch/ubicom32/mach-common/switch-bcm539x-reg.h
32715 + *   Broadcom switch definitions for Ubicom32 architecture.
32716 + *
32717 + * (C) Copyright 2009, Ubicom, Inc.
32718 + *
32719 + * This file is part of the Ubicom32 Linux Kernel Port.
32720 + *
32721 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
32722 + * it and/or modify it under the terms of the GNU General Public License
32723 + * as published by the Free Software Foundation, either version 2 of the
32724 + * License, or (at your option) any later version.
32725 + *
32726 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
32727 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
32728 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
32729 + * the GNU General Public License for more details.
32730 + *
32731 + * You should have received a copy of the GNU General Public License
32732 + * along with the Ubicom32 Linux Kernel Port.  If not,
32733 + * see <http://www.gnu.org/licenses/>.
32734 + *
32735 + * Ubicom32 implementation derived from (with many thanks):
32736 + *   arch/m68knommu
32737 + *   arch/blackfin
32738 + *   arch/parisc
32739 + */
32740 +
32741 +/*
32742 + * Broadcom 53xx RoboSwitch device driver.
32743 + *
32744 + * Copyright 2007, Broadcom Corporation
32745 + * All Rights Reserved.
32746 + *
32747 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32748 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
32749 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
32750 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32751 + *
32752 + * $Id$
32753 + */
32754 +
32755 +#ifndef _SWITCH_BCM539X_REG_H_
32756 +#define _SWITCH_BCM539X_REG_H_
32757 +
32758 +#define        BCM539X_CMD_READ                0x60
32759 +#define        BCM539X_CMD_WRITE               0x61
32760 +
32761 +#define        BCM539X_GLOBAL_SPI_DATA0        0xf0
32762 +
32763 +#define        BCM539X_GLOBAL_SPI_STATUS       0xfe
32764 +#define        BCM539X_GLOBAL_SPI_ST_SPIF      (1<<7)
32765 +#define        BCM539X_GLOBAL_SPI_ST_RACK      (1<<5)
32766 +
32767 +#define        BCM539X_GLOBAL_PAGE             0xff
32768 +
32769 +#define PAGE_PORT_TC                   0x00            // Port Traffic Control Register
32770 +
32771 +#define PAGE_QOS_CTL                   0x30            // QoS Global Control Register
32772 +#define PAGE_QOS_TAG                   0x34            // Default IEEE 802.1Q TAG Register
32773 +
32774 +#define PAGE_MII_CTL_PORT0             0x10            // Internal PHY MII Register
32775 +#define PAGE_MII_CTL_PORT1             0x11
32776 +#define PAGE_MII_CTL_PORT2             0x12
32777 +#define PAGE_MII_CTL_PORT3             0x13
32778 +#define PAGE_MII_CTL_PORT4             0x14
32779 +
32780 +#define PAGE_STATUS                    0x01            // Status Register Page
32781 +#define PAGE_RATE_CONTROL              0x41            // Broadcast Storm Suppression Register
32782 +
32783 +#define REG_GRATE_CONTROL              0x00
32784 +
32785 +#define REG_LED_POWER                  0x12
32786 +
32787 +// Ingress Rate Control
32788 +#define REG_IRATE_CONTROLP0            0x10
32789 +#define REG_IRATE_CONTROLP1            0x14
32790 +#define REG_IRATE_CONTROLP2            0x18
32791 +#define REG_IRATE_CONTROLP3            0x1C
32792 +#define REG_IRATE_CONTROLP4            0x20
32793 +#define REG_IRATE_CONTROLP7            0x2C
32794 +#define REG_IRATE_CONTROLPI            0x30
32795 +
32796 +// Egress Rate Control
32797 +#define REG_ERATE_CONTROLP0            0x80
32798 +#define REG_ERATE_CONTROLP1            0x82
32799 +#define REG_ERATE_CONTROLP2            0x84
32800 +#define REG_ERATE_CONTROLP3            0x86
32801 +#define REG_ERATE_CONTROLP4            0x88
32802 +#define REG_ERATE_CONTROLP5            0x8A
32803 +#define REG_ERATE_CONTROLP6            0x8C
32804 +#define REG_ERATE_CONTROLP7            0x8E
32805 +#define REG_ERATE_CONTROLPI            0x90
32806 +
32807 +#define REG_LINK_STATUS                        0x00
32808 +
32809 +#define REG_TC_PORT0                   0x00
32810 +#define REG_TC_PORT1                   0x01
32811 +#define REG_TC_PORT2                   0x02
32812 +#define REG_TC_PORT3                   0x03
32813 +#define REG_TC_PORT4                   0x04
32814 +#define REG_TC_PORT5                   0x05
32815 +
32816 +#define REG_SPEED_CTL                  0x00
32817 +#define REG_SPEED_ADV100               0x08
32818 +#define REG_SPEED_ADV1000              0x12
32819 +
32820 +#define REG_QOS_EN                     0x00
32821 +#define REG_QOS_TAG_PORT1              0x12            // Default IEEE 802.1Q TAG, PORT 1
32822 +#define REG_QOS_TAG_PORT2              0x14            // Default IEEE 802.1Q TAG, PORT 2
32823 +#define REG_QOS_TAG_PORT3              0x16            // Default IEEE 802.1Q TAG, PORT 3
32824 +#define REG_QOS_TAG_PORT4              0x18            // Default IEEE 802.1Q TAG, PORT 4
32825 +#define REG_QOS_PID_PORT1              0x52            // Ingress Port Priority ID MAP, PORT 1
32826 +#define REG_QOS_PID_PORT2              0x54            // Ingress Port Priority ID MAP, PORT 2
32827 +#define REG_QOS_PID_PORT3              0x56            // Ingress Port Priority ID MAP, PORT 3
32828 +#define REG_QOS_PID_PORT4              0x58            // Ingress Port Priority ID MAP, PORT 4
32829 +#define REG_QOS_TXQ_CTL                        0x80            // Tx Queue Control Register
32830 +#define REG_QOS_TXQ_WHTQ0              0x81            // Tx Queue Weight Register Queue 0
32831 +#define REG_QOS_TXQ_WHTQ1              0x82            // Tx Queue Weight Register Queue 1
32832 +#define REG_QOS_TXQ_WHTQ2              0x83            // Tx Queue Weight Register Queue 2
32833 +#define REG_QOS_TXQ_WHTQ3              0x84            // Tx Queue Weight Register Queue 3
32834 +
32835 +#define REG_CTRL_PPSEL                 0x24            /* 5397: Protected port select register */
32836 +
32837 +#define RATE_CONTROL_ENABLED           (1 << 22)
32838 +#define RATE_CONTROL_BSIZE             ((1 << 10) | (1 << 9) | (1 << 8))
32839 +
32840 +#define RATE_CONTROL_HIGH              ((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4))
32841 +#define RATE_CONTROL_HIGH_N            ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
32842 +
32843 +#define RATE_CONTROL_MEDIUM            ((1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
32844 +#define RATE_CONTROL_MEDIUM_N          ~((1 << 7))
32845 +
32846 +#define RATE_CONTROL_NORMAL            ((1 << 5) | (1 << 2) | (1 << 0))
32847 +#define RATE_CONTROL_NORMAL_N          ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1))
32848 +
32849 +#define RATE_CONTROL_LOW               ((1 << 4) | (1 << 3) | (1 << 0))
32850 +#define RATE_CONTROL_LOW_N             ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2) | (1 << 1))
32851 +
32852 +// --- Gemtek, Configure the switch to support Ethernet Port QoS
32853 +
32854 +/* MII access registers */
32855 +#define PSEUDO_PHYAD                   0x1E    /* MII Pseudo PHY address */
32856 +#define REG_MII_PAGE                   0x10    /* MII Page register */
32857 +#define REG_MII_ADDR                   0x11    /* MII Address register */
32858 +#define REG_MII_DATA0                  0x18    /* MII Data register 0 */
32859 +#define REG_MII_DATA1                  0x19    /* MII Data register 1 */
32860 +#define REG_MII_DATA2                  0x1a    /* MII Data register 2 */
32861 +#define REG_MII_DATA3                  0x1b    /* MII Data register 3 */
32862 +
32863 +/* Page numbers */
32864 +#define PAGE_CTRL                      0x00    /* Control page */
32865 +#define PAGE_MMR                       0x02    /* 5397 Management/Mirroring page */
32866 +#define PAGE_VTBL                      0x05    /* ARL/VLAN Table access page */
32867 +#define PAGE_VLAN                      0x34    /* VLAN page */
32868 +
32869 +/* Control page registers */
32870 +#define REG_CTRL_PORT0                 0x00    /* Port 0 traffic control register */
32871 +#define REG_CTRL_PORT1                 0x01    /* Port 1 traffic control register */
32872 +#define REG_CTRL_PORT2                 0x02    /* Port 2 traffic control register */
32873 +#define REG_CTRL_PORT3                 0x03    /* Port 3 traffic control register */
32874 +#define REG_CTRL_PORT4                 0x04    /* Port 4 traffic control register */
32875 +#define REG_CTRL_PORT5                 0x05    /* Port 5 traffic control register */
32876 +#define REG_CTRL_PORT6                 0x06    /* Port 6 traffic control register */
32877 +#define REG_CTRL_PORT7                 0x07    /* Port 7 traffic control register */
32878 +#define REG_CTRL_MODE                  0x0B    /* Switch Mode register */
32879 +#define REG_CTRL_MIIPO                 0x0E    /* 5325: MII Port Override register */
32880 +#define REG_CTRL_SRST                  0x79    /* Software reset control register */
32881 +
32882 +#define REG_DEVICE_ID                  0x30    /* 539x Device id: */
32883 +#define        DEVID5395                       0x95    /*  5395 */
32884 +#define        DEVID5397                       0x97    /*  5397 */
32885 +#define        DEVID5398                       0x98    /*  5398 */
32886 +#define REG_REVISION_ID                        0x40    /* 539x Revision id: */
32887 +
32888 +/* VLAN page registers */
32889 +#define REG_VLAN_CTRL0                 0x00    /* VLAN Control 0 register */
32890 +#define REG_VLAN_CTRL1                 0x01    /* VLAN Control 1 register */
32891 +#define REG_VLAN_CTRL2                 0x02    /* VLAN Control 2 register */
32892 +#define REG_VLAN_CTRL3                 0x03    /* VLAN Control 3 register */
32893 +#define REG_VLAN_CTRL4                 0x04    /* VLAN Control 4 register */
32894 +#define REG_VLAN_CTRL5                 0x05    /* VLAN Control 5 register */
32895 +#define REG_VLAN_ACCESS                        0x06    /* VLAN Table Access register */
32896 +#define REG_VLAN_WRITE                 0x08    /* VLAN Write register */
32897 +#define REG_VLAN_READ                  0x0C    /* VLAN Read register */
32898 +#define REG_VLAN_PTAG0                 0x10    /* VLAN Default Port Tag register - port 0 */
32899 +#define REG_VLAN_PTAG1                 0x12    /* VLAN Default Port Tag register - port 1 */
32900 +#define REG_VLAN_PTAG2                 0x14    /* VLAN Default Port Tag register - port 2 */
32901 +#define REG_VLAN_PTAG3                 0x16    /* VLAN Default Port Tag register - port 3 */
32902 +#define REG_VLAN_PTAG4                 0x18    /* VLAN Default Port Tag register - port 4 */
32903 +#define REG_VLAN_PTAG5                 0x1a    /* VLAN Default Port Tag register - port 5 */
32904 +#define REG_VLAN_PTAG6                 0x1c    /* VLAN Default Port Tag register - port 6 */
32905 +#define REG_VLAN_PTAG7                 0x1e    /* VLAN Default Port Tag register - port 7 */
32906 +#define REG_VLAN_PTAG8                 0x20    /* 539x: VLAN Default Port Tag register - IMP port */
32907 +#define REG_VLAN_PMAP                  0x20    /* 5325: VLAN Priority Re-map register */
32908 +
32909 +/* ARL/VLAN Table Access page registers */
32910 +#define REG_VTBL_CTRL                  0x00    /* ARL Read/Write Control */
32911 +#define REG_VTBL_MINDX                 0x02    /* MAC Address Index */
32912 +#define REG_VTBL_VINDX                 0x08    /* VID Table Index */
32913 +#define REG_VTBL_ARL_E0                        0x10    /* ARL Entry 0 */
32914 +#define REG_VTBL_ARL_E1                        0x18    /* ARL Entry 1 */
32915 +#define REG_VTBL_DAT_E0                        0x18    /* ARL Table Data Entry 0 */
32916 +#define REG_VTBL_SCTRL                 0x20    /* ARL Search Control */
32917 +#define REG_VTBL_SADDR                 0x22    /* ARL Search Address */
32918 +#define REG_VTBL_SRES                  0x24    /* ARL Search Result */
32919 +#define REG_VTBL_SREXT                 0x2c    /* ARL Search Result */
32920 +#define REG_VTBL_VID_E0                        0x30    /* VID Entry 0 */
32921 +#define REG_VTBL_VID_E1                        0x32    /* VID Entry 1 */
32922 +#define REG_VTBL_PREG                  0xFF    /* Page Register */
32923 +#define REG_VTBL_ACCESS                        0x60    /* VLAN table access register */
32924 +#define REG_VTBL_INDX                  0x61    /* VLAN table address index register */
32925 +#define REG_VTBL_ENTRY                 0x63    /* VLAN table entry register */
32926 +#define REG_VTBL_ACCESS_5395           0x80    /* VLAN table access register */
32927 +#define REG_VTBL_INDX_5395             0x81    /* VLAN table address index register */
32928 +#define REG_VTBL_ENTRY_5395            0x83    /* VLAN table entry register */
32929 +
32930 +/* SPI registers */
32931 +#define REG_SPI_PAGE                   0xff    /* SPI Page register */
32932 +
32933 +#endif
32934 --- /dev/null
32935 +++ b/arch/ubicom32/mach-common/switch-core.c
32936 @@ -0,0 +1,737 @@
32937 +/*
32938 + * arch/ubicom32/mach-common/switch-core.c
32939 + *   Ubicom32 architecture switch and /proc/switch/... implementation.
32940 + *
32941 + * (C) Copyright 2009, Ubicom, Inc.
32942 + * Copyright (C) 2005 Felix Fietkau <openwrt@nbd.name>
32943 + *
32944 + * This file is part of the Ubicom32 Linux Kernel Port.
32945 + *
32946 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
32947 + * it and/or modify it under the terms of the GNU General Public License
32948 + * as published by the Free Software Foundation, either version 2 of the
32949 + * License, or (at your option) any later version.
32950 + *
32951 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
32952 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
32953 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
32954 + * the GNU General Public License for more details.
32955 + *
32956 + * You should have received a copy of the GNU General Public License
32957 + * along with the Ubicom32 Linux Kernel Port.  If not,
32958 + * see <http://www.gnu.org/licenses/>.
32959 + *
32960 + * Ubicom32 implementation derived from (with many thanks):
32961 + *   arch/m68knommu
32962 + *   arch/blackfin
32963 + *   arch/parisc
32964 + *
32965 + * Basic doc of driver's /proc interface:
32966 + * /proc/switch/<interface>/
32967 + *   registers:              read-only
32968 + *   counters:               read-only
32969 + *   reset:                  write causes hardware reset
32970 + *   enable:                 "0", "1"
32971 + *   enable_vlan:            "0", "1"
32972 + *   port/<port-number>/
32973 + *     enabled:              "0", "1"
32974 + *     link state:           read-only
32975 + *     media:                "AUTO", "1000FD", "100FD", "100HD", "10FD", "10HD"
32976 + *   vlan/<port-number>/
32977 + *     ports: same syntax as for nvram's vlan*ports (eg. "1 2 3 4 5*")
32978 + */
32979 +
32980 +#include <linux/module.h>
32981 +#include <linux/init.h>
32982 +#include <linux/uaccess.h>
32983 +#include <linux/ctype.h>
32984 +#include <linux/proc_fs.h>
32985 +#include <linux/list.h>
32986 +#include <linux/rwsem.h>
32987 +#include <linux/device.h>
32988 +
32989 +#include "switch-core.h"
32990 +
32991 +/*
32992 + * Pointer to the root of our filesystem
32993 + */
32994 +static struct proc_dir_entry *switch_root;
32995 +
32996 +/*
32997 + * Lock used to manage access to the switch list
32998 + */
32999 +DECLARE_RWSEM(switch_list_lock);
33000 +EXPORT_SYMBOL_GPL(switch_list_lock);
33001 +
33002 +/*
33003 + * List of switches we are managing
33004 + */
33005 +LIST_HEAD(switch_list);
33006 +EXPORT_SYMBOL_GPL(switch_list);
33007 +
33008 +/*
33009 + * List of handlers we have
33010 + */
33011 +LIST_HEAD(switch_handler_list);
33012 +EXPORT_SYMBOL_GPL(switch_handler_list);
33013 +
33014 +/*
33015 + * Keep track of all the handlers we added
33016 + */
33017 +struct switch_handler_entry {
33018 +       struct list_head                node;
33019 +       struct proc_dir_entry           *parent;
33020 +       struct switch_device            *dev;
33021 +       const struct switch_handler     *handler;
33022 +       int                             inst;
33023 +};
33024 +
33025 +/*
33026 + * Keep track of all VLAN dirs we created
33027 + */
33028 +struct switch_vlan_entry {
33029 +       struct list_head                node;
33030 +       struct proc_dir_entry           *pde;
33031 +       int                             vlan_id;
33032 +       const struct switch_handler     *handlers;
33033 +};
33034 +
33035 +/*
33036 + * switch_parse_vlan_ports
33037 + *     Parse the vlan properties written to <driver>/vlan/<vlan_id>/ports
33038 + */
33039 +void switch_parse_vlan_ports(struct switch_device *switch_dev,
33040 +                            char *buf, u32_t *untag,
33041 +                            u32_t *ports, u32_t *def)
33042 +{
33043 +       u32_t tag = 0;
33044 +       *untag = 0;
33045 +       *ports = 0;
33046 +       *def = 0;
33047 +
33048 +
33049 +       /*
33050 +        * Skip any leading spaces
33051 +        */
33052 +       while (isspace(*buf)) {
33053 +               buf++;
33054 +       }
33055 +
33056 +       /*
33057 +        * Parse out the string
33058 +        */
33059 +       while (*buf) {
33060 +               u32_t port = simple_strtoul(buf, &buf, 10);
33061 +               u32_t mask = (1 << port);
33062 +
33063 +               /*
33064 +                * Parse out any flags
33065 +                */
33066 +               while (*buf && !isspace(*buf)) {
33067 +                       switch (*buf++) {
33068 +                       case 't':
33069 +                               tag |= mask;
33070 +                               break;
33071 +                       case '*':
33072 +                               *def |= mask;
33073 +                               break;
33074 +                       }
33075 +               }
33076 +               *ports |= mask;
33077 +
33078 +               /*
33079 +                * Skip any spaces
33080 +                */
33081 +               while (isspace(*buf)) {
33082 +                       buf++;
33083 +               }
33084 +       }
33085 +
33086 +       *untag = ~tag & *ports;
33087 +}
33088 +
33089 +/*
33090 + * switch_proc_read
33091 + *     Handle reads from the procfs, dispatches the driver specific handler
33092 + */
33093 +static ssize_t switch_proc_read(struct file *file, char *buf, size_t count,
33094 +                               loff_t *ppos)
33095 +{
33096 +       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33097 +       char *page;
33098 +       int len = 0;
33099 +
33100 +       page = kmalloc(SWITCH_MAX_BUFSZ, GFP_KERNEL);
33101 +       if (!page) {
33102 +               return -ENOBUFS;
33103 +       }
33104 +
33105 +       if (pde->data != NULL) {
33106 +               struct switch_handler_entry *she =
33107 +                       (struct switch_handler_entry *)pde->data;
33108 +               if (she->handler->read) {
33109 +                       len += she->handler->read(she->dev, page + len,
33110 +                                                 she->inst);
33111 +               }
33112 +       }
33113 +       len += 1;
33114 +
33115 +       if (*ppos < len) {
33116 +               len = min_t(int, len - *ppos, count);
33117 +               if (copy_to_user(buf, (page + *ppos), len)) {
33118 +                       kfree(page);
33119 +                       return -EFAULT;
33120 +               }
33121 +               *ppos += len;
33122 +       } else {
33123 +               len = 0;
33124 +       }
33125 +
33126 +       kfree(page);
33127 +
33128 +       return len;
33129 +}
33130 +
33131 +/*
33132 + * switch_proc_write
33133 + *     Handle writes from the procfs, dispatches the driver specific handler
33134 + */
33135 +static ssize_t switch_proc_write(struct file *file, const char *buf,
33136 +                                size_t count, loff_t *data)
33137 +{
33138 +       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33139 +       char *page;
33140 +       int ret = -EINVAL;
33141 +
33142 +       page = kmalloc(count + 1, GFP_KERNEL);
33143 +       if (page == NULL)
33144 +               return -ENOBUFS;
33145 +
33146 +       if (copy_from_user(page, buf, count)) {
33147 +               kfree(page);
33148 +               return -EINVAL;
33149 +       }
33150 +       page[count] = 0;
33151 +
33152 +       if (pde->data != NULL) {
33153 +               struct switch_handler_entry *she =
33154 +                       (struct switch_handler_entry *)pde->data;
33155 +               if (she->handler->write) {
33156 +                       ret = she->handler->write(she->dev, page, she->inst);
33157 +                       if (ret >= 0) {
33158 +                               ret = count;
33159 +                       }
33160 +               }
33161 +       }
33162 +
33163 +       kfree(page);
33164 +       return ret;
33165 +}
33166 +
33167 +/*
33168 + * File operations for the proc_fs, we must cast here since proc_fs' definitions
33169 + * differ from file_operations definitions.
33170 + */
33171 +static struct file_operations switch_proc_fops = {
33172 +       .read = (ssize_t (*) (struct file *, char __user *,
33173 +                             size_t, loff_t *))switch_proc_read,
33174 +       .write = (ssize_t (*) (struct file *, const char __user *,
33175 +                              size_t, loff_t *))switch_proc_write,
33176 +};
33177 +
33178 +/*
33179 + * switch_add_handler
33180 + */
33181 +static int switch_add_handler(struct switch_device *switch_dev,
33182 +                             struct proc_dir_entry *parent,
33183 +                             const struct switch_handler *handler,
33184 +                             int inst)
33185 +{
33186 +       struct switch_handler_entry *she;
33187 +       struct proc_dir_entry *pde;
33188 +       int mode;
33189 +
33190 +       she = (struct switch_handler_entry *)
33191 +               kzalloc(sizeof(struct switch_handler_entry), GFP_KERNEL);
33192 +       if (!she) {
33193 +               return -ENOMEM;
33194 +       }
33195 +
33196 +       INIT_LIST_HEAD(&she->node);
33197 +       she->parent = parent;
33198 +       she->dev = switch_dev;
33199 +       she->inst = inst;
33200 +       she->handler = handler;
33201 +       list_add(&she->node, &switch_dev->handlers);
33202 +
33203 +       mode = 0;
33204 +       if (handler->read != NULL) {
33205 +               mode |= S_IRUSR;
33206 +       }
33207 +       if (handler->write != NULL) {
33208 +               mode |= S_IWUSR;
33209 +       }
33210 +
33211 +       pde = create_proc_entry(handler->name, mode, parent);
33212 +       if (!pde) {
33213 +               kfree(she);
33214 +               printk("Failed to create node '%s' in parent %p\n",
33215 +                      handler->name, parent);
33216 +               return -ENOMEM;
33217 +       }
33218 +       pde->data = (void *)she;
33219 +       pde->proc_fops = &switch_proc_fops;
33220 +
33221 +       return 0;
33222 +}
33223 +
33224 +/*
33225 + * switch_add_handlers
33226 + */
33227 +static int switch_add_handlers(struct switch_device *switch_dev,
33228 +                              struct proc_dir_entry *parent,
33229 +                              const struct switch_handler *handlers,
33230 +                              int inst)
33231 +{
33232 +       while (handlers->name) {
33233 +               int ret = switch_add_handler(switch_dev,
33234 +                                            parent, handlers, inst);
33235 +               if (ret) {
33236 +                       return ret;
33237 +               }
33238 +               handlers++;
33239 +       }
33240 +
33241 +       return 0;
33242 +}
33243 +
33244 +/*
33245 + * switch_remove_vlan_dirs
33246 + *     Removes all vlan directories
33247 + *
33248 + * Assumes all vlan directories are empty, should be called after
33249 + * switch_remove_handlers
33250 + */
33251 +static void switch_remove_vlan_dirs(struct switch_device *switch_dev)
33252 +{
33253 +       struct list_head *pos;
33254 +       struct list_head *tmp;
33255 +       struct switch_vlan_entry *sve;
33256 +
33257 +       list_for_each_safe(pos, tmp, &switch_dev->vlan_dirs) {
33258 +               sve = list_entry(pos, struct switch_vlan_entry, node);
33259 +               list_del(pos);
33260 +               remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33261 +               kfree(sve);
33262 +       }
33263 +}
33264 +
33265 +/*
33266 + * switch_remove_handlers
33267 + *     Removes all handlers registered to the given switch_device
33268 + */
33269 +static void switch_remove_handlers(struct switch_device *switch_dev)
33270 +{
33271 +       struct list_head *pos;
33272 +       struct list_head *tmp;
33273 +       struct switch_handler_entry *she;
33274 +
33275 +       list_for_each_safe(pos, tmp, &switch_dev->handlers) {
33276 +               she = list_entry(pos, struct switch_handler_entry, node);
33277 +               list_del(pos);
33278 +               remove_proc_entry(she->handler->name, she->parent);
33279 +               kfree(she);
33280 +       }
33281 +}
33282 +
33283 +/*
33284 + * switch_unregister_proc_nodes
33285 + *     Unregisters all proc nodes related to switch_dev
33286 + */
33287 +void switch_unregister_proc_nodes(struct switch_device *switch_dev)
33288 +{
33289 +       switch_remove_handlers(switch_dev);
33290 +
33291 +       if (switch_dev->port_dirs) {
33292 +               int i;
33293 +
33294 +               for (i = 0; i < switch_dev->ports; i++) {
33295 +                       if (switch_dev->port_dirs[i]) {
33296 +                               remove_proc_entry(
33297 +                                       switch_dev->port_dirs[i]->name,
33298 +                                       switch_dev->port_dir);
33299 +                       }
33300 +               }
33301 +       }
33302 +
33303 +       if (switch_dev->port_dir) {
33304 +               remove_proc_entry("port", switch_dev->driver_dir);
33305 +               switch_dev->port_dir = NULL;
33306 +       }
33307 +
33308 +       if (switch_dev->reg_dir) {
33309 +               remove_proc_entry("reg", switch_dev->reg_dir);
33310 +               switch_dev->reg_dir = NULL;
33311 +       }
33312 +
33313 +       if (switch_dev->vlan_dir) {
33314 +               switch_remove_vlan_dirs(switch_dev);
33315 +               remove_proc_entry("vlan", switch_dev->driver_dir);
33316 +               switch_dev->vlan_dir = NULL;
33317 +       }
33318 +
33319 +       if (switch_dev->driver_dir) {
33320 +               remove_proc_entry(switch_dev->name, switch_root);
33321 +               switch_dev->driver_dir = NULL;
33322 +       }
33323 +}
33324 +
33325 +/*
33326 + * switch_remove_vlan_dir
33327 + *     Removes vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33328 + */
33329 +int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id)
33330 +{
33331 +       struct list_head *pos;
33332 +       struct switch_vlan_entry *sve = NULL;
33333 +
33334 +       list_for_each(pos, &switch_dev->vlan_dirs) {
33335 +               struct switch_vlan_entry *tmp =
33336 +                       list_entry(pos, struct switch_vlan_entry, node);
33337 +               if (tmp->vlan_id == vlan_id) {
33338 +                       sve = tmp;
33339 +                       break;
33340 +               }
33341 +       }
33342 +
33343 +       if (!sve) {
33344 +               return -ENOENT;
33345 +       }
33346 +
33347 +       /*
33348 +        * Remove it from the list
33349 +        */
33350 +       list_del(pos);
33351 +
33352 +       /*
33353 +        * Remove the handlers
33354 +        */
33355 +       while (sve->handlers->name) {
33356 +               remove_proc_entry(sve->handlers->name, sve->pde);
33357 +               sve->handlers++;
33358 +       }
33359 +
33360 +       /*
33361 +        * Remove the proc entry for the <vlan_id> dir
33362 +        */
33363 +       remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33364 +
33365 +       kfree(sve);
33366 +
33367 +       return 0;
33368 +}
33369 +
33370 +/*
33371 + * switch_create_vlan_dir
33372 + *     Creates vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33373 + */
33374 +int switch_create_vlan_dir(struct switch_device *switch_dev,
33375 +                          int vlan_id, const struct switch_handler *handlers)
33376 +{
33377 +       char s[14];
33378 +       struct proc_dir_entry *pde = NULL;
33379 +       struct switch_vlan_entry *sve = NULL;
33380 +       int ret;
33381 +       struct list_head *pos;
33382 +
33383 +       /*
33384 +        * Check to see if it exists already
33385 +        */
33386 +       list_for_each(pos, &switch_dev->vlan_dirs) {
33387 +               sve = list_entry(pos, struct switch_vlan_entry, node);
33388 +               if (sve->vlan_id == vlan_id) {
33389 +                       return -EEXIST;
33390 +               }
33391 +       }
33392 +       sve = NULL;
33393 +
33394 +       /*
33395 +        * Create the vlan directory if we didn't have it before
33396 +        */
33397 +       if (!switch_dev->vlan_dir) {
33398 +               switch_dev->vlan_dir = proc_mkdir("vlan",
33399 +                                                 switch_dev->driver_dir);
33400 +               if (!switch_dev->vlan_dir) {
33401 +                       goto fail;
33402 +               }
33403 +               if (switch_dev->vlan_handlers) {
33404 +                       ret = switch_add_handlers(switch_dev,
33405 +                                                 switch_dev->vlan_dir,
33406 +                                                 switch_dev->vlan_handlers, 0);
33407 +                       if (ret) {
33408 +                               goto fail;
33409 +                       }
33410 +               }
33411 +       }
33412 +
33413 +       /*
33414 +        * Create the vlan_id directory
33415 +        */
33416 +       snprintf(s, 14, "%d", vlan_id);
33417 +       pde = proc_mkdir(s, switch_dev->vlan_dir);
33418 +       if (!pde) {
33419 +               goto fail;
33420 +       }
33421 +
33422 +       /*
33423 +        * Create the handlers for this vlan
33424 +        */
33425 +       if (handlers) {
33426 +               ret = switch_add_handlers(switch_dev, pde, handlers, vlan_id);
33427 +               if (ret) {
33428 +                       goto fail;
33429 +               }
33430 +       }
33431 +
33432 +       /*
33433 +        * Keep track of all the switch vlan entries created
33434 +        */
33435 +       sve = (struct switch_vlan_entry *)
33436 +               kzalloc(sizeof(struct switch_vlan_entry), GFP_KERNEL);
33437 +       if (!sve) {
33438 +               goto fail;
33439 +       }
33440 +       INIT_LIST_HEAD(&sve->node);
33441 +       sve->handlers = handlers;
33442 +       sve->vlan_id = vlan_id;
33443 +       sve->pde = pde;
33444 +       list_add(&sve->node, &switch_dev->vlan_dirs);
33445 +
33446 +       return 0;
33447 +
33448 +fail:
33449 +       if (sve) {
33450 +               kfree(sve);
33451 +       }
33452 +
33453 +       if (pde) {
33454 +               /*
33455 +                * Remove any proc entries we might have created
33456 +                */
33457 +               while (handlers->name) {
33458 +                       remove_proc_entry(handlers->name, pde);
33459 +                       handlers++;
33460 +               }
33461 +
33462 +               remove_proc_entry(s, switch_dev->driver_dir);
33463 +       }
33464 +
33465 +       return -ENOMEM;
33466 +}
33467 +
33468 +/*
33469 + * switch_register_proc_nodes
33470 + */
33471 +int switch_register_proc_nodes(struct switch_device *switch_dev)
33472 +{
33473 +       int i;
33474 +       int n;
33475 +
33476 +       switch_dev->port_dirs = kzalloc(switch_dev->ports *
33477 +                                       sizeof(struct proc_dir_entry *),
33478 +                                       GFP_KERNEL);
33479 +       if (!switch_dev->port_dirs) {
33480 +               return -ENOMEM;
33481 +       }
33482 +
33483 +       /*
33484 +        * Create a new proc entry for this switch
33485 +        */
33486 +       switch_dev->driver_dir = proc_mkdir(switch_dev->name, switch_root);
33487 +       if (!switch_dev->driver_dir) {
33488 +               goto fail;
33489 +       }
33490 +       if (switch_dev->driver_handlers) {
33491 +               switch_add_handlers(switch_dev,
33492 +                                   switch_dev->driver_dir,
33493 +                                   switch_dev->driver_handlers,
33494 +                                   0);
33495 +       }
33496 +
33497 +       /*
33498 +        * Create the ports
33499 +        */
33500 +       switch_dev->port_dir = proc_mkdir("port", switch_dev->driver_dir);
33501 +       if (!switch_dev->port_dir) {
33502 +               goto fail;
33503 +       }
33504 +       for (n = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33505 +               if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33506 +                       char s[14];
33507 +
33508 +                       snprintf(s, 14, "%d", i);
33509 +                       switch_dev->port_dirs[n] =
33510 +                               proc_mkdir(s, switch_dev->port_dir);
33511 +                       if (!switch_dev->port_dirs[n]) {
33512 +                               goto fail;
33513 +                       }
33514 +                       if (switch_dev->port_handlers) {
33515 +                               switch_add_handlers(switch_dev,
33516 +                                                   switch_dev->port_dirs[n],
33517 +                                                   switch_dev->port_handlers,
33518 +                                                   i);
33519 +                       }
33520 +                       n++;
33521 +               }
33522 +       }
33523 +
33524 +       /*
33525 +        * Create the register directory for switch register access.
33526 +        */
33527 +       if (switch_dev->reg_handlers) {
33528 +               switch_dev->reg_dir = proc_mkdir("reg", switch_dev->driver_dir);
33529 +               if (!switch_dev->reg_dir) {
33530 +                       goto fail;
33531 +               }
33532 +
33533 +               switch_add_handlers(switch_dev,
33534 +                                   switch_dev->reg_dir,
33535 +                                   switch_dev->reg_handlers,
33536 +                                   0);
33537 +       }
33538 +
33539 +       /*
33540 +        * Create the vlan directory
33541 +        */
33542 +       if (switch_dev->vlan_handlers) {
33543 +               switch_dev->vlan_dir = proc_mkdir("vlan",
33544 +                                                 switch_dev->driver_dir);
33545 +               if (!switch_dev->vlan_dir) {
33546 +                       goto fail;
33547 +               }
33548 +               if (switch_dev->vlan_handlers) {
33549 +                       switch_add_handlers(switch_dev,
33550 +                                           switch_dev->vlan_dir,
33551 +                                           switch_dev->vlan_handlers,
33552 +                                           0);
33553 +               }
33554 +       }
33555 +
33556 +       return 0;
33557 +
33558 +fail:
33559 +       switch_unregister_proc_nodes(switch_dev);
33560 +       return -ENOMEM;
33561 +}
33562 +
33563 +/*
33564 + * switch_release
33565 + */
33566 +void switch_release(struct switch_device *switch_dev)
33567 +{
33568 +       kfree(switch_dev);
33569 +}
33570 +
33571 +/*
33572 + * switch_alloc
33573 + */
33574 +struct switch_device *switch_alloc(void)
33575 +{
33576 +       struct switch_device *switch_dev =
33577 +               kzalloc(sizeof(struct switch_device),
33578 +                                               GFP_KERNEL);
33579 +       INIT_LIST_HEAD(&switch_dev->node);
33580 +       INIT_LIST_HEAD(&switch_dev->vlan_dirs);
33581 +       INIT_LIST_HEAD(&switch_dev->handlers);
33582 +       return switch_dev;
33583 +}
33584 +
33585 +/*
33586 + * switch_register
33587 + */
33588 +int switch_register(struct switch_device *switch_dev)
33589 +{
33590 +       int ret;
33591 +       int i;
33592 +
33593 +       /*
33594 +        * Make sure that the number of ports and the port mask make sense
33595 +        */
33596 +       for (ret = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33597 +               if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33598 +                       ret++;
33599 +               }
33600 +       }
33601 +       if (ret > switch_dev->ports) {
33602 +               return -EINVAL;
33603 +       }
33604 +
33605 +       /*
33606 +        * Create the /proc entries
33607 +        */
33608 +       ret = switch_register_proc_nodes(switch_dev);
33609 +       if (ret) {
33610 +               return ret;
33611 +       }
33612 +
33613 +       /*
33614 +        * Add it to the list of switches
33615 +        */
33616 +       down_write(&switch_list_lock);
33617 +       list_add_tail(&switch_dev->node, &switch_list);
33618 +       up_write(&switch_list_lock);
33619 +
33620 +       printk(KERN_INFO "Registered switch device: %s\n", switch_dev->name);
33621 +
33622 +       return 0;
33623 +}
33624 +EXPORT_SYMBOL_GPL(switch_register);
33625 +
33626 +/*
33627 + * switch_unregister
33628 + *     Unregisters a previously registered switch_device object
33629 + */
33630 +void switch_unregister(struct switch_device *switch_dev)
33631 +{
33632 +       /*
33633 +        * remove the proc entries
33634 +        */
33635 +       switch_unregister_proc_nodes(switch_dev);
33636 +
33637 +       /*
33638 +        * Remove it from the list of switches
33639 +        */
33640 +       down_write(&switch_list_lock);
33641 +       list_del(&switch_dev->node);
33642 +       up_write(&switch_list_lock);
33643 +
33644 +       printk(KERN_INFO "Unregistered switch device: %s\n", switch_dev->name);
33645 +}
33646 +EXPORT_SYMBOL_GPL(switch_unregister);
33647 +
33648 +/*
33649 + * switch_init
33650 + */
33651 +static int __init switch_init(void)
33652 +{
33653 +       switch_root = proc_mkdir("switch", NULL);
33654 +       if (!switch_root) {
33655 +               printk(KERN_WARNING "Failed to make root switch node\n");
33656 +               return -ENODEV;
33657 +       }
33658 +       return 0;
33659 +}
33660 +module_init(switch_init);
33661 +
33662 +/*
33663 + * switch_exit
33664 + */
33665 +static void __exit switch_exit(void)
33666 +{
33667 +       remove_proc_entry("switch", NULL);
33668 +}
33669 +module_exit(switch_exit);
33670 +
33671 +MODULE_AUTHOR("Patrick Tjin");
33672 +MODULE_LICENSE("GPL");
33673 +MODULE_DESCRIPTION("Ethernet Switch Class Interface");
33674 --- /dev/null
33675 +++ b/arch/ubicom32/mach-common/switch-core.h
33676 @@ -0,0 +1,92 @@
33677 +/*
33678 + * arch/ubicom32/mach-common/switch-core.h
33679 + *   Private data for the switch module
33680 + *
33681 + * (C) Copyright 2009, Ubicom, Inc.
33682 + *
33683 + * This file is part of the Ubicom32 Linux Kernel Port.
33684 + *
33685 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33686 + * it and/or modify it under the terms of the GNU General Public License
33687 + * as published by the Free Software Foundation, either version 2 of the
33688 + * License, or (at your option) any later version.
33689 + *
33690 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33691 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33692 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
33693 + * the GNU General Public License for more details.
33694 + *
33695 + * You should have received a copy of the GNU General Public License
33696 + * along with the Ubicom32 Linux Kernel Port.  If not,
33697 + * see <http://www.gnu.org/licenses/>.
33698 + *
33699 + * Ubicom32 implementation derived from (with many thanks):
33700 + *   arch/m68knommu
33701 + *   arch/blackfin
33702 + *   arch/parisc
33703 + */
33704 +#ifndef _SWITCH_CORE_H_
33705 +#define _SWITCH_CORE_H_
33706 +
33707 +struct switch_handler_entry;
33708 +struct switch_vlan_entry;
33709 +
33710 +#define SWITCH_PORT_MASK_SIZE  2
33711 +
33712 +struct switch_device {
33713 +       struct list_head                node;
33714 +
33715 +       const char                      *name;
33716 +       void                            *drvdata;
33717 +
33718 +       u8_t                            ports;
33719 +
33720 +       struct proc_dir_entry           *driver_dir;
33721 +       const struct switch_handler     *driver_handlers;
33722 +
33723 +       struct proc_dir_entry           *port_dir;
33724 +       struct proc_dir_entry           **port_dirs;
33725 +       const struct switch_handler     *port_handlers;
33726 +
33727 +       struct proc_dir_entry           *reg_dir;
33728 +       const struct switch_handler     *reg_handlers;
33729 +
33730 +       struct proc_dir_entry           *vlan_dir;
33731 +       const struct switch_handler     *vlan_handlers;
33732 +       struct list_head                vlan_dirs;
33733 +
33734 +       struct list_head                handlers;
33735 +
33736 +       u32_t                           port_mask[SWITCH_PORT_MASK_SIZE];
33737 +};
33738 +
33739 +typedef int (*switch_handler_fn)(struct switch_device *, char *buf, int nr);
33740 +struct switch_handler {
33741 +       const char              *name;
33742 +
33743 +       switch_handler_fn       read;
33744 +       switch_handler_fn       write;
33745 +};
33746 +
33747 +#define SWITCH_MAX_BUFSZ       4096
33748 +
33749 +static inline void switch_set_drvdata(struct switch_device *switch_dev, void *drvdata)
33750 +{
33751 +       switch_dev->drvdata = drvdata;
33752 +}
33753 +
33754 +static inline void *switch_get_drvdata(struct switch_device *switch_dev)
33755 +{
33756 +       return switch_dev->drvdata;
33757 +}
33758 +
33759 +extern int switch_create_vlan_dir(struct switch_device *switch_dev, int vlan_id, const struct switch_handler *handlers);
33760 +extern int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id);
33761 +extern void switch_parse_vlan_ports(struct switch_device *switch_dev, char *buf, u32_t *untag, u32_t *ports, u32_t *def);
33762 +
33763 +extern void switch_release(struct switch_device *switch_dev);
33764 +extern struct switch_device *switch_alloc(void);
33765 +extern int switch_register(struct switch_device *switch_dev);
33766 +extern void switch_unregister(struct switch_device *switch_dev);
33767 +
33768 +#endif
33769 --- /dev/null
33770 +++ b/arch/ubicom32/mach-common/ubi32-gpio.c
33771 @@ -0,0 +1,411 @@
33772 +/*
33773 + * arch/ubicom32/mach-common/ubi32-gpio.c
33774 + *   Ubicom gpio driver
33775 + *
33776 + * (C) Copyright 2009, Ubicom, Inc.
33777 + *
33778 + * This file is part of the Ubicom32 Linux Kernel Port.
33779 + *
33780 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33781 + * it and/or modify it under the terms of the GNU General Public License
33782 + * as published by the Free Software Foundation, either version 2 of the
33783 + * License, or (at your option) any later version.
33784 + *
33785 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33786 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33787 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
33788 + * the GNU General Public License for more details.
33789 + *
33790 + * You should have received a copy of the GNU General Public License
33791 + * along with the Ubicom32 Linux Kernel Port.  If not,
33792 + * see <http://www.gnu.org/licenses/>.
33793 + *
33794 + * Ubicom32 implementation derived from (with many thanks):
33795 + *   arch/m68knommu
33796 + *   arch/blackfin
33797 + *   arch/parisc
33798 + */
33799 +
33800 +#include <linux/module.h>
33801 +#include <linux/init.h>
33802 +#include <linux/errno.h>
33803 +#include <linux/kernel.h>
33804 +#include <linux/io.h>
33805 +#include <linux/gpio.h>
33806 +#include <linux/irq.h>
33807 +#include <linux/version.h>
33808 +
33809 +#if defined(CONFIG_PROC_FS)
33810 +#include <linux/proc_fs.h>
33811 +#endif
33812 +
33813 +#include <linux/io.h>
33814 +#include <asm/ip5000.h>
33815 +#include <linux/gpio.h>
33816 +
33817 +#define UBI_GPIO_CHECK_RANGE     0  /* !0 enables range checking */
33818 +
33819 +
33820 +/*
33821 + * Each I/O port can be configured to operate in one of several
33822 + * functional modes. One of these modes is GPIO, which causes the
33823 + * entire port to function as a GPIO port.  Since the various port
33824 + * registers serve the system with other important functions, such as
33825 + * ethernet, serial, USB, etc., it isn't advantageous to set any of
33826 + * the ports to be entirely dedicated for GPIO use.  The processor
33827 + * alternatively allows individual bits of a port to be assigned to be
33828 + * used as GPIO independently from the overall port function.  This
33829 + * bit-by-bit assignment is selected by setting the corresponding bit
33830 + * in the port's gpio_mask register.  When set, the selected bit is
33831 + * then enabled as a GPIO.  If the corresponding bit is set in the
33832 + * gpio_ctl register of the port, the bit is configured as a GPIO
33833 + * output.  Otherwise, it is an input.
33834 + *
33835 + * NOTE: This driver uses the bit-by-bit GPIO function assignment
33836 + * exclusively and *never* sets the port function registers to the
33837 + * GPIO function.
33838 + *
33839 + * GPIO is not the main function of any of the I/O ports.  The port
33840 + * bit widths are variable from one port to the next, determined by
33841 + * the more common I/O functions of the ports.  For simplicity, this
33842 + * driver assumes all the ports are 32 bits wide regardless of the
33843 + * real bit width of the port.  GPIO bits are numbered from zero to
33844 + * MAX_UBICOM_GPIOS.  Within a port, the least significant bit is
33845 + * numbered bit zero, the most significant is bit 31.  Since the ports
33846 + * are considered logically contiguous, GPIO #32 is the zeroth bit in
33847 + * port #1, and so on.  Due to the hardware definition, there are
33848 + * large gaps in the GPIO numbers representing real pins.
33849 + *
33850 + * NOTE: It is up to the programmer to refer to the processor data
33851 + * sheet to determine which bits in which ports can be accessed and
33852 + * used for GPIO.
33853 + *
33854 + */
33855 +
33856 +
33857 +/* There are 9 ports, A through I. Not all 32 bits in each
33858 + * port can be a GPIO, but we pretend they are.  Its up to the
33859 + * programmer to refer to the processor data sheet.
33860 + */
33861 +#define MAX_UBICOM_GPIOS   (9 * 32) /* ARCH_NR_GPIOS */
33862 +#define NUM_GPIO_PORTS     (gpio_bank(MAX_UBICOM_GPIOS))
33863 +
33864 +
33865 +/* GPIO reservation bit map array */
33866 +static int reserved_gpio_map[NUM_GPIO_PORTS];
33867 +
33868 +
33869 +/* Array of hardware io_port addresses */
33870 +static struct ubicom32_io_port *gpio_bank_addr[NUM_GPIO_PORTS] =
33871 +{
33872 +       UBICOM32_IO_PORT(RA),
33873 +       UBICOM32_IO_PORT(RB),
33874 +       UBICOM32_IO_PORT(RC),
33875 +       UBICOM32_IO_PORT(RD),
33876 +       UBICOM32_IO_PORT(RE),
33877 +       UBICOM32_IO_PORT(RF),
33878 +       UBICOM32_IO_PORT(RG),
33879 +       UBICOM32_IO_PORT(RH),
33880 +       UBICOM32_IO_PORT(RI)
33881 +};
33882 +
33883 +
33884 +struct ubi_gpio_chip {
33885 +       /*
33886 +        * Right now, nothing else lives here.
33887 +        */
33888 +       struct gpio_chip gpio_chip;
33889 +};
33890 +
33891 +
33892 +#if UBI_GPIO_CHECK_RANGE
33893 +inline int check_gpio(unsigned gpio)
33894 +{
33895 +       if (gpio >= MAX_UBICOM_GPIOS)
33896 +               return -EINVAL;
33897 +       return 0;
33898 +}
33899 +#else
33900 +#define check_gpio(n)   (0)
33901 +#endif
33902 +
33903 +/*
33904 + * ubi_gpio_get_port
33905 + *     Get the IO port associated with a certain gpio
33906 + */
33907 +struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio)
33908 +{
33909 +       if (gpio_bank(gpio) > NUM_GPIO_PORTS) {
33910 +               return NULL;
33911 +       }
33912 +       return gpio_bank_addr[gpio_bank(gpio)];
33913 +}
33914 +
33915 +/*
33916 + * ubi_gpio_error()
33917 + */
33918 +static void ubi_gpio_error(unsigned gpio)
33919 +{
33920 +       printk(KERN_ERR "ubicom-gpio: GPIO %d wasn't requested!\n", gpio);
33921 +}
33922 +
33923 +/*
33924 + * ubi_port_setup()
33925 + */
33926 +static void ubi_port_setup(unsigned gpio, unsigned short usage)
33927 +{
33928 +       if (!check_gpio(gpio)) {
33929 +               if (usage) {
33930 +                       UBICOM32_GPIO_ENABLE(gpio);
33931 +               } else {
33932 +                       UBICOM32_GPIO_DISABLE(gpio);
33933 +               }
33934 +       }
33935 +}
33936 +
33937 +/*
33938 + * ubi_gpio_request()
33939 + */
33940 +static int ubi_gpio_request(struct gpio_chip *chip, unsigned gpio)
33941 +{
33942 +       unsigned long flags;
33943 +
33944 +       if (check_gpio(gpio) < 0)
33945 +               return -EINVAL;
33946 +
33947 +       local_irq_save(flags);
33948 +
33949 +       if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
33950 +               printk(KERN_ERR "ubi-gpio: GPIO %d is already reserved!\n",
33951 +                      gpio);
33952 +               local_irq_restore(flags);
33953 +               return -EBUSY;
33954 +       }
33955 +
33956 +       reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
33957 +
33958 +       ubi_port_setup(gpio, 1);
33959 +
33960 +       local_irq_restore(flags);
33961 +
33962 +       return 0;
33963 +}
33964 +
33965 +/*
33966 + * ubi_gpio_free()
33967 + */
33968 +static void ubi_gpio_free(struct gpio_chip *chip, unsigned gpio)
33969 +{
33970 +       unsigned long flags;
33971 +
33972 +       if (check_gpio(gpio) < 0)
33973 +               return;
33974 +
33975 +       local_irq_save(flags);
33976 +
33977 +       if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
33978 +               ubi_gpio_error(gpio);
33979 +               local_irq_restore(flags);
33980 +               return;
33981 +       }
33982 +
33983 +       /* Assert the pin is no longer claimed */
33984 +       reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
33985 +
33986 +       /* Revert port bit to use specified by port->function */
33987 +       ubi_port_setup(gpio, 0);
33988 +
33989 +       local_irq_restore(flags);
33990 +}
33991 +
33992 +/*
33993 + * ubi_gpio_direction_input()
33994 + */
33995 +static int ubi_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
33996 +{
33997 +       unsigned long flags;
33998 +
33999 +       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34000 +               ubi_gpio_error(gpio);
34001 +               return -EINVAL;
34002 +       }
34003 +
34004 +       local_irq_save(flags);
34005 +
34006 +       /* Configure pin as gpio */
34007 +       ubi_port_setup(gpio, 1);
34008 +
34009 +       /* Assert pin is an input */
34010 +       UBICOM32_GPIO_SET_PIN_INPUT(gpio);
34011 +
34012 +       local_irq_restore(flags);
34013 +
34014 +       return 0;
34015 +}
34016 +
34017 +
34018 +/*
34019 + * ubi_gpio_direction_output()
34020 + */
34021 +static int ubi_gpio_direction_output(struct gpio_chip *chip,
34022 +                                    unsigned gpio, int value)
34023 +{
34024 +       unsigned long flags;
34025 +
34026 +       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34027 +               ubi_gpio_error(gpio);
34028 +               return -EINVAL;
34029 +       }
34030 +
34031 +       local_irq_save(flags);
34032 +
34033 +       /* Configure pin as gpio and set initial value in gpio_out register
34034 +        * so that when we enable it as an output, it will have the correct
34035 +        * initial value.
34036 +        */
34037 +       ubi_port_setup(gpio, 1);
34038 +       if (value) {
34039 +               UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34040 +       } else {
34041 +               UBICOM32_GPIO_SET_PIN_LOW(gpio);
34042 +       }
34043 +
34044 +       /* Enable the pin as an output */
34045 +       UBICOM32_GPIO_SET_PIN_OUTPUT(gpio);
34046 +
34047 +       local_irq_restore(flags);
34048 +
34049 +       return 0;
34050 +}
34051 +
34052 +
34053 +/*
34054 + * ubi_gpio_get_value()
34055 + */
34056 +static int ubi_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
34057 +{
34058 +       return 0 != (gpio_bank_addr[gpio_bank(gpio)]->gpio_in & gpio_bit(gpio));
34059 +}
34060 +
34061 +
34062 +/*
34063 + * ubi_gpio_set_value()
34064 + */
34065 +static void ubi_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
34066 +                              int arg)
34067 +{
34068 +       unsigned long flags;
34069 +       local_irq_save(flags);
34070 +
34071 +       if (arg) {
34072 +               UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34073 +       } else {
34074 +               UBICOM32_GPIO_SET_PIN_LOW(gpio);
34075 +       }
34076 +
34077 +       local_irq_restore(flags);
34078 +}
34079 +
34080 +
34081 +/*
34082 + * ubi_gpio_to_irq()
34083 + */
34084 +static int ubi_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
34085 +{
34086 +       return gpio_to_irq(gpio);
34087 +}
34088 +
34089 +
34090 +/*
34091 + * ubi_gpio_init()
34092 + */
34093 +int __init ubi_gpio_init(void)
34094 +{
34095 +       int k;
34096 +       int status;
34097 +       struct ubi_gpio_chip *chip;
34098 +       struct gpio_chip *gc;
34099 +
34100 +       printk(KERN_INFO "Ubicom GPIO Controller\n");
34101 +
34102 +       chip = kzalloc(sizeof(struct ubi_gpio_chip), GFP_KERNEL);
34103 +       if (chip == NULL)
34104 +               return -ENOMEM;
34105 +
34106 +       gc = &chip->gpio_chip;
34107 +       gc->request          = ubi_gpio_request;
34108 +       gc->free             = ubi_gpio_free;
34109 +       gc->to_irq           = ubi_gpio_to_irq;
34110 +       gc->direction_input  = ubi_gpio_direction_input;
34111 +       gc->direction_output = ubi_gpio_direction_output;
34112 +       gc->get              = ubi_gpio_get_value;
34113 +       gc->set              = ubi_gpio_set_value;
34114 +       gc->can_sleep        = 0;
34115 +       gc->base             = 0;
34116 +       gc->ngpio            = MAX_UBICOM_GPIOS; /* ARCH_NR_GPIOS - 1 */
34117 +       gc->label            = "ubi_gpio";
34118 +
34119 +       status = gpiochip_add(gc);
34120 +       if (status != 0) {
34121 +               kfree(chip);
34122 +               return status;
34123 +       }
34124 +
34125 +       /* Assert all pins are free */
34126 +       for (k = 0; k < NUM_GPIO_PORTS; k++) {
34127 +               reserved_gpio_map[k] = 0;
34128 +       }
34129 +
34130 +       return 0;
34131 +}
34132 +
34133 +#if defined(CONFIG_PROC_FS)
34134 +/*
34135 + * ubi_get_gpio_dir()
34136 + */
34137 +static int ubi_get_gpio_dir(unsigned gpio)
34138 +{
34139 +       if (gpio_bank_addr[gpio_bank(gpio)]->gpio_ctl & gpio_bit(gpio))
34140 +               return 1;
34141 +       else
34142 +               return 0;
34143 +}
34144 +
34145 +/*
34146 + * gpio_proc_read()
34147 + */
34148 +static int ubi_gpio_proc_read(char *buf, char **start, off_t offset,
34149 +                         int len, int *unused_i, void *unused_v)
34150 +{
34151 +       int c, outlen = 0;
34152 +
34153 +       for (c = 0; c < MAX_UBICOM_GPIOS; c++) {
34154 +               if (!check_gpio(c) &&
34155 +                   (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) {
34156 +                       len = sprintf(buf, "GPIO_%d:\t\tGPIO %s\n", c,
34157 +                                     ubi_get_gpio_dir(c) ? "OUTPUT" : "INPUT");
34158 +               } else {
34159 +                       continue;
34160 +               }
34161 +
34162 +               buf += len;
34163 +               outlen += len;
34164 +       }
34165 +       return outlen;
34166 +}
34167 +
34168 +/*
34169 + * ubi_gpio_register_proc()
34170 + */
34171 +static __init int ubi_gpio_register_proc(void)
34172 +{
34173 +       struct proc_dir_entry *proc_gpio;
34174 +
34175 +       proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
34176 +       if (proc_gpio)
34177 +               proc_gpio->read_proc = ubi_gpio_proc_read;
34178 +
34179 +       return proc_gpio != NULL;
34180 +}
34181 +device_initcall(ubi_gpio_register_proc);
34182 +#endif
34183 --- /dev/null
34184 +++ b/arch/ubicom32/mach-common/ubicom32hid.c
34185 @@ -0,0 +1,557 @@
34186 +/*
34187 + * arch/ubicom32/mach-common/ubicom32hid.c
34188 + *   I2C driver for HID coprocessor found on some DPF implementations.
34189 + *
34190 + * (C) Copyright 2009, Ubicom, Inc.
34191 + *
34192 + * This file is part of the Ubicom32 Linux Kernel Port.
34193 + *
34194 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34195 + * it and/or modify it under the terms of the GNU General Public License
34196 + * as published by the Free Software Foundation, either version 2 of the
34197 + * License, or (at your option) any later version.
34198 + *
34199 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34200 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34201 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
34202 + * the GNU General Public License for more details.
34203 + *
34204 + * You should have received a copy of the GNU General Public License
34205 + * along with the Ubicom32 Linux Kernel Port.  If not,
34206 + * see <http://www.gnu.org/licenses/>.
34207 + *
34208 + * Ubicom32 implementation derived from (with many thanks):
34209 + *   arch/m68knommu
34210 + *   arch/blackfin
34211 + *   arch/parisc
34212 + */
34213 +
34214 +#include <linux/module.h>
34215 +#include <linux/init.h>
34216 +#include <linux/gpio.h>
34217 +#include <linux/delay.h>
34218 +#include <linux/platform_device.h>
34219 +#include <linux/i2c.h>
34220 +#include <linux/backlight.h>
34221 +#include <linux/fb.h>
34222 +#include <linux/input.h>
34223 +#include <linux/input-polldev.h>
34224 +
34225 +#include <asm/ubicom32hid.h>
34226 +
34227 +#define DRIVER_NAME "ubicom32hid"
34228 +
34229 +#ifdef DEBUG
34230 +static int ubicom32hid_debug;
34231 +#endif
34232 +
34233 +static const struct i2c_device_id ubicom32hid_id[] = {
34234 +       { DRIVER_NAME, },
34235 +       { }
34236 +};
34237 +MODULE_DEVICE_TABLE(i2c, ubicom32hid_id);
34238 +
34239 +/*
34240 + * Define this to make IR checking strict, in general, it's not needed
34241 + */
34242 +#undef UBICOM32HID_STRICT_IR_CHECK
34243 +
34244 +#define UBICOM32HID_CMD_SET_PWM                0x01
34245 +#define UBICOM32HID_CMD_SET_BL_EN      0x02
34246 +#define UBICOM32HID_BL_EN_LOW          0x00
34247 +#define UBICOM32HID_BL_EN_HIZ          0x01
34248 +#define UBICOM32HID_BL_EN_HI           0x02
34249 +#define UBICOM32HID_CMD_FLUSH          0x99
34250 +#define UBICOM32HID_CMD_RESET          0x99
34251 +#define UBICOM32HID_CMD_GET_IR_SWITCH  0xC0
34252 +#define UBICOM32HID_CMD_GET_REVISION   0xfd
34253 +#define UBICOM32HID_CMD_GET_DEVICE_ID  0xfe
34254 +#define UBICOM32HID_CMD_GET_VERSION    0xff
34255 +#define UBICOM32HID_DEVICE_ID          0x49
34256 +
34257 +#define UBICOM32HID_MAX_BRIGHTNESS_PWM 255
34258 +
34259 +/*
34260 + * Data structure returned by the HID device
34261 + */
34262 +struct ubicom32hid_input_data {
34263 +       uint32_t        ircmd;
34264 +       uint8_t         sw_state;
34265 +       uint8_t         sw_changed;
34266 +};
34267 +
34268 +/*
34269 + * Our private data
34270 + */
34271 +struct ubicom32hid_data {
34272 +       /*
34273 +        * Pointer to the platform data structure, we need the settings.
34274 +        */
34275 +       const struct ubicom32hid_platform_data  *pdata;
34276 +
34277 +       /*
34278 +        * Backlight device
34279 +        */
34280 +       struct backlight_device                 *bldev;
34281 +
34282 +       /*
34283 +        * I2C client, for sending messages to the HID device
34284 +        */
34285 +       struct i2c_client                       *client;
34286 +
34287 +       /*
34288 +        * Current intensity, used for get_intensity.
34289 +        */
34290 +       int                                     cur_intensity;
34291 +
34292 +       /*
34293 +        * Input subsystem
34294 +        *      We won't register an input subsystem if there are no mappings.
34295 +        */
34296 +       struct input_polled_dev                 *poll_dev;
34297 +};
34298 +
34299 +
34300 +/*
34301 + * ubicom32hid_set_intensity
34302 + */
34303 +static int ubicom32hid_set_intensity(struct backlight_device *bd)
34304 +{
34305 +       struct ubicom32hid_data *ud =
34306 +               (struct ubicom32hid_data *)bl_get_data(bd);
34307 +       int intensity = bd->props.brightness;
34308 +       int reg;
34309 +       u8_t val;
34310 +       int ret;
34311 +
34312 +       /*
34313 +        * If we're blanked the the intensity doesn't matter.
34314 +        */
34315 +       if ((bd->props.power != FB_BLANK_UNBLANK) ||
34316 +           (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
34317 +               intensity = 0;
34318 +       }
34319 +
34320 +       /*
34321 +        * Set the brightness based on the type of backlight
34322 +        */
34323 +       if (ud->pdata->type == UBICOM32HID_BL_TYPE_BINARY) {
34324 +               reg = UBICOM32HID_CMD_SET_BL_EN;
34325 +               if (intensity) {
34326 +                       val = ud->pdata->invert
34327 +                               ? UBICOM32HID_BL_EN_LOW : UBICOM32HID_BL_EN_HI;
34328 +               } else {
34329 +                       val = ud->pdata->invert
34330 +                               ? UBICOM32HID_BL_EN_HI : UBICOM32HID_BL_EN_LOW;
34331 +               }
34332 +       } else {
34333 +               reg = UBICOM32HID_CMD_SET_PWM;
34334 +               val = ud->pdata->invert
34335 +                       ? (UBICOM32HID_MAX_BRIGHTNESS_PWM - intensity) :
34336 +                       intensity;
34337 +       }
34338 +
34339 +       /*
34340 +        * Send the command
34341 +        */
34342 +       ret = i2c_smbus_write_byte_data(ud->client, reg, val);
34343 +       if (ret < 0) {
34344 +               dev_warn(&ud->client->dev, "Unable to write backlight err=%d\n",
34345 +                        ret);
34346 +               return ret;
34347 +       }
34348 +
34349 +       ud->cur_intensity = intensity;
34350 +
34351 +       return 0;
34352 +}
34353 +
34354 +/*
34355 + * ubicom32hid_get_intensity
34356 + *     Return the current intensity of the backlight.
34357 + */
34358 +static int ubicom32hid_get_intensity(struct backlight_device *bd)
34359 +{
34360 +       struct ubicom32hid_data *ud =
34361 +               (struct ubicom32hid_data *)bl_get_data(bd);
34362 +
34363 +       return ud->cur_intensity;
34364 +}
34365 +
34366 +/*
34367 + * ubicom32hid_verify_data
34368 + *     Verify the data to see if there is any action to be taken
34369 + *
34370 + * Returns 0 if no action is to be taken, non-zero otherwise
34371 + */
34372 +static int ubicom32hid_verify_data(struct ubicom32hid_data *ud,
34373 +                                  struct ubicom32hid_input_data *data)
34374 +{
34375 +       uint8_t *ircmd = (uint8_t *)&(data->ircmd);
34376 +
34377 +       /*
34378 +        * ircmd == DEADBEEF means ir queue is empty.  Since this is a
34379 +        * meaningful code, that means the rest of the message is most likely
34380 +        * correct, so only process the data if the switch state has changed.
34381 +        */
34382 +       if (data->ircmd == 0xDEADBEEF) {
34383 +               return data->sw_changed != 0;
34384 +       }
34385 +
34386 +       /*
34387 +        * We have an ircmd which is not empty:
34388 +        *      Data[1] should be the complement of Data[0]
34389 +        */
34390 +       if (ircmd[0] != (u8_t)~ircmd[1]) {
34391 +               return 0;
34392 +       }
34393 +
34394 +#ifdef UBICOM32HID_STRICT_IR_CHECK
34395 +       /*
34396 +        * It seems that some remote controls don't follow the NEC protocol
34397 +        * properly, so only do this check if the remote does indeed follow the
34398 +        * spec.  Data[3] should be the complement of Data[2]
34399 +        */
34400 +       if (ircmd[2] == (u8_t)~ircmd[3]) {
34401 +               return 1;
34402 +       }
34403 +
34404 +       /*
34405 +        * For non-compliant remotes, check the system code according to what
34406 +        * they send.
34407 +        */
34408 +       if ((ircmd[2] != UBICOM32HID_IR_SYSTEM_CODE_CHECK) ||
34409 +           (ircmd[3] != UBICOM32HID_IR_SYSTEM_CODE)) {
34410 +               return 0;
34411 +       }
34412 +#endif
34413 +
34414 +       /*
34415 +        * Data checks out, process
34416 +        */
34417 +       return 1;
34418 +}
34419 +
34420 +/*
34421 + * ubicom32hid_poll_input
34422 + *     Poll the input from the HID device.
34423 + */
34424 +static void ubicom32hid_poll_input(struct input_polled_dev *dev)
34425 +{
34426 +       struct ubicom32hid_data *ud = (struct ubicom32hid_data *)dev->private;
34427 +       const struct ubicom32hid_platform_data *pdata = ud->pdata;
34428 +       struct ubicom32hid_input_data data;
34429 +       struct input_dev *id = dev->input;
34430 +       int i;
34431 +       int sync_needed = 0;
34432 +       uint8_t cmd;
34433 +       int ret;
34434 +
34435 +       /*
34436 +        * Flush the queue
34437 +        */
34438 +       cmd = UBICOM32HID_CMD_FLUSH;
34439 +       ret = i2c_master_send(ud->client, &cmd, 1);
34440 +       if (ret < 0) {
34441 +               return;
34442 +       }
34443 +
34444 +       ret = i2c_smbus_read_i2c_block_data(
34445 +               ud->client, UBICOM32HID_CMD_GET_IR_SWITCH, 6, (void *)&data);
34446 +       if (ret < 0) {
34447 +               return;
34448 +       }
34449 +
34450 +       /*
34451 +        * Verify the data to see if there is any action to be taken
34452 +        */
34453 +       if (!ubicom32hid_verify_data(ud, &data)) {
34454 +               return;
34455 +       }
34456 +
34457 +#ifdef DEBUG
34458 +       if (ubicom32hid_debug) {
34459 +               printk("Polled ircmd=%8x swstate=%2x swchanged=%2x\n",
34460 +                      data.ircmd, data.sw_state, data.sw_changed);
34461 +       }
34462 +#endif
34463 +
34464 +       /*
34465 +        * Process changed switches
34466 +        */
34467 +       if (data.sw_changed) {
34468 +               const struct ubicom32hid_button *ub = pdata->buttons;
34469 +               for (i = 0; i < pdata->nbuttons; i++, ub++) {
34470 +                       uint8_t mask = (1 << ub->bit);
34471 +                       if (!(data.sw_changed & mask)) {
34472 +                               continue;
34473 +                       }
34474 +
34475 +                       sync_needed = 1;
34476 +                       input_event(id, ub->type, ub->code,
34477 +                                   (data.sw_state & mask) ? 1 : 0);
34478 +               }
34479 +       }
34480 +       if (sync_needed) {
34481 +               input_sync(id);
34482 +       }
34483 +
34484 +       /*
34485 +        * Process ir codes
34486 +        */
34487 +       if (data.ircmd != 0xDEADBEEF) {
34488 +               const struct ubicom32hid_ir *ui = pdata->ircodes;
34489 +               for (i = 0; i < pdata->nircodes; i++, ui++) {
34490 +                       if (ui->ir_code == data.ircmd) {
34491 +                               /*
34492 +                                * Simulate a up/down event
34493 +                                */
34494 +                               input_event(id, ui->type, ui->code, 1);
34495 +                               input_sync(id);
34496 +                               input_event(id, ui->type, ui->code, 0);
34497 +                               input_sync(id);
34498 +                       }
34499 +               }
34500 +       }
34501 +}
34502 +
34503 +
34504 +/*
34505 + * Backlight ops
34506 + */
34507 +static struct backlight_ops ubicom32hid_blops = {
34508 +       .get_brightness = ubicom32hid_get_intensity,
34509 +       .update_status  = ubicom32hid_set_intensity,
34510 +};
34511 +
34512 +/*
34513 + * ubicom32hid_probe
34514 + */
34515 +static int ubicom32hid_probe(struct i2c_client *client,
34516 +                            const struct i2c_device_id *id)
34517 +{
34518 +       struct ubicom32hid_platform_data *pdata;
34519 +       struct ubicom32hid_data *ud;
34520 +       int ret;
34521 +       int i;
34522 +       u8 version[2];
34523 +       char buf[1];
34524 +
34525 +       pdata = client->dev.platform_data;
34526 +       if (pdata == NULL) {
34527 +               return -ENODEV;
34528 +       }
34529 +
34530 +       /*
34531 +        * See if we even have a device available before allocating memory.
34532 +        *
34533 +        * Hard reset the device
34534 +        */
34535 +       ret = gpio_request(pdata->gpio_reset, "ubicom32hid-reset");
34536 +       if (ret < 0) {
34537 +               return ret;
34538 +       }
34539 +       gpio_direction_output(pdata->gpio_reset, pdata->gpio_reset_polarity);
34540 +       udelay(100);
34541 +       gpio_set_value(pdata->gpio_reset, !pdata->gpio_reset_polarity);
34542 +       udelay(100);
34543 +
34544 +       /*
34545 +        * soft reset the device.  It sometimes takes a while to do this.
34546 +        */
34547 +       for (i = 0; i < 50; i++) {
34548 +               buf[0] = UBICOM32HID_CMD_RESET;
34549 +               ret = i2c_master_send(client, buf, 1);
34550 +               if (ret > 0) {
34551 +                       break;
34552 +               }
34553 +               udelay(10000);
34554 +       }
34555 +       if (i == 50) {
34556 +               dev_warn(&client->dev, "Unable to reset device\n");
34557 +               goto fail;
34558 +       }
34559 +
34560 +       ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_DEVICE_ID);
34561 +       if (ret != UBICOM32HID_DEVICE_ID) {
34562 +               dev_warn(&client->dev, "Incorrect device id %02x\n", buf[0]);
34563 +               ret = -ENODEV;
34564 +               goto fail;
34565 +       }
34566 +
34567 +       ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_VERSION);
34568 +       if (ret < 0) {
34569 +               dev_warn(&client->dev, "Unable to get version\n");
34570 +               goto fail;
34571 +       }
34572 +       version[0] = ret;
34573 +
34574 +       ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_REVISION);
34575 +       if (ret < 0) {
34576 +               dev_warn(&client->dev, "Unable to get revision\n");
34577 +               goto fail;
34578 +       }
34579 +       version[1] = ret;
34580 +
34581 +       /*
34582 +        * Allocate our private data
34583 +        */
34584 +       ud = kzalloc(sizeof(struct ubicom32hid_data), GFP_KERNEL);
34585 +       if (!ud) {
34586 +               ret = -ENOMEM;
34587 +               goto fail;
34588 +       }
34589 +       ud->pdata = pdata;
34590 +       ud->client = client;
34591 +
34592 +       /*
34593 +        * Register our backlight device
34594 +        */
34595 +       ud->bldev = backlight_device_register(DRIVER_NAME, &client->dev,
34596 +                                             ud, &ubicom32hid_blops);
34597 +       if (IS_ERR(ud->bldev)) {
34598 +               ret = PTR_ERR(ud->bldev);
34599 +               goto fail2;
34600 +       }
34601 +       platform_set_drvdata(client, ud);
34602 +
34603 +       /*
34604 +        * Start up the backlight with the requested intensity
34605 +        */
34606 +       ud->bldev->props.power = FB_BLANK_UNBLANK;
34607 +       ud->bldev->props.max_brightness =
34608 +               (pdata->type == UBICOM32HID_BL_TYPE_PWM) ?
34609 +               UBICOM32HID_MAX_BRIGHTNESS_PWM : 1;
34610 +       if (pdata->default_intensity < ud->bldev->props.max_brightness) {
34611 +               ud->bldev->props.brightness = pdata->default_intensity;
34612 +       } else {
34613 +               dev_warn(&client->dev, "Default brightness out of range, "
34614 +                        "setting to max\n");
34615 +               ud->bldev->props.brightness = ud->bldev->props.max_brightness;
34616 +       }
34617 +
34618 +       ubicom32hid_set_intensity(ud->bldev);
34619 +
34620 +       /*
34621 +        * Check to see if we have any inputs
34622 +        */
34623 +       if (!pdata->nbuttons && !pdata->nircodes) {
34624 +               goto done;
34625 +       }
34626 +
34627 +       /*
34628 +        * We have buttons or codes, we must register an input device
34629 +        */
34630 +       ud->poll_dev = input_allocate_polled_device();
34631 +       if (!ud->poll_dev) {
34632 +               ret = -ENOMEM;
34633 +               goto fail3;
34634 +       }
34635 +
34636 +       /*
34637 +        * Setup the polling to default to 100ms
34638 +        */
34639 +       ud->poll_dev->poll = ubicom32hid_poll_input;
34640 +       ud->poll_dev->poll_interval =
34641 +               pdata->poll_interval ? pdata->poll_interval : 100;
34642 +       ud->poll_dev->private = ud;
34643 +
34644 +       ud->poll_dev->input->name =
34645 +               pdata->input_name ? pdata->input_name : "Ubicom32HID";
34646 +       ud->poll_dev->input->phys = "ubicom32hid/input0";
34647 +       ud->poll_dev->input->dev.parent = &client->dev;
34648 +       ud->poll_dev->input->id.bustype = BUS_I2C;
34649 +
34650 +       /*
34651 +        * Set the capabilities by running through the buttons and ir codes
34652 +        */
34653 +       for (i = 0; i < pdata->nbuttons; i++) {
34654 +               const struct ubicom32hid_button *ub = &pdata->buttons[i];
34655 +
34656 +               input_set_capability(ud->poll_dev->input,
34657 +                                    ub->type ? ub->type : EV_KEY, ub->code);
34658 +       }
34659 +
34660 +       for (i = 0; i < pdata->nircodes; i++) {
34661 +               const struct ubicom32hid_ir *ui = &pdata->ircodes[i];
34662 +
34663 +               input_set_capability(ud->poll_dev->input,
34664 +                                    ui->type ? ui->type : EV_KEY, ui->code);
34665 +       }
34666 +
34667 +       ret = input_register_polled_device(ud->poll_dev);
34668 +       if (ret) {
34669 +               goto fail3;
34670 +       }
34671 +
34672 +done:
34673 +       printk(KERN_INFO DRIVER_NAME ": enabled, version=%02x.%02x\n",
34674 +              version[0], version[1]);
34675 +
34676 +       return 0;
34677 +
34678 +fail3:
34679 +       gpio_free(ud->pdata->gpio_reset);
34680 +       backlight_device_unregister(ud->bldev);
34681 +fail2:
34682 +       kfree(ud);
34683 +fail:
34684 +       gpio_free(pdata->gpio_reset);
34685 +       return ret;
34686 +}
34687 +
34688 +/*
34689 + * ubicom32hid_remove
34690 + */
34691 +static int ubicom32hid_remove(struct i2c_client *client)
34692 +{
34693 +       struct ubicom32hid_data *ud =
34694 +               (struct ubicom32hid_data *)platform_get_drvdata(client);
34695 +
34696 +       gpio_free(ud->pdata->gpio_reset);
34697 +
34698 +       backlight_device_unregister(ud->bldev);
34699 +
34700 +       if (ud->poll_dev) {
34701 +               input_unregister_polled_device(ud->poll_dev);
34702 +               input_free_polled_device(ud->poll_dev);
34703 +       }
34704 +
34705 +       platform_set_drvdata(client, NULL);
34706 +
34707 +       kfree(ud);
34708 +
34709 +       return 0;
34710 +}
34711 +
34712 +static struct i2c_driver ubicom32hid_driver = {
34713 +       .driver = {
34714 +               .name   = DRIVER_NAME,
34715 +               .owner  = THIS_MODULE,
34716 +       },
34717 +       .probe          = ubicom32hid_probe,
34718 +       .remove         = __exit_p(ubicom32hid_remove),
34719 +       .id_table       = ubicom32hid_id,
34720 +};
34721 +
34722 +/*
34723 + * ubicom32hid_init
34724 + */
34725 +static int __init ubicom32hid_init(void)
34726 +{
34727 +       return i2c_add_driver(&ubicom32hid_driver);
34728 +}
34729 +module_init(ubicom32hid_init);
34730 +
34731 +/*
34732 + * ubicom32hid_exit
34733 + */
34734 +static void __exit ubicom32hid_exit(void)
34735 +{
34736 +       i2c_del_driver(&ubicom32hid_driver);
34737 +}
34738 +module_exit(ubicom32hid_exit);
34739 +
34740 +MODULE_AUTHOR("Pat Tjin <@ubicom.com>")
34741 +MODULE_DESCRIPTION("Ubicom HID driver");
34742 +MODULE_LICENSE("GPL");
34743 --- /dev/null
34744 +++ b/arch/ubicom32/mach-common/ubicom32input.c
34745 @@ -0,0 +1,265 @@
34746 +/*
34747 + * arch/ubicom32/mach-common/ubicom32input.c
34748 + *   Ubicom32 Input driver
34749 + *
34750 + *   based on gpio-keys
34751 + *
34752 + * (C) Copyright 2009, Ubicom, Inc.
34753 + *
34754 + * This file is part of the Ubicom32 Linux Kernel Port.
34755 + *
34756 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34757 + * it and/or modify it under the terms of the GNU General Public License
34758 + * as published by the Free Software Foundation, either version 2 of the
34759 + * License, or (at your option) any later version.
34760 + *
34761 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34762 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34763 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
34764 + * the GNU General Public License for more details.
34765 + *
34766 + * You should have received a copy of the GNU General Public License
34767 + * along with the Ubicom32 Linux Kernel Port.  If not,
34768 + * see <http://www.gnu.org/licenses/>.
34769 + *
34770 + * Ubicom32 implementation derived from (with many thanks):
34771 + *   arch/m68knommu
34772 + *   arch/blackfin
34773 + *   arch/parisc
34774 + *
34775 + *
34776 + * TODO: add groups for inputs which can be sampled together (i.e. I2C)
34777 + */
34778 +
34779 +#include <linux/kernel.h>
34780 +#include <linux/module.h>
34781 +#include <linux/platform_device.h>
34782 +#include <linux/input.h>
34783 +#include <linux/input-polldev.h>
34784 +#include <linux/delay.h>
34785 +#include <linux/gpio.h>
34786 +
34787 +#include <asm/ubicom32input.h>
34788 +
34789 +struct ubicom32input_data {
34790 +       struct ubicom32input_platform_data      *pdata;
34791 +
34792 +       struct input_polled_dev                 *poll_dev;
34793 +
34794 +       /*
34795 +        * collection of previous states for buttons
34796 +        */
34797 +       u8                                      prev_state[0];
34798 +};
34799 +
34800 +/*
34801 + * ubicom32input_poll
34802 + */
34803 +static void ubicom32input_poll(struct input_polled_dev *dev)
34804 +{
34805 +       struct ubicom32input_data *ud =
34806 +               (struct ubicom32input_data *)dev->private;
34807 +       struct ubicom32input_platform_data *pdata = ud->pdata;
34808 +       struct input_dev *id = dev->input;
34809 +       int i;
34810 +       int sync_needed = 0;
34811 +
34812 +       for (i = 0; i < pdata->nbuttons; i++) {
34813 +               const struct ubicom32input_button *ub = &pdata->buttons[i];
34814 +               int state = 0;
34815 +
34816 +               int val = gpio_get_value(ub->gpio);
34817 +
34818 +               /*
34819 +                * Check to see if the state changed from the last time we
34820 +                * looked
34821 +                */
34822 +               if (val == ud->prev_state[i]) {
34823 +                       continue;
34824 +               }
34825 +
34826 +               /*
34827 +                * The state has changed, determine if we are "up" or "down"
34828 +                */
34829 +               ud->prev_state[i] = val;
34830 +
34831 +               if ((!val && ub->active_low) || (val && !ub->active_low)) {
34832 +                       state = 1;
34833 +               }
34834 +
34835 +               input_event(id, ub->type, ub->code, state);
34836 +               sync_needed = 1;
34837 +       }
34838 +
34839 +       if (sync_needed) {
34840 +               input_sync(id);
34841 +       }
34842 +}
34843 +
34844 +/*
34845 + * ubicom32input_probe
34846 + */
34847 +static int __devinit ubicom32input_probe(struct platform_device *pdev)
34848 +{
34849 +       int i;
34850 +       struct ubicom32input_data *ud;
34851 +       struct input_polled_dev *poll_dev;
34852 +       struct input_dev *input_dev;
34853 +       struct ubicom32input_platform_data *pdata;
34854 +       int ret;
34855 +
34856 +       pdata = pdev->dev.platform_data;
34857 +       if (!pdata) {
34858 +               return -EINVAL;
34859 +       }
34860 +
34861 +       ud = kzalloc(sizeof(struct ubicom32input_data) +
34862 +                    pdata->nbuttons, GFP_KERNEL);
34863 +       if (!ud) {
34864 +               return -ENOMEM;
34865 +       }
34866 +       ud->pdata = pdata;
34867 +
34868 +       poll_dev = input_allocate_polled_device();
34869 +       if (!poll_dev) {
34870 +               ret = -ENOMEM;
34871 +               goto fail;
34872 +       }
34873 +
34874 +       platform_set_drvdata(pdev, ud);
34875 +
34876 +       ud->poll_dev = poll_dev;
34877 +       poll_dev->private = ud;
34878 +       poll_dev->poll = ubicom32input_poll;
34879 +
34880 +       /*
34881 +        * Set the poll interval requested, default to 50 msec
34882 +        */
34883 +       if (pdata->poll_interval) {
34884 +               poll_dev->poll_interval = pdata->poll_interval;
34885 +       } else {
34886 +               poll_dev->poll_interval = 50;
34887 +       }
34888 +
34889 +       /*
34890 +        * Setup the input device
34891 +        */
34892 +       input_dev = poll_dev->input;
34893 +       input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input";
34894 +       input_dev->phys = "ubicom32input/input0";
34895 +       input_dev->dev.parent = &pdev->dev;
34896 +       input_dev->id.bustype = BUS_HOST;
34897 +
34898 +       /*
34899 +        * Reserve the GPIOs
34900 +        */
34901 +       for (i = 0; i < pdata->nbuttons; i++) {
34902 +               const struct ubicom32input_button *ub = &pdata->buttons[i];
34903 +
34904 +               ret = gpio_request(ub->gpio,
34905 +                                  ub->desc ? ub->desc : "ubicom32input");
34906 +               if (ret < 0) {
34907 +                       pr_err("ubicom32input: failed to request "
34908 +                              "GPIO %d ret=%d\n", ub->gpio, ret);
34909 +                       goto fail2;
34910 +               }
34911 +
34912 +               ret = gpio_direction_input(ub->gpio);
34913 +               if (ret < 0) {
34914 +                       pr_err("ubicom32input: failed to set "
34915 +                              "GPIO %d to input ret=%d\n", ub->gpio, ret);
34916 +                       goto fail2;
34917 +               }
34918 +
34919 +               /*
34920 +                * Set the previous state to the non-active stae
34921 +                */
34922 +               ud->prev_state[i] = ub->active_low;
34923 +
34924 +               input_set_capability(input_dev,
34925 +                                    ub->type ? ub->type : EV_KEY, ub->code);
34926 +       }
34927 +
34928 +       /*
34929 +        * Register
34930 +        */
34931 +       ret = input_register_polled_device(ud->poll_dev);
34932 +       if (ret) {
34933 +               goto fail2;
34934 +       }
34935 +
34936 +       return 0;
34937 +
34938 +fail2:
34939 +       /*
34940 +        * release the GPIOs we have already requested.
34941 +        */
34942 +       while (--i >= 0) {
34943 +               gpio_free(pdata->buttons[i].gpio);
34944 +       }
34945 +
34946 +fail:
34947 +       printk(KERN_ERR "Ubicom32Input: Failed to register driver %d", ret);
34948 +       platform_set_drvdata(pdev, NULL);
34949 +       input_free_polled_device(poll_dev);
34950 +       kfree(ud);
34951 +       return ret;
34952 +}
34953 +
34954 +/*
34955 + * ubicom32input_remove
34956 + */
34957 +static int __devexit ubicom32input_remove(struct platform_device *dev)
34958 +{
34959 +       struct ubicom32input_data *ud =
34960 +               (struct ubicom32input_data *)platform_get_drvdata(dev);
34961 +       int i;
34962 +
34963 +       /*
34964 +        * Free the GPIOs
34965 +        */
34966 +       for (i = 0; i < ud->pdata->nbuttons; i++) {
34967 +               gpio_free(ud->pdata->buttons[i].gpio);
34968 +       }
34969 +
34970 +       platform_set_drvdata(dev, NULL);
34971 +       input_unregister_polled_device(ud->poll_dev);
34972 +       input_free_polled_device(ud->poll_dev);
34973 +
34974 +       kfree(ud);
34975 +
34976 +       return 0;
34977 +}
34978 +
34979 +static struct platform_driver ubicom32input_driver = {
34980 +       .driver         = {
34981 +               .name   = "ubicom32input",
34982 +               .owner  = THIS_MODULE,
34983 +       },
34984 +       .probe          = ubicom32input_probe,
34985 +       .remove         = __devexit_p(ubicom32input_remove),
34986 +};
34987 +
34988 +/*
34989 + * ubicom32input_init
34990 + */
34991 +static int __devinit ubicom32input_init(void)
34992 +{
34993 +       return platform_driver_register(&ubicom32input_driver);
34994 +}
34995 +
34996 +/*
34997 + * ubicom32input_exit
34998 + */
34999 +static void __exit ubicom32input_exit(void)
35000 +{
35001 +       platform_driver_unregister(&ubicom32input_driver);
35002 +}
35003 +
35004 +module_init(ubicom32input_init);
35005 +module_exit(ubicom32input_exit);
35006 +
35007 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35008 +MODULE_DESCRIPTION("Ubicom32 Input Driver");
35009 +MODULE_LICENSE("GPL");
35010 +MODULE_ALIAS("platform:ubicom32-input");
35011 --- /dev/null
35012 +++ b/arch/ubicom32/mach-common/ubicom32input_i2c.c
35013 @@ -0,0 +1,325 @@
35014 +/*
35015 + * arch/ubicom32/mach-common/ubicom32input_i2c.c
35016 + *   Ubicom32 Input driver for I2C
35017 + *       Supports PCA953x and family
35018 + *
35019 + *   We hog the I2C device, turning it all to input.
35020 + *
35021 + *   Based on gpio-keys, pca953x
35022 + *
35023 + * (C) Copyright 2009, Ubicom, Inc.
35024 + *
35025 + * This file is part of the Ubicom32 Linux Kernel Port.
35026 + *
35027 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35028 + * it and/or modify it under the terms of the GNU General Public License
35029 + * as published by the Free Software Foundation, either version 2 of the
35030 + * License, or (at your option) any later version.
35031 + *
35032 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35033 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35034 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
35035 + * the GNU General Public License for more details.
35036 + *
35037 + * You should have received a copy of the GNU General Public License
35038 + * along with the Ubicom32 Linux Kernel Port.  If not,
35039 + * see <http://www.gnu.org/licenses/>.
35040 + *
35041 + * Ubicom32 implementation derived from (with many thanks):
35042 + *   arch/m68knommu
35043 + *   arch/blackfin
35044 + *   arch/parisc
35045 + */
35046 +#include <linux/kernel.h>
35047 +#include <linux/module.h>
35048 +#include <linux/platform_device.h>
35049 +#include <linux/input.h>
35050 +#include <linux/input-polldev.h>
35051 +#include <linux/i2c.h>
35052 +
35053 +#include <asm/ubicom32input_i2c.h>
35054 +
35055 +#define UBICOM32INPUT_I2C_REG_INPUT    0
35056 +#define UBICOM32INPUT_I2C_REG_OUTPUT   1
35057 +#define UBICOM32INPUT_I2C_REG_INVERT   2
35058 +#define UBICOM32INPUT_I2C_REG_DIRECTION        3
35059 +
35060 +static const struct i2c_device_id ubicom32input_i2c_id[] = {
35061 +       { "ubicom32in_pca9534", 8, },
35062 +       { "ubicom32in_pca9535", 16, },
35063 +       { "ubicom32in_pca9536", 4, },
35064 +       { "ubicom32in_pca9537", 4, },
35065 +       { "ubicom32in_pca9538", 8, },
35066 +       { "ubicom32in_pca9539", 16, },
35067 +       { "ubicom32in_pca9554", 8, },
35068 +       { "ubicom32in_pca9555", 16, },
35069 +       { "ubicom32in_pca9557", 8, },
35070 +       { "ubicom32in_max7310", 8, },
35071 +       { }
35072 +};
35073 +MODULE_DEVICE_TABLE(i2c, ubicom32input_i2c_id);
35074 +
35075 +struct ubicom32input_i2c_data {
35076 +       struct ubicom32input_i2c_platform_data  *pdata;
35077 +
35078 +       struct i2c_client                       *client;
35079 +
35080 +       struct input_polled_dev                 *poll_dev;
35081 +
35082 +       /*
35083 +        * collection of previous states for buttons
35084 +        */
35085 +       uint16_t                                prev_state;
35086 +
35087 +       uint8_t                                 ngpios;
35088 +};
35089 +
35090 +/*
35091 + * ubicom32input_i2c_write_reg
35092 + *     writes a register to the I2C device.
35093 + */
35094 +static int ubicom32input_i2c_write_reg(struct ubicom32input_i2c_data *ud,
35095 +                                      int reg, uint16_t val)
35096 +{
35097 +       int ret;
35098 +
35099 +       if (ud->ngpios <= 8) {
35100 +               ret = i2c_smbus_write_byte_data(ud->client, reg, val);
35101 +       } else {
35102 +               ret = i2c_smbus_write_word_data(ud->client, reg << 1, val);
35103 +       }
35104 +
35105 +       if (ret < 0) {
35106 +               return ret;
35107 +       }
35108 +
35109 +       return 0;
35110 +}
35111 +
35112 +/*
35113 + * ubicom32input_i2c_read_reg
35114 + *     reads a register from the I2C device.
35115 + */
35116 +static int ubicom32input_i2c_read_reg(struct ubicom32input_i2c_data *ud,
35117 +                                     int reg, uint16_t *val)
35118 +{
35119 +       int ret;
35120 +
35121 +       if (ud->ngpios <= 8) {
35122 +               ret = i2c_smbus_read_byte_data(ud->client, reg);
35123 +       } else {
35124 +               ret = i2c_smbus_read_word_data(ud->client, reg);
35125 +       }
35126 +
35127 +       if (ret < 0) {
35128 +               return ret;
35129 +       }
35130 +
35131 +       *val = (uint16_t)ret;
35132 +
35133 +       return 0;
35134 +}
35135 +
35136 +/*
35137 + * ubicom32input_i2c_poll
35138 + */
35139 +static void ubicom32input_i2c_poll(struct input_polled_dev *dev)
35140 +{
35141 +       struct ubicom32input_i2c_data *ud =
35142 +               (struct ubicom32input_i2c_data *)dev->private;
35143 +       struct ubicom32input_i2c_platform_data *pdata = ud->pdata;
35144 +       struct input_dev *id = dev->input;
35145 +       int i;
35146 +       int sync_needed = 0;
35147 +       uint16_t val;
35148 +       uint16_t change_mask;
35149 +
35150 +       /*
35151 +        * Try to get the input status, if we fail, bail out, maybe we can do it
35152 +        * next time.
35153 +        */
35154 +       if (ubicom32input_i2c_read_reg(ud, UBICOM32INPUT_I2C_REG_INPUT, &val)) {
35155 +               return;
35156 +       }
35157 +
35158 +       /*
35159 +        * see if anything changed by using XOR
35160 +        */
35161 +       change_mask = ud->prev_state ^ val;
35162 +       ud->prev_state = val;
35163 +
35164 +       for (i = 0; i < pdata->nbuttons; i++) {
35165 +               const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35166 +               uint16_t mask = 1 << ub->bit;
35167 +               int state = val & mask;
35168 +
35169 +               /*
35170 +                * Check to see if the state changed from the last time we
35171 +                * looked
35172 +                */
35173 +               if (!(change_mask & mask)) {
35174 +                       continue;
35175 +               }
35176 +               input_event(id, ub->type, ub->code, state);
35177 +               sync_needed = 1;
35178 +       }
35179 +
35180 +       if (sync_needed) {
35181 +               input_sync(id);
35182 +       }
35183 +}
35184 +
35185 +/*
35186 + * ubicom32input_i2c_probe
35187 + */
35188 +static int __devinit ubicom32input_i2c_probe(struct i2c_client *client,
35189 +                                            const struct i2c_device_id *id)
35190 +{
35191 +       int i;
35192 +       struct ubicom32input_i2c_data *ud;
35193 +       struct input_polled_dev *poll_dev;
35194 +       struct input_dev *input_dev;
35195 +       struct ubicom32input_i2c_platform_data *pdata;
35196 +       int ret;
35197 +       uint16_t invert_mask = 0;
35198 +
35199 +       pdata = client->dev.platform_data;
35200 +       if (!pdata) {
35201 +               return -EINVAL;
35202 +       }
35203 +
35204 +       ud = kzalloc(sizeof(struct ubicom32input_i2c_data), GFP_KERNEL);
35205 +       if (!ud) {
35206 +               return -ENOMEM;
35207 +       }
35208 +       ud->pdata = pdata;
35209 +       ud->client = client;
35210 +       ud->ngpios = id->driver_data;
35211 +
35212 +       poll_dev = input_allocate_polled_device();
35213 +       if (!poll_dev) {
35214 +               ret = -ENOMEM;
35215 +               goto fail;
35216 +       }
35217 +
35218 +       ud->poll_dev = poll_dev;
35219 +       poll_dev->private = ud;
35220 +       poll_dev->poll = ubicom32input_i2c_poll;
35221 +
35222 +       /*
35223 +        * Set the poll interval requested, default to 100 msec
35224 +        */
35225 +       if (pdata->poll_interval) {
35226 +               poll_dev->poll_interval = pdata->poll_interval;
35227 +       } else {
35228 +               poll_dev->poll_interval = 100;
35229 +       }
35230 +
35231 +       /*
35232 +        * Setup the input device
35233 +        */
35234 +       input_dev = poll_dev->input;
35235 +       input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input I2C";
35236 +       input_dev->phys = "ubicom32input_i2c/input0";
35237 +       input_dev->dev.parent = &client->dev;
35238 +       input_dev->id.bustype = BUS_I2C;
35239 +
35240 +       /*
35241 +        * Set the capabilities
35242 +        */
35243 +       for (i = 0; i < pdata->nbuttons; i++) {
35244 +               const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35245 +
35246 +               if (ub->active_low) {
35247 +                       invert_mask |= (1 << ub->bit);
35248 +               }
35249 +
35250 +               input_set_capability(input_dev,
35251 +                                    ub->type ? ub->type : EV_KEY, ub->code);
35252 +       }
35253 +
35254 +       /*
35255 +        * Setup the device (all inputs)
35256 +        */
35257 +       ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_DIRECTION,
35258 +                                         0xFFFF);
35259 +       if (ret < 0) {
35260 +               goto fail;
35261 +       }
35262 +
35263 +       ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_INVERT,
35264 +                                         invert_mask);
35265 +       if (ret < 0) {
35266 +               goto fail;
35267 +       }
35268 +
35269 +       /*
35270 +        * Register
35271 +        */
35272 +       ret = input_register_polled_device(ud->poll_dev);
35273 +       if (ret) {
35274 +               goto fail;
35275 +       }
35276 +
35277 +       i2c_set_clientdata(client, ud);
35278 +
35279 +       return 0;
35280 +
35281 +fail:
35282 +       printk(KERN_ERR "ubicom32input_i2c: Failed to register driver %d\n",
35283 +              ret);
35284 +       input_free_polled_device(poll_dev);
35285 +       kfree(ud);
35286 +       return ret;
35287 +}
35288 +
35289 +/*
35290 + * ubicom32input_i2c_remove
35291 + */
35292 +static int __devexit ubicom32input_i2c_remove(struct i2c_client *client)
35293 +{
35294 +       struct ubicom32input_i2c_data *ud =
35295 +               (struct ubicom32input_i2c_data *)i2c_get_clientdata(client);
35296 +
35297 +       i2c_set_clientdata(client, NULL);
35298 +       input_unregister_polled_device(ud->poll_dev);
35299 +       input_free_polled_device(ud->poll_dev);
35300 +
35301 +       kfree(ud);
35302 +
35303 +       return 0;
35304 +}
35305 +
35306 +static struct i2c_driver ubicom32input_i2c_driver = {
35307 +       .driver         = {
35308 +               .name   = "ubicom32input_i2c",
35309 +               .owner  = THIS_MODULE,
35310 +       },
35311 +       .remove         = __devexit_p(ubicom32input_i2c_remove),
35312 +       .id_table       = ubicom32input_i2c_id,
35313 +       .probe          = ubicom32input_i2c_probe,
35314 +};
35315 +
35316 +/*
35317 + * ubicom32input_i2c_init
35318 + */
35319 +static int __devinit ubicom32input_i2c_init(void)
35320 +{
35321 +       return i2c_add_driver(&ubicom32input_i2c_driver);
35322 +}
35323 +
35324 +/*
35325 + * ubicom32input_i2c_exit
35326 + */
35327 +static void __exit ubicom32input_i2c_exit(void)
35328 +{
35329 +       i2c_del_driver(&ubicom32input_i2c_driver);
35330 +}
35331 +
35332 +module_init(ubicom32input_i2c_init);
35333 +module_exit(ubicom32input_i2c_exit);
35334 +
35335 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35336 +MODULE_DESCRIPTION("Ubicom32 Input Driver I2C");
35337 +MODULE_LICENSE("GPL");
35338 +MODULE_ALIAS("platform:ubicom32-input");
35339 --- /dev/null
35340 +++ b/arch/ubicom32/mach-common/usb.c
35341 @@ -0,0 +1,132 @@
35342 +/*
35343 + * arch/ubicom32/mach-common/ip5k_usb.c
35344 + *   Ubicom32 architecture usb support.
35345 + *
35346 + * (C) Copyright 2009, Ubicom, Inc.
35347 + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
35348 + * Author: Kevin Hilman
35349 + *
35350 + * This file is part of the Ubicom32 Linux Kernel Port.
35351 + *
35352 + * The Ubicom32 Linux Kernel Port is free software: you can
35353 + * redistribute it and/or modify it under the terms of the GNU General
35354 + * Public License as published by the Free Software Foundation, either
35355 + * version 2 of the License, or (at your option) any later version.
35356 + *
35357 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35358 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35359 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
35360 + * See the GNU General Public License for more details.
35361 + *
35362 + * You should have received a copy of the GNU General Public License
35363 + * along with the Ubicom32 Linux Kernel Port.  If not,
35364 + * see <http://www.gnu.org/licenses/>.
35365 + *
35366 + * Ubicom32 implementation derived from (with many thanks):
35367 + *   arch/m68knommu
35368 + *   arch/blackfin
35369 + *   arch/parisc
35370 + */
35371 +
35372 +#include <linux/types.h>
35373 +#include <linux/errno.h>
35374 +#include <linux/delay.h>
35375 +#include <linux/platform_device.h>
35376 +#include <linux/dma-mapping.h>
35377 +#include <linux/usb/musb.h>
35378 +#include <asm/devtree.h>
35379 +#include <asm/ip5000.h>
35380 +#include "usb_tio.h"
35381 +
35382 +struct usbtionode *unode = NULL;
35383 +
35384 +static struct resource usb_resources[] = {
35385 +       [0] = {
35386 +               .start  = RJ + 0x800,
35387 +               .end    = RJ + 0x1000,
35388 +               .flags  = IORESOURCE_MEM,
35389 +       },
35390 +       [1] = { /* general IRQ */
35391 +               .start  = 1, /* this is a dummy value, the real irq number is passed from kernel_setup_param */
35392 +               .flags  = IORESOURCE_IRQ,
35393 +       },
35394 +};
35395 +
35396 +
35397 +static struct musb_hdrc_eps_bits musb_eps[] = {
35398 +       { "ep1_tx", 4, },
35399 +       { "ep1_rx", 4, },
35400 +       { "ep2_tx", 10, },
35401 +       { "ep2_rx", 10, },
35402 +       { "ep3_tx", 9, },
35403 +       { "ep3_rx", 9, },
35404 +       { "ep4_tx", 9, },
35405 +       { "ep4_rx", 9, },
35406 +       { "ep5_tx", 6, },
35407 +       { "ep5_rx", 6, },
35408 +};
35409 +
35410 +static struct musb_hdrc_config musb_config = {
35411 +       .multipoint     = true,
35412 +       .dyn_fifo       = false,
35413 +       .soft_con       = true,
35414 +       .dma            = false,
35415 +
35416 +       .num_eps        = 6,
35417 +       .dma_channels   = 0,
35418 +       .ram_bits       = 0,
35419 +       .eps_bits       = musb_eps,
35420 +};
35421 +
35422 +static struct musb_hdrc_platform_data usb_data = {
35423 +#ifdef CONFIG_USB_MUSB_OTG
35424 +       .mode           = MUSB_OTG,
35425 +#else
35426 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
35427 +       .mode           = MUSB_HOST,
35428 +#else
35429 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
35430 +       .mode           = MUSB_PERIPHERAL,
35431 +#endif
35432 +#endif
35433 +#endif
35434 +       .clock          = NULL,
35435 +       .set_clock      = NULL,
35436 +       .config         = &musb_config,
35437 +};
35438 +
35439 +static struct platform_device musb_device = {
35440 +       .name           = "musb_hdrc",
35441 +       .id             = 0,
35442 +       .dev = {
35443 +               .platform_data          = &usb_data,
35444 +               .dma_mask               = NULL,
35445 +               .coherent_dma_mask      = 0,
35446 +       },
35447 +       .resource       = usb_resources,
35448 +       .num_resources  = ARRAY_SIZE(usb_resources),
35449 +};
35450 +
35451 +struct usbtio_node *usb_node = NULL;
35452 +void ubi32_usb_init(void)
35453 +{
35454 +       /*
35455 +        * See if the usbtio is in the device tree.
35456 +        */
35457 +       usb_node = (struct usbtio_node *)devtree_find_node("usbtio");
35458 +       if (!usb_node) {
35459 +               printk(KERN_WARNING "usb init failed\n");
35460 +               return;
35461 +       }
35462 +
35463 +       usb_resources[1].start = usb_node->dn.recvirq;
35464 +       if (platform_device_register(&musb_device) < 0) {
35465 +               printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
35466 +               return;
35467 +       }
35468 +}
35469 +
35470 +void ubi32_usb_int_clr(void)
35471 +{
35472 +        UBICOM32_IO_PORT(RJ)->int_clr = (1 << 3);
35473 +}
35474 --- /dev/null
35475 +++ b/arch/ubicom32/mach-common/usb_tio.c
35476 @@ -0,0 +1,356 @@
35477 +/*
35478 + * arch/ubicom32/mach-common/usb_tio.c
35479 + *  Linux side Ubicom USB TIO driver
35480 + *
35481 + * (C) Copyright 2009, Ubicom, Inc.
35482 + *
35483 + * This file is part of the Ubicom32 Linux Kernel Port.
35484 + *
35485 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35486 + * it and/or modify it under the terms of the GNU General Public License
35487 + * as published by the Free Software Foundation, either version 2 of the
35488 + * License, or (at your option) any later version.
35489 + *
35490 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35491 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35492 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
35493 + * the GNU General Public License for more details.
35494 + *
35495 + * You should have received a copy of the GNU General Public License
35496 + * along with the Ubicom32 Linux Kernel Port.  If not,
35497 + * see <http://www.gnu.org/licenses/>.
35498 + *
35499 + * Ubicom32 implementation derived from (with many thanks):
35500 + *   arch/m68knommu
35501 + *   arch/blackfin
35502 + *   arch/parisc
35503 + */
35504 +#include <linux/module.h>
35505 +#include <linux/spinlock.h>
35506 +#include <linux/slab.h>
35507 +#include <asm/devtree.h>
35508 +#include "usb_tio.h"
35509 +
35510 +#ifdef CONFIG_SMP
35511 +static DEFINE_SPINLOCK(tio_lock);
35512 +#define USB_TIO_LOCK(lock, flag) spin_lock_irqsave(lock, flag)
35513 +#define USB_TIO_UNLOCK(lock, flag) spin_unlock_irqrestore(lock, flag)
35514 +#define USB_TIO_LOCK_ISLOCKED(lock) spin_try_lock(lock)
35515 +#else
35516 +#define USB_TIO_LOCK(lock, flag) local_irq_save(flag)
35517 +#define USB_TIO_UNLOCK(lock, flag) local_irq_restore(flag)
35518 +#endif
35519 +
35520 +spinlock_t usb_tio_lock;
35521 +
35522 +/*
35523 + * usb_tio_set_hrt_interrupt()
35524 + */
35525 +static inline void usb_tio_set_hrt_interrupt(void)
35526 +{
35527 +       ubicom32_set_interrupt(usb_node->dn.sendirq);
35528 +}
35529 +
35530 +static inline void usb_tio_wait_hrt(void)
35531 +{
35532 +       while (unlikely(usb_node->pdesc));
35533 +}
35534 +
35535 +#if defined(USB_TIO_DEBUG)
35536 +static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req)
35537 +{
35538 +       BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2);
35539 +}
35540 +
35541 +static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req)
35542 +{
35543 +       req->magic = 0;
35544 +}
35545 +#endif
35546 +
35547 +static void usb_tio_request_set_magic(volatile struct usb_tio_request *req)
35548 +{
35549 +       req->magic = USB_TIO_REQUEST_MAGIC1;
35550 +}
35551 +
35552 +/*
35553 + * usb_tio_commit_request()
35554 + */
35555 +static inline void usb_tio_commit_request(volatile struct usb_tio_request *request)
35556 +{
35557 +       wmb();
35558 +       usb_node->pdesc = request;
35559 +
35560 +       /*
35561 +        * next thing to do is alway checking if (usb_node->pdesc == NULL)
35562 +        * to see if the request is done, so add a mb() here
35563 +        */
35564 +       mb();
35565 +       usb_tio_set_hrt_interrupt();
35566 +}
35567 +
35568 +/*
35569 + * usb_tio_read_u16()
35570 + *     Synchronously read 16 bits.
35571 + */
35572 +u8_t usb_tio_read_u16(u32_t address, u16_t *data)
35573 +{
35574 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35575 +       unsigned long flag;
35576 +
35577 +       /*
35578 +        * Wait for any previous request to complete and then make this request.
35579 +        */
35580 +       USB_TIO_LOCK(&tio_lock, flag);
35581 +       usb_tio_wait_hrt();
35582 +
35583 +       /*
35584 +        * Fill in the request.
35585 +        */
35586 +       tio_req->address = address;
35587 +       tio_req->cmd = USB_TIO_READ16_SYNC;
35588 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35589 +       usb_tio_commit_request(tio_req);
35590 +
35591 +       /*
35592 +        * Wait for the result to show up.
35593 +        */
35594 +       usb_tio_wait_hrt();
35595 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35596 +       *data = (u16_t)tio_req->data;
35597 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35598 +       USB_TIO_UNLOCK(&tio_lock, flag);
35599 +       return USB_TIO_OK;
35600 +}
35601 +
35602 +/*
35603 + * usb_tio_read_u8()
35604 + *     Synchronously read 16 bits.
35605 + */
35606 +u8_t usb_tio_read_u8(u32_t address, u8_t *data)
35607 +{
35608 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35609 +       unsigned long flag;
35610 +
35611 +       /*
35612 +        * Wait for any previous request to complete and then make this request.
35613 +        */
35614 +       USB_TIO_LOCK(&tio_lock, flag);
35615 +       usb_tio_wait_hrt();
35616 +
35617 +       /*
35618 +        * Fill in the request.
35619 +        */
35620 +       tio_req->address = address;
35621 +       tio_req->cmd = USB_TIO_READ8_SYNC;
35622 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35623 +
35624 +       /*
35625 +        * commit the request
35626 +        */
35627 +       usb_tio_commit_request(tio_req);
35628 +
35629 +       /*
35630 +        * Wait for the result to show up.
35631 +        */
35632 +       usb_tio_wait_hrt();
35633 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35634 +       *data = (u8_t)tio_req->data;
35635 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35636 +       USB_TIO_UNLOCK(&tio_lock, flag);
35637 +       return USB_TIO_OK;
35638 +}
35639 +
35640 +/*
35641 + * usb_tio_write_u16()
35642 + *     Asynchronously  write 16 bits.
35643 + */
35644 +u8_t usb_tio_write_u16(u32_t address, u16_t data)
35645 +{
35646 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35647 +       unsigned long flag;
35648 +
35649 +       /*
35650 +        * Wait for any previous write or pending read to complete.
35651 +        */
35652 +       USB_TIO_LOCK(&tio_lock, flag);
35653 +       usb_tio_wait_hrt();
35654 +
35655 +       tio_req->address = address;
35656 +       tio_req->data = data;
35657 +       tio_req->cmd = USB_TIO_WRITE16_ASYNC;
35658 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35659 +
35660 +       /*
35661 +        * commit the request
35662 +        */
35663 +       usb_tio_commit_request(tio_req);
35664 +       USB_TIO_UNLOCK(&tio_lock, flag);
35665 +       return USB_TIO_OK;
35666 +}
35667 +
35668 +/*
35669 + * usb_tio_write_u8()
35670 + *     Asynchronously  write 8 bits.
35671 + */
35672 +u8_t usb_tio_write_u8(u32_t address, u8_t data)
35673 +{
35674 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35675 +       unsigned long flag;
35676 +
35677 +       /*
35678 +        * Wait for any previous write or pending read to complete.
35679 +        */
35680 +       USB_TIO_LOCK(&tio_lock, flag);
35681 +       usb_tio_wait_hrt();
35682 +
35683 +       tio_req->address = address;
35684 +       tio_req->data = data;
35685 +       tio_req->cmd = USB_TIO_WRITE8_ASYNC;
35686 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35687 +
35688 +       /*
35689 +        * commit the request
35690 +        */
35691 +       usb_tio_commit_request(tio_req);
35692 +       USB_TIO_UNLOCK(&tio_lock, flag);
35693 +       return USB_TIO_OK;
35694 +}
35695 +
35696 +/*
35697 + * usb_tio_read_fifo()
35698 + *     Synchronously read FIFO.
35699 + */
35700 +u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes)
35701 +{
35702 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35703 +       unsigned long flag;
35704 +
35705 +       /*
35706 +        * Wait for any previous request to complete and then make this request.
35707 +        */
35708 +       USB_TIO_LOCK(&tio_lock, flag);
35709 +       usb_tio_wait_hrt();
35710 +
35711 +       /*
35712 +        * Fill in the request.
35713 +        */
35714 +       tio_req->address = address;
35715 +       tio_req->cmd = USB_TIO_READ_FIFO_SYNC;
35716 +       tio_req->buffer = buffer;
35717 +       tio_req->transfer_length = bytes;
35718 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35719 +
35720 +       /*
35721 +        * commit the request
35722 +        */
35723 +       usb_tio_commit_request(tio_req);
35724 +
35725 +        /*
35726 +        * Wait for the result to show up.
35727 +        */
35728 +       usb_tio_wait_hrt();
35729 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35730 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35731 +       USB_TIO_UNLOCK(&tio_lock, flag);
35732 +       return USB_TIO_OK;
35733 +}
35734 +
35735 +/*
35736 + * usb_tio_write_fifo()
35737 + *     Synchronously  write 32 bits.
35738 + */
35739 +u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes)
35740 +{
35741 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35742 +       unsigned long flag;
35743 +
35744 +       USB_TIO_LOCK(&tio_lock, flag);
35745 +       usb_tio_wait_hrt();
35746 +
35747 +       tio_req->address = address;
35748 +       tio_req->buffer = buffer;
35749 +       tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
35750 +       tio_req->transfer_length = bytes;
35751 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35752 +       /*
35753 +        * commit the request
35754 +        */
35755 +       usb_tio_commit_request(tio_req);
35756 +
35757 +       /*
35758 +        * Wait for the result to show up.
35759 +        */
35760 +       usb_tio_wait_hrt();
35761 +       USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35762 +       USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35763 +       USB_TIO_UNLOCK(&tio_lock, flag);
35764 +       return USB_TIO_OK;
35765 +}
35766 +
35767 +/*
35768 + * usb_tio_write_fifo_async()
35769 + *     Asynchronously write 32 bits.
35770 + */
35771 +u8_t usb_tio_write_fifo_async(u32_t address, u32_t buffer, u32_t bytes)
35772 +{
35773 +       volatile struct usb_tio_request *tio_req = &usb_node->request;
35774 +       unsigned long flag;
35775 +
35776 +       USB_TIO_LOCK(&tio_lock, flag);
35777 +       usb_tio_wait_hrt();
35778 +
35779 +       tio_req->address = address;
35780 +
35781 +       /*
35782 +        * Is it necessary to make a local copy of the buffer? Any chance the URB is aborted before TIO finished the FIFO write?
35783 +        */
35784 +       tio_req->buffer = buffer;
35785 +       tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
35786 +       tio_req->transfer_length = bytes;
35787 +       USB_TIO_REQUEST_SET_MAGIC(tio_req);
35788 +       /*
35789 +        * commit the request
35790 +        */
35791 +       usb_tio_commit_request(tio_req);
35792 +       USB_TIO_UNLOCK(&tio_lock, flag);
35793 +       return USB_TIO_OK;
35794 +}
35795 +
35796 +/*
35797 + * usb_tio_read_int_status()
35798 + *     read and clear the interrupt status registers
35799 + */
35800 +void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
35801 +{
35802 +
35803 +       /*
35804 +        * clear the interrupt must be syncronized with the TIO thread to prevent the racing condiiton
35805 +        * that TIO thread try to set it at same time
35806 +        */
35807 +       asm volatile (
35808 +       "1:     bset (%0), (%0), #0     \n\t" \
35809 +       "       jmpne.f 1b              \n\t" \
35810 +               :
35811 +               : "a" (&usb_node->usb_vp_control)
35812 +               : "memory", "cc"
35813 +       );
35814 +
35815 +       *int_usb = usb_node->usb_vp_hw_int_usb;
35816 +       *int_tx  = cpu_to_le16(usb_node->usb_vp_hw_int_tx);
35817 +       *int_rx  = cpu_to_le16(usb_node->usb_vp_hw_int_rx);
35818 +
35819 +       //printk(KERN_INFO "int read %x, %x, %x\n", *int_usb, *int_tx, *int_rx);
35820 +
35821 +       /*
35822 +        * The interrupt status register is read-clean, so clear it now
35823 +        */
35824 +       usb_node->usb_vp_hw_int_usb = 0;
35825 +       usb_node->usb_vp_hw_int_tx = 0;
35826 +       usb_node->usb_vp_hw_int_rx = 0;
35827 +
35828 +       /*
35829 +        * release the lock bit
35830 +        */
35831 +       usb_node->usb_vp_control &= 0xfffe;
35832 +}
35833 --- /dev/null
35834 +++ b/arch/ubicom32/mach-common/usb_tio.h
35835 @@ -0,0 +1,111 @@
35836 +/*
35837 + * arch/ubicom32/mach-common/usb_tio.h
35838 + *   Definitions for usb_tio.c
35839 + *
35840 + * (C) Copyright 2009, Ubicom, Inc.
35841 + *
35842 + * This file is part of the Ubicom32 Linux Kernel Port.
35843 + *
35844 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35845 + * it and/or modify it under the terms of the GNU General Public License
35846 + * as published by the Free Software Foundation, either version 2 of the
35847 + * License, or (at your option) any later version.
35848 + *
35849 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35850 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35851 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
35852 + * the GNU General Public License for more details.
35853 + *
35854 + * You should have received a copy of the GNU General Public License
35855 + * along with the Ubicom32 Linux Kernel Port.  If not,
35856 + * see <http://www.gnu.org/licenses/>.
35857 + *
35858 + * Ubicom32 implementation derived from (with many thanks):
35859 + *   arch/m68knommu
35860 + *   arch/blackfin
35861 + *   arch/parisc
35862 + */
35863 +
35864 +#include <linux/version.h>
35865 +#include <linux/kernel.h>
35866 +#include <linux/types.h>
35867 +#include <linux/errno.h>
35868 +#include <linux/err.h>
35869 +#include <asm/devtree.h>
35870 +#include <asm/ip5000.h>
35871 +
35872 +#ifndef _USB_TIO_H
35873 +#define _USB_TIO_H
35874 +
35875 +#undef  USB_TIO_DEBUG
35876 +
35877 +#define USB_TIO_REQUEST_MAGIC1 0x2307
35878 +#define USB_TIO_REQUEST_MAGIC2 0x0789
35879 +#if defined(USB_TIO_DEBUG)
35880 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req)      usb_tio_request_verify_magic(req)
35881 +#define USB_TIO_REQUEST_SET_MAGIC(req)          usb_tio_request_set_magic(req)
35882 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req)       usb_tio_request_clear_magic(req)
35883 +#else
35884 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req)
35885 +#define USB_TIO_REQUEST_SET_MAGIC(req)          usb_tio_request_set_magic(req)
35886 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req)
35887 +#endif
35888 +
35889 +enum USB_TIO_status {
35890 +       USB_TIO_OK,
35891 +       USB_TIO_ERROR,
35892 +       USB_TIO_ERROR_COMMIT,
35893 +};
35894 +
35895 +enum USB_TIO_cmds {
35896 +       USB_TIO_READ16_SYNC,
35897 +       USB_TIO_READ8_SYNC,
35898 +       USB_TIO_READ_FIFO_SYNC,
35899 +
35900 +       USB_TIO_WRITE16_ASYNC,
35901 +       USB_TIO_WRITE8_ASYNC,
35902 +       USB_TIO_WRITE_FIFO_ASYNC,
35903 +
35904 +       USB_TIO_WRITE16_SYNC,
35905 +       USB_TIO_WRITE8_SYNC,
35906 +       USB_TIO_WRITE_FIFO_SYNC,
35907 +
35908 +};
35909 +
35910 +enum USB_TIO_state {
35911 +       USB_TIO_NORMAL,
35912 +       USB_TIO_DMA_SETUP,
35913 +};
35914 +
35915 +struct usb_tio_request {
35916 +       volatile u32_t address;
35917 +       union {
35918 +               volatile u32_t data;
35919 +               volatile u32_t buffer;
35920 +       };
35921 +       volatile u16_t cmd;
35922 +       const volatile u16_t status;
35923 +       volatile u32_t transfer_length;
35924 +       volatile u32_t thread_mask;
35925 +       volatile u16_t magic;
35926 +};
35927 +
35928 +struct usbtio_node {
35929 +       struct devtree_node dn;
35930 +       volatile struct usb_tio_request * volatile pdesc;
35931 +       struct usb_tio_request  request;
35932 +       volatile u32_t usb_vp_config;
35933 +       volatile u32_t usb_vp_control;
35934 +       const volatile u32_t usb_vp_status;
35935 +       volatile u16_t usb_vp_hw_int_tx;
35936 +       volatile u16_t usb_vp_hw_int_rx;
35937 +       volatile u8_t  usb_vp_hw_int_usb;
35938 +       volatile u8_t usb_vp_hw_int_mask_usb;
35939 +        volatile u16_t usb_vp_hw_int_mask_tx;
35940 +        volatile u16_t usb_vp_hw_int_mask_rx;
35941 +
35942 +};
35943 +
35944 +extern struct usbtio_node *usb_node;
35945 +extern void ubi32_usb_init(void);
35946 +#endif
35947 --- /dev/null
35948 +++ b/arch/ubicom32/mach-common/vdc_tio.c
35949 @@ -0,0 +1,111 @@
35950 +/*
35951 + * arch/ubicom32/mach-common/vdc_tio.c
35952 + *   Generic initialization for VDC
35953 + *
35954 + * (C) Copyright 2009, Ubicom, Inc.
35955 + *
35956 + * This file is part of the Ubicom32 Linux Kernel Port.
35957 + *
35958 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35959 + * it and/or modify it under the terms of the GNU General Public License
35960 + * as published by the Free Software Foundation, either version 2 of the
35961 + * License, or (at your option) any later version.
35962 + *
35963 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35964 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35965 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
35966 + * the GNU General Public License for more details.
35967 + *
35968 + * You should have received a copy of the GNU General Public License
35969 + * along with the Ubicom32 Linux Kernel Port.  If not,
35970 + * see <http://www.gnu.org/licenses/>.
35971 + *
35972 + * Ubicom32 implementation derived from (with many thanks):
35973 + *   arch/m68knommu
35974 + *   arch/blackfin
35975 + *   arch/parisc
35976 + */
35977 +
35978 +#include <linux/platform_device.h>
35979 +#include <linux/types.h>
35980 +
35981 +#include <asm/devtree.h>
35982 +#include <asm/vdc_tio.h>
35983 +
35984 +/*
35985 + * Resources that this driver uses
35986 + */
35987 +static struct resource vdc_tio_resources[] = {
35988 +       /*
35989 +        * Send IRQ
35990 +        */
35991 +       [0] = {
35992 +               /*
35993 +                * The init routine will query the devtree and fill this in
35994 +                */
35995 +               .flags  = IORESOURCE_IRQ,
35996 +       },
35997 +
35998 +       /*
35999 +        * Receive IRQ (optional)
36000 +        */
36001 +       [1] = {
36002 +               /*
36003 +                * The init routine will query the devtree and fill this in
36004 +                */
36005 +               .flags  = IORESOURCE_IRQ,
36006 +       },
36007 +
36008 +       /*
36009 +        * Memory Mapped Registers
36010 +        */
36011 +       [2] = {
36012 +               /*
36013 +                * The init routine will query the devtree and fill this in
36014 +                */
36015 +               .flags  = IORESOURCE_MEM,
36016 +       },
36017 +};
36018 +
36019 +/*
36020 + * The platform_device structure which is passed to the driver
36021 + */
36022 +static struct platform_device vdc_tio_platform_device = {
36023 +       .name           = "ubicom32fb",
36024 +       .id             = -1,
36025 +       .resource       = vdc_tio_resources,
36026 +       .num_resources  = ARRAY_SIZE(vdc_tio_resources),
36027 +};
36028 +
36029 +/*
36030 + * vdc_tio_init
36031 + *     Checks the device tree and instantiates the driver if found
36032 + */
36033 +void __init vdc_tio_init(void)
36034 +{
36035 +       /*
36036 +        * Check the device tree for the vdc_tio
36037 +        */
36038 +       struct vdc_tio_node *vdc_node =
36039 +               (struct vdc_tio_node *)devtree_find_node("vdctio");
36040 +       if (!vdc_node) {
36041 +               printk(KERN_WARNING "No vdc_tio found\n");
36042 +               return;
36043 +       }
36044 +
36045 +       /*
36046 +        * Fill in the resources and platform data from devtree information
36047 +        */
36048 +       vdc_tio_resources[0].start = vdc_node->dn.sendirq;
36049 +       vdc_tio_resources[1].start = vdc_node->dn.recvirq;
36050 +       vdc_tio_resources[2].start = (u32_t)vdc_node->regs;
36051 +       vdc_tio_resources[2].end = (u32_t)vdc_node->regs +
36052 +               sizeof(struct vdc_tio_vp_regs);
36053 +
36054 +       /*
36055 +        * Try to get the device registered
36056 +        */
36057 +       if (platform_device_register(&vdc_tio_platform_device) < 0) {
36058 +               printk(KERN_WARNING "VDC failed to register\n");
36059 +       }
36060 +}
36061 --- /dev/null
36062 +++ b/arch/ubicom32/mach-ip5k/board-ip5160dev.c
36063 @@ -0,0 +1,109 @@
36064 +/*
36065 + * arch/ubicom32/mach-ip5k/board-ip5160dev.c
36066 + *   Platform initialization for ip5160dev board.
36067 + *
36068 + * (C) Copyright 2009, Ubicom, Inc.
36069 + *
36070 + * This file is part of the Ubicom32 Linux Kernel Port.
36071 + *
36072 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36073 + * it and/or modify it under the terms of the GNU General Public License
36074 + * as published by the Free Software Foundation, either version 2 of the
36075 + * License, or (at your option) any later version.
36076 + *
36077 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36078 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36079 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36080 + * the GNU General Public License for more details.
36081 + *
36082 + * You should have received a copy of the GNU General Public License
36083 + * along with the Ubicom32 Linux Kernel Port.  If not,
36084 + * see <http://www.gnu.org/licenses/>.
36085 + *
36086 + * Ubicom32 implementation derived from (with many thanks):
36087 + *   arch/m68knommu
36088 + *   arch/blackfin
36089 + *   arch/parisc
36090 + */
36091 +#include <linux/device.h>
36092 +#include <linux/platform_device.h>
36093 +#include <linux/gpio.h>
36094 +
36095 +#include <asm/board.h>
36096 +#include <asm/machdep.h>
36097 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36098 +#include <asm/ubicom32suart.h>
36099 +#endif
36100 +
36101 +/*
36102 + * Factory Default Button on the board at PXn
36103 + * TODO: This is just a placeholder and it needs to include proper header files
36104 + */
36105 +struct ubicom32fdb_platform_data {
36106 +       int             fdb_gpio;
36107 +       bool            fdb_polarity;
36108 +};
36109 +
36110 +static struct ubicom32fdb_platform_data ip5160dev_fdb_data = {
36111 +       .fdb_gpio               = 0,
36112 +       .fdb_polarity           = true,
36113 +};
36114 +
36115 +static struct platform_device ip5160dev_fdb_device = {
36116 +       .name   = "ubicom32fdb",
36117 +       .id     = -1,
36118 +       .dev    = {
36119 +               .platform_data = &ip5160dev_fdb_data,
36120 +       },
36121 +};
36122 +
36123 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36124 +static struct resource ip5160dev_ubicom32_suart_resources[] = {
36125 +        {
36126 +               .start  = RD,
36127 +               .end    = RD,
36128 +               .flags  = IORESOURCE_MEM,
36129 +        },
36130 +        {
36131 +               .start  = PORT_OTHER_INT(RD),
36132 +               .end    = PORT_OTHER_INT(RD),
36133 +               .flags  = IORESOURCE_IRQ,
36134 +        },
36135 +        {
36136 +               .start  = 240000000,
36137 +               .end    = 240000000,
36138 +               .flags  = UBICOM32_SUART_IORESOURCE_CLOCK,
36139 +        },
36140 +};
36141 +
36142 +static struct platform_device ip5160dev_ubicom32_suart_device = {
36143 +       .name           = "ubicom32suart",
36144 +       .id             = -1,
36145 +        .num_resources  = ARRAY_SIZE(ip5160dev_ubicom32_suart_resources),
36146 +        .resource       = ip5160dev_ubicom32_suart_resources,
36147 +};
36148 +#endif
36149 +
36150 +/*
36151 + * List of all devices in our system
36152 + */
36153 +static struct platform_device *ip5160dev_devices[] __initdata = {
36154 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36155 +       &ip5160dev_ubicom32_suart_device,
36156 +#endif
36157 +       &ip5160dev_fdb_device,
36158 +};
36159 +
36160 +/*
36161 + * ip5160dev_init
36162 + *     Called to add the devices which we have on this board
36163 + */
36164 +static int __init ip5160dev_init(void)
36165 +{
36166 +       ubi_gpio_init();
36167 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36168 +       platform_add_devices(ip5160dev_devices, ARRAY_SIZE(ip5160dev_devices));
36169 +       return 0;
36170 +}
36171 +
36172 +arch_initcall(ip5160dev_init);
36173 --- /dev/null
36174 +++ b/arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36175 @@ -0,0 +1,75 @@
36176 +/*
36177 + * arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36178 + *   Platform initialization for ip5160rgw board.
36179 + *
36180 + * (C) Copyright 2009, Ubicom, Inc.
36181 + *
36182 + * This file is part of the Ubicom32 Linux Kernel Port.
36183 + *
36184 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36185 + * it and/or modify it under the terms of the GNU General Public License
36186 + * as published by the Free Software Foundation, either version 2 of the
36187 + * License, or (at your option) any later version.
36188 + *
36189 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36190 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36191 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36192 + * the GNU General Public License for more details.
36193 + *
36194 + * You should have received a copy of the GNU General Public License
36195 + * along with the Ubicom32 Linux Kernel Port.  If not,
36196 + * see <http://www.gnu.org/licenses/>.
36197 + *
36198 + * Ubicom32 implementation derived from (with many thanks):
36199 + *   arch/m68knommu
36200 + *   arch/blackfin
36201 + *   arch/parisc
36202 + */
36203 +#include <linux/device.h>
36204 +#include <linux/platform_device.h>
36205 +#include <linux/gpio.h>
36206 +#include <asm/board.h>
36207 +#include <asm/machdep.h>
36208 +
36209 +/*
36210 + * Factory Default Button on the board at PXn
36211 + * TODO: This is just a placeholder and it needs to include proper header files
36212 + */
36213 +struct ubicom32fdb_platform_data {
36214 +       int             fdb_gpio;
36215 +       bool            fdb_polarity;
36216 +};
36217 +
36218 +static struct ubicom32fdb_platform_data ip5160rgw_fdb_data = {
36219 +       .fdb_gpio               = 0,
36220 +       .fdb_polarity           = true,
36221 +};
36222 +
36223 +static struct platform_device ip5160rgw_fdb_device = {
36224 +       .name   = "ubicom32fdb",
36225 +       .id     = -1,
36226 +       .dev    = {
36227 +               .platform_data = &ip5160rgw_fdb_data,
36228 +       },
36229 +};
36230 +
36231 +/*
36232 + * List of all devices in our system
36233 + */
36234 +static struct platform_device *ip5160rgw_devices[] __initdata = {
36235 +       &ip5160rgw_fdb_device,
36236 +};
36237 +
36238 +/*
36239 + * ip5160rgw_init
36240 + *     Called to add the devices which we have on this board
36241 + */
36242 +static int __init ip5160rgw_init(void)
36243 +{
36244 +       ubi_gpio_init();
36245 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36246 +       platform_add_devices(ip5160rgw_devices, ARRAY_SIZE(ip5160rgw_devices));
36247 +       return 0;
36248 +}
36249 +
36250 +arch_initcall(ip5160rgw_init);
36251 --- /dev/null
36252 +++ b/arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36253 @@ -0,0 +1,279 @@
36254 +/*
36255 + * arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36256 + *   Platform initialization for ip5160dpf board.
36257 + *
36258 + * (C) Copyright 2009, Ubicom, Inc.
36259 + *
36260 + * This file is part of the Ubicom32 Linux Kernel Port.
36261 + *
36262 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36263 + * it and/or modify it under the terms of the GNU General Public License
36264 + * as published by the Free Software Foundation, either version 2 of the
36265 + * License, or (at your option) any later version.
36266 + *
36267 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36268 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36269 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36270 + * the GNU General Public License for more details.
36271 + *
36272 + * You should have received a copy of the GNU General Public License
36273 + * along with the Ubicom32 Linux Kernel Port.  If not,
36274 + * see <http://www.gnu.org/licenses/>.
36275 + *
36276 + * Ubicom32 implementation derived from (with many thanks):
36277 + *   arch/m68knommu
36278 + *   arch/blackfin
36279 + *   arch/parisc
36280 + */
36281 +#include <linux/device.h>
36282 +#include <linux/platform_device.h>
36283 +#include <linux/gpio.h>
36284 +#include <linux/leds.h>
36285 +
36286 +#include <linux/i2c.h>
36287 +#include <linux/i2c-gpio.h>
36288 +
36289 +#include <linux/input.h>
36290 +#include <asm/board.h>
36291 +#include <asm/machdep.h>
36292 +#include <asm/ubicom32hid.h>
36293 +#include <asm/vdc_tio.h>
36294 +
36295 +/*
36296 + * LEDs
36297 + *
36298 + * WLAN                        PD9     (Note this is shared with MISO, but we don't use it)
36299 + * WPS                 PD8
36300 + *
36301 + * TODO: check triggers, are they generic?
36302 + */
36303 +static struct gpio_led ip5170dpf_gpio_leds[] = {
36304 +       {
36305 +               .name                   = "d31:green:WLAN1",
36306 +               .default_trigger        = "WLAN1",
36307 +               .gpio                   = GPIO_RD_9,
36308 +               .active_low             = 1,
36309 +       },
36310 +       {
36311 +               .name                   = "d30:green:WPS",
36312 +               .default_trigger        = "WPS",
36313 +               .gpio                   = GPIO_RD_8,
36314 +               .active_low             = 1,
36315 +       },
36316 +};
36317 +
36318 +static struct gpio_led_platform_data ip5170dpf_gpio_led_platform_data = {
36319 +       .num_leds       = 2,
36320 +       .leds           = ip5170dpf_gpio_leds,
36321 +};
36322 +
36323 +static struct platform_device ip5170dpf_gpio_leds_device = {
36324 +       .name           = "leds-gpio",
36325 +       .id             = -1,
36326 +       .dev = {
36327 +               .platform_data = &ip5170dpf_gpio_led_platform_data,
36328 +       },
36329 +};
36330 +
36331 +/*
36332 + * Backlight on the board PD0, hardware PWM
36333 + */
36334 +static const struct ubicom32hid_button ip5170dpf_ubicom32hid_buttons[] = {
36335 +       {
36336 +               .type   = EV_KEY,
36337 +               .code   = KEY_UP,
36338 +               .bit    = 0,
36339 +       },
36340 +       {
36341 +               .type   = EV_KEY,
36342 +               .code   = KEY_LEFT,
36343 +               .bit    = 1,
36344 +       },
36345 +       {
36346 +               .type   = EV_KEY,
36347 +               .code   = KEY_RIGHT,
36348 +               .bit    = 2,
36349 +       },
36350 +       {
36351 +               .type   = EV_KEY,
36352 +               .code   = KEY_DOWN,
36353 +               .bit    = 3,
36354 +       },
36355 +       {
36356 +               .type   = EV_KEY,
36357 +               .code   = KEY_ENTER,
36358 +               .bit    = 4,
36359 +       },
36360 +       {
36361 +               .type   = EV_KEY,
36362 +               .code   = KEY_MENU,
36363 +               .bit    = 5,
36364 +       },
36365 +       {
36366 +               .type   = EV_KEY,
36367 +               .code   = KEY_ESC,
36368 +               .bit    = 7,
36369 +       },
36370 +};
36371 +
36372 +static const struct ubicom32hid_ir ip5170dpf_ubicom32hid_ircodes[] = {
36373 +       {
36374 +               .type           = EV_KEY,
36375 +               .code           = KEY_UP,
36376 +               .ir_code        = 0xF807916E
36377 +       },
36378 +       {
36379 +               .type           = EV_KEY,
36380 +               .code           = KEY_DOWN,
36381 +               .ir_code        = 0xF20D916E
36382 +       },
36383 +       {
36384 +               .type           = EV_KEY,
36385 +               .code           = KEY_LEFT,
36386 +               .ir_code        = 0xF609916E
36387 +       },
36388 +       {
36389 +               .type           = EV_KEY,
36390 +               .code           = KEY_RIGHT,
36391 +               .ir_code        = 0xF40B916E
36392 +       },
36393 +       {
36394 +               .type           = EV_KEY,
36395 +               .code           = KEY_ENTER,
36396 +               .ir_code        = 0xF50A916E
36397 +       },
36398 +       {       /* rotate */
36399 +               .type           = EV_KEY,
36400 +               .code           = KEY_FN_F1,
36401 +               .ir_code        = 0xF906916E
36402 +       },
36403 +       {
36404 +               .type           = EV_KEY,
36405 +               .code           = KEY_MENU,
36406 +               .ir_code        = 0xF708916E
36407 +       },
36408 +       {       /* font size */
36409 +               .type           = EV_KEY,
36410 +               .code           = KEY_FN_F2,
36411 +               .ir_code        = 0xF30C916E
36412 +       },
36413 +       {
36414 +               .type           = EV_KEY,
36415 +               .code           = KEY_ESC,
36416 +               .ir_code        = 0xF10E916E
36417 +       },
36418 +       {
36419 +               .type           = EV_KEY,
36420 +               .code           = KEY_VOLUMEUP,
36421 +               .ir_code        = 0xF00F916E
36422 +       },
36423 +       {
36424 +               .type           = EV_KEY,
36425 +               .code           = KEY_VOLUMEDOWN,
36426 +               .ir_code        = 0xED12916E
36427 +       },
36428 +       {
36429 +               .type           = EV_KEY,
36430 +               .code           = KEY_MUTE,
36431 +               .ir_code        = 0xEA15916E
36432 +       },
36433 +       {
36434 +               .type           = EV_KEY,
36435 +               .code           = KEY_INFO,
36436 +               .ir_code        = 0xEF10916E
36437 +       },
36438 +       {       /* Like */
36439 +               .type           = EV_KEY,
36440 +               .code           = KEY_FN_F3,
36441 +               .ir_code        = 0xEE11916E
36442 +       },
36443 +       {       /* Dislike */
36444 +               .type           = EV_KEY,
36445 +               .code           = KEY_FN_F4,
36446 +               .ir_code        = 0xEB14916E
36447 +       },
36448 +       {
36449 +               .type           = EV_KEY,
36450 +               .code           = KEY_POWER,
36451 +               .ir_code        = 0xFD02916E
36452 +       },
36453 +};
36454 +
36455 +static struct ubicom32hid_platform_data ip5170dpf_ubicom32hid_platform_data = {
36456 +       .gpio_reset             = GPIO_RA_4,
36457 +       .gpio_reset_polarity    = 0,
36458 +       .type                   = UBICOM32HID_BL_TYPE_BINARY,
36459 +       .invert                 = 0,
36460 +       .default_intensity      = 1,
36461 +       .buttons                = ip5170dpf_ubicom32hid_buttons,
36462 +       .nbuttons               = ARRAY_SIZE(ip5170dpf_ubicom32hid_buttons),
36463 +       .ircodes                = ip5170dpf_ubicom32hid_ircodes,
36464 +       .nircodes               = ARRAY_SIZE(ip5170dpf_ubicom32hid_ircodes),
36465 +};
36466 +
36467 +/*
36468 + * Devices on the I2C bus
36469 + */
36470 +static struct i2c_board_info __initdata ip5170dpf_i2c_board_info[] = {
36471 +       /*
36472 +        * U24, ubicom32hid
36473 +        */
36474 +       {
36475 +               .type           = "ubicom32hid",
36476 +               .addr           = 0x08,
36477 +               .platform_data  = &ip5170dpf_ubicom32hid_platform_data,
36478 +       },
36479 +
36480 +       /*
36481 +        * U14, CS4350 DAC, address 0x4B
36482 +        */
36483 +};
36484 +
36485 +/*
36486 + * I2C bus on the board, SDA PF13, SCL PF14
36487 + */
36488 +static struct i2c_gpio_platform_data ip5170dpf_i2c_data = {
36489 +       .sda_pin                = GPIO_RF_13,
36490 +       .scl_pin                = GPIO_RF_14,
36491 +       .sda_is_open_drain      = 0,
36492 +       .scl_is_open_drain      = 0,
36493 +       .scl_is_output_only     = 1,
36494 +       .udelay                 = 5,
36495 +};
36496 +
36497 +static struct platform_device ip5170dpf_i2c_device = {
36498 +       .name   = "i2c-gpio",
36499 +       .id     = 0,
36500 +       .dev    = {
36501 +               .platform_data = &ip5170dpf_i2c_data,
36502 +       },
36503 +};
36504 +
36505 +/*
36506 + * List of all devices in our system
36507 + */
36508 +static struct platform_device *ip5170dpf_devices[] __initdata = {
36509 +       &ip5170dpf_i2c_device,
36510 +       &ip5170dpf_gpio_leds_device,
36511 +};
36512 +
36513 +/*
36514 + * ip5170dpf_init
36515 + *     Called to add the devices which we have on this board
36516 + */
36517 +static int __init ip5170dpf_init(void)
36518 +{
36519 +       ubi_gpio_init();
36520 +
36521 +       vdc_tio_init();
36522 +
36523 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36524 +       platform_add_devices(ip5170dpf_devices, ARRAY_SIZE(ip5170dpf_devices));
36525 +
36526 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
36527 +       i2c_register_board_info(0, ip5170dpf_i2c_board_info, ARRAY_SIZE(ip5170dpf_i2c_board_info));
36528 +
36529 +       return 0;
36530 +}
36531 +
36532 +arch_initcall(ip5170dpf_init);
36533 --- /dev/null
36534 +++ b/arch/ubicom32/mach-ip5k/Kconfig
36535 @@ -0,0 +1,28 @@
36536 +
36537 +config IP5170DPF
36538 +       bool "IP5170DPF"
36539 +       select UBICOM32_V3
36540 +       select I2C
36541 +       select I2C_GPIO
36542 +       select FB
36543 +       select FB_UBICOM32
36544 +       select BACKLIGHT_LCD_SUPPORT
36545 +       select BACKLIGHT_CLASS_DEVICE
36546 +       select UBICOM_HID
36547 +       select NEW_LEDS
36548 +       select LEDS_CLASS
36549 +       select LEDS_GPIO
36550 +       help
36551 +               IP5170 Digital Picture Frame board, 8005-1113, IP5K-BEV-0011-13 v1.3
36552 +
36553 +config IP5160DEV
36554 +       bool "IP5160Dev_Ver1Dot1"
36555 +       select UBICOM32_V3
36556 +       help
36557 +               Ubicom StreamEngine 5000 Development Board, IP5K-BDV-0004-11 v1.1
36558 +
36559 +config IP5160EVAL
36560 +       bool "IP5160RGWEval_Ver2Rev2"
36561 +       select UBICOM32_V3
36562 +       help
36563 +               Ubicom StreamEngine 5000 RGW Evaluation Board, IP5K-RGW-0004-11 v2.2
36564 --- /dev/null
36565 +++ b/arch/ubicom32/mach-ip5k/Makefile
36566 @@ -0,0 +1,31 @@
36567 +#
36568 +# arch/ubicom32/mach-ip5k/Makefile
36569 +#      Makefile for boards which have an ip5k on them.
36570 +#
36571 +# (C) Copyright 2009, Ubicom, Inc.
36572 +#
36573 +# This file is part of the Ubicom32 Linux Kernel Port.
36574 +#
36575 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
36576 +# it and/or modify it under the terms of the GNU General Public License
36577 +# as published by the Free Software Foundation, either version 2 of the
36578 +# License, or (at your option) any later version.
36579 +#
36580 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
36581 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
36582 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36583 +# the GNU General Public License for more details.
36584 +#
36585 +# You should have received a copy of the GNU General Public License
36586 +# along with the Ubicom32 Linux Kernel Port.  If not,
36587 +# see <http://www.gnu.org/licenses/>.
36588 +#
36589 +# Ubicom32 implementation derived from (with many thanks):
36590 +#   arch/m68knommu
36591 +#   arch/blackfin
36592 +#   arch/parisc
36593 +#
36594 +
36595 +obj-$(CONFIG_IP5170DPF)                += board-ip5170dpf.o
36596 +obj-$(CONFIG_IP5160DEV)                += board-ip5160dev.o
36597 +obj-$(CONFIG_IP5160EVAL)       += board-ip5160rgw.o
36598 --- /dev/null
36599 +++ b/arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36600 @@ -0,0 +1,715 @@
36601 +/*
36602 + * arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36603 + *   Board file for IP7145DPF, rev 1.0, P/N 8007-0410
36604 + *
36605 + * (C) Copyright 2009, Ubicom, Inc.
36606 + *
36607 + * This file is part of the Ubicom32 Linux Kernel Port.
36608 + *
36609 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36610 + * it and/or modify it under the terms of the GNU General Public License
36611 + * as published by the Free Software Foundation, either version 2 of the
36612 + * License, or (at your option) any later version.
36613 + *
36614 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36615 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36616 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
36617 + * the GNU General Public License for more details.
36618 + *
36619 + * You should have received a copy of the GNU General Public License
36620 + * along with the Ubicom32 Linux Kernel Port.  If not,
36621 + * see <http://www.gnu.org/licenses/>.
36622 + *
36623 + * Ubicom32 implementation derived from (with many thanks):
36624 + *   arch/m68knommu
36625 + *   arch/blackfin
36626 + *   arch/parisc
36627 + */
36628 +#include <linux/device.h>
36629 +#include <linux/platform_device.h>
36630 +#include <linux/gpio.h>
36631 +
36632 +#include <linux/input.h>
36633 +
36634 +#include <linux/i2c.h>
36635 +#include <linux/i2c-gpio.h>
36636 +#include <linux/i2c/pca953x.h>
36637 +
36638 +#include <asm/board.h>
36639 +#include <asm/machdep.h>
36640 +#include <asm/ubicom32input.h>
36641 +#include <asm/ubicom32input_i2c.h>
36642 +#include <asm/ubicom32bl.h>
36643 +#include <asm/ubicom32lcdpower.h>
36644 +#include <asm/vdc_tio.h>
36645 +
36646 +#include <asm/ubicom32sd.h>
36647 +#include <asm/sd_tio.h>
36648 +#include <asm/devtree.h>
36649 +#include <asm/audio.h>
36650 +
36651 +#include <asm/ring_tio.h>
36652 +
36653 +/******************************************************************************
36654 + * SD/IO Port F (Slot 1) platform data
36655 + */
36656 +static struct resource ip7145dpf_portf_sd_resources[] = {
36657 +       /*
36658 +        * Send IRQ
36659 +        */
36660 +       [0] = {
36661 +               /*
36662 +                * The init routine will query the devtree and fill this in
36663 +                */
36664 +               .flags  = IORESOURCE_IRQ,
36665 +       },
36666 +
36667 +       /*
36668 +        * Receive IRQ
36669 +        */
36670 +       [1] = {
36671 +               /*
36672 +                * The init routine will query the devtree and fill this in
36673 +                */
36674 +               .flags  = IORESOURCE_IRQ,
36675 +       },
36676 +
36677 +       /*
36678 +        * Memory Mapped Registers
36679 +        */
36680 +       [2] = {
36681 +               /*
36682 +                * The init routine will query the devtree and fill this in
36683 +                */
36684 +               .flags  = IORESOURCE_MEM,
36685 +       },
36686 +};
36687 +
36688 +static struct ubicom32sd_card ip7145dpf_portf_sd_cards[] = {
36689 +       [0] = {
36690 +               .pin_wp         = IP7145DPF_IOB0,
36691 +               .wp_polarity    = 1,
36692 +               .pin_pwr        = IP7145DPF_IOB4,
36693 +               .pin_cd         = GPIO_RA_4,
36694 +       },
36695 +       [1] = {
36696 +               .pin_wp         = IP7145DPF_IOB1,
36697 +               .wp_polarity    = 1,
36698 +               .pin_pwr        = IP7145DPF_IOB5,
36699 +               .pin_cd         = GPIO_RA_6,
36700 +       },
36701 +};
36702 +
36703 +static struct ubicom32sd_platform_data ip7145dpf_portf_sd_platform_data = {
36704 +       .ncards         = 2,
36705 +       .cards          = ip7145dpf_portf_sd_cards,
36706 +};
36707 +
36708 +static struct platform_device ip7145dpf_portf_sd_device = {
36709 +       .name           = "ubicom32sd",
36710 +       .id             = 0,
36711 +       .resource       = ip7145dpf_portf_sd_resources,
36712 +       .num_resources  = ARRAY_SIZE(ip7145dpf_portf_sd_resources),
36713 +       .dev            = {
36714 +                       .platform_data = &ip7145dpf_portf_sd_platform_data,
36715 +       },
36716 +
36717 +};
36718 +
36719 +/*
36720 + * ip7145dpf_portf_sd_init
36721 + */
36722 +static void ip7145dpf_portf_sd_init(void)
36723 +{
36724 +       /*
36725 +        * Check the device tree for the sd_tio
36726 +        */
36727 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
36728 +       if (!sd_node) {
36729 +               printk(KERN_INFO "PortF SDTIO not found\n");
36730 +               return;
36731 +       }
36732 +
36733 +       /*
36734 +        * Fill in the resources and platform data from devtree information
36735 +        */
36736 +       ip7145dpf_portf_sd_resources[0].start = sd_node->dn.sendirq;
36737 +       ip7145dpf_portf_sd_resources[1].start = sd_node->dn.recvirq;
36738 +       ip7145dpf_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
36739 +       ip7145dpf_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
36740 +
36741 +       platform_device_register(&ip7145dpf_portf_sd_device);
36742 +}
36743 +
36744 +/******************************************************************************
36745 + * SD/IO Port B (Slot 2) platform data
36746 + */
36747 +static struct resource ip7145dpf_portb_sd_resources[] = {
36748 +       /*
36749 +        * Send IRQ
36750 +        */
36751 +       [0] = {
36752 +               /*
36753 +                * The init routine will query the devtree and fill this in
36754 +                */
36755 +               .flags  = IORESOURCE_IRQ,
36756 +       },
36757 +
36758 +       /*
36759 +        * Receive IRQ
36760 +        */
36761 +       [1] = {
36762 +               /*
36763 +                * The init routine will query the devtree and fill this in
36764 +                */
36765 +               .flags  = IORESOURCE_IRQ,
36766 +       },
36767 +
36768 +       /*
36769 +        * Memory Mapped Registers
36770 +        */
36771 +       [2] = {
36772 +               /*
36773 +                * The init routine will query the devtree and fill this in
36774 +                */
36775 +               .flags  = IORESOURCE_MEM,
36776 +       },
36777 +};
36778 +
36779 +static struct ubicom32sd_card ip7145dpf_portb_sd_cards[] = {
36780 +       [0] = {
36781 +               .pin_wp         = IP7145DPF_IOB2,
36782 +               .wp_polarity    = 1,
36783 +               .pin_pwr        = IP7145DPF_IOB6,
36784 +               .pin_cd         = IP7145DPF_IOB3,
36785 +       },
36786 +};
36787 +
36788 +static struct ubicom32sd_platform_data ip7145dpf_portb_sd_platform_data = {
36789 +       .ncards         = 1,
36790 +       .cards          = ip7145dpf_portb_sd_cards,
36791 +};
36792 +
36793 +static struct platform_device ip7145dpf_portb_sd_device = {
36794 +       .name           = "ubicom32sd",
36795 +       .id             = 1,
36796 +       .resource       = ip7145dpf_portb_sd_resources,
36797 +       .num_resources  = ARRAY_SIZE(ip7145dpf_portb_sd_resources),
36798 +       .dev            = {
36799 +                       .platform_data = &ip7145dpf_portb_sd_platform_data,
36800 +       },
36801 +
36802 +};
36803 +
36804 +/*
36805 + * ip7145dpf_portb_sd_init
36806 + */
36807 +static void ip7145dpf_portb_sd_init(void)
36808 +{
36809 +       /*
36810 +        * Check the device tree for the sd_tio
36811 +        */
36812 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
36813 +       if (!sd_node) {
36814 +               printk(KERN_INFO "PortB SDTIO not found\n");
36815 +               return;
36816 +       }
36817 +
36818 +       /*
36819 +        * Fill in the resources and platform data from devtree information
36820 +        */
36821 +       ip7145dpf_portb_sd_resources[0].start = sd_node->dn.sendirq;
36822 +       ip7145dpf_portb_sd_resources[1].start = sd_node->dn.recvirq;
36823 +       ip7145dpf_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
36824 +       ip7145dpf_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
36825 +
36826 +       platform_device_register(&ip7145dpf_portb_sd_device);
36827 +}
36828 +
36829 +
36830 +#ifdef IP7145DPF_USE_MMC_SPI
36831 +/******************************************************************************
36832 + * SPI over GPIO (MMC_SPI)
36833 + */
36834 +#include <linux/spi/spi.h>
36835 +#include <linux/spi/mmc_spi.h>
36836 +#include <linux/mmc/host.h>
36837 +#include <asm/ubicom32-spi-gpio.h>
36838 +
36839 +#define MMC_CS GPIO_RF_5       // PF5 D3
36840 +#define MMC_CD GPIO_RA_4       // PA4 CD
36841 +#define MMC_WP IP7145DPF_IOB0  // IOB0 WP
36842 +#define MMC_PWR        IP7145DPF_IOB4  // IOB4 PWR
36843 +
36844 +/*
36845 + * SPI bus over GPIO (for SD card)
36846 + */
36847 +static struct ubicom32_spi_gpio_platform_data ip7145dpf_spi_gpio_data = {
36848 +       .pin_mosi       = GPIO_RF_0,    // PF0 CMD
36849 +       .pin_miso       = GPIO_RF_2,    // PF2 D0
36850 +       .pin_clk        = GPIO_RF_1,    // PF1 CLK
36851 +       .bus_num        = 0,            // We'll call this SPI bus 0
36852 +       .num_chipselect = 1,            // only one device on this SPI bus
36853 +};
36854 +
36855 +static struct platform_device ip7145dpf_spi_gpio_device = {
36856 +       .name   = "ubicom32-spi-gpio",
36857 +       .id     = 0,
36858 +       .dev    = {
36859 +               .platform_data = &ip7145dpf_spi_gpio_data,
36860 +       },
36861 +};
36862 +
36863 +/*
36864 + * ip7145dpf_mmc_spi_setpower_slot_a
36865 + *     Set the power state for slot A
36866 + */
36867 +static void ip7145dpf_mmc_spi_setpower_slot_a(struct device *dev, unsigned int vdd)
36868 +{
36869 +       struct mmc_spi_platform_data *pd = dev->platform_data;
36870 +
36871 +       /*
36872 +        * Power is inverted, we could tell the IOB to do it, but it's cleaner this way.
36873 +        */
36874 +       if ((1 << vdd) & pd->ocr_mask) {
36875 +               gpio_set_value(MMC_PWR, 0);
36876 +               return;
36877 +       }
36878 +       gpio_set_value(MMC_PWR, 1);
36879 +}
36880 +
36881 +/*
36882 + * ip7145dpf_mmc_spi_get_cd_slot_a
36883 + *     Get the CD bit for slot A
36884 + */
36885 +static int ip7145dpf_mmc_spi_get_cd_slot_a(struct device *dev)
36886 +{
36887 +       /*
36888 +        * Note that the sense of the GPIO is inverted
36889 +        */
36890 +       return !gpio_get_value(MMC_CD);
36891 +}
36892 +
36893 +/*
36894 + * ip7145dpf_mmc_spi_get_ro_slot_a
36895 + *     Get the WP bit for slot A
36896 + */
36897 +static int ip7145dpf_mmc_spi_get_ro_slot_a(struct device *dev)
36898 +{
36899 +       /*
36900 +        * Note that the sense of the GPIO is inverted, we could tell the IOB to do it, but
36901 +        * it's clearer this way.
36902 +        */
36903 +       return !gpio_get_value(MMC_WP);
36904 +}
36905 +
36906 +/*
36907 + * ip7145dpf_mmc_spi_exit_slot_a
36908 + *     Free the appropriate GPIOs for slot A SD slot.
36909 + */
36910 +static void ip7145dpf_mmc_spi_exit_slot_a(struct device *dev, void *appdata)
36911 +{
36912 +       gpio_free(MMC_CD);
36913 +       gpio_free(MMC_CS);
36914 +       gpio_free(MMC_WP);
36915 +       gpio_free(MMC_PWR);
36916 +       platform_device_unregister(&ip7145dpf_spi_gpio_device);
36917 +}
36918 +
36919 +/*
36920 + * ip7145dpf_mmc_spi_init_slot_a
36921 + *     Allocate the appropriate GPIOs for slot A SD slot.
36922 + *     WP is on IOB0, CD is PA4, CS is on PF5
36923 + *     TODO: make CD an interrupt
36924 + */
36925 +static int ip7145dpf_mmc_spi_init_slot_a(void)
36926 +{
36927 +       int ret = gpio_request(MMC_CD, "mmc-a-cd");
36928 +       if (ret) {
36929 +               printk(KERN_ERR "%s: could not request mmc-a-cd pin\n", __FUNCTION__);
36930 +               return -ENOSYS;
36931 +       }
36932 +       gpio_direction_input(MMC_CD);
36933 +
36934 +       ret = gpio_request(MMC_CS, "mmc-a-cs");
36935 +       if (ret) {
36936 +               printk(KERN_ERR "%s: could not request mmc-a-cs pin\n", __FUNCTION__);
36937 +               goto no_cs;
36938 +       }
36939 +       gpio_direction_output(MMC_CS, 0);
36940 +
36941 +       ret = gpio_request(MMC_WP, "mmc-a-wp");
36942 +       if (ret) {
36943 +               printk(KERN_ERR "%s: could not request mmc-a-wp pin\n", __FUNCTION__);
36944 +               goto no_wp;
36945 +       }
36946 +       gpio_direction_input(MMC_WP);
36947 +
36948 +       /*
36949 +        * Start off with power off
36950 +        */
36951 +       ret = gpio_request(MMC_PWR, "mmc-a-pwr");
36952 +       if (ret) {
36953 +               printk(KERN_ERR "%s: could not request mmc-a-pwr pin\n", __FUNCTION__);
36954 +               goto no_pwr;
36955 +       }
36956 +       ret = gpio_direction_output(MMC_PWR, 1);
36957 +
36958 +       return 0;
36959 +
36960 +no_pwr:
36961 +       gpio_free(MMC_WP);
36962 +
36963 +no_wp:
36964 +       gpio_free(MMC_CS);
36965 +
36966 +no_cs:
36967 +       gpio_free(MMC_CD);
36968 +       return -ENOSYS;
36969 +}
36970 +
36971 +/*
36972 + * MMC_SPI driver (currently bitbang)
36973 + */
36974 +static struct mmc_spi_platform_data ip7145dpf_mmc_platform_data = {
36975 +       .ocr_mask       = MMC_VDD_33_34,
36976 +       .exit           = ip7145dpf_mmc_spi_exit_slot_a,
36977 +       .get_ro         = ip7145dpf_mmc_spi_get_ro_slot_a,
36978 +       .get_cd         = ip7145dpf_mmc_spi_get_cd_slot_a,
36979 +
36980 +       .setpower       = ip7145dpf_mmc_spi_setpower_slot_a,
36981 +       .powerup_msecs  = 500,
36982 +
36983 +       .detect_delay   = 100,
36984 +
36985 +       .caps           = MMC_CAP_NEEDS_POLL,
36986 +};
36987 +
36988 +static struct ubicom32_spi_gpio_controller_data ip7145dpf_mmc_controller_data = {
36989 +       .pin_cs =  MMC_CS,
36990 +};
36991 +
36992 +static struct spi_board_info ip7145dpf_spi_board_info[] = {
36993 +       {
36994 +               .modalias = "mmc_spi",
36995 +               .bus_num = 0,
36996 +               .chip_select = 0,
36997 +               .max_speed_hz = 2000000,
36998 +               .platform_data = &ip7145dpf_mmc_platform_data,
36999 +               .controller_data = &ip7145dpf_mmc_controller_data,
37000 +       }
37001 +};
37002 +#endif /* IP7145DPF_USE_MMC_SPI */
37003 +
37004 +/*
37005 + * ip7145dpf_u72_setup
37006 + *     Called by I2C to tell us that u72 is setup.
37007 + *
37008 + * This function is called by I2C to tell us that u72 has been setup.  All
37009 + * devices which rely on this chip being initialized (or even present) need to
37010 + * be initialized in this function otherwise they may get initialized too early.
37011 + *
37012 + * Currently the only device depending on u72 is the SPI
37013 + */
37014 +static int __init ip7145dpf_u72_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
37015 +{
37016 +#ifdef IP7145DPF_USE_MMC_SPI
37017 +       if (ip7145dpf_mmc_spi_init_slot_a()) {
37018 +               printk(KERN_ERR "%s: could not request mmc resources\n", __FUNCTION__);
37019 +       } else {
37020 +               printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
37021 +               spi_register_board_info(ip7145dpf_spi_board_info, ARRAY_SIZE(ip7145dpf_spi_board_info));
37022 +               platform_device_register(&ip7145dpf_spi_gpio_device);
37023 +       }
37024 +#else
37025 +       /*
37026 +        * Initialize the Port F/Port B SD slots
37027 +        */
37028 +       ip7145dpf_portf_sd_init();
37029 +       ip7145dpf_portb_sd_init();
37030 +#endif
37031 +       return 0;
37032 +}
37033 +
37034 +/******************************************************************************
37035 + * LCD VGH on the board at PE6
37036 + */
37037 +static struct ubicom32lcdpower_platform_data ip7145dpf_lcdpower_data = {
37038 +       .vgh_gpio               = GPIO_RE_6,
37039 +       .vgh_polarity           = true,
37040 +};
37041 +
37042 +static struct platform_device ip7145dpf_lcdpower_device = {
37043 +       .name   = "ubicom32lcdpower",
37044 +       .id     = -1,
37045 +       .dev    = {
37046 +               .platform_data = &ip7145dpf_lcdpower_data,
37047 +       },
37048 +};
37049 +
37050 +/******************************************************************************
37051 + * Backlight on the board PD0, hardware PWM
37052 + */
37053 +static struct ubicom32bl_platform_data ip7145dpf_backlight_data = {
37054 +       .type                   = UBICOM32BL_TYPE_PWM,
37055 +       .pwm_channel            = 2,
37056 +       .pwm_prescale           = 15,
37057 +       .pwm_period             = 60,
37058 +       .default_intensity      = 0x80,
37059 +};
37060 +
37061 +static struct platform_device ip7145dpf_backlight_device = {
37062 +       .name   = "ubicom32bl",
37063 +       .id     = -1,
37064 +       .dev    = {
37065 +               .platform_data = &ip7145dpf_backlight_data,
37066 +       },
37067 +};
37068 +
37069 +/******************************************************************************
37070 + * Ubicom32Input on I2C, U48 MAX7310, address 0x18, 8 bits
37071 + */
37072 +static struct ubicom32input_i2c_button ip7145dpf_ubicom32input_i2c_u48_buttons[] = {
37073 +       {
37074 +               .type           = EV_KEY,
37075 +               .code           = KEY_UP,
37076 +               .bit            = 0,
37077 +               .active_low     = 1,
37078 +       },
37079 +       {
37080 +               .type           = EV_KEY,
37081 +               .code           = KEY_LEFT,
37082 +               .bit            = 1,
37083 +               .active_low     = 1,
37084 +       },
37085 +       {
37086 +               .type           = EV_KEY,
37087 +               .code           = KEY_RIGHT,
37088 +               .bit            = 2,
37089 +               .active_low     = 1,
37090 +       },
37091 +       {
37092 +               .type           = EV_KEY,
37093 +               .code           = KEY_DOWN,
37094 +               .bit            = 3,
37095 +               .active_low     = 1,
37096 +       },
37097 +       {
37098 +               .type           = EV_KEY,
37099 +               .code           = KEY_ENTER,
37100 +               .bit            = 4,
37101 +               .active_low     = 1,
37102 +       },
37103 +       {
37104 +               .type           = EV_KEY,
37105 +               .code           = KEY_MENU,
37106 +               .bit            = 5,
37107 +               .active_low     = 1,
37108 +       },
37109 +       {
37110 +               .type           = EV_KEY,
37111 +               .code           = KEY_ESC,
37112 +               .bit            = 6,
37113 +               .active_low     = 1,
37114 +       },
37115 +};
37116 +
37117 +static struct ubicom32input_i2c_platform_data ip7145dpf_ubicom32input_i2c_u48_platform_data = {
37118 +       .buttons        = ip7145dpf_ubicom32input_i2c_u48_buttons,
37119 +       .nbuttons       = ARRAY_SIZE(ip7145dpf_ubicom32input_i2c_u48_buttons),
37120 +       .name           = "Ubicom32 Input I2C U48",
37121 +};
37122 +
37123 +/******************************************************************************
37124 + * Additional GPIO chips
37125 + */
37126 +static struct pca953x_platform_data ip7145dpf_gpio_u72_platform_data = {
37127 +       .gpio_base = IP7145DPF_U72_BASE,
37128 +       .setup = ip7145dpf_u72_setup,
37129 +};
37130 +
37131 +/******************************************************************************
37132 + * Devices on the I2C bus
37133 + */
37134 +static struct i2c_board_info __initdata ip7145dpf_i2c_board_info[] = {
37135 +       /*
37136 +        * U51, S35390A RTC, address 0x30
37137 +        */
37138 +       {
37139 +               .type           = "s35390a",
37140 +               .addr           = 0x30,
37141 +       },
37142 +
37143 +       /*
37144 +        * U48, MAX7310 IO expander, 8 bits, address 0x18
37145 +        */
37146 +       {
37147 +               .type           = "ubicom32in_max7310",
37148 +               .addr           = 0x18,
37149 +               .platform_data  = &ip7145dpf_ubicom32input_i2c_u48_platform_data,
37150 +       },
37151 +
37152 +       /*
37153 +        * U72, MAX7310 IOB expander, 8 bits, address 0x19
37154 +        */
37155 +       {
37156 +               .type           = "max7310",
37157 +               .addr           = 0x19,
37158 +               .platform_data  = &ip7145dpf_gpio_u72_platform_data,
37159 +       },
37160 +};
37161 +
37162 +/*
37163 + * I2C bus on the board, SDA PE1, SCL PE2
37164 + */
37165 +static struct i2c_gpio_platform_data ip7145dpf_i2c_data = {
37166 +       .sda_pin                = GPIO_RE_1,
37167 +       .scl_pin                = GPIO_RE_2,
37168 +       .sda_is_open_drain      = 0,
37169 +       .scl_is_open_drain      = 0,
37170 +};
37171 +
37172 +static struct platform_device ip7145dpf_i2c_device = {
37173 +       .name   = "i2c-gpio",
37174 +       .id     = 0,
37175 +       .dev    = {
37176 +               .platform_data = &ip7145dpf_i2c_data,
37177 +       },
37178 +};
37179 +
37180 +/******************************************************************************
37181 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37182 + *
37183 + * WPS                 PF12
37184 + * FACT_DEFAULT                PF13
37185 + * POWER               PE4
37186 + *
37187 + * Not sutable for the keypad buttons since those run on I2C GPIO.  The polling
37188 + * of ubicom32input would seem to be excessive for this.
37189 + *
37190 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37191 + */
37192 +static struct ubicom32input_button ip7145dpf_ubicom32input_buttons[] = {
37193 +       {
37194 +               .type           = EV_KEY,
37195 +               .code           = KEY_FN_F1,
37196 +               .gpio           = GPIO_RF_12,
37197 +               .desc           = "WPS",
37198 +               .active_low     = 1,
37199 +       },
37200 +       {
37201 +               .type           = EV_KEY,
37202 +               .code           = KEY_FN_F2,
37203 +               .gpio           = GPIO_RF_13,
37204 +               .desc           = "Factory Default",
37205 +               .active_low     = 1,
37206 +       },
37207 +       {
37208 +               .type           = EV_KEY,
37209 +               .code           = KEY_POWER,
37210 +               .gpio           = GPIO_RE_4,
37211 +               .desc           = "Power",
37212 +               .active_low     = 1,
37213 +       },
37214 +};
37215 +
37216 +static struct ubicom32input_platform_data ip7145dpf_ubicom32input_data = {
37217 +       .buttons        = ip7145dpf_ubicom32input_buttons,
37218 +       .nbuttons       = ARRAY_SIZE(ip7145dpf_ubicom32input_buttons),
37219 +};
37220 +
37221 +static struct platform_device ip7145dpf_ubicom32input_device = {
37222 +       .name   = "ubicom32input",
37223 +       .id     = -1,
37224 +       .dev    = {
37225 +               .platform_data = &ip7145dpf_ubicom32input_data,
37226 +       },
37227 +};
37228 +
37229 +/*
37230 + * List of all devices in our system
37231 + */
37232 +static struct platform_device *ip7145dpf_devices[] __initdata = {
37233 +       &ip7145dpf_i2c_device,
37234 +       &ip7145dpf_lcdpower_device,
37235 +       &ip7145dpf_backlight_device,
37236 +       &ip7145dpf_ubicom32input_device,
37237 +};
37238 +
37239 +/*
37240 + * ip7145dpf_power_off
37241 + *     Called to turn the power off for this board
37242 + */
37243 +static void ip7145dpf_power_off(void)
37244 +{
37245 +       gpio_set_value(GPIO_RE_5, 0);
37246 +}
37247 +
37248 +/*
37249 + * ip7145dpf_init
37250 + *     Called to add the devices which we have on this board
37251 + */
37252 +static int __init ip7145dpf_init(void)
37253 +{
37254 +       int ret;
37255 +       struct platform_device *audio_dev;
37256 +
37257 +       ubi_gpio_init();
37258 +
37259 +#ifdef CONFIG_UIO_UBICOM32RING
37260 +       ring_tio_init("decoder_ring");
37261 +#endif
37262 +
37263 +       /*
37264 +        * Start up the video driver first
37265 +        */
37266 +       vdc_tio_init();
37267 +
37268 +       /*
37269 +        * Take over holding of the power from the system
37270 +        */
37271 +       ret = gpio_request(GPIO_RE_5, "power_hold");
37272 +       if (ret) {
37273 +               printk(KERN_ERR "%s: could not request power hold GPIO\n", __FUNCTION__);
37274 +       }
37275 +       gpio_direction_output(GPIO_RE_5, 1);
37276 +       mach_power_off = ip7145dpf_power_off;
37277 +
37278 +       /*
37279 +        * USB SEL_HOST_USB line
37280 +        */
37281 +       ret = gpio_request(GPIO_RF_11, "SEL_HOST_USB");
37282 +       if (ret) {
37283 +               printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37284 +       }
37285 +       gpio_direction_output(GPIO_RF_11, 0);
37286 +
37287 +       /*
37288 +        * Setup audio
37289 +        */
37290 +       audio_dev = audio_device_alloc("snd-ubi32-generic", "audio", "audio-i2sout", 0);
37291 +       if (audio_dev) {
37292 +               platform_device_register(audio_dev);
37293 +       }
37294 +
37295 +       /*
37296 +        * Register all of the devices we have on this board
37297 +        */
37298 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37299 +       platform_add_devices(ip7145dpf_devices, ARRAY_SIZE(ip7145dpf_devices));
37300 +
37301 +       /*
37302 +        * Register all of the devices which sit on the I2C bus
37303 +        */
37304 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
37305 +       i2c_register_board_info(0, ip7145dpf_i2c_board_info, ARRAY_SIZE(ip7145dpf_i2c_board_info));
37306 +
37307 +       /*
37308 +        * We have to initialize the SPI after the I2C IOB gets setup. SPI is initialized in
37309 +        * ip7145dpf_u72_setup
37310 +        */
37311 +
37312 +       return 0;
37313 +}
37314 +
37315 +arch_initcall(ip7145dpf_init);
37316 --- /dev/null
37317 +++ b/arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37318 @@ -0,0 +1,134 @@
37319 +/*
37320 + * arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37321 + *   Support for the IP7160 bringup board.
37322 + *
37323 + * (C) Copyright 2009, Ubicom, Inc.
37324 + *
37325 + * This file is part of the Ubicom32 Linux Kernel Port.
37326 + *
37327 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37328 + * it and/or modify it under the terms of the GNU General Public License
37329 + * as published by the Free Software Foundation, either version 2 of the
37330 + * License, or (at your option) any later version.
37331 + *
37332 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37333 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37334 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
37335 + * the GNU General Public License for more details.
37336 + *
37337 + * You should have received a copy of the GNU General Public License
37338 + * along with the Ubicom32 Linux Kernel Port.  If not,
37339 + * see <http://www.gnu.org/licenses/>.
37340 + *
37341 + * Ubicom32 implementation derived from (with many thanks):
37342 + *   arch/m68knommu
37343 + *   arch/blackfin
37344 + *   arch/parisc
37345 + */
37346 +#include <linux/device.h>
37347 +#include <linux/platform_device.h>
37348 +#include <linux/gpio.h>
37349 +#include <linux/leds.h>
37350 +#include <linux/delay.h>
37351 +#include <linux/input.h>
37352 +
37353 +#include <asm/board.h>
37354 +#include <asm/machdep.h>
37355 +#include <asm/ubicom32input.h>
37356 +
37357 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37358 +#include <asm/ubicom32suart.h>
37359 +#endif
37360 +
37361 +/*
37362 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37363 + *
37364 + * WPS                 PD5
37365 + * FACT_DEFAULT                PD6
37366 + *
37367 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37368 + */
37369 +static struct ubicom32input_button ip7160bringup_ubicom32input_buttons[] = {
37370 +       {
37371 +               .type           = EV_KEY,
37372 +               .code           = KEY_FN_F1,
37373 +               .gpio           = GPIO_RD_5,
37374 +               .desc           = "WPS",
37375 +               .active_low     = 1,
37376 +       },
37377 +       {
37378 +               .type           = EV_KEY,
37379 +               .code           = KEY_FN_F2,
37380 +               .gpio           = GPIO_RD_6,
37381 +               .desc           = "Factory Default",
37382 +               .active_low     = 1,
37383 +       },
37384 +};
37385 +
37386 +static struct ubicom32input_platform_data ip7160bringup_ubicom32input_data = {
37387 +       .buttons        = ip7160bringup_ubicom32input_buttons,
37388 +       .nbuttons       = ARRAY_SIZE(ip7160bringup_ubicom32input_buttons),
37389 +};
37390 +
37391 +static struct platform_device ip7160bringup_ubicom32input_device = {
37392 +       .name   = "ubicom32input",
37393 +       .id     = -1,
37394 +       .dev    = {
37395 +               .platform_data = &ip7160bringup_ubicom32input_data,
37396 +       },
37397 +};
37398 +
37399 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37400 +static struct resource ip7160bringup_ubicom32_suart_resources[] = {
37401 +       {
37402 +               .start  = RE,
37403 +               .end    = RE,
37404 +               .flags  = IORESOURCE_MEM,
37405 +       },
37406 +       {
37407 +               .start  = PORT_OTHER_INT(RE),
37408 +               .end    = PORT_OTHER_INT(RE),
37409 +               .flags  = IORESOURCE_IRQ,
37410 +       },
37411 +       {
37412 +               .start  = 250000000,
37413 +               .end    = 250000000,
37414 +               .flags  = UBICOM32_SUART_IORESOURCE_CLOCK,
37415 +       },
37416 +};
37417 +
37418 +static struct platform_device ip7160bringup_ubicom32_suart_device = {
37419 +       .name           = "ubicom32suart",
37420 +       .id             = -1,
37421 +       .num_resources  = ARRAY_SIZE(ip7160bringup_ubicom32_suart_resources),
37422 +       .resource       = ip7160bringup_ubicom32_suart_resources,
37423 +};
37424 +#endif
37425 +
37426 +/*
37427 + * List of all devices in our system
37428 + */
37429 +static struct platform_device *ip7160bringup_devices[] __initdata = {
37430 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37431 +       &ip7160bringup_ubicom32_suart_device,
37432 +#endif
37433 +       &ip7160bringup_ubicom32input_device,
37434 +};
37435 +
37436 +/*
37437 + * ip7160bringup_init
37438 + *     Called to add the devices which we have on this board
37439 + */
37440 +static int __init ip7160bringup_init(void)
37441 +{
37442 +       board_init();
37443 +
37444 +       ubi_gpio_init();
37445 +
37446 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37447 +       platform_add_devices(ip7160bringup_devices, ARRAY_SIZE(ip7160bringup_devices));
37448 +
37449 +       return 0;
37450 +}
37451 +
37452 +arch_initcall(ip7160bringup_init);
37453 --- /dev/null
37454 +++ b/arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37455 @@ -0,0 +1,326 @@
37456 +/*
37457 + * arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37458 + *   Platform initialization for ip7160dpf board.
37459 + *
37460 + * (C) Copyright 2009, Ubicom, Inc.
37461 + *
37462 + * This file is part of the Ubicom32 Linux Kernel Port.
37463 + *
37464 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37465 + * it and/or modify it under the terms of the GNU General Public License
37466 + * as published by the Free Software Foundation, either version 2 of the
37467 + * License, or (at your option) any later version.
37468 + *
37469 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37470 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37471 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
37472 + * the GNU General Public License for more details.
37473 + *
37474 + * You should have received a copy of the GNU General Public License
37475 + * along with the Ubicom32 Linux Kernel Port.  If not,
37476 + * see <http://www.gnu.org/licenses/>.
37477 + *
37478 + * Ubicom32 implementation derived from (with many thanks):
37479 + *   arch/m68knommu
37480 + *   arch/blackfin
37481 + *   arch/parisc
37482 + */
37483 +#include <linux/device.h>
37484 +#include <linux/platform_device.h>
37485 +#include <linux/delay.h>
37486 +#include <linux/gpio.h>
37487 +
37488 +#include <linux/i2c.h>
37489 +#include <linux/i2c-gpio.h>
37490 +
37491 +#include <linux/input.h>
37492 +
37493 +#include <asm/board.h>
37494 +#include <asm/machdep.h>
37495 +#include <asm/ubicom32hid.h>
37496 +#include <asm/vdc_tio.h>
37497 +#include <asm/audio.h>
37498 +
37499 +/*
37500 + * Backlight on the board PD0, hardware PWM
37501 + */
37502 +static const struct ubicom32hid_button ip7160dpf_ubicom32hid_buttons[] = {
37503 +       {
37504 +               .type   = EV_KEY,
37505 +               .code   = KEY_UP,
37506 +               .bit    = 0,
37507 +       },
37508 +       {
37509 +               .type   = EV_KEY,
37510 +               .code   = KEY_LEFT,
37511 +               .bit    = 1,
37512 +       },
37513 +       {
37514 +               .type   = EV_KEY,
37515 +               .code   = KEY_RIGHT,
37516 +               .bit    = 2,
37517 +       },
37518 +       {
37519 +               .type   = EV_KEY,
37520 +               .code   = KEY_DOWN,
37521 +               .bit    = 3,
37522 +       },
37523 +       {
37524 +               .type   = EV_KEY,
37525 +               .code   = KEY_ENTER,
37526 +               .bit    = 4,
37527 +       },
37528 +       {
37529 +               .type   = EV_KEY,
37530 +               .code   = KEY_MENU,
37531 +               .bit    = 5,
37532 +       },
37533 +       {
37534 +               .type   = EV_KEY,
37535 +               .code   = KEY_ESC,
37536 +               .bit    = 7,
37537 +       },
37538 +};
37539 +
37540 +static const struct ubicom32hid_ir ip7160dpf_ubicom32hid_ircodes[] = {
37541 +       {
37542 +               .type           = EV_KEY,
37543 +               .code           = KEY_UP,
37544 +               .ir_code        = 0xF807916E
37545 +       },
37546 +       {
37547 +               .type           = EV_KEY,
37548 +               .code           = KEY_DOWN,
37549 +               .ir_code        = 0xF20D916E
37550 +       },
37551 +       {
37552 +               .type           = EV_KEY,
37553 +               .code           = KEY_LEFT,
37554 +               .ir_code        = 0xF609916E
37555 +       },
37556 +       {
37557 +               .type           = EV_KEY,
37558 +               .code           = KEY_RIGHT,
37559 +               .ir_code        = 0xF40B916E
37560 +       },
37561 +       {
37562 +               .type           = EV_KEY,
37563 +               .code           = KEY_ENTER,
37564 +               .ir_code        = 0xF50A916E
37565 +       },
37566 +       {       /* rotate */
37567 +               .type           = EV_KEY,
37568 +               .code           = KEY_FN_F1,
37569 +               .ir_code        = 0xF906916E
37570 +       },
37571 +       {
37572 +               .type           = EV_KEY,
37573 +               .code           = KEY_MENU,
37574 +               .ir_code        = 0xF708916E
37575 +       },
37576 +       {       /* font size */
37577 +               .type           = EV_KEY,
37578 +               .code           = KEY_FN_F2,
37579 +               .ir_code        = 0xF30C916E
37580 +       },
37581 +       {
37582 +               .type           = EV_KEY,
37583 +               .code           = KEY_ESC,
37584 +               .ir_code        = 0xF10E916E
37585 +       },
37586 +       {
37587 +               .type           = EV_KEY,
37588 +               .code           = KEY_VOLUMEUP,
37589 +               .ir_code        = 0xF00F916E
37590 +       },
37591 +       {
37592 +               .type           = EV_KEY,
37593 +               .code           = KEY_VOLUMEDOWN,
37594 +               .ir_code        = 0xED12916E
37595 +       },
37596 +       {
37597 +               .type           = EV_KEY,
37598 +               .code           = KEY_MUTE,
37599 +               .ir_code        = 0xEA15916E
37600 +       },
37601 +       {
37602 +               .type           = EV_KEY,
37603 +               .code           = KEY_INFO,
37604 +               .ir_code        = 0xEF10916E
37605 +       },
37606 +       {       /* Like */
37607 +               .type           = EV_KEY,
37608 +               .code           = KEY_FN_F3,
37609 +               .ir_code        = 0xEE11916E
37610 +       },
37611 +       {       /* Dislike */
37612 +               .type           = EV_KEY,
37613 +               .code           = KEY_FN_F4,
37614 +               .ir_code        = 0xEB14916E
37615 +       },
37616 +       {
37617 +               .type           = EV_KEY,
37618 +               .code           = KEY_POWER,
37619 +               .ir_code        = 0xFD02916E
37620 +       },
37621 +};
37622 +
37623 +static struct ubicom32hid_platform_data ip7160dpf_ubicom32hid_platform_data = {
37624 +       .gpio_reset             = GPIO_RI_5,
37625 +       .gpio_reset_polarity    = 0,
37626 +       .type                   = UBICOM32HID_BL_TYPE_PWM,
37627 +       .invert                 = 0,
37628 +       .default_intensity      = 128,
37629 +       .buttons                = ip7160dpf_ubicom32hid_buttons,
37630 +       .nbuttons               = ARRAY_SIZE(ip7160dpf_ubicom32hid_buttons),
37631 +       .ircodes                = ip7160dpf_ubicom32hid_ircodes,
37632 +       .nircodes               = ARRAY_SIZE(ip7160dpf_ubicom32hid_ircodes),
37633 +};
37634 +
37635 +/*
37636 + * Devices on the I2C bus
37637 + *     This board has a "bus 2" which is isolated from the main bus by U47
37638 + *     and pin RI0.  It should be safe to always enable bus 2 by setting
37639 + *     RI0 to low, however, it should be noted that on all existing configurations
37640 + *     of this board, U49 and U51 are not populated.
37641 + */
37642 +static struct i2c_board_info __initdata ip7160dpf_i2c_board_info[] = {
37643 +       /*
37644 +        * U37, CS4350 DAC, address 0x4B, bus 2
37645 +        *      THIS ENTRY MUST BE FIRST
37646 +        */
37647 +       {
37648 +               .type           = "cs4350",
37649 +               .addr           = 0x4B,
37650 +       }
37651 +
37652 +       /*
37653 +        * U24, ubicom32hid
37654 +        */
37655 +       {
37656 +               .type           = "ubicom32hid",
37657 +               .addr           = 0x08,
37658 +               .platform_data  = &ip7160dpf_ubicom32hid_platform_data,
37659 +       },
37660 +
37661 +       /*
37662 +        * U49, ISL29001 Ambient Light Sensor, address 0x44, bus 2 (may not be stuffed)
37663 +        */
37664 +
37665 +       /*
37666 +        * U51, S35390A RTC, address 0x30, bus 2 (may not be stuffed)
37667 +        */
37668 +#ifdef CONFIG_RTC_DRV_S35390A
37669 +       {
37670 +               .type           = "s35390a",
37671 +               .addr           = 0x30,
37672 +       },
37673 +#endif
37674 +};
37675 +
37676 +/*
37677 + * I2C bus on the board, SDA PI1, SCL PI2
37678 + */
37679 +static struct i2c_gpio_platform_data ip7160dpf_i2c_data = {
37680 +       .sda_pin                = GPIO_RI_1,
37681 +       .scl_pin                = GPIO_RI_2,
37682 +       .sda_is_open_drain      = 0,
37683 +       .scl_is_open_drain      = 0,
37684 +       .scl_is_output_only     = 1,
37685 +       .udelay                 = 6,
37686 +};
37687 +
37688 +static struct platform_device ip7160dpf_i2c_device = {
37689 +       .name   = "i2c-gpio",
37690 +       .id     = 0,
37691 +       .dev    = {
37692 +               .platform_data = &ip7160dpf_i2c_data,
37693 +       },
37694 +};
37695 +
37696 +/*
37697 + * List of all devices in our system
37698 + */
37699 +static struct platform_device *ip7160dpf_devices[] __initdata = {
37700 +       &ip7160dpf_i2c_device,
37701 +};
37702 +
37703 +/*
37704 + * ip7160dpf_power_off
37705 + *     Called to turn the power off for this board
37706 + */
37707 +static void ip7160dpf_power_off(void)
37708 +{
37709 +       gpio_set_value(GPIO_RF_14, 0);
37710 +}
37711 +
37712 +/*
37713 + * ip7160dpf_init
37714 + *     Called to add the devices which we have on this board
37715 + */
37716 +static int __init ip7160dpf_init(void)
37717 +{
37718 +       int ret;
37719 +       struct platform_device *audio_dev;
37720 +
37721 +       ubi_gpio_init();
37722 +
37723 +       /*
37724 +        * Hold the POWER_HOLD line
37725 +        */
37726 +       ret = gpio_request(GPIO_RF_14, "POWER_HOLD");
37727 +       if (ret) {
37728 +               printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
37729 +       }
37730 +       gpio_direction_output(GPIO_RF_14, 1);
37731 +       mach_power_off = ip7160dpf_power_off;
37732 +
37733 +       /*
37734 +        * USB SEL_HOST_USB line
37735 +        */
37736 +       ret = gpio_request(GPIO_RI_13, "SEL_HOST_USB");
37737 +       if (ret) {
37738 +               printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37739 +       }
37740 +       gpio_direction_output(GPIO_RI_13, 0);
37741 +
37742 +       /*
37743 +        * USB/DAC nRESET line
37744 +        */
37745 +       ret = gpio_request(GPIO_RI_3, "USB_DAC_nRESET");
37746 +       if (ret) {
37747 +               printk(KERN_ERR "%s: could not request USB_DAC_nRESET GPIO\n", __FUNCTION__);
37748 +       }
37749 +       gpio_direction_output(GPIO_RI_3, 0);
37750 +       udelay(1);
37751 +       gpio_direction_output(GPIO_RI_3, 1);
37752 +
37753 +       /*
37754 +        * I2C BUS2 Disable line
37755 +        */
37756 +       ret = gpio_request(GPIO_RI_0, "DISABLE_BUS2");
37757 +       if (ret) {
37758 +               printk(KERN_ERR "%s: could not request DISABLE_BUS2 GPIO\n", __FUNCTION__);
37759 +       }
37760 +       gpio_direction_output(GPIO_RI_0, 0);
37761 +
37762 +       vdc_tio_init();
37763 +
37764 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37765 +       platform_add_devices(ip7160dpf_devices, ARRAY_SIZE(ip7160dpf_devices));
37766 +
37767 +       /*
37768 +        * Allocate the audio driver if we can
37769 +        */
37770 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio-i2sout", 0);
37771 +       if (audio_dev) {
37772 +               ip7160dpf_i2c_board_info[0].platform_data = audio_dev;
37773 +       }
37774 +
37775 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
37776 +       i2c_register_board_info(0, ip7160dpf_i2c_board_info, ARRAY_SIZE(ip7160dpf_i2c_board_info));
37777 +
37778 +       return 0;
37779 +}
37780 +
37781 +arch_initcall(ip7160dpf_init);
37782 --- /dev/null
37783 +++ b/arch/ubicom32/mach-ip7k/board-ip7160rgw.c
37784 @@ -0,0 +1,355 @@
37785 +/*
37786 + * arch/ubicom32/mach-ip7k/board-ip7160rgw.c
37787 + *   Platform initialization for ip7160rgw board.
37788 + *
37789 + * (C) Copyright 2009, Ubicom, Inc.
37790 + *
37791 + * This file is part of the Ubicom32 Linux Kernel Port.
37792 + *
37793 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37794 + * it and/or modify it under the terms of the GNU General Public License
37795 + * as published by the Free Software Foundation, either version 2 of the
37796 + * License, or (at your option) any later version.
37797 + *
37798 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37799 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37800 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
37801 + * the GNU General Public License for more details.
37802 + *
37803 + * You should have received a copy of the GNU General Public License
37804 + * along with the Ubicom32 Linux Kernel Port.  If not,
37805 + * see <http://www.gnu.org/licenses/>.
37806 + *
37807 + * Ubicom32 implementation derived from (with many thanks):
37808 + *   arch/m68knommu
37809 + *   arch/blackfin
37810 + *   arch/parisc
37811 + */
37812 +#include <linux/device.h>
37813 +#include <linux/platform_device.h>
37814 +#include <linux/gpio.h>
37815 +#include <linux/leds.h>
37816 +#include <linux/delay.h>
37817 +#include <linux/input.h>
37818 +#include <linux/spi/spi.h>
37819 +
37820 +#include <asm/board.h>
37821 +#include <asm/machdep.h>
37822 +#include <asm/ubicom32input.h>
37823 +
37824 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37825 +#include <asm/ubicom32suart.h>
37826 +#endif
37827 +
37828 +#include <asm/ubicom32-spi-gpio.h>
37829 +#include <asm/switch-dev.h>
37830 +
37831 +#ifdef CONFIG_IP7160RGWLCD
37832 +#include <linux/i2c.h>
37833 +#include <linux/i2c-gpio.h>
37834 +/*
37835 + * LCD Adapter board 8007-092x support
37836 + *
37837 + * Touch controller
37838 + *
37839 + * Connected via I2C bus, interrupt on PA6
37840 + */
37841 +#include <linux/i2c/tsc2007.h>
37842 +
37843 +/*
37844 + * ip7160rgwlcd_tsc2007_exit_platform_hw
37845 + */
37846 +static void ip7160rgwlcd_tsc2007_exit_platform_hw(void)
37847 +{
37848 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
37849 +       gpio_free(GPIO_RA_5);
37850 +}
37851 +
37852 +/*
37853 + * ip7160rgwlcd_tsc2007_init_platform_hw
37854 + */
37855 +static int ip7160rgwlcd_tsc2007_init_platform_hw(void)
37856 +{
37857 +       int res = gpio_request(GPIO_RA_5, "TSC2007_IRQ");
37858 +       if (res) {
37859 +               return res;
37860 +       }
37861 +
37862 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
37863 +       UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 17);
37864 +       return 0;
37865 +}
37866 +
37867 +/*
37868 + * ip7160rgwlcd_tsc2007_get_pendown_state
37869 + */
37870 +static int ip7160rgwlcd_tsc2007_get_pendown_state(void)
37871 +{
37872 +       return !gpio_get_value(GPIO_RA_5);
37873 +}
37874 +
37875 +static struct tsc2007_platform_data ip7160rgwlcd_tsc2007_data = {
37876 +       .model                  = 2007,
37877 +       .x_plate_ohms           = 350,
37878 +       .get_pendown_state      = ip7160rgwlcd_tsc2007_get_pendown_state,
37879 +       .init_platform_hw       = ip7160rgwlcd_tsc2007_init_platform_hw,
37880 +       .exit_platform_hw       = ip7160rgwlcd_tsc2007_exit_platform_hw,
37881 +};
37882 +
37883 +/******************************************************************************
37884 + * I2C bus on the board, SDA PI14, SCL PI13
37885 + */
37886 +static struct i2c_gpio_platform_data ip7160rgwlcd_i2c_data = {
37887 +       .sda_pin                = GPIO_RI_14,
37888 +       .scl_pin                = GPIO_RI_13,
37889 +       .sda_is_open_drain      = 0,
37890 +       .scl_is_open_drain      = 0,
37891 +       .udelay                 = 50,
37892 +};
37893 +
37894 +static struct platform_device ip7160rgwlcd_i2c_device = {
37895 +       .name   = "i2c-gpio",
37896 +       .id     = 0,
37897 +       .dev    = {
37898 +               .platform_data = &ip7160rgwlcd_i2c_data,
37899 +       },
37900 +};
37901 +
37902 +static struct i2c_board_info __initdata ip7160rgwlcd_i2c_board_info[] = {
37903 +       {
37904 +               .type = "tsc2007",
37905 +               .addr = 0x48,
37906 +               .irq = 45, // RA5
37907 +               .platform_data = &ip7160rgwlcd_tsc2007_data,
37908 +       },
37909 +};
37910 +
37911 +#endif
37912 +
37913 +/*
37914 + * SPI bus over GPIO for Gigabit Ethernet Switch
37915 + *     U58:
37916 + *             MOSI    PE0
37917 + *             MISO    PE1
37918 + *             CLK     PE3
37919 + *             CS      PE2
37920 + */
37921 +static struct ubicom32_spi_gpio_platform_data ip7160rgw_spi_gpio_data = {
37922 +       .pin_mosi       = GPIO_RE_0,
37923 +       .pin_miso       = GPIO_RE_1,
37924 +       .pin_clk        = GPIO_RE_3,
37925 +       .bus_num        = 0,            // We'll call this SPI bus 0
37926 +       .num_chipselect = 1,            // only one device on this SPI bus
37927 +       .clk_default    = 1,
37928 +};
37929 +
37930 +static struct platform_device ip7160rgw_spi_gpio_device = {
37931 +       .name   = "ubicom32-spi-gpio",
37932 +       .id     = 0,
37933 +       .dev    = {
37934 +               .platform_data = &ip7160rgw_spi_gpio_data,
37935 +       },
37936 +};
37937 +
37938 +static struct ubicom32_spi_gpio_controller_data ip7160rgw_bcm539x_controller_data = {
37939 +       .pin_cs = GPIO_RE_2,
37940 +};
37941 +
37942 +static struct switch_core_platform_data ip7160rgw_bcm539x_platform_data = {
37943 +       .flags          = SWITCH_DEV_FLAG_HW_RESET,
37944 +       .pin_reset      = GPIO_RE_4,
37945 +       .name           = "bcm539x",
37946 +};
37947 +
37948 +static struct spi_board_info ip7160rgw_spi_board_info[] = {
37949 +       {
37950 +               .modalias               = "bcm539x-spi",
37951 +               .bus_num                = 0,
37952 +               .chip_select            = 0,
37953 +               .max_speed_hz           = 2000000,
37954 +               .platform_data          = &ip7160rgw_bcm539x_platform_data,
37955 +               .controller_data        = &ip7160rgw_bcm539x_controller_data,
37956 +               .mode                   = SPI_MODE_3,
37957 +       }
37958 +};
37959 +
37960 +/*
37961 + * LEDs
37962 + *
37963 + * WLAN1               PD0     (PWM capable)
37964 + * WLAN2               PD1
37965 + * USB2.0              PD2
37966 + * Status              PD3
37967 + * WPS                 PD4
37968 + *
37969 + * TODO: check triggers, are they generic?
37970 + */
37971 +static struct gpio_led ip7160rgw_gpio_leds[] = {
37972 +       {
37973 +               .name                   = "d53:green:WLAN1",
37974 +               .default_trigger        = "WLAN1",
37975 +               .gpio                   = GPIO_RD_0,
37976 +               .active_low             = 1,
37977 +       },
37978 +       {
37979 +               .name                   = "d54:green:WLAN2",
37980 +               .default_trigger        = "WLAN2",
37981 +               .gpio                   = GPIO_RD_1,
37982 +               .active_low             = 1,
37983 +       },
37984 +       {
37985 +               .name                   = "d55:green:USB",
37986 +               .default_trigger        = "USB",
37987 +               .gpio                   = GPIO_RD_2,
37988 +               .active_low             = 1,
37989 +       },
37990 +       {
37991 +               .name                   = "d56:green:Status",
37992 +               .default_trigger        = "Status",
37993 +               .gpio                   = GPIO_RD_3,
37994 +               .active_low             = 1,
37995 +       },
37996 +       {
37997 +               .name                   = "d57:green:WPS",
37998 +               .default_trigger        = "WPS",
37999 +               .gpio                   = GPIO_RD_4,
38000 +               .active_low             = 1,
38001 +       },
38002 +};
38003 +
38004 +static struct gpio_led_platform_data ip7160rgw_gpio_led_platform_data = {
38005 +       .num_leds       = 5,
38006 +       .leds           = ip7160rgw_gpio_leds,
38007 +};
38008 +
38009 +static struct platform_device ip7160rgw_gpio_leds_device = {
38010 +       .name           = "leds-gpio",
38011 +       .id             = -1,
38012 +       .dev = {
38013 +               .platform_data = &ip7160rgw_gpio_led_platform_data,
38014 +       },
38015 +};
38016 +
38017 +/*
38018 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
38019 + *
38020 + * WPS                 PD5
38021 + * FACT_DEFAULT                PD6
38022 + *
38023 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
38024 + */
38025 +static struct ubicom32input_button ip7160rgw_ubicom32input_buttons[] = {
38026 +       {
38027 +               .type           = EV_KEY,
38028 +               .code           = KEY_FN_F1,
38029 +               .gpio           = GPIO_RD_5,
38030 +               .desc           = "WPS",
38031 +               .active_low     = 1,
38032 +       },
38033 +       {
38034 +               .type           = EV_KEY,
38035 +               .code           = KEY_FN_F2,
38036 +               .gpio           = GPIO_RD_6,
38037 +               .desc           = "Factory Default",
38038 +               .active_low     = 1,
38039 +       },
38040 +};
38041 +
38042 +static struct ubicom32input_platform_data ip7160rgw_ubicom32input_data = {
38043 +       .buttons        = ip7160rgw_ubicom32input_buttons,
38044 +       .nbuttons       = ARRAY_SIZE(ip7160rgw_ubicom32input_buttons),
38045 +};
38046 +
38047 +static struct platform_device ip7160rgw_ubicom32input_device = {
38048 +       .name   = "ubicom32input",
38049 +       .id     = -1,
38050 +       .dev    = {
38051 +               .platform_data = &ip7160rgw_ubicom32input_data,
38052 +       },
38053 +};
38054 +
38055 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38056 +static struct resource ip7160rgw_ubicom32_suart_resources[] = {
38057 +       {
38058 +               .start  = RE,
38059 +               .end    = RE,
38060 +               .flags  = IORESOURCE_MEM,
38061 +       },
38062 +       {
38063 +               .start  = PORT_OTHER_INT(RE),
38064 +               .end    = PORT_OTHER_INT(RE),
38065 +               .flags  = IORESOURCE_IRQ,
38066 +       },
38067 +       {
38068 +               .start  = 250000000,
38069 +               .end    = 250000000,
38070 +               .flags  = UBICOM32_SUART_IORESOURCE_CLOCK,
38071 +       },
38072 +};
38073 +
38074 +static struct platform_device ip7160rgw_ubicom32_suart_device = {
38075 +       .name           = "ubicom32suart",
38076 +       .id             = -1,
38077 +       .num_resources  = ARRAY_SIZE(ip7160rgw_ubicom32_suart_resources),
38078 +       .resource       = ip7160rgw_ubicom32_suart_resources,
38079 +};
38080 +#endif
38081 +
38082 +/*
38083 + * List of all devices in our system
38084 + */
38085 +static struct platform_device *ip7160rgw_devices[] __initdata = {
38086 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38087 +       &ip7160rgw_ubicom32_suart_device,
38088 +#endif
38089 +       &ip7160rgw_ubicom32input_device,
38090 +       &ip7160rgw_gpio_leds_device,
38091 +       &ip7160rgw_spi_gpio_device,
38092 +#ifdef CONFIG_IP7160RGWLCD
38093 +       &ip7160rgwlcd_i2c_device,
38094 +#endif
38095 +};
38096 +
38097 +/*
38098 + * ip7160rgw_init
38099 + *     Called to add the devices which we have on this board
38100 + */
38101 +static int __init ip7160rgw_init(void)
38102 +{
38103 +       board_init();
38104 +
38105 +       /*
38106 +        * Rev 1.2 boards have spi in a different place than 1.1/1.0
38107 +        */
38108 +       if (strcmp(board_get_revision(), "1.2") == 0) {
38109 +               ip7160rgw_spi_gpio_data.pin_mosi = GPIO_RD_7;
38110 +       }
38111 +
38112 +       ubi_gpio_init();
38113 +
38114 +       /*
38115 +        * Reserve switch SPI CS on behalf on switch driver
38116 +        */
38117 +       if (gpio_request(ip7160rgw_bcm539x_controller_data.pin_cs, "switch-bcm539x-cs")) {
38118 +               printk(KERN_WARNING "Could not request cs of switch SPI I/F\n");
38119 +               return -EIO;
38120 +       }
38121 +       gpio_direction_output(ip7160rgw_bcm539x_controller_data.pin_cs, 1);
38122 +
38123 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38124 +       platform_add_devices(ip7160rgw_devices, ARRAY_SIZE(ip7160rgw_devices));
38125 +
38126 +       printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
38127 +       spi_register_board_info(ip7160rgw_spi_board_info, ARRAY_SIZE(ip7160rgw_spi_board_info));
38128 +
38129 +#ifdef CONFIG_IP7160RGWLCD
38130 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38131 +       i2c_register_board_info(0, ip7160rgwlcd_i2c_board_info, ARRAY_SIZE(ip7160rgwlcd_i2c_board_info));
38132 +       printk(KERN_INFO "IP7160 RGW + LCD\n");
38133 +#else
38134 +       printk(KERN_INFO "IP7160 RGW\n");
38135 +#endif
38136 +       return 0;
38137 +}
38138 +
38139 +arch_initcall(ip7160rgw_init);
38140 --- /dev/null
38141 +++ b/arch/ubicom32/mach-ip7k/board-ip7500av.c
38142 @@ -0,0 +1,273 @@
38143 +/*
38144 + * arch/ubicom32/mach-ip7k/board-ip7500av.c
38145 + *   Support for IP7500 Audio Video Board + CPU module board.
38146 + *
38147 + * This file supports the IP7500 Audio Video Board:
38148 + *     8007-0810  Rev 1.0
38149 + * with one of the following CPU module boards:
38150 + *     8007-0510  Rev 1.0
38151 + *     8007-0510A Rev 1.0 (with ethernet)
38152 + *
38153 + * DIP Switch SW2 configuration: (*) default
38154 + *     POS 1: on(*) = PCI enabled, off = PCI disabled
38155 + *     POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
38156 + *     POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
38157 + *     POS 4: unused
38158 + *
38159 + * (C) Copyright 2009, Ubicom, Inc.
38160 + *
38161 + * This file is part of the Ubicom32 Linux Kernel Port.
38162 + *
38163 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38164 + * it and/or modify it under the terms of the GNU General Public License
38165 + * as published by the Free Software Foundation, either version 2 of the
38166 + * License, or (at your option) any later version.
38167 + *
38168 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38169 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38170 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
38171 + * the GNU General Public License for more details.
38172 + *
38173 + * You should have received a copy of the GNU General Public License
38174 + * along with the Ubicom32 Linux Kernel Port.  If not,
38175 + * see <http://www.gnu.org/licenses/>.
38176 + */
38177 +
38178 +#include <linux/platform_device.h>
38179 +#include <linux/device.h>
38180 +#include <linux/gpio.h>
38181 +#include <linux/i2c.h>
38182 +#include <linux/i2c-gpio.h>
38183 +#include <linux/delay.h>
38184 +#include <asm/board.h>
38185 +#include <asm/machdep.h>
38186 +#include <asm/ring_tio.h>
38187 +#include <asm/vdc_tio.h>
38188 +#include <asm/audio.h>
38189 +#include <asm/ubi32-pcm.h>
38190 +#include <asm/ubi32-cs4384.h>
38191 +
38192 +/******************************************************************************
38193 + * Devices on the I2C bus
38194 + *
38195 + * BEWARE of changing the order of things in this array as we depend on
38196 + * certain things to be in certain places.
38197 + */
38198 +static struct i2c_board_info __initdata ip7500av_i2c_board_info[] = {
38199 +       /*
38200 +        * U6, CS4384 DAC, address 0x19
38201 +        */
38202 +       {
38203 +               .type           = "cs4384",
38204 +               .addr           = 0x19,
38205 +       },
38206 +};
38207 +
38208 +/*
38209 + * I2C bus on the board, SDA PD1, SCL PD2
38210 + */
38211 +static struct i2c_gpio_platform_data ip7500av_i2c_data = {
38212 +       .sda_pin                = GPIO_RD_6,
38213 +       .scl_pin                = GPIO_RD_3,
38214 +       .sda_is_open_drain      = 0,
38215 +       .scl_is_open_drain      = 0,
38216 +       .udelay                 = 50,
38217 +};
38218 +
38219 +static struct platform_device ip7500av_i2c_device = {
38220 +       .name   = "i2c-gpio",
38221 +       .id     = 0,
38222 +       .dev    = {
38223 +               .platform_data = &ip7500av_i2c_data,
38224 +       },
38225 +};
38226 +
38227 +/*
38228 + * List of possible mclks we can generate.  This depends on the CPU frequency.
38229 + */
38230 +static struct ubi32_cs4384_mclk_entry ip7500av_cs4384_mclk_entries[] = {
38231 +       {
38232 +               .rate   =       12288000,
38233 +               .div    =       44,
38234 +       },
38235 +       {
38236 +               .rate   =       11289600,
38237 +               .div    =       48,
38238 +       },
38239 +};
38240 +
38241 +/*
38242 + * List of all devices in our system
38243 + */
38244 +static struct platform_device *ip7500av_devices[] __initdata = {
38245 +       &ip7500av_i2c_device,
38246 +};
38247 +
38248 +/*
38249 + * ip7500av_vdac_write
38250 + */
38251 +static int __init ip7500av_vdac_write(int reg, int val)
38252 +{
38253 +       struct i2c_adapter *adap;
38254 +       struct i2c_msg msg[1];
38255 +       unsigned char data[2];
38256 +       int err;
38257 +
38258 +       adap = i2c_get_adapter(0);
38259 +       if (!adap) {
38260 +               printk(KERN_WARNING "%s: failed to get i2c adapter\n", __FUNCTION__);
38261 +               return -ENODEV;
38262 +       }
38263 +       msg->addr = 0x2B;
38264 +       msg->flags = 0;
38265 +       msg->len = 2;
38266 +       msg->buf = data;
38267 +       data[0] = reg;
38268 +       data[1] = val;
38269 +       err = i2c_transfer(adap, msg, 1);
38270 +       i2c_put_adapter(adap);
38271 +       if (err >= 0) {
38272 +               return 0;
38273 +       }
38274 +       return err;
38275 +}
38276 +
38277 +/*
38278 + * ip7500av_vdac_init
38279 + *     Initializes the video DAC via I2C
38280 + *
38281 + * Equivalent mode line: 720x480p = 27 Mhz, 720 736 800 858 480 484 492 525
38282 + */
38283 +static int __init ip7500av_vdac_init(void)
38284 +{
38285 +       int err;
38286 +
38287 +       printk(KERN_INFO "Initializing ADV7393 DAC\n");
38288 +
38289 +       /*
38290 +        * Reset the VDAC
38291 +        */
38292 +       if (gpio_request(GPIO_RF_6, "VDAC Reset")) {
38293 +               printk(KERN_WARNING "%s: failed to allocate VDAC Reset\n", __FUNCTION__);
38294 +               return -EBUSY;
38295 +       }
38296 +       gpio_direction_output(GPIO_RF_6, 0);
38297 +       udelay(1);
38298 +       gpio_set_value(GPIO_RF_6, 1);
38299 +
38300 +       /*
38301 +        * See table 100 of ADV7393 data sheet: 16-bit 525p YCrCb In, YPbPr Out
38302 +        */
38303 +       err = ip7500av_vdac_write(0x17, 0x02);
38304 +       if (err) {
38305 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38306 +               return err;
38307 +       }
38308 +       err = ip7500av_vdac_write(0x00, 0x1c);
38309 +       if (err) {
38310 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38311 +               return err;
38312 +       }
38313 +       err = ip7500av_vdac_write(0x01, 0x10);
38314 +       if (err) {
38315 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38316 +               return err;
38317 +       }
38318 +       err = ip7500av_vdac_write(0x31, 0x01);
38319 +       if (err) {
38320 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38321 +               return err;
38322 +       }
38323 +#ifdef IP7500AV_VDAC_SWAP_PBPR
38324 +       err = ip7500av_vdac_write(0x35, 0x08);
38325 +       if (err) {
38326 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38327 +               return err;
38328 +       }
38329 +#endif
38330 +#ifdef IP7500AV_VDAC_FULL_RANGE
38331 +       err = ip7500av_vdac_write(0x30, 0x02);
38332 +       if (err) {
38333 +               printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38334 +               return err;
38335 +       }
38336 +#endif
38337 +       return 0;
38338 +}
38339 +late_initcall(ip7500av_vdac_init);
38340 +
38341 +/*
38342 + * ip7500av_init
38343 + *     Called to add the devices which we have on this board
38344 + */
38345 +static int __init ip7500av_init(void)
38346 +{
38347 +       struct platform_device *audio_dev;
38348 +       struct platform_device *audio_dev2;
38349 +       struct ubi32_cs4384_platform_data *cs4384_pd;
38350 +
38351 +       board_init();
38352 +
38353 +       ubi_gpio_init();
38354 +
38355 +       vdc_tio_init();
38356 +
38357 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38358 +       platform_add_devices(ip7500av_devices, ARRAY_SIZE(ip7500av_devices));
38359 +
38360 +       /*
38361 +        * CS4384 DAC
38362 +        */
38363 +       audio_dev = audio_device_alloc("snd-ubi32-cs4384", "audio", "audio-i2sout",
38364 +                       sizeof(struct ubi32_cs4384_platform_data));
38365 +       if (audio_dev) {
38366 +               /*
38367 +                * Attempt to figure out a good divisor.  This will only work
38368 +                * assuming the core frequency is compatible.
38369 +                */
38370 +               int i;
38371 +               unsigned int freq = processor_frequency();
38372 +               for (i = 0; i < ARRAY_SIZE(ip7500av_cs4384_mclk_entries); i++) {
38373 +                       unsigned int div;
38374 +                       unsigned int rate = ip7500av_cs4384_mclk_entries[i].rate / 1000;
38375 +                       div = ((freq / rate) + 500) / 1000;
38376 +                       ip7500av_cs4384_mclk_entries[i].div = div;
38377 +                       printk("CS4384 mclk %d rate %u000Hz div %u act %u\n", i, rate, div, freq / div);
38378 +               }
38379 +
38380 +               cs4384_pd = audio_device_priv(audio_dev);
38381 +               cs4384_pd->mclk_src = UBI32_CS4384_MCLK_PWM_0;
38382 +               cs4384_pd->n_mclk = ARRAY_SIZE(ip7500av_cs4384_mclk_entries);
38383 +               cs4384_pd->mclk_entries = ip7500av_cs4384_mclk_entries;
38384 +               ip7500av_i2c_board_info[0].platform_data = audio_dev;
38385 +
38386 +               /*
38387 +                * Reset the DAC
38388 +                */
38389 +               if (gpio_request(GPIO_RF_4, "DAC Reset") == 0) {
38390 +                       gpio_direction_output(GPIO_RF_4, 0);
38391 +                       udelay(1);
38392 +                       gpio_direction_output(GPIO_RF_4, 1);
38393 +               } else {
38394 +                       printk("Unable to request DAC reset GPIO\n");
38395 +               }
38396 +       }
38397 +
38398 +       /*
38399 +        * SPDIF port
38400 +        */
38401 +       audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
38402 +       if (audio_dev2) {
38403 +               platform_device_register(audio_dev2);
38404 +       }
38405 +
38406 +       /*
38407 +        * Register all of the devices which sit on the I2C bus
38408 +        */
38409 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38410 +       i2c_register_board_info(0, ip7500av_i2c_board_info, ARRAY_SIZE(ip7500av_i2c_board_info));
38411 +
38412 +       printk(KERN_INFO "IP7500 Audio/Video Board\n");
38413 +       return 0;
38414 +}
38415 +arch_initcall(ip7500av_init);
38416 --- /dev/null
38417 +++ b/arch/ubicom32/mach-ip7k/board-ip7500iap.c
38418 @@ -0,0 +1,414 @@
38419 +/*
38420 + * arch/ubicom32/mach-ip7k/board-ip7500iap.c
38421 + *   Support for IP7500 Internet Audio Player
38422 + *
38423 + * This file supports the IP7500 Internet Audio Player:
38424 + *     8007-1110  Rev 1.0
38425 + *
38426 + * (C) Copyright 2009, Ubicom, Inc.
38427 + *
38428 + * This file is part of the Ubicom32 Linux Kernel Port.
38429 + *
38430 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38431 + * it and/or modify it under the terms of the GNU General Public License
38432 + * as published by the Free Software Foundation, either version 2 of the
38433 + * License, or (at your option) any later version.
38434 + *
38435 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38436 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38437 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
38438 + * the GNU General Public License for more details.
38439 + *
38440 + * You should have received a copy of the GNU General Public License
38441 + * along with the Ubicom32 Linux Kernel Port.  If not,
38442 + * see <http://www.gnu.org/licenses/>.
38443 + */
38444 +#include <linux/device.h>
38445 +#include <linux/gpio.h>
38446 +#include <asm/board.h>
38447 +
38448 +#include <linux/delay.h>
38449 +
38450 +#include <linux/platform_device.h>
38451 +#include <asm/audio.h>
38452 +#include <linux/i2c.h>
38453 +#include <linux/i2c-gpio.h>
38454 +
38455 +#include <asm/ubicom32sd.h>
38456 +#include <asm/sd_tio.h>
38457 +
38458 +#include <asm/ubicom32bl.h>
38459 +
38460 +#include <asm/machdep.h>
38461 +
38462 +/******************************************************************************
38463 + * SD/IO Port F (Slot 1) platform data
38464 + */
38465 +static struct resource ip7500iap_portf_sd_resources[] = {
38466 +       /*
38467 +        * Send IRQ
38468 +        */
38469 +       [0] = {
38470 +               /*
38471 +                * The init routine will query the devtree and fill this in
38472 +                */
38473 +               .flags  = IORESOURCE_IRQ,
38474 +       },
38475 +
38476 +       /*
38477 +        * Receive IRQ
38478 +        */
38479 +       [1] = {
38480 +               /*
38481 +                * The init routine will query the devtree and fill this in
38482 +                */
38483 +               .flags  = IORESOURCE_IRQ,
38484 +       },
38485 +
38486 +       /*
38487 +        * Memory Mapped Registers
38488 +        */
38489 +       [2] = {
38490 +               /*
38491 +                * The init routine will query the devtree and fill this in
38492 +                */
38493 +               .flags  = IORESOURCE_MEM,
38494 +       },
38495 +};
38496 +
38497 +static struct ubicom32sd_card ip7500iap_portf_sd_cards[] = {
38498 +       [0] = {
38499 +               .pin_wp         = GPIO_RF_7,
38500 +               .wp_polarity    = 1,
38501 +               .pin_pwr        = GPIO_RF_8,
38502 +               .pin_cd         = GPIO_RF_6,
38503 +       },
38504 +};
38505 +
38506 +static struct ubicom32sd_platform_data ip7500iap_portf_sd_platform_data = {
38507 +       .ncards         = 1,
38508 +       .cards          = ip7500iap_portf_sd_cards,
38509 +};
38510 +
38511 +static struct platform_device ip7500iap_portf_sd_device = {
38512 +       .name           = "ubicom32sd",
38513 +       .id             = 0,
38514 +       .resource       = ip7500iap_portf_sd_resources,
38515 +       .num_resources  = ARRAY_SIZE(ip7500iap_portf_sd_resources),
38516 +       .dev            = {
38517 +                       .platform_data = &ip7500iap_portf_sd_platform_data,
38518 +       },
38519 +
38520 +};
38521 +
38522 +/*
38523 + * ip7500iap_portf_sd_init
38524 + */
38525 +static void ip7500iap_portf_sd_init(void)
38526 +{
38527 +       /*
38528 +        * Check the device tree for the sd_tio
38529 +        */
38530 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
38531 +       if (!sd_node) {
38532 +               printk(KERN_INFO "PortF SDTIO not found\n");
38533 +               return;
38534 +       }
38535 +
38536 +       /*
38537 +        * Fill in the resources and platform data from devtree information
38538 +        */
38539 +       ip7500iap_portf_sd_resources[0].start = sd_node->dn.sendirq;
38540 +       ip7500iap_portf_sd_resources[1].start = sd_node->dn.recvirq;
38541 +       ip7500iap_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
38542 +       ip7500iap_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38543 +
38544 +       platform_device_register(&ip7500iap_portf_sd_device);
38545 +}
38546 +
38547 +/******************************************************************************
38548 + * SD/IO Port B (Slot 2) platform data
38549 + */
38550 +static struct resource ip7500iap_portb_sd_resources[] = {
38551 +       /*
38552 +        * Send IRQ
38553 +        */
38554 +       [0] = {
38555 +               /*
38556 +                * The init routine will query the devtree and fill this in
38557 +                */
38558 +               .flags  = IORESOURCE_IRQ,
38559 +       },
38560 +
38561 +       /*
38562 +        * Receive IRQ
38563 +        */
38564 +       [1] = {
38565 +               /*
38566 +                * The init routine will query the devtree and fill this in
38567 +                */
38568 +               .flags  = IORESOURCE_IRQ,
38569 +       },
38570 +
38571 +       /*
38572 +        * Memory Mapped Registers
38573 +        */
38574 +       [2] = {
38575 +               /*
38576 +                * The init routine will query the devtree and fill this in
38577 +                */
38578 +               .flags  = IORESOURCE_MEM,
38579 +       },
38580 +};
38581 +
38582 +static struct ubicom32sd_card ip7500iap_portb_sd_cards[] = {
38583 +       [0] = {
38584 +               .pin_wp         = GPIO_RB_13,
38585 +               .wp_polarity    = 1,
38586 +               .pin_pwr        = GPIO_RB_11,
38587 +               .pin_cd         = GPIO_RB_12,
38588 +       },
38589 +};
38590 +
38591 +static struct ubicom32sd_platform_data ip7500iap_portb_sd_platform_data = {
38592 +       .ncards         = 1,
38593 +       .cards          = ip7500iap_portb_sd_cards,
38594 +};
38595 +
38596 +static struct platform_device ip7500iap_portb_sd_device = {
38597 +       .name           = "ubicom32sd",
38598 +       .id             = 1,
38599 +       .resource       = ip7500iap_portb_sd_resources,
38600 +       .num_resources  = ARRAY_SIZE(ip7500iap_portb_sd_resources),
38601 +       .dev            = {
38602 +                       .platform_data = &ip7500iap_portb_sd_platform_data,
38603 +       },
38604 +
38605 +};
38606 +
38607 +/*
38608 + * ip7500iap_portb_sd_init
38609 + */
38610 +static void ip7500iap_portb_sd_init(void)
38611 +{
38612 +       /*
38613 +        * Check the device tree for the sd_tio
38614 +        */
38615 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
38616 +       if (!sd_node) {
38617 +               printk(KERN_INFO "PortB SDTIO not found\n");
38618 +               return;
38619 +       }
38620 +
38621 +       /*
38622 +        * Fill in the resources and platform data from devtree information
38623 +        */
38624 +       ip7500iap_portb_sd_resources[0].start = sd_node->dn.sendirq;
38625 +       ip7500iap_portb_sd_resources[1].start = sd_node->dn.recvirq;
38626 +       ip7500iap_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
38627 +       ip7500iap_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38628 +
38629 +       platform_device_register(&ip7500iap_portb_sd_device);
38630 +}
38631 +
38632 +/******************************************************************************
38633 + * Touch controller
38634 + *
38635 + * Connected via I2C bus, interrupt on PA6
38636 + */
38637 +#include <linux/i2c/tsc2007.h>
38638 +
38639 +/*
38640 + * ip7500iap_tsc2007_exit_platform_hw
38641 + */
38642 +static void ip7500iap_tsc2007_exit_platform_hw(void)
38643 +{
38644 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38645 +       gpio_free(GPIO_RA_6);
38646 +}
38647 +
38648 +/*
38649 + * ip7500iap_tsc2007_init_platform_hw
38650 + */
38651 +static int ip7500iap_tsc2007_init_platform_hw(void)
38652 +{
38653 +       int res = gpio_request(GPIO_RA_6, "TSC2007_IRQ");
38654 +       if (res) {
38655 +               return res;
38656 +       }
38657 +
38658 +       UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38659 +       UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 19);
38660 +       return 0;
38661 +}
38662 +
38663 +/*
38664 + * ip7500iap_tsc2007_get_pendown_state
38665 + */
38666 +static int ip7500iap_tsc2007_get_pendown_state(void)
38667 +{
38668 +       return !gpio_get_value(GPIO_RA_6);
38669 +}
38670 +
38671 +static struct tsc2007_platform_data ip7500iap_tsc2007_data = {
38672 +       .model                  = 2007,
38673 +       .x_plate_ohms           = 350,
38674 +       .get_pendown_state      = ip7500iap_tsc2007_get_pendown_state,
38675 +       .init_platform_hw       = ip7500iap_tsc2007_init_platform_hw,
38676 +       .exit_platform_hw       = ip7500iap_tsc2007_exit_platform_hw,
38677 +};
38678 +
38679 +/******************************************************************************
38680 + * i2c devices
38681 + *
38682 + * DO NOT CHANGE THE ORDER HERE unless you know how this works.  There
38683 + * are hardcoded indicies which refer to the order of drivers listed here.
38684 + */
38685 +static struct i2c_board_info __initdata ip7500iap_i2c_board_info[] = {
38686 +       /*
38687 +        * U6, CS4350 DAC, address 0x4B
38688 +        */
38689 +       {
38690 +               .type           = "cs4350",
38691 +               .addr           = 0x4B,
38692 +       },
38693 +
38694 +       /*
38695 +        * U20, S35390A RTC, address 0x30
38696 +        */
38697 +       {
38698 +               .type           = "s35390a",
38699 +               .addr           = 0x30,
38700 +       },
38701 +
38702 +       /*
38703 +        * U9, TSC2007 Touch screen controller, address 0x49, irq RA6
38704 +        */
38705 +       {
38706 +               .type           = "tsc2007",
38707 +               .addr           = 0x49,
38708 +               .irq            = 46,
38709 +               .platform_data  = &ip7500iap_tsc2007_data,
38710 +       },
38711 +};
38712 +
38713 +/*
38714 + * I2C bus on the board, SDA PE4, SCL PE5
38715 + */
38716 +static struct i2c_gpio_platform_data ip7500iap_i2c_data = {
38717 +       .sda_pin                = GPIO_RF_14,
38718 +       .scl_pin                = GPIO_RF_13,
38719 +       .sda_is_open_drain      = 0,
38720 +       .scl_is_open_drain      = 0,
38721 +       .udelay                 = 50,
38722 +};
38723 +
38724 +static struct platform_device ip7500iap_i2c_device = {
38725 +       .name   = "i2c-gpio",
38726 +       .id     = 0,
38727 +       .dev    = {
38728 +               .platform_data = &ip7500iap_i2c_data,
38729 +       },
38730 +};
38731 +
38732 +/******************************************************************************
38733 + * Backlight on the board PD0, hardware PWM
38734 + */
38735 +static struct ubicom32bl_platform_data ip7500iap_backlight_data = {
38736 +       .type                   = UBICOM32BL_TYPE_PWM,
38737 +       .pwm_channel            = 2,
38738 +       .pwm_prescale           = 15,
38739 +       .pwm_period             = 60,
38740 +       .default_intensity      = 0x80,
38741 +};
38742 +
38743 +static struct platform_device ip7500iap_backlight_device = {
38744 +       .name   = "ubicom32bl",
38745 +       .id     = -1,
38746 +       .dev    = {
38747 +               .platform_data = &ip7500iap_backlight_data,
38748 +       },
38749 +};
38750 +
38751 +/******************************************************************************
38752 + * Devices on this board
38753 + */
38754 +static struct platform_device *ip7500iap_devices[] __initdata = {
38755 +       &ip7500iap_i2c_device,
38756 +       &ip7500iap_backlight_device,
38757 +};
38758 +
38759 +/*
38760 + * ip7500iap_power_off
38761 + *     Called to turn the power off for this board
38762 + */
38763 +static void ip7500iap_power_off(void)
38764 +{
38765 +       gpio_set_value(GPIO_RF_11, 0);
38766 +}
38767 +
38768 +/*
38769 + * ip7500iap_init
38770 + *     Called to add the devices which we have on this board
38771 + */
38772 +static int __init ip7500iap_init(void)
38773 +{
38774 +       struct platform_device *audio_dev;
38775 +       struct platform_device *audio_dev2;
38776 +       int ret;
38777 +
38778 +       board_init();
38779 +
38780 +       ubi_gpio_init();
38781 +
38782 +       /*
38783 +        * Hold the POWER_HOLD line
38784 +        */
38785 +       ret = gpio_request(GPIO_RF_11, "POWER_HOLD");
38786 +       if (ret) {
38787 +               printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
38788 +       }
38789 +       gpio_direction_output(GPIO_RF_11, 1);
38790 +       mach_power_off = ip7500iap_power_off;
38791 +
38792 +       /*
38793 +        * DAC nRESET line
38794 +        */
38795 +       ret = gpio_request(GPIO_RE_7, "DAC_nRESET");
38796 +       if (ret) {
38797 +               printk(KERN_ERR "%s: could not request DAC_nRESET GPIO\n", __FUNCTION__);
38798 +       }
38799 +       gpio_direction_output(GPIO_RE_7, 0);
38800 +       udelay(1);
38801 +       gpio_set_value(GPIO_RE_7, 1);
38802 +
38803 +       /*
38804 +        * Bring up any SDIO slots
38805 +        */
38806 +       ip7500iap_portb_sd_init();
38807 +       ip7500iap_portf_sd_init();
38808 +
38809 +       /*
38810 +        * Bring up audio devices
38811 +        */
38812 +       platform_add_devices(ip7500iap_devices, ARRAY_SIZE(ip7500iap_devices));
38813 +
38814 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
38815 +       if (audio_dev) {
38816 +               ip7500iap_i2c_board_info[0].platform_data = audio_dev;
38817 +       }
38818 +
38819 +       audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
38820 +       if (audio_dev2) {
38821 +               platform_device_register(audio_dev2);
38822 +       }
38823 +
38824 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38825 +       i2c_register_board_info(0, ip7500iap_i2c_board_info, ARRAY_SIZE(ip7500iap_i2c_board_info));
38826 +
38827 +       printk(KERN_INFO "IP7500 Internet Audio Player\n");
38828 +
38829 +       return 0;
38830 +}
38831 +
38832 +arch_initcall(ip7500iap_init);
38833 --- /dev/null
38834 +++ b/arch/ubicom32/mach-ip7k/board-ip7500media.c
38835 @@ -0,0 +1,732 @@
38836 +/*
38837 + * arch/ubicom32/mach-ip7k/board-ip7500media.c
38838 + *   Board file for IP7500 media board.
38839 + *
38840 + * Supports the following configuration
38841 + *     CPU Module:
38842 + *             P/N 8007-0510 rev 1.0 NOPHY
38843 + *             P/N 8007-0511 rev 1.1 NOPHY
38844 + *                     DIP Switch SW2 configuration:
38845 + *                             POS 1: on  = PCI enabled
38846 + *                             POS 2: off = TTYX => PF12
38847 + *                             POS 3: off = TTYY => PF15
38848 + *                             POS 4: unused
38849 + *     Media Board:
38850 + *             P/N 8007-0610 rev 1.0
38851 + *
38852 + *     LCD Adapter Board: (optional)
38853 + *             P/N 8007-0920 rev 2.0
38854 + *             P/N 8007-0921 rev 2.1
38855 + *
38856 + * (C) Copyright 2009, Ubicom, Inc.
38857 + *
38858 + * This file is part of the Ubicom32 Linux Kernel Port.
38859 + *
38860 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38861 + * it and/or modify it under the terms of the GNU General Public License
38862 + * as published by the Free Software Foundation, either version 2 of the
38863 + * License, or (at your option) any later version.
38864 + *
38865 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38866 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38867 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
38868 + * the GNU General Public License for more details.
38869 + *
38870 + * You should have received a copy of the GNU General Public License
38871 + * along with the Ubicom32 Linux Kernel Port.  If not,
38872 + * see <http://www.gnu.org/licenses/>.
38873 + *
38874 + * Ubicom32 implementation derived from (with many thanks):
38875 + *   arch/m68knommu
38876 + *   arch/blackfin
38877 + *   arch/parisc
38878 + */
38879 +#include <linux/device.h>
38880 +#include <linux/platform_device.h>
38881 +#include <linux/gpio.h>
38882 +
38883 +#include <linux/input.h>
38884 +
38885 +#include <linux/i2c.h>
38886 +#include <linux/i2c-gpio.h>
38887 +#include <linux/i2c/pca953x.h>
38888 +
38889 +#include <asm/board.h>
38890 +#include <asm/machdep.h>
38891 +#include <asm/ubicom32input_i2c.h>
38892 +#include <asm/ubicom32bl.h>
38893 +#include <asm/ubicom32lcdpower.h>
38894 +#include <asm/vdc_tio.h>
38895 +
38896 +#include <asm/ubicom32sd.h>
38897 +#include <asm/sd_tio.h>
38898 +#include <asm/devtree.h>
38899 +#include <asm/audio.h>
38900 +
38901 +#include <asm/ring_tio.h>
38902 +
38903 +/******************************************************************************
38904 + * SD/IO Port F (Slot 1) platform data
38905 + */
38906 +static struct resource ip7500media_portf_sd_resources[] = {
38907 +       /*
38908 +        * Send IRQ
38909 +        */
38910 +       [0] = {
38911 +               /*
38912 +                * The init routine will query the devtree and fill this in
38913 +                */
38914 +               .flags  = IORESOURCE_IRQ,
38915 +       },
38916 +
38917 +       /*
38918 +        * Receive IRQ
38919 +        */
38920 +       [1] = {
38921 +               /*
38922 +                * The init routine will query the devtree and fill this in
38923 +                */
38924 +               .flags  = IORESOURCE_IRQ,
38925 +       },
38926 +
38927 +       /*
38928 +        * Memory Mapped Registers
38929 +        */
38930 +       [2] = {
38931 +               /*
38932 +                * The init routine will query the devtree and fill this in
38933 +                */
38934 +               .flags  = IORESOURCE_MEM,
38935 +       },
38936 +};
38937 +
38938 +static struct ubicom32sd_card ip7500media_portf_sd_cards[] = {
38939 +       [0] = {
38940 +               .pin_wp         = IP7500MEDIA_IO16,
38941 +               .wp_polarity    = 1,
38942 +               .pin_pwr        = IP7500MEDIA_IO20,
38943 +               .pin_cd         = IP7500MEDIA_IO23,
38944 +       },
38945 +       [1] = {
38946 +               .pin_wp         = IP7500MEDIA_IO17,
38947 +               .wp_polarity    = 1,
38948 +               .pin_pwr        = IP7500MEDIA_IO21,
38949 +               .pin_cd         = IP7500MEDIA_IO24,
38950 +       },
38951 +};
38952 +
38953 +static struct ubicom32sd_platform_data ip7500media_portf_sd_platform_data = {
38954 +       .ncards         = 2,
38955 +       .cards          = ip7500media_portf_sd_cards,
38956 +};
38957 +
38958 +static struct platform_device ip7500media_portf_sd_device = {
38959 +       .name           = "ubicom32sd",
38960 +       .id             = 0,
38961 +       .resource       = ip7500media_portf_sd_resources,
38962 +       .num_resources  = ARRAY_SIZE(ip7500media_portf_sd_resources),
38963 +       .dev            = {
38964 +                       .platform_data = &ip7500media_portf_sd_platform_data,
38965 +       },
38966 +
38967 +};
38968 +
38969 +/*
38970 + * ip7500media_portf_sd_init
38971 + */
38972 +static void ip7500media_portf_sd_init(void)
38973 +{
38974 +       /*
38975 +        * Check the device tree for the sd_tio
38976 +        */
38977 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
38978 +       if (!sd_node) {
38979 +               printk(KERN_INFO "PortF SDTIO not found\n");
38980 +               return;
38981 +       }
38982 +
38983 +       /*
38984 +        * Fill in the resources and platform data from devtree information
38985 +        */
38986 +       ip7500media_portf_sd_resources[0].start = sd_node->dn.sendirq;
38987 +       ip7500media_portf_sd_resources[1].start = sd_node->dn.recvirq;
38988 +       ip7500media_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
38989 +       ip7500media_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38990 +
38991 +       platform_device_register(&ip7500media_portf_sd_device);
38992 +}
38993 +
38994 +/******************************************************************************
38995 + * SD/IO Port B (Slot 2) platform data
38996 + */
38997 +static struct resource ip7500media_portb_sd_resources[] = {
38998 +       /*
38999 +        * Send IRQ
39000 +        */
39001 +       [0] = {
39002 +               /*
39003 +                * The init routine will query the devtree and fill this in
39004 +                */
39005 +               .flags  = IORESOURCE_IRQ,
39006 +       },
39007 +
39008 +       /*
39009 +        * Receive IRQ
39010 +        */
39011 +       [1] = {
39012 +               /*
39013 +                * The init routine will query the devtree and fill this in
39014 +                */
39015 +               .flags  = IORESOURCE_IRQ,
39016 +       },
39017 +
39018 +       /*
39019 +        * Memory Mapped Registers
39020 +        */
39021 +       [2] = {
39022 +               /*
39023 +                * The init routine will query the devtree and fill this in
39024 +                */
39025 +               .flags  = IORESOURCE_MEM,
39026 +       },
39027 +};
39028 +
39029 +static struct ubicom32sd_card ip7500media_portb_sd_cards[] = {
39030 +       [0] = {
39031 +               .pin_wp         = IP7500MEDIA_IO19,
39032 +               .wp_polarity    = 1,
39033 +               .pin_pwr        = IP7500MEDIA_IO22,
39034 +               .pin_cd         = IP7500MEDIA_IO18,
39035 +       },
39036 +};
39037 +
39038 +static struct ubicom32sd_platform_data ip7500media_portb_sd_platform_data = {
39039 +       .ncards         = 1,
39040 +       .cards          = ip7500media_portb_sd_cards,
39041 +};
39042 +
39043 +static struct platform_device ip7500media_portb_sd_device = {
39044 +       .name           = "ubicom32sd",
39045 +       .id             = 1,
39046 +       .resource       = ip7500media_portb_sd_resources,
39047 +       .num_resources  = ARRAY_SIZE(ip7500media_portb_sd_resources),
39048 +       .dev            = {
39049 +                       .platform_data = &ip7500media_portb_sd_platform_data,
39050 +       },
39051 +
39052 +};
39053 +
39054 +/*
39055 + * ip7500media_portb_sd_init
39056 + */
39057 +static void ip7500media_portb_sd_init(void)
39058 +{
39059 +       /*
39060 +        * Check the device tree for the sd_tio
39061 +        */
39062 +       struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
39063 +       if (!sd_node) {
39064 +               printk(KERN_INFO "PortB SDTIO not found\n");
39065 +               return;
39066 +       }
39067 +
39068 +       /*
39069 +        * Fill in the resources and platform data from devtree information
39070 +        */
39071 +       ip7500media_portb_sd_resources[0].start = sd_node->dn.sendirq;
39072 +       ip7500media_portb_sd_resources[1].start = sd_node->dn.recvirq;
39073 +       ip7500media_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
39074 +       ip7500media_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
39075 +
39076 +       platform_device_register(&ip7500media_portb_sd_device);
39077 +}
39078 +
39079 +/*
39080 + * ip7500media_u17_setup
39081 + *     Called by I2C to tell us that u17 is setup.
39082 + *
39083 + * This function is called by I2C to tell us that u17 has been setup.  All
39084 + * devices which rely on this chip being initialized (or even present) need to
39085 + * be initialized in this function otherwise they may get initialized too early.
39086 + *
39087 + * Currently the only device depending on u17 is the SDIO
39088 + */
39089 +static int __init ip7500media_u17_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
39090 +{
39091 +       /*
39092 +        * Initialize the Port F/Port B SD slots (only the enabled ports will init)
39093 +        */
39094 +       ip7500media_portf_sd_init();
39095 +       ip7500media_portb_sd_init();
39096 +
39097 +       return 0;
39098 +}
39099 +
39100 +/******************************************************************************
39101 + * LCD VGH on the board at PE6
39102 + */
39103 +static struct ubicom32lcdpower_platform_data ip7500media_lcdpower_data = {
39104 +       .vgh_gpio               = GPIO_RE_7,
39105 +       .vgh_polarity           = true,
39106 +};
39107 +
39108 +static struct platform_device ip7500media_lcdpower_device = {
39109 +       .name   = "ubicom32lcdpower",
39110 +       .id     = -1,
39111 +       .dev    = {
39112 +               .platform_data = &ip7500media_lcdpower_data,
39113 +       },
39114 +};
39115 +
39116 +/******************************************************************************
39117 + * Backlight on the board PD0, hardware PWM
39118 + */
39119 +static struct ubicom32bl_platform_data ip7500media_backlight_data = {
39120 +       .type                   = UBICOM32BL_TYPE_PWM,
39121 +       .pwm_channel            = 2,
39122 +       .pwm_prescale           = 15,
39123 +       .pwm_period             = 60,
39124 +       .default_intensity      = 0x80,
39125 +};
39126 +
39127 +static struct platform_device ip7500media_backlight_device = {
39128 +       .name   = "ubicom32bl",
39129 +       .id     = -1,
39130 +       .dev    = {
39131 +               .platform_data = &ip7500media_backlight_data,
39132 +       },
39133 +};
39134 +
39135 +/******************************************************************************
39136 + * Ubicom32Input on I2C, U15 MAX7310, address 0x18, 8 bits
39137 + */
39138 +static struct ubicom32input_i2c_button ip7500media_ubicom32input_i2c_u15_buttons[] = {
39139 +       {
39140 +               .type           = EV_KEY,
39141 +               .code           = KEY_LEFT,
39142 +               .bit            = 0,
39143 +               .active_low     = 1,
39144 +       },
39145 +       {
39146 +               .type           = EV_KEY,
39147 +               .code           = KEY_RIGHT,
39148 +               .bit            = 1,
39149 +               .active_low     = 1,
39150 +       },
39151 +       {
39152 +               .type           = EV_KEY,
39153 +               .code           = KEY_UP,
39154 +               .bit            = 2,
39155 +               .active_low     = 1,
39156 +       },
39157 +       {
39158 +               .type           = EV_KEY,
39159 +               .code           = KEY_DOWN,
39160 +               .bit            = 3,
39161 +               .active_low     = 1,
39162 +       },
39163 +       {
39164 +               .type           = EV_KEY,
39165 +               .code           = KEY_ENTER,
39166 +               .bit            = 4,
39167 +               .active_low     = 1,
39168 +       },
39169 +       {
39170 +               .type           = EV_KEY,
39171 +               .code           = KEY_MENU,
39172 +               .bit            = 5,
39173 +               .active_low     = 1,
39174 +       },
39175 +       {
39176 +               .type           = EV_KEY,
39177 +               .code           = KEY_ESC,
39178 +               .bit            = 6,
39179 +               .active_low     = 1,
39180 +       },
39181 +};
39182 +
39183 +static struct ubicom32input_i2c_platform_data ip7500media_ubicom32input_i2c_u15_platform_data = {
39184 +       .buttons        = ip7500media_ubicom32input_i2c_u15_buttons,
39185 +       .nbuttons       = ARRAY_SIZE(ip7500media_ubicom32input_i2c_u15_buttons),
39186 +       .name           = "Ubicom32 Input I2C U15",
39187 +};
39188 +
39189 +/******************************************************************************
39190 + * Additional GPIO chips
39191 + */
39192 +static struct pca953x_platform_data ip7500media_gpio_u16_platform_data = {
39193 +       .gpio_base = IP7500MEDIA_U16_BASE,
39194 +};
39195 +
39196 +static struct pca953x_platform_data ip7500media_gpio_u17_platform_data = {
39197 +       .gpio_base = IP7500MEDIA_U17_BASE,
39198 +       .setup = ip7500media_u17_setup,
39199 +};
39200 +
39201 +static struct pca953x_platform_data ip7500media_gpio_u18_platform_data = {
39202 +       .gpio_base = IP7500MEDIA_U18_BASE,
39203 +};
39204 +
39205 +
39206 +/******************************************************************************
39207 + * Touch controller present on LCD Adapter board
39208 + *
39209 + * Connected via I2C bus, interrupt on PD1
39210 + */
39211 +#include <linux/i2c/tsc2007.h>
39212 +
39213 +/*
39214 + * ip7500media_tsc2007_exit_platform_hw
39215 + */
39216 +static void ip7500media_tsc2007_exit_platform_hw(void)
39217 +{
39218 +       UBICOM32_IO_PORT(RD)->int_mask &= ~(1 << 11);
39219 +       UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39220 +       gpio_free(GPIO_RD_1);
39221 +}
39222 +
39223 +/*
39224 + * ip7500media_tsc2007_init_platform_hw
39225 + */
39226 +static int ip7500media_tsc2007_init_platform_hw(void)
39227 +{
39228 +       int res = gpio_request(GPIO_RD_1, "TSC2007_IRQ");
39229 +       if (res) {
39230 +               return res;
39231 +       }
39232 +       UBICOM32_IO_PORT(RD)->function = 0;
39233 +       UBICOM32_IO_PORT(RD)->int_mask = (1 << 11);
39234 +       UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39235 +       UBICOM32_IO_PORT(RD)->ctl2 |= (0x02 << 16);
39236 +
39237 +       return 0;
39238 +}
39239 +
39240 +/*
39241 + * ip7500media_tsc2007_clear_penirq
39242 + */
39243 +static void ip7500media_tsc2007_clear_penirq(void)
39244 +{
39245 +       UBICOM32_IO_PORT(RD)->int_clr = (1 << 11);
39246 +}
39247 +
39248 +/*
39249 + * ip7500media_tsc2007_get_pendown_state
39250 + */
39251 +static int ip7500media_tsc2007_get_pendown_state(void)
39252 +{
39253 +       return !gpio_get_value(GPIO_RD_1);
39254 +}
39255 +
39256 +static struct tsc2007_platform_data ip7500media_tsc2007_data = {
39257 +       .model                  = 2007,
39258 +       .x_plate_ohms           = 350,
39259 +       .get_pendown_state      = ip7500media_tsc2007_get_pendown_state,
39260 +       .init_platform_hw       = ip7500media_tsc2007_init_platform_hw,
39261 +       .exit_platform_hw       = ip7500media_tsc2007_exit_platform_hw,
39262 +       .clear_penirq           = ip7500media_tsc2007_clear_penirq,
39263 +};
39264 +
39265 +/******************************************************************************
39266 + * Devices on the I2C bus
39267 + *
39268 + * BEWARE of changing the order of things in this array as we depend on
39269 + * certain things to be in certain places.
39270 + */
39271 +static struct i2c_board_info __initdata ip7500media_i2c_board_info[] = {
39272 +       /*
39273 +        * U6, CS4350 DAC, address 0x4B
39274 +        */
39275 +       {
39276 +               .type           = "cs4350",
39277 +               .addr           = 0x4B,
39278 +       },
39279 +
39280 +       /*
39281 +        * U14, S35390A RTC, address 0x30
39282 +        */
39283 +       {
39284 +               .type           = "s35390a",
39285 +               .addr           = 0x30,
39286 +       },
39287 +
39288 +       /*
39289 +        * U15, MAX7310 IO expander, 8 bits, address 0x18
39290 +        *      IO0: User I/O (J16-1) (Left)    IO4: User I/O (J16-5) (Enter)
39291 +        *      IO1: User I/O (J16-2) (Right)   IO5: User I/O (J16-6) (Menu)
39292 +        *      IO2: User I/O (J16-3) (Up)      IO6: User I/O (J16-7) (Back)
39293 +        *      IO3: User I/O (J16-4) (Down)    IO7: User I/O (J16-8)
39294 +        */
39295 +       {
39296 +               .type           = "ubicom32in_max7310",
39297 +               .addr           = 0x18,
39298 +               .platform_data  = &ip7500media_ubicom32input_i2c_u15_platform_data,
39299 +       },
39300 +
39301 +       /*
39302 +        * U16, MAX7310 IO expander, 8 bits, address 0x1C
39303 +        *      IO8 : User I/O (J16-9)          IO12: User I/O (J16-17)
39304 +        *      IO9 : User I/O (J16-10)         IO13: User I/O (J16-18)
39305 +        *      IO10: User I/O (J16-15)         IO14: User I/O (J16-19)
39306 +        *      IO11: User I/O (J16-16)         IO15: User I/O (J16-20)
39307 +        */
39308 +       {
39309 +               .type           = "max7310",
39310 +               .addr           = 0x1C,
39311 +               .platform_data  = &ip7500media_gpio_u16_platform_data,
39312 +       },
39313 +
39314 +       /*
39315 +        * U17, MAX7310 IO expander, 8 bits, address 0x1A
39316 +        *      IO16: SDIO1A_WP                 IO20: SD1A_PWREN
39317 +        *      IO17: SDIO1B_WP                 IO21: SD1B_PWREN
39318 +        *      IO18: SDIO2_CD                  IO22: SD2_PWREN
39319 +        *      IO19: SDIO2_WP                  IO23: SDIO1A_CD
39320 +        *
39321 +        */
39322 +       {
39323 +               .type           = "max7310",
39324 +               .addr           = 0x1A,
39325 +               .platform_data  = &ip7500media_gpio_u17_platform_data,
39326 +       },
39327 +
39328 +       /*
39329 +        * U18, MAX7310 IOB expander, 8 bits, address 0x1E
39330 +        *      IO24: SDIO1B_CD                 IO28: User I/O TP6
39331 +        *      IO25: User I/O TP9              IO29: User I/O TP5
39332 +        *      IO26: User I/O TP8              IO30: User I/O TP4
39333 +        *      IO27: User I/O TP7              IO31: User I/O TP3
39334 +        */
39335 +       {
39336 +               .type           = "max7310",
39337 +               .addr           = 0x1E,
39338 +               .platform_data  = &ip7500media_gpio_u18_platform_data,
39339 +       },
39340 +};
39341 +
39342 +/*
39343 + * Additional I2C devices to add when a LCD adapter board is present
39344 + */
39345 +static struct i2c_board_info __initdata ip7500media_lcd_adapter_i2c_board_info[] = {
39346 +       {
39347 +               I2C_BOARD_INFO("tsc2007", 0x48),
39348 +               .irq = PORT_OTHER_INT(RD),
39349 +               .platform_data = &ip7500media_tsc2007_data,
39350 +       },
39351 +};
39352 +
39353 +/*
39354 + * I2C bus on the board, SDA PE4, SCL PE5
39355 + */
39356 +static struct i2c_gpio_platform_data ip7500media_i2c_data = {
39357 +       .sda_pin                = GPIO_RE_4,
39358 +       .scl_pin                = GPIO_RE_5,
39359 +       .sda_is_open_drain      = 0,
39360 +       .scl_is_open_drain      = 0,
39361 +       .udelay                 = 50,
39362 +};
39363 +
39364 +static struct platform_device ip7500media_i2c_device = {
39365 +       .name   = "i2c-gpio",
39366 +       .id     = 0,
39367 +       .dev    = {
39368 +               .platform_data = &ip7500media_i2c_data,
39369 +       },
39370 +};
39371 +
39372 +/*
39373 + * Virtual Frame Buffer device for use with LCD Adapter
39374 + */
39375 +static struct platform_device ip7500media_vfb_device = {
39376 +       .name   = "ubicom32vfb",
39377 +       .id     = -1,
39378 +};
39379 +
39380 +/*
39381 + * vdc_override:
39382 + *     0: no override (auto-detect)
39383 + *     1: force vdc usage
39384 + *     2: force lcd adapter usage
39385 + */
39386 +static int __initdata vdc_override = 0;
39387 +
39388 +/*
39389 + * ip7500media_set_forcevdc
39390 + *     Called when forcevdc is present on the kernel boot line
39391 + */
39392 +static int __init ip7500media_set_forcevdc(char *str)
39393 +{
39394 +       if (str[0] == '1') {
39395 +               vdc_override = 1;
39396 +       } else {
39397 +               vdc_override = 2;
39398 +       }
39399 +       return 1;
39400 +}
39401 +
39402 +/*
39403 + * ip7500media_video_init
39404 + *     Called late to determine what kind of video we have on this board
39405 + */
39406 +static int __init ip7500media_video_init(void)
39407 +{
39408 +       struct i2c_adapter *adap;
39409 +       struct i2c_msg msg[1];
39410 +       unsigned char *data;
39411 +       unsigned char checksum;
39412 +       int err;
39413 +       int i;
39414 +
39415 +       if (vdc_override == 1) {
39416 +               printk(KERN_INFO "Force VDCTIO mode\n");
39417 +               goto no_adapter;
39418 +       }
39419 +       if (vdc_override == 2) {
39420 +               printk(KERN_INFO "Force LCD Adapter Board mode\n");
39421 +               return 0;
39422 +       }
39423 +
39424 +       /*
39425 +        * Check to see if there is an EEPROM out there.  If we see an
39426 +        * EEPROM then we will assume a LCD Adapter Board (8007-092x)
39427 +        * exists.
39428 +        */
39429 +       data = kmalloc(256, GFP_KERNEL);
39430 +       if (!data) {
39431 +               printk(KERN_WARNING "%s: Failed to allocate memory\n", __FUNCTION__);
39432 +               return -ENOMEM;
39433 +       }
39434 +
39435 +       adap = i2c_get_adapter(0);
39436 +       if (!adap) {
39437 +               printk(KERN_WARNING "%s: Failed to get i2c adapter\n", __FUNCTION__);
39438 +               kfree(data);
39439 +               return -ENODEV;
39440 +       }
39441 +       data[0] = 0;
39442 +       msg->addr = 0x50;
39443 +       msg->flags = 0;
39444 +       msg->len = 1;
39445 +       msg->buf = data;
39446 +       err = i2c_transfer(adap, msg, 1);
39447 +       if (err < 0) {
39448 +               goto no_adapter;
39449 +       }
39450 +
39451 +       msg->addr = 0x50;
39452 +       msg->flags = I2C_M_RD;
39453 +       msg->len = 256;
39454 +       msg->buf = data;
39455 +       err = i2c_transfer(adap, msg, 1);
39456 +       if (err < 0) {
39457 +               goto no_adapter;
39458 +       }
39459 +
39460 +       i2c_put_adapter(adap);
39461 +
39462 +       /*
39463 +        * Verify the checksum
39464 +        */
39465 +       checksum = 0xff;
39466 +       for (i = 0; i < 255; i++) {
39467 +               checksum ^= data[i];
39468 +       }
39469 +       if (checksum != data[255]) {
39470 +               printk(KERN_WARNING "%s: Checksum mismatch\n", __FUNCTION__);
39471 +       }
39472 +
39473 +       kfree(data);
39474 +
39475 +       /*
39476 +        * Bring up VFB
39477 +        */
39478 +       platform_device_register(&ip7500media_vfb_device);
39479 +
39480 +       /*
39481 +        * Add the i2c devices on the LCD Adapter board.  (We have to use i2c_new_device
39482 +        * since it's late in the boot process.)
39483 +        */
39484 +       printk(KERN_INFO "%s: registering LCD Adapter board i2c resources\n", __FUNCTION__);
39485 +       for (i = 0; i < ARRAY_SIZE(ip7500media_lcd_adapter_i2c_board_info); i++) {
39486 +               i2c_new_device(adap, &ip7500media_lcd_adapter_i2c_board_info[i]);
39487 +       }
39488 +
39489 +       i2c_put_adapter(adap);
39490 +
39491 +       return 0;
39492 +
39493 +       /*
39494 +        * No LCD Adapter board, bring up VDC
39495 +        */
39496 +no_adapter:
39497 +       vdc_tio_init();
39498 +       return 0;
39499 +}
39500 +late_initcall(ip7500media_video_init);
39501 +__setup("forcevdc=", ip7500media_set_forcevdc);
39502 +
39503 +/*
39504 + * ip7500media_init
39505 + *     Called to add the devices which we have on this board
39506 + */
39507 +static int __init ip7500media_init(void)
39508 +{
39509 +       struct platform_device *audio_dev;
39510 +       int have_ethernet = (devtree_find_node("eth_lan") != 0);
39511 +
39512 +       board_init();
39513 +
39514 +       ubi_gpio_init();
39515 +
39516 +#ifdef CONFIG_UIO_UBICOM32RING
39517 +       ring_tio_init("decoder_ring");
39518 +#endif
39519 +
39520 +       /*
39521 +        * Register all of the devices we have on this board
39522 +        */
39523 +       printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
39524 +       platform_device_register(&ip7500media_i2c_device);
39525 +       platform_device_register(&ip7500media_backlight_device);
39526 +
39527 +       /*
39528 +        * If ethernet doesn't exist then we can init the lcdpower
39529 +        */
39530 +       if (!have_ethernet) {
39531 +               platform_device_register(&ip7500media_lcdpower_device);
39532 +       }
39533 +
39534 +       /*
39535 +        * Allocate the audio drivers.  SPDIF not supported on boards with ethernet.
39536 +        */
39537 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39538 +       if (audio_dev) {
39539 +               ip7500media_i2c_board_info[0].platform_data = audio_dev;
39540 +       }
39541 +
39542 +       if (!have_ethernet) {
39543 +               struct platform_device *audio_dev2;
39544 +
39545 +               audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39546 +               if (audio_dev2) {
39547 +                       platform_device_register(audio_dev2);
39548 +               }
39549 +       }
39550 +
39551 +       /*
39552 +        * Register all of the devices which sit on the I2C bus
39553 +        */
39554 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39555 +       i2c_register_board_info(0, ip7500media_i2c_board_info, ARRAY_SIZE(ip7500media_i2c_board_info));
39556 +
39557 +       /*
39558 +        * We have to initialize the SDIO after the I2C IOB gets setup.  SDIO is initialized in
39559 +        * ip7500media_u17_setup
39560 +        */
39561 +
39562 +       printk("IP7500 Media Board\n");
39563 +
39564 +       return 0;
39565 +}
39566 +
39567 +arch_initcall(ip7500media_init);
39568 --- /dev/null
39569 +++ b/arch/ubicom32/mach-ip7k/board-ip7500module.c
39570 @@ -0,0 +1,55 @@
39571 +/*
39572 + * arch/ubicom32/mach-ip7k/board-ip7500module.c
39573 + *   Support for IP7500 CPU module board.
39574 + *
39575 + * This file supports the IP7500 CPU module board:
39576 + *     8007-0510  Rev 1.0
39577 + *     8007-0510A Rev 1.0 (with ethernet)
39578 + *
39579 + * DIP Switch SW2 configuration: (*) default
39580 + *     POS 1: on(*) = PCI enabled, off = PCI disabled
39581 + *     POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
39582 + *     POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
39583 + *     POS 4: unused
39584 + *
39585 + * (C) Copyright 2009, Ubicom, Inc.
39586 + *
39587 + * This file is part of the Ubicom32 Linux Kernel Port.
39588 + *
39589 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39590 + * it and/or modify it under the terms of the GNU General Public License
39591 + * as published by the Free Software Foundation, either version 2 of the
39592 + * License, or (at your option) any later version.
39593 + *
39594 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39595 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39596 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39597 + * the GNU General Public License for more details.
39598 + *
39599 + * You should have received a copy of the GNU General Public License
39600 + * along with the Ubicom32 Linux Kernel Port.  If not,
39601 + * see <http://www.gnu.org/licenses/>.
39602 + *
39603 + * Ubicom32 implementation derived from (with many thanks):
39604 + *   arch/m68knommu
39605 + *   arch/blackfin
39606 + *   arch/parisc
39607 + */
39608 +#include <linux/device.h>
39609 +#include <linux/gpio.h>
39610 +#include <asm/board.h>
39611 +
39612 +/*
39613 + * ip7500module_init
39614 + *     Called to add the devices which we have on this board
39615 + */
39616 +static int __init ip7500module_init(void)
39617 +{
39618 +       board_init();
39619 +
39620 +       ubi_gpio_init();
39621 +
39622 +       return 0;
39623 +}
39624 +
39625 +arch_initcall(ip7500module_init);
39626 --- /dev/null
39627 +++ b/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39628 @@ -0,0 +1,101 @@
39629 +/*
39630 + * arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39631 + *   Support for IP7500 Wireless Speaker board.
39632 + *
39633 + * This file supports the IP7500 Wireless Speaker board:
39634 + *     8007-1210  Rev 1.0
39635 + *
39636 + * (C) Copyright 2009, Ubicom, Inc.
39637 + *
39638 + * This file is part of the Ubicom32 Linux Kernel Port.
39639 + *
39640 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39641 + * it and/or modify it under the terms of the GNU General Public License
39642 + * as published by the Free Software Foundation, either version 2 of the
39643 + * License, or (at your option) any later version.
39644 + *
39645 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39646 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39647 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39648 + * the GNU General Public License for more details.
39649 + *
39650 + * You should have received a copy of the GNU General Public License
39651 + * along with the Ubicom32 Linux Kernel Port.  If not,
39652 + * see <http://www.gnu.org/licenses/>.
39653 + */
39654 +#include <linux/device.h>
39655 +#include <linux/gpio.h>
39656 +#include <asm/board.h>
39657 +
39658 +#include <linux/platform_device.h>
39659 +#include <asm/audio.h>
39660 +#include <linux/i2c.h>
39661 +#include <linux/i2c-gpio.h>
39662 +
39663 +static struct i2c_board_info __initdata ip7500wspkr_i2c_board_info[] = {
39664 +       /*
39665 +        * U6, CS4350 DAC, address 0x4B
39666 +        */
39667 +       {
39668 +               .type           = "cs4350",
39669 +               .addr           = 0x4B,
39670 +       },
39671 +};
39672 +
39673 +/*
39674 + * I2C bus on the board, SDA PE4, SCL PE5
39675 + */
39676 +static struct i2c_gpio_platform_data ip7500wspkr_i2c_data = {
39677 +       .sda_pin                = GPIO_RD_5,
39678 +       .scl_pin                = GPIO_RD_6,
39679 +       .sda_is_open_drain      = 0,
39680 +       .scl_is_open_drain      = 0,
39681 +       .udelay                 = 50,
39682 +};
39683 +
39684 +static struct platform_device ip7500wspkr_i2c_device = {
39685 +       .name   = "i2c-gpio",
39686 +       .id     = 0,
39687 +       .dev    = {
39688 +               .platform_data = &ip7500wspkr_i2c_data,
39689 +       },
39690 +};
39691 +
39692 +static struct platform_device *ip7500wspkr_devices[] __initdata = {
39693 +       &ip7500wspkr_i2c_device,
39694 +};
39695 +
39696 +/*
39697 + * ip7500wspkr_init
39698 + *     Called to add the devices which we have on this board
39699 + */
39700 +static int __init ip7500wspkr_init(void)
39701 +{
39702 +       struct platform_device *audio_dev;
39703 +       struct platform_device *audio_dev2;
39704 +
39705 +       board_init();
39706 +
39707 +       ubi_gpio_init();
39708 +
39709 +       platform_add_devices(ip7500wspkr_devices, ARRAY_SIZE(ip7500wspkr_devices));
39710 +
39711 +       audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39712 +       if (audio_dev) {
39713 +               ip7500wspkr_i2c_board_info[0].platform_data = audio_dev;
39714 +       }
39715 +
39716 +       audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39717 +       if (audio_dev2) {
39718 +               platform_device_register(audio_dev2);
39719 +       }
39720 +
39721 +       printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39722 +       i2c_register_board_info(0, ip7500wspkr_i2c_board_info, ARRAY_SIZE(ip7500wspkr_i2c_board_info));
39723 +
39724 +       printk(KERN_INFO "IP7500 Wireless Speaker Board\n");
39725 +
39726 +       return 0;
39727 +}
39728 +
39729 +arch_initcall(ip7500wspkr_init);
39730 --- /dev/null
39731 +++ b/arch/ubicom32/mach-ip7k/Kconfig
39732 @@ -0,0 +1,205 @@
39733 +config IP7145DPF
39734 +       bool "IP7145DPF"
39735 +       select UBICOM32_V4
39736 +       select UBICOM_INPUT
39737 +       select UBICOM_INPUT_I2C
39738 +       select RTC_CLASS
39739 +       select RTC_DRV_S35390A
39740 +       select I2C
39741 +       select I2C_GPIO
39742 +       select GPIO_PCA953X
39743 +       select FB
39744 +       select FB_UBICOM32
39745 +       select LCD_CLASS_DEVICE
39746 +       select LCD_UBICOM32POWER
39747 +       select BACKLIGHT_LCD_SUPPORT
39748 +       select BACKLIGHT_CLASS_DEVICE
39749 +       select BACKLIGHT_UBICOM32
39750 +       select SND_UBI32
39751 +       select MMC_UBICOM32
39752 +       select MMC
39753 +       select MMC_BLOCK
39754 +       help
39755 +               IP7145 Digital Picture Frame reference design, supports:
39756 +                       8007-0410 v1.0
39757 +
39758 +config IP7160RGW
39759 +       bool "IP7160RGW"
39760 +       select UBICOM32_V4
39761 +       select UBICOM_INPUT
39762 +       select NEW_LEDS
39763 +       select LEDS_CLASS
39764 +       select LEDS_GPIO
39765 +       select SPI
39766 +       select SPI_UBICOM32_GPIO
39767 +       select VLAN_8021Q
39768 +       select UBICOM_SWITCH
39769 +       select UBICOM_SWITCH_BCM539X
39770 +       help
39771 +               Ubicom IP7160 RGW Eval, supports:
39772 +                       8007-0110 v1.0
39773 +                       8007-0111 v1.1
39774 +                       8007-0112 v1.2
39775 +
39776 +config IP7160RGWLCD
39777 +       bool "IP7160RGWLCD"
39778 +       select UBICOM32_V4
39779 +       select UBICOM_INPUT
39780 +       select NEW_LEDS
39781 +       select LEDS_CLASS
39782 +       select LEDS_GPIO
39783 +       select SPI
39784 +       select SPI_UBICOM32_GPIO
39785 +       select VLAN_8021Q
39786 +       select UBICOM_SWITCH
39787 +       select UBICOM_SWITCH_BCM539X
39788 +       select INPUT_TOUCHSCREEN
39789 +       select TOUCHSCREEN_TSC2007
39790 +       select FB
39791 +       select FB_UBICOM32_VIRTUAL
39792 +       select I2C
39793 +       select I2C_GPIO
39794 +       help
39795 +               Ubicom IP7160 RGW Eval, supports:
39796 +                       8007-0112 v1.2 + 8007-1410 v1.0
39797 +
39798 +               With Ubicom LCD Adapter
39799 +                       8007-0920 v2.0
39800 +                       8007-0921 v2.1
39801 +
39802 +
39803 +config IP7160BRINGUP
39804 +       bool "IP7160BRINGUP"
39805 +       select UBICOM32_V4
39806 +       select NEW_LEDS
39807 +       select LEDS_CLASS
39808 +       select LEDS_GPIO
39809 +       help
39810 +               Ubicom IP7160 Bringup, supports:
39811 +                       8007-0010 v1.0
39812 +
39813 +config IP7160DPF
39814 +       bool "IP7160DPF"
39815 +       select UBICOM32_V4
39816 +       select I2C
39817 +       select I2C_GPIO
39818 +       select FB
39819 +       select FB_UBICOM32
39820 +       select BACKLIGHT_LCD_SUPPORT
39821 +       select BACKLIGHT_CLASS_DEVICE
39822 +       select SND_UBI32
39823 +       select SND_UBI32_AUDIO_CS4350
39824 +       select UBICOM_HID
39825 +       help
39826 +               IP7160 Digital Picture Frame board, supports:
39827 +                       8007-0211 Rev 1.1
39828 +
39829 +config IP7500MODULE
39830 +       bool "IP7500MODULE"
39831 +       select UBICOM32_V4
39832 +       help
39833 +               Ubicom IP7500 CPU Module board, supports:
39834 +                       8007-0510  v1.0
39835 +                       8007-0510A v1.0
39836 +
39837 +               Please see ip7500module.c for more details.
39838 +
39839 +config IP7500AV
39840 +       bool "IP7500AV"
39841 +       select UBICOM32_V4
39842 +       select I2C
39843 +       select I2C_GPIO
39844 +       select SND_UBI32
39845 +       select SND_UBI32_AUDIO_CS4384
39846 +       select FB
39847 +       select FB_UBICOM32
39848 +       help
39849 +               Ubicom IP7500 Audio Video board, supports:
39850 +                       8007-0810  v1.0
39851 +
39852 +               With Ubicom IP7500 CPU Module board:
39853 +                       8007-0510  v1.0 -or-
39854 +                       8007-0510A v1.0
39855 +
39856 +               Please see ip7500av.c for more details.
39857 +
39858 +config IP7500MEDIA
39859 +       bool "IP7500MEDIA"
39860 +       select UBICOM32_V4
39861 +       select UBICOM_INPUT_I2C
39862 +       select RTC_CLASS
39863 +       select RTC_DRV_S35390A
39864 +       select I2C
39865 +       select I2C_GPIO
39866 +       select GPIO_PCA953X
39867 +       select FB
39868 +       select FB_UBICOM32
39869 +       select FB_UBICOM32_VIRTUAL
39870 +       select FB_UBICOM32_VIRTUAL_NOAUTO
39871 +       select LCD_CLASS_DEVICE
39872 +       select LCD_UBICOM32POWER
39873 +       select BACKLIGHT_LCD_SUPPORT
39874 +       select BACKLIGHT_CLASS_DEVICE
39875 +       select BACKLIGHT_UBICOM32
39876 +       select INPUT_TOUCHSCREEN
39877 +       select TOUCHSCREEN_TSC2007
39878 +       select SOUND
39879 +       select SND
39880 +       select SND_UBI32
39881 +       select SND_UBI32_AUDIO_CS4350
39882 +       select MMC_UBICOM32
39883 +       select MMC
39884 +       select MMC_BLOCK
39885 +       help
39886 +               IP7500 Media Board w/ IP7500 CPU Module board, supports:
39887 +                       8007-0610 v1.0 w/ 8007-0510 v1.0
39888 +                       8007-0610 v1.0 w/ 8007-0510 v1.0 NOPHY
39889 +                       8007-0610 v1.0 w/ 8007-0511 v1.1 NOPHY
39890 +
39891 +               Also supports optional LCD Adapter board:
39892 +                       8006-0920 v2.0
39893 +                       8006-0921 v2.1
39894 +
39895 +               Please see ip7500media.c for more details.
39896 +
39897 +config IP7500WSPKR
39898 +       bool "IP7500WSPKR"
39899 +       select UBICOM32_V4
39900 +       select I2C
39901 +       select I2C_GPIO
39902 +       select SOUND
39903 +       select SND
39904 +       select SND_UBI32
39905 +       select SND_UBI32_AUDIO_CS4350
39906 +       help
39907 +               IP7500 Wireless Speaker Board, supports:
39908 +                       8007-1210 v1.0
39909 +
39910 +               Please see ip7500wspkr.c for more details.
39911 +
39912 +config IP7500IAP
39913 +       bool "IP7500IAP"
39914 +       select UBICOM32_V4
39915 +       select I2C
39916 +       select I2C_GPIO
39917 +       select FB
39918 +       select FB_UBICOM32_VIRTUAL
39919 +       select SOUND
39920 +       select SND
39921 +       select SND_UBI32
39922 +       select SND_UBI32_AUDIO_CS4350
39923 +       select RTC_CLASS
39924 +       select RTC_DRV_S35390A
39925 +       select INPUT_TOUCHSCREEN
39926 +       select TOUCHSCREEN_TSC2007
39927 +       select BACKLIGHT_LCD_SUPPORT
39928 +       select BACKLIGHT_CLASS_DEVICE
39929 +       select BACKLIGHT_UBICOM32
39930 +       help
39931 +               IP7500 Internet Audio Player, supports:
39932 +                       8007-1110 v1.0
39933 +
39934 +               Please see ip7500iap.c for more details.
39935 +
39936 +
39937 +               Please see ip7500media.c for more details.
39938 --- /dev/null
39939 +++ b/arch/ubicom32/mach-ip7k/Makefile
39940 @@ -0,0 +1,38 @@
39941 +#
39942 +# arch/ubicom32/mach-ip7k/Makefile
39943 +#      Makefile for ip7k based boards.
39944 +#
39945 +# (C) Copyright 2009, Ubicom, Inc.
39946 +#
39947 +# This file is part of the Ubicom32 Linux Kernel Port.
39948 +#
39949 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
39950 +# it and/or modify it under the terms of the GNU General Public License
39951 +# as published by the Free Software Foundation, either version 2 of the
39952 +# License, or (at your option) any later version.
39953 +#
39954 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
39955 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
39956 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39957 +# the GNU General Public License for more details.
39958 +#
39959 +# You should have received a copy of the GNU General Public License
39960 +# along with the Ubicom32 Linux Kernel Port.  If not,
39961 +# see <http://www.gnu.org/licenses/>.
39962 +#
39963 +# Ubicom32 implementation derived from (with many thanks):
39964 +#   arch/m68knommu
39965 +#   arch/blackfin
39966 +#   arch/parisc
39967 +#
39968 +
39969 +obj-$(CONFIG_IP7145DPF)                += board-ip7145dpf.o
39970 +obj-$(CONFIG_IP7160RGW)                += board-ip7160rgw.o
39971 +obj-$(CONFIG_IP7160RGWLCD)     += board-ip7160rgw.o
39972 +obj-$(CONFIG_IP7160BRINGUP)    += board-ip7160bringup.o
39973 +obj-$(CONFIG_IP7160DPF)                += board-ip7160dpf.o
39974 +obj-$(CONFIG_IP7500MODULE)     += board-ip7500module.o
39975 +obj-$(CONFIG_IP7500MEDIA)      += board-ip7500media.o
39976 +obj-$(CONFIG_IP7500AV)         += board-ip7500av.o
39977 +obj-$(CONFIG_IP7500WSPKR)      += board-ip7500wspkr.o
39978 +obj-$(CONFIG_IP7500IAP)                += board-ip7500iap.o
39979 --- /dev/null
39980 +++ b/arch/ubicom32/Makefile
39981 @@ -0,0 +1,104 @@
39982 +#
39983 +# arch/ubicom32/Makefile
39984 +#      <TODO: Replace with short file description>
39985 +#
39986 +# (C) Copyright 2009, Ubicom, Inc.
39987 +#
39988 +# This file is part of the Ubicom32 Linux Kernel Port.
39989 +#
39990 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
39991 +# it and/or modify it under the terms of the GNU General Public License
39992 +# as published by the Free Software Foundation, either version 2 of the
39993 +# License, or (at your option) any later version.
39994 +#
39995 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
39996 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
39997 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
39998 +# the GNU General Public License for more details.
39999 +#
40000 +# You should have received a copy of the GNU General Public License
40001 +# along with the Ubicom32 Linux Kernel Port.  If not,
40002 +# see <http://www.gnu.org/licenses/>.
40003 +#
40004 +# Ubicom32 implementation derived from (with many thanks):
40005 +#   arch/m68knommu
40006 +#   arch/blackfin
40007 +#   arch/parisc
40008 +#
40009 +
40010 +KBUILD_DEFCONFIG :=
40011 +
40012 +# setup the machine name and machine dependent settings
40013 +machine-$(CONFIG_UBICOM32_V3)  := ip5k
40014 +machine-$(CONFIG_UBICOM32_V4)  := ip7k
40015 +MACHINE := $(machine-y)
40016 +export MACHINE
40017 +
40018 +model-$(CONFIG_RAMKERNEL)      := ram
40019 +model-$(CONFIG_ROMKERNEL)      := rom
40020 +MODEL := $(model-y)
40021 +export MODEL
40022 +
40023 +CPUCLASS := $(cpuclass-y)
40024 +
40025 +export CPUCLASS
40026 +
40027 +#
40028 +# We want the core kernel built using the fastcall ABI but modules need
40029 +# to be built using the slower calling convention because they could be
40030 +# loaded out of range for fast calls.
40031 +#
40032 +CFLAGS_KERNEL    += -mfastcall
40033 +CFLAGS_MODULE    += -mno-fastcall
40034 +
40035 +#
40036 +# Some CFLAG additions based on specific CPU type.
40037 +#
40038 +cflags-$(CONFIG_UBICOM32_V3)           := -march=ubicom32v3 -DIP5000
40039 +cflags-$(CONFIG_UBICOM32_V4)           := -march=ubicom32v4 -DIP7000
40040 +
40041 +ldflags-$(CONFIG_LINKER_RELAXATION)    := --relax
40042 +LDFLAGS_vmlinux := $(ldflags-y)
40043 +
40044 +GCCLIBDIR := $(dir $(shell $(CC) $(cflags-y) -print-libgcc-file-name))
40045 +GCC_LIBS := $(GCCLIBDIR)/libgcc.a
40046 +
40047 +KBUILD_CFLAGS += $(cflags-y) -ffunction-sections
40048 +KBUILD_AFLAGS += $(cflags-y)
40049 +
40050 +KBUILD_CFLAGS += -D__linux__ -Dlinux
40051 +KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
40052 +
40053 +# include any machine specific directory
40054 +ifneq ($(machine-y),)
40055 +core-y += arch/$(ARCH)/mach-$(MACHINE)/
40056 +endif
40057 +
40058 +head-y := arch/$(ARCH)/kernel/head.o
40059 +
40060 +core-y += arch/$(ARCH)/kernel/ \
40061 +          arch/$(ARCH)/mm/ \
40062 +          arch/$(ARCH)/crypto/ \
40063 +          arch/$(ARCH)/mach-common/
40064 +
40065 +drivers-$(CONFIG_OPROFILE)     += arch/ubicom32/oprofile/
40066 +
40067 +libs-y += arch/$(ARCH)/lib/
40068 +libs-y += $(GCC_LIBS)
40069 +
40070 +archclean:
40071 +
40072 +# make sure developer has selected a valid board
40073 +ifeq ($(CONFIG_NOBOARD),y)
40074 +# $(error have to select a valid board file $(CONFIG_NOBOARD), please run kernel config again)
40075 +_all: config_board_error
40076 +endif
40077 +
40078 +config_board_error:
40079 +       @echo "*************************************************"
40080 +       @echo "You have not selected a proper board."
40081 +       @echo "Please run menuconfig (or config) against your"
40082 +       @echo "kernel and choose your board under Processor"
40083 +       @echo "options"
40084 +       @echo "*************************************************"
40085 +       @exit 1
40086 --- /dev/null
40087 +++ b/arch/ubicom32/mm/fault.c
40088 @@ -0,0 +1,80 @@
40089 +/*
40090 + * arch/ubicom32/mm/fault.c
40091 + *   Ubicom32 architecture page fault implementation.
40092 + *
40093 + * (C) Copyright 2009, Ubicom, Inc.
40094 + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
40095 + *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com)
40096 + *
40097 + *  Based on:
40098 + *
40099 + *  linux/arch/m68k/mm/fault.c
40100 + *
40101 + *  Copyright (C) 1995  Hamish Macdonald
40102 + *
40103 + * This file is part of the Ubicom32 Linux Kernel Port.
40104 + *
40105 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40106 + * it and/or modify it under the terms of the GNU General Public License
40107 + * as published by the Free Software Foundation, either version 2 of the
40108 + * License, or (at your option) any later version.
40109 + *
40110 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40111 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40112 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40113 + * the GNU General Public License for more details.
40114 + *
40115 + * You should have received a copy of the GNU General Public License
40116 + * along with the Ubicom32 Linux Kernel Port.  If not,
40117 + * see <http://www.gnu.org/licenses/>.
40118 + *
40119 + * Ubicom32 implementation derived from (with many thanks):
40120 + *   arch/m68knommu
40121 + *   arch/blackfin
40122 + *   arch/parisc
40123 + */
40124 +
40125 +#include <linux/module.h>
40126 +#include <linux/mman.h>
40127 +#include <linux/mm.h>
40128 +#include <linux/kernel.h>
40129 +#include <linux/ptrace.h>
40130 +
40131 +#include <asm/system.h>
40132 +#include <asm/pgtable.h>
40133 +
40134 +extern void die_if_kernel(char *, struct pt_regs *, long);
40135 +
40136 +/*
40137 + * This routine handles page faults.  It determines the problem, and
40138 + * then passes it off to one of the appropriate routines.
40139 + *
40140 + * error_code:
40141 + *     bit 0 == 0 means no page found, 1 means protection fault
40142 + *     bit 1 == 0 means read, 1 means write
40143 + *
40144 + * If this routine detects a bad access, it returns 1, otherwise it
40145 + * returns 0.
40146 + */
40147 +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
40148 +                             unsigned long error_code)
40149 +{
40150 +#ifdef DEBUG
40151 +       printk (KERN_DEBUG "regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
40152 +               regs->sr, regs->pc, address, error_code);
40153 +#endif
40154 +
40155 +       /*
40156 +        * Oops. The kernel tried to access some bad page. We'll have to
40157 +        * terminate things with extreme prejudice.
40158 +        */
40159 +       if ((unsigned long) address < PAGE_SIZE) {
40160 +               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
40161 +       } else
40162 +               printk(KERN_ALERT "Unable to handle kernel access");
40163 +       printk(KERN_ALERT " at virtual address %08lx\n",address);
40164 +       die_if_kernel("Oops", regs, error_code);
40165 +       do_exit(SIGKILL);
40166 +
40167 +       return 1;
40168 +}
40169 --- /dev/null
40170 +++ b/arch/ubicom32/mm/init.c
40171 @@ -0,0 +1,262 @@
40172 +/*
40173 + * arch/ubicom32/mm/init.c
40174 + *   Ubicom32 architecture virtual memory initialization.
40175 + *
40176 + * (C) Copyright 2009, Ubicom, Inc.
40177 + *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
40178 + *                      Kenneth Albanowski <kjahds@kjahds.com>,
40179 + *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com)
40180 + *
40181 + *  Based on:
40182 + *
40183 + *  linux/arch/m68k/mm/init.c
40184 + *
40185 + *  Copyright (C) 1995  Hamish Macdonald
40186 + *
40187 + *  JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
40188 + *  DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
40189 + *
40190 + * This file is part of the Ubicom32 Linux Kernel Port.
40191 + *
40192 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40193 + * it and/or modify it under the terms of the GNU General Public License
40194 + * as published by the Free Software Foundation, either version 2 of the
40195 + * License, or (at your option) any later version.
40196 + *
40197 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40198 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40199 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40200 + * the GNU General Public License for more details.
40201 + *
40202 + * You should have received a copy of the GNU General Public License
40203 + * along with the Ubicom32 Linux Kernel Port.  If not,
40204 + * see <http://www.gnu.org/licenses/>.
40205 + *
40206 + * Ubicom32 implementation derived from (with many thanks):
40207 + *   arch/m68knommu
40208 + *   arch/blackfin
40209 + *   arch/parisc
40210 + */
40211 +
40212 +#include <linux/signal.h>
40213 +#include <linux/sched.h>
40214 +#include <linux/kernel.h>
40215 +#include <linux/errno.h>
40216 +#include <linux/string.h>
40217 +#include <linux/types.h>
40218 +#include <linux/ptrace.h>
40219 +#include <linux/mman.h>
40220 +#include <linux/mm.h>
40221 +#include <linux/swap.h>
40222 +#include <linux/init.h>
40223 +#include <linux/highmem.h>
40224 +#include <linux/pagemap.h>
40225 +#include <linux/bootmem.h>
40226 +#include <linux/slab.h>
40227 +
40228 +#include <asm/setup.h>
40229 +#include <asm/segment.h>
40230 +#include <asm/page.h>
40231 +#include <asm/pgtable.h>
40232 +#include <asm/system.h>
40233 +#include <asm/machdep.h>
40234 +#include <asm/ocm-alloc.h>
40235 +#include <asm/processor.h>
40236 +
40237 +#undef DEBUG
40238 +
40239 +extern void die_if_kernel(char *,struct pt_regs *,long);
40240 +extern void free_initmem(void);
40241 +
40242 +/*
40243 + * BAD_PAGE is the page that is used for page faults when linux
40244 + * is out-of-memory. Older versions of linux just did a
40245 + * do_exit(), but using this instead means there is less risk
40246 + * for a process dying in kernel mode, possibly leaving a inode
40247 + * unused etc..
40248 + *
40249 + * BAD_PAGETABLE is the accompanying page-table: it is initialized
40250 + * to point to BAD_PAGE entries.
40251 + *
40252 + * ZERO_PAGE is a special page that is used for zero-initialized
40253 + * data and COW.
40254 + */
40255 +static unsigned long empty_bad_page_table;
40256 +
40257 +static unsigned long empty_bad_page;
40258 +
40259 +unsigned long empty_zero_page;
40260 +
40261 +void show_mem(void)
40262 +{
40263 +    unsigned long i;
40264 +    int free = 0, total = 0, reserved = 0, shared = 0;
40265 +    int cached = 0;
40266 +
40267 +    printk(KERN_INFO "\nMem-info:\n");
40268 +    show_free_areas();
40269 +    i = max_mapnr;
40270 +    while (i-- > 0) {
40271 +       total++;
40272 +       if (PageReserved(mem_map+i))
40273 +           reserved++;
40274 +       else if (PageSwapCache(mem_map+i))
40275 +           cached++;
40276 +       else if (!page_count(mem_map+i))
40277 +           free++;
40278 +       else
40279 +           shared += page_count(mem_map+i) - 1;
40280 +    }
40281 +    printk(KERN_INFO "%d pages of RAM\n",total);
40282 +    printk(KERN_INFO "%d free pages\n",free);
40283 +    printk(KERN_INFO "%d reserved pages\n",reserved);
40284 +    printk(KERN_INFO "%d pages shared\n",shared);
40285 +    printk(KERN_INFO "%d pages swap cached\n",cached);
40286 +}
40287 +
40288 +extern unsigned long memory_start;
40289 +extern unsigned long memory_end;
40290 +extern char __ocm_free_begin;
40291 +extern char __ocm_free_end;
40292 +
40293 +/*
40294 + * paging_init() continues the virtual memory environment setup which
40295 + * was begun by the code in arch/head.S.
40296 + * The parameters are pointers to where to stick the starting and ending
40297 + * addresses of available kernel virtual memory.
40298 + */
40299 +void __init paging_init(void)
40300 +{
40301 +       /*
40302 +        * Make sure start_mem is page aligned, otherwise bootmem and
40303 +        * page_alloc get different views of the world.
40304 +        */
40305 +#ifdef DEBUG
40306 +       unsigned long start_mem = PAGE_ALIGN(memory_start);
40307 +#endif
40308 +       unsigned long end_mem   = memory_end & PAGE_MASK;
40309 +
40310 +#ifdef DEBUG
40311 +       printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
40312 +               start_mem, end_mem);
40313 +#endif
40314 +
40315 +       /*
40316 +        * Initialize the bad page table and bad page to point
40317 +        * to a couple of allocated pages.
40318 +        */
40319 +       empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40320 +       empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40321 +       empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40322 +       memset((void *)empty_zero_page, 0, PAGE_SIZE);
40323 +
40324 +       /*
40325 +        * TODO: enable setting up for user memory management interface.
40326 +        */
40327 +
40328 +#ifdef DEBUG
40329 +       printk (KERN_DEBUG "before free_area_init\n");
40330 +
40331 +       printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
40332 +               start_mem, end_mem);
40333 +#endif
40334 +
40335 +       {
40336 +               unsigned long zones_size[MAX_NR_ZONES] = {0, };
40337 +#ifdef CONFIG_ZONE_DMA
40338 +               zones_size[ZONE_DMA] = OCMSIZE >> PAGE_SHIFT;
40339 +#endif
40340 +               zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
40341 +#ifdef CONFIG_HIGHMEM
40342 +               zones_size[ZONE_HIGHMEM] = 0;
40343 +#endif
40344 +               free_area_init(zones_size);
40345 +       }
40346 +}
40347 +
40348 +void __init mem_init(void)
40349 +{
40350 +       int codek = 0, datak = 0, initk = 0;
40351 +       unsigned long tmp, ram_start, ram_end, len;
40352 +       extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
40353 +
40354 +       unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
40355 +       unsigned long end_mem   = memory_end; /* DAVIDM - this must not include kernel stack at top */
40356 +       processor_dram(&ram_start, &ram_end);
40357 +       len = (ram_end - ram_start) + OCMSIZE;
40358 +#ifdef DEBUG
40359 +       printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
40360 +#endif
40361 +
40362 +       end_mem &= PAGE_MASK;
40363 +       high_memory = (void *) end_mem;
40364 +
40365 +       start_mem = PAGE_ALIGN(start_mem);
40366 +       max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
40367 +
40368 +       /* this will put all memory onto the freelists */
40369 +#ifdef CONFIG_ZONE_DMA
40370 +       {
40371 +               unsigned long ocm_free_begin = (unsigned long)&__ocm_free_begin;
40372 +               unsigned long ocm_free_end = (unsigned long)&__ocm_free_end;
40373 +               unsigned long zone_dma_begin = (ocm_free_begin + PAGE_SIZE - 1) & PAGE_MASK;
40374 +               unsigned long zone_dma_end = ocm_free_end & PAGE_MASK;
40375 +               if (zone_dma_end > zone_dma_begin)
40376 +                       free_bootmem(zone_dma_begin, zone_dma_end-zone_dma_begin);
40377 +       }
40378 +#endif
40379 +       totalram_pages = free_all_bootmem();
40380 +
40381 +       codek = (&_etext - &_stext) >> 10;
40382 +       datak = (&_ebss - &_sdata) >> 10;
40383 +       initk = (&__init_begin - &__init_end) >> 10;
40384 +
40385 +       tmp = nr_free_pages() << PAGE_SHIFT;
40386 +       printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
40387 +              tmp >> 10,
40388 +              len >> 10,
40389 +              codek,
40390 +              datak
40391 +              );
40392 +
40393 +}
40394 +
40395 +#ifdef CONFIG_BLK_DEV_INITRD
40396 +void free_initrd_mem(unsigned long start, unsigned long end)
40397 +{
40398 +       int pages = 0;
40399 +       for (; start < end; start += PAGE_SIZE) {
40400 +               ClearPageReserved(virt_to_page(start));
40401 +               init_page_count(virt_to_page(start));
40402 +               free_page(start);
40403 +               totalram_pages++;
40404 +               pages++;
40405 +       }
40406 +       printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
40407 +}
40408 +#endif
40409 +
40410 +void
40411 +free_initmem()
40412 +{
40413 +#ifdef CONFIG_RAMKERNEL
40414 +       unsigned long addr;
40415 +       extern char __init_begin, __init_end;
40416 +       /*
40417 +        * The following code should be cool even if these sections
40418 +        * are not page aligned.
40419 +        */
40420 +       addr = PAGE_ALIGN((unsigned long)(&__init_begin));
40421 +       /* next to check that the page we free is not a partial page */
40422 +       for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
40423 +               ClearPageReserved(virt_to_page(addr));
40424 +               init_page_count(virt_to_page(addr));
40425 +               free_page(addr);
40426 +               totalram_pages++;
40427 +       }
40428 +       printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
40429 +                       (addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
40430 +                       (int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
40431 +                       (int)(addr - PAGE_SIZE));
40432 +#endif
40433 +}
40434 --- /dev/null
40435 +++ b/arch/ubicom32/mm/kmap.c
40436 @@ -0,0 +1,79 @@
40437 +/*
40438 + * arch/ubicom32/mm/kmap.c
40439 + *   Ubicom32 architecture non-mmu ioremap and friends implementation.
40440 + *
40441 + * (C) Copyright 2009, Ubicom, Inc.
40442 + * Copyright (C) 2000 Lineo, <davidm@snapgear.com>
40443 + * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
40444 + *
40445 + * This file is part of the Ubicom32 Linux Kernel Port.
40446 + *
40447 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40448 + * it and/or modify it under the terms of the GNU General Public License
40449 + * as published by the Free Software Foundation, either version 2 of the
40450 + * License, or (at your option) any later version.
40451 + *
40452 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40453 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40454 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40455 + * the GNU General Public License for more details.
40456 + *
40457 + * You should have received a copy of the GNU General Public License
40458 + * along with the Ubicom32 Linux Kernel Port.  If not,
40459 + * see <http://www.gnu.org/licenses/>.
40460 + *
40461 + * Ubicom32 implementation derived from (with many thanks):
40462 + *   arch/m68knommu
40463 + *   arch/blackfin
40464 + *   arch/parisc
40465 + */
40466 +
40467 +#include <linux/module.h>
40468 +#include <linux/mm.h>
40469 +#include <linux/kernel.h>
40470 +#include <linux/string.h>
40471 +#include <linux/types.h>
40472 +#include <linux/slab.h>
40473 +#include <linux/vmalloc.h>
40474 +
40475 +#include <asm/setup.h>
40476 +#include <asm/segment.h>
40477 +#include <asm/page.h>
40478 +#include <asm/pgalloc.h>
40479 +#include <asm/io.h>
40480 +#include <asm/system.h>
40481 +
40482 +#undef DEBUG
40483 +
40484 +/*
40485 + * Map some physical address range into the kernel address space.
40486 + */
40487 +void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
40488 +{
40489 +       return (void *)physaddr;
40490 +}
40491 +
40492 +/*
40493 + * Unmap a ioremap()ed region again.
40494 + */
40495 +void iounmap(void *addr)
40496 +{
40497 +}
40498 +
40499 +/*
40500 + * __iounmap unmaps nearly everything, so be careful
40501 + * it doesn't free currently pointer/page tables anymore but it
40502 + * wans't used anyway and might be added later.
40503 + */
40504 +void __iounmap(void *addr, unsigned long size)
40505 +{
40506 +}
40507 +
40508 +/*
40509 + * Set new cache mode for some kernel address space.
40510 + * The caller must push data for that range itself, if such data may already
40511 + * be in the cache.
40512 + */
40513 +void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
40514 +{
40515 +}
40516 --- /dev/null
40517 +++ b/arch/ubicom32/mm/Makefile
40518 @@ -0,0 +1,32 @@
40519 +#
40520 +# arch/ubicom32/mm/Makefile
40521 +#      <TODO: Replace with short file description>
40522 +#
40523 +# (C) Copyright 2009, Ubicom, Inc.
40524 +#
40525 +# This file is part of the Ubicom32 Linux Kernel Port.
40526 +#
40527 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40528 +# it and/or modify it under the terms of the GNU General Public License
40529 +# as published by the Free Software Foundation, either version 2 of the
40530 +# License, or (at your option) any later version.
40531 +#
40532 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40533 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40534 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40535 +# the GNU General Public License for more details.
40536 +#
40537 +# You should have received a copy of the GNU General Public License
40538 +# along with the Ubicom32 Linux Kernel Port.  If not,
40539 +# see <http://www.gnu.org/licenses/>.
40540 +#
40541 +# Ubicom32 implementation derived from (with many thanks):
40542 +#   arch/m68knommu
40543 +#   arch/blackfin
40544 +#   arch/parisc
40545 +#
40546 +#
40547 +# Makefile for the linux m68knommu specific parts of the memory manager.
40548 +#
40549 +
40550 +obj-y += init.o fault.o memory.o kmap.o ocm-alloc.o
40551 --- /dev/null
40552 +++ b/arch/ubicom32/mm/memory.c
40553 @@ -0,0 +1,58 @@
40554 +/*
40555 + * arch/ubicom32/mm/memory.c
40556 + *   Ubicom32 architecture kernel_map() implementation.
40557 + *
40558 + * (C) Copyright 2009, Ubicom, Inc.
40559 + *  Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
40560 + *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
40561 + *
40562 + *  Based on:
40563 + *
40564 + *  linux/arch/m68k/mm/memory.c
40565 + *
40566 + *  Copyright (C) 1995  Hamish Macdonald
40567 + *
40568 + * This file is part of the Ubicom32 Linux Kernel Port.
40569 + *
40570 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40571 + * it and/or modify it under the terms of the GNU General Public License
40572 + * as published by the Free Software Foundation, either version 2 of the
40573 + * License, or (at your option) any later version.
40574 + *
40575 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40576 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40577 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40578 + * the GNU General Public License for more details.
40579 + *
40580 + * You should have received a copy of the GNU General Public License
40581 + * along with the Ubicom32 Linux Kernel Port.  If not,
40582 + * see <http://www.gnu.org/licenses/>.
40583 + *
40584 + * Ubicom32 implementation derived from (with many thanks):
40585 + *   arch/m68knommu
40586 + *   arch/blackfin
40587 + *   arch/parisc
40588 + */
40589 +
40590 +#include <linux/module.h>
40591 +#include <linux/mm.h>
40592 +#include <linux/kernel.h>
40593 +#include <linux/string.h>
40594 +#include <linux/types.h>
40595 +#include <linux/slab.h>
40596 +
40597 +#include <asm/segment.h>
40598 +#include <asm/page.h>
40599 +#include <asm/pgtable.h>
40600 +#include <asm/system.h>
40601 +
40602 +/*
40603 + * Map some physical address range into the kernel address space.
40604 + * The code is copied and adapted from map_chunk().
40605 + */
40606 +
40607 +unsigned long kernel_map(unsigned long paddr, unsigned long size,
40608 +                        int nocacheflag, unsigned long *memavailp )
40609 +{
40610 +       return paddr;
40611 +}
40612 --- /dev/null
40613 +++ b/arch/ubicom32/mm/ocm-alloc.c
40614 @@ -0,0 +1,487 @@
40615 +/*
40616 + * arch/ubicom32/mm/ocm-alloc.c
40617 + *     OCM allocator for Uibcom32 On-Chip memory
40618 + *
40619 + * (C) Copyright 2009, Ubicom, Inc.
40620 + *  Copyright 2004-2008 Analog Devices Inc.
40621 + *
40622 + *  Based on:
40623 + *
40624 + *  arch/blackfin/mm/sram-alloc.c
40625 + *
40626 + *
40627 + * This file is part of the Ubicom32 Linux Kernel Port.
40628 + *
40629 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40630 + * it and/or modify it under the terms of the GNU General Public License
40631 + * as published by the Free Software Foundation, either version 2 of the
40632 + * License, or (at your option) any later version.
40633 + *
40634 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40635 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40636 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
40637 + * the GNU General Public License for more details.
40638 + *
40639 + * You should have received a copy of the GNU General Public License
40640 + * along with the Ubicom32 Linux Kernel Port.  If not,
40641 + * see <http://www.gnu.org/licenses/>.
40642 + *
40643 + * Ubicom32 implementation derived from (with many thanks):
40644 + *   arch/m68knommu
40645 + *   arch/blackfin
40646 + *   arch/parisc
40647 + */
40648 +
40649 +#include <linux/module.h>
40650 +#include <linux/kernel.h>
40651 +#include <linux/types.h>
40652 +#include <linux/miscdevice.h>
40653 +#include <linux/ioport.h>
40654 +#include <linux/fcntl.h>
40655 +#include <linux/init.h>
40656 +#include <linux/poll.h>
40657 +#include <linux/proc_fs.h>
40658 +#include <linux/mutex.h>
40659 +#include <linux/rtc.h>
40660 +#include <asm/ocm-alloc.h>
40661 +
40662 +#if 0
40663 +#define DEBUGP printk
40664 +#else
40665 +#define DEBUGP(fmt, a...)
40666 +#endif
40667 +/*
40668 + * the data structure for OCM heap pieces
40669 + */
40670 +struct ocm_piece {
40671 +       void *paddr;
40672 +       int size;
40673 +       pid_t pid;
40674 +       struct ocm_piece *next;
40675 +};
40676 +
40677 +/*
40678 + * struct ocm_heap
40679 + */
40680 +struct ocm_heap {
40681 +       struct ocm_piece free_head;
40682 +       struct ocm_piece used_head;
40683 +       struct mutex lock;
40684 +};
40685 +
40686 +static struct ocm_heap ocm_inst_heap;
40687 +int ubi32_ocm_skbuf_max = 21, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
40688 +
40689 +/*
40690 + * OCM area for storing code
40691 + */
40692 +extern asmlinkage void *__ocm_free_begin;
40693 +extern asmlinkage void *__ocm_free_end;
40694 +extern asmlinkage void *__ocm_inst_heap_begin;
40695 +extern asmlinkage void *__ocm_inst_heap_end;
40696 +#define OCM_INST_HEAP_BEGIN ((unsigned int)&__ocm_inst_heap_begin)
40697 +#define OCM_INST_HEAP_END ((unsigned int)&__ocm_inst_heap_end)
40698 +#define OCM_INST_HEAP_LENGTH (OCM_INST_HEAP_END - OCM_INST_HEAP_BEGIN)
40699 +
40700 +static struct kmem_cache *ocm_piece_cache;
40701 +
40702 +/*
40703 + * _ocm_heap_init()
40704 + */
40705 +static int __init _ocm_heap_init(struct ocm_heap *ocmh,
40706 +                                 unsigned int start,
40707 +                                 unsigned int size)
40708 +{
40709 +       ocmh->free_head.next = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
40710 +
40711 +       if (!ocmh->free_head.next)
40712 +               return -1;
40713 +
40714 +       ocmh->free_head.next->paddr = (void *)start;
40715 +       ocmh->free_head.next->size = size;
40716 +       ocmh->free_head.next->pid = 0;
40717 +       ocmh->free_head.next->next = 0;
40718 +
40719 +       ocmh->used_head.next = NULL;
40720 +
40721 +       /* mutex initialize */
40722 +       mutex_init(&ocmh->lock);
40723 +
40724 +       return 0;
40725 +}
40726 +
40727 +/*
40728 + * _ocm_alloc_init()
40729 + *
40730 + * starts the ocm heap(s)
40731 + */
40732 +static int __init _ocm_alloc_init(void)
40733 +{
40734 +       if (OCM_INST_HEAP_LENGTH) {
40735 +               ocm_piece_cache = kmem_cache_create("ocm_piece_cache",
40736 +                                                   sizeof(struct ocm_piece),
40737 +                                                   0, SLAB_PANIC, NULL);
40738 +
40739 +               if (_ocm_heap_init(&ocm_inst_heap,
40740 +                                  OCM_INST_HEAP_BEGIN,
40741 +                                  OCM_INST_HEAP_LENGTH) == 0)
40742 +                       printk(KERN_INFO "OCM Instruction Heap %d KB\n",
40743 +                              OCM_INST_HEAP_LENGTH >> 10);
40744 +               else
40745 +                       printk(KERN_INFO "Failed to initialize OCM "
40746 +                              "Instruction Heap\n");
40747 +
40748 +       } else
40749 +               printk(KERN_INFO "No space available for OCM "
40750 +                      "Instruction Heap\n");
40751 +
40752 +       return 0;
40753 +}
40754 +pure_initcall(_ocm_alloc_init);
40755 +
40756 +/*
40757 + * _ocm_alloc()
40758 + *     generic alloc a block in the ocm heap, if successful
40759 + *     returns the pointer.
40760 + */
40761 +static void *_ocm_alloc(size_t size, pid_t pid, struct ocm_heap *ocmheap)
40762 +{
40763 +       struct ocm_piece *pslot, *plast, *pavail;
40764 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
40765 +       struct ocm_piece *pused_head = &ocmheap->used_head;
40766 +
40767 +       if (size <= 0 || !pfree_head || !pused_head)
40768 +               return NULL;
40769 +
40770 +       /* Align the size */
40771 +       size = (size + 3) & ~3;
40772 +
40773 +       pslot = pfree_head->next;
40774 +       plast = pfree_head;
40775 +
40776 +       /*
40777 +        * search an available piece slot
40778 +        */
40779 +       while (pslot != NULL && size > pslot->size) {
40780 +               plast = pslot;
40781 +               pslot = pslot->next;
40782 +       }
40783 +
40784 +       if (!pslot)
40785 +               return NULL;
40786 +
40787 +       if (pslot->size == size) {
40788 +               /*
40789 +                * Unlink this block from the list
40790 +                */
40791 +               plast->next = pslot->next;
40792 +               pavail = pslot;
40793 +       } else {
40794 +               /*
40795 +                * Split this block in two.
40796 +                */
40797 +               pavail = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
40798 +
40799 +               if (!pavail)
40800 +                       return NULL;
40801 +
40802 +               pavail->paddr = pslot->paddr;
40803 +               pavail->size = size;
40804 +               pslot->paddr += size;
40805 +               pslot->size -= size;
40806 +       }
40807 +
40808 +       pavail->pid = pid;
40809 +
40810 +       pslot = pused_head->next;
40811 +       plast = pused_head;
40812 +
40813 +       /*
40814 +        * insert new piece into used piece list !!!
40815 +        */
40816 +       while (pslot != NULL && pavail->paddr < pslot->paddr) {
40817 +               plast = pslot;
40818 +               pslot = pslot->next;
40819 +       }
40820 +
40821 +       pavail->next = pslot;
40822 +       plast->next = pavail;
40823 +
40824 +       DEBUGP("_ocm_alloc %d bytes at %p from in %p",
40825 +              size, pavail->paddr, ocmheap);
40826 +
40827 +       return pavail->paddr;
40828 +}
40829 +
40830 +#if 0
40831 +/* Allocate the largest available block.  */
40832 +static void *_ocm_alloc_max(struct ocm_heap *ocmheap,
40833 +                            unsigned long *psize)
40834 +{
40835 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
40836 +       struct ocm_piece *pslot, *pmax;
40837 +
40838 +       pmax = pslot = pfree_head->next;
40839 +
40840 +       /* search an available piece slot */
40841 +       while (pslot != NULL) {
40842 +               if (pslot->size > pmax->size)
40843 +                       pmax = pslot;
40844 +               pslot = pslot->next;
40845 +       }
40846 +
40847 +       if (!pmax)
40848 +               return NULL;
40849 +
40850 +       *psize = pmax->size;
40851 +
40852 +       return _ocm_alloc(*psize, ocmheap);
40853 +}
40854 +#endif
40855 +
40856 +/*
40857 + * _ocm_free()
40858 + *     generic free a block in the ocm heap, if successful
40859 + */
40860 +static int _ocm_free(const void *addr,
40861 +                    struct ocm_heap *ocmheap)
40862 +{
40863 +       struct ocm_piece *pslot, *plast, *pavail;
40864 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
40865 +       struct ocm_piece *pused_head = &ocmheap->used_head;
40866 +
40867 +       /* search the relevant memory slot */
40868 +       pslot = pused_head->next;
40869 +       plast = pused_head;
40870 +
40871 +       /* search an available piece slot */
40872 +       while (pslot != NULL && pslot->paddr != addr) {
40873 +               plast = pslot;
40874 +               pslot = pslot->next;
40875 +       }
40876 +
40877 +       if (!pslot) {
40878 +               DEBUGP("_ocm_free %p  not found in %p", addr, ocmheap);
40879 +               return -1;
40880 +       }
40881 +       DEBUGP("_ocm_free %p from in %p", addr, ocmheap);
40882 +
40883 +       plast->next = pslot->next;
40884 +       pavail = pslot;
40885 +       pavail->pid = 0;
40886 +
40887 +       /* insert free pieces back to the free list */
40888 +       pslot = pfree_head->next;
40889 +       plast = pfree_head;
40890 +
40891 +       while (pslot != NULL && addr > pslot->paddr) {
40892 +               plast = pslot;
40893 +               pslot = pslot->next;
40894 +       }
40895 +
40896 +       if (plast != pfree_head &&
40897 +           plast->paddr + plast->size == pavail->paddr) {
40898 +               plast->size += pavail->size;
40899 +               kmem_cache_free(ocm_piece_cache, pavail);
40900 +       } else {
40901 +               pavail->next = plast->next;
40902 +               plast->next = pavail;
40903 +               plast = pavail;
40904 +       }
40905 +
40906 +       if (pslot && plast->paddr + plast->size == pslot->paddr) {
40907 +               plast->size += pslot->size;
40908 +               plast->next = pslot->next;
40909 +               kmem_cache_free(ocm_piece_cache, pslot);
40910 +       }
40911 +
40912 +       return 0;
40913 +}
40914 +
40915 +/*
40916 + * ocm_inst_alloc()
40917 + *
40918 + *     allocates a block of size in the ocm instrction heap, if
40919 + *     successful returns address allocated.
40920 + */
40921 +void *ocm_inst_alloc(size_t size, pid_t pid)
40922 +{
40923 +       void *addr;
40924 +
40925 +       if (!OCM_INST_HEAP_LENGTH)
40926 +               return NULL;
40927 +
40928 +
40929 +       mutex_lock(&ocm_inst_heap.lock);
40930 +
40931 +       addr = _ocm_alloc(size, pid, &ocm_inst_heap);
40932 +
40933 +       mutex_unlock(&ocm_inst_heap.lock);
40934 +
40935 +       return addr;
40936 +}
40937 +EXPORT_SYMBOL(ocm_inst_alloc);
40938 +
40939 +/*
40940 + * ocm_inst_free()
40941 + *     free a block in the ocm instrction heap, returns 0 if successful.
40942 + */
40943 +int ocm_inst_free(const void *addr)
40944 +{
40945 +       int ret;
40946 +
40947 +       if (!OCM_INST_HEAP_LENGTH)
40948 +               return -1;
40949 +
40950 +       mutex_lock(&ocm_inst_heap.lock);
40951 +
40952 +       ret = _ocm_free(addr, &ocm_inst_heap);
40953 +
40954 +       mutex_unlock(&ocm_inst_heap.lock);
40955 +
40956 +       return ret;
40957 +}
40958 +EXPORT_SYMBOL(ocm_inst_free);
40959 +
40960 +/*
40961 + * ocm_free()
40962 + *     free a block in one of the ocm heaps, returns 0 if successful.
40963 + */
40964 +int ocm_free(const void *addr)
40965 +{
40966 +       if (addr >= (void *)OCM_INST_HEAP_BEGIN
40967 +                && addr < (void *)(OCM_INST_HEAP_END))
40968 +               return ocm_inst_free(addr);
40969 +       else
40970 +               return -1;
40971 +}
40972 +EXPORT_SYMBOL(ocm_free);
40973 +
40974 +
40975 +#ifdef CONFIG_PROC_FS
40976 +/* Need to keep line of output the same.  Currently, that is 46 bytes
40977 + * (including newline).
40978 + */
40979 +static int _ocm_proc_read(char *buf, int *len, int count, const char *desc,
40980 +                          struct ocm_heap *ocmheap)
40981 +{
40982 +       struct ocm_piece *pslot;
40983 +       struct ocm_piece *pfree_head = &ocmheap->free_head;
40984 +       struct ocm_piece *pused_head = &ocmheap->used_head;
40985 +
40986 +       /* The format is the following
40987 +        * --- OCM 123456789012345 Size   PID State     \n
40988 +        * 12345678-12345678 1234567890 12345 1234567890\n
40989 +        */
40990 +       int l;
40991 +       l = sprintf(&buf[*len], "--- OCM %-15s Size   PID State     \n",
40992 +                   desc);
40993 +
40994 +       *len += l;
40995 +       count -= l;
40996 +
40997 +       mutex_lock(&ocm_inst_heap.lock);
40998 +
40999 +       /*
41000 +        * search the relevant memory slot
41001 +        */
41002 +       pslot = pused_head->next;
41003 +
41004 +       while (pslot != NULL && count > 46) {
41005 +               l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41006 +                            pslot->paddr, pslot->paddr + pslot->size,
41007 +                            pslot->size, pslot->pid, "ALLOCATED");
41008 +
41009 +               *len += l;
41010 +               count -= l;
41011 +               pslot = pslot->next;
41012 +       }
41013 +
41014 +       pslot = pfree_head->next;
41015 +
41016 +       while (pslot != NULL && count > 46) {
41017 +               l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41018 +                           pslot->paddr, pslot->paddr + pslot->size,
41019 +                           pslot->size, pslot->pid, "FREE");
41020 +
41021 +               *len += l;
41022 +               count -= l;
41023 +               pslot = pslot->next;
41024 +       }
41025 +
41026 +       mutex_unlock(&ocm_inst_heap.lock);
41027 +
41028 +       return 0;
41029 +}
41030 +
41031 +static int ocm_proc_read(char *buf, char **start, off_t offset, int count,
41032 +               int *eof, void *data)
41033 +{
41034 +       int len = 0;
41035 +
41036 +       len = sprintf(&buf[len], "--- OCM SKB usage (max RX buf %d)\n"
41037 +                       "(SKB in OCM) %d - (SKB in DDR) %d\n",
41038 +                       ubi32_ocm_skbuf_max,
41039 +                       ubi32_ocm_skbuf,
41040 +                       ubi32_ddr_skbuf);
41041 +
41042 +       len += sprintf(&buf[len], "--- OCM Data Heap       Size\n"
41043 +                       "%p-%p %10i\n",
41044 +                       ((void *)&__ocm_free_begin),
41045 +                       ((void *)&__ocm_free_end),
41046 +                       ((unsigned int)&__ocm_free_end) -
41047 +                       ((unsigned int)&__ocm_free_begin));
41048 +
41049 +       if (_ocm_proc_read(buf, &len, count - len, "Inst Heap",
41050 +                           &ocm_inst_heap))
41051 +               goto not_done;
41052 +       *eof = 1;
41053 + not_done:
41054 +       return len;
41055 +}
41056 +
41057 +static int ocm_proc_write(struct file *file, const char __user *buffer,
41058 +                           unsigned long count, void *data)
41059 +{
41060 +       int n, v;
41061 +       char in[8];
41062 +
41063 +       if (count > sizeof(in))
41064 +               return -EINVAL;
41065 +
41066 +       if (copy_from_user(in, buffer, count))
41067 +               return -EFAULT;
41068 +       in[count-1] = 0;
41069 +
41070 +       printk(KERN_INFO "OCM skb alloc max = %s\n", in);
41071 +
41072 +       n = 0;
41073 +       v = 0;
41074 +       while ((in[n] >= '0') && (in[n] <= '9')) {
41075 +               v = v * 10 + (int)(in[n] - '0');
41076 +               n++;
41077 +       }
41078 +
41079 +       if (v == 0)
41080 +               return -EINVAL;
41081 +
41082 +       ubi32_ocm_skbuf_max = v;
41083 +       ubi32_ocm_skbuf = ubi32_ddr_skbuf = 0;
41084 +
41085 +       return count;
41086 +}
41087 +
41088 +static int __init sram_proc_init(void)
41089 +{
41090 +       struct proc_dir_entry *ptr;
41091 +       ptr = create_proc_entry("ocm", S_IFREG | S_IRUGO, NULL);
41092 +       if (!ptr) {
41093 +               printk(KERN_WARNING "unable to create /proc/ocm\n");
41094 +               return -1;
41095 +       }
41096 +       ptr->read_proc = ocm_proc_read;
41097 +       ptr->write_proc = ocm_proc_write;
41098 +       return 0;
41099 +}
41100 +late_initcall(sram_proc_init);
41101 +#endif
41102 --- /dev/null
41103 +++ b/arch/ubicom32/oprofile/ipProf.h
41104 @@ -0,0 +1,39 @@
41105 +#ifndef __IP_PROF_H__
41106 +#define __IP_PROF_H__
41107 +
41108 +/* This number MUST match what is used in the ultra configuration! */
41109 +#define IPPROFILETIO_MAX_SAMPLES       600
41110 +
41111 +/* Move to .h file used in both; avoid special types  */
41112 +struct profile_sample {
41113 +       unsigned int    pc;             /* PC value */
41114 +       unsigned int    parent;         /* a5 contents, to find the caller */
41115 +       unsigned char   cond_codes;     /* for branch prediction */
41116 +       unsigned char   thread;         /* I-blocked, D-blocked,
41117 +                                          4-bit thread number */
41118 +       unsigned short  active;         /* which threads are active -
41119 +                                          for accurate counting */
41120 +       unsigned short  blocked;        /* which threads are blocked due to
41121 +                                          I or D cache misses */
41122 +       unsigned int    latency;        /* CPU clocks since the last message
41123 +                                          dispatch in this thread
41124 +                                          (thread 0 only for now) */
41125 +};
41126 +
41127 +
41128 +struct profilenode {
41129 +       struct devtree_node dn;
41130 +       volatile unsigned char enabled; /* Is the tio enabled to
41131 +                                          take samples? */
41132 +       volatile unsigned char busy;    /* set when the samples
41133 +                                          are being read */
41134 +       volatile unsigned int mask;     /* Threads that change the MT_EN flag */
41135 +       volatile unsigned short rate;   /* What is the sampling rate? */
41136 +       volatile unsigned short head;   /* sample taker puts samples here */
41137 +       volatile unsigned short tail;   /* packet filler takes samples here */
41138 +       volatile unsigned short count;  /* number of valid samples */
41139 +       volatile unsigned short total;  /* Total samples */
41140 +       struct profile_sample samples[IPPROFILETIO_MAX_SAMPLES];
41141 +};
41142 +
41143 +#endif
41144 --- /dev/null
41145 +++ b/arch/ubicom32/oprofile/Makefile
41146 @@ -0,0 +1,37 @@
41147 +#
41148 +# arch/ubicom32/Makefile
41149 +#       Makefile for Oprofile support on Ubicom32
41150 +#
41151 +# (C) Copyright 2009, Ubicom, Inc.
41152 +#
41153 +# This file is part of the Ubicom32 Linux Kernel Port.
41154 +#
41155 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
41156 +# it and/or modify it under the terms of the GNU General Public License
41157 +# as published by the Free Software Foundation, either version 2 of the
41158 +# License, or (at your option) any later version.
41159 +#
41160 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
41161 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
41162 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
41163 +# the GNU General Public License for more details.
41164 +#
41165 +# You should have received a copy of the GNU General Public License
41166 +# along with the Ubicom32 Linux Kernel Port.  If not,
41167 +# see <http://www.gnu.org/licenses/>.
41168 +#
41169 +# Ubicom32 implementation derived from (with many thanks):
41170 +#   arch/m68knommu
41171 +#   arch/blackfin
41172 +#   arch/parisc
41173 +#
41174 +
41175 +obj-$(CONFIG_OPROFILE) += oprofile.o
41176 +
41177 +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
41178 +               oprof.o cpu_buffer.o buffer_sync.o \
41179 +               event_buffer.o oprofile_files.o \
41180 +               oprofilefs.o oprofile_stats.o \
41181 +               timer_int.o )
41182 +
41183 +oprofile-y     := $(DRIVER_OBJS) profile.o
41184 --- /dev/null
41185 +++ b/arch/ubicom32/oprofile/profile.c
41186 @@ -0,0 +1,221 @@
41187 +/*
41188 + * arch/ubicom32/oprofile/profile.c
41189 + *     Oprofile support for arch Ubicom32
41190 + *
41191 + * (C) Copyright 2009, Ubicom, Inc.
41192 + *
41193 + * This file is part of the Ubicom32 Linux Kernel Port.
41194 + *
41195 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41196 + * it and/or modify it under the terms of the GNU General Public License
41197 + * as published by the Free Software Foundation, either version 2 of the
41198 + * License, or (at your option)
41199 + * any later version.
41200 + *
41201 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it will
41202 + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41203 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41204 + * General Public License for more details.
41205 + *
41206 + * You should have received a copy of the GNU General Public License
41207 + * along with the Ubicom32 Linux Kernel Port.  If not, see
41208 + * <http://www.gnu.org/licenses/>.
41209 + *
41210 + * Ubicom32 implementation derived from (with many thanks):
41211 + *   arch/m68knommu
41212 + *   arch/blackfin
41213 + *   arch/parisc
41214 + */
41215 +
41216 +/**
41217 + * @file profile.c
41218 + *
41219 + * @remark Copyright 2002 OProfile authors
41220 + * @remark Read the file COPYING
41221 + *
41222 + * @author Hunyue Yau <hy@hy-research.com>
41223 + */
41224 +
41225 +#include <linux/oprofile.h>
41226 +#include <linux/init.h>
41227 +#include <linux/errno.h>
41228 +#include <linux/interrupt.h>
41229 +#include <linux/module.h>
41230 +#include <linux/kernel.h>
41231 +
41232 +#include <asm/devtree.h>
41233 +#include <asm/thread.h>
41234 +
41235 +/* For identifying userland vs kernel address */
41236 +#include <asm/stacktrace.h>
41237 +#include "ipProf.h"
41238 +
41239 +/* For communications with the backend */
41240 +static struct profilenode *profile_node;
41241 +
41242 +/* Bitmask containing all Linux threads - as seen by the ROSR reg */
41243 +static unsigned long th_all_mask;
41244 +
41245 +/* Lookup table to translate a hardware thread into a CPU identifier
41246 + * Table is indexed by the ROSR value which is assumed to be
41247 + * relatively small (0...15).
41248 + */
41249 +unsigned int cpu_map[THREAD_ARCHITECTURAL_MAX];
41250 +
41251 +static struct pt_regs regs;
41252 +
41253 +/*
41254 + * For each sample returned, checked to see if they are relevant to
41255 + * us. This is necessary as the ubicom32 architecture has other software
41256 + * running outside of Linux. Only then, put the sample into the relevant
41257 + * cpu bins.
41258 + *
41259 + * To minimize overhead, a global mask with all possible threads of in
41260 + * interest to us is used as a first check. Then a second mask identifying
41261 + * the thread is used to obtain an identifier for that "CPU".
41262 + */
41263 +
41264 +/*
41265 + * ubicom32_build_cpu_th_mask()
41266 + *
41267 + * Build a lookup table for translation between hardware thread
41268 + * "ROSR" values and Linux CPU ids
41269 + *
41270 + * *** This gets executed on all CPUs at once! ***
41271 + */
41272 +static void ubicom32_build_cpu_th_mask(void *mask)
41273 +{
41274 +       thread_t self = thread_get_self();
41275 +       unsigned long *th_m = mask;
41276 +
41277 +       BUG_ON(self <= 0 || self >= THREAD_ARCHITECTURAL_MAX);
41278 +       cpu_map[self] = smp_processor_id();
41279 +
41280 +       set_bit(self, th_m);
41281 +}
41282 +
41283 +/*
41284 + * profile_interrupt()
41285 + *
41286 + * Process samples returned from the profiler backend. The backend
41287 + * may return samples that are irrelevant to us or may even return
41288 + * multiple samples for the same CPU. Note that the sames may be
41289 + * for ANY cpu. At this time, this is unique and to support this requires
41290 + * Oprofile to expose an interface to accept the CPU that the same came
41291 + * frome.
41292 + */
41293 +static irqreturn_t profile_interrupt(int irq, void *arg)
41294 +{
41295 +       int i, buf_entry;
41296 +       int is_kernel;
41297 +       unsigned int bit_th;
41298 +       unsigned int th;
41299 +
41300 +       if (!(profile_node->enabled) || profile_node->count < 0) {
41301 +               printk(KERN_WARNING
41302 +                       "Unexpected interrupt, no samples or not enabled!\n");
41303 +               return IRQ_HANDLED;
41304 +       }
41305 +
41306 +       profile_node->busy = 1;         /* Keep backend out */
41307 +
41308 +       for (i = 0; i < profile_node->count; i++) {
41309 +               buf_entry = profile_node->tail;
41310 +               profile_node->tail++;
41311 +               profile_node->tail %= IPPROFILETIO_MAX_SAMPLES;
41312 +
41313 +               /* Note - the "thread" ID is only the lower 4 bits */
41314 +               th = (0x0f & profile_node->samples[buf_entry].thread);
41315 +               bit_th = (1 << th);
41316 +
41317 +               if ((bit_th & th_all_mask) == 0)
41318 +                       continue;
41319 +
41320 +               regs.pc = profile_node->samples[buf_entry].pc;
41321 +
41322 +               is_kernel = ubicom32_is_kernel(regs.pc);
41323 +
41324 +               oprofile_add_ext_sample_cpu(regs.pc, &regs, 0, is_kernel,
41325 +                                           cpu_map[th]);
41326 +       }
41327 +       profile_node->count = 0;
41328 +       profile_node->busy = 0;
41329 +
41330 +       return IRQ_HANDLED;
41331 +}
41332 +
41333 +/*
41334 + * profile_start()
41335 + *
41336 + * Notification from oprofile to start the profiler
41337 + */
41338 +static int profile_start(void)
41339 +{
41340 +       if (!profile_node)
41341 +               return -1;
41342 +
41343 +       profile_node->enabled = 1;
41344 +
41345 +       return 0;
41346 +}
41347 +
41348 +/*
41349 + * profile_stop()
41350 + *
41351 + * Notification from oprofile to stop the profiler
41352 + */
41353 +static void profile_stop(void)
41354 +{
41355 +       if (profile_node)
41356 +               profile_node->enabled = 0;
41357 +}
41358 +
41359 +/*
41360 + * oprofile_arch_init()
41361 + *
41362 + * Attach to Oprofile after qualify the availability of the backend
41363 + * profiler support.
41364 + */
41365 +int __init oprofile_arch_init(struct oprofile_operations *ops)
41366 +{
41367 +       int r = -ENODEV;
41368 +
41369 +       profile_node = (struct profilenode *)devtree_find_node("profiler");
41370 +
41371 +       if (profile_node == NULL) {
41372 +               printk(KERN_WARNING "Cannot find profiler node\n");
41373 +               return r;
41374 +       }
41375 +
41376 +       r = request_irq(profile_node->dn.recvirq, profile_interrupt,
41377 +                       IRQF_DISABLED, "profiler", NULL);
41378 +
41379 +       if (r < 0) {
41380 +               profile_node = NULL;
41381 +               printk(KERN_WARNING "Cannot get profiler IRQ\n");
41382 +               return r;
41383 +       }
41384 +
41385 +       ops->start = profile_start;
41386 +       ops->stop = profile_stop;
41387 +       ops->cpu_type = "timer";
41388 +
41389 +       memset(cpu_map, 0, sizeof(cpu_map));
41390 +
41391 +       on_each_cpu(ubicom32_build_cpu_th_mask, &th_all_mask, 1);
41392 +
41393 +       memset(&regs, 0, sizeof(regs));
41394 +
41395 +       return r;
41396 +}
41397 +
41398 +/*
41399 + * oprofile_arch_exit()
41400 + *
41401 + * External call to take outselves out.
41402 + * Make sure backend is not running.
41403 + */
41404 +void oprofile_arch_exit(void)
41405 +{
41406 +       BUG_ON(profile_node->enabled);
41407 +}
41408 --- a/drivers/char/hw_random/Kconfig
41409 +++ b/drivers/char/hw_random/Kconfig
41410 @@ -148,3 +148,16 @@ config HW_RANDOM_VIRTIO
41411  
41412           To compile this driver as a module, choose M here: the
41413           module will be called virtio-rng.  If unsure, say N.
41414 +
41415 +config HW_RANDOM_UBICOM32
41416 +       tristate "Ubicom32 HW Random Number Generator support"
41417 +       depends on HW_RANDOM && UBICOM32
41418 +       default HW_RANDOM
41419 +       ---help---
41420 +         This driver provides kernel-side support for the Random Number
41421 +         Generator hardware found on Ubicom32 processors.
41422 +
41423 +         To compile this driver as a module, choose M here: the
41424 +         module will be called pasemi-rng.
41425 +
41426 +         If unsure, say Y.
41427 --- a/drivers/char/hw_random/Makefile
41428 +++ b/drivers/char/hw_random/Makefile
41429 @@ -15,3 +15,4 @@ obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx
41430  obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
41431  obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
41432  obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
41433 +obj-$(CONFIG_HW_RANDOM_UBICOM32) += ubicom32-rng.o
41434 --- /dev/null
41435 +++ b/drivers/char/hw_random/ubicom32-rng.c
41436 @@ -0,0 +1,105 @@
41437 +/*
41438 + * drivers/net/ubi32-eth.c
41439 + *   Ubicom32 hardware random number generator driver.
41440 + *
41441 + * (C) Copyright 2009, Ubicom, Inc.
41442 + *
41443 + * This file is part of the Ubicom32 Linux Kernel Port.
41444 + *
41445 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41446 + * it and/or modify it under the terms of the GNU General Public License
41447 + * as published by the Free Software Foundation, either version 2 of the
41448 + * License, or (at your option) any later version.
41449 + *
41450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41451 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41452 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
41453 + * the GNU 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,
41457 + * see <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 +#include <linux/kernel.h>
41466 +#include <linux/module.h>
41467 +#include <linux/hw_random.h>
41468 +#include <linux/delay.h>
41469 +#include <asm/io.h>
41470 +#include <asm/ip5000.h>
41471 +
41472 +#define MODULE_NAME "ubicom32_rng"
41473 +
41474 +static int ubicom32_rng_data_present(struct hwrng *rng, int wait)
41475 +{
41476 +       int data, i;
41477 +
41478 +       for (i = 0; i < 20; i++) {
41479 +               data = *(int *)(TIMER_BASE + TIMER_TRN);
41480 +               if (data || !wait)
41481 +                       break;
41482 +               udelay(10);
41483 +       }
41484 +       return data;
41485 +}
41486 +
41487 +static int ubicom32_rng_data_read(struct hwrng *rng, u32 *data)
41488 +{
41489 +       *data = *(int *)(TIMER_BASE + TIMER_TRN);
41490 +       return 4;
41491 +}
41492 +
41493 +static int ubicom32_rng_init(struct hwrng *rng)
41494 +{
41495 +       printk(KERN_INFO "ubicom32 rng init\n");
41496 +       *(int *)(TIMER_BASE + TIMER_TRN_CFG) = TIMER_TRN_CFG_ENABLE_OSC;
41497 +       return 0;
41498 +}
41499 +
41500 +static void ubicom32_rng_cleanup(struct hwrng *rng)
41501 +{
41502 +       printk(KERN_INFO "ubicom32 rng cleanup\n");
41503 +       *(int *)(TIMER_BASE + TIMER_TRN_CFG) = 0;
41504 +}
41505 +
41506 +static struct hwrng ubicom32_rng = {
41507 +       .name           = MODULE_NAME,
41508 +       .init           = ubicom32_rng_init,
41509 +       .cleanup        = ubicom32_rng_cleanup,
41510 +       .data_present   = ubicom32_rng_data_present,
41511 +       .data_read      = ubicom32_rng_data_read,
41512 +       .priv           = 0,
41513 +};
41514 +
41515 +static int __init mod_init(void)
41516 +{
41517 +       int err;
41518 +
41519 +       printk(KERN_INFO "ubicom32 rng started\n");
41520 +       err = hwrng_register(&ubicom32_rng);
41521 +       if (err) {
41522 +               printk(KERN_ERR "ubicom32 rng register failed (%d)\n",
41523 +                       err);
41524 +       }
41525 +
41526 +       return err;
41527 +}
41528 +
41529 +static void __exit mod_exit(void)
41530 +{
41531 +       printk(KERN_INFO "ubicom32 rng stopped\n");
41532 +       hwrng_unregister(&ubicom32_rng);
41533 +}
41534 +
41535 +module_init(mod_init);
41536 +module_exit(mod_exit);
41537 +
41538 +MODULE_LICENSE("GPL");
41539 +MODULE_AUTHOR("Ubicom, Inc.");
41540 +MODULE_DESCRIPTION("H/W rng driver for ubicom32 processor");
41541 +MODULE_VERSION("1:1.0.a");
41542 --- a/drivers/crypto/Kconfig
41543 +++ b/drivers/crypto/Kconfig
41544 @@ -61,6 +61,40 @@ config CRYPTO_DEV_GEODE
41545           To compile this driver as a module, choose M here: the module
41546           will be called geode-aes.
41547  
41548 +config CRYPTO_UBICOM32
41549 +        bool "Ubicom32 Security Module"
41550 +        depends on UBICOM32
41551 +        help
41552 +          This is the ubicom32 hardware acceleration common code.
41553 +
41554 +config CRYPTO_AES_UBICOM32
41555 +        tristate "Ubicom32 AES implementation"
41556 +        depends on CRYPTO_UBICOM32
41557 +        select CRYPTO_ALGAPI
41558 +        help
41559 +          This is the ubicom32 hardware AES implementation.
41560 +
41561 +config CRYPTO_DES_UBICOM32
41562 +        tristate "Ubicom32 DES implementation"
41563 +        depends on CRYPTO_UBICOM32
41564 +        select CRYPTO_ALGAPI
41565 +        help
41566 +          This is the ubicom32 hardware DES and 3DES implementation.
41567 +
41568 +config CRYPTO_SHA1_UBICOM32
41569 +        tristate "Ubicom32 SHA1 implementation"
41570 +        depends on CRYPTO_UBICOM32
41571 +        select CRYPTO_ALGAPI
41572 +        help
41573 +          This is the ubicom32 hardware SHA1 implementation.
41574 +
41575 +config CRYPTO_MD5_UBICOM32
41576 +        tristate "Ubicom32 MD5 implementation"
41577 +        depends on CRYPTO_UBICOM32
41578 +        select CRYPTO_ALGAPI
41579 +        help
41580 +          This is the ubicom32 hardware MD5 implementation.
41581 +
41582  config ZCRYPT
41583         tristate "Support for PCI-attached cryptographic adapters"
41584         depends on S390
41585 --- a/drivers/mmc/host/Kconfig
41586 +++ b/drivers/mmc/host/Kconfig
41587 @@ -266,3 +266,10 @@ config GPIOMMC_CONFIGFS
41588         help
41589           This option automatically enables configfs support for gpiommc
41590           if configfs is available.
41591 +
41592 +config MMC_UBICOM32
41593 +       tristate "Ubicom32 MMC/SD host controller"
41594 +       depends on UBICOM32
41595 +       help
41596 +         This provides support for the SD/MMC hardware found on Ubicom32
41597 +         IP7K processors
41598 --- a/drivers/mmc/host/Makefile
41599 +++ b/drivers/mmc/host/Makefile
41600 @@ -30,4 +30,5 @@ obj-$(CONFIG_MMC_S3C)         += s3cmci.o
41601  obj-$(CONFIG_MMC_SDRICOH_CS)   += sdricoh_cs.o
41602  obj-$(CONFIG_MMC_TMIO)         += tmio_mmc.o
41603  obj-$(CONFIG_GPIOMMC)          += gpiommc.o
41604 +obj-$(CONFIG_MMC_UBICOM32)     += ubicom32sd.o
41605  
41606 --- /dev/null
41607 +++ b/drivers/mmc/host/ubicom32sd.c
41608 @@ -0,0 +1,773 @@
41609 +/*
41610 + * drivers/mmc/host/ubicom32sd.c
41611 + *     Ubicom32 Secure Digital Host Controller Interface driver
41612 + *
41613 + * (C) Copyright 2009, Ubicom, Inc.
41614 + *
41615 + * This file is part of the Ubicom32 Linux Kernel Port.
41616 + *
41617 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41618 + * it and/or modify it under the terms of the GNU General Public License
41619 + * as published by the Free Software Foundation, either version 2 of the
41620 + * License, or (at your option) any later version.
41621 + *
41622 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41623 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41624 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
41625 + * the GNU General Public License for more details.
41626 + *
41627 + * You should have received a copy of the GNU General Public License
41628 + * along with the Ubicom32 Linux Kernel Port.  If not,
41629 + * see <http://www.gnu.org/licenses/>.
41630 + */
41631 +
41632 +#include <linux/module.h>
41633 +#include <linux/platform_device.h>
41634 +#include <linux/delay.h>
41635 +#include <linux/scatterlist.h>
41636 +#include <linux/leds.h>
41637 +#include <linux/gpio.h>
41638 +#include <linux/mmc/host.h>
41639 +
41640 +#include <asm/ubicom32sd.h>
41641 +
41642 +#define DRIVER_NAME "ubicom32sd"
41643 +
41644 +#define sd_printk(...)
41645 +//#define sd_printk printk
41646 +
41647 +#define SDTIO_VP_VERSION       3
41648 +
41649 +#define SDTIO_MAX_SG_BLOCKS    16
41650 +
41651 +enum sdtio_commands {
41652 +       SDTIO_COMMAND_NOP,
41653 +       SDTIO_COMMAND_SETUP,
41654 +       SDTIO_COMMAND_SETUP_SDIO,
41655 +       SDTIO_COMMAND_EXECUTE,
41656 +       SDTIO_COMMAND_RESET,
41657 +};
41658 +
41659 +#define SDTIO_COMMAND_SHIFT                    24
41660 +#define SDTIO_COMMAND_FLAG_STOP_RSP_CRC                (1 << 10)
41661 +#define SDTIO_COMMAND_FLAG_STOP_RSP_136                (1 << 9)
41662 +#define SDTIO_COMMAND_FLAG_STOP_RSP            (1 << 8)
41663 +#define SDTIO_COMMAND_FLAG_STOP_CMD            (1 << 7)
41664 +#define SDTIO_COMMAND_FLAG_DATA_STREAM         (1 << 6)
41665 +#define SDTIO_COMMAND_FLAG_DATA_RD             (1 << 5)
41666 +#define SDTIO_COMMAND_FLAG_DATA_WR             (1 << 4)
41667 +#define SDTIO_COMMAND_FLAG_CMD_RSP_CRC         (1 << 3)
41668 +#define SDTIO_COMMAND_FLAG_CMD_RSP_136         (1 << 2)
41669 +#define SDTIO_COMMAND_FLAG_CMD_RSP             (1 << 1)
41670 +#define SDTIO_COMMAND_FLAG_CMD                 (1 << 0)
41671 +
41672 +/*
41673 + * SDTIO_COMMAND_SETUP_SDIO
41674 + */
41675 +#define SDTIO_COMMAND_FLAG_SDIO_INT_EN         (1 << 0)
41676 +
41677 +/*
41678 + * SDTIO_COMMAND_SETUP
41679 + *      clock speed in arg
41680 + */
41681 +#define SDTIO_COMMAND_FLAG_4BIT                 (1 << 3)
41682 +#define SDTIO_COMMAND_FLAG_1BIT                 (1 << 2)
41683 +#define SDTIO_COMMAND_FLAG_SET_CLOCK            (1 << 1)
41684 +#define SDTIO_COMMAND_FLAG_SET_WIDTH            (1 << 0)
41685 +
41686 +#define SDTIO_COMMAND_FLAG_CMD_RSP_MASK                (SDTIO_COMMAND_FLAG_CMD_RSP | SDTIO_COMMAND_FLAG_CMD_RSP_136)
41687 +#define SDTIO_COMMAND_FLAG_STOP_RSP_MASK       (SDTIO_COMMAND_FLAG_STOP_RSP | SDTIO_COMMAND_FLAG_STOP_RSP_136)
41688 +#define SDTIO_COMMAND_FLAG_RSP_MASK            (SDTIO_COMMAND_FLAG_CMD_RSP_MASK | SDTIO_COMMAND_FLAG_STOP_RSP_MASK)
41689 +
41690 +struct sdtio_vp_sg {
41691 +       volatile void           *addr;
41692 +       volatile u32_t          len;
41693 +};
41694 +
41695 +#define SDTIO_VP_INT_STATUS_DONE               (1 << 31)
41696 +#define SDTIO_VP_INT_STATUS_SDIO_INT           (1 << 10)
41697 +#define SDTIO_VP_INT_STATUS_DATA_CRC_ERR       (1 << 9)
41698 +#define SDTIO_VP_INT_STATUS_DATA_PROG_ERR      (1 << 8)
41699 +#define SDTIO_VP_INT_STATUS_DATA_TIMEOUT       (1 << 7)
41700 +#define SDTIO_VP_INT_STATUS_STOP_RSP_CRC       (1 << 6)
41701 +#define SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT   (1 << 5)
41702 +#define SDTIO_VP_INT_STATUS_CMD_RSP_CRC                (1 << 4)
41703 +#define SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT    (1 << 3)
41704 +#define SDTIO_VP_INT_STATUS_CMD_TIMEOUT                (1 << 2)
41705 +#define SDTIO_VP_INT_STATUS_CARD1_INSERT       (1 << 1)
41706 +#define SDTIO_VP_INT_STATUS_CARD0_INSERT       (1 << 0)
41707 +
41708 +struct sdtio_vp_regs {
41709 +       u32_t                           version;
41710 +       u32_t                           f_max;
41711 +       u32_t                           f_min;
41712 +
41713 +       volatile u32_t                  int_status;
41714 +
41715 +       volatile u32_t                  command;
41716 +       volatile u32_t                  arg;
41717 +
41718 +       volatile u32_t                  cmd_opcode;
41719 +       volatile u32_t                  cmd_arg;
41720 +       volatile u32_t                  cmd_rsp0;
41721 +       volatile u32_t                  cmd_rsp1;
41722 +       volatile u32_t                  cmd_rsp2;
41723 +       volatile u32_t                  cmd_rsp3;
41724 +
41725 +       volatile u32_t                  stop_opcode;
41726 +       volatile u32_t                  stop_arg;
41727 +       volatile u32_t                  stop_rsp0;
41728 +       volatile u32_t                  stop_rsp1;
41729 +       volatile u32_t                  stop_rsp2;
41730 +       volatile u32_t                  stop_rsp3;
41731 +
41732 +       volatile u32_t                  data_timeout_ns;
41733 +       volatile u16_t                  data_blksz;
41734 +       volatile u16_t                  data_blkct;
41735 +       volatile u32_t                  data_bytes_transferred;
41736 +       volatile u32_t                  sg_len;
41737 +       struct sdtio_vp_sg              sg[SDTIO_MAX_SG_BLOCKS];
41738 +};
41739 +
41740 +struct ubicom32sd_data {
41741 +       const struct ubicom32sd_platform_data   *pdata;
41742 +
41743 +       struct mmc_host                         *mmc;
41744 +
41745 +       /*
41746 +        * Lock used to protect the data structure
41747 +       spinlock_t                              lock;
41748 +        */
41749 +       int     int_en;
41750 +       int     int_pend;
41751 +
41752 +       /*
41753 +        * Receive and transmit interrupts used for communicating
41754 +        * with hardware
41755 +        */
41756 +       int                                     irq_tx;
41757 +       int                                     irq_rx;
41758 +
41759 +       /*
41760 +        * Current outstanding mmc request
41761 +        */
41762 +       struct mmc_request                      *mrq;
41763 +
41764 +       /*
41765 +        * Hardware registers
41766 +        */
41767 +       struct sdtio_vp_regs                    *regs;
41768 +};
41769 +
41770 +/*****************************************************************************\
41771 + *                                                                           *
41772 + * Suspend/resume                                                            *
41773 + *                                                                           *
41774 +\*****************************************************************************/
41775 +
41776 +#if 0//def CONFIG_PM
41777 +
41778 +int ubicom32sd_suspend_host(struct ubicom32sd_host *host, pm_message_t state)
41779 +{
41780 +       int ret;
41781 +
41782 +       ret = mmc_suspend_host(host->mmc, state);
41783 +       if (ret)
41784 +               return ret;
41785 +
41786 +       free_irq(host->irq, host);
41787 +
41788 +       return 0;
41789 +}
41790 +
41791 +EXPORT_SYMBOL_GPL(ubicom32sd_suspend_host);
41792 +
41793 +int ubicom32sd_resume_host(struct ubicom32sd_host *host)
41794 +{
41795 +       int ret;
41796 +
41797 +       if (host->flags & UBICOM32SD_USE_DMA) {
41798 +               if (host->ops->enable_dma)
41799 +                       host->ops->enable_dma(host);
41800 +       }
41801 +
41802 +       ret = request_irq(host->irq, ubicom32sd_irq, IRQF_SHARED,
41803 +                         mmc_hostname(host->mmc), host);
41804 +       if (ret)
41805 +               return ret;
41806 +
41807 +       ubicom32sd_init(host);
41808 +       mmiowb();
41809 +
41810 +       ret = mmc_resume_host(host->mmc);
41811 +       if (ret)
41812 +               return ret;
41813 +
41814 +       return 0;
41815 +}
41816 +
41817 +EXPORT_SYMBOL_GPL(ubicom32sd_resume_host);
41818 +
41819 +#endif /* CONFIG_PM */
41820 +
41821 +/*
41822 + * ubicom32sd_send_command_sync
41823 + */
41824 +static void ubicom32sd_send_command_sync(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
41825 +{
41826 +       ud->regs->command = command;
41827 +       ud->regs->arg = arg;
41828 +       ubicom32_set_interrupt(ud->irq_tx);
41829 +       while (ud->regs->command) {
41830 +               ndelay(100);
41831 +       }
41832 +}
41833 +
41834 +/*
41835 + * ubicom32sd_send_command
41836 + */
41837 +static void ubicom32sd_send_command(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
41838 +{
41839 +       ud->regs->command = command;
41840 +       ud->regs->arg = arg;
41841 +       ubicom32_set_interrupt(ud->irq_tx);
41842 +}
41843 +
41844 +/*
41845 + * ubicom32sd_reset
41846 + */
41847 +static void ubicom32sd_reset(struct ubicom32sd_data *ud)
41848 +{
41849 +       ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_RESET << SDTIO_COMMAND_SHIFT, 0);
41850 +       ud->regs->int_status = 0;
41851 +}
41852 +
41853 +/*
41854 + * ubicom32sd_mmc_request
41855 + */
41856 +static void ubicom32sd_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
41857 +{
41858 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
41859 +       u32_t command = SDTIO_COMMAND_EXECUTE << SDTIO_COMMAND_SHIFT;
41860 +       int ret = 0;
41861 +
41862 +       WARN(ud->mrq != NULL, "ud->mrq still set to %p\n", ud->mrq);
41863 +       //pr_debug("send cmd %08x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags);
41864 +
41865 +       if (mrq->cmd) {
41866 +               struct mmc_command *cmd = mrq->cmd;
41867 +
41868 +               sd_printk("%s:\t\t\tsetup cmd %02d arg %08x flags %08x\n", mmc_hostname(mmc), cmd->opcode, cmd->arg, cmd->flags);
41869 +
41870 +               ud->regs->cmd_opcode = cmd->opcode;
41871 +               ud->regs->cmd_arg = cmd->arg;
41872 +
41873 +               command |= SDTIO_COMMAND_FLAG_CMD;
41874 +
41875 +               if (cmd->flags & MMC_RSP_PRESENT) {
41876 +                       command |= SDTIO_COMMAND_FLAG_CMD_RSP;
41877 +               }
41878 +
41879 +               if (cmd->flags & MMC_RSP_136) {
41880 +                       command |= SDTIO_COMMAND_FLAG_CMD_RSP_136;
41881 +               }
41882 +
41883 +               if (cmd->flags & MMC_RSP_CRC) {
41884 +                       command |= SDTIO_COMMAND_FLAG_CMD_RSP_CRC;
41885 +               }
41886 +       }
41887 +
41888 +       if (mrq->data) {
41889 +               struct mmc_data *data = mrq->data;
41890 +               struct scatterlist *sg = data->sg;
41891 +               int i;
41892 +
41893 +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);
41894 +
41895 +               sd_printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n",
41896 +                         mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len,
41897 +                         data->flags, data->timeout_ns);
41898 +
41899 +               if (data->sg_len > SDTIO_MAX_SG_BLOCKS) {
41900 +                       ret = -EINVAL;
41901 +                       data->error = -EINVAL;
41902 +                       goto fail;
41903 +               }
41904 +
41905 +               ud->regs->data_timeout_ns = data->timeout_ns;
41906 +               ud->regs->data_blksz = data->blksz;
41907 +               ud->regs->data_blkct = data->blocks;
41908 +               ud->regs->sg_len = data->sg_len;
41909 +
41910 +               /*
41911 +                * Load all of our sg list into the driver sg buffer
41912 +                */
41913 +               for (i = 0; i < data->sg_len; i++) {
41914 +                       sd_printk("%s: sg %d = %p %d\n", mmc_hostname(mmc), i, sg_virt(sg), sg->length);
41915 +                       ud->regs->sg[i].addr = sg_virt(sg);
41916 +                       ud->regs->sg[i].len = sg->length;
41917 +                       if (((u32_t)ud->regs->sg[i].addr & 0x03) || (sg->length & 0x03)) {
41918 +                               sd_printk("%s: Need aligned buffers\n", mmc_hostname(mmc));
41919 +                               ret = -EINVAL;
41920 +                               data->error = -EINVAL;
41921 +                               goto fail;
41922 +                       }
41923 +                       sg++;
41924 +               }
41925 +               if (data->flags & MMC_DATA_READ) {
41926 +                       command |= SDTIO_COMMAND_FLAG_DATA_RD;
41927 +               } else if (data->flags & MMC_DATA_WRITE) {
41928 +                       command |= SDTIO_COMMAND_FLAG_DATA_WR;
41929 +               } else if (data->flags & MMC_DATA_STREAM) {
41930 +                       command |= SDTIO_COMMAND_FLAG_DATA_STREAM;
41931 +               }
41932 +       }
41933 +
41934 +       if (mrq->stop) {
41935 +               struct mmc_command *stop = mrq->stop;
41936 +               sd_printk("%s: \t\t\tsetup stop %02d arg %08x flags %08x\n", mmc_hostname(mmc), stop->opcode, stop->arg, stop->flags);
41937 +
41938 +               ud->regs->stop_opcode = stop->opcode;
41939 +               ud->regs->stop_arg = stop->arg;
41940 +
41941 +               command |= SDTIO_COMMAND_FLAG_STOP_CMD;
41942 +
41943 +               if (stop->flags & MMC_RSP_PRESENT) {
41944 +                       command |= SDTIO_COMMAND_FLAG_STOP_RSP;
41945 +               }
41946 +
41947 +               if (stop->flags & MMC_RSP_136) {
41948 +                       command |= SDTIO_COMMAND_FLAG_STOP_RSP_136;
41949 +               }
41950 +
41951 +               if (stop->flags & MMC_RSP_CRC) {
41952 +                       command |= SDTIO_COMMAND_FLAG_STOP_RSP_CRC;
41953 +               }
41954 +       }
41955 +
41956 +       ud->mrq = mrq;
41957 +
41958 +       sd_printk("%s: Sending command %08x\n", mmc_hostname(mmc), command);
41959 +
41960 +       ubicom32sd_send_command(ud, command, 0);
41961 +
41962 +       return;
41963 +fail:
41964 +       sd_printk("%s: mmcreq ret = %d\n", mmc_hostname(mmc), ret);
41965 +       mrq->cmd->error = ret;
41966 +       mmc_request_done(mmc, mrq);
41967 +}
41968 +
41969 +/*
41970 + * ubicom32sd_mmc_set_ios
41971 + */
41972 +static void ubicom32sd_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
41973 +{
41974 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
41975 +       u32_t command = SDTIO_COMMAND_SETUP << SDTIO_COMMAND_SHIFT;
41976 +       u32_t arg = 0;
41977 +       sd_printk("%s: ios call bw:%u pm:%u clk:%u\n", mmc_hostname(mmc), 1 << ios->bus_width, ios->power_mode, ios->clock);
41978 +
41979 +       switch (ios->bus_width) {
41980 +       case MMC_BUS_WIDTH_1:
41981 +               command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_1BIT;
41982 +               break;
41983 +
41984 +       case MMC_BUS_WIDTH_4:
41985 +               command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_4BIT;
41986 +               break;
41987 +       }
41988 +
41989 +       if (ios->clock) {
41990 +               arg = ios->clock;
41991 +               command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
41992 +       }
41993 +
41994 +       switch (ios->power_mode) {
41995 +
41996 +       /*
41997 +        * Turn off the SD bus (power + clock)
41998 +        */
41999 +       case MMC_POWER_OFF:
42000 +               gpio_set_value(ud->pdata->cards[0].pin_pwr, !ud->pdata->cards[0].pwr_polarity);
42001 +               command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
42002 +               break;
42003 +
42004 +       /*
42005 +        * Turn on the power to the SD bus
42006 +        */
42007 +       case MMC_POWER_ON:
42008 +               gpio_set_value(ud->pdata->cards[0].pin_pwr, ud->pdata->cards[0].pwr_polarity);
42009 +               break;
42010 +
42011 +       /*
42012 +        * Turn on the clock to the SD bus
42013 +        */
42014 +       case MMC_POWER_UP:
42015 +               /*
42016 +                * Done above
42017 +                */
42018 +               break;
42019 +       }
42020 +
42021 +       ubicom32sd_send_command_sync(ud, command, arg);
42022 +
42023 +       /*
42024 +        * Let the power settle down
42025 +        */
42026 +       udelay(500);
42027 +}
42028 +
42029 +/*
42030 + * ubicom32sd_mmc_get_cd
42031 + */
42032 +static int ubicom32sd_mmc_get_cd(struct mmc_host *mmc)
42033 +{
42034 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42035 +       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));
42036 +
42037 +       return gpio_get_value(ud->pdata->cards[0].pin_cd) ?
42038 +                               ud->pdata->cards[0].cd_polarity :
42039 +                               !ud->pdata->cards[0].cd_polarity;
42040 +}
42041 +
42042 +/*
42043 + * ubicom32sd_mmc_get_ro
42044 + */
42045 +static int ubicom32sd_mmc_get_ro(struct mmc_host *mmc)
42046 +{
42047 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42048 +       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));
42049 +
42050 +       return gpio_get_value(ud->pdata->cards[0].pin_wp) ?
42051 +                               ud->pdata->cards[0].wp_polarity :
42052 +                               !ud->pdata->cards[0].wp_polarity;
42053 +}
42054 +
42055 +/*
42056 + * ubicom32sd_mmc_enable_sdio_irq
42057 + */
42058 +static void ubicom32sd_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
42059 +{
42060 +       struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42061 +
42062 +       ud->int_en = enable;
42063 +       if (enable && ud->int_pend) {
42064 +               ud->int_pend = 0;
42065 +               mmc_signal_sdio_irq(mmc);
42066 +       }
42067 +}
42068 +
42069 +/*
42070 + * ubicom32sd_interrupt
42071 + */
42072 +static irqreturn_t ubicom32sd_interrupt(int irq, void *dev)
42073 +{
42074 +       struct mmc_host *mmc = (struct mmc_host *)dev;
42075 +       struct mmc_request *mrq;
42076 +       struct ubicom32sd_data *ud;
42077 +       u32_t int_status;
42078 +
42079 +       if (!mmc) {
42080 +               return IRQ_HANDLED;
42081 +       }
42082 +
42083 +       ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42084 +       if (!ud) {
42085 +               return IRQ_HANDLED;
42086 +       }
42087 +
42088 +       int_status = ud->regs->int_status;
42089 +       ud->regs->int_status &= ~int_status;
42090 +
42091 +       if (int_status & SDTIO_VP_INT_STATUS_SDIO_INT) {
42092 +               if (ud->int_en) {
42093 +                       ud->int_pend = 0;
42094 +                       mmc_signal_sdio_irq(mmc);
42095 +               } else {
42096 +                       ud->int_pend++;
42097 +               }
42098 +       }
42099 +
42100 +       if (!(int_status & SDTIO_VP_INT_STATUS_DONE)) {
42101 +               return IRQ_HANDLED;
42102 +       }
42103 +
42104 +       mrq = ud->mrq;
42105 +       if (!mrq) {
42106 +               sd_printk("%s: Spurious interrupt", mmc_hostname(mmc));
42107 +               return IRQ_HANDLED;
42108 +       }
42109 +       ud->mrq = NULL;
42110 +
42111 +       /*
42112 +        * SDTIO_VP_INT_DONE
42113 +        */
42114 +       if (mrq->cmd->flags & MMC_RSP_PRESENT) {
42115 +               struct mmc_command *cmd = mrq->cmd;
42116 +               cmd->error = 0;
42117 +
42118 +               if ((cmd->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_CRC)) {
42119 +                       cmd->error = -EILSEQ;
42120 +               } else if (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT) {
42121 +                       cmd->error = -ETIMEDOUT;
42122 +                       goto done;
42123 +               } else if (cmd->flags & MMC_RSP_136) {
42124 +                       cmd->resp[0] = ud->regs->cmd_rsp0;
42125 +                       cmd->resp[1] = ud->regs->cmd_rsp1;
42126 +                       cmd->resp[2] = ud->regs->cmd_rsp2;
42127 +                       cmd->resp[3] = ud->regs->cmd_rsp3;
42128 +               } else {
42129 +                       cmd->resp[0] = ud->regs->cmd_rsp0;
42130 +               }
42131 +               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);
42132 +       }
42133 +
42134 +       if (mrq->data) {
42135 +               struct mmc_data *data = mrq->data;
42136 +
42137 +               if (int_status & SDTIO_VP_INT_STATUS_DATA_TIMEOUT) {
42138 +                       data->error = -ETIMEDOUT;
42139 +                       sd_printk("%s:\t\t\tData Timeout\n", mmc_hostname(mmc));
42140 +                       goto done;
42141 +               } else if (int_status & SDTIO_VP_INT_STATUS_DATA_CRC_ERR) {
42142 +                       data->error = -EILSEQ;
42143 +                       sd_printk("%s:\t\t\tData CRC\n", mmc_hostname(mmc));
42144 +                       goto done;
42145 +               } else if (int_status & SDTIO_VP_INT_STATUS_DATA_PROG_ERR) {
42146 +                       data->error = -EILSEQ;
42147 +                       sd_printk("%s:\t\t\tData Program Error\n", mmc_hostname(mmc));
42148 +                       goto done;
42149 +               } else {
42150 +                       data->error = 0;
42151 +                       data->bytes_xfered = ud->regs->data_bytes_transferred;
42152 +               }
42153 +       }
42154 +
42155 +       if (mrq->stop && (mrq->stop->flags & MMC_RSP_PRESENT)) {
42156 +               struct mmc_command *stop = mrq->stop;
42157 +               stop->error = 0;
42158 +
42159 +               if ((stop->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_CRC)) {
42160 +                       stop->error = -EILSEQ;
42161 +               } else if (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT) {
42162 +                       stop->error = -ETIMEDOUT;
42163 +                       goto done;
42164 +               } else if (stop->flags & MMC_RSP_136) {
42165 +                       stop->resp[0] = ud->regs->stop_rsp0;
42166 +                       stop->resp[1] = ud->regs->stop_rsp1;
42167 +                       stop->resp[2] = ud->regs->stop_rsp2;
42168 +                       stop->resp[3] = ud->regs->stop_rsp3;
42169 +               } else {
42170 +                       stop->resp[0] = ud->regs->stop_rsp0;
42171 +               }
42172 +               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);
42173 +       }
42174 +
42175 +done:
42176 +       mmc_request_done(mmc, mrq);
42177 +
42178 +       return IRQ_HANDLED;
42179 +}
42180 +
42181 +static struct mmc_host_ops ubicom32sd_ops = {
42182 +       .request                = ubicom32sd_mmc_request,
42183 +       .set_ios                = ubicom32sd_mmc_set_ios,
42184 +       .get_ro                 = ubicom32sd_mmc_get_ro,
42185 +       .get_cd                 = ubicom32sd_mmc_get_cd,
42186 +       .enable_sdio_irq        = ubicom32sd_mmc_enable_sdio_irq,
42187 +};
42188 +
42189 +/*
42190 + * ubicom32sd_probe
42191 + */
42192 +static int __devinit ubicom32sd_probe(struct platform_device *pdev)
42193 +{
42194 +       struct ubicom32sd_platform_data *pdata = (struct ubicom32sd_platform_data *)pdev->dev.platform_data;
42195 +       struct mmc_host *mmc;
42196 +       struct ubicom32sd_data *ud;
42197 +       struct resource *res_regs;
42198 +       struct resource *res_irq_tx;
42199 +       struct resource *res_irq_rx;
42200 +       int ret;
42201 +
42202 +       /*
42203 +        * Get our resources, regs is the hardware driver base address
42204 +        * and the tx and rx irqs are used to communicate with the
42205 +        * hardware driver.
42206 +        */
42207 +       res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42208 +       res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
42209 +       res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
42210 +       if (!res_regs || !res_irq_tx || !res_irq_rx) {
42211 +               ret = -EINVAL;
42212 +               goto fail;
42213 +       }
42214 +
42215 +       /*
42216 +        * Reserve any gpios we need
42217 +        */
42218 +       ret = gpio_request(pdata->cards[0].pin_wp, "sd-wp");
42219 +       if (ret) {
42220 +               goto fail;
42221 +       }
42222 +       gpio_direction_input(pdata->cards[0].pin_wp);
42223 +
42224 +       ret = gpio_request(pdata->cards[0].pin_cd, "sd-cd");
42225 +       if (ret) {
42226 +               goto fail_cd;
42227 +       }
42228 +       gpio_direction_input(pdata->cards[0].pin_cd);
42229 +
42230 +       /*
42231 +        * HACK: for the dual port controller on port F, we don't support the second port right now
42232 +        */
42233 +       if (pdata->ncards > 1) {
42234 +               ret = gpio_request(pdata->cards[1].pin_pwr, "sd-pwr");
42235 +               gpio_direction_output(pdata->cards[1].pin_pwr, !pdata->cards[1].pwr_polarity);
42236 +               gpio_direction_output(pdata->cards[1].pin_pwr, pdata->cards[1].pwr_polarity);
42237 +       }
42238 +
42239 +       ret = gpio_request(pdata->cards[0].pin_pwr, "sd-pwr");
42240 +       if (ret) {
42241 +               goto fail_pwr;
42242 +       }
42243 +       gpio_direction_output(pdata->cards[0].pin_pwr, !pdata->cards[0].pwr_polarity);
42244 +
42245 +       /*
42246 +        * Allocate the MMC driver, it includes memory for our data.
42247 +        */
42248 +       mmc = mmc_alloc_host(sizeof(struct ubicom32sd_data), &pdev->dev);
42249 +       if (!mmc) {
42250 +               ret = -ENOMEM;
42251 +               goto fail_mmc;
42252 +       }
42253 +       ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42254 +       ud->mmc = mmc;
42255 +       ud->pdata = pdata;
42256 +       ud->regs = (struct sdtio_vp_regs *)res_regs->start;
42257 +       ud->irq_tx = res_irq_tx->start;
42258 +       ud->irq_rx = res_irq_rx->start;
42259 +       platform_set_drvdata(pdev, mmc);
42260 +
42261 +       ret = request_irq(ud->irq_rx, ubicom32sd_interrupt, IRQF_DISABLED, mmc_hostname(mmc), mmc);
42262 +       if (ret) {
42263 +               goto fail_mmc;
42264 +       }
42265 +
42266 +       /*
42267 +        * Fill in the mmc structure
42268 +        */
42269 +       mmc->ops = &ubicom32sd_ops;
42270 +       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ |
42271 +                   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
42272 +
42273 +       mmc->f_min = ud->regs->f_min;
42274 +       mmc->f_max = ud->regs->f_max;
42275 +       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
42276 +
42277 +       /*
42278 +        * Setup some restrictions on transfers
42279 +        *
42280 +        * We allow up to SDTIO_MAX_SG_BLOCKS of data to DMA into, there are
42281 +        * not really any "max_seg_size", "max_req_size", or "max_blk_count"
42282 +        * restrictions (must be less than U32_MAX though), pick
42283 +        * something large?!...
42284 +        *
42285 +        * The hardware can do up to 4095 bytes per block, since the spec
42286 +        * only requires 2048, we'll set it to that and not worry about
42287 +        * potential weird blk lengths.
42288 +        */
42289 +       mmc->max_hw_segs = SDTIO_MAX_SG_BLOCKS;
42290 +       mmc->max_phys_segs = SDTIO_MAX_SG_BLOCKS;
42291 +       mmc->max_seg_size = 1024 * 1024;
42292 +       mmc->max_req_size = 1024 * 1024;
42293 +       mmc->max_blk_count = 1024;
42294 +
42295 +       mmc->max_blk_size = 2048;
42296 +
42297 +       ubicom32sd_reset(ud);
42298 +
42299 +       /*
42300 +        * enable interrupts
42301 +        */
42302 +       ud->int_en = 0;
42303 +       ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_SETUP_SDIO << SDTIO_COMMAND_SHIFT | SDTIO_COMMAND_FLAG_SDIO_INT_EN, 0);
42304 +
42305 +       mmc_add_host(mmc);
42306 +
42307 +       printk(KERN_INFO "%s at %p, irq %d/%d\n", mmc_hostname(mmc),
42308 +                       ud->regs, ud->irq_tx, ud->irq_rx);
42309 +       return 0;
42310 +
42311 +fail_mmc:
42312 +       gpio_free(pdata->cards[0].pin_pwr);
42313 +fail_pwr:
42314 +       gpio_free(pdata->cards[0].pin_cd);
42315 +fail_cd:
42316 +       gpio_free(pdata->cards[0].pin_wp);
42317 +fail:
42318 +       return ret;
42319 +}
42320 +
42321 +/*
42322 + * ubicom32sd_remove
42323 + */
42324 +static int __devexit ubicom32sd_remove(struct platform_device *pdev)
42325 +{
42326 +       struct mmc_host *mmc = platform_get_drvdata(pdev);
42327 +
42328 +       platform_set_drvdata(pdev, NULL);
42329 +
42330 +       if (mmc) {
42331 +               struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42332 +
42333 +               gpio_free(ud->pdata->cards[0].pin_pwr);
42334 +               gpio_free(ud->pdata->cards[0].pin_cd);
42335 +               gpio_free(ud->pdata->cards[0].pin_wp);
42336 +
42337 +               mmc_remove_host(mmc);
42338 +               mmc_free_host(mmc);
42339 +       }
42340 +
42341 +       /*
42342 +        * Note that our data is allocated as part of the mmc structure
42343 +        * so we don't need to free it.
42344 +        */
42345 +       return 0;
42346 +}
42347 +
42348 +static struct platform_driver ubicom32sd_driver = {
42349 +       .driver = {
42350 +               .name = DRIVER_NAME,
42351 +               .owner = THIS_MODULE,
42352 +       },
42353 +       .probe = ubicom32sd_probe,
42354 +       .remove = __devexit_p(ubicom32sd_remove),
42355 +#if 0
42356 +       .suspend = ubicom32sd_suspend,
42357 +       .resume = ubicom32sd_resume,
42358 +#endif
42359 +};
42360 +
42361 +/*
42362 + * ubicom32sd_init
42363 + */
42364 +static int __init ubicom32sd_init(void)
42365 +{
42366 +       return platform_driver_register(&ubicom32sd_driver);
42367 +}
42368 +module_init(ubicom32sd_init);
42369 +
42370 +/*
42371 + * ubicom32sd_exit
42372 + */
42373 +static void __exit ubicom32sd_exit(void)
42374 +{
42375 +    platform_driver_unregister(&ubicom32sd_driver);
42376 +}
42377 +module_exit(ubicom32sd_exit);
42378 +
42379 +MODULE_AUTHOR("Patrick Tjin");
42380 +MODULE_DESCRIPTION("Ubicom32 Secure Digital Host Controller Interface driver");
42381 +MODULE_LICENSE("GPL");
42382 --- a/drivers/mtd/devices/Kconfig
42383 +++ b/drivers/mtd/devices/Kconfig
42384 @@ -104,6 +104,31 @@ config M25PXX_USE_FAST_READ
42385         help
42386           This option enables FAST_READ access supported by ST M25Pxx.
42387  
42388 +config MTD_UBI32_NAND_SPI_ER
42389 +       tristate "UBI32_NAND SPI-ER support"
42390 +       help
42391 +         This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42392 +         using the built in flash controller on the Ubicom32 architecture.
42393 +         Partial page writes are not supported by this driver.
42394 +
42395 +config MTD_NAND_SPI_ER
42396 +       tristate "NAND SPI-ER support"
42397 +       help
42398 +         This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42399 +         using a generic SPI bus.  Partial page writes are supported
42400 +         by this driver.
42401 +
42402 +config MTD_UBI32_M25P80
42403 +       tristate "Ubicom processor support for most SPI Flash chips (AT26DF, M25P, W25X, ...)"
42404 +       depends on UBICOM32
42405 +       default y
42406 +       help
42407 +         This enables access to most modern SPI flash chips, used for
42408 +         program and data storage.   Series supported include Atmel AT26DF,
42409 +         Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X.  Other chips
42410 +         are supported as well.  See the driver source for the current list,
42411 +         or to add other chips.
42412 +
42413  config MTD_SLRAM
42414         tristate "Uncached system RAM"
42415         help
42416 --- a/drivers/mtd/devices/Makefile
42417 +++ b/drivers/mtd/devices/Makefile
42418 @@ -16,3 +16,6 @@ obj-$(CONFIG_MTD_LART)                += lart.o
42419  obj-$(CONFIG_MTD_BLOCK2MTD)    += block2mtd.o
42420  obj-$(CONFIG_MTD_DATAFLASH)    += mtd_dataflash.o
42421  obj-$(CONFIG_MTD_M25P80)       += m25p80.o
42422 +obj-$(CONFIG_MTD_UBI32_M25P80) += ubi32-m25p80.o
42423 +obj-$(CONFIG_MTD_NAND_SPI_ER)  += nand-spi-er.o
42424 +obj-$(CONFIG_MTD_UBI32_NAND_SPI_ER)    += ubi32-nand-spi-er.o
42425 --- /dev/null
42426 +++ b/drivers/mtd/devices/nand-spi-er.c
42427 @@ -0,0 +1,1017 @@
42428 +/*
42429 + * Micron SPI-ER NAND Flash Memory
42430 + *
42431 + * (C) Copyright 2009, Ubicom, Inc.
42432 + *
42433 + * This file is part of the Ubicom32 Linux Kernel Port.
42434 + *
42435 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
42436 + * it and/or modify it under the terms of the GNU General Public License
42437 + * as published by the Free Software Foundation, either version 2 of the
42438 + * License, or (at your option) any later version.
42439 + *
42440 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
42441 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
42442 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
42443 + * the GNU General Public License for more details.
42444 + *
42445 + * You should have received a copy of the GNU General Public License
42446 + * along with the Ubicom32 Linux Kernel Port.  If not,
42447 + * see <http://www.gnu.org/licenses/>.
42448 +*/
42449 +#include <linux/module.h>
42450 +#include <linux/init.h>
42451 +#include <linux/slab.h>
42452 +#include <linux/delay.h>
42453 +#include <linux/device.h>
42454 +#include <linux/mutex.h>
42455 +#include <linux/err.h>
42456 +
42457 +#include <linux/spi/spi.h>
42458 +#include <linux/spi/flash.h>
42459 +
42460 +#include <linux/mtd/mtd.h>
42461 +#include <linux/mtd/partitions.h>
42462 +
42463 +#define NAND_SPI_ER_BLOCK_FROM_ROW(row)                (row >> 6)
42464 +
42465 +#define NAND_SPI_ER_STATUS_P_FAIL              (1 << 3)
42466 +#define NAND_SPI_ER_STATUS_E_FAIL              (1 << 2)
42467 +#define NAND_SPI_ER_STATUS_OIP                 (1 << 0)
42468 +
42469 +#define NAND_SPI_ER_LAST_ROW_INVALID           0xFFFFFFFF
42470 +#define        NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET       0x08
42471 +
42472 +struct nand_spi_er_device {
42473 +       const char              *name;
42474 +
42475 +       uint8_t                 id0;
42476 +       uint8_t                 id1;
42477 +
42478 +       unsigned int            blocks;
42479 +       unsigned int            pages_per_block;
42480 +       unsigned int            page_size;
42481 +       unsigned int            write_size;
42482 +       unsigned int            erase_size;
42483 +};
42484 +
42485 +struct nand_spi_er {
42486 +       char                            name[24];
42487 +
42488 +       const struct nand_spi_er_device *device;
42489 +
42490 +       struct mutex                    lock;
42491 +       struct spi_device               *spi;
42492 +
42493 +       struct mtd_info                 mtd;
42494 +
42495 +       unsigned int                    last_row;       /* the last row we fetched */
42496 +
42497 +       /*
42498 +        * Bad block table (MUST be last in strcuture)
42499 +        */
42500 +       unsigned long                   nbb;
42501 +       unsigned long                   bbt[0];
42502 +};
42503 +
42504 +const struct nand_spi_er_device nand_spi_er_devices[] = {
42505 +       {
42506 +               name:                   "MT29F1G01ZDC",
42507 +               id0:                    0x2C,
42508 +               id1:                    0x12,
42509 +               blocks:                 1024,
42510 +               pages_per_block:        64,
42511 +               page_size:              2048,
42512 +               write_size:             512,
42513 +               erase_size:             64 * 2048,
42514 +       },
42515 +       {
42516 +               name:                   "MT29F1G01ZDC",
42517 +               id0:                    0x2C,
42518 +               id1:                    0x13,
42519 +               blocks:                 1024,
42520 +               pages_per_block:        64,
42521 +               page_size:              2048,
42522 +               write_size:             512,
42523 +               erase_size:             64 * 2048,
42524 +       },
42525 +};
42526 +
42527 +static int read_only = 0;
42528 +module_param(read_only, int, 0);
42529 +MODULE_PARM_DESC(read_only, "Leave device locked");
42530 +
42531 +/*
42532 + * nand_spi_er_get_feature
42533 + *     Get Feature register
42534 + */
42535 +static int nand_spi_er_get_feature(struct nand_spi_er *chip, int reg, uint8_t *data)
42536 +{
42537 +       uint8_t txbuf[2];
42538 +       uint8_t rxbuf[1];
42539 +       int res;
42540 +
42541 +       txbuf[0] = 0x0F;
42542 +       txbuf[1] = reg;
42543 +       res = spi_write_then_read(chip->spi, txbuf, 2, rxbuf, 1);
42544 +       if (res) {
42545 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed get feature res=%d\n", chip->name, res);
42546 +               return res;
42547 +       }
42548 +       *data = rxbuf[0];
42549 +       return 0;
42550 +}
42551 +
42552 +/*
42553 + * nand_spi_er_busywait
42554 + *     Wait until the chip is not busy
42555 + */
42556 +static int nand_spi_er_busywait(struct nand_spi_er *chip, uint8_t *data)
42557 +{
42558 +       int i;
42559 +
42560 +       for (i = 0; i < 100; i++) {
42561 +               int res = nand_spi_er_get_feature(chip, 0xC0, data);
42562 +               if (res) {
42563 +                       return res;
42564 +               }
42565 +               if (!(*data & NAND_SPI_ER_STATUS_OIP)) {
42566 +                       break;
42567 +               }
42568 +       }
42569 +
42570 +       return 0;
42571 +}
42572 +
42573 +/*
42574 + * nand_spi_er_erase
42575 + *     Erase a block, parameters must be block aligned
42576 + */
42577 +static int nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
42578 +{
42579 +       struct nand_spi_er *chip = mtd->priv;
42580 +       struct spi_device *spi = chip->spi;
42581 +       uint8_t txbuf[4];
42582 +       int res;
42583 +
42584 +       DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
42585 +
42586 +       if ((instr->addr + instr->len) > mtd->size) {
42587 +               return -EINVAL;
42588 +       }
42589 +
42590 +       if (instr->addr & (chip->device->erase_size - 1)) {
42591 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
42592 +               return -EINVAL;
42593 +       }
42594 +
42595 +       if (instr->len & (chip->device->erase_size - 1)) {
42596 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
42597 +               return -EINVAL;
42598 +       }
42599 +
42600 +       mutex_lock(&chip->lock);
42601 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42602 +
42603 +       while (instr->len) {
42604 +               uint32_t block = instr->addr >> 17;
42605 +               uint32_t row = block << 6;
42606 +               uint8_t stat;
42607 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
42608 +
42609 +               /*
42610 +                * Write enable
42611 +                */
42612 +               txbuf[0] = 0x06;
42613 +               res = spi_write(spi, txbuf, 1);
42614 +               if (res) {
42615 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
42616 +                       mutex_unlock(&chip->lock);
42617 +                       return res;
42618 +               }
42619 +
42620 +               /*
42621 +                * Test for bad block
42622 +                */
42623 +               if (test_bit(block, chip->bbt)) {
42624 +                       instr->fail_addr = block << 17;
42625 +                       instr->state = MTD_ERASE_FAILED;
42626 +                       res = -EBADMSG;
42627 +                       goto done;
42628 +               }
42629 +
42630 +               /*
42631 +                * Block erase
42632 +                */
42633 +               txbuf[0] = 0xD8;
42634 +               txbuf[1] = 0x00;
42635 +               txbuf[2] = row >> 8;
42636 +               txbuf[3] = row & 0xFF;
42637 +               res = spi_write(spi, txbuf, 4);
42638 +               if (res) {
42639 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed block erase res=%d\n", chip->name, res);
42640 +                       instr->fail_addr = block << 17;
42641 +                       instr->state = MTD_ERASE_FAILED;
42642 +                       goto done;
42643 +               }
42644 +
42645 +               /*
42646 +                * Wait
42647 +                */
42648 +               res = nand_spi_er_busywait(chip, &stat);
42649 +               if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42650 +                       instr->fail_addr = block << 17;
42651 +                       instr->state = MTD_ERASE_FAILED;
42652 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42653 +                       if (res) {
42654 +                               goto done;
42655 +                       }
42656 +
42657 +                       /*
42658 +                        * Chip is stuck?
42659 +                        */
42660 +                       res = -EIO;
42661 +                       goto done;
42662 +               }
42663 +
42664 +               /*
42665 +                * Check the status register
42666 +                */
42667 +               if (stat & NAND_SPI_ER_STATUS_E_FAIL) {
42668 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
42669 +                       instr->fail_addr = block << 17;
42670 +                       instr->state = MTD_ERASE_FAILED;
42671 +                       goto done;
42672 +               }
42673 +
42674 +               /*
42675 +                * Next
42676 +                */
42677 +               block++;
42678 +               instr->len -= chip->device->erase_size;
42679 +               instr->addr += chip->device->erase_size;
42680 +       }
42681 +
42682 +       instr->state = MTD_ERASE_DONE;
42683 +
42684 +       mutex_unlock(&chip->lock);
42685 +       return 0;
42686 +
42687 +done:
42688 +       /*
42689 +        * Write disable
42690 +        */
42691 +       txbuf[0] = 0x04;
42692 +       res = spi_write(spi, txbuf, 1);
42693 +       if (res) {
42694 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
42695 +       }
42696 +
42697 +       mutex_unlock(&chip->lock);
42698 +
42699 +       mtd_erase_callback(instr);
42700 +       return 0;
42701 +}
42702 +
42703 +/*
42704 + * nand_spi_er_read
42705 + *
42706 + * return -EUCLEAN: ecc error recovered
42707 + * return -EBADMSG: ecc error not recovered
42708 +*/
42709 +static int nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
42710 +                              size_t *retlen, u_char *buf)
42711 +{
42712 +       struct nand_spi_er *chip = mtd->priv;
42713 +       struct spi_device *spi = chip->spi;
42714 +
42715 +       uint32_t row;
42716 +       uint32_t column;
42717 +       int retval = 0;
42718 +
42719 +       *retlen = 0;
42720 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
42721 +
42722 +       /*
42723 +        * Zero length reads, nothing to do
42724 +        */
42725 +       if (len == 0) {
42726 +               return 0;
42727 +       }
42728 +
42729 +       /*
42730 +        * Reject reads which go over the end of the flash
42731 +        */
42732 +       if ((from + len) > mtd->size) {
42733 +               return -EINVAL;
42734 +       }
42735 +
42736 +       /*
42737 +        * Get the row and column address to start at
42738 +        */
42739 +       row = from >> 11;
42740 +       column = from & 0x7FF;
42741 +       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);
42742 +
42743 +       /*
42744 +        * Read the data from the chip
42745 +        */
42746 +       mutex_lock(&chip->lock);
42747 +       while (len) {
42748 +               uint8_t stat;
42749 +               uint8_t txbuf[4];
42750 +               struct spi_message message;
42751 +               struct spi_transfer x[2];
42752 +               int res;
42753 +               size_t toread;
42754 +
42755 +               /*
42756 +                * Figure out how much to read
42757 +                *
42758 +                * If we are reading from the middle of a page then the most we
42759 +                * can read is to the end of the page
42760 +                */
42761 +               toread = len;
42762 +               if (toread > (chip->device->page_size - column)) {
42763 +                       toread = chip->device->page_size - column;
42764 +               }
42765 +
42766 +               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);
42767 +
42768 +               if (chip->last_row != row) {
42769 +                       /*
42770 +                        * Check if the block is bad
42771 +                        */
42772 +                       if (test_bit(NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
42773 +                               mutex_unlock(&chip->lock);
42774 +                               return -EBADMSG;
42775 +                       }
42776 +
42777 +                       /*
42778 +                        * Load the appropriate page
42779 +                        */
42780 +                       txbuf[0] = 0x13;
42781 +                       txbuf[1] = 0x00;
42782 +                       txbuf[2] = row >> 8;
42783 +                       txbuf[3] = row & 0xFF;
42784 +                       res = spi_write(spi, txbuf, 4);
42785 +                       if (res) {
42786 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed page load res=%d\n", chip->name, res);
42787 +                               mutex_unlock(&chip->lock);
42788 +                               return res;
42789 +                       }
42790 +
42791 +                       /*
42792 +                        * Wait
42793 +                        */
42794 +                       res = nand_spi_er_busywait(chip, &stat);
42795 +                       if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42796 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42797 +                               if (res) {
42798 +                                       mutex_unlock(&chip->lock);
42799 +                                       return res;
42800 +                               }
42801 +
42802 +                               /*
42803 +                                * Chip is stuck?
42804 +                                */
42805 +                               mutex_unlock(&chip->lock);
42806 +                               return -EIO;
42807 +                       }
42808 +
42809 +                       /*
42810 +                        * Check the ECC bits
42811 +                        */
42812 +                       stat >>= 4;
42813 +                       if (stat == 1) {
42814 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
42815 +                               retval = -EUCLEAN;
42816 +                       }
42817 +                       if (stat == 2) {
42818 +                               DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
42819 +                               chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42820 +                               mutex_unlock(&chip->lock);
42821 +                               return -EBADMSG;
42822 +                       }
42823 +
42824 +               }
42825 +
42826 +               chip->last_row = row;
42827 +
42828 +               /*
42829 +                * Read out the data
42830 +                */
42831 +               spi_message_init(&message);
42832 +               memset(x, 0, sizeof(x));
42833 +
42834 +               txbuf[0] = 0x03;
42835 +               txbuf[1] = column >> 8;
42836 +               txbuf[2] = column & 0xFF;
42837 +               txbuf[3] = 0;
42838 +               x[0].tx_buf = txbuf;
42839 +               x[0].len = 4;
42840 +               spi_message_add_tail(&x[0], &message);
42841 +
42842 +               x[1].rx_buf = buf;
42843 +               x[1].len = toread;
42844 +               spi_message_add_tail(&x[1], &message);
42845 +
42846 +               res = spi_sync(spi, &message);
42847 +               if (res) {
42848 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed data read res=%d\n", chip->name, res);
42849 +                       mutex_unlock(&chip->lock);
42850 +                       return res;
42851 +               }
42852 +               buf += toread;
42853 +               len -= toread;
42854 +               *retlen += toread;
42855 +
42856 +               /*
42857 +                * For the next page, increment the row and always start at column 0
42858 +                */
42859 +               column = 0;
42860 +               row++;
42861 +       }
42862 +
42863 +       mutex_unlock(&chip->lock);
42864 +       return retval;
42865 +}
42866 +
42867 +/*
42868 + * nand_spi_er_write
42869 + */
42870 +#define NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
42871 +static int nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
42872 +                               size_t *retlen, const u_char *buf)
42873 +{
42874 +       struct nand_spi_er *chip = mtd->priv;
42875 +       struct spi_device *spi = chip->spi;
42876 +       const struct nand_spi_er_device *device = chip->device;
42877 +       uint32_t row;
42878 +       uint32_t col;
42879 +       uint8_t txbuf[4];
42880 +       int res;
42881 +       size_t towrite;
42882 +
42883 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
42884 +
42885 +       *retlen = 0;
42886 +
42887 +       /*
42888 +        * nothing to write
42889 +        */
42890 +       if (!len) {
42891 +               return 0;
42892 +       }
42893 +
42894 +       /*
42895 +        * Reject writes which go over the end of the flash
42896 +        */
42897 +       if ((to + len) > mtd->size) {
42898 +               return -EINVAL;
42899 +       }
42900 +
42901 +       /*
42902 +        * Check to see if everything is page aligned
42903 +        */
42904 +       if (NOT_ALIGNED(to) || NOT_ALIGNED(len)) {
42905 +               printk(KERN_NOTICE "nand_spi_er_write: Attempt to write non page aligned data\n");
42906 +               return -EINVAL;
42907 +       }
42908 +
42909 +       mutex_lock(&chip->lock);
42910 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42911 +
42912 +       /*
42913 +        * If the first write is a partial write then write at most the number of
42914 +        * bytes to get us page aligned and then the remainder will be
42915 +        * page aligned.  The last bit may be a partial page as well.
42916 +        */
42917 +       col = to & (device->page_size - 1);
42918 +       towrite = device->page_size - col;
42919 +       if (towrite > len) {
42920 +               towrite = len;
42921 +       }
42922 +
42923 +       /*
42924 +        * Write the data
42925 +        */
42926 +       row = to >> 11;
42927 +       while (len) {
42928 +               struct spi_message message;
42929 +               struct spi_transfer x[2];
42930 +               uint8_t stat;
42931 +
42932 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
42933 +
42934 +               /*
42935 +                * Write enable
42936 +                */
42937 +               txbuf[0] = 0x06;
42938 +               res = spi_write(spi, txbuf, 1);
42939 +               if (res) {
42940 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
42941 +                       mutex_unlock(&chip->lock);
42942 +                       return res;
42943 +               }
42944 +
42945 +               /*
42946 +                * Write the data into the cache
42947 +                */
42948 +               spi_message_init(&message);
42949 +               memset(x, 0, sizeof(x));
42950 +               txbuf[0] = 0x02;
42951 +               txbuf[1] = col >> 8;
42952 +               txbuf[2] = col & 0xFF;
42953 +               x[0].tx_buf = txbuf;
42954 +               x[0].len = 3;
42955 +               spi_message_add_tail(&x[0], &message);
42956 +               x[1].tx_buf = buf;
42957 +               x[1].len = towrite;
42958 +               spi_message_add_tail(&x[1], &message);
42959 +               res = spi_sync(spi, &message);
42960 +               if (res) {
42961 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed cache write res=%d\n", chip->name, res);
42962 +                       goto done;
42963 +               }
42964 +
42965 +               /*
42966 +                * Program execute
42967 +                */
42968 +               txbuf[0] = 0x10;
42969 +               txbuf[1] = 0x00;
42970 +               txbuf[2] = row >> 8;
42971 +               txbuf[3] = row & 0xFF;
42972 +               res = spi_write(spi, txbuf, 4);
42973 +               if (res) {
42974 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: failed prog execute res=%d\n", chip->name, res);
42975 +                       goto done;
42976 +               }
42977 +
42978 +               /*
42979 +                * Wait
42980 +                */
42981 +               res = nand_spi_er_busywait(chip, &stat);
42982 +               if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42983 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42984 +                       if (res) {
42985 +                               goto done;
42986 +                       }
42987 +
42988 +                       /*
42989 +                        * Chip is stuck?
42990 +                        */
42991 +                       res = -EIO;
42992 +                       goto done;
42993 +               }
42994 +
42995 +               if (stat & (1 << 3)) {
42996 +                       res = -EBADMSG;
42997 +                       goto done;
42998 +               }
42999 +
43000 +               row++;
43001 +               buf += towrite;
43002 +               len -= towrite;
43003 +               *retlen += towrite;
43004 +
43005 +               /*
43006 +                * At this point, we are always page aligned so start at column 0.
43007 +                * Note we may not have a full page to write at the end, hence the
43008 +                * check if towrite > len.
43009 +                */
43010 +               col = 0;
43011 +               towrite = device->page_size;
43012 +               if (towrite > len) {
43013 +                       towrite = len;
43014 +               }
43015 +       }
43016 +
43017 +       mutex_unlock(&chip->lock);
43018 +       return res;
43019 +
43020 +done:
43021 +       /*
43022 +        * Write disable
43023 +        */
43024 +       txbuf[0] = 0x04;
43025 +       res = spi_write(spi, txbuf, 1);
43026 +       if (res) {
43027 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43028 +       }
43029 +
43030 +       mutex_unlock(&chip->lock);
43031 +
43032 +       return res;
43033 +}
43034 +
43035 +/*
43036 + * nand_spi_er_isbad
43037 + */
43038 +static int nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
43039 +{
43040 +       struct nand_spi_er *chip = mtd->priv;
43041 +       uint32_t block;
43042 +
43043 +       if (ofs & (chip->device->erase_size - 1)) {
43044 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43045 +               return -EINVAL;
43046 +       }
43047 +
43048 +       block = ofs >> 17;
43049 +
43050 +       return test_bit(block, chip->bbt);
43051 +}
43052 +
43053 +/*
43054 + * nand_spi_er_markbad
43055 + */
43056 +static int nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
43057 +{
43058 +       struct nand_spi_er *chip = mtd->priv;
43059 +       struct spi_device *spi = chip->spi;
43060 +       uint32_t block;
43061 +       uint32_t row;
43062 +       uint8_t txbuf[7];
43063 +       int res;
43064 +       uint8_t stat;
43065 +
43066 +       if (ofs & (chip->device->erase_size - 1)) {
43067 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43068 +               return -EINVAL;
43069 +       }
43070 +
43071 +       block = ofs >> 17;
43072 +
43073 +       /*
43074 +        * If it's already marked bad, no need to mark it
43075 +        */
43076 +       if (test_bit(block, chip->bbt)) {
43077 +               return 0;
43078 +       }
43079 +
43080 +       /*
43081 +        * Mark it in our cache
43082 +        */
43083 +       __set_bit(block, chip->bbt);
43084 +
43085 +       /*
43086 +        * Write the user bad block mark.  If it fails, then we really
43087 +        * can't do anything about it.
43088 +        */
43089 +       mutex_lock(&chip->lock);
43090 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43091 +
43092 +       /*
43093 +        * Write enable
43094 +        */
43095 +       txbuf[0] = 0x06;
43096 +       res = spi_write(spi, txbuf, 1);
43097 +       if (res) {
43098 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
43099 +               mutex_unlock(&chip->lock);
43100 +               return res;
43101 +       }
43102 +
43103 +       /*
43104 +        * Write the mark
43105 +        */
43106 +       txbuf[0] = 0x84;
43107 +       txbuf[1] = 0x08;
43108 +       txbuf[2] = NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET;
43109 +       txbuf[3] = 0xde;
43110 +       txbuf[4] = 0xad;
43111 +       txbuf[5] = 0xbe;
43112 +       txbuf[6] = 0xef;
43113 +       res = spi_write(spi, txbuf, 7);
43114 +       if (res) {
43115 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write mark res=%d\n", chip->name, res);
43116 +               goto done;
43117 +       }
43118 +
43119 +       /*
43120 +        * Program execute
43121 +        */
43122 +       row = ofs >> 11;
43123 +       txbuf[0] = 0x10;
43124 +       txbuf[1] = 0x00;
43125 +       txbuf[2] = row >> 8;
43126 +       txbuf[3] = row & 0xFF;
43127 +       res = spi_write(spi, txbuf, 4);
43128 +       if (res) {
43129 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed program execute res=%d\n", chip->name, res);
43130 +               goto done;
43131 +       }
43132 +
43133 +       /*
43134 +        * Wait
43135 +        */
43136 +       res = nand_spi_er_busywait(chip, &stat);
43137 +       if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43138 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43139 +               if (res) {
43140 +                       goto done;
43141 +               }
43142 +
43143 +               /*
43144 +                * Chip is stuck?
43145 +                */
43146 +               res = -EIO;
43147 +               goto done;
43148 +       }
43149 +
43150 +       if (stat & (1 << 3)) {
43151 +               res = -EBADMSG;
43152 +       }
43153 +
43154 +done:
43155 +       /*
43156 +        * Write disable
43157 +        */
43158 +       txbuf[0] = 0x04;
43159 +       res = spi_write(spi, txbuf, 1);
43160 +       if (res) {
43161 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43162 +       }
43163 +
43164 +       mutex_unlock(&chip->lock);
43165 +
43166 +       return res;
43167 +}
43168 +
43169 +/*
43170 + * nand_spi_er_read_bbt
43171 + */
43172 +static int nand_spi_er_read_bbt(struct nand_spi_er *chip)
43173 +{
43174 +       int j;
43175 +       for (j = 0; j < chip->device->blocks; j++) {
43176 +               uint8_t txbuf[4];
43177 +               uint8_t rxbuf[16];
43178 +               uint32_t bbmark;
43179 +               int res;
43180 +               unsigned short row = j << 6;
43181 +               uint8_t stat;
43182 +
43183 +               /*
43184 +                * Read Page
43185 +                */
43186 +               txbuf[0] = 0x13;
43187 +               txbuf[1] = 0x00;
43188 +               txbuf[2] = row >> 8;
43189 +               txbuf[3] = row & 0xFF;
43190 +               res = spi_write(chip->spi, txbuf, 4);
43191 +               if (res) {
43192 +                       return res;
43193 +               }
43194 +
43195 +               /*
43196 +                * Wait
43197 +                */
43198 +               res = nand_spi_er_busywait(chip, &stat);
43199 +               if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43200 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43201 +                       if (res) {
43202 +                               return res;
43203 +                       }
43204 +
43205 +                       /*
43206 +                        * Chip is stuck?
43207 +                        */
43208 +                       return -EIO;
43209 +               }
43210 +
43211 +               /*
43212 +                * Check factory bad block mark
43213 +                */
43214 +               txbuf[0] = 0x03;
43215 +               txbuf[1] = 0x08;
43216 +               txbuf[2] = 0x00;
43217 +               txbuf[3] = 0x00;
43218 +               res = spi_write_then_read(chip->spi, txbuf, 4, rxbuf, 16);
43219 +               if (res) {
43220 +                       return res;
43221 +               }
43222 +               if (rxbuf[0] != 0xFF) {
43223 +                       chip->nbb++;
43224 +                       __set_bit(j, chip->bbt);
43225 +                       continue;
43226 +               }
43227 +
43228 +               memcpy(&bbmark, &rxbuf[8], 4);
43229 +               if (bbmark == 0xdeadbeef) {
43230 +                       chip->nbb++;
43231 +                       __set_bit(j, chip->bbt);
43232 +               }
43233 +       }
43234 +
43235 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
43236 +       printk("%s: Bad Block Table:", chip->name);
43237 +       for (j = 0; j < chip->device->blocks; j++) {
43238 +               if ((j % 64) == 0) {
43239 +                       printk("\n%s: block %03x: ", chip->name, j);
43240 +               }
43241 +               printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
43242 +       }
43243 +       printk("\n%s: Bad Block Numbers: ", chip->name);
43244 +       for (j = 0; j < chip->device->blocks; j++) {
43245 +               if (test_bit(j, chip->bbt)) {
43246 +                       printk("%x ", j);
43247 +               }
43248 +       }
43249 +       printk("\n");
43250 +#endif
43251 +
43252 +       return 0;
43253 +}
43254 +
43255 +#ifndef MODULE
43256 +/*
43257 + * Called at boot time:
43258 + *
43259 + * nand_spi_er=read_only
43260 + *     if read_only specified then do not unlock device
43261 + */
43262 +static int __init nand_spi_er_setup(char *str)
43263 +{
43264 +       if (str && (strncasecmp(str, "read_only", 9) == 0)) {
43265 +               read_only = 1;
43266 +       }
43267 +       return 0;
43268 +}
43269 +
43270 +__setup("nand_spi_er=", nand_spi_er_setup);
43271 +#endif
43272 +
43273 +/*
43274 + * nand_spi_er_probe
43275 + *     Detect and initialize nand_spi_er device.
43276 + */
43277 +static int __devinit nand_spi_er_probe(struct spi_device *spi)
43278 +{
43279 +       uint8_t txbuf[3];
43280 +       uint8_t rxbuf[2];
43281 +       int i;
43282 +       int res;
43283 +       size_t bbt_bytes;
43284 +       struct nand_spi_er *chip;
43285 +       const struct nand_spi_er_device *device;
43286 +
43287 +       res = spi_setup(spi);
43288 +       if (res) {
43289 +               return res;
43290 +       }
43291 +
43292 +       /*
43293 +        * Reset
43294 +        */
43295 +       for (i = 0; i < 2; i++) {
43296 +               txbuf[0] = 0xFF;
43297 +               res = spi_write(spi, txbuf, 1);
43298 +               if (res) {
43299 +                       return res;
43300 +               }
43301 +               udelay(250);
43302 +       }
43303 +       udelay(1000);
43304 +
43305 +       /*
43306 +        * Read ID
43307 +        */
43308 +       txbuf[0] = 0x9F;
43309 +       txbuf[1] = 0x00;
43310 +       res = spi_write_then_read(spi, txbuf, 2, rxbuf, 2);
43311 +       if (res) {
43312 +               return res;
43313 +       }
43314 +
43315 +       device = nand_spi_er_devices;
43316 +       for (i = 0; i < ARRAY_SIZE(nand_spi_er_devices); i++) {
43317 +               if ((device->id0 == rxbuf[0]) && (device->id1 == rxbuf[1])) {
43318 +                       break;
43319 +               }
43320 +               device++;
43321 +       }
43322 +       if (i == ARRAY_SIZE(nand_spi_er_devices)) {
43323 +               return -ENODEV;
43324 +       }
43325 +
43326 +       /*
43327 +        * Initialize our chip structure
43328 +        */
43329 +       bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
43330 +       chip = kzalloc(sizeof(struct nand_spi_er) + bbt_bytes, GFP_KERNEL);
43331 +       if (!chip) {
43332 +               return -ENOMEM;
43333 +       }
43334 +       snprintf(chip->name, sizeof(chip->name), "%s.%d.%d", device->name, spi->master->bus_num, spi->chip_select);
43335 +
43336 +       chip->spi = spi;
43337 +       chip->device = device;
43338 +       chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43339 +
43340 +       mutex_init(&chip->lock);
43341 +
43342 +       chip->mtd.type = MTD_NANDFLASH;
43343 +       chip->mtd.flags = MTD_WRITEABLE;
43344 +
43345 +       /*
43346 +        * #blocks * block size * n blocks
43347 +        */
43348 +       chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
43349 +       chip->mtd.erasesize = device->erase_size;
43350 +
43351 +       /*
43352 +        * 1 page, optionally we can support partial write (512)
43353 +        */
43354 +       chip->mtd.writesize = device->write_size;
43355 +       chip->mtd.name = device->name;
43356 +       chip->mtd.erase = nand_spi_er_erase;
43357 +       chip->mtd.read = nand_spi_er_read;
43358 +       chip->mtd.write = nand_spi_er_write;
43359 +       chip->mtd.block_isbad = nand_spi_er_isbad;
43360 +       chip->mtd.block_markbad = nand_spi_er_markbad;
43361 +       chip->mtd.priv = chip;
43362 +
43363 +       /*
43364 +        * Cache the bad block table
43365 +        */
43366 +       res = nand_spi_er_read_bbt(chip);
43367 +       if (res) {
43368 +               kfree(chip);
43369 +               return res;
43370 +       }
43371 +
43372 +       /*
43373 +        * Un/lock the chip
43374 +        */
43375 +       txbuf[0] = 0x1F;
43376 +       txbuf[1] = 0xA0;
43377 +       if (read_only) {
43378 +               txbuf[2] = 0x38;
43379 +       } else {
43380 +               txbuf[2] = 0x00;
43381 +       }
43382 +       res = spi_write(spi, txbuf, 3);
43383 +       if (res) {
43384 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: failed lock operation res=%d\n", chip->name, res);
43385 +               mutex_unlock(&chip->lock);
43386 +               return res;
43387 +       }
43388 +
43389 +       spi_set_drvdata(spi, chip);
43390 +
43391 +       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]" : "");
43392 +       return add_mtd_device(&chip->mtd);
43393 +}
43394 +
43395 +/*
43396 + * nand_spi_er_remove
43397 + */
43398 +static int __devexit nand_spi_er_remove(struct spi_device *spi)
43399 +{
43400 +       struct nand_spi_er *chip = spi_get_drvdata(spi);
43401 +       int status = 0;
43402 +
43403 +       DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
43404 +       status = del_mtd_device(&chip->mtd);
43405 +       if (status == 0)
43406 +               kfree(chip);
43407 +       return status;
43408 +}
43409 +
43410 +static struct spi_driver nand_spi_er_driver = {
43411 +       .driver = {
43412 +               .name           = "nand-spi-er",
43413 +               .bus            = &spi_bus_type,
43414 +               .owner          = THIS_MODULE,
43415 +       },
43416 +
43417 +       .probe          = nand_spi_er_probe,
43418 +       .remove         = __devexit_p(nand_spi_er_remove),
43419 +
43420 +       /* FIXME:  investigate suspend and resume... */
43421 +};
43422 +
43423 +/*
43424 + * nand_spi_er_init
43425 + */
43426 +static int __init nand_spi_er_init(void)
43427 +{
43428 +       return spi_register_driver(&nand_spi_er_driver);
43429 +}
43430 +module_init(nand_spi_er_init);
43431 +
43432 +/*
43433 + * nand_spi_er_exit
43434 + */
43435 +static void __exit nand_spi_er_exit(void)
43436 +{
43437 +       spi_unregister_driver(&nand_spi_er_driver);
43438 +}
43439 +module_exit(nand_spi_er_exit);
43440 +
43441 +
43442 +MODULE_LICENSE("GPL");
43443 +MODULE_AUTHOR("Patrick Tjin");
43444 +MODULE_DESCRIPTION("MTD nand_spi_er driver");
43445 --- /dev/null
43446 +++ b/drivers/mtd/devices/ubi32-m25p80.c
43447 @@ -0,0 +1,1066 @@
43448 +/*
43449 + * drivers/mtd/devices/ubi32-m25p80.c
43450 + *   NOR flash driver, Ubicom processor internal SPI flash interface.
43451 + *
43452 + *   This code instantiates the serial flash that contains the
43453 + *   original bootcode.  The serial flash start at address 0x60000000
43454 + *   in both Ubicom32V3 and Ubicom32V4 ISAs.
43455 + *
43456 + *   This piece of flash is made to appear as a Memory Technology
43457 + *   Device (MTD) with this driver to allow Read/Write/Erase operations.
43458 + *
43459 + * (C) Copyright 2009, Ubicom, Inc.
43460 + *
43461 + * This file is part of the Ubicom32 Linux Kernel Port.
43462 + *
43463 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
43464 + * it and/or modify it under the terms of the GNU General Public License
43465 + * as published by the Free Software Foundation, either version 2 of the
43466 + * License, or (at your option) any later version.
43467 + *
43468 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
43469 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
43470 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
43471 + * the GNU General Public License for more details.
43472 + *
43473 + * You should have received a copy of the GNU General Public License
43474 + * along with the Ubicom32 Linux Kernel Port.  If not,
43475 + * see <http://www.gnu.org/licenses/>.
43476 + *
43477 + * Ubicom32 implementation derived from (with many thanks):
43478 + *   arch/m68knommu
43479 + *   arch/blackfin
43480 + *   arch/parisc
43481 + */
43482 +#include <linux/types.h>
43483 +#include <linux/device.h>
43484 +#include <linux/platform_device.h>
43485 +#include <linux/mtd/mtd.h>
43486 +#include <linux/mtd/partitions.h>
43487 +#include <linux/mtd/physmap.h>
43488 +#include <linux/spi/spi.h>
43489 +#include <linux/spi/flash.h>
43490 +
43491 +#include <linux/init.h>
43492 +#include <linux/module.h>
43493 +#include <linux/interrupt.h>
43494 +#include <linux/mutex.h>
43495 +
43496 +#include <asm/ip5000.h>
43497 +#include <asm/devtree.h>
43498 +
43499 +#define UBICOM32_FLASH_BASE    0x60000000
43500 +#define UBICOM32_FLASH_MAX_SIZE 0x01000000
43501 +#define UBICOM32_FLASH_START   0x00000000
43502 +#define UBICOM32_KERNEL_OFFSET 0x00010000 /* The kernel starts after Ubicom
43503 +                                           * .protect section. */
43504 +
43505 +static struct mtd_partition ubicom32_flash_partitions[] = {
43506 +       {
43507 +               .name   = "Bootloader",         /* Protected Section
43508 +                                                * Partition */
43509 +               .size   = 0x10000,
43510 +               .offset = UBICOM32_FLASH_START,
43511 +//             .mask_flags = MTD_WRITEABLE     /* Mark Read-only */
43512 +       },
43513 +       {
43514 +               .name   = "Kernel",             /* Kernel Partition. */
43515 +               .size   = 0,                    /* this will be set up during
43516 +                                                * probe stage. At that time we
43517 +                                                * will know end of linux image
43518 +                                                * in flash. */
43519 +               .offset = MTDPART_OFS_APPEND,   /* Starts right after Protected
43520 +                                                * section. */
43521 +//             .mask_flags = MTD_WRITEABLE     /* Mark Read-only */
43522 +       },
43523 +       {
43524 +               .name   = "Rest",               /* Rest of the flash. */
43525 +               .size   = 0x200000,             /* Use up what remains in the
43526 +                                                * flash. */
43527 +               .offset = MTDPART_OFS_NXTBLK,   /* Starts right after Protected
43528 +                                                * section. */
43529 +       }
43530 +};
43531 +
43532 +static struct flash_platform_data ubicom32_flash_data = {
43533 +       .name = "ubicom32_boot_flash",
43534 +       .parts = ubicom32_flash_partitions,
43535 +       .nr_parts = ARRAY_SIZE(ubicom32_flash_partitions),
43536 +};
43537 +
43538 +static struct resource ubicom32_flash_resource[] = {
43539 +       {
43540 +               .start  = UBICOM32_FLASH_BASE,
43541 +               .end    = UBICOM32_FLASH_BASE +
43542 +               UBICOM32_FLASH_MAX_SIZE - 1,
43543 +               .flags  = IORESOURCE_MEM,
43544 +       },
43545 +};
43546 +
43547 +static struct platform_device ubicom32_flash_device = {
43548 +       .name = "ubicom32flashdriver",
43549 +       .id = 0, /* Bus number */
43550 +       .num_resources = ARRAY_SIZE(ubicom32_flash_resource),
43551 +       .resource = ubicom32_flash_resource,
43552 +       .dev = {
43553 +               .platform_data = &ubicom32_flash_data,
43554 +       },
43555 +};
43556 +
43557 +static struct platform_device *ubicom32_flash_devices[] = {
43558 +       &ubicom32_flash_device,
43559 +};
43560 +
43561 +static int __init ubicom32_flash_init(void)
43562 +{
43563 +       printk(KERN_INFO "%s(): registering device resources\n",
43564 +              __FUNCTION__);
43565 +       platform_add_devices(ubicom32_flash_devices,
43566 +                            ARRAY_SIZE(ubicom32_flash_devices));
43567 +       return 0;
43568 +}
43569 +
43570 +arch_initcall(ubicom32_flash_init);
43571 +
43572 +/*
43573 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips through
43574 + * Ubicom32 SPI controller.
43575 + *
43576 + * Author: Mike Lavender, mike@steroidmicros.com
43577 + *
43578 + * Copyright (c) 2005, Intec Automation Inc.
43579 + *
43580 + * Some parts are based on lart.c by Abraham Van Der Merwe
43581 + *
43582 + * Cleaned up and generalized based on mtd_dataflash.c
43583 + *
43584 + * This code is free software; you can redistribute it and/or modify
43585 + * it under the terms of the GNU General Public License version 2 as
43586 + * published by the Free Software Foundation.
43587 + *
43588 + */
43589 +
43590 +#define FLASH_PAGESIZE         256
43591 +
43592 +/* Flash opcodes. */
43593 +#define        OPCODE_WREN             0x06    /* Write enable */
43594 +#define        OPCODE_RDSR             0x05    /* Read status register */
43595 +#define        OPCODE_READ             0x03    /* Read data bytes (low frequency) */
43596 +#define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
43597 +#define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
43598 +#define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
43599 +#define        OPCODE_BE_32K           0x52    /* Erase 32KiB block */
43600 +#define        OPCODE_SE               0xd8    /* Sector erase (usually 64KiB) */
43601 +#define        OPCODE_RDID             0x9f    /* Read JEDEC ID */
43602 +
43603 +/* Status Register bits. */
43604 +#define        SR_WIP                  1       /* Write in progress */
43605 +#define        SR_WEL                  2       /* Write enable latch */
43606 +/* meaning of other SR_* bits may differ between vendors */
43607 +#define        SR_BP0                  4       /* Block protect 0 */
43608 +#define        SR_BP1                  8       /* Block protect 1 */
43609 +#define        SR_BP2                  0x10    /* Block protect 2 */
43610 +#define        SR_SRWD                 0x80    /* SR write protect */
43611 +
43612 +/* Define max times to check status register before we give up. */
43613 +#define        MAX_READY_WAIT_COUNT    100000
43614 +
43615 +
43616 +#ifdef CONFIG_MTD_PARTITIONS
43617 +#define        mtd_has_partitions()    (1)
43618 +#else
43619 +#define        mtd_has_partitions()    (0)
43620 +#endif
43621 +
43622 +/*
43623 + * Ubicom32 FLASH Command Set
43624 + */
43625 +#define FLASH_FC_INST_CMD      0x00    /* for SPI command only transaction */
43626 +#define FLASH_FC_INST_WR       0x01    /* for SPI write transaction */
43627 +#define FLASH_FC_INST_RD       0x02    /* for SPI read transaction */
43628 +
43629 +#define ALIGN_DOWN(v, a) ((v) & ~((a) - 1))
43630 +#define ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1))
43631 +
43632 +#define        FLASH_COMMAND_KICK_OFF(io)                                                      \
43633 +       asm volatile(                                                                   \
43634 +       "       bset    "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)")   \n\t"   \
43635 +       "       jmpt.t  .+4                                                     \n\t"   \
43636 +       "       bset    "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)")  \n\t"   \
43637 +               :                                                                       \
43638 +               : "a" (io)                                                              \
43639 +               : "memory", "cc"                                                        \
43640 +       );
43641 +
43642 +#define        FLASH_COMMAND_WAIT_FOR_COMPLETION(io)                                           \
43643 +       asm volatile(                                                                   \
43644 +       "       btst    "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)")    \n\t"   \
43645 +       "       jmpeq.f .-4                                                     \n\t"   \
43646 +               :                                                                       \
43647 +               : "a" (io)                                                              \
43648 +               : "memory", "cc"                                                                        \
43649 +       );
43650 +
43651 +#define        FLASH_COMMAND_EXEC(io)                                                          \
43652 +       FLASH_COMMAND_KICK_OFF(io)                                                      \
43653 +       FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
43654 +
43655 +
43656 +#define OSC1_FREQ 12000000
43657 +#define TEN_MICRO_SECONDS (OSC1_FREQ * 10 / 1000000)
43658 +
43659 +/*
43660 + * We will have to eventually replace this null definition with the real thing.
43661 + */
43662 +#define WATCHDOG_RESET()
43663 +
43664 +#define EXTFLASH_WRITE_FIFO_SIZE 32
43665 +#define EXTFLASH_WRITE_BLOCK_SIZE EXTFLASH_WRITE_FIFO_SIZE /* limit the size to
43666 +                                                           * FIFO capacity, so
43667 +                                                           * the thread can be
43668 +                                                           * suspended. */
43669 +
43670 +#define JFFS2_FILESYSTEM_SIZE 0x100000
43671 +
43672 +/****************************************************************************/
43673 +
43674 +struct m25p {
43675 +       struct platform_device  *plt_dev;
43676 +       struct mutex            lock;
43677 +       struct mtd_info         mtd;
43678 +       unsigned                partitioned:1;
43679 +       u8                      erase_opcode;
43680 +       u8                      command[4];
43681 +};
43682 +
43683 +static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
43684 +{
43685 +       return container_of(mtd, struct m25p, mtd);
43686 +}
43687 +
43688 +/****************************************************************************/
43689 +
43690 +/*
43691 + * Internal helper functions
43692 + */
43693 +
43694 +/*
43695 + * Read the status register, returning its value in the location
43696 + * Return the status register value.
43697 + * Returns negative if error occurred.
43698 + */
43699 +static int read_sr(struct m25p *flash)
43700 +{
43701 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43702 +
43703 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
43704 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43705 +               IO_XFL_CTL1_FC_DATA(1);
43706 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
43707 +       FLASH_COMMAND_EXEC(io);
43708 +
43709 +       return io->status1 & 0xff;
43710 +}
43711 +
43712 +/*
43713 + * mem_flash_io_read_u32()
43714 + */
43715 +static u32 mem_flash_io_read_u32(u32 addr)
43716 +{
43717 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43718 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
43719 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43720 +               IO_XFL_CTL1_FC_DATA(4) | IO_XFL_CTL1_FC_DUMMY(1) |
43721 +               IO_XFL_CTL1_FC_ADDR;
43722 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_FAST_READ) |
43723 +               IO_XFL_CTL2_FC_ADDR(addr);
43724 +       FLASH_COMMAND_EXEC(io);
43725 +       return io->status1;
43726 +}
43727 +
43728 +/*
43729 + * mem_flash_read_u8()
43730 + */
43731 +static u8 mem_flash_read_u8(u32 addr)
43732 +{
43733 +       u32 tmp_addr = ALIGN_DOWN(addr, 4);
43734 +       u32 tmp_data = mem_flash_io_read_u32(tmp_addr);
43735 +       u8 *ptr = (u8 *)&tmp_data;
43736 +       return ptr[addr & 0x3];
43737 +}
43738 +
43739 +/*
43740 + * mem_flash_read()
43741 + *     No need to lock as read is implemented with ireads (same as normal flash
43742 + *     execution).
43743 + */
43744 +static void mem_flash_read(u32 addr, void *dst, size_t length)
43745 +{
43746 +       /*
43747 +        * Range check
43748 +        */
43749 +       /*
43750 +        * Fix source alignment.
43751 +        */
43752 +       while (addr & 0x03) {
43753 +               if (length == 0) {
43754 +                       return;
43755 +               }
43756 +               *((u8 *)dst) = mem_flash_read_u8(addr++);
43757 +               dst++;
43758 +               length--;
43759 +       }
43760 +
43761 +       while (length >= 4) {
43762 +               u32 tmp_data = mem_flash_io_read_u32(addr);
43763 +               addr += 4;
43764 +               length -= 4;
43765 +
43766 +               /*
43767 +                * Send the data to the destination.
43768 +                */
43769 +               memcpy((void *)dst, (void *)&tmp_data, 4);
43770 +               dst += 4;
43771 +       }
43772 +
43773 +       while (length--) {
43774 +               *((u8 *)dst) = mem_flash_read_u8(addr++);
43775 +               dst++;
43776 +       }
43777 +}
43778 +
43779 +/*
43780 + * mem_flash_wait_until_complete()
43781 + */
43782 +static void mem_flash_wait_until_complete(void)
43783 +{
43784 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43785 +
43786 +       do {
43787 +               /*
43788 +                * Put a delay here to deal with flash programming problem.
43789 +                */
43790 +               u32 mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
43791 +               while (UBICOM32_IO_TIMER->mptval < mptval)
43792 +                       ;
43793 +
43794 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
43795 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43796 +                       IO_XFL_CTL1_FC_DATA(1);
43797 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
43798 +               FLASH_COMMAND_EXEC(io);
43799 +       } while (io->status1 & SR_WIP);
43800 +}
43801 +
43802 +/*
43803 + * mem_flash_write_next()
43804 + */
43805 +static size_t mem_flash_write_next(u32 addr, u8 *buf, size_t length)
43806 +{
43807 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43808 +       u32 data_start = addr;
43809 +       u32 data_end = addr + length;
43810 +       size_t count;
43811 +       u32 i, j;
43812 +
43813 +       /*
43814 +        * Top limit address.
43815 +        */
43816 +       u32 block_start = ALIGN_DOWN(data_start, 4);
43817 +       u32 block_end = block_start + EXTFLASH_WRITE_BLOCK_SIZE;
43818 +
43819 +       union {
43820 +               u8 byte[EXTFLASH_WRITE_BLOCK_SIZE];
43821 +               u32 word[EXTFLASH_WRITE_BLOCK_SIZE / 4];
43822 +       } write_buf;
43823 +
43824 +       u32 *flash_addr = (u32 *)block_start;
43825 +
43826 +       /*
43827 +        * The write block must be limited by FLASH internal buffer.
43828 +        */
43829 +       u32 block_end_align = ALIGN_DOWN(block_end, 256);
43830 +       bool write_needed;
43831 +
43832 +       block_end = (block_end_align > block_start)
43833 +               ? block_end_align : block_end;
43834 +       data_end = (data_end <= block_end) ? data_end : block_end;
43835 +       block_end = ALIGN_UP(data_end, 4);
43836 +       count = data_end - data_start;
43837 +
43838 +       /*
43839 +        * Transfer data to a buffer.
43840 +        */
43841 +       for (i = 0; i < (block_end - block_start) / 4; i++) {
43842 +               /*
43843 +                * The FLASH read can hold D-cache for a long time.
43844 +                * Use I/O operation to read FLASH to avoid starving other
43845 +                * threads, especially HRT.  (Do this for application only)
43846 +                */
43847 +               write_buf.word[i] = mem_flash_io_read_u32(
43848 +                       (u32)(&flash_addr[i]));
43849 +       }
43850 +
43851 +       write_needed = false;
43852 +       for (i = 0, j = (data_start - block_start);
43853 +            i < (data_end - data_start); i++, j++) {
43854 +               write_needed = write_needed || (write_buf.byte[j] != buf[i]);
43855 +               write_buf.byte[j] &= buf[i];
43856 +       }
43857 +
43858 +
43859 +       /*
43860 +        * If the data in FLASH is identical to what to be written. Then skip
43861 +        * it.
43862 +        */
43863 +       if (write_needed) {
43864 +               /*
43865 +                * Write to flash.
43866 +                */
43867 +               void *tmp __attribute__((unused));
43868 +               s32 extra_words;
43869 +
43870 +               asm volatile(
43871 +               "       move.4  %0, %2                                                                  \n\t"
43872 +               "       bset    "D(IO_INT_SET)"(%1), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")        \n\t"
43873 +               "       pipe_flush 0                                                                    \n\t"
43874 +               "       .rept   "D(EXTFLASH_WRITE_FIFO_SIZE / 4)"                                       \n\t"
43875 +               "       move.4  "D(IO_TX_FIFO)"(%1), (%0)4++                                            \n\t"
43876 +               "       .endr                                                                           \n\t"
43877 +                       : "=&a" (tmp)
43878 +                       : "a" (io), "r" (&write_buf.word[0])
43879 +                       : "memory", "cc"
43880 +               );
43881 +
43882 +               /* Lock FLASH for write access. */
43883 +               io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
43884 +
43885 +               /* Command: WREN */
43886 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
43887 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
43888 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
43889 +               FLASH_COMMAND_EXEC(io);
43890 +
43891 +               /* Command: BYTE PROGRAM */
43892 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
43893 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) |
43894 +                       IO_XFL_CTL1_FC_DATA(block_end - block_start) |
43895 +                       IO_XFL_CTL1_FC_ADDR;
43896 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_PP) |
43897 +                       IO_XFL_CTL2_FC_ADDR(block_start);
43898 +               FLASH_COMMAND_KICK_OFF(io);
43899 +
43900 +               extra_words = (s32)(block_end - block_start -
43901 +                                   EXTFLASH_WRITE_FIFO_SIZE) / 4;
43902 +               if (extra_words > 0) {
43903 +                       asm volatile(
43904 +                       "       move.4          %0, %3                          \n\t"
43905 +                       "1:     cmpi            "D(IO_FIFO_LEVEL)"(%1), #4      \n\t"
43906 +                       "       jmpgt.s.t       1b                              \n\t"
43907 +                       "       move.4          "D(IO_TX_FIFO)"(%1), (%0)4++    \n\t"
43908 +                       "       add.4           %2, #-1, %2                     \n\t"
43909 +                       "       jmpgt.t         1b                              \n\t"
43910 +                               : "=&a" (tmp)
43911 +                               : "a" (io), "d" (extra_words),
43912 +                                 "r" (&write_buf.word[EXTFLASH_WRITE_FIFO_SIZE / 4])
43913 +                               : "memory", "cc"
43914 +                       );
43915 +               }
43916 +               FLASH_COMMAND_WAIT_FOR_COMPLETION(io);
43917 +
43918 +               mem_flash_wait_until_complete();
43919 +
43920 +
43921 +               /* Unlock FLASH for cache access. */
43922 +               io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
43923 +       }
43924 +
43925 +       /*
43926 +        * Complete.
43927 +        */
43928 +       return count;
43929 +}
43930 +
43931 +/*
43932 + * mem_flash_write()
43933 + */
43934 +static void mem_flash_write(u32 addr, const void *src, size_t length)
43935 +{
43936 +       /*
43937 +        * Write data
43938 +        */
43939 +       u8_t *ptr = (u8_t *)src;
43940 +       while (length) {
43941 +               size_t count = mem_flash_write_next(addr, ptr, length);
43942 +               addr += count;
43943 +               ptr += count;
43944 +               length -= count;
43945 +       }
43946 +}
43947 +
43948 +/*
43949 + * Service routine to read status register until ready, or timeout occurs.
43950 + * Returns non-zero if error.
43951 + */
43952 +static int wait_till_ready(struct m25p *flash)
43953 +{
43954 +       int count;
43955 +       int sr;
43956 +
43957 +       /* one chip guarantees max 5 msec wait here after page writes,
43958 +        * but potentially three seconds (!) after page erase.
43959 +        */
43960 +       for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
43961 +               u32 mptval;
43962 +               sr = read_sr(flash);
43963 +               if (sr < 0)
43964 +                       break;
43965 +               else if (!(sr & SR_WIP))
43966 +                       return 0;
43967 +
43968 +               /*
43969 +                * Put a 10us delay here to deal with flash programming problem.
43970 +                */
43971 +               mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
43972 +               while ((s32)(mptval - UBICOM32_IO_TIMER->mptval) > 0) {
43973 +                       WATCHDOG_RESET();
43974 +               }
43975 +               /* REVISIT sometimes sleeping would be best */
43976 +       }
43977 +
43978 +       return 1;
43979 +}
43980 +
43981 +/*
43982 + * mem_flash_erase_page()
43983 + */
43984 +static void mem_flash_erase_page(u32 addr)
43985 +{
43986 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43987 +
43988 +       /* Lock FLASH for write access. */
43989 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
43990 +
43991 +       /* Command: WREN */
43992 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
43993 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
43994 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
43995 +       FLASH_COMMAND_EXEC(io);
43996 +
43997 +       /* Command: ERASE */
43998 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
43999 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) |
44000 +               IO_XFL_CTL1_FC_ADDR;
44001 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_SE) |
44002 +               IO_XFL_CTL2_FC_ADDR(addr);
44003 +       FLASH_COMMAND_EXEC(io);
44004 +
44005 +       mem_flash_wait_until_complete();
44006 +
44007 +       /* Unlock FLASH for cache access. */
44008 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
44009 +}
44010 +
44011 +/*
44012 + * mem_flash_erase()
44013 + */
44014 +static u32 mem_flash_erase(u32 addr, u32 length)
44015 +{
44016 +       /*
44017 +        * Calculate the endaddress to be the first address of the page
44018 +        * just beyond this erase section of pages.
44019 +        */
44020 +       u32 endaddr = addr + length;
44021 +
44022 +       /*
44023 +        * Erase.
44024 +        */
44025 +       while (addr < endaddr) {
44026 +               u32 test_addr = addr;
44027 +               mem_flash_erase_page(addr);
44028 +
44029 +               /*
44030 +                * Test how much was erased as actual flash page at this address
44031 +                * may be smaller than the expected page size.
44032 +                */
44033 +               while (test_addr < endaddr) {
44034 +                       /*
44035 +                        * The FLASH read can hold D-cache for a long time.  Use
44036 +                        * I/O operation to read FLASH to avoid starving other
44037 +                        * threads, especially HRT.  (Do this for application
44038 +                        * only)
44039 +                        */
44040 +                       if (mem_flash_io_read_u32(test_addr) != 0xFFFFFFFF) {
44041 +                               break;
44042 +                       }
44043 +                       test_addr += 4;
44044 +               }
44045 +               if (test_addr == addr) {
44046 +                       printk("erase failed at address 0x%x, skipping",
44047 +                              test_addr);
44048 +                       test_addr += 4;
44049 +                       return 1;
44050 +               }
44051 +               addr = test_addr;
44052 +       }
44053 +       return 0;
44054 +}
44055 +
44056 +
44057 +/****************************************************************************/
44058 +
44059 +/*
44060 + * MTD implementation
44061 + */
44062 +
44063 +/*
44064 + * Erase an address range on the flash chip.  The address range may extend
44065 + * one or more erase sectors.  Return an error is there is a problem erasing.
44066 + */
44067 +static int ubicom32_flash_driver_erase(struct mtd_info *mtd,
44068 +                                      struct erase_info *instr)
44069 +{
44070 +       struct m25p *flash = mtd_to_m25p(mtd);
44071 +       u32 addr, len;
44072 +
44073 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %lld\n",
44074 +             dev_name(&flash->plt_dev->dev), __FUNCTION__, "at",
44075 +             (u32)instr->addr, instr->len);
44076 +
44077 +       /* sanity checks */
44078 +       if (instr->addr + instr->len > flash->mtd.size)
44079 +               return -EINVAL;
44080 +       if ((instr->addr % mtd->erasesize) != 0
44081 +                       || (instr->len % mtd->erasesize) != 0) {
44082 +               return -EINVAL;
44083 +       }
44084 +
44085 +       addr = instr->addr + UBICOM32_FLASH_BASE;
44086 +       len = instr->len;
44087 +
44088 +       mutex_lock(&flash->lock);
44089 +
44090 +       /* REVISIT in some cases we could speed up erasing large regions
44091 +        * by using OPCODE_SE instead of OPCODE_BE_4K
44092 +        */
44093 +
44094 +       /* now erase those sectors */
44095 +       if (mem_flash_erase(addr, len)) {
44096 +               instr->state = MTD_ERASE_FAILED;
44097 +               mutex_unlock(&flash->lock);
44098 +               return -EIO;
44099 +       }
44100 +
44101 +       mutex_unlock(&flash->lock);
44102 +       instr->state = MTD_ERASE_DONE;
44103 +       mtd_erase_callback(instr);
44104 +       return 0;
44105 +}
44106 +
44107 +/*
44108 + * Read an address range from the flash chip.  The address range
44109 + * may be any size provided it is within the physical boundaries.
44110 + */
44111 +static int ubicom32_flash_driver_read(struct mtd_info *mtd, loff_t from,
44112 +                                     size_t len, size_t *retlen, u_char *buf)
44113 +{
44114 +       struct m25p *flash = mtd_to_m25p(mtd);
44115 +       u32 base_addr = UBICOM32_FLASH_BASE + from;
44116 +
44117 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44118 +             dev_name(&flash->plt_dev->dev), __FUNCTION__, "from",
44119 +             (u32)from, len);
44120 +
44121 +       /* sanity checks */
44122 +       if (!len)
44123 +               return 0;
44124 +
44125 +       if (from + len > flash->mtd.size)
44126 +               return -EINVAL;
44127 +
44128 +       /* Byte count starts at zero. */
44129 +       if (retlen)
44130 +               *retlen = 0;
44131 +
44132 +       mutex_lock(&flash->lock);
44133 +
44134 +       /* Wait till previous write/erase is done. */
44135 +       if (wait_till_ready(flash)) {
44136 +               /* REVISIT status return?? */
44137 +               mutex_unlock(&flash->lock);
44138 +               return 1;
44139 +       }
44140 +
44141 +       mem_flash_read(base_addr, (void *)buf, len);
44142 +
44143 +       if (retlen)
44144 +               *retlen = len;
44145 +
44146 +       mutex_unlock(&flash->lock);
44147 +
44148 +       return 0;
44149 +}
44150 +
44151 +/*
44152 + * Write an address range to the flash chip.  Data must be written in
44153 + * FLASH_PAGESIZE chunks.  The address range may be any size provided
44154 + * it is within the physical boundaries.
44155 + */
44156 +static int ubicom32_flash_driver_write(struct mtd_info *mtd, loff_t to,
44157 +                                      size_t len, size_t *retlen,
44158 +                                      const u_char *buf)
44159 +{
44160 +       struct m25p *flash = mtd_to_m25p(mtd);
44161 +       u32 base_addr = UBICOM32_FLASH_BASE + to;
44162 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44163 +             dev_name(&flash->plt_dev->dev), __FUNCTION__, "to",
44164 +             (u32)to, len);
44165 +
44166 +       if (retlen)
44167 +               *retlen = 0;
44168 +
44169 +       /* sanity checks */
44170 +       if (!len)
44171 +               return 0;
44172 +
44173 +       if (to + len > flash->mtd.size)
44174 +               return -EINVAL;
44175 +
44176 +       mutex_lock(&flash->lock);
44177 +
44178 +       mem_flash_write(base_addr, (void *) buf, len);
44179 +
44180 +       /* Wait until finished previous write command. */
44181 +       if (wait_till_ready(flash)) {
44182 +               mutex_unlock(&flash->lock);
44183 +               return 1;
44184 +       }
44185 +
44186 +       if (retlen)
44187 +               *retlen = len;
44188 +
44189 +       mutex_unlock(&flash->lock);
44190 +       return 0;
44191 +}
44192 +
44193 +
44194 +/****************************************************************************/
44195 +
44196 +/*
44197 + * SPI device driver setup and teardown
44198 + */
44199 +
44200 +struct flash_info {
44201 +       char            *name;
44202 +
44203 +       /* JEDEC id zero means "no ID" (most older chips); otherwise it has
44204 +        * a high byte of zero plus three data bytes: the manufacturer id,
44205 +        * then a two byte device id.
44206 +        */
44207 +       u32             jedec_id;
44208 +
44209 +       /* The size listed here is what works with OPCODE_SE, which isn't
44210 +        * necessarily called a "sector" by the vendor.
44211 +        */
44212 +       unsigned        sector_size;
44213 +       u16             n_sectors;
44214 +
44215 +       u16             flags;
44216 +#define        SECT_4K         0x01            /* OPCODE_BE_4K works uniformly */
44217 +};
44218 +
44219 +
44220 +/* NOTE: double check command sets and memory organization when you add
44221 + * more flash chips.  This current list focusses on newer chips, which
44222 + * have been converging on command sets which including JEDEC ID.
44223 + */
44224 +static struct flash_info __devinitdata m25p_data[] = {
44225 +
44226 +       /* Atmel -- some are (confusingly) marketed as "DataFlash" */
44227 +       { "at25fs010",  0x1f6601, 32 * 1024, 4, SECT_4K, },
44228 +       { "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },
44229 +
44230 +       { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
44231 +
44232 +       { "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
44233 +       { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
44234 +       { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
44235 +       { "at26df321",  0x1f4701, 64 * 1024, 64, SECT_4K, },
44236 +
44237 +       /* Spansion -- single (large) sector size only, at least
44238 +        * for the chips listed here (without boot sectors).
44239 +        */
44240 +       { "s25sl004a", 0x010212, 64 * 1024, 8, },
44241 +       { "s25sl008a", 0x010213, 64 * 1024, 16, },
44242 +       { "s25sl016a", 0x010214, 64 * 1024, 32, },
44243 +       { "s25sl032a", 0x010215, 64 * 1024, 64, },
44244 +       { "s25sl064a", 0x010216, 64 * 1024, 128, },
44245 +
44246 +       /* SST -- large erase sizes are "overlays", "sectors" are 4K */
44247 +       { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
44248 +       { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
44249 +       { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
44250 +       { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
44251 +
44252 +       /* ST Microelectronics -- newer production may have feature updates */
44253 +       { "m25p05",  0x202010,  32 * 1024, 2, },
44254 +       { "m25p10",  0x202011,  32 * 1024, 4, },
44255 +       { "m25p20",  0x202012,  64 * 1024, 4, },
44256 +       { "m25p40",  0x202013,  64 * 1024, 8, },
44257 +       { "m25p80",         0,  64 * 1024, 16, },
44258 +       { "m25p16",  0x202015,  64 * 1024, 32, },
44259 +       { "m25p32",  0x202016,  64 * 1024, 64, },
44260 +       { "m25p64",  0x202017,  64 * 1024, 128, },
44261 +       { "m25p128", 0x202018, 256 * 1024, 64, },
44262 +
44263 +       { "m45pe80", 0x204014,  64 * 1024, 16, },
44264 +       { "m45pe16", 0x204015,  64 * 1024, 32, },
44265 +
44266 +       { "m25pe80", 0x208014,  64 * 1024, 16, },
44267 +       { "m25pe16", 0x208015,  64 * 1024, 32, SECT_4K, },
44268 +
44269 +       /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
44270 +       { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
44271 +       { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
44272 +       { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
44273 +       { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
44274 +       { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
44275 +       { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
44276 +       { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
44277 +
44278 +       /* Macronix -- mx25lxxx */
44279 +       { "mx25l32",  0xc22016, 64 * 1024,  64, },
44280 +       { "mx25l64",  0xc22017, 64 * 1024, 128, },
44281 +       { "mx25l128", 0xc22018, 64 * 1024, 256, },
44282 +
44283 +};
44284 +
44285 +struct flash_info *__devinit jedec_probe(struct platform_device *spi)
44286 +{
44287 +       int                     tmp;
44288 +       u32                     jedec;
44289 +       struct flash_info       *info;
44290 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44291 +
44292 +       /*
44293 +        * Setup and run RDID command on the flash.
44294 +        */
44295 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44296 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
44297 +               IO_XFL_CTL1_FC_DATA(3);
44298 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDID);
44299 +       FLASH_COMMAND_EXEC(io);
44300 +
44301 +       jedec = io->status1 & 0x00ffffff;
44302 +
44303 +       for (tmp = 0, info = m25p_data;
44304 +                       tmp < ARRAY_SIZE(m25p_data);
44305 +                       tmp++, info++) {
44306 +               if (info->jedec_id == jedec)
44307 +                       return info;
44308 +       }
44309 +       dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
44310 +       return NULL;
44311 +}
44312 +
44313 +
44314 +/*
44315 + * board specific setup should have ensured the SPI clock used here
44316 + * matches what the READ command supports, at least until this driver
44317 + * understands FAST_READ (for clocks over 25 MHz).
44318 + */
44319 +static int __devinit ubicom32_flash_probe(struct platform_device *spi)
44320 +{
44321 +       struct flash_platform_data      *data;
44322 +       struct m25p                     *flash;
44323 +       struct flash_info               *info;
44324 +       unsigned                        i;
44325 +
44326 +       /* Platform data helps sort out which chip type we have, as
44327 +        * well as how this board partitions it.  If we don't have
44328 +        * a chip ID, try the JEDEC id commands; they'll work for most
44329 +        * newer chips, even if we don't recognize the particular chip.
44330 +        */
44331 +       data = spi->dev.platform_data;
44332 +       if (data && data->type) {
44333 +               for (i = 0, info = m25p_data;
44334 +                               i < ARRAY_SIZE(m25p_data);
44335 +                               i++, info++) {
44336 +                       if (strcmp(data->type, info->name) == 0)
44337 +                               break;
44338 +               }
44339 +
44340 +               /* unrecognized chip? */
44341 +               if (i == ARRAY_SIZE(m25p_data)) {
44342 +                       DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
44343 +                             dev_name(&spi->dev), data->type);
44344 +                       info = NULL;
44345 +
44346 +               /* recognized; is that chip really what's there? */
44347 +               } else if (info->jedec_id) {
44348 +                       struct flash_info       *chip = jedec_probe(spi);
44349 +
44350 +                       if (!chip || chip != info) {
44351 +                               dev_warn(&spi->dev, "found %s, expected %s\n",
44352 +                                               chip ? chip->name : "UNKNOWN",
44353 +                                               info->name);
44354 +                               info = NULL;
44355 +                       }
44356 +               }
44357 +       } else
44358 +               info = jedec_probe(spi);
44359 +
44360 +       if (!info)
44361 +               return -ENODEV;
44362 +
44363 +       flash = kzalloc(sizeof *flash, GFP_KERNEL);
44364 +       if (!flash)
44365 +               return -ENOMEM;
44366 +
44367 +       flash->plt_dev = spi;
44368 +       mutex_init(&flash->lock);
44369 +       dev_set_drvdata(&spi->dev, flash);
44370 +
44371 +       if (data && data->name)
44372 +               flash->mtd.name = data->name;
44373 +       else
44374 +               flash->mtd.name = dev_name(&spi->dev);
44375 +
44376 +       flash->mtd.type = MTD_NORFLASH;
44377 +       flash->mtd.writesize = 1;
44378 +       flash->mtd.flags = MTD_CAP_NORFLASH;
44379 +       flash->mtd.size = info->sector_size * info->n_sectors;
44380 +       flash->mtd.erase = ubicom32_flash_driver_erase;
44381 +       flash->mtd.read = ubicom32_flash_driver_read;
44382 +       flash->mtd.write = ubicom32_flash_driver_write;
44383 +
44384 +       /* prefer "small sector" erase if possible */
44385 +       /*
44386 +        * The Ubicom erase code does not use the opcode for smaller sectors,
44387 +        * so disable that functionality and keep erasesize == sector_size
44388 +        * so that the test in ubicom32_flash_driver_erase works properly.
44389 +        *
44390 +        * This was: `if (info->flags & SECT_4K) {' instead of `if (0) {'
44391 +        */
44392 +       if (0) {
44393 +               flash->erase_opcode = OPCODE_BE_4K;
44394 +               flash->mtd.erasesize = 4096;
44395 +       } else {
44396 +               flash->erase_opcode = OPCODE_SE;
44397 +               flash->mtd.erasesize = info->sector_size;
44398 +       }
44399 +
44400 +       dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
44401 +                flash->mtd.size / 1024);
44402 +
44403 +       DEBUG(MTD_DEBUG_LEVEL2,
44404 +               "mtd .name = %s, .size = 0x%.8llx (%lluMiB) "
44405 +                       ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
44406 +               flash->mtd.name,
44407 +               flash->mtd.size, flash->mtd.size / (1024*1024),
44408 +               flash->mtd.erasesize, flash->mtd.erasesize / 1024,
44409 +               flash->mtd.numeraseregions);
44410 +
44411 +       if (flash->mtd.numeraseregions)
44412 +               for (i = 0; i < flash->mtd.numeraseregions; i++)
44413 +                       DEBUG(MTD_DEBUG_LEVEL2,
44414 +                               "mtd.eraseregions[%d] = { .offset = 0x%.8llx, "
44415 +                               ".erasesize = 0x%.8x (%uKiB), "
44416 +                               ".numblocks = %d }\n",
44417 +                               i, flash->mtd.eraseregions[i].offset,
44418 +                               flash->mtd.eraseregions[i].erasesize,
44419 +                               flash->mtd.eraseregions[i].erasesize / 1024,
44420 +                               flash->mtd.eraseregions[i].numblocks);
44421 +
44422 +
44423 +       /* partitions should match sector boundaries; and it may be good to
44424 +        * use readonly partitions for writeprotected sectors (BP2..BP0).
44425 +        */
44426 +       if (mtd_has_partitions()) {
44427 +               struct mtd_partition    *parts = NULL;
44428 +               int                     nr_parts = 0;
44429 +
44430 +#ifdef CONFIG_MTD_CMDLINE_PARTS
44431 +               static const char *part_probes[] = { "cmdlinepart", NULL, };
44432 +
44433 +               nr_parts = parse_mtd_partitions(&flash->mtd,
44434 +                               part_probes, &parts, 0);
44435 +#endif
44436 +
44437 +               if (nr_parts <= 0 && data && data->parts) {
44438 +                       parts = data->parts;
44439 +                       nr_parts = data->nr_parts;
44440 +                       if (nr_parts >= 2) {
44441 +                               /*
44442 +                                * Set last partition size to be 1M.
44443 +                                */
44444 +                               parts[1].size = flash->mtd.size -
44445 +                                       parts[0].size - JFFS2_FILESYSTEM_SIZE;
44446 +                               parts[2].size = JFFS2_FILESYSTEM_SIZE;
44447 +                       }
44448 +               }
44449 +
44450 +               if (nr_parts > 0) {
44451 +                       for (i = 0; i < nr_parts; i++) {
44452 +                               DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
44453 +                                       "{.name = %s, .offset = 0x%.8llx, "
44454 +                                               ".size = 0x%.8llx (%lluKiB) }\n",
44455 +                                       i, parts[i].name,
44456 +                                       parts[i].offset,
44457 +                                       parts[i].size,
44458 +                                       parts[i].size / 1024);
44459 +                       }
44460 +                       flash->partitioned = 1;
44461 +                       return add_mtd_partitions(&flash->mtd, parts, nr_parts);
44462 +               }
44463 +       } else if (data->nr_parts)
44464 +               dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
44465 +                               data->nr_parts, data->name);
44466 +
44467 +       return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
44468 +}
44469 +
44470 +
44471 +static int __devexit ubicom32_flash_remove(struct spi_device *spi)
44472 +{
44473 +       struct m25p     *flash = dev_get_drvdata(&spi->dev);
44474 +       int             status;
44475 +
44476 +       /* Clean up MTD stuff. */
44477 +       if (mtd_has_partitions() && flash->partitioned)
44478 +               status = del_mtd_partitions(&flash->mtd);
44479 +       else
44480 +               status = del_mtd_device(&flash->mtd);
44481 +       if (status == 0)
44482 +               kfree(flash);
44483 +       return 0;
44484 +}
44485 +
44486 +static struct platform_driver ubicom32_flash_driver = {
44487 +       .driver = {
44488 +               .name   = "ubicom32flashdriver",
44489 +               .bus    = &platform_bus_type,
44490 +               .owner  = THIS_MODULE,
44491 +       },
44492 +       .probe  = ubicom32_flash_probe,
44493 +       .remove = NULL,
44494 +};
44495 +
44496 +static int ubicom32_flash_driver_init(void)
44497 +{
44498 +       return platform_driver_register(&ubicom32_flash_driver);
44499 +}
44500 +
44501 +
44502 +static void ubicom32_flash_driver_exit(void)
44503 +{
44504 +       platform_driver_unregister(&ubicom32_flash_driver);
44505 +}
44506 +
44507 +
44508 +module_init(ubicom32_flash_driver_init);
44509 +module_exit(ubicom32_flash_driver_exit);
44510 +
44511 +MODULE_LICENSE("GPL");
44512 +MODULE_AUTHOR("Mike Lavender");
44513 +MODULE_DESCRIPTION("Ubicom32 MTD SPI driver for ST M25Pxx flash chips");
44514 --- /dev/null
44515 +++ b/drivers/mtd/devices/ubi32-nand-spi-er.c
44516 @@ -0,0 +1,1188 @@
44517 +/*
44518 + * Micron SPI-ER NAND Flash Memory
44519 + *     This code uses the built in Ubicom flash controller
44520 + *
44521 + * (C) Copyright 2009, Ubicom, Inc.
44522 + *
44523 + * This file is part of the Ubicom32 Linux Kernel Port.
44524 + *
44525 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
44526 + * it and/or modify it under the terms of the GNU General Public License
44527 + * as published by the Free Software Foundation, either version 2 of the
44528 + * License, or (at your option) any later version.
44529 + *
44530 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
44531 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
44532 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
44533 + * the GNU General Public License for more details.
44534 + *
44535 + * You should have received a copy of the GNU General Public License
44536 + * along with the Ubicom32 Linux Kernel Port.  If not,
44537 + * see <http://www.gnu.org/licenses/>.
44538 +*/
44539 +#include <linux/module.h>
44540 +#include <linux/init.h>
44541 +#include <linux/slab.h>
44542 +#include <linux/delay.h>
44543 +#include <linux/device.h>
44544 +#include <linux/platform_device.h>
44545 +#include <linux/mutex.h>
44546 +#include <linux/err.h>
44547 +
44548 +#include <linux/mtd/mtd.h>
44549 +#include <linux/mtd/partitions.h>
44550 +
44551 +#define DRIVER_NAME                            "ubi32-nand-spi-er"
44552 +#define UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row)  (row >> 6)
44553 +
44554 +#define UBI32_NAND_SPI_ER_STATUS_P_FAIL                (1 << 3)
44555 +#define UBI32_NAND_SPI_ER_STATUS_E_FAIL                (1 << 2)
44556 +#define UBI32_NAND_SPI_ER_STATUS_OIP           (1 << 0)
44557 +
44558 +#define UBI32_NAND_SPI_ER_LAST_ROW_INVALID     0xFFFFFFFF
44559 +#define        UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET 0x08
44560 +
44561 +struct ubi32_nand_spi_er_device {
44562 +       const char              *name;
44563 +
44564 +       uint16_t                id;
44565 +
44566 +       unsigned int            blocks;
44567 +       unsigned int            pages_per_block;
44568 +       unsigned int            page_size;
44569 +       unsigned int            write_size;
44570 +       unsigned int            erase_size;
44571 +};
44572 +
44573 +struct ubi32_nand_spi_er {
44574 +       char                            name[24];
44575 +
44576 +       const struct ubi32_nand_spi_er_device   *device;
44577 +
44578 +       struct mutex                    lock;
44579 +       struct platform_device          *pdev;
44580 +
44581 +       struct mtd_info                 mtd;
44582 +
44583 +       unsigned int                    last_row;       /* the last row we fetched */
44584 +
44585 +       /*
44586 +        * Bad block table (MUST be last in strcuture)
44587 +        */
44588 +       unsigned long                   nbb;
44589 +       unsigned long                   bbt[0];
44590 +};
44591 +
44592 +/*
44593 + * Chip supports a write_size of 512, but we cannot do partial
44594 + * page with command 0x84.
44595 + *
44596 + * We need to use command 0x84 because we cannot fill the FIFO fast
44597 + * enough to transfer the whole 512 bytes at a time. (maybe through
44598 + * OCM?)
44599 + */
44600 +const struct ubi32_nand_spi_er_device ubi32_nand_spi_er_devices[] = {
44601 +       {
44602 +               name:                   "MT29F1G01ZDC",
44603 +               id:                     0x2C12,
44604 +               blocks:                 1024,
44605 +               pages_per_block:        64,
44606 +               page_size:              2048,
44607 +               write_size:             2048,
44608 +               erase_size:             64 * 2048,
44609 +       },
44610 +       {
44611 +               name:                   "MT29F1G01ZDC",
44612 +               id:                     0x2C13,
44613 +               blocks:                 1024,
44614 +               pages_per_block:        64,
44615 +               page_size:              2048,
44616 +               write_size:             2048,
44617 +               erase_size:             64 * 2048,
44618 +       },
44619 +};
44620 +
44621 +static int read_only = 0;
44622 +module_param(read_only, int, 0);
44623 +MODULE_PARM_DESC(read_only, "Leave device locked");
44624 +
44625 +/*
44626 + * Ubicom32 FLASH Command Set
44627 + */
44628 +#define FLASH_PORT             RA
44629 +
44630 +#define FLASH_FC_INST_CMD      0x00    /* for SPI command only transaction */
44631 +#define FLASH_FC_INST_WR       0x01    /* for SPI write transaction */
44632 +#define FLASH_FC_INST_RD       0x02    /* for SPI read transaction */
44633 +
44634 +#define FLASH_COMMAND_KICK_OFF(io)                                                             \
44635 +       asm volatile(                                                                           \
44636 +               "       bset    "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)")   \n\t"   \
44637 +               "       jmpt.t  .+4                                                     \n\t"   \
44638 +               "       bset    "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)")  \n\t"   \
44639 +               :                                                                               \
44640 +               : "a" (io)                                                                      \
44641 +               : "cc"                                                                          \
44642 +               );
44643 +
44644 +#define FLASH_COMMAND_WAIT_FOR_COMPLETION(io)                                                  \
44645 +       asm volatile(                                                                           \
44646 +               "       btst    "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)")    \n\t"   \
44647 +               "       jmpeq.f .-4                                                     \n\t"   \
44648 +               :                                                                               \
44649 +               : "a" (io)                                                                      \
44650 +               : "cc"                                                                          \
44651 +       );
44652 +
44653 +#define FLASH_COMMAND_EXEC(io)                         \
44654 +               FLASH_COMMAND_KICK_OFF(io)              \
44655 +               FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
44656 +
44657 +/*
44658 + * ubi32_nand_spi_er_get_feature
44659 + *     Get Feature register
44660 + */
44661 +static uint8_t ubi32_nand_spi_er_get_feature(uint32_t reg)
44662 +{
44663 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44664 +
44665 +       /*
44666 +        * Note that this will produce the sequence:
44667 +        *      SI [0F][REG][00][00]
44668 +        *      SO ---------[SR][SR][SR]
44669 +        * Since the flash controller can only output 24 bits of address, this is
44670 +        * ok for this command since the data will just repeat as long as the CS
44671 +        * is asserted and the clock is running.
44672 +        */
44673 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44674 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(1) |
44675 +                   IO_XFL_CTL1_FC_ADDR;
44676 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x0F) | IO_XFL_CTL2_FC_ADDR(reg << 16);
44677 +       FLASH_COMMAND_EXEC(io);
44678 +
44679 +       return io->status1 & 0xFF;
44680 +}
44681 +
44682 +/*
44683 + * ubi32_nand_spi_er_write_buf
44684 + *     writes a buffer to the bus
44685 + *
44686 + * Writes 511 + 1 bytes to the bus, we have to stuff one data byte into the address.
44687 + */
44688 +static void ubi32_nand_spi_er_write_buf(const uint8_t *buf, uint32_t col)
44689 +{
44690 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44691 +       uint32_t tmp;
44692 +
44693 +       asm volatile (
44694 +               "       bset            "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")   \n\t"
44695 +               "       pipe_flush      0                                                                       \n\t"
44696 +               :
44697 +               : [port] "a" (FLASH_PORT)
44698 +               : "cc"
44699 +       );
44700 +
44701 +       /*
44702 +        * Write the data into the cache
44703 +        */
44704 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44705 +#ifdef SUPPORT_512_FIFO
44706 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(511) |
44707 +#endif
44708 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(31) |
44709 +                   IO_XFL_CTL1_FC_ADDR;
44710 +
44711 +       /*
44712 +        * Construct the address with the first byte of data
44713 +        */
44714 +       tmp = (col << 8) | *buf++;
44715 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84) | IO_XFL_CTL2_FC_ADDR(tmp);
44716 +
44717 +       asm volatile (
44718 +
44719 +               /*
44720 +                * Move 32 bytes
44721 +                *
44722 +                * The first word needs to be [11][22][33][33] to work around a flash
44723 +                * controller bug.
44724 +                */
44725 +               "       move.2          %[tmp], (%[data])2++                                                    \n\t"
44726 +               "       shmrg.1         %[tmp], (%[data]), %[tmp]                                               \n\t"
44727 +               "       shmrg.1         %[tmp], (%[data])1++, %[tmp]                                            \n\t"
44728 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[tmp]                                        \n\t"
44729 +
44730 +               /*
44731 +                * We're aligned again!
44732 +                */
44733 +               "       .rept 7                                                                                 \n\t"
44734 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
44735 +               "       .endr                                                                                   \n\t"
44736 +
44737 +               /*
44738 +                * Kick off the flash command
44739 +                */
44740 +               "       bset    "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)")                      \n\t"
44741 +               "       jmpt.t  .+4                                                                             \n\t"
44742 +               "       bset    "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)")                     \n\t"
44743 +
44744 +#ifdef SUPPORT_512_FIFO
44745 +               /*
44746 +                * Fill the remaining 120 words as space becomes available
44747 +                */
44748 +               "1:                                                                                             \n\t"
44749 +               "       cmpi            "D(IO_FIFO_LEVEL)"(%[port]), #4                                         \n\t"
44750 +               "       jmpgt.s.t       1b                                                                      \n\t"
44751 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
44752 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
44753 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
44754 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), (%[data])4++                                  \n\t"
44755 +               "       add.4           %[cnt], #-4, %[cnt]                                                     \n\t"
44756 +               "       jmpgt.t         1b                                                                      \n\t"
44757 +#endif
44758 +               /*
44759 +                * Wait for the transaction to finish
44760 +                */
44761 +               "       btst    "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)")                       \n\t"
44762 +               "       jmpeq.f .-4                                                                             \n\t"
44763 +
44764 +               : [tmp] "=&d" (tmp),
44765 +                 [data] "+&a" (buf)
44766 +               : [column] "d" (col),
44767 +                 [port] "a" (FLASH_PORT),
44768 +                 [cnt] "d" (120)               // see above comment
44769 +               : "cc"
44770 +       );
44771 +}
44772 +
44773 +/*
44774 + * ubi32_nand_spi_er_send_rd_addr
44775 + *     perform FC_RD: CMD + address
44776 + */
44777 +static void ubi32_nand_spi_er_send_rd_addr(uint8_t command, uint32_t address)
44778 +{
44779 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44780 +
44781 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44782 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(4) |
44783 +                   IO_XFL_CTL1_FC_ADDR;
44784 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
44785 +       FLASH_COMMAND_EXEC(io);
44786 +}
44787 +
44788 +/*
44789 + * ubi32_nand_spi_er_send_cmd_addr
44790 + *     perform FC_(xxx): CMD + address
44791 + */
44792 +static void ubi32_nand_spi_er_send_cmd_addr(uint8_t command, uint32_t address)
44793 +{
44794 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44795 +
44796 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44797 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) | IO_XFL_CTL1_FC_ADDR;
44798 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
44799 +       FLASH_COMMAND_EXEC(io);
44800 +}
44801 +
44802 +/*
44803 + * ubi32_nand_spi_er_write_disable
44804 + *     clear the write enable bit
44805 + */
44806 +static void ubi32_nand_spi_er_write_disable(void)
44807 +{
44808 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44809 +
44810 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44811 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44812 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x04);
44813 +       FLASH_COMMAND_EXEC(io);
44814 +}
44815 +
44816 +/*
44817 + * ubi32_nand_spi_er_write_enable
44818 + *     set the write enable bit
44819 + */
44820 +static void ubi32_nand_spi_er_write_enable(void)
44821 +{
44822 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44823 +
44824 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
44825 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44826 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x06);
44827 +       FLASH_COMMAND_EXEC(io);
44828 +}
44829 +
44830 +/*
44831 + * ubi32_nand_spi_er_busywait
44832 + *     Wait until the chip is not busy
44833 + */
44834 +static uint8_t ubi32_nand_spi_er_busywait(void)
44835 +{
44836 +       int i;
44837 +       uint8_t data;
44838 +
44839 +       /*
44840 +        * tRD is 100us, so don't delay too long, however, tERS is
44841 +        * 10ms so you'd better loop enough.
44842 +        */
44843 +       for (i = 0; i < 200; i++) {
44844 +               data = ubi32_nand_spi_er_get_feature(0xC0);
44845 +               if (!(data & UBI32_NAND_SPI_ER_STATUS_OIP)) {
44846 +                       break;
44847 +               }
44848 +
44849 +               udelay(50);
44850 +       }
44851 +
44852 +       return data;
44853 +}
44854 +
44855 +/*
44856 + * ubi32_nand_spi_er_erase
44857 + *     Erase a block, parameters must be block aligned
44858 + */
44859 +static int ubi32_nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
44860 +{
44861 +       struct ubi32_nand_spi_er *chip = mtd->priv;
44862 +       int res;
44863 +
44864 +       DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
44865 +
44866 +       if ((instr->addr + instr->len) > mtd->size) {
44867 +               return -EINVAL;
44868 +       }
44869 +
44870 +       if (instr->addr & (chip->device->erase_size - 1)) {
44871 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
44872 +               return -EINVAL;
44873 +       }
44874 +
44875 +       if (instr->len & (chip->device->erase_size - 1)) {
44876 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
44877 +               return -EINVAL;
44878 +       }
44879 +
44880 +       mutex_lock(&chip->lock);
44881 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
44882 +
44883 +       while (instr->len) {
44884 +               uint32_t block = instr->addr >> 17;
44885 +               uint32_t row = block << 6;
44886 +               uint8_t stat;
44887 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
44888 +
44889 +               /*
44890 +                * Test for bad block
44891 +                */
44892 +               if (test_bit(block, chip->bbt)) {
44893 +                       instr->fail_addr = block << 17;
44894 +                       instr->state = MTD_ERASE_FAILED;
44895 +                       res = -EBADMSG;
44896 +                       goto done;
44897 +               }
44898 +
44899 +               ubi32_nand_spi_er_write_enable();
44900 +
44901 +               /*
44902 +                * Block erase
44903 +                */
44904 +               ubi32_nand_spi_er_send_cmd_addr(0xD8, row);
44905 +
44906 +               /*
44907 +                * Wait
44908 +                */
44909 +               stat = ubi32_nand_spi_er_busywait();
44910 +               if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
44911 +                       instr->fail_addr = block << 17;
44912 +                       instr->state = MTD_ERASE_FAILED;
44913 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
44914 +
44915 +                       /*
44916 +                        * Chip is stuck?
44917 +                        */
44918 +                       res = -EIO;
44919 +                       goto done;
44920 +               }
44921 +
44922 +               /*
44923 +                * Check the status register
44924 +                */
44925 +               if (stat & UBI32_NAND_SPI_ER_STATUS_E_FAIL) {
44926 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
44927 +                       instr->fail_addr = block << 17;
44928 +                       instr->state = MTD_ERASE_FAILED;
44929 +                       goto done;
44930 +               }
44931 +
44932 +               /*
44933 +                * Next
44934 +                */
44935 +               block++;
44936 +               instr->len -= chip->device->erase_size;
44937 +               instr->addr += chip->device->erase_size;
44938 +       }
44939 +
44940 +       instr->state = MTD_ERASE_DONE;
44941 +
44942 +       mutex_unlock(&chip->lock);
44943 +       return 0;
44944 +
44945 +done:
44946 +       ubi32_nand_spi_er_write_disable();
44947 +
44948 +       mutex_unlock(&chip->lock);
44949 +
44950 +       mtd_erase_callback(instr);
44951 +       return 0;
44952 +}
44953 +
44954 +/*
44955 + * ubi32_nand_spi_er_read
44956 + *
44957 + * return -EUCLEAN: ecc error recovered
44958 + * return -EBADMSG: ecc error not recovered
44959 +*/
44960 +static int ubi32_nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
44961 +                                 size_t *retlen, u_char *buf)
44962 +{
44963 +       struct ubi32_nand_spi_er *chip = mtd->priv;
44964 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44965 +
44966 +       uint32_t row;
44967 +       uint32_t column;
44968 +       int retval = 0;
44969 +       uint32_t *pbuf = (uint32_t *)buf;
44970 +
44971 +       *retlen = 0;
44972 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
44973 +
44974 +       /*
44975 +        * buf should be aligned
44976 +        */
44977 +       if ((uint32_t)buf & 0x03) {
44978 +               return -EINVAL;
44979 +       }
44980 +
44981 +       /*
44982 +        * Zero length reads, nothing to do
44983 +        */
44984 +       if (len == 0) {
44985 +               return 0;
44986 +       }
44987 +
44988 +       /*
44989 +        * Reject reads which go over the end of the flash
44990 +        */
44991 +       if ((from + len) > mtd->size) {
44992 +               return -EINVAL;
44993 +       }
44994 +
44995 +       /*
44996 +        * Get the row and column address to start at
44997 +        */
44998 +       row = from >> 11;
44999 +       column = from & 0x7FF;
45000 +       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);
45001 +
45002 +       /*
45003 +        * Read the data from the chip
45004 +        */
45005 +       mutex_lock(&chip->lock);
45006 +       while (len) {
45007 +               uint8_t stat;
45008 +               size_t toread;
45009 +               int i;
45010 +               int tmp;
45011 +
45012 +               /*
45013 +                * Figure out how much to read
45014 +                *
45015 +                * If we are reading from the middle of a page then the most we
45016 +                * can read is to the end of the page
45017 +                */
45018 +               toread = len;
45019 +               if (toread > (chip->device->page_size - column)) {
45020 +                       toread = chip->device->page_size - column;
45021 +               }
45022 +
45023 +               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);
45024 +
45025 +               if (chip->last_row != row) {
45026 +                       /*
45027 +                        * Check if the block is bad
45028 +                        */
45029 +                       if (test_bit(UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
45030 +                               mutex_unlock(&chip->lock);
45031 +                               return -EBADMSG;
45032 +                       }
45033 +
45034 +                       /*
45035 +                        * Load the appropriate page
45036 +                        */
45037 +                       ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45038 +
45039 +                       /*
45040 +                        * Wait
45041 +                        */
45042 +                       stat = ubi32_nand_spi_er_busywait();
45043 +                       if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45044 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45045 +
45046 +                               /*
45047 +                                * Chip is stuck?
45048 +                                */
45049 +                               mutex_unlock(&chip->lock);
45050 +                               return -EIO;
45051 +                       }
45052 +
45053 +                       /*
45054 +                        * Check the ECC bits
45055 +                        */
45056 +                       stat >>= 4;
45057 +                       if (stat == 1) {
45058 +                               DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
45059 +                               retval = -EUCLEAN;
45060 +                       }
45061 +                       if (stat == 2) {
45062 +                               DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
45063 +                               chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45064 +                               mutex_unlock(&chip->lock);
45065 +                               return -EBADMSG;
45066 +                       }
45067 +
45068 +               }
45069 +
45070 +               chip->last_row = row;
45071 +
45072 +               /*
45073 +                * Read out the data:
45074 +                *      We can always read a little too much since there is the
45075 +                *      OOB after byte addr 2047.  The most we'll overread is 3 bytes.
45076 +                */
45077 +               if (((uint32_t)pbuf & 0x03) == 0) {
45078 +                       /*
45079 +                        * Aligned read
45080 +                        */
45081 +                       tmp = toread & (~0x03);
45082 +                       for (i = 0; i < tmp; i += 4) {
45083 +                               ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45084 +                               *pbuf++ = io->status1;
45085 +                               column += 4;
45086 +                       }
45087 +               } else {
45088 +                       /*
45089 +                        * Unaligned read
45090 +                        */
45091 +                       tmp = toread & (~0x03);
45092 +                       for (i = 0; i < tmp; i += 4) {
45093 +                               ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45094 +                               memcpy(pbuf, &io->status1, 4);
45095 +                               column += 4;
45096 +                       }
45097 +               }
45098 +
45099 +               /*
45100 +                * Fill in any single bytes
45101 +                */
45102 +               tmp = toread & 0x03;
45103 +               if (tmp) {
45104 +                       uint8_t *bbuf = pbuf;
45105 +                       uint32_t val;
45106 +                       ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45107 +                       val = io->status1;
45108 +                       for (i = 0; i < tmp; i++) {
45109 +                               *bbuf++ = val >> 24;
45110 +                               val <<= 8;
45111 +                       }
45112 +               }
45113 +
45114 +               len -= toread;
45115 +               *retlen += toread;
45116 +
45117 +               /*
45118 +                * For the next page, increment the row and always start at column 0
45119 +                */
45120 +               column = 0;
45121 +               row++;
45122 +       }
45123 +
45124 +       mutex_unlock(&chip->lock);
45125 +       return retval;
45126 +}
45127 +
45128 +/*
45129 + * ubi32_nand_spi_er_write
45130 + */
45131 +#define WRITE_NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
45132 +static int ubi32_nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
45133 +                                  size_t *retlen, const u_char *buf)
45134 +{
45135 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45136 +       const struct ubi32_nand_spi_er_device *device = chip->device;
45137 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45138 +       uint32_t row;
45139 +       uint32_t col;
45140 +       int res = 0;
45141 +       size_t towrite;
45142 +
45143 +       DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
45144 +
45145 +       *retlen = 0;
45146 +
45147 +       /*
45148 +        * nothing to write
45149 +        */
45150 +       if (!len) {
45151 +               return 0;
45152 +       }
45153 +
45154 +       /*
45155 +        * Reject writes which go over the end of the flash
45156 +        */
45157 +       if ((to + len) > mtd->size) {
45158 +               return -EINVAL;
45159 +       }
45160 +
45161 +       /*
45162 +        * buf should be aligned to 16 bits
45163 +        */
45164 +       if ((uint32_t)buf & 0x01) {
45165 +               return -EINVAL;
45166 +       }
45167 +
45168 +       /*
45169 +        * Check to see if everything is page aligned
45170 +        */
45171 +       if (WRITE_NOT_ALIGNED(to) || WRITE_NOT_ALIGNED(len)) {
45172 +               printk(KERN_NOTICE "ubi32_nand_spi_er_write: Attempt to write non page aligned data\n");
45173 +               return -EINVAL;
45174 +       }
45175 +
45176 +       mutex_lock(&chip->lock);
45177 +
45178 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45179 +
45180 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45181 +
45182 +       /*
45183 +        * If the first write is a partial write then write at most the number of
45184 +        * bytes to get us page aligned and then the remainder will be
45185 +        * page aligned.  The last bit may be a partial page as well.
45186 +        */
45187 +       col = to & (device->page_size - 1);
45188 +       towrite = device->page_size - col;
45189 +       if (towrite > len) {
45190 +               towrite = len;
45191 +       }
45192 +
45193 +       /*
45194 +        * Write the data
45195 +        */
45196 +       row = to >> 11;
45197 +       while (len) {
45198 +               uint8_t stat;
45199 +               uint32_t my_towrite;
45200 +
45201 +               DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
45202 +
45203 +               ubi32_nand_spi_er_write_enable();
45204 +
45205 +               /*
45206 +                * Move the data into the cache
45207 +                */
45208 +               my_towrite = towrite;
45209 +               while (my_towrite) {
45210 +                       uint32_t len = my_towrite;
45211 +                       if (len > 32) {
45212 +                               len = 32;
45213 +                       }
45214 +
45215 +                       ubi32_nand_spi_er_write_buf(buf, col);
45216 +                       buf += len;
45217 +                       col += len;
45218 +                       my_towrite -= len;
45219 +               }
45220 +
45221 +               /*
45222 +                * Program execute
45223 +                */
45224 +               ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45225 +
45226 +               /*
45227 +                * Wait
45228 +                */
45229 +               stat = ubi32_nand_spi_er_busywait();
45230 +               if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45231 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45232 +
45233 +                       /*
45234 +                        * Chip is stuck?
45235 +                        */
45236 +                       res = -EIO;
45237 +                       goto done;
45238 +               }
45239 +
45240 +               if (stat & (1 << 3)) {
45241 +                       res = -EBADMSG;
45242 +                       goto done;
45243 +               }
45244 +
45245 +               row++;
45246 +               len -= towrite;
45247 +               *retlen += towrite;
45248 +
45249 +               /*
45250 +                * At this point, we are always page aligned so start at column 0.
45251 +                * Note we may not have a full page to write at the end, hence the
45252 +                * check if towrite > len.
45253 +                */
45254 +               col = 0;
45255 +               towrite = device->page_size;
45256 +               if (towrite > len) {
45257 +                       towrite = len;
45258 +               }
45259 +       }
45260 +
45261 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45262 +
45263 +       mutex_unlock(&chip->lock);
45264 +       return res;
45265 +
45266 +done:
45267 +       ubi32_nand_spi_er_write_disable();
45268 +
45269 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45270 +
45271 +       mutex_unlock(&chip->lock);
45272 +
45273 +       return res;
45274 +}
45275 +
45276 +/*
45277 + * ubi32_nand_spi_er_isbad
45278 + */
45279 +static int ubi32_nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
45280 +{
45281 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45282 +       uint32_t block;
45283 +
45284 +       if (ofs & (chip->device->erase_size - 1)) {
45285 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45286 +               return -EINVAL;
45287 +       }
45288 +
45289 +       block = ofs >> 17;
45290 +
45291 +       return test_bit(block, chip->bbt);
45292 +}
45293 +
45294 +/*
45295 + * ubi32_nand_spi_er_markbad
45296 + */
45297 +static int ubi32_nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
45298 +{
45299 +       struct ubi32_nand_spi_er *chip = mtd->priv;
45300 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45301 +       uint32_t block;
45302 +       uint32_t row;
45303 +       int res = 0;
45304 +       uint8_t stat;
45305 +
45306 +       if (ofs & (chip->device->erase_size - 1)) {
45307 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45308 +               return -EINVAL;
45309 +       }
45310 +
45311 +       block = ofs >> 17;
45312 +
45313 +       /*
45314 +        * If it's already marked bad, no need to mark it
45315 +        */
45316 +       if (test_bit(block, chip->bbt)) {
45317 +               return 0;
45318 +       }
45319 +
45320 +       /*
45321 +        * Mark it in our cache
45322 +        */
45323 +       __set_bit(block, chip->bbt);
45324 +
45325 +       /*
45326 +        * Write the user bad block mark.  If it fails, then we really
45327 +        * can't do anything about it.
45328 +        */
45329 +       mutex_lock(&chip->lock);
45330 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45331 +
45332 +       ubi32_nand_spi_er_write_enable();
45333 +
45334 +       /*
45335 +        * Write the mark
45336 +        */
45337 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45338 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45339 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(6);
45340 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84);
45341 +
45342 +       asm volatile (
45343 +               "       bset            "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")   \n\t"
45344 +               "       pipe_flush      0                                                                       \n\t"
45345 +
45346 +               /*
45347 +                * Move the data into the FIFO
45348 +                */
45349 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[word1]                                      \n\t"
45350 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[word2]                                      \n\t"
45351 +
45352 +               /*
45353 +                * Kick off the flash command
45354 +                */
45355 +               "       bset    "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)")                      \n\t"
45356 +               "       jmpt.t  .+4                                                                             \n\t"
45357 +               "       bset    "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)")                     \n\t"
45358 +
45359 +               /*
45360 +                * Wait for the transaction to finish
45361 +                */
45362 +               "       btst    "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)")                       \n\t"
45363 +               "       jmpeq.f .-4                                                                             \n\t"
45364 +
45365 +               :
45366 +               : [word1] "d" (0x0800dead | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 16)),
45367 +                 [word2] "d" (0xbeef0000),
45368 +                 [port] "a" (FLASH_PORT)
45369 +               : "cc"
45370 +       );
45371 +
45372 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45373 +
45374 +       /*
45375 +        * Program execute
45376 +        */
45377 +       row = block << 6;
45378 +       ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45379 +
45380 +       /*
45381 +        * Wait
45382 +        */
45383 +       stat = ubi32_nand_spi_er_busywait();
45384 +       if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45385 +               DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45386 +
45387 +               /*
45388 +                * Chip is stuck?
45389 +                */
45390 +               res = -EIO;
45391 +               goto done;
45392 +       }
45393 +
45394 +       if (stat & (1 << 3)) {
45395 +               res = -EBADMSG;
45396 +       }
45397 +
45398 +done:
45399 +       ubi32_nand_spi_er_write_disable();
45400 +
45401 +       mutex_unlock(&chip->lock);
45402 +
45403 +       return res;
45404 +}
45405 +
45406 +/*
45407 + * ubi32_nand_spi_er_read_bbt
45408 + */
45409 +static int ubi32_nand_spi_er_read_bbt(struct ubi32_nand_spi_er *chip)
45410 +{
45411 +       int j;
45412 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45413 +
45414 +       for (j = 0; j < chip->device->blocks; j++) {
45415 +               unsigned short row = j << 6;
45416 +               uint8_t stat;
45417 +
45418 +               /*
45419 +                * Read Page
45420 +                */
45421 +               ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45422 +
45423 +               /*
45424 +                * Wait
45425 +                */
45426 +               stat = ubi32_nand_spi_er_busywait();
45427 +               if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45428 +                       DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45429 +
45430 +                       /*
45431 +                        * Chip is stuck?
45432 +                        */
45433 +                       return -EIO;
45434 +               }
45435 +
45436 +               /*
45437 +                * Check factory bad block mark
45438 +                */
45439 +               ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000);
45440 +
45441 +               if ((io->status1 >> 24) != 0xFF) {
45442 +                       chip->nbb++;
45443 +                       __set_bit(j, chip->bbt);
45444 +                       continue;
45445 +               }
45446 +
45447 +               ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000 | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 8));
45448 +               if (io->status1 == 0xdeadbeef) {
45449 +                       chip->nbb++;
45450 +                       __set_bit(j, chip->bbt);
45451 +               }
45452 +       }
45453 +
45454 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
45455 +       printk("%s: Bad Block Table:", chip->name);
45456 +       for (j = 0; j < chip->device->blocks; j++) {
45457 +               if ((j % 64) == 0) {
45458 +                       printk("\n%s: block %03x: ", chip->name, j);
45459 +               }
45460 +               printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
45461 +       }
45462 +       printk("\n%s: Bad Block Numbers: ", chip->name);
45463 +       for (j = 0; j < chip->device->blocks; j++) {
45464 +               if (test_bit(j, chip->bbt)) {
45465 +                       printk("%x ", j);
45466 +               }
45467 +       }
45468 +       printk("\n");
45469 +#endif
45470 +
45471 +       return 0;
45472 +}
45473 +
45474 +#ifndef MODULE
45475 +/*
45476 + * Called at boot time:
45477 + *
45478 + * ubi32_nand_spi_er=read_only
45479 + *     if read_only specified then do not unlock device
45480 + */
45481 +static int __init ubi32_nand_spi_er_setup(char *str)
45482 +{
45483 +       if (str && (strncasecmp(str, "read_only", 9) == 0)) {
45484 +               read_only = 1;
45485 +       }
45486 +       return 0;
45487 +}
45488 +
45489 +__setup("ubi32_nand_spi_er=", ubi32_nand_spi_er_setup);
45490 +#endif
45491 +
45492 +/*
45493 + * ubi32_nand_spi_er_probe
45494 + *     Detect and initialize ubi32_nand_spi_er device.
45495 + */
45496 +static int __devinit ubi32_nand_spi_er_probe(struct platform_device *pdev)
45497 +{
45498 +       uint32_t i;
45499 +       uint32_t id;
45500 +       int res;
45501 +       size_t bbt_bytes;
45502 +       struct ubi32_nand_spi_er *chip;
45503 +       const struct ubi32_nand_spi_er_device *device;
45504 +       struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45505 +
45506 +       /*
45507 +        * Reset
45508 +        */
45509 +       for (i = 0; i < 2; i++) {
45510 +               io->ctl1 &= ~IO_XFL_CTL1_MASK;
45511 +               io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45512 +               io->ctl2 = IO_XFL_CTL2_FC_CMD(0xFF);
45513 +               FLASH_COMMAND_EXEC(io);
45514 +               udelay(250);
45515 +       }
45516 +       udelay(1000);
45517 +
45518 +       /*
45519 +        * Read out ID
45520 +        */
45521 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45522 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(2) |
45523 +                   IO_XFL_CTL1_FC_ADDR;
45524 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x9F);
45525 +       FLASH_COMMAND_EXEC(io);
45526 +
45527 +       id = io->status1 >> 16;
45528 +       device = ubi32_nand_spi_er_devices;
45529 +       for (i = 0; i < ARRAY_SIZE(ubi32_nand_spi_er_devices); i++) {
45530 +               if (device->id == id) {
45531 +                       break;
45532 +               }
45533 +               device++;
45534 +       }
45535 +       if (i == ARRAY_SIZE(ubi32_nand_spi_er_devices)) {
45536 +               return -ENODEV;
45537 +       }
45538 +
45539 +       /*
45540 +        * Initialize our chip structure
45541 +        */
45542 +       bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
45543 +       chip = kzalloc(sizeof(struct ubi32_nand_spi_er) + bbt_bytes, GFP_KERNEL);
45544 +       if (!chip) {
45545 +               return -ENOMEM;
45546 +       }
45547 +       snprintf(chip->name, sizeof(chip->name), "%s", device->name);
45548 +
45549 +       chip->device = device;
45550 +       chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45551 +
45552 +       mutex_init(&chip->lock);
45553 +
45554 +       chip->mtd.type = MTD_NANDFLASH;
45555 +       chip->mtd.flags = MTD_WRITEABLE;
45556 +
45557 +       /*
45558 +        * #blocks * block size * n blocks
45559 +        */
45560 +       chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
45561 +       chip->mtd.erasesize = device->erase_size;
45562 +
45563 +       /*
45564 +        * 1 page, optionally we can support partial write (512)
45565 +        */
45566 +       chip->mtd.writesize = device->write_size;
45567 +       chip->mtd.name = device->name;
45568 +       chip->mtd.erase = ubi32_nand_spi_er_erase;
45569 +       chip->mtd.read = ubi32_nand_spi_er_read;
45570 +       chip->mtd.write = ubi32_nand_spi_er_write;
45571 +       chip->mtd.block_isbad = ubi32_nand_spi_er_isbad;
45572 +       chip->mtd.block_markbad = ubi32_nand_spi_er_markbad;
45573 +       chip->mtd.priv = chip;
45574 +
45575 +       /*
45576 +        * Cache the bad block table
45577 +        */
45578 +       res = ubi32_nand_spi_er_read_bbt(chip);
45579 +       if (res) {
45580 +               kfree(chip);
45581 +               return res;
45582 +       }
45583 +
45584 +       /*
45585 +        * Un/lock the chip
45586 +        */
45587 +       io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45588 +       io->ctl1 &= ~IO_XFL_CTL1_MASK;
45589 +       io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(2);
45590 +       io->ctl2 = IO_XFL_CTL2_FC_CMD(0x1F);
45591 +
45592 +       if (read_only) {
45593 +               i = 0xa0380000;
45594 +       } else {
45595 +               i = 0xa0000000;
45596 +       }
45597 +       asm volatile (
45598 +               "       bset            "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)")   \n\t"
45599 +               "       pipe_flush      0                                                                       \n\t"
45600 +
45601 +               /*
45602 +                * Move the data into the FIFO
45603 +                */
45604 +               "       move.4          "D(IO_TX_FIFO)"(%[port]), %[word1]                                      \n\t"
45605 +
45606 +               /*
45607 +                * Kick off the flash command
45608 +                */
45609 +               "       bset    "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)")                      \n\t"
45610 +               "       jmpt.t  .+4                                                                             \n\t"
45611 +               "       bset    "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)")                     \n\t"
45612 +
45613 +               /*
45614 +                * Wait for the transaction to finish
45615 +                */
45616 +               "       btst    "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)")                       \n\t"
45617 +               "       jmpeq.f .-4                                                                             \n\t"
45618 +
45619 +               :
45620 +               : [word1] "d" (i),
45621 +                 [port] "a" (FLASH_PORT)
45622 +               : "cc"
45623 +       );
45624 +       io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45625 +
45626 +       dev_set_drvdata(&pdev->dev, chip);
45627 +
45628 +       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]" : "");
45629 +       return add_mtd_device(&chip->mtd);
45630 +}
45631 +
45632 +/*
45633 + * ubi32_nand_spi_er_remove
45634 + */
45635 +static int __devexit ubi32_nand_spi_er_remove(struct platform_device *pdev)
45636 +{
45637 +       struct ubi32_nand_spi_er *chip = dev_get_drvdata(&pdev->dev);
45638 +       int status;
45639 +
45640 +       DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", chip->name);
45641 +
45642 +       status = del_mtd_device(&chip->mtd);
45643 +       if (status == 0) {
45644 +               kfree(chip);
45645 +       }
45646 +
45647 +       dev_set_drvdata(&pdev->dev, NULL);
45648 +       return status;
45649 +}
45650 +
45651 +static struct platform_device *ubi32_nand_spi_er_device;
45652 +
45653 +static struct platform_driver ubi32_nand_spi_er_driver = {
45654 +       .driver = {
45655 +               .name           = DRIVER_NAME,
45656 +               .owner          = THIS_MODULE,
45657 +       },
45658 +
45659 +       .probe          = ubi32_nand_spi_er_probe,
45660 +       .remove         = ubi32_nand_spi_er_remove,
45661 +};
45662 +
45663 +/*
45664 + * ubi32_nand_spi_er_init
45665 + */
45666 +static int __init ubi32_nand_spi_er_init(void)
45667 +{
45668 +       int ret;
45669 +
45670 +       ret = platform_driver_register(&ubi32_nand_spi_er_driver);
45671 +
45672 +       if (ret) {
45673 +               return ret;
45674 +       }
45675 +
45676 +       ubi32_nand_spi_er_device = platform_device_alloc(DRIVER_NAME, 0);
45677 +       if (!ubi32_nand_spi_er_device) {
45678 +               return -ENOMEM;
45679 +       }
45680 +
45681 +       ret = platform_device_add(ubi32_nand_spi_er_device);
45682 +       if (ret) {
45683 +               platform_device_put(ubi32_nand_spi_er_device);
45684 +               platform_driver_unregister(&ubi32_nand_spi_er_driver);
45685 +       }
45686 +
45687 +       return ret;
45688 +}
45689 +module_init(ubi32_nand_spi_er_init);
45690 +
45691 +/*
45692 + * ubi32_nand_spi_er_exit
45693 + */
45694 +static void __exit ubi32_nand_spi_er_exit(void)
45695 +{
45696 +       platform_device_unregister(ubi32_nand_spi_er_device);
45697 +       platform_driver_unregister(&ubi32_nand_spi_er_driver);
45698 +}
45699 +module_exit(ubi32_nand_spi_er_exit);
45700 +
45701 +
45702 +MODULE_LICENSE("GPL");
45703 +MODULE_AUTHOR("Patrick Tjin");
45704 +MODULE_DESCRIPTION("MTD ubi32_nand_spi_er driver for ubicom32 SPI flash controller.");
45705 --- a/drivers/net/Kconfig
45706 +++ b/drivers/net/Kconfig
45707 @@ -2540,6 +2540,19 @@ config JME
45708           To compile this driver as a module, choose M here. The module
45709           will be called jme.
45710  
45711 +config UBICOM32_GMAC
45712 +       tristate "Ubicom Gigabit Ethernet support"
45713 +       depends on UBICOM32
45714 +       help
45715 +         Gigabit Ethernet support for ubicom32 processors
45716 +
45717 +config UBICOM32_OCM_FOR_SKB
45718 +        bool  "USE OCM for SKB (EXPERIMENTAL)"
45719 +        depends on UBICOM32_GMAC
45720 +       default n
45721 +        help
45722 +          Allocate skb from OCM for Ethernet Receive when possible
45723 +
45724  endif # NETDEV_1000
45725  
45726  #
45727 --- a/drivers/net/Makefile
45728 +++ b/drivers/net/Makefile
45729 @@ -272,3 +272,5 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
45730  obj-$(CONFIG_SFC) += sfc/
45731  
45732  obj-$(CONFIG_WIMAX) += wimax/
45733 +
45734 +obj-$(CONFIG_UBICOM32_GMAC) += ubi32-eth.o
45735 --- /dev/null
45736 +++ b/drivers/net/ubi32-eth.c
45737 @@ -0,0 +1,760 @@
45738 +/*
45739 + * drivers/net/ubi32-eth.c
45740 + *   Ubicom32 ethernet TIO interface driver.
45741 + *
45742 + * (C) Copyright 2009, Ubicom, Inc.
45743 + *
45744 + * This file is part of the Ubicom32 Linux Kernel Port.
45745 + *
45746 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
45747 + * it and/or modify it under the terms of the GNU General Public License
45748 + * as published by the Free Software Foundation, either version 2 of the
45749 + * License, or (at your option) any later version.
45750 + *
45751 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
45752 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
45753 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
45754 + * the GNU General Public License for more details.
45755 + *
45756 + * You should have received a copy of the GNU General Public License
45757 + * along with the Ubicom32 Linux Kernel Port.  If not,
45758 + * see <http://www.gnu.org/licenses/>.
45759 + *
45760 + * Ubicom32 implementation derived from (with many thanks):
45761 + *   arch/m68knommu
45762 + *   arch/blackfin
45763 + *   arch/parisc
45764 + */
45765 +/*
45766 + * ubi32_eth.c
45767 + * Ethernet driver for Ip5k/Ip7K
45768 + */
45769 +
45770 +#include <linux/module.h>
45771 +#include <linux/init.h>
45772 +#include <linux/moduleparam.h>
45773 +
45774 +#include <linux/sched.h>
45775 +#include <linux/kernel.h>
45776 +#include <linux/errno.h>
45777 +#include <linux/types.h>
45778 +#include <linux/interrupt.h>
45779 +
45780 +#include <linux/in.h>
45781 +#include <linux/netdevice.h>
45782 +#include <linux/etherdevice.h>
45783 +#include <linux/mii.h>
45784 +#include <linux/if_vlan.h>
45785 +#include <linux/ip.h>
45786 +#include <linux/tcp.h>
45787 +#include <linux/skbuff.h>
45788 +#include <asm/checksum.h>
45789 +#include <asm/ip5000.h>
45790 +#include <asm/devtree.h>
45791 +#include <asm/system.h>
45792 +
45793 +#define UBICOM32_USE_NAPI      /* define this to use NAPI instead of tasklet */
45794 +//#define UBICOM32_USE_POLLING /* define this to use polling instead of interrupt */
45795 +#include "ubi32-eth.h"
45796 +
45797 +/*
45798 + * TODO:
45799 + * mac address from flash
45800 + * multicast filter
45801 + * ethtool support
45802 + * sysfs support
45803 + * skb->nrfrag support
45804 + * ioctl
45805 + * monitor phy status
45806 + */
45807 +
45808 +extern int ubi32_ocm_skbuf_max, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
45809 +static const char *eth_if_name[UBI32_ETH_NUM_OF_DEVICES] =
45810 +       {"eth_lan", "eth_wan"};
45811 +static struct net_device *ubi32_eth_devices[UBI32_ETH_NUM_OF_DEVICES] =
45812 +       {NULL, NULL};
45813 +static u8_t mac_addr[UBI32_ETH_NUM_OF_DEVICES][ETH_ALEN] = {
45814 +       {0x00, 0x03, 0x64, 'l', 'a', 'n'},
45815 +       {0x00, 0x03, 0x64, 'w', 'a', 'n'}};
45816 +
45817 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
45818 +static inline struct sk_buff *ubi32_alloc_skb_ocm(struct net_device *dev, unsigned int length)
45819 +{
45820 +       return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
45821 +}
45822 +#endif
45823 +
45824 +static inline struct sk_buff *ubi32_alloc_skb(struct net_device *dev, unsigned int length)
45825 +{
45826 +       return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN);
45827 +}
45828 +
45829 +static void ubi32_eth_vp_rxtx_enable(struct net_device *dev)
45830 +{
45831 +       struct ubi32_eth_private *priv = netdev_priv(dev);
45832 +       priv->regs->command = UBI32_ETH_VP_CMD_RX_ENABLE | UBI32_ETH_VP_CMD_TX_ENABLE;
45833 +       priv->regs->int_mask = (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
45834 +       ubicom32_set_interrupt(priv->vp_int_bit);
45835 +}
45836 +
45837 +static void ubi32_eth_vp_rxtx_stop(struct net_device *dev)
45838 +{
45839 +       struct ubi32_eth_private *priv = netdev_priv(dev);
45840 +       priv->regs->command = 0;
45841 +       priv->regs->int_mask = 0;
45842 +       ubicom32_set_interrupt(priv->vp_int_bit);
45843 +
45844 +       /* Wait for graceful shutdown */
45845 +       while (priv->regs->status & (UBI32_ETH_VP_STATUS_RX_STATE | UBI32_ETH_VP_STATUS_TX_STATE));
45846 +}
45847 +
45848 +/*
45849 + * ubi32_eth_tx_done()
45850 + */
45851 +static int ubi32_eth_tx_done(struct net_device *dev)
45852 +{
45853 +       struct ubi32_eth_private *priv;
45854 +       struct sk_buff *skb;
45855 +       volatile void *pdata;
45856 +       struct ubi32_eth_dma_desc *desc;
45857 +       u32_t   count = 0;
45858 +
45859 +       priv = netdev_priv(dev);
45860 +
45861 +       priv->regs->int_status &= ~UBI32_ETH_VP_INT_TX;
45862 +       while (priv->tx_tail != priv->regs->tx_out) {
45863 +               pdata = priv->regs->tx_dma_ring[priv->tx_tail];
45864 +               BUG_ON(pdata == NULL);
45865 +
45866 +               skb = container_of((void *)pdata, struct sk_buff, cb);
45867 +               desc = (struct ubi32_eth_dma_desc *)pdata;
45868 +               if (unlikely(!(desc->status & UBI32_ETH_VP_TX_OK))) {
45869 +                       dev->stats.tx_errors++;
45870 +               } else {
45871 +                       dev->stats.tx_packets++;
45872 +                       dev->stats.tx_bytes += skb->len;
45873 +               }
45874 +               dev_kfree_skb_any(skb);
45875 +               priv->regs->tx_dma_ring[priv->tx_tail] = NULL;
45876 +               priv->tx_tail = (priv->tx_tail + 1) & TX_DMA_RING_MASK;
45877 +               count++;
45878 +       }
45879 +
45880 +       if (unlikely(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
45881 +               spin_lock(&priv->lock);
45882 +               if (priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL) {
45883 +                       priv->regs->status &= ~UBI32_ETH_VP_STATUS_TX_Q_FULL;
45884 +                       netif_wake_queue(dev);
45885 +               }
45886 +               spin_unlock(&priv->lock);
45887 +       }
45888 +       return count;
45889 +}
45890 +
45891 +/*
45892 + * ubi32_eth_receive()
45893 + *     To avoid locking overhead, this is called only
45894 + *     by tasklet when not using NAPI, or
45895 + *     by NAPI poll when using NAPI.
45896 + *     return number of frames processed
45897 + */
45898 +static int ubi32_eth_receive(struct net_device *dev, int quota)
45899 +{
45900 +       struct ubi32_eth_private *priv = netdev_priv(dev);
45901 +       unsigned short rx_in = priv->regs->rx_in;
45902 +       struct sk_buff *skb;
45903 +       struct ubi32_eth_dma_desc *desc = NULL;
45904 +       volatile void *pdata;
45905 +
45906 +       int extra_reserve_adj;
45907 +       int extra_alloc = UBI32_ETH_RESERVE_SPACE + UBI32_ETH_TRASHED_MEMORY;
45908 +       int replenish_cnt, count = 0;
45909 +       int replenish_max = RX_DMA_MAX_QUEUE_SIZE;
45910 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
45911 +       if (likely(dev == ubi32_eth_devices[0]))
45912 +               replenish_max = min(ubi32_ocm_skbuf_max, RX_DMA_MAX_QUEUE_SIZE);;
45913 +#endif
45914 +
45915 +       if (unlikely(rx_in == priv->regs->rx_out))
45916 +               priv->vp_stats.rx_q_full_cnt++;
45917 +
45918 +       priv->regs->int_status &= ~UBI32_ETH_VP_INT_RX;
45919 +       while (priv->rx_tail != priv->regs->rx_out) {
45920 +               if (unlikely(count == quota)) {
45921 +                       /* There is still frame pending to be processed */
45922 +                       priv->vp_stats.rx_throttle++;
45923 +                       break;
45924 +               }
45925 +
45926 +               pdata = priv->regs->rx_dma_ring[priv->rx_tail];
45927 +               BUG_ON(pdata == NULL);
45928 +
45929 +               desc = (struct ubi32_eth_dma_desc *)pdata;
45930 +               skb = container_of((void *)pdata, struct sk_buff, cb);
45931 +               count++;
45932 +               priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
45933 +               priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
45934 +
45935 +               /*
45936 +                * Check only RX_OK bit here.
45937 +                * The rest of status word is used as timestamp
45938 +                */
45939 +               if (unlikely(!(desc->status & UBI32_ETH_VP_RX_OK))) {
45940 +                       dev->stats.rx_errors++;
45941 +                       dev_kfree_skb_any(skb);
45942 +                       continue;
45943 +               }
45944 +
45945 +               skb_put(skb, desc->data_len);
45946 +               skb->dev = dev;
45947 +               skb->protocol = eth_type_trans(skb, dev);
45948 +               skb->ip_summed = CHECKSUM_NONE;
45949 +               dev->stats.rx_bytes += skb->len;
45950 +               dev->stats.rx_packets++;
45951 +#ifndef UBICOM32_USE_NAPI
45952 +               netif_rx(skb);
45953 +#else
45954 +               netif_receive_skb(skb);
45955 +#endif
45956 +       }
45957 +
45958 +       /* fill in more descripor for VP*/
45959 +       replenish_cnt =  replenish_max -
45960 +               ((RX_DMA_RING_SIZE + rx_in - priv->rx_tail) & RX_DMA_RING_MASK);
45961 +       if (replenish_cnt > 0) {
45962 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
45963 +               /*
45964 +                * black magic for perforamnce:
45965 +                *   Try to allocate skb from OCM only for first Ethernet I/F.
45966 +                *   Also limit number of RX buffers to 21 due to limited OCM.
45967 +                */
45968 +               if (likely(dev == ubi32_eth_devices[0])) {
45969 +                       do {
45970 +                               skb = ubi32_alloc_skb_ocm(dev, RX_BUF_SIZE + extra_alloc);
45971 +                               if (!skb) {
45972 +                                       break;
45973 +                               }
45974 +                               /* set up dma descriptor */
45975 +                               ubi32_ocm_skbuf++;
45976 +                               desc = (struct ubi32_eth_dma_desc *)skb->cb;
45977 +                               extra_reserve_adj =
45978 +                                       ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
45979 +                                       (CACHE_LINE_SIZE - 1);
45980 +                               skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
45981 +                               desc->data_pointer = skb->data;
45982 +                               desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
45983 +                               desc->data_len = 0;
45984 +                               desc->status = 0;
45985 +                               priv->regs->rx_dma_ring[rx_in] = desc;
45986 +                               rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
45987 +                       } while (--replenish_cnt > 0);
45988 +               }
45989 +#endif
45990 +
45991 +               while (replenish_cnt-- > 0) {
45992 +                       skb = ubi32_alloc_skb(dev, RX_BUF_SIZE + extra_alloc);
45993 +                       if (!skb) {
45994 +                               priv->vp_stats.rx_alloc_err++;
45995 +                               break;
45996 +                       }
45997 +                       /* set up dma descriptor */
45998 +                       ubi32_ddr_skbuf++;
45999 +                       desc = (struct ubi32_eth_dma_desc *)skb->cb;
46000 +                       extra_reserve_adj =
46001 +                               ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
46002 +                               (CACHE_LINE_SIZE - 1);
46003 +                       skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
46004 +                       desc->data_pointer = skb->data;
46005 +                       desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
46006 +                       desc->data_len = 0;
46007 +                       desc->status = 0;
46008 +                       priv->regs->rx_dma_ring[rx_in] = desc;
46009 +                       rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
46010 +               }
46011 +
46012 +               wmb();
46013 +               priv->regs->rx_in = rx_in;
46014 +               ubicom32_set_interrupt(priv->vp_int_bit);
46015 +       }
46016 +
46017 +       if (likely(count > 0)) {
46018 +               dev->last_rx = jiffies;
46019 +       }
46020 +       return count;
46021 +}
46022 +
46023 +#ifdef UBICOM32_USE_NAPI
46024 +static int ubi32_eth_napi_poll(struct napi_struct *napi, int budget)
46025 +{
46026 +       struct ubi32_eth_private *priv = container_of(napi, struct ubi32_eth_private, napi);
46027 +       struct net_device *dev = priv->dev;
46028 +       u32_t count;
46029 +
46030 +       if (priv->tx_tail != priv->regs->tx_out) {
46031 +                ubi32_eth_tx_done(dev);
46032 +        }
46033 +
46034 +       count = ubi32_eth_receive(dev, budget);
46035 +
46036 +       if (count < budget) {
46037 +               napi_complete(napi);
46038 +               priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46039 +               if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46040 +                       if (napi_reschedule(napi)) {
46041 +                               priv->regs->int_mask = 0;
46042 +                       }
46043 +               }
46044 +       }
46045 +       return count;
46046 +}
46047 +
46048 +#else
46049 +static void ubi32_eth_do_tasklet(unsigned long arg)
46050 +{
46051 +       struct net_device *dev = (struct net_device *)arg;
46052 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46053 +
46054 +       if (priv->tx_tail != priv->regs->tx_out) {
46055 +               ubi32_eth_tx_done(dev);
46056 +       }
46057 +
46058 +       /* always call receive to process new RX frame as well as replenish RX buffers */
46059 +       ubi32_eth_receive(dev, UBI32_RX_BOUND);
46060 +
46061 +       priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46062 +       if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46063 +               priv->regs->int_mask = 0;
46064 +               tasklet_schedule(&priv->tsk);
46065 +       }
46066 +}
46067 +#endif
46068 +
46069 +#if defined(UBICOM32_USE_POLLING)
46070 +static struct timer_list eth_poll_timer;
46071 +
46072 +static void ubi32_eth_poll(unsigned long arg)
46073 +{
46074 +       struct net_device *dev;
46075 +       struct ubi32_eth_private *priv;
46076 +       int i;
46077 +
46078 +       for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46079 +               dev = ubi32_eth_devices[i];
46080 +               if (dev && (dev->flags & IFF_UP)) {
46081 +                       priv = netdev_priv(dev);
46082 +#ifdef UBICOM32_USE_NAPI
46083 +                       napi_schedule(&priv->napi);
46084 +#else
46085 +                       tasklet_schedule(&priv->tsk);
46086 +#endif
46087 +               }
46088 +       }
46089 +
46090 +       eth_poll_timer.expires = jiffies + 2;
46091 +       add_timer(&eth_poll_timer);
46092 +}
46093 +
46094 +#else
46095 +static irqreturn_t ubi32_eth_interrupt(int irq, void *dev_id)
46096 +{
46097 +       struct ubi32_eth_private *priv;
46098 +
46099 +       struct net_device *dev = (struct net_device *)dev_id;
46100 +       BUG_ON(irq != dev->irq);
46101 +
46102 +       priv = netdev_priv(dev);
46103 +       if (unlikely(!(priv->regs->int_status & priv->regs->int_mask))) {
46104 +               return IRQ_NONE;
46105 +       }
46106 +
46107 +       /*
46108 +        * Disable port interrupt
46109 +        */
46110 +#ifdef UBICOM32_USE_NAPI
46111 +       if (napi_schedule_prep(&priv->napi)) {
46112 +               priv->regs->int_mask = 0;
46113 +               __napi_schedule(&priv->napi);
46114 +       }
46115 +#else
46116 +       priv->regs->int_mask = 0;
46117 +       tasklet_schedule(&priv->tsk);
46118 +#endif
46119 +       return IRQ_HANDLED;
46120 +}
46121 +#endif
46122 +
46123 +/*
46124 + * ubi32_eth_open
46125 + */
46126 +static int ubi32_eth_open(struct net_device *dev)
46127 +{
46128 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46129 +       int err;
46130 +
46131 +       printk(KERN_INFO "eth open %s\n",dev->name);
46132 +#ifndef UBICOM32_USE_POLLING
46133 +       /* request_region() */
46134 +       err = request_irq(dev->irq, ubi32_eth_interrupt, IRQF_DISABLED, dev->name, dev);
46135 +       if (err) {
46136 +               printk(KERN_WARNING "fail to request_irq %d\n",err);
46137 +                return -ENODEV;
46138 +       }
46139 +#endif
46140 +#ifdef  UBICOM32_USE_NAPI
46141 +       napi_enable(&priv->napi);
46142 +#else
46143 +       tasklet_init(&priv->tsk, ubi32_eth_do_tasklet, (unsigned long)dev);
46144 +#endif
46145 +
46146 +       /* call receive to supply RX buffers */
46147 +       ubi32_eth_receive(dev, RX_DMA_MAX_QUEUE_SIZE);
46148 +
46149 +       /* check phy status and call netif_carrier_on */
46150 +       ubi32_eth_vp_rxtx_enable(dev);
46151 +       netif_start_queue(dev);
46152 +       return 0;
46153 +}
46154 +
46155 +static int ubi32_eth_close(struct net_device *dev)
46156 +{
46157 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46158 +       volatile void *pdata;
46159 +       struct sk_buff *skb;
46160 +
46161 +#ifndef UBICOM32_USE_POLLING
46162 +       free_irq(dev->irq, dev);
46163 +#endif
46164 +       netif_stop_queue(dev); /* can't transmit any more */
46165 +#ifdef UBICOM32_USE_NAPI
46166 +       napi_disable(&priv->napi);
46167 +#else
46168 +       tasklet_kill(&priv->tsk);
46169 +#endif
46170 +       ubi32_eth_vp_rxtx_stop(dev);
46171 +
46172 +       /*
46173 +        * RX clean up
46174 +        */
46175 +       while (priv->rx_tail != priv->regs->rx_in) {
46176 +               pdata = priv->regs->rx_dma_ring[priv->rx_tail];
46177 +               skb = container_of((void *)pdata, struct sk_buff, cb);
46178 +               priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
46179 +               dev_kfree_skb_any(skb);
46180 +               priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
46181 +       }
46182 +       priv->regs->rx_in = 0;
46183 +       priv->regs->rx_out = priv->regs->rx_in;
46184 +       priv->rx_tail = priv->regs->rx_in;
46185 +
46186 +       /*
46187 +        * TX clean up
46188 +        */
46189 +       BUG_ON(priv->regs->tx_out != priv->regs->tx_in);
46190 +       ubi32_eth_tx_done(dev);
46191 +       BUG_ON(priv->tx_tail != priv->regs->tx_in);
46192 +       priv->regs->tx_in = 0;
46193 +       priv->regs->tx_out = priv->regs->tx_in;
46194 +       priv->tx_tail = priv->regs->tx_in;
46195 +
46196 +       return 0;
46197 +}
46198 +
46199 +/*
46200 + * ubi32_eth_set_config
46201 + */
46202 +static int ubi32_eth_set_config(struct net_device *dev, struct ifmap *map)
46203 +{
46204 +       /* if must to down to config it */
46205 +       printk(KERN_INFO "set_config %x\n", dev->flags);
46206 +       if (dev->flags & IFF_UP)
46207 +               return -EBUSY;
46208 +
46209 +       /* I/O and IRQ can not be changed */
46210 +       if (map->base_addr != dev->base_addr) {
46211 +               printk(KERN_WARNING "%s: Can't change I/O address\n", dev->name);
46212 +               return -EOPNOTSUPP;
46213 +       }
46214 +
46215 +#ifndef UBICOM32_USE_POLLING
46216 +       if (map->irq != dev->irq) {
46217 +               printk(KERN_WARNING "%s: Can't change IRQ\n", dev->name);
46218 +               return -EOPNOTSUPP;
46219 +       }
46220 +#endif
46221 +
46222 +       /* ignore other fields */
46223 +       return 0;
46224 +}
46225 +
46226 +static int ubi32_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
46227 +{
46228 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46229 +       struct ubi32_eth_dma_desc *desc = NULL;
46230 +       unsigned short space, tx_in;
46231 +
46232 +       tx_in = priv->regs->tx_in;
46233 +
46234 +       dev->trans_start = jiffies; /* save the timestamp */
46235 +       space = TX_DMA_RING_MASK - ((TX_DMA_RING_SIZE + tx_in - priv->tx_tail) & TX_DMA_RING_MASK);
46236 +
46237 +       if (unlikely(space == 0)) {
46238 +               if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46239 +                       spin_lock(&priv->lock);
46240 +                       if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46241 +                               priv->regs->status |= UBI32_ETH_VP_STATUS_TX_Q_FULL;
46242 +                               priv->vp_stats.tx_q_full_cnt++;
46243 +                               netif_stop_queue(dev);
46244 +                       }
46245 +                       spin_unlock(&priv->lock);
46246 +               }
46247 +
46248 +               /* give both HW and this driver an extra trigger */
46249 +               priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46250 +#ifndef UBICOM32_USE_POLLING
46251 +               ubicom32_set_interrupt(dev->irq);
46252 +#endif
46253 +               ubicom32_set_interrupt(priv->vp_int_bit);
46254 +
46255 +               return NETDEV_TX_BUSY;
46256 +       }
46257 +
46258 +       /*still have room */
46259 +       desc = (struct ubi32_eth_dma_desc *)skb->cb;
46260 +       desc->data_pointer = skb->data;
46261 +       desc->data_len = skb->len;
46262 +       priv->regs->tx_dma_ring[tx_in] = desc;
46263 +       tx_in = ((tx_in + 1) & TX_DMA_RING_MASK);
46264 +       wmb();
46265 +       priv->regs->tx_in = tx_in;
46266 +       /* kick the HRT */
46267 +       ubicom32_set_interrupt(priv->vp_int_bit);
46268 +
46269 +       return NETDEV_TX_OK;
46270 +}
46271 +
46272 +/*
46273 + * Deal with a transmit timeout.
46274 + */
46275 +static void ubi32_eth_tx_timeout (struct net_device *dev)
46276 +{
46277 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46278 +       dev->stats.tx_errors++;
46279 +       priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46280 +#ifndef UBICOM32_USE_POLLING
46281 +       ubicom32_set_interrupt(dev->irq);
46282 +#endif
46283 +       ubicom32_set_interrupt(priv->vp_int_bit);
46284 +}
46285 +
46286 +static int ubi32_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
46287 +{
46288 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46289 +       struct mii_ioctl_data *data = if_mii(rq);
46290 +
46291 +       printk(KERN_INFO "ioctl %s, %d\n", dev->name, cmd);
46292 +       switch (cmd) {
46293 +       case SIOCGMIIPHY:
46294 +               data->phy_id = 0;
46295 +               break;
46296 +
46297 +       case SIOCGMIIREG:
46298 +               if ((data->reg_num & 0x1F) == MII_BMCR) {
46299 +                       /* Make up MII control register value from what we know */
46300 +                       data->val_out = 0x0000
46301 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_DUPLEX)
46302 +                                       ? BMCR_FULLDPLX : 0)
46303 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED100)
46304 +                                       ? BMCR_SPEED100 : 0)
46305 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED1000)
46306 +                                       ? BMCR_SPEED1000 : 0);
46307 +               } else if ((data->reg_num & 0x1F) == MII_BMSR) {
46308 +                       /* Make up MII status register value from what we know */
46309 +                       data->val_out =
46310 +                       (BMSR_100FULL|BMSR_100HALF|BMSR_10FULL|BMSR_10HALF)
46311 +                       | ((priv->regs->status & UBI32_ETH_VP_STATUS_LINK)
46312 +                                       ? BMSR_LSTATUS : 0);
46313 +               } else {
46314 +                       return -EIO;
46315 +               }
46316 +               break;
46317 +
46318 +       case SIOCSMIIREG:
46319 +               return -EOPNOTSUPP;
46320 +               break;
46321 +
46322 +       default:
46323 +               return -EOPNOTSUPP;
46324 +       }
46325 +
46326 +       return 0;
46327 +}
46328 +
46329 +/*
46330 + * Return statistics to the caller
46331 + */
46332 +static struct net_device_stats *ubi32_eth_get_stats(struct net_device *dev)
46333 +{
46334 +       return &dev->stats;
46335 +}
46336 +
46337 +
46338 +static int ubi32_eth_change_mtu(struct net_device *dev, int new_mtu)
46339 +{
46340 +       struct ubi32_eth_private *priv = netdev_priv(dev);
46341 +       unsigned long flags;
46342 +
46343 +       if ((new_mtu < 68) || (new_mtu > 1500))
46344 +               return -EINVAL;
46345 +
46346 +       spin_lock_irqsave(&priv->lock, flags);
46347 +       dev->mtu = new_mtu;
46348 +       spin_unlock_irqrestore(&priv->lock, flags);
46349 +       printk(KERN_INFO "set mtu to %d", new_mtu);
46350 +       return 0;
46351 +}
46352 +
46353 +/*
46354 + * ubi32_eth_cleanup: unload the module
46355 + */
46356 +void ubi32_eth_cleanup(void)
46357 +{
46358 +       struct ubi32_eth_private *priv;
46359 +       struct net_device *dev;
46360 +       int i;
46361 +
46362 +       for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46363 +               dev = ubi32_eth_devices[i];
46364 +               if (dev) {
46365 +                       priv = netdev_priv(dev);
46366 +                       kfree(priv->regs->tx_dma_ring);
46367 +                       unregister_netdev(dev);
46368 +                       free_netdev(dev);
46369 +                       ubi32_eth_devices[i] = NULL;
46370 +               }
46371 +       }
46372 +}
46373 +
46374 +int ubi32_eth_init_module(void)
46375 +{
46376 +       struct ethtionode *eth_node;
46377 +       struct net_device *dev;
46378 +       struct ubi32_eth_private *priv;
46379 +       int i, err;
46380 +
46381 +       /*
46382 +        * Device allocation.
46383 +        */
46384 +       err = 0;
46385 +       for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46386 +               /*
46387 +                * See if the eth_vp is in the device tree.
46388 +                */
46389 +               eth_node = (struct ethtionode *)devtree_find_node(eth_if_name[i]);
46390 +               if (!eth_node) {
46391 +                       printk(KERN_INFO "%s does not exist\n", eth_if_name[i]);
46392 +                       continue;
46393 +               }
46394 +
46395 +               eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46396 +                               sizeof(struct ubi32_eth_dma_desc *) *
46397 +                               (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE),
46398 +                               GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
46399 +
46400 +               if (eth_node->tx_dma_ring == NULL) {
46401 +                       eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46402 +                               sizeof(struct ubi32_eth_dma_desc *) *
46403 +                               (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE), GFP_KERNEL);
46404 +                       printk(KERN_INFO "fail to allocate from OCM\n");
46405 +               }
46406 +
46407 +               if (!eth_node->tx_dma_ring) {
46408 +                       err = -ENOMEM;
46409 +                       break;
46410 +               }
46411 +               eth_node->rx_dma_ring = eth_node->tx_dma_ring + TX_DMA_RING_SIZE;
46412 +               eth_node->tx_sz = TX_DMA_RING_SIZE - 1;
46413 +               eth_node->rx_sz = RX_DMA_RING_SIZE - 1;
46414 +
46415 +               dev = alloc_etherdev(sizeof(struct ubi32_eth_private));
46416 +               if (!dev) {
46417 +                       kfree(eth_node->tx_dma_ring);
46418 +                       err = -ENOMEM;
46419 +                       break;
46420 +               }
46421 +               priv = netdev_priv(dev);
46422 +               priv->dev = dev;
46423 +
46424 +               /*
46425 +                * This just fill in some default Ubicom MAC address
46426 +                */
46427 +               memcpy(dev->dev_addr, mac_addr[i], ETH_ALEN);
46428 +               memset(dev->broadcast, 0xff, ETH_ALEN);
46429 +
46430 +               priv->regs = eth_node;
46431 +               priv->regs->command = 0;
46432 +               priv->regs->int_mask = 0;
46433 +               priv->regs->int_status = 0;
46434 +               priv->regs->tx_out = 0;
46435 +               priv->regs->rx_out = 0;
46436 +               priv->regs->tx_in = 0;
46437 +               priv->regs->rx_in = 0;
46438 +               priv->rx_tail = 0;
46439 +               priv->tx_tail = 0;
46440 +
46441 +               priv->vp_int_bit = eth_node->dn.sendirq;
46442 +               dev->irq = eth_node->dn.recvirq;
46443 +
46444 +               spin_lock_init(&priv->lock);
46445 +
46446 +               dev->open               = ubi32_eth_open;
46447 +               dev->stop               = ubi32_eth_close;
46448 +               dev->hard_start_xmit    = ubi32_eth_start_xmit;
46449 +               dev->tx_timeout         = ubi32_eth_tx_timeout;
46450 +               dev->watchdog_timeo     = UBI32_ETH_VP_TX_TIMEOUT;
46451 +
46452 +               dev->set_config         = ubi32_eth_set_config;
46453 +               dev->do_ioctl           = ubi32_eth_ioctl;
46454 +               dev->get_stats          = ubi32_eth_get_stats;
46455 +               dev->change_mtu         = ubi32_eth_change_mtu;
46456 +#ifdef UBICOM32_USE_NAPI
46457 +               netif_napi_add(dev, &priv->napi, ubi32_eth_napi_poll, UBI32_ETH_NAPI_WEIGHT);
46458 +#endif
46459 +               err = register_netdev(dev);
46460 +               if (err) {
46461 +                       printk(KERN_WARNING "Failed to register netdev %s\n", eth_if_name[i]);
46462 +                       //release_region();
46463 +                       free_netdev(dev);
46464 +                       kfree(eth_node->tx_dma_ring);
46465 +                       break;
46466 +               }
46467 +
46468 +               ubi32_eth_devices[i] = dev;
46469 +               printk(KERN_INFO "%s vp_base:0x%p, tio_int:%d irq:%d feature:0x%lx\n",
46470 +                       dev->name, priv->regs, eth_node->dn.sendirq, dev->irq, dev->features);
46471 +       }
46472 +
46473 +       if (err) {
46474 +               ubi32_eth_cleanup();
46475 +               return err;
46476 +       }
46477 +
46478 +       if (!ubi32_eth_devices[0] && !ubi32_eth_devices[1]) {
46479 +               return -ENODEV;
46480 +       }
46481 +
46482 +#if defined(UBICOM32_USE_POLLING)
46483 +       init_timer(&eth_poll_timer);
46484 +       eth_poll_timer.function = ubi32_eth_poll;
46485 +       eth_poll_timer.data = (unsigned long)0;
46486 +       eth_poll_timer.expires = jiffies + 2;
46487 +       add_timer(&eth_poll_timer);
46488 +#endif
46489 +
46490 +       return 0;
46491 +}
46492 +
46493 +module_init(ubi32_eth_init_module);
46494 +module_exit(ubi32_eth_cleanup);
46495 +
46496 +MODULE_AUTHOR("Kan Yan, Greg Ren");
46497 +MODULE_LICENSE("GPL");
46498 --- /dev/null
46499 +++ b/drivers/net/ubi32-eth.h
46500 @@ -0,0 +1,132 @@
46501 +/*
46502 + * drivers/net/ubi32-eth.h
46503 + *   Ubicom32 ethernet TIO interface driver definitions.
46504 + *
46505 + * (C) Copyright 2009, Ubicom, Inc.
46506 + *
46507 + * This file is part of the Ubicom32 Linux Kernel Port.
46508 + *
46509 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46510 + * it and/or modify it under the terms of the GNU General Public License
46511 + * as published by the Free Software Foundation, either version 2 of the
46512 + * License, or (at your option) any later version.
46513 + *
46514 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46515 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46516 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
46517 + * the GNU General Public License for more details.
46518 + *
46519 + * You should have received a copy of the GNU General Public License
46520 + * along with the Ubicom32 Linux Kernel Port.  If not,
46521 + * see <http://www.gnu.org/licenses/>.
46522 + *
46523 + * Ubicom32 implementation derived from (with many thanks):
46524 + *   arch/m68knommu
46525 + *   arch/blackfin
46526 + *   arch/parisc
46527 + */
46528 +#ifndef _UBI32_ETH_H
46529 +#define _UBI32_ETH_H
46530 +
46531 +#include <asm/devtree.h>
46532 +
46533 +#define UBI32_ETH_NUM_OF_DEVICES 2
46534 +
46535 +/*
46536 + * Number of bytes trashed beyond the packet data.
46537 + */
46538 +#define UBI32_ETH_TRASHED_MEMORY       (CACHE_LINE_SIZE + ETH_HLEN - 1)
46539 +
46540 +/*
46541 + * Linux already reserves NET_SKB_PAD bytes of headroom in each sk_buff.
46542 + * We want to be able to reserve at least one cache line to align Ethernet
46543 + * and IP header to cache line.
46544 + * Note that the TIO expects a CACHE_LINE_SIZE - ETH_HLEN aligned Ethernet
46545 + * header, while satisfies NET_IP_ALIGN (= 2) automatically.
46546 + * (NET_SKB_PAD is 16, NET_IP_ALIGN is 2, CACHE_LINE_SIZE is 32).
46547 + * You can add more space by making UBI32_ETH_RESERVE_EXTRA != 0.
46548 + */
46549 +#define UBI32_ETH_RESERVE_EXTRA (1 * CACHE_LINE_SIZE)
46550 +#define UBI32_ETH_RESERVE_SPACE        (UBI32_ETH_RESERVE_EXTRA + CACHE_LINE_SIZE)
46551 +
46552 +struct ubi32_eth_dma_desc {
46553 +       volatile void   *data_pointer;  /* pointer to the buffer */
46554 +       volatile u16    buffer_len;     /* the buffer size */
46555 +       volatile u16    data_len;       /* actual frame length */
46556 +       volatile u32    status;         /* bit0: status to be update by VP; bit[31:1] time stamp */
46557 +};
46558 +
46559 +#define TX_DMA_RING_SIZE (1<<8)
46560 +#define TX_DMA_RING_MASK (TX_DMA_RING_SIZE - 1)
46561 +#define RX_DMA_RING_SIZE (1<<8)
46562 +#define RX_DMA_RING_MASK (RX_DMA_RING_SIZE - 1)
46563 +
46564 +#define RX_DMA_MAX_QUEUE_SIZE (RX_DMA_RING_SIZE - 1)   /* no more than (RX_DMA_RING_SIZE - 1) */
46565 +#define RX_MAX_PKT_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN)
46566 +#define RX_MIN_PKT_SIZE        ETH_ZLEN
46567 +#define RX_BUF_SIZE (RX_MAX_PKT_SIZE + VLAN_HLEN)      /* allow double VLAN tag */
46568 +
46569 +#define UBI32_ETH_VP_TX_TIMEOUT (10*HZ)
46570 +
46571 +struct ubi32_eth_vp_stats {
46572 +       u32     rx_alloc_err;
46573 +       u32     tx_q_full_cnt;
46574 +       u32     rx_q_full_cnt;
46575 +       u32     rx_throttle;
46576 +};
46577 +
46578 +struct ubi32_eth_private {
46579 +       struct net_device *dev;
46580 +       struct ubi32_eth_vp_stats vp_stats;
46581 +       spinlock_t lock;
46582 +#ifdef UBICOM32_USE_NAPI
46583 +       struct napi_struct napi;
46584 +#else
46585 +       struct tasklet_struct tsk;
46586 +#endif
46587 +       struct ethtionode *regs;
46588 +       u16     rx_tail;
46589 +       u16     tx_tail;
46590 +       u32     vp_int_bit;
46591 +};
46592 +
46593 +struct ethtionode {
46594 +       struct devtree_node dn;
46595 +       volatile u16    command;
46596 +       volatile u16    status;
46597 +       volatile u16    int_mask;       /* interrupt mask */
46598 +       volatile u16    int_status;     /* interrupt mask */
46599 +       volatile u16    tx_in;          /* owned by driver */
46600 +       volatile u16    tx_out;         /* owned by vp */
46601 +       volatile u16    rx_in;          /* owned by driver */
46602 +       volatile u16    rx_out;         /* owned by vp */
46603 +       u16             tx_sz;          /* owned by driver */
46604 +       u16             rx_sz;          /* owned by driver */
46605 +       struct ubi32_eth_dma_desc **tx_dma_ring;
46606 +       struct ubi32_eth_dma_desc **rx_dma_ring;
46607 +};
46608 +
46609 +#define UBI32_ETH_VP_STATUS_LINK       (1<<0)
46610 +#define UBI32_ETH_VP_STATUS_SPEED100   (0x1<<1)
46611 +#define UBI32_ETH_VP_STATUS_SPEED1000  (0x1<<2)
46612 +#define UBI32_ETH_VP_STATUS_DUPLEX     (0x1<<3)
46613 +#define UBI32_ETH_VP_STATUS_FLOW_CTRL  (0x1<<4)
46614 +
46615 +#define UBI32_ETH_VP_STATUS_RX_STATE   (0x1<<5)
46616 +#define UBI32_ETH_VP_STATUS_TX_STATE   (0x1<<6)
46617 +
46618 +#define UBI32_ETH_VP_STATUS_TX_Q_FULL  (1<<8)
46619 +
46620 +#define UBI32_ETH_VP_INT_RX    (1<<0)
46621 +#define UBI32_ETH_VP_INT_TX    (1<<1)
46622 +
46623 +#define UBI32_ETH_VP_CMD_RX_ENABLE     (1<<0)
46624 +#define UBI32_ETH_VP_CMD_TX_ENABLE     (1<<1)
46625 +
46626 +#define UBI32_ETH_VP_RX_OK             (1<<0)
46627 +#define UBI32_ETH_VP_TX_OK             (1<<1)
46628 +
46629 +#define UBI32_TX_BOUND         TX_DMA_RING_SIZE
46630 +#define UBI32_RX_BOUND         64
46631 +#define UBI32_ETH_NAPI_WEIGHT  64              /* for GigE */
46632 +#endif
46633 --- a/drivers/net/usb/asix.c
46634 +++ b/drivers/net/usb/asix.c
46635 @@ -319,14 +319,33 @@ static int asix_rx_fixup(struct usbnet *
46636                 /* get the packet length */
46637                 size = (u16) (header & 0x0000ffff);
46638  
46639 -               if ((skb->len) - ((size + 1) & 0xfffe) == 0)
46640 +               if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
46641 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46642 +                       if (((u32)packet & 0x02) == 0) {
46643 +                               memmove(packet - 2, packet, size);
46644 +                               skb->data -= 2;
46645 +                               skb->tail -= 2;
46646 +                       }
46647 +#endif
46648                         return 2;
46649 +               }
46650 +
46651                 if (size > ETH_FRAME_LEN) {
46652                         deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
46653                         return 0;
46654                 }
46655                 ax_skb = skb_clone(skb, GFP_ATOMIC);
46656                 if (ax_skb) {
46657 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46658 +                       if (((u32)packet & 0x02) == 0) {
46659 +                               memmove(packet - 2, packet, size);
46660 +                               ax_skb->data = packet - 2;
46661 +                       } else {
46662 +                               ax_skb->data = packet;
46663 +                       }
46664 +#else
46665 +                       ax_skb->data = packet;
46666 +#endif
46667                         ax_skb->len = size;
46668                         ax_skb->data = packet;
46669                         skb_set_tail_pointer(ax_skb, size);
46670 @@ -1125,13 +1144,19 @@ static int ax88178_link_reset(struct usb
46671         mode = AX88178_MEDIUM_DEFAULT;
46672  
46673         if (ecmd.speed == SPEED_1000)
46674 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46675                 mode |= AX_MEDIUM_GM;
46676 +#else
46677 +               mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
46678 +#endif
46679         else if (ecmd.speed == SPEED_100)
46680                 mode |= AX_MEDIUM_PS;
46681         else
46682                 mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
46683  
46684 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46685         mode |= AX_MEDIUM_ENCK;
46686 +#endif
46687  
46688         if (ecmd.duplex == DUPLEX_FULL)
46689                 mode |= AX_MEDIUM_FD;
46690 --- a/drivers/oprofile/cpu_buffer.c
46691 +++ b/drivers/oprofile/cpu_buffer.c
46692 @@ -328,10 +328,10 @@ static inline void oprofile_end_trace(st
46693  }
46694  
46695  static inline void
46696 -__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46697 -                         unsigned long event, int is_kernel)
46698 +__oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
46699 +                             unsigned long event, int is_kernel, int cpu)
46700  {
46701 -       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
46702 +       struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
46703         unsigned long backtrace = oprofile_backtrace_depth;
46704  
46705         /*
46706 @@ -353,7 +353,8 @@ __oprofile_add_ext_sample(unsigned long 
46707  void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46708                              unsigned long event, int is_kernel)
46709  {
46710 -       __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46711 +       __oprofile_add_ext_sample_cpu(pc, regs, event,
46712 +                                     is_kernel, smp_processor_id());
46713  }
46714  
46715  void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
46716 @@ -361,7 +362,8 @@ void oprofile_add_sample(struct pt_regs 
46717         int is_kernel = !user_mode(regs);
46718         unsigned long pc = profile_pc(regs);
46719  
46720 -       __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46721 +       __oprofile_add_ext_sample_cpu(pc, regs, event,
46722 +                                     is_kernel, smp_processor_id());
46723  }
46724  
46725  /*
46726 --- a/drivers/pci/Makefile
46727 +++ b/drivers/pci/Makefile
46728 @@ -44,8 +44,8 @@ obj-$(CONFIG_PPC) += setup-bus.o
46729  obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
46730  obj-$(CONFIG_X86_VISWS) += setup-irq.o
46731  obj-$(CONFIG_MN10300) += setup-bus.o
46732 +obj-$(CONFIG_UBICOM32) += setup-bus.o setup-irq.o
46733  
46734 -#
46735  # ACPI Related PCI FW Functions
46736  #
46737  obj-$(CONFIG_ACPI)    += pci-acpi.o
46738 --- a/drivers/serial/Kconfig
46739 +++ b/drivers/serial/Kconfig
46740 @@ -871,6 +871,57 @@ config SERIAL_UARTLITE_CONSOLE
46741           console (the system console is the device which receives all kernel
46742           messages and warnings and which allows logins in single user mode).
46743  
46744 +config SERIAL_UBI32_UARTTIO
46745 +        tristate "Ubicom UARTTIO support"
46746 +        depends on UBICOM32=y
46747 +        select SERIAL_CORE
46748 +       default y
46749 +        help
46750 +          Add support for the Ubicom virtual peripherial serial interface.
46751 +
46752 +config SERIAL_UBI32_UARTTIO_NR_UARTS
46753 +       int "Maximum number of UARTTIO virtual serial ports"
46754 +       depends on SERIAL_UBI32_UARTTIO
46755 +       default "4"
46756 +       help
46757 +         Set this to the maximum number of serial ports you want the driver to support.
46758 +
46759 +config SERIAL_UBI32_UARTTIO_CONSOLE
46760 +        tristate "Ubicom UARTTIO console support"
46761 +        depends on SERIAL_UBI32_UARTTIO=y
46762 +        select SERIAL_CORE_CONSOLE
46763 +       default y
46764 +        help
46765 +          Add support for console on the Ubicom virtual peripherial serial interface.
46766 +
46767 +config SERIAL_UBI32_SERDES
46768 +        bool "Ubicom serial port support"
46769 +        depends on UBICOM32=y
46770 +        select SERIAL_CORE
46771 +       default y
46772 +        help
46773 +          Add support for the Ubicom serial interface.
46774 +
46775 +config SERIAL_UBI32_SERDES_CONSOLE
46776 +        bool "Ubicom serial console support"
46777 +        depends on SERIAL_UBI32_SERDES=y
46778 +        select SERIAL_CORE_CONSOLE
46779 +       default y
46780 +
46781 +config SERIAL_UBI32_MAILBOX
46782 +        bool "Ubicom mailbox support"
46783 +        depends on UBICOM32=y
46784 +        select SERIAL_CORE
46785 +       default n
46786 +        help
46787 +          Add support for the Ubicom mailbox interface.
46788 +
46789 +config SERIAL_UBI32_MAILBOX_CONSOLE
46790 +        bool "Ubicom mailbox console support"
46791 +        depends on SERIAL_UBI32_MAILBOX=y
46792 +        select SERIAL_CORE_CONSOLE
46793 +       default y
46794 +
46795  config SERIAL_SUNCORE
46796         bool
46797         depends on SPARC
46798 --- a/drivers/serial/Makefile
46799 +++ b/drivers/serial/Makefile
46800 @@ -77,3 +77,6 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIA
46801  obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
46802  obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
46803  obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
46804 +obj-$(CONFIG_SERIAL_UBI32_SERDES) += ubi32_serdes.o
46805 +obj-$(CONFIG_SERIAL_UBI32_UARTTIO) += ubi32_uarttio.o
46806 +obj-$(CONFIG_SERIAL_UBI32_MAILBOX) += ubi32_mailbox.o
46807 --- /dev/null
46808 +++ b/drivers/serial/ubi32_mailbox.c
46809 @@ -0,0 +1,928 @@
46810 +/*
46811 + * drivers/serial/ubi32_mailbox.c
46812 + *   Ubicom32 On-Chip Mailbox Driver
46813 + *
46814 + * (C) Copyright 2009, Ubicom, Inc.
46815 + *
46816 + * This file is part of the Ubicom32 Linux Kernel Port.
46817 + *
46818 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46819 + * it and/or modify it under the terms of the GNU General Public License
46820 + * as published by the Free Software Foundation, either version 2 of the
46821 + * License, or (at your option) any later version.
46822 + *
46823 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46824 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46825 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
46826 + * the GNU General Public License for more details.
46827 + *
46828 + * You should have received a copy of the GNU General Public License
46829 + * along with the Ubicom32 Linux Kernel Port.  If not,
46830 + * see <http://www.gnu.org/licenses/>.
46831 + *
46832 + * Ubicom32 implementation derived from (with many thanks):
46833 + *   arch/m68knommu
46834 + *   arch/blackfin
46835 + *   arch/parisc
46836 + */
46837 +#include <linux/module.h>
46838 +#include <linux/ioport.h>
46839 +#include <linux/init.h>
46840 +#include <linux/console.h>
46841 +#include <linux/sysrq.h>
46842 +#include <linux/platform_device.h>
46843 +#include <linux/tty.h>
46844 +#include <linux/tty_flip.h>
46845 +#include <linux/serial_core.h>
46846 +
46847 +#include <asm/ip5000.h>
46848 +
46849 +#define SERIAL_UBICOM_BAUDRATE 115200
46850 +#define SERIAL_UBICOM_DATA_BIT 8       /* Fixed parameter - do not change */
46851 +#define SERIAL_UBICOM_PAR_BIT  0       /* Fixed parameter - do not change */
46852 +#define SERIAL_UBICOM_STOP_BIT 1       /* Fixed parameter - do not change */
46853 +
46854 +/* UART name and device definitions */
46855 +#define UBI32_MAILBOX_NAME     "ttyUM" // XXX
46856 +#define UBI32_MAILBOX_MAJOR    207 // XXX
46857 +#define UBI32_MAILBOX_MINOR    64
46858 +
46859 +#define PORT_UBI32_MAILBOX     1235
46860 +#define NR_PORTS 1
46861 +
46862 +#define get_sclk() 0
46863 +
46864 +struct ubi32_mailbox_port {
46865 +       struct uart_port port;
46866 +       /*
46867 +        * NOTE (rkeller):
46868 +        * the uart port is wrapped in another structure in case we need to hold more state than
46869 +        * what we can hold in the uart_port.
46870 +        * Not sure if we need this, I took over the concept from the blackfin driver.
46871 +        */
46872 +} ubi32_mailbox_ports[NR_PORTS];
46873 +
46874 +struct ubi32_mailbox_resource {
46875 +       int uart_base_addr;
46876 +       int uart_irq;
46877 +} ubi32_mailbox_resource[NR_PORTS] = {
46878 +       /*
46879 +        * uart_base_addr has to be non-NULL because it is put in the uart_port membase.
46880 +        * If membase if null the kernel skips the configuration and our port_type never gets set.
46881 +        */
46882 +       {ISD_MAILBOX_BASE, ISD_MAILBOX_INT}
46883 +};
46884 +
46885 +static volatile struct ubicom32_isd_mailbox {
46886 +       volatile u32_t in;
46887 +       volatile u32_t out;
46888 +       volatile u32_t status;
46889 +} *ubi32_mailbox = (struct ubicom32_isd_mailbox *)ISD_MAILBOX_BASE;
46890 +
46891 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart);
46892 +
46893 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart);
46894 +
46895 +#define TRUE 1
46896 +#define FALSE 0
46897 +
46898 +static int mailbox_console_flg = TRUE;
46899 +static int num_timeouts = 0;
46900 +
46901 +/*
46902 + * dummy functions and defined to be able to compile the Blackfin code
46903 + */
46904 +#define UART_GET_LSR(port) (1)
46905 +#define UART_PUT_LSR(port, bits)
46906 +#define UART_CLEAR_LSR(port) (1)
46907 +#define TEMT 1
46908 +#define TFI 1
46909 +#define BI 1
46910 +#define PE 1
46911 +#define OE 1
46912 +#define FE 1
46913 +#define THRE 1
46914 +#define DR 1
46915 +#define UART_GET_LCR(port) (1)
46916 +#define UART_PUT_LCR(port, bits)
46917 +#define SB 1
46918 +#define STB 1
46919 +#define PEN 1
46920 +#define EPS 1
46921 +#define STP 1
46922 +#define WLS(n) 0
46923 +#define UART_GET_IER(port) (1)
46924 +#define UART_SET_IER(port, bits)
46925 +#define UART_CLEAR_IER(port, bits)
46926 +#define ETBEI 0
46927 +#define ERBFI 0
46928 +#define UART_GET_CHAR(port) ubi32_mailbox_get_char()
46929 +#define UART_PUT_CHAR(port, ch) ubi32_mailbox_put_char(ch)
46930 +#define SSYNC()
46931 +#define UART_GET_DLL(port) 0
46932 +#define UART_PUT_DLL(port, ch)
46933 +#define UART_GET_DLH(port) 0
46934 +#define UART_PUT_DLH(port, ch)
46935 +#define UART_GET_GCTL(port) (0)
46936 +#define UART_PUT_GCTL(port, ch)
46937 +#define UCEN 1
46938 +
46939 +/*
46940 + * ubi32_mailbox_get_char_avail()
46941 + */
46942 +static int ubi32_mailbox_get_char_avail(void)
46943 +{
46944 +       return !(ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
46945 +}
46946 +
46947 +/*
46948 + * ubi32_mailbox_get_char()
46949 + */
46950 +static u32_t ubi32_mailbox_get_char(void)
46951 +{
46952 +       if (mailbox_console_flg == TRUE) {
46953 +               /*
46954 +                * Mailbox console is connected.
46955 +                */
46956 +               while (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
46957 +               return ubi32_mailbox->in & 0xff;
46958 +       }
46959 +
46960 +       /*
46961 +        * Mailbox console was not connected.
46962 +        */
46963 +       if (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY) {
46964 +               return 0xff;
46965 +       }
46966 +
46967 +       /*
46968 +        * Mailbox console is connecting.
46969 +        */
46970 +       mailbox_console_flg = TRUE;
46971 +       num_timeouts = 0;
46972 +       return ubi32_mailbox->in & 0xff;
46973 +}
46974 +
46975 +#define MAILBOX_MAX_ATTEMPTS 1000000
46976 +#define MAILBOX_MAX_TIMEOUTS 5
46977 +/*
46978 + * ubi32_mailbox_put_char()
46979 + */
46980 +static void ubi32_mailbox_put_char(u32_t v)
46981 +{
46982 +       /*
46983 +        * Wait to be able to output.
46984 +        */
46985 +       u32_t num_attempts = 0;
46986 +
46987 +       if(mailbox_console_flg == TRUE) {
46988 +               while(num_attempts++ < MAILBOX_MAX_ATTEMPTS) {
46989 +                       if(ubi32_mailbox->status & ISD_MAILBOX_STATUS_OUT_EMPTY) {
46990 +                               break;
46991 +                       }
46992 +               }
46993 +
46994 +               /*
46995 +                * If timed out more than 5 times on send, mailbox console is disconnected now.
46996 +                */
46997 +               if (num_attempts > MAILBOX_MAX_ATTEMPTS) {
46998 +                       if (num_timeouts++ > MAILBOX_MAX_TIMEOUTS) {
46999 +                               mailbox_console_flg = FALSE;
47000 +                       }
47001 +               }
47002 +       }
47003 +
47004 +       asm volatile(
47005 +               "pipe_flush 0   \n\t"
47006 +               "pipe_flush 0   \n\t"
47007 +               "pipe_flush 0   \n\t"
47008 +               "pipe_flush 0   \n\t"
47009 +               "pipe_flush 0   \n\t"
47010 +               "pipe_flush 0   \n\t"
47011 +               "pipe_flush 0   \n\t"
47012 +       );
47013 +
47014 +       ubi32_mailbox->out = v & 0xff;
47015 +}
47016 +
47017 +static void ubi32_mailbox_hw_init(struct ubi32_mailbox_port *uart)
47018 +{
47019 +// NOTE: It does not do any good to do these here because we are running on the linux hardware thread,
47020 +//     and these have to be called on the ldsr thread.
47021 +//     ubicom32_clear_interrupt(ISD_MAILBOX_INT);
47022 +//     ubicom32_enable_interrupt(ISD_MAILBOX_INT);
47023 +}
47024 +
47025 +/*
47026 + * interrupts are disabled on entry
47027 + */
47028 +static void ubi32_mailbox_stop_tx(struct uart_port *port)
47029 +{
47030 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47031 +//     struct circ_buf *xmit = &uart->port.info->xmit;
47032 +
47033 +       while (!(UART_GET_LSR(uart) & TEMT))
47034 +               cpu_relax();
47035 +
47036 +       /* Clear TFI bit */
47037 +       UART_PUT_LSR(uart, TFI);
47038 +       UART_CLEAR_IER(uart, ETBEI);
47039 +}
47040 +
47041 +/*
47042 + * port is locked and interrupts are disabled
47043 + */
47044 +static void ubi32_mailbox_start_tx(struct uart_port *port)
47045 +{
47046 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47047 +
47048 +       UART_SET_IER(uart, ETBEI);
47049 +
47050 +       ubi32_mailbox_tx_chars(uart);
47051 +}
47052 +
47053 +/*
47054 + * Interrupts are enabled
47055 + */
47056 +static void ubi32_mailbox_stop_rx(struct uart_port *port)
47057 +{
47058 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47059 +       UART_CLEAR_IER(uart, ERBFI);
47060 +}
47061 +
47062 +/*
47063 + * Set the modem control timer to fire immediately.
47064 + */
47065 +static void ubi32_mailbox_enable_ms(struct uart_port *port)
47066 +{
47067 +}
47068 +
47069 +static void ubi32_mailbox_rx_chars(struct ubi32_mailbox_port *uart)
47070 +{
47071 +       struct uart_info *info = uart->port.info;
47072 +       struct tty_struct *tty = info->port.tty;
47073 +       unsigned int status, ch, flg;
47074 +
47075 +       status = 0; // XXX? UART_GET_LSR(uart);
47076 +       UART_CLEAR_LSR(uart);
47077 +
47078 +       ch = UART_GET_CHAR(uart);
47079 +
47080 +       if(ch == 0xff)
47081 +               return;
47082 +
47083 +       uart->port.icount.rx++;
47084 +
47085 +       if (status & BI) {
47086 +               uart->port.icount.brk++;
47087 +               if (uart_handle_break(&uart->port))
47088 +                       goto ignore_char;
47089 +               status &= ~(PE | FE);
47090 +       }
47091 +       if (status & PE)
47092 +               uart->port.icount.parity++;
47093 +       if (status & OE)
47094 +               uart->port.icount.overrun++;
47095 +       if (status & FE)
47096 +               uart->port.icount.frame++;
47097 +
47098 +       status &= uart->port.read_status_mask;
47099 +
47100 +       if (status & BI)
47101 +               flg = TTY_BREAK;
47102 +       else if (status & PE)
47103 +               flg = TTY_PARITY;
47104 +       else if (status & FE)
47105 +               flg = TTY_FRAME;
47106 +       else
47107 +               flg = TTY_NORMAL;
47108 +
47109 +       if (uart_handle_sysrq_char(&uart->port, ch))
47110 +               goto ignore_char;
47111 +
47112 +       uart_insert_char(&uart->port, status, OE, ch, flg);
47113 +
47114 + ignore_char:
47115 +       tty_flip_buffer_push(tty);
47116 +}
47117 +
47118 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart)
47119 +{
47120 +       struct circ_buf *xmit = &uart->port.info->xmit;
47121 +
47122 +       if (uart->port.x_char) {
47123 +               UART_PUT_CHAR(uart, uart->port.x_char);
47124 +               uart->port.icount.tx++;
47125 +               uart->port.x_char = 0;
47126 +       }
47127 +       /*
47128 +        * Check the modem control lines before
47129 +        * transmitting anything.
47130 +        */
47131 +       ubi32_mailbox_mctrl_check(uart);
47132 +
47133 +       if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
47134 +               ubi32_mailbox_stop_tx(&uart->port);
47135 +               return;
47136 +       }
47137 +
47138 +       while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
47139 +               UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
47140 +               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
47141 +               uart->port.icount.tx++;
47142 +               SSYNC();
47143 +       }
47144 +
47145 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
47146 +               uart_write_wakeup(&uart->port);
47147 +
47148 +       if (uart_circ_empty(xmit))
47149 +               ubi32_mailbox_stop_tx(&uart->port);
47150 +}
47151 +
47152 +static irqreturn_t ubi32_mailbox_isr(int irq, void *dev_id)
47153 +{
47154 +       struct ubi32_mailbox_port *uart = dev_id;
47155 +
47156 +       spin_lock(&uart->port.lock);
47157 +
47158 +       //XXX?while (UART_GET_LSR(uart) & DR)
47159 +
47160 +       /*
47161 +        * RX process
47162 +        */
47163 +       while (ubi32_mailbox_get_char_avail()) {
47164 +               ubi32_mailbox_rx_chars(uart);
47165 +       }
47166 +
47167 +#if 0
47168 +       /*
47169 +        * TX process
47170 +        */
47171 +       if (this_uart.tx_in == this_uart.tx_out) {
47172 +               UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask &= ~IO_PORTX_INT_SERDES_TXBE;
47173 +       } else if (UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_status & IO_PORTX_INT_SERDES_TXBE) {
47174 +               uart_ubicom32_send(this_uart.tx_buf[this_uart.tx_out & (SERIAL_UBICOM_BUF_SIZE - 1)]);
47175 +               this_uart.tx_out++;
47176 +               UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask |= IO_PORTX_INT_SERDES_TXBE;
47177 +       }
47178 +#endif
47179 +
47180 +       spin_unlock(&uart->port.lock);
47181 +
47182 +       return IRQ_HANDLED;
47183 +}
47184 +#if 0
47185 +static irqreturn_t ubi32_mailbox_tx_int(int irq, void *dev_id)
47186 +{
47187 +       struct ubi32_mailbox_port *uart = dev_id;
47188 +
47189 +       spin_lock(&uart->port.lock);
47190 +       if (UART_GET_LSR(uart) & THRE)
47191 +               ubi32_mailbox_tx_chars(uart);
47192 +       spin_unlock(&uart->port.lock);
47193 +
47194 +       return IRQ_HANDLED;
47195 +}
47196 +#endif
47197 +
47198 +/*
47199 + * Return TIOCSER_TEMT when transmitter is not busy.
47200 + */
47201 +static unsigned int ubi32_mailbox_tx_empty(struct uart_port *port)
47202 +{
47203 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47204 +       unsigned short lsr;
47205 +
47206 +       lsr = UART_GET_LSR(uart);
47207 +       if (lsr & TEMT)
47208 +               return TIOCSER_TEMT;
47209 +       else
47210 +               return 0;
47211 +}
47212 +
47213 +static unsigned int ubi32_mailbox_get_mctrl(struct uart_port *port)
47214 +{
47215 +               return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
47216 +}
47217 +
47218 +static void ubi32_mailbox_set_mctrl(struct uart_port *port, unsigned int mctrl)
47219 +{
47220 +}
47221 +
47222 +/*
47223 + * Handle any change of modem status signal since we were last called.
47224 + */
47225 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart)
47226 +{
47227 +}
47228 +
47229 +/*
47230 + * Interrupts are always disabled.
47231 + */
47232 +static void ubi32_mailbox_break_ctl(struct uart_port *port, int break_state)
47233 +{
47234 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47235 +       u16 lcr = UART_GET_LCR(uart);
47236 +       if (break_state)
47237 +               lcr |= SB;
47238 +       else
47239 +               lcr &= ~SB;
47240 +       UART_PUT_LCR(uart, lcr);
47241 +       SSYNC();
47242 +}
47243 +
47244 +static int ubi32_mailbox_startup(struct uart_port *port)
47245 +{
47246 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47247 +
47248 +       if (request_irq(uart->port.irq, ubi32_mailbox_isr, IRQF_DISABLED,
47249 +            "UBI32_MAILBOX", uart)) {
47250 +               printk(KERN_NOTICE "Unable to attach Ubicom32 SERDES interrupt\n");
47251 +               return -EBUSY;
47252 +       }
47253 +
47254 +       UART_SET_IER(uart, ERBFI);
47255 +       return 0;
47256 +}
47257 +
47258 +static void ubi32_mailbox_shutdown(struct uart_port *port)
47259 +{
47260 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47261 +
47262 +       free_irq(uart->port.irq, uart);
47263 +}
47264 +
47265 +static void
47266 +ubi32_mailbox_set_termios(struct uart_port *port, struct ktermios *termios,
47267 +                  struct ktermios *old)
47268 +{
47269 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47270 +       unsigned long flags;
47271 +       unsigned int baud, quot;
47272 +       unsigned short val, ier, lsr, lcr = 0;
47273 +
47274 +       switch (termios->c_cflag & CSIZE) {
47275 +       case CS8:
47276 +               lcr = WLS(8);
47277 +               break;
47278 +       case CS7:
47279 +               lcr = WLS(7);
47280 +               break;
47281 +       case CS6:
47282 +               lcr = WLS(6);
47283 +               break;
47284 +       case CS5:
47285 +               lcr = WLS(5);
47286 +               break;
47287 +       default:
47288 +               printk(KERN_ERR "%s: word lengh not supported\n",
47289 +                       __FUNCTION__);
47290 +       }
47291 +
47292 +       if (termios->c_cflag & CSTOPB)
47293 +               lcr |= STB;
47294 +       if (termios->c_cflag & PARENB)
47295 +               lcr |= PEN;
47296 +       if (!(termios->c_cflag & PARODD))
47297 +               lcr |= EPS;
47298 +       if (termios->c_cflag & CMSPAR)
47299 +               lcr |= STP;
47300 +
47301 +       port->read_status_mask = OE;
47302 +       if (termios->c_iflag & INPCK)
47303 +               port->read_status_mask |= (FE | PE);
47304 +       if (termios->c_iflag & (BRKINT | PARMRK))
47305 +               port->read_status_mask |= BI;
47306 +
47307 +       /*
47308 +        * Characters to ignore
47309 +        */
47310 +       port->ignore_status_mask = 0;
47311 +       if (termios->c_iflag & IGNPAR)
47312 +               port->ignore_status_mask |= FE | PE;
47313 +       if (termios->c_iflag & IGNBRK) {
47314 +               port->ignore_status_mask |= BI;
47315 +               /*
47316 +                * If we're ignoring parity and break indicators,
47317 +                * ignore overruns too (for real raw support).
47318 +                */
47319 +               if (termios->c_iflag & IGNPAR)
47320 +                       port->ignore_status_mask |= OE;
47321 +       }
47322 +
47323 +       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
47324 +       quot = uart_get_divisor(port, baud);
47325 +       spin_lock_irqsave(&uart->port.lock, flags);
47326 +
47327 +       do {
47328 +               lsr = UART_GET_LSR(uart);
47329 +       } while (!(lsr & TEMT));
47330 +
47331 +       /* Disable UART */
47332 +       ier = UART_GET_IER(uart);
47333 +       UART_CLEAR_IER(uart, 0xF);
47334 +
47335 +       UART_PUT_DLL(uart, quot & 0xFF);
47336 +       SSYNC();
47337 +       UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
47338 +       SSYNC();
47339 +
47340 +       UART_PUT_LCR(uart, lcr);
47341 +
47342 +       /* Enable UART */
47343 +       UART_SET_IER(uart, ier);
47344 +
47345 +       val = UART_GET_GCTL(uart);
47346 +       val |= UCEN;
47347 +       UART_PUT_GCTL(uart, val);
47348 +
47349 +       spin_unlock_irqrestore(&uart->port.lock, flags);
47350 +}
47351 +
47352 +static const char *ubi32_mailbox_type(struct uart_port *port)
47353 +{
47354 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47355 +
47356 +       return uart->port.type == PORT_UBI32_MAILBOX ? "UBI32_MAILBOX" : NULL;
47357 +}
47358 +
47359 +/*
47360 + * Release the memory region(s) being used by 'port'.
47361 + */
47362 +static void ubi32_mailbox_release_port(struct uart_port *port)
47363 +{
47364 +}
47365 +
47366 +/*
47367 + * Request the memory region(s) being used by 'port'.
47368 + */
47369 +static int ubi32_mailbox_request_port(struct uart_port *port)
47370 +{
47371 +       return 0;
47372 +}
47373 +
47374 +/*
47375 + * Configure/autoconfigure the port.
47376 + */
47377 +static void ubi32_mailbox_config_port(struct uart_port *port, int flags)
47378 +{
47379 +       struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47380 +
47381 +       if (flags & UART_CONFIG_TYPE && ubi32_mailbox_request_port(&uart->port) == 0)
47382 +               uart->port.type = PORT_UBI32_MAILBOX;
47383 +}
47384 +
47385 +/*
47386 + * Verify the new serial_struct (for TIOCSSERIAL).
47387 + * The only change we allow are to the flags and type, and
47388 + * even then only between PORT_UBI32_MAILBOX and PORT_UNKNOWN
47389 + */
47390 +static int
47391 +ubi32_mailbox_verify_port(struct uart_port *port, struct serial_struct *ser)
47392 +{
47393 +       return 0;
47394 +}
47395 +
47396 +static struct uart_ops ubi32_mailbox_pops = {
47397 +       .tx_empty       = ubi32_mailbox_tx_empty,
47398 +       .set_mctrl      = ubi32_mailbox_set_mctrl,
47399 +       .get_mctrl      = ubi32_mailbox_get_mctrl,
47400 +       .stop_tx        = ubi32_mailbox_stop_tx,
47401 +       .start_tx       = ubi32_mailbox_start_tx,
47402 +       .stop_rx        = ubi32_mailbox_stop_rx,
47403 +       .enable_ms      = ubi32_mailbox_enable_ms,
47404 +       .break_ctl      = ubi32_mailbox_break_ctl,
47405 +       .startup        = ubi32_mailbox_startup,
47406 +       .shutdown       = ubi32_mailbox_shutdown,
47407 +       .set_termios    = ubi32_mailbox_set_termios,
47408 +       .type           = ubi32_mailbox_type,
47409 +       .release_port   = ubi32_mailbox_release_port,
47410 +       .request_port   = ubi32_mailbox_request_port,
47411 +       .config_port    = ubi32_mailbox_config_port,
47412 +       .verify_port    = ubi32_mailbox_verify_port,
47413 +};
47414 +
47415 +static void __init ubi32_mailbox_init_ports(void)
47416 +{
47417 +       static int first = 1;
47418 +       int i;
47419 +
47420 +       if (!first)
47421 +               return;
47422 +       first = 0;
47423 +
47424 +       for (i = 0; i < NR_PORTS; i++) {
47425 +               ubi32_mailbox_ports[i].port.uartclk   = get_sclk();
47426 +               ubi32_mailbox_ports[i].port.ops       = &ubi32_mailbox_pops;
47427 +               ubi32_mailbox_ports[i].port.line      = i;
47428 +               ubi32_mailbox_ports[i].port.iotype    = UPIO_MEM;
47429 +               ubi32_mailbox_ports[i].port.membase   =
47430 +                       (void __iomem *)ubi32_mailbox_resource[i].uart_base_addr;
47431 +               ubi32_mailbox_ports[i].port.mapbase   =
47432 +                       ubi32_mailbox_resource[i].uart_base_addr;
47433 +               ubi32_mailbox_ports[i].port.irq       =
47434 +                       ubi32_mailbox_resource[i].uart_irq;
47435 +               ubi32_mailbox_ports[i].port.flags     = UPF_BOOT_AUTOCONF;
47436 +               spin_lock_init(&ubi32_mailbox_ports[i].port.lock);
47437 +
47438 +               ubi32_mailbox_hw_init(&ubi32_mailbox_ports[i]);
47439 +       }
47440 +
47441 +}
47442 +
47443 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47444 +/*
47445 + * If the port was already initialised (eg, by a boot loader),
47446 + * try to determine the current setup.
47447 + */
47448 +static void __init
47449 +ubi32_mailbox_console_get_options(struct ubi32_mailbox_port *uart, int *baud,
47450 +                          int *parity, int *bits)
47451 +{
47452 +       unsigned short status;
47453 +
47454 +       status = UART_GET_IER(uart) & (ERBFI | ETBEI);
47455 +       if (status == (ERBFI | ETBEI)) {
47456 +               /* ok, the port was enabled */
47457 +               unsigned short lcr;
47458 +               unsigned short dlh, dll;
47459 +
47460 +               lcr = UART_GET_LCR(uart);
47461 +
47462 +               *parity = 'n';
47463 +               if (lcr & PEN) {
47464 +                       if (lcr & EPS)
47465 +                               *parity = 'e';
47466 +                       else
47467 +                               *parity = 'o';
47468 +               }
47469 +               switch (lcr & 0x03) {
47470 +                       case 0: *bits = 5; break;
47471 +                       case 1: *bits = 6; break;
47472 +                       case 2: *bits = 7; break;
47473 +                       case 3: *bits = 8; break;
47474 +               }
47475 +
47476 +               dll = UART_GET_DLL(uart);
47477 +               dlh = UART_GET_DLH(uart);
47478 +
47479 +               *baud = get_sclk() / (16*(dll | dlh << 8));
47480 +       }
47481 +       pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
47482 +}
47483 +#endif
47484 +
47485 +#if defined(CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
47486 +static struct uart_driver ubi32_mailbox_reg;
47487 +
47488 +static int __init
47489 +ubi32_mailbox_console_setup(struct console *co, char *options)
47490 +{
47491 +       struct ubi32_mailbox_port *uart;
47492 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47493 +       int baud = SERIAL_UBICOM_BAUDRATE;
47494 +       int bits = 8;
47495 +       int parity = 'n';
47496 +       int flow = 'n';
47497 +# endif
47498 +
47499 +       /*
47500 +        * Check whether an invalid uart number has been specified, and
47501 +        * if so, search for the first available port that does have
47502 +        * console support.
47503 +        */
47504 +       if (co->index == -1 || co->index >= NR_PORTS)
47505 +               co->index = 0;
47506 +       uart = &ubi32_mailbox_ports[co->index];
47507 +
47508 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47509 +       if (options)
47510 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
47511 +       else
47512 +               ubi32_mailbox_console_get_options(uart, &baud, &parity, &bits);
47513 +
47514 +       //JB return uart_set_options(&uart->port, co, baud, parity, bits, flow);
47515 +       return 0;
47516 +# else
47517 +       return 0;
47518 +# endif
47519 +}
47520 +#endif /* defined (CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) ||
47521 +                                defined (CONFIG_EARLY_PRINTK) */
47522 +
47523 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47524 +static void ubi32_mailbox_console_putchar(struct uart_port *port, int ch)
47525 +{
47526 +//     struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47527 +       while (!(UART_GET_LSR(uart) & THRE))
47528 +               barrier();
47529 +       UART_PUT_CHAR(uart, ch);
47530 +       SSYNC();
47531 +}
47532 +
47533 +/*
47534 + * Interrupts are disabled on entering
47535 + */
47536 +static void
47537 +ubi32_mailbox_console_write(struct console *co, const char *s, unsigned int count)
47538 +{
47539 +       struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[co->index];
47540 +       unsigned long flags = 0;
47541 +
47542 +       spin_lock_irqsave(&uart->port.lock, flags);
47543 +       uart_console_write(&uart->port, s, count, ubi32_mailbox_console_putchar);
47544 +       spin_unlock_irqrestore(&uart->port.lock, flags);
47545 +
47546 +}
47547 +
47548 +static struct console ubi32_mailbox_console = {
47549 +       .name           = UBI32_MAILBOX_NAME,
47550 +       .write          = ubi32_mailbox_console_write,
47551 +       .device         = uart_console_device,
47552 +       .setup          = ubi32_mailbox_console_setup,
47553 +       .flags          = CON_PRINTBUFFER,
47554 +       .index          = -1,
47555 +       .data           = &ubi32_mailbox_reg,
47556 +};
47557 +
47558 +static int __init ubi32_mailbox_console_init(void)
47559 +{
47560 +       ubi32_mailbox_init_ports();
47561 +       register_console(&ubi32_mailbox_console);
47562 +       return 0;
47563 +}
47564 +console_initcall(ubi32_mailbox_console_init);
47565 +
47566 +#define UBI32_MAILBOX_CONSOLE  &ubi32_mailbox_console
47567 +#else
47568 +#define UBI32_MAILBOX_CONSOLE  NULL
47569 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47570 +
47571 +
47572 +#ifdef CONFIG_EARLY_PRINTK
47573 +static __init void ubi32_mailbox_early_putc(struct uart_port *port, int ch)
47574 +{
47575 +       UART_PUT_CHAR(uart, ch);
47576 +}
47577 +
47578 +static __init void ubi32_mailbox_early_write(struct console *con, const char *s,
47579 +                                       unsigned int n)
47580 +{
47581 +       struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[con->index];
47582 +       unsigned int i;
47583 +
47584 +       for (i = 0; i < n; i++, s++) {
47585 +               if (*s == '\n')
47586 +                       ubi32_mailbox_early_putc(&uart->port, '\r');
47587 +               ubi32_mailbox_early_putc(&uart->port, *s);
47588 +       }
47589 +}
47590 +
47591 +static struct __init console ubi32_mailbox_early_console = {
47592 +       .name = "early_UM",
47593 +       .write = ubi32_mailbox_early_write,
47594 +       .device = uart_console_device,
47595 +       .flags = CON_PRINTBUFFER,
47596 +       .setup = ubi32_mailbox_console_setup,
47597 +       .index = -1,
47598 +       .data  = &ubi32_mailbox_reg,
47599 +};
47600 +
47601 +/*
47602 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
47603 + */
47604 +struct console __init *ubi32_mailbox_early_init(unsigned int port,
47605 +                                               unsigned int cflag)
47606 +{
47607 +       struct ubi32_mailbox_port *uart;
47608 +       struct ktermios t;
47609 +
47610 +       if (port == -1 || port >= NR_PORTS)
47611 +               port = 0;
47612 +       ubi32_mailbox_init_ports();
47613 +       ubi32_mailbox_early_console.index = port;
47614 +       uart = &ubi32_mailbox_ports[port];
47615 +       t.c_cflag = cflag;
47616 +       t.c_iflag = 0;
47617 +       t.c_oflag = 0;
47618 +       t.c_lflag = ICANON;
47619 +       t.c_line = port;
47620 +       ubi32_mailbox_set_termios(&uart->port, &t, &t);
47621 +       return &ubi32_mailbox_early_console;
47622 +}
47623 +
47624 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47625 +
47626 +static struct uart_driver ubi32_mailbox_reg = {
47627 +       .owner                  = THIS_MODULE,
47628 +       .driver_name            = "ubi32_mailbox",
47629 +       .dev_name               = UBI32_MAILBOX_NAME,
47630 +       .major                  = UBI32_MAILBOX_MAJOR,
47631 +       .minor                  = UBI32_MAILBOX_MINOR,
47632 +       .nr                     = NR_PORTS,
47633 +       .cons                   = UBI32_MAILBOX_CONSOLE,
47634 +};
47635 +
47636 +static int ubi32_mailbox_suspend(struct platform_device *dev, pm_message_t state)
47637 +{
47638 +       struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47639 +
47640 +       if (uart)
47641 +               uart_suspend_port(&ubi32_mailbox_reg, &uart->port);
47642 +
47643 +       return 0;
47644 +}
47645 +
47646 +static int ubi32_mailbox_resume(struct platform_device *dev)
47647 +{
47648 +       struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47649 +
47650 +       if (uart)
47651 +               uart_resume_port(&ubi32_mailbox_reg, &uart->port);
47652 +
47653 +       return 0;
47654 +}
47655 +
47656 +static int ubi32_mailbox_probe(struct platform_device *dev)
47657 +{
47658 +       struct resource *res = dev->resource;
47659 +       int i;
47660 +
47661 +       for (i = 0; i < dev->num_resources; i++, res++)
47662 +               if (res->flags & IORESOURCE_MEM)
47663 +                       break;
47664 +
47665 +       if (i < dev->num_resources) {
47666 +               for (i = 0; i < NR_PORTS; i++, res++) {
47667 +                       if (ubi32_mailbox_ports[i].port.mapbase != res->start)
47668 +                               continue;
47669 +                       ubi32_mailbox_ports[i].port.dev = &dev->dev;
47670 +                       uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[i].port);
47671 +                       platform_set_drvdata(dev, &ubi32_mailbox_ports[i]);
47672 +               }
47673 +       }
47674 +
47675 +       return 0;
47676 +}
47677 +
47678 +static int ubi32_mailbox_remove(struct platform_device *pdev)
47679 +{
47680 +       struct ubi32_mailbox_port *uart = platform_get_drvdata(pdev);
47681 +
47682 +       platform_set_drvdata(pdev, NULL);
47683 +
47684 +       if (uart)
47685 +               uart_remove_one_port(&ubi32_mailbox_reg, &uart->port);
47686 +
47687 +       return 0;
47688 +}
47689 +
47690 +static struct platform_driver ubi32_mailbox_driver = {
47691 +       .probe          = ubi32_mailbox_probe,
47692 +       .remove         = ubi32_mailbox_remove,
47693 +       .suspend        = ubi32_mailbox_suspend,
47694 +       .resume         = ubi32_mailbox_resume,
47695 +       .driver         = {
47696 +               .name   = "ubi32-mbox",
47697 +               .owner  = THIS_MODULE,
47698 +       },
47699 +};
47700 +
47701 +static int __init ubi32_mailbox_init(void)
47702 +{
47703 +       int ret;
47704 +
47705 +       pr_info("Serial: Ubicom32 mailbox serial driver.\n");
47706 +
47707 +       mailbox_console_flg = TRUE;
47708 +       num_timeouts = 0;
47709 +       ubi32_mailbox_init_ports();
47710 +
47711 +       ret = uart_register_driver(&ubi32_mailbox_reg);
47712 +       if (ret == 0) {
47713 +               ret = platform_driver_register(&ubi32_mailbox_driver);
47714 +               if (ret) {
47715 +                       pr_debug("uart register failed\n");
47716 +                       uart_unregister_driver(&ubi32_mailbox_reg);
47717 +               }
47718 +       }
47719 +
47720 +       /*
47721 +        * XXX HACK: currently probe does not get called, but the port needs to be added to work.
47722 +        */
47723 +       uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[0].port);
47724 +       return ret;
47725 +}
47726 +
47727 +static void __exit ubi32_mailbox_exit(void)
47728 +{
47729 +       platform_driver_unregister(&ubi32_mailbox_driver);
47730 +       uart_unregister_driver(&ubi32_mailbox_reg);
47731 +}
47732 +
47733 +module_init(ubi32_mailbox_init);
47734 +module_exit(ubi32_mailbox_exit);
47735 +
47736 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_MAILBOX_MAJOR);
47737 +MODULE_ALIAS("platform:ubi32_mailbox");
47738 --- /dev/null
47739 +++ b/drivers/serial/ubi32_serdes.c
47740 @@ -0,0 +1,817 @@
47741 +/*
47742 + * drivers/serial/ubi32_serdes.c
47743 + *   Ubicom32 On-Chip Serial Driver
47744 + *
47745 + * (C) Copyright 2009, Ubicom, Inc.
47746 + *
47747 + * This file is part of the Ubicom32 Linux Kernel Port.
47748 + *
47749 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
47750 + * it and/or modify it under the terms of the GNU General Public License
47751 + * as published by the Free Software Foundation, either version 2 of the
47752 + * License, or (at your option) any later version.
47753 + *
47754 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
47755 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
47756 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
47757 + * the GNU General Public License for more details.
47758 + *
47759 + * You should have received a copy of the GNU General Public License
47760 + * along with the Ubicom32 Linux Kernel Port.  If not,
47761 + * see <http://www.gnu.org/licenses/>.
47762 + *
47763 + * Ubicom32 implementation derived from (with many thanks):
47764 + *   arch/m68knommu
47765 + *   arch/blackfin
47766 + *   arch/parisc
47767 + */
47768 +#include <linux/module.h>
47769 +#include <linux/ioport.h>
47770 +#include <linux/init.h>
47771 +#include <linux/console.h>
47772 +#include <linux/sysrq.h>
47773 +#include <linux/platform_device.h>
47774 +#include <linux/tty.h>
47775 +#include <linux/tty_flip.h>
47776 +#include <linux/serial_core.h>
47777 +
47778 +#include <asm/ip5000.h>
47779 +#include <asm/ubicom32suart.h>
47780 +
47781 +
47782 +#define SERIAL_UBICOM_PIN_RXD  (1 << 0)
47783 +#define SERIAL_UBICOM_PIN_TXD  (1 << 6)
47784 +#define SERIAL_UBICOM_CTL0     0x8b300000
47785 +#define SERIAL_UBICOM_CTL1     0x00000009
47786 +
47787 +#define SERIAL_UBICOM_DATA_BIT 8       /* Fixed parameter - do not change */
47788 +#define SERIAL_UBICOM_PAR_BIT  0       /* Fixed parameter - do not change */
47789 +#define SERIAL_UBICOM_STOP_BIT 1       /* Fixed parameter - do not change */
47790 +
47791 +/* UART name and device definitions */
47792 +#define UBI32_SERDES_NAME      "ttyUS" // XXX
47793 +#define UBI32_SERDES_MAJOR     206 // XXX
47794 +#define UBI32_SERDES_MINOR     64 // XXX
47795 +
47796 +#define PORT_UBI32_SERDES      1234
47797 +#define NR_PORTS 1
47798 +
47799 +struct uart_port ubi32_serdes_ports[NR_PORTS];
47800 +
47801 +struct ubi32_serdes_resource {
47802 +       void *uart_base_addr;
47803 +       int uart_irq;
47804 +       int uart_clock;
47805 +} ubi32_serdes_resource[NR_PORTS] = {
47806 +       /*
47807 +        * Get params from kernel command line (required for early printk)
47808 +        * or from platform resources.
47809 +        */
47810 +       {0, 0, 0}
47811 +};
47812 +
47813 +/*
47814 + * Can get overridden by 'serdes=' kernel command line.
47815 + */
47816 +static int ubi32_serdes_default_baud_rate = 115200;
47817 +
47818 +
47819 +#define IO_PORT(port) ((struct ubicom32_io_port *)port->membase)
47820 +#define IO_PORT_INT_STATUS(port) (IO_PORT(port)->int_status)
47821 +#define IO_PORT_INT_MASK(port) (IO_PORT(port)->int_mask)
47822 +#define IO_PORT_INT_CLR(port) (IO_PORT(port)->int_clr)
47823 +
47824 +
47825 +/*
47826 + * ubi32_serdes_get_char()
47827 + */
47828 +static u8_t ubi32_serdes_get_char(struct ubicom32_io_port *io_port)
47829 +{
47830 +       /*
47831 +        * Read from hardware (forced 32-bit atomic read).
47832 +        */
47833 +       u32_t data = 0;
47834 +
47835 +       if ( io_port ) {
47836 +               io_port->int_clr = IO_PORTX_INT_SERDES_RXBF;
47837 +               asm volatile (
47838 +                       "move.4         %0, %1          \n\t"
47839 +                       : "=r" (data)
47840 +                       : "m" (*(u32_t *)&(io_port->rx_fifo))
47841 +                       );
47842 +       }
47843 +
47844 +       return (u8_t)(data & 0x000000ff);
47845 +}
47846 +
47847 +/*
47848 + * ubi32_serdes_put_char()
47849 + */
47850 +static void ubi32_serdes_put_char(struct ubicom32_io_port *io_port, u8_t c)
47851 +{
47852 +       u32_t data = 0x0000fe00 | (c << 1);
47853 +
47854 +       if ( io_port ) {
47855 +               /*
47856 +                * Fixed data format:
47857 +                * [LSB]1 start bit - 8 data bits - no parity - 1 stop bit[MSB]
47858 +                */
47859 +               io_port->int_clr = IO_PORTX_INT_SERDES_TXBE;
47860 +               io_port->ctl2 = data;
47861 +               io_port->int_set = IO_PORTX_INT_SERDES_TXBUF_VALID;
47862 +       }
47863 +}
47864 +
47865 +static void ubi32_serdes_hw_init(struct uart_port *port, int baud)
47866 +{
47867 +       struct ubicom32_io_port *io_port = IO_PORT(port);
47868 +
47869 +       if ( io_port ) {
47870 +               /*
47871 +                * Put port functions 1-4 into reset state.
47872 +                * Function 0 (GPIO) does not need or have a reset bit.
47873 +                *
47874 +                * Select SERDES function for restart below.
47875 +                */
47876 +               io_port->function =
47877 +                       IO_FUNC_FUNCTION_RESET(1) | IO_FUNC_FUNCTION_RESET(2) |
47878 +                       IO_FUNC_FUNCTION_RESET(3) | IO_FUNC_FUNCTION_RESET(4) |
47879 +                       IO_PORTX_FUNC_SERDES;
47880 +
47881 +               /*
47882 +                * Configure SERDES baudrate
47883 +                */
47884 +               if ( baud == 0 ) {
47885 +                       baud = ubi32_serdes_default_baud_rate;
47886 +               }
47887 +
47888 +               io_port->ctl0 =
47889 +                       SERIAL_UBICOM_CTL0 |
47890 +                       ((port->uartclk / (16 * baud)) - 1);
47891 +
47892 +               io_port->ctl1 =
47893 +                       SERIAL_UBICOM_CTL1;
47894 +
47895 +               /*
47896 +                * don't interrupt until startup and start_tx
47897 +                */
47898 +               io_port->int_mask = 0;
47899 +
47900 +               /*
47901 +                * Set TXD pin output, RXD input and prevent GPIO
47902 +                * override on the TXD & RXD pins
47903 +                */
47904 +               io_port->gpio_ctl &= ~SERIAL_UBICOM_PIN_RXD;
47905 +               io_port->gpio_ctl |= SERIAL_UBICOM_PIN_TXD;
47906 +               io_port->gpio_mask &= ~(SERIAL_UBICOM_PIN_RXD | SERIAL_UBICOM_PIN_TXD);
47907 +
47908 +               /*
47909 +                * Restart (un-reset) the port's SERDES function.
47910 +                */
47911 +               io_port->function &= ~(IO_FUNC_FUNCTION_RESET(IO_PORTX_FUNC_SERDES));
47912 +       }
47913 +}
47914 +
47915 +#define ULITE_STATUS_RXVALID IO_PORTX_INT_SERDES_RXBF
47916 +#define ULITE_STATUS_OVERRUN 0
47917 +#define ULITE_STATUS_FRAME 0
47918 +#define ULITE_STATUS_PARITY 0
47919 +#define ULITE_STATUS_TXEMPTY IO_PORTX_INT_SERDES_TXBE
47920 +#define ULITE_STATUS_TXFULL 0
47921 +
47922 +static int ubi32_serdes_receive(struct uart_port *port, int stat)
47923 +{
47924 +       struct tty_struct *tty = port->info->port.tty;
47925 +       unsigned char ch = 0;
47926 +       char flag = TTY_NORMAL;
47927 +
47928 +       if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
47929 +                    | ULITE_STATUS_FRAME)) == 0)
47930 +               return 0;
47931 +
47932 +       /* stats */
47933 +       if (stat & ULITE_STATUS_RXVALID) {
47934 +               port->icount.rx++;
47935 +               ch = ubi32_serdes_get_char((struct ubicom32_io_port *)port->membase);
47936 +
47937 +               if (stat & ULITE_STATUS_PARITY)
47938 +                       port->icount.parity++;
47939 +       }
47940 +
47941 +       if (stat & ULITE_STATUS_OVERRUN)
47942 +               port->icount.overrun++;
47943 +
47944 +       if (stat & ULITE_STATUS_FRAME)
47945 +               port->icount.frame++;
47946 +
47947 +
47948 +       /* drop byte with parity error if IGNPAR specificed */
47949 +       if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
47950 +               stat &= ~ULITE_STATUS_RXVALID;
47951 +
47952 +       stat &= port->read_status_mask;
47953 +
47954 +       if (stat & ULITE_STATUS_PARITY)
47955 +               flag = TTY_PARITY;
47956 +
47957 +       stat &= ~port->ignore_status_mask;
47958 +
47959 +       if (stat & ULITE_STATUS_RXVALID)
47960 +               tty_insert_flip_char(tty, ch, flag);
47961 +
47962 +       if (stat & ULITE_STATUS_FRAME)
47963 +               tty_insert_flip_char(tty, 0, TTY_FRAME);
47964 +
47965 +       if (stat & ULITE_STATUS_OVERRUN)
47966 +               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
47967 +
47968 +       return 1;
47969 +}
47970 +
47971 +/*
47972 + * interrupts are disabled on entry
47973 + */
47974 +static void ubi32_serdes_stop_tx(struct uart_port *port)
47975 +{
47976 +       IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) & ~IO_PORTX_INT_SERDES_TXBE;
47977 +}
47978 +
47979 +static int ubi32_serdes_transmit(struct uart_port *port, int stat)
47980 +{
47981 +       struct circ_buf *xmit  = &port->info->xmit;
47982 +
47983 +       if (!(stat & IO_PORTX_INT_SERDES_TXBE))
47984 +               return 0;
47985 +
47986 +       if (port->x_char) {
47987 +               ubi32_serdes_put_char(IO_PORT(port), port->x_char);
47988 +               port->x_char = 0;
47989 +               port->icount.tx++;
47990 +               return 1;
47991 +       }
47992 +
47993 +       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
47994 +               ubi32_serdes_stop_tx(port);
47995 +               return 0;
47996 +       }
47997 +
47998 +       ubi32_serdes_put_char(IO_PORT(port), xmit->buf[xmit->tail]);
47999 +       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
48000 +       port->icount.tx++;
48001 +
48002 +       /* wake up */
48003 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
48004 +               uart_write_wakeup(port);
48005 +
48006 +       if (uart_circ_empty(xmit))
48007 +               ubi32_serdes_stop_tx(port);
48008 +
48009 +       return 1;
48010 +}
48011 +
48012 +/*
48013 + * port is locked and interrupts are disabled
48014 + */
48015 +static void ubi32_serdes_start_tx(struct uart_port *port)
48016 +{
48017 +       IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) | IO_PORTX_INT_SERDES_TXBE;
48018 +       ubi32_serdes_transmit(port, IO_PORT_INT_STATUS(port));
48019 +}
48020 +
48021 +/*
48022 + * Interrupts are enabled
48023 + */
48024 +static void ubi32_serdes_stop_rx(struct uart_port *port)
48025 +{
48026 +       /* don't forward any more data (like !CREAD) */
48027 +       port->ignore_status_mask = IO_PORTX_INT_SERDES_RXBF;
48028 +}
48029 +
48030 +/*
48031 + * Set the modem control timer to fire immediately.
48032 + */
48033 +static void ubi32_serdes_enable_ms(struct uart_port *port)
48034 +{
48035 +       /* N/A */
48036 +}
48037 +
48038 +static irqreturn_t ubi32_serdes_isr(int irq, void *dev_id)
48039 +{
48040 +       struct uart_port *port = dev_id;
48041 +       int busy;
48042 +
48043 +       spin_lock(&port->lock);
48044 +
48045 +       do {
48046 +               int stat = IO_PORT_INT_STATUS(port);
48047 +               busy  = ubi32_serdes_receive(port, stat);
48048 +               busy |= ubi32_serdes_transmit(port, stat);
48049 +       } while (busy);
48050 +
48051 +       tty_flip_buffer_push(port->info->port.tty);
48052 +
48053 +       spin_unlock(&port->lock);
48054 +
48055 +       return IRQ_HANDLED;
48056 +}
48057 +
48058 +/*
48059 + * Return TIOCSER_TEMT when transmitter is not busy.
48060 + */
48061 +static unsigned int ubi32_serdes_tx_empty(struct uart_port *port)
48062 +{
48063 +       unsigned long flags;
48064 +       unsigned int ret;
48065 +
48066 +       spin_lock_irqsave(&port->lock, flags);
48067 +       ret = IO_PORT_INT_STATUS(port);
48068 +       spin_unlock_irqrestore(&port->lock, flags);
48069 +
48070 +       return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
48071 +}
48072 +
48073 +static unsigned int ubi32_serdes_get_mctrl(struct uart_port *port)
48074 +{
48075 +       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
48076 +}
48077 +
48078 +static void ubi32_serdes_set_mctrl(struct uart_port *port, unsigned int mctrl)
48079 +{
48080 +       /* N/A */
48081 +}
48082 +
48083 +/*
48084 + * Interrupts are always disabled.
48085 + */
48086 +static void ubi32_serdes_break_ctl(struct uart_port *port, int break_state)
48087 +{
48088 +       /* N/A */
48089 +}
48090 +
48091 +static int ubi32_serdes_startup(struct uart_port *port)
48092 +{
48093 +       if (request_irq(port->irq, ubi32_serdes_isr, IRQF_DISABLED,
48094 +            "UBI32_SERDES", port)) {
48095 +               printk(KERN_NOTICE "Unable to attach port interrupt\n");
48096 +               return -EBUSY;
48097 +       }
48098 +
48099 +       IO_PORT_INT_CLR(port) = IO_PORTX_INT_SERDES_RXBF;
48100 +       IO_PORT_INT_MASK(port) = IO_PORTX_INT_SERDES_RXBF;
48101 +       return 0;
48102 +}
48103 +
48104 +static void ubi32_serdes_shutdown(struct uart_port *port)
48105 +{
48106 +       struct ubi32_serdes_port *uart = (struct ubi32_serdes_port *)port;
48107 +
48108 +       IO_PORT_INT_MASK(port) = 0;
48109 +       free_irq(port->irq, uart);
48110 +}
48111 +
48112 +static void
48113 +ubi32_serdes_set_termios(struct uart_port *port, struct ktermios *termios,
48114 +                  struct ktermios *old)
48115 +{
48116 +       unsigned long flags;
48117 +       unsigned int baud;
48118 +
48119 +       spin_lock_irqsave(&port->lock, flags);
48120 +
48121 +       port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
48122 +               | ULITE_STATUS_TXFULL;
48123 +
48124 +       if (termios->c_iflag & INPCK)
48125 +               port->read_status_mask |=
48126 +                       ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
48127 +
48128 +       port->ignore_status_mask = 0;
48129 +       if (termios->c_iflag & IGNPAR)
48130 +               port->ignore_status_mask |= ULITE_STATUS_PARITY
48131 +                       | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48132 +
48133 +       /* ignore all characters if CREAD is not set */
48134 +       if ((termios->c_cflag & CREAD) == 0)
48135 +               port->ignore_status_mask |=
48136 +                       ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
48137 +                       | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48138 +
48139 +       /* update timeout */
48140 +       baud = uart_get_baud_rate(port, termios, old, 0, 460800);
48141 +       uart_update_timeout(port, termios->c_cflag, baud);
48142 +
48143 +       IO_PORT(port)->ctl0 = SERIAL_UBICOM_CTL0 |
48144 +                       ((port->uartclk / (16 * baud)) - 1);
48145 +
48146 +       spin_unlock_irqrestore(&port->lock, flags);
48147 +}
48148 +
48149 +static const char *ubi32_serdes_type(struct uart_port *port)
48150 +{
48151 +       return port->type == PORT_UBI32_SERDES ? "UBI32_SERDES" : NULL;
48152 +}
48153 +
48154 +/*
48155 + * Release the memory region(s) being used by 'port'.
48156 + */
48157 +static void ubi32_serdes_release_port(struct uart_port *port)
48158 +{
48159 +}
48160 +
48161 +/*
48162 + * Request the memory region(s) being used by 'port'.
48163 + */
48164 +static int ubi32_serdes_request_port(struct uart_port *port)
48165 +{
48166 +       return 0;
48167 +}
48168 +
48169 +/*
48170 + * Configure/autoconfigure the port.
48171 + */
48172 +static void ubi32_serdes_config_port(struct uart_port *port, int flags)
48173 +{
48174 +       if (flags & UART_CONFIG_TYPE &&
48175 +           ubi32_serdes_request_port(port) == 0)
48176 +               port->type = PORT_UBI32_SERDES;
48177 +}
48178 +
48179 +/*
48180 + * Verify the new serial_struct (for TIOCSSERIAL).
48181 + * The only change we allow are to the flags and type, and
48182 + * even then only between PORT_UBI32_SERDES and PORT_UNKNOWN
48183 + */
48184 +static int
48185 +ubi32_serdes_verify_port(struct uart_port *port, struct serial_struct *ser)
48186 +{
48187 +       return 0;
48188 +}
48189 +
48190 +static struct uart_ops ubi32_serdes_pops = {
48191 +       .tx_empty       = ubi32_serdes_tx_empty,
48192 +       .set_mctrl      = ubi32_serdes_set_mctrl,
48193 +       .get_mctrl      = ubi32_serdes_get_mctrl,
48194 +       .stop_tx        = ubi32_serdes_stop_tx,
48195 +       .start_tx       = ubi32_serdes_start_tx,
48196 +       .stop_rx        = ubi32_serdes_stop_rx,
48197 +       .enable_ms      = ubi32_serdes_enable_ms,
48198 +       .break_ctl      = ubi32_serdes_break_ctl,
48199 +       .startup        = ubi32_serdes_startup,
48200 +       .shutdown       = ubi32_serdes_shutdown,
48201 +       .set_termios    = ubi32_serdes_set_termios,
48202 +       .type           = ubi32_serdes_type,
48203 +       .release_port   = ubi32_serdes_release_port,
48204 +       .request_port   = ubi32_serdes_request_port,
48205 +       .config_port    = ubi32_serdes_config_port,
48206 +       .verify_port    = ubi32_serdes_verify_port,
48207 +};
48208 +
48209 +static void __init ubi32_serdes_init_ports(void)
48210 +{
48211 +       int i;
48212 +
48213 +       for (i = 0; i < NR_PORTS; i++) {
48214 +               ubi32_serdes_ports[i].uartclk   = ubi32_serdes_resource[i].uart_clock;
48215 +               ubi32_serdes_ports[i].ops       = &ubi32_serdes_pops;
48216 +               ubi32_serdes_ports[i].line      = i;
48217 +               ubi32_serdes_ports[i].iotype    = UPIO_MEM;
48218 +               ubi32_serdes_ports[i].membase   =
48219 +                       (void __iomem *)ubi32_serdes_resource[i].uart_base_addr;
48220 +               ubi32_serdes_ports[i].mapbase   =
48221 +                       (resource_size_t)ubi32_serdes_resource[i].uart_base_addr;
48222 +               ubi32_serdes_ports[i].irq       =
48223 +                       ubi32_serdes_resource[i].uart_irq;
48224 +               ubi32_serdes_ports[i].flags     = UPF_BOOT_AUTOCONF;
48225 +
48226 +               ubi32_serdes_hw_init(&ubi32_serdes_ports[i], 0);
48227 +       }
48228 +
48229 +}
48230 +
48231 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48232 +/*
48233 + * If the port was already initialised (eg, by a boot loader),
48234 + * try to determine the current setup.
48235 + */
48236 +static void __init
48237 +ubi32_serdes_console_get_options(struct uart_port *port, int *baud)
48238 +{
48239 +       u32 round_to = 1200;
48240 +       u32 real_baud;
48241 +
48242 +       /*
48243 +        * We might get called before platform init and with no
48244 +        * kernel command line options, so port might be NULL.
48245 +        */
48246 +       *baud = ubi32_serdes_default_baud_rate;;
48247 +       if ( IO_PORT(port) == 0 )
48248 +               return;
48249 +
48250 +       real_baud = port->uartclk
48251 +               / (16 * ((IO_PORT(port)->ctl0 & ~SERIAL_UBICOM_CTL0) + 1));
48252 +
48253 +       *baud = ((real_baud + round_to - 1) / round_to) * round_to;
48254 +
48255 +       pr_debug("%s:baud = %d, real_baud = %d\n", __FUNCTION__, *baud, real_baud);
48256 +}
48257 +#endif
48258 +
48259 +#if defined(CONFIG_SERIAL_UBI32_SERDES_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
48260 +static struct uart_driver ubi32_serdes_reg;
48261 +
48262 +static int __init
48263 +ubi32_serdes_console_setup(struct console *co, char *options)
48264 +{
48265 +       struct uart_port *port;
48266 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48267 +       int baud = ubi32_serdes_default_baud_rate;
48268 +       int bits = 8;
48269 +       int parity = 'n';
48270 +       int flow = 'n';
48271 +#endif
48272 +
48273 +       /*
48274 +        * Check whether an invalid uart number has been specified, and
48275 +        * if so, search for the first available port that does have
48276 +        * console support.
48277 +        */
48278 +       if (co->index == -1 || co->index >= NR_PORTS)
48279 +               co->index = 0;
48280 +       port = &ubi32_serdes_ports[co->index];
48281 +
48282 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48283 +       if (options) {
48284 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
48285 +               ubi32_serdes_hw_init(port, baud);
48286 +       }
48287 +       else
48288 +               ubi32_serdes_console_get_options(port, &baud);
48289 +
48290 +       return uart_set_options(port, co, baud, parity, bits, flow);
48291 +#else
48292 +       return 0;
48293 +#endif
48294 +}
48295 +#endif /* defined (CONFIG_SERIAL_UBI32_SERDES_CONSOLE) ||
48296 +                                defined (CONFIG_EARLY_PRINTK) */
48297 +
48298 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48299 +static void
48300 +ubi32_serdes_console_putchar(struct uart_port *port, int ch)
48301 +{
48302 +       if ( IO_PORT(port) ) {
48303 +               while (!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE))
48304 +                       barrier();
48305 +               ubi32_serdes_put_char(IO_PORT(port), ch);
48306 +       }
48307 +}
48308 +
48309 +/*
48310 + * Interrupts are disabled on entering
48311 + */
48312 +static void
48313 +ubi32_serdes_console_write(struct console *co, const char *s, unsigned int count)
48314 +{
48315 +       struct uart_port *port = &ubi32_serdes_ports[co->index];
48316 +       unsigned long flags = 0;
48317 +
48318 +       spin_lock_irqsave(&port->lock, flags);
48319 +       uart_console_write(port, s, count, ubi32_serdes_console_putchar);
48320 +       spin_unlock_irqrestore(&port->lock, flags);
48321 +
48322 +}
48323 +
48324 +static struct console ubi32_serdes_console = {
48325 +       .name           = UBI32_SERDES_NAME,
48326 +       .write          = ubi32_serdes_console_write,
48327 +       .device         = uart_console_device,
48328 +       .setup          = ubi32_serdes_console_setup,
48329 +       .flags          = CON_PRINTBUFFER,
48330 +       .index          = -1,
48331 +       .data           = &ubi32_serdes_reg,
48332 +};
48333 +
48334 +static int __init ubi32_serdes_console_init(void)
48335 +{
48336 +       ubi32_serdes_init_ports();
48337 +       register_console(&ubi32_serdes_console);
48338 +       return 0;
48339 +}
48340 +console_initcall(ubi32_serdes_console_init);
48341 +
48342 +#define UBI32_SERDES_CONSOLE   &ubi32_serdes_console
48343 +#else
48344 +#define UBI32_SERDES_CONSOLE   NULL
48345 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48346 +
48347 +
48348 +#ifdef CONFIG_EARLY_PRINTK
48349 +static __init void ubi32_serdes_early_putc(struct uart_port *port, int ch)
48350 +{
48351 +       unsigned timeout = 0xffff;
48352 +
48353 +       while ((!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE)) && --timeout)
48354 +               cpu_relax();
48355 +       ubi32_serdes_put_char(IO_PORT(port), ch);
48356 +}
48357 +
48358 +static __init void ubi32_serdes_early_write(struct console *con, const char *s,
48359 +                                       unsigned int n)
48360 +{
48361 +       struct uart_port *port = &ubi32_serdes_ports[con->index];
48362 +       unsigned int i;
48363 +
48364 +       for (i = 0; i < n; i++, s++) {
48365 +               if (*s == '\n')
48366 +                       ubi32_serdes_early_putc(port, '\r');
48367 +               ubi32_serdes_early_putc(port, *s);
48368 +       }
48369 +}
48370 +
48371 +static struct __init console ubi32_serdes_early_console = {
48372 +       .name = "early_US",
48373 +       .write = ubi32_serdes_early_write,
48374 +       .device = uart_console_device,
48375 +       .flags = CON_PRINTBUFFER,
48376 +       .setup = ubi32_serdes_console_setup,
48377 +       .index = -1,
48378 +       .data  = &ubi32_serdes_reg,
48379 +};
48380 +
48381 +/*
48382 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
48383 + */
48384 +struct console __init *ubi32_serdes_early_init(unsigned int port_index,
48385 +                                               unsigned int cflag)
48386 +{
48387 +       struct uart_port *uart;
48388 +       struct ktermios t;
48389 +
48390 +       if (port_index == -1 || port_index >= NR_PORTS)
48391 +               port_index = 0;
48392 +       ubi32_serdes_init_ports();
48393 +       ubi32_serdes_early_console.index = port_index;
48394 +       uart = &ubi32_serdes_ports[port_index];
48395 +       t.c_cflag = cflag;
48396 +       t.c_iflag = 0;
48397 +       t.c_oflag = 0;
48398 +       t.c_lflag = ICANON;
48399 +       t.c_line = port_index;
48400 +       ubi32_serdes_set_termios(uart, &t, &t);
48401 +       return &ubi32_serdes_early_console;
48402 +}
48403 +
48404 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48405 +
48406 +static struct uart_driver ubi32_serdes_reg = {
48407 +       .owner                  = THIS_MODULE,
48408 +       .driver_name            = "ubi32_serdes",
48409 +       .dev_name               = UBI32_SERDES_NAME,
48410 +       .major                  = UBI32_SERDES_MAJOR,
48411 +       .minor                  = UBI32_SERDES_MINOR,
48412 +       .nr                     = NR_PORTS,
48413 +       .cons                   = UBI32_SERDES_CONSOLE,
48414 +};
48415 +
48416 +static int ubi32_serdes_suspend(struct platform_device *dev, pm_message_t state)
48417 +{
48418 +       struct uart_port *port = platform_get_drvdata(dev);
48419 +
48420 +       if (port)
48421 +               uart_suspend_port(&ubi32_serdes_reg, port);
48422 +
48423 +       return 0;
48424 +}
48425 +
48426 +static int ubi32_serdes_resume(struct platform_device *dev)
48427 +{
48428 +       struct uart_port *port = platform_get_drvdata(dev);
48429 +
48430 +       if (port)
48431 +               uart_resume_port(&ubi32_serdes_reg, port);
48432 +
48433 +       return 0;
48434 +}
48435 +
48436 +static int ubi32_serdes_probe(struct platform_device *dev)
48437 +{
48438 +       struct resource *res = dev->resource;
48439 +       int i;
48440 +
48441 +       for (i = 0; i < dev->num_resources; i++, res++) {
48442 +               if (res->flags & IORESOURCE_MEM) {
48443 +                       ubi32_serdes_resource[0].uart_base_addr = (void *) res->start;
48444 +               }
48445 +               else if (res->flags & IORESOURCE_IRQ) {
48446 +                       ubi32_serdes_resource[0].uart_irq = res->start;
48447 +               }
48448 +               else if (res->flags & UBICOM32_SUART_IORESOURCE_CLOCK) {
48449 +                       ubi32_serdes_resource[0].uart_clock = res->start;
48450 +               }
48451 +       }
48452 +
48453 +       ubi32_serdes_init_ports();
48454 +
48455 +       return 0;
48456 +}
48457 +
48458 +static int ubi32_serdes_remove(struct platform_device *pdev)
48459 +{
48460 +       struct uart_port *port = platform_get_drvdata(pdev);
48461 +
48462 +       platform_set_drvdata(pdev, NULL);
48463 +
48464 +       if (port)
48465 +               uart_remove_one_port(&ubi32_serdes_reg, port);
48466 +
48467 +       return 0;
48468 +}
48469 +
48470 +static struct platform_driver ubi32_serdes_driver = {
48471 +       .remove         = ubi32_serdes_remove,
48472 +       .suspend        = ubi32_serdes_suspend,
48473 +       .resume         = ubi32_serdes_resume,
48474 +       .driver         = {
48475 +               .name   = "ubicom32suart",
48476 +               .owner  = THIS_MODULE,
48477 +       },
48478 +};
48479 +
48480 +
48481 +#ifndef MODULE
48482 +/*
48483 + * Called at boot time.
48484 + *
48485 + * You can specify IO base, IRQ, and clock for the serdes serial port
48486 + * using kernel command line "serdes=0xiobase,irq,clock".  Values
48487 + * specified will be overwritten by platform device data, if present.
48488 + */
48489 +static int __init ubi32_serdes_setup(char *str)
48490 +{
48491 +#define N_PARMS   (4+1)
48492 +       int ints[N_PARMS];
48493 +       int i;
48494 +
48495 +       str = get_options(str, ARRAY_SIZE(ints), ints);
48496 +
48497 +       for (i = 0; i < N_PARMS; i++) {
48498 +               if (i < ints[0]) {
48499 +                       if (i == 0) {
48500 +                               ubi32_serdes_resource[0].uart_base_addr = (void *) ints[i+1];
48501 +                       }
48502 +                       else if (i == 1) {
48503 +                               ubi32_serdes_resource[0].uart_irq = ints[i+1];
48504 +                       }
48505 +                       else if (i == 2) {
48506 +                               ubi32_serdes_resource[0].uart_clock = ints[i+1];
48507 +                       }
48508 +                       else if (i == 3) {
48509 +                               ubi32_serdes_default_baud_rate = ints[i+1];
48510 +                       }
48511 +               }
48512 +       }
48513 +       return 1;
48514 +}
48515 +
48516 +__setup("serdes=", ubi32_serdes_setup);
48517 +#endif
48518 +
48519 +static int __init ubi32_serdes_init(void)
48520 +{
48521 +       int ret;
48522 +
48523 +       pr_info("Serial: Ubicom32 serdes uart serial driver\n");
48524 +
48525 +       ret = platform_driver_probe(&ubi32_serdes_driver, ubi32_serdes_probe);
48526 +       if (ret != 0) {
48527 +               printk(KERN_INFO "serdes platform_driver_probe() failed: %d\n", ret);
48528 +               return ret;
48529 +       }
48530 +
48531 +       ubi32_serdes_init_ports();
48532 +
48533 +       ret = uart_register_driver(&ubi32_serdes_reg);
48534 +       if ( ret == 0 ) {
48535 +               ret = uart_add_one_port(&ubi32_serdes_reg, &ubi32_serdes_ports[0]);
48536 +               if ( ret != 0 ) {
48537 +                       uart_unregister_driver(&ubi32_serdes_reg);
48538 +               }
48539 +       }
48540 +
48541 +       return ret;
48542 +}
48543 +
48544 +static void __exit ubi32_serdes_exit(void)
48545 +{
48546 +       platform_driver_unregister(&ubi32_serdes_driver);
48547 +       uart_unregister_driver(&ubi32_serdes_reg);
48548 +}
48549 +
48550 +module_init(ubi32_serdes_init);
48551 +module_exit(ubi32_serdes_exit);
48552 +
48553 +MODULE_AUTHOR("Rainer Keller <rkeller@ubicom.com>");
48554 +MODULE_DESCRIPTION("Ubicom generic serial port driver");
48555 +MODULE_LICENSE("GPL");
48556 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_SERDES_MAJOR);
48557 +MODULE_ALIAS("platform:ubi32_serdes");
48558 --- /dev/null
48559 +++ b/drivers/serial/ubi32_uarttio.c
48560 @@ -0,0 +1,1172 @@
48561 +/*
48562 + * drivers/serial/ubi32_uarttio.c
48563 + *   Ubicom32 Serial Virtual Peripherial Driver
48564 + *
48565 + * (C) Copyright 2009, Ubicom, Inc.
48566 + *
48567 + * This file is part of the Ubicom32 Linux Kernel Port.
48568 + *
48569 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
48570 + * it and/or modify it under the terms of the GNU General Public License
48571 + * as published by the Free Software Foundation, either version 2 of the
48572 + * License, or (at your option) any later version.
48573 + *
48574 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
48575 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
48576 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
48577 + * the GNU General Public License for more details.
48578 + *
48579 + * You should have received a copy of the GNU General Public License
48580 + * along with the Ubicom32 Linux Kernel Port.  If not,
48581 + * see <http://www.gnu.org/licenses/>.
48582 + */
48583 +
48584 +#include <linux/module.h>
48585 +#include <linux/ioport.h>
48586 +#include <linux/init.h>
48587 +#include <linux/console.h>
48588 +#include <linux/sysrq.h>
48589 +#include <linux/platform_device.h>
48590 +#include <linux/tty.h>
48591 +#include <linux/tty_flip.h>
48592 +#include <linux/serial_core.h>
48593 +
48594 +#include <asm/ip5000.h>
48595 +#include <asm/gpio.h>
48596 +#include <asm/thread.h>
48597 +#include <asm/uart_tio.h>
48598 +
48599 +#define DRIVER_NAME    "ubi32_uarttio"
48600 +
48601 +/*
48602 + * For storing the module parameters.
48603 + */
48604 +#define UBI32_UARTTIO_MAX_PARAM_LEN    80
48605 +static char utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN];
48606 +
48607 +/*
48608 + * UART name and device definitions
48609 + */
48610 +#define UBI32_UARTTIO_NAME     "ttyUV" // XXX
48611 +#define UBI32_UARTTIO_MAJOR    206 // XXX
48612 +#define UBI32_UARTTIO_MINOR    64 // XXX
48613 +
48614 +/*
48615 + * The following structures are allocated statically because the
48616 + * memory allocation subsystem is not initialized this early on
48617 + */
48618 +
48619 +/*
48620 + * Per port structure
48621 + */
48622 +struct ubi32_uarttio_port {
48623 +       struct uarttio_uart             *uart;
48624 +       unsigned int                    tx_pin;
48625 +       unsigned int                    rx_pin;
48626 +
48627 +       struct uart_port                port;
48628 +
48629 +       u8_t                            added;
48630 +
48631 +       /*
48632 +        * If this value is set, the port has had its direction set already
48633 +        */
48634 +       u8_t                            port_init;
48635 +};
48636 +static struct ubi32_uarttio_port uarttio_ports[CONFIG_SERIAL_UBI32_UARTTIO_NR_UARTS];
48637 +
48638 +/*
48639 + * Number of ports currently initialized
48640 + */
48641 +static int uarttio_nports;
48642 +
48643 +/*
48644 + * Per device structure
48645 + */
48646 +struct ubi32_uarttio_instance {
48647 +       struct uarttio_regs             *regs;
48648 +       struct ubi32_uarttio_port       *ports;
48649 +
48650 +       u8_t                            irq_requested;
48651 +       u8_t                            driver_registered;
48652 +       u8_t                            irq;
48653 +};
48654 +static struct ubi32_uarttio_instance uarttio_inst;
48655 +
48656 +#ifdef CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE
48657 +static struct console ubi32_uarttio_console;
48658 +#define UBI32_UARTTIO_CONSOLE  &ubi32_uarttio_console
48659 +#else
48660 +#define UBI32_UARTTIO_CONSOLE  NULL
48661 +#endif
48662 +
48663 +static struct uart_driver ubi32_uarttio_uart_driver = {
48664 +       .owner                  = THIS_MODULE,
48665 +       .driver_name            = DRIVER_NAME,
48666 +       .dev_name               = UBI32_UARTTIO_NAME,
48667 +       .major                  = UBI32_UARTTIO_MAJOR,
48668 +       .minor                  = UBI32_UARTTIO_MINOR,
48669 +       .cons                   = UBI32_UARTTIO_CONSOLE,
48670 +};
48671 +
48672 +#ifdef UBI32_UARTTIO_UNUSED
48673 +/*
48674 + * ubi32_uarttio_get_send_space
48675 + */
48676 +static int ubi32_uarttio_get_send_space(struct uarttio_uart *uart)
48677 +{
48678 +       int count = uart->tx_fifo_head - uart->tx_fifo_tail;
48679 +       if (count < 0) {
48680 +               count += uart->tx_fifo_size;
48681 +       }
48682 +       return uart->tx_fifo_size - count;
48683 +}
48684 +#endif
48685 +
48686 +/*
48687 + * ubi32_uarttio_get_recv_ready
48688 + */
48689 +static int ubi32_uarttio_get_recv_ready(struct uarttio_uart *uart)
48690 +{
48691 +       int count = uart->rx_fifo_head - uart->rx_fifo_tail;
48692 +       if (count < 0) {
48693 +               count += uart->rx_fifo_size;
48694 +       }
48695 +       return count;
48696 +}
48697 +
48698 +/*
48699 + * ubi32_uarttio_get_char()
48700 + */
48701 +static u8_t ubi32_uarttio_get_char(struct uarttio_uart *uart)
48702 +{
48703 +       /*
48704 +        * Retrieve byte
48705 +        */
48706 +       u32_t tail = uart->rx_fifo_tail;
48707 +       u8_t data = uart->rx_fifo[tail];
48708 +
48709 +       if (++tail == uart->rx_fifo_size) {
48710 +               tail = 0;
48711 +       }
48712 +       uart->rx_fifo_tail = tail;
48713 +
48714 +       return data;
48715 +}
48716 +
48717 +/*
48718 + * ubi32_uarttio_put_char()
48719 + */
48720 +static int ubi32_uarttio_put_char(struct uarttio_uart *uart, u8_t c)
48721 +{
48722 +       u32_t head = uart->tx_fifo_head;
48723 +       u32_t prev = head;
48724 +
48725 +       /*
48726 +        * Wrap
48727 +        */
48728 +       if (++head == uart->tx_fifo_size) {
48729 +               head = 0;
48730 +       }
48731 +
48732 +       /*
48733 +        * If there isn't any space, return EBUSY
48734 +        */
48735 +       if (head == uart->tx_fifo_tail) {
48736 +               return -EBUSY;
48737 +       }
48738 +
48739 +       /*
48740 +        * Put the character in the queue
48741 +        */
48742 +       uart->tx_fifo[prev] = c;
48743 +       uart->tx_fifo_head = head;
48744 +
48745 +       return 0;
48746 +}
48747 +
48748 +/*
48749 + * ubi32_uarttio_set_baud
48750 + */
48751 +static int ubi32_uarttio_set_baud(struct ubi32_uarttio_port *uup, unsigned int baud)
48752 +{
48753 +       if (uup->uart->current_baud_rate == baud) {
48754 +               return 0;
48755 +       }
48756 +
48757 +       uup->uart->baud_rate = baud;
48758 +       uup->uart->flags |= UARTTIO_UART_FLAG_SET_RATE;
48759 +       while (uup->uart->flags & UARTTIO_UART_FLAG_SET_RATE) {
48760 +               cpu_relax();
48761 +       }
48762 +
48763 +       if (uup->uart->current_baud_rate != baud) {
48764 +               /*
48765 +                * Failed to set baud rate
48766 +                */
48767 +               printk(KERN_WARNING "Invalid baud rate %u, running at %u\n", baud, uup->uart->current_baud_rate);
48768 +               return -EINVAL;
48769 +       }
48770 +
48771 +       return 0;
48772 +}
48773 +
48774 +/*
48775 + * ubi32_uarttio_handle_receive
48776 + */
48777 +static void ubi32_uarttio_handle_receive(struct ubi32_uarttio_port *uup, int stat)
48778 +{
48779 +       struct uarttio_uart *uart = uup->uart;
48780 +       struct uart_port *port = &uup->port;
48781 +       struct tty_struct *tty = port->info->port.tty;
48782 +       unsigned char ch = 0;
48783 +       char flag = TTY_NORMAL;
48784 +       int count;
48785 +
48786 +       if ((stat & (UARTTIO_UART_INT_RX | UARTTIO_UART_INT_RXFRAME | UARTTIO_UART_INT_RXOVF)) == 0) {
48787 +               return;
48788 +       }
48789 +
48790 +       if (stat & UARTTIO_UART_INT_RX) {
48791 +               count = ubi32_uarttio_get_recv_ready(uart);
48792 +               port->icount.rx += count;
48793 +       }
48794 +
48795 +       if (stat & UARTTIO_UART_INT_RXOVF) {
48796 +               port->icount.overrun++;
48797 +       }
48798 +
48799 +       if (stat & UARTTIO_UART_INT_RXFRAME) {
48800 +               port->icount.frame++;
48801 +       }
48802 +
48803 +       stat &= ~port->ignore_status_mask;
48804 +
48805 +       if (stat & UARTTIO_UART_INT_RX) {
48806 +               int i;
48807 +               for (i = 0; i < count; i++) {
48808 +                       ch = ubi32_uarttio_get_char(uart);
48809 +                       tty_insert_flip_char(tty, ch, flag);
48810 +               }
48811 +       }
48812 +
48813 +       if (stat & UARTTIO_UART_INT_RXFRAME) {
48814 +               tty_insert_flip_char(tty, 0, TTY_FRAME);
48815 +       }
48816 +
48817 +       if (stat & UARTTIO_UART_INT_RXOVF) {
48818 +               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
48819 +       }
48820 +}
48821 +
48822 +/*
48823 + * ubi32_uarttio_stop_tx
48824 + *     interrupts are disabled on entry
48825 + */
48826 +static void ubi32_uarttio_stop_tx(struct uart_port *port)
48827 +{
48828 +       struct ubi32_uarttio_port *uup = port->private_data;
48829 +
48830 +       uup->uart->int_mask &= ~UARTTIO_UART_INT_TXBE;
48831 +}
48832 +
48833 +/*
48834 + * ubi32_uarttio_handle_transmit
48835 + */
48836 +static void ubi32_uarttio_handle_transmit(struct ubi32_uarttio_port *uup, int stat)
48837 +{
48838 +       struct uarttio_uart *uart = uup->uart;
48839 +       struct uart_port *port = &uup->port;
48840 +       struct circ_buf *xmit  = &port->info->xmit;
48841 +
48842 +       if (!(stat & UARTTIO_UART_INT_TXBE)) {
48843 +               return;
48844 +       }
48845 +
48846 +       if (port->x_char) {
48847 +               if (ubi32_uarttio_put_char(uart, port->x_char)) {
48848 +                       return;
48849 +               }
48850 +               port->x_char = 0;
48851 +               port->icount.tx++;
48852 +               return;
48853 +       }
48854 +
48855 +       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
48856 +               ubi32_uarttio_stop_tx(port);
48857 +               return;
48858 +       }
48859 +
48860 +       /*
48861 +        * Send as many characters as we can
48862 +        */
48863 +       while (ubi32_uarttio_put_char(uart, xmit->buf[xmit->tail]) == 0) {
48864 +               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
48865 +               port->icount.tx++;
48866 +               if (uart_circ_empty(xmit)) {
48867 +                       break;
48868 +               }
48869 +       }
48870 +
48871 +       /* wake up */
48872 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
48873 +               uart_write_wakeup(port);
48874 +       }
48875 +
48876 +       if (uart_circ_empty(xmit)) {
48877 +               ubi32_uarttio_stop_tx(port);
48878 +       }
48879 +}
48880 +
48881 +/*
48882 + * ubi32_uarttio_start_tx
48883 + *     port is locked and interrupts are disabled
48884 + */
48885 +static void ubi32_uarttio_start_tx(struct uart_port *port)
48886 +{
48887 +       struct ubi32_uarttio_port *uup = port->private_data;
48888 +       struct uarttio_uart *uart = uup->uart;
48889 +
48890 +       uart->int_mask |= UARTTIO_UART_INT_TXBE;
48891 +}
48892 +
48893 +/*
48894 + * ubi32_uarttio_stop_rx
48895 + *     Interrupts are enabled
48896 + */
48897 +static void ubi32_uarttio_stop_rx(struct uart_port *port)
48898 +{
48899 +       struct ubi32_uarttio_port *uup = port->private_data;
48900 +       struct uarttio_uart *uart = uup->uart;
48901 +
48902 +       /*
48903 +        * don't forward any more data (like !CREAD)
48904 +        */
48905 +       uart->int_mask &= ~UARTTIO_UART_INT_RX;
48906 +       port->ignore_status_mask = UARTTIO_UART_INT_RX;
48907 +}
48908 +
48909 +/*
48910 + * ubi32_uarttio_enable_ms
48911 + *     Set the modem control timer to fire immediately.
48912 + */
48913 +static void ubi32_uarttio_enable_ms(struct uart_port *port)
48914 +{
48915 +       /* N/A */
48916 +}
48917 +
48918 +/*
48919 + * ubi32_uarttio_isr
48920 + */
48921 +static irqreturn_t ubi32_uarttio_isr(int irq, void *appdata)
48922 +{
48923 +       struct ubi32_uarttio_port *uup = uarttio_ports;
48924 +       int i;
48925 +
48926 +       /*
48927 +        * Service all of the ports
48928 +        */
48929 +       for (i = 0; i < uarttio_nports; i++) {
48930 +               unsigned int flags;
48931 +
48932 +               if (!(uup->uart->flags & UARTTIO_UART_FLAG_ENABLED)) {
48933 +                       uup++;
48934 +                       continue;
48935 +               }
48936 +
48937 +               spin_lock(&uup->port.lock);
48938 +
48939 +               flags = uup->uart->int_flags;
48940 +
48941 +               uup->uart->int_flags = 0;
48942 +
48943 +               ubi32_uarttio_handle_receive(uup, flags);
48944 +               ubi32_uarttio_handle_transmit(uup, flags);
48945 +
48946 +               tty_flip_buffer_push(uup->port.info->port.tty);
48947 +
48948 +               spin_unlock(&uup->port.lock);
48949 +
48950 +               uup++;
48951 +       }
48952 +
48953 +       return IRQ_HANDLED;
48954 +}
48955 +
48956 +/*
48957 + * ubi32_uarttio_tx_empty
48958 + *     Return TIOCSER_TEMT when transmitter is not busy.
48959 + */
48960 +static unsigned int ubi32_uarttio_tx_empty(struct uart_port *port)
48961 +{
48962 +       struct ubi32_uarttio_port *uup = port->private_data;
48963 +
48964 +       if (uup->uart->tx_fifo_head == uup->uart->tx_fifo_tail) {
48965 +               return TIOCSER_TEMT;
48966 +       }
48967 +
48968 +       return 0;
48969 +}
48970 +
48971 +/*
48972 + * ubi32_uarttio_get_mctrl
48973 + */
48974 +static unsigned int ubi32_uarttio_get_mctrl(struct uart_port *port)
48975 +{
48976 +       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
48977 +}
48978 +
48979 +/*
48980 + * ubi32_uarttio_set_mctrl
48981 + */
48982 +static void ubi32_uarttio_set_mctrl(struct uart_port *port, unsigned int mctrl)
48983 +{
48984 +       /* N/A */
48985 +}
48986 +
48987 +/*
48988 + * ubi32_uarttio_break_ctl
48989 + */
48990 +static void ubi32_uarttio_break_ctl(struct uart_port *port, int break_state)
48991 +{
48992 +       /* N/A */
48993 +}
48994 +
48995 +/*
48996 + * ubi32_uarttio_startup
48997 + */
48998 +static int ubi32_uarttio_startup(struct uart_port *port)
48999 +{
49000 +       struct ubi32_uarttio_port *uup = port->private_data;
49001 +       struct uarttio_uart *uart = uup->uart;
49002 +
49003 +       uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49004 +
49005 +       uart->int_mask |= UARTTIO_UART_INT_TXBE | UARTTIO_UART_INT_RX;
49006 +
49007 +       return 0;
49008 +}
49009 +
49010 +/*
49011 + * ubi32_uarttio_shutdown
49012 + */
49013 +static void ubi32_uarttio_shutdown(struct uart_port *port)
49014 +{
49015 +       struct ubi32_uarttio_port *uup = port->private_data;
49016 +       struct uarttio_uart *uart = uup->uart;
49017 +
49018 +       uart->int_mask = 0;
49019 +       uart->flags &= ~UARTTIO_UART_FLAG_ENABLED;
49020 +}
49021 +
49022 +/*
49023 + * ubi32_uarttio_set_termios
49024 + */
49025 +static void ubi32_uarttio_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
49026 +{
49027 +       struct ubi32_uarttio_port *uup = port->private_data;
49028 +       unsigned long flags;
49029 +       unsigned int baud;
49030 +
49031 +       spin_lock_irqsave(&port->lock, flags);
49032 +
49033 +#if 0
49034 +       port->read_status_mask = UBI32_UARTTIO_RX | UBI32_UARTTIO_RXOVF | UBI32_UARTTIO_TXOVF;
49035 +
49036 +       if (termios->c_iflag & INPCK) {
49037 +               port->read_status_mask |= UBI32_UARTTIO_RXFRAME;
49038 +       }
49039 +#endif
49040 +
49041 +       port->ignore_status_mask = 0;
49042 +       if (termios->c_iflag & IGNPAR) {
49043 +               port->ignore_status_mask |= UARTTIO_UART_INT_RXFRAME |
49044 +                                           UARTTIO_UART_INT_RXOVF;
49045 +       }
49046 +
49047 +       /*
49048 +        * ignore all characters if CREAD is not set
49049 +        */
49050 +       if ((termios->c_cflag & CREAD) == 0) {
49051 +               port->ignore_status_mask |= UARTTIO_UART_INT_RX |
49052 +                                           UARTTIO_UART_INT_RXFRAME |
49053 +                                           UARTTIO_UART_INT_RXOVF;
49054 +       }
49055 +
49056 +       /* update timeout */
49057 +       baud = uart_get_baud_rate(port, termios, old, 0, 460800);
49058 +       uart_update_timeout(port, termios->c_cflag, baud);
49059 +
49060 +       ubi32_uarttio_set_baud(uup, baud);
49061 +       spin_unlock_irqrestore(&port->lock, flags);
49062 +}
49063 +
49064 +/*
49065 + * ubi32_uarttio_type
49066 + */
49067 +static const char *ubi32_uarttio_type(struct uart_port *port)
49068 +{
49069 +       return (port->type == PORT_UBI32_UARTTIO) ? "UBI32_UARTTIO" : NULL;
49070 +}
49071 +
49072 +/*
49073 + * ubi32_uarttio_release_port
49074 + *     Release the memory region(s) being used by 'port'.
49075 + */
49076 +static void ubi32_uarttio_release_port(struct uart_port *port)
49077 +{
49078 +}
49079 +
49080 +/*
49081 + * ubi32_uarttio_request_port
49082 + *     Request the memory region(s) being used by 'port'.
49083 + */
49084 +static int ubi32_uarttio_request_port(struct uart_port *port)
49085 +{
49086 +       return 0;
49087 +}
49088 +
49089 +/*
49090 + * ubi32_uarttio_config_port
49091 + *     Configure/autoconfigure the port.
49092 + */
49093 +static void ubi32_uarttio_config_port(struct uart_port *port, int flags)
49094 +{
49095 +       if ((flags & UART_CONFIG_TYPE) && (ubi32_uarttio_request_port(port) == 0)) {
49096 +               port->type = PORT_UBI32_UARTTIO;
49097 +       }
49098 +}
49099 +
49100 +/*
49101 + * ubi32_uarttio_verify_port
49102 + *     Verify the new serial_struct (for TIOCSSERIAL).
49103 + *
49104 + * The only change we allow are to the flags and type, and
49105 + * even then only between PORT_UBI32_UARTTIO and PORT_UNKNOWN
49106 + */
49107 +static int ubi32_uarttio_verify_port(struct uart_port *port, struct serial_struct *ser)
49108 +{
49109 +       return 0;
49110 +}
49111 +
49112 +static struct uart_ops ubi32_uarttio_pops = {
49113 +       .tx_empty       = ubi32_uarttio_tx_empty,
49114 +       .set_mctrl      = ubi32_uarttio_set_mctrl,
49115 +       .get_mctrl      = ubi32_uarttio_get_mctrl,
49116 +       .stop_tx        = ubi32_uarttio_stop_tx,
49117 +       .start_tx       = ubi32_uarttio_start_tx,
49118 +       .stop_rx        = ubi32_uarttio_stop_rx,
49119 +       .enable_ms      = ubi32_uarttio_enable_ms,
49120 +       .break_ctl      = ubi32_uarttio_break_ctl,
49121 +       .startup        = ubi32_uarttio_startup,
49122 +       .shutdown       = ubi32_uarttio_shutdown,
49123 +       .set_termios    = ubi32_uarttio_set_termios,
49124 +       .type           = ubi32_uarttio_type,
49125 +       .release_port   = ubi32_uarttio_release_port,
49126 +       .request_port   = ubi32_uarttio_request_port,
49127 +       .config_port    = ubi32_uarttio_config_port,
49128 +       .verify_port    = ubi32_uarttio_verify_port,
49129 +};
49130 +
49131 +/*
49132 + * ubi32_uarttio_add_ports
49133 + */
49134 +static int __init ubi32_uarttio_add_ports(void)
49135 +{
49136 +       int res = 0;
49137 +       struct ubi32_uarttio_port *uup = uarttio_ports;
49138 +       int i = 0;
49139 +
49140 +       for (i = 0; i < uarttio_nports; i++) {
49141 +               /*
49142 +                * Setup the GPIOs
49143 +                */
49144 +               res = gpio_request(uup->tx_pin, "ubi32_uarttio_tx");
49145 +               if (res) {
49146 +                       printk(KERN_WARNING "Failed to request GPIO %d\n", uup->tx_pin);
49147 +                       res = -EBUSY;
49148 +                       goto next;
49149 +               }
49150 +
49151 +               res = gpio_request(uup->rx_pin, "ubi32_uarttio_rx");
49152 +               if (res) {
49153 +                       gpio_free(uup->tx_pin);
49154 +                       printk(KERN_WARNING "Failed to request GPIO %d\n", uup->rx_pin);
49155 +                       res = -EBUSY;
49156 +                       goto next;
49157 +               }
49158 +
49159 +               res = uart_add_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49160 +               if (res) {
49161 +                       gpio_free(uup->rx_pin);
49162 +                       gpio_free(uup->tx_pin);
49163 +                       res = -ENODEV;
49164 +                       printk(KERN_WARNING "Failed to add port %d,%d\n", uup->tx_pin, uup->rx_pin);
49165 +                       goto next;
49166 +               }
49167 +               uup->added = 1;
49168 +
49169 +               /*
49170 +                * Set the direction of the ports now, after we're sure that everything is ok
49171 +                */
49172 +               if (!uup->port_init) {
49173 +                       gpio_direction_output(uup->tx_pin, 1);
49174 +                       gpio_direction_input(uup->rx_pin);
49175 +               }
49176 +
49177 +next:
49178 +               uup++;
49179 +       }
49180 +       return res;
49181 +}
49182 +
49183 +/*
49184 + * ubi32_uarttio_cleanup
49185 + */
49186 +static void ubi32_uarttio_cleanup(void)
49187 +{
49188 +       struct ubi32_uarttio_port *uup;
49189 +       int i;
49190 +
49191 +       /*
49192 +        * Stop the hardware thread
49193 +        */
49194 +       if (uarttio_inst.regs) {
49195 +               thread_disable(uarttio_inst.regs->thread);
49196 +       }
49197 +       if (uarttio_inst.irq_requested) {
49198 +               free_irq(uarttio_inst.irq, NULL);
49199 +       }
49200 +
49201 +       /*
49202 +        * Get rid of the ports
49203 +        */
49204 +       uup = uarttio_inst.ports;
49205 +       for (i = 0; i < uarttio_nports; i++) {
49206 +               gpio_free(uup->tx_pin);
49207 +               gpio_free(uup->rx_pin);
49208 +               if (uup->added) {
49209 +                       uart_remove_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49210 +               }
49211 +               uup++;
49212 +       }
49213 +
49214 +       if (uarttio_inst.driver_registered) {
49215 +               uart_unregister_driver(&ubi32_uarttio_uart_driver);
49216 +       }
49217 +}
49218 +
49219 +/*
49220 + * ubi32_uarttio_setup_port
49221 + *     Setup a port in the TIO registers
49222 + */
49223 +static int ubi32_uarttio_setup_port(int index,
49224 +                                   struct uarttio_uart *uart,
49225 +                                   unsigned int baud, unsigned int tx_pin,
49226 +                                   unsigned int rx_pin)
49227 +{
49228 +       struct ubi32_uarttio_port *uup = &uarttio_ports[index];
49229 +       void *tx_port = ubi_gpio_get_port(tx_pin);
49230 +       void *rx_port = ubi_gpio_get_port(rx_pin);
49231 +
49232 +       /*
49233 +        * Verify the ports are on chip
49234 +        */
49235 +       if (!tx_port || !rx_port) {
49236 +               printk(KERN_WARNING "Invalid port(s) specified: %u or %u\n", tx_pin, rx_pin);
49237 +               return -EINVAL;
49238 +       }
49239 +
49240 +       uup->tx_pin = tx_pin;
49241 +       uup->rx_pin = rx_pin;
49242 +       uup->uart = uart;
49243 +
49244 +       /*
49245 +        * Setup the port structure
49246 +        */
49247 +       uup->port.ops           = &ubi32_uarttio_pops;
49248 +       uup->port.line          = index;
49249 +       uup->port.iotype        = UPIO_MEM;
49250 +       uup->port.flags         = UPF_BOOT_AUTOCONF;
49251 +       uup->port.fifosize      = uup->uart->tx_fifo_size;
49252 +       uup->port.private_data  = uup;
49253 +
49254 +       /*
49255 +        * We share this IRQ across all ports
49256 +        */
49257 +       uup->port.irq           = uarttio_inst.irq;
49258 +
49259 +       /*
49260 +        * We really don't have a mem/map base but without these variables
49261 +        * set, the serial_core won't startup.
49262 +        */
49263 +       uup->port.membase       = (void __iomem *)uup;
49264 +       uup->port.mapbase       = (resource_size_t)uup;
49265 +       spin_lock_init(&uup->port.lock);
49266 +
49267 +       /*
49268 +        * Set up the hardware
49269 +        */
49270 +       uart->flags = UARTTIO_UART_FLAG_SET_RATE | UARTTIO_UART_FLAG_RESET;
49271 +
49272 +       uart->tx_port = (unsigned int)tx_port;
49273 +       uart->tx_pin = gpio_pin_index(tx_pin);
49274 +       uart->tx_bits = 8;
49275 +       uart->tx_stop_bits = 1;
49276 +
49277 +       uart->rx_port = (unsigned int)rx_port;
49278 +       uart->rx_pin = gpio_pin_index(rx_pin);
49279 +       uart->rx_bits = 8;
49280 +       uart->rx_stop_bits = 1;
49281 +
49282 +       uart->baud_rate = baud;
49283 +
49284 +       return 0;
49285 +}
49286 +
49287 +enum ubi32_uarttio_parse_states {
49288 +       UBI32_UARTTIO_PARSE_STATE_BAUD,
49289 +       UBI32_UARTTIO_PARSE_STATE_TX_PIN,
49290 +       UBI32_UARTTIO_PARSE_STATE_RX_PIN,
49291 +       UBI32_UARTTIO_PARSE_STATE_HS,
49292 +       UBI32_UARTTIO_PARSE_STATE_CTS_PIN,
49293 +       UBI32_UARTTIO_PARSE_STATE_RTS_PIN,
49294 +};
49295 +
49296 +/*
49297 + * ubi32_uarttio_parse_param
49298 + */
49299 +static int ubi32_uarttio_parse_param(char *str)
49300 +{
49301 +       int res;
49302 +       int i;
49303 +       int baud = 0;
49304 +       int tx_pin = 0;
49305 +       int rx_pin = 0;
49306 +       int hs = 0;
49307 +       int cts_pin = 0;
49308 +       int rts_pin = 0;
49309 +       int nfound = 0;
49310 +       enum ubi32_uarttio_parse_states state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49311 +       struct uarttio_uart *uart = uarttio_inst.regs->uarts;
49312 +
49313 +       /*
49314 +        * Run though the options and generate the proper structures
49315 +        */
49316 +       res = get_option(&str, &i);
49317 +       while ((res == 2) || (res == 1)) {
49318 +               switch (state) {
49319 +               case UBI32_UARTTIO_PARSE_STATE_BAUD:
49320 +                       /*
49321 +                        * If we are here and nfound > 0 then create the port
49322 +                        * based on the previous input
49323 +                        */
49324 +                       if (nfound) {
49325 +                               /*
49326 +                                * Create the port
49327 +                                */
49328 +                               if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49329 +                                       /*
49330 +                                        * Port was invalid
49331 +                                        */
49332 +                                       goto fail;
49333 +                               } else {
49334 +                                       printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49335 +                                       uart++;
49336 +                               }
49337 +                       }
49338 +
49339 +                       /*
49340 +                        * Reset the variables and go to the next state
49341 +                        */
49342 +                       hs = 0;
49343 +                       baud = i;
49344 +                       state = UBI32_UARTTIO_PARSE_STATE_TX_PIN;
49345 +                       break;
49346 +
49347 +               case UBI32_UARTTIO_PARSE_STATE_TX_PIN:
49348 +                       tx_pin = i;
49349 +                       state = UBI32_UARTTIO_PARSE_STATE_RX_PIN;
49350 +                       break;
49351 +
49352 +               case UBI32_UARTTIO_PARSE_STATE_RX_PIN:
49353 +                       rx_pin = i;
49354 +                       state = UBI32_UARTTIO_PARSE_STATE_HS;
49355 +                       break;
49356 +
49357 +               case UBI32_UARTTIO_PARSE_STATE_HS:
49358 +                       hs = i;
49359 +                       if (hs) {
49360 +                               state = UBI32_UARTTIO_PARSE_STATE_CTS_PIN;
49361 +                               break;
49362 +                       }
49363 +
49364 +                       if (nfound == uarttio_inst.regs->max_uarts) {
49365 +                               printk(KERN_WARNING "Maximum number of serial ports reached\n");
49366 +                               goto done;
49367 +                       }
49368 +                       nfound++;
49369 +                       state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49370 +                       break;
49371 +
49372 +               case UBI32_UARTTIO_PARSE_STATE_CTS_PIN:
49373 +                       cts_pin = i;
49374 +                       state = UBI32_UARTTIO_PARSE_STATE_RTS_PIN;
49375 +                       break;
49376 +
49377 +               case UBI32_UARTTIO_PARSE_STATE_RTS_PIN:
49378 +                       rts_pin = i;
49379 +
49380 +                       if (nfound == uarttio_inst.regs->max_uarts) {
49381 +                               printk(KERN_WARNING "Maximum number of serial ports reached\n");
49382 +                               goto done;
49383 +                       }
49384 +                       nfound++;
49385 +                       state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49386 +                       break;
49387 +               }
49388 +               res = get_option(&str, &i);
49389 +       }
49390 +
49391 +       if ((res > 2) || state != UBI32_UARTTIO_PARSE_STATE_BAUD) {
49392 +               printk(KERN_WARNING "Parameter syntax error.\n");
49393 +               res = -EINVAL;
49394 +               goto fail;
49395 +       }
49396 +
49397 +       /*
49398 +        * Create the final port
49399 +        */
49400 +       if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49401 +               goto fail;
49402 +       }
49403 +       printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49404 +
49405 +done:
49406 +       uarttio_nports = nfound;
49407 +
49408 +       return nfound ? 0 : -ENODEV;
49409 +
49410 +fail:
49411 +       /*
49412 +        * Reset the ports
49413 +        */
49414 +       uart = uarttio_inst.regs->uarts;
49415 +       for (i = 0; i < uarttio_inst.regs->max_uarts; i++) {
49416 +               uart->flags = 0;
49417 +               uart++;
49418 +       }
49419 +
49420 +       return res;
49421 +}
49422 +
49423 +/*
49424 + * ubi32_uarttio_probe
49425 + */
49426 +static int ubi32_uarttio_probe(void)
49427 +{
49428 +       int ret;
49429 +       struct uarttio_node *uart_node;
49430 +       char *str = utio_ports_param;
49431 +       static int probed;
49432 +       static int probe_result;
49433 +
49434 +       /*
49435 +        * We only want to be probed once, we could be probed twice
49436 +        * for example if we are used as a console
49437 +        */
49438 +       if (probed) {
49439 +               return probe_result;
49440 +       }
49441 +       probed = 1;
49442 +
49443 +       /*
49444 +        * Extract the TIO name from the setup string
49445 +        */
49446 +       while (*str) {
49447 +               if (*str == ',') {
49448 +                       *str++ = 0;
49449 +                       break;
49450 +               }
49451 +               str++;
49452 +       }
49453 +
49454 +       if (!*str) {
49455 +               probe_result = -EINVAL;
49456 +               return -EINVAL;
49457 +       }
49458 +
49459 +       uart_node = (struct uarttio_node *)devtree_find_node(utio_ports_param);
49460 +       if (!uart_node) {
49461 +               probe_result = -ENODEV;
49462 +               return -ENODEV;
49463 +       }
49464 +
49465 +       uarttio_inst.irq = uart_node->dn.recvirq;
49466 +       uarttio_inst.regs = uart_node->regs;
49467 +
49468 +       /*
49469 +        * Parse module parameters.
49470 +        */
49471 +       ret = ubi32_uarttio_parse_param(str);
49472 +       if (ret != 0) {
49473 +               ubi32_uarttio_cleanup();
49474 +               probe_result = ret;
49475 +               return ret;
49476 +       }
49477 +
49478 +       ubi32_uarttio_uart_driver.nr = uarttio_nports;
49479 +
49480 +       return 0;
49481 +}
49482 +
49483 +#if defined(CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE)
49484 +/*
49485 + * ubi32_uarttio_console_setup
49486 + */
49487 +static int __init ubi32_uarttio_console_setup(struct console *co, char *options)
49488 +{
49489 +       int baud;
49490 +       int bits = 8;
49491 +       int parity = 'n';
49492 +       int flow = 'n';
49493 +       struct ubi32_uarttio_port *uup;
49494 +
49495 +       /*
49496 +        * Check whether an invalid uart number has been specified, and
49497 +        * if so, search for the first available port that does have
49498 +        * console support.
49499 +        */
49500 +       if (co->index == -1 || co->index >= uarttio_nports) {
49501 +               co->index = 0;
49502 +       }
49503 +       uup = &uarttio_ports[co->index];
49504 +       baud = uup->uart->baud_rate;
49505 +       uup->uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49506 +
49507 +       /*
49508 +        * Setup the GPIOs
49509 +        *      We have to use the direct interface because the gpio
49510 +        *      subsystem is not available at this point.
49511 +        */
49512 +       uup->port_init = 1;
49513 +       UBICOM32_GPIO_SET_PIN_HIGH(uup->tx_pin);
49514 +       UBICOM32_GPIO_SET_PIN_OUTPUT(uup->tx_pin);
49515 +       UBICOM32_GPIO_SET_PIN_INPUT(uup->rx_pin);
49516 +
49517 +       /*
49518 +        * Start the thread
49519 +        */
49520 +       thread_enable(uarttio_inst.regs->thread);
49521 +
49522 +       /*
49523 +        * Process options
49524 +        */
49525 +       if (options) {
49526 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
49527 +               if (ubi32_uarttio_set_baud(uup, baud)) {
49528 +                       baud = uup->uart->current_baud_rate;
49529 +               }
49530 +       }
49531 +
49532 +       return uart_set_options(&uup->port, co, baud, 'n', 8, 'n');
49533 +}
49534 +
49535 +/*
49536 + * ubi32_uarttio_console_putchar
49537 + */
49538 +static void ubi32_uarttio_console_putchar(struct uart_port *port, int ch)
49539 +{
49540 +       struct ubi32_uarttio_port *uup = port->private_data;
49541 +
49542 +       while (ubi32_uarttio_put_char(uup->uart, ch)) {
49543 +               cpu_relax();
49544 +       }
49545 +}
49546 +
49547 +/*
49548 + * ubi32_uarttio_console_write
49549 + *     Interrupts are disabled on entering
49550 + */
49551 +static void ubi32_uarttio_console_write(struct console *co, const char *s, unsigned int count)
49552 +{
49553 +       struct uart_port *port = &(uarttio_ports[co->index].port);
49554 +       unsigned long flags = 0;
49555 +
49556 +       spin_lock_irqsave(&port->lock, flags);
49557 +       uart_console_write(port, s, count, ubi32_uarttio_console_putchar);
49558 +       spin_unlock_irqrestore(&port->lock, flags);
49559 +}
49560 +
49561 +static struct console ubi32_uarttio_console = {
49562 +       .name           = UBI32_UARTTIO_NAME,
49563 +       .write          = ubi32_uarttio_console_write,
49564 +       .device         = uart_console_device,
49565 +       .setup          = ubi32_uarttio_console_setup,
49566 +       .flags          = CON_PRINTBUFFER,
49567 +       .index          = -1,
49568 +       .data           = &ubi32_uarttio_uart_driver,
49569 +};
49570 +
49571 +static int __init ubi32_uarttio_console_init(void)
49572 +{
49573 +       int res;
49574 +
49575 +       res = ubi32_uarttio_probe();
49576 +       if (res) {
49577 +               return res;
49578 +       }
49579 +
49580 +       register_console(&ubi32_uarttio_console);
49581 +       return 0;
49582 +}
49583 +console_initcall(ubi32_uarttio_console_init);
49584 +#endif /* CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE */
49585 +
49586 +/*
49587 + * ubi32_serial_suspend
49588 + */
49589 +static int ubi32_uarttio_suspend(struct platform_device *pdev, pm_message_t state)
49590 +{
49591 +       int i;
49592 +       for (i = 0; i < uarttio_nports; i++) {
49593 +               uart_suspend_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49594 +       }
49595 +
49596 +       return 0;
49597 +}
49598 +
49599 +/*
49600 + * ubi32_serial_resume
49601 + */
49602 +static int ubi32_uarttio_resume(struct platform_device *pdev)
49603 +{
49604 +       int i;
49605 +       for (i = 0; i < uarttio_nports; i++) {
49606 +               uart_resume_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49607 +       }
49608 +
49609 +       return 0;
49610 +}
49611 +
49612 +/*
49613 + * ubi32_uarttio_remove
49614 + */
49615 +static int __devexit ubi32_uarttio_remove(struct platform_device *pdev)
49616 +{
49617 +       ubi32_uarttio_cleanup();
49618 +
49619 +       uart_unregister_driver(&ubi32_uarttio_uart_driver);
49620 +
49621 +       return 0;
49622 +}
49623 +
49624 +static struct platform_driver ubi32_uarttio_platform_driver = {
49625 +       .remove         = __devexit_p(ubi32_uarttio_remove),
49626 +       .suspend        = ubi32_uarttio_suspend,
49627 +       .resume         = ubi32_uarttio_resume,
49628 +       .driver         = {
49629 +               .name   = DRIVER_NAME,
49630 +               .owner  = THIS_MODULE,
49631 +       },
49632 +};
49633 +
49634 +#ifndef MODULE
49635 +/*
49636 + * Called at boot time.
49637 + *
49638 + * uarttio=TIONAME,(baud,tx_pin,rx_pin,handshake[,cts_pin,rts_pin],...)
49639 + *     TIONAME is the name of the devtree node which describes the UARTTIO
49640 + *     pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]
49641 + *     handshake = 1 to enable handshaking, provide cts_pin, rts_pin (UNSUPPORTED)
49642 + *     handshake = 0 to disable handshaking, do not provide cts_pin, rts_pin
49643 + *     Ex: uarttio=UARTTIO,57600,7,6,0,9600,8,9,0
49644 + */
49645 +static int __init ubi32_uarttio_setup(char *str)
49646 +{
49647 +       strncpy(utio_ports_param, str, UBI32_UARTTIO_MAX_PARAM_LEN);
49648 +       utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN - 1] = 0;
49649 +       return 1;
49650 +}
49651 +__setup("uarttio=", ubi32_uarttio_setup);
49652 +#endif
49653 +
49654 +/*
49655 + * ubi32_uarttio_init
49656 + */
49657 +static int __init ubi32_uarttio_init(void)
49658 +{
49659 +       int ret;
49660 +       int i;
49661 +
49662 +       ret = ubi32_uarttio_probe();
49663 +       if (ret) {
49664 +               return ret;
49665 +       }
49666 +
49667 +       /*
49668 +        * Request the IRQ (do it here since many ports share the same IRQ)
49669 +        */
49670 +       ret = request_irq(uarttio_inst.irq, ubi32_uarttio_isr, IRQF_DISABLED, DRIVER_NAME, NULL);
49671 +       if (ret != 0) {
49672 +               printk(KERN_WARNING "Could not request IRQ %d\n", uarttio_inst.irq);
49673 +               goto fail;
49674 +       }
49675 +       uarttio_inst.irq_requested = 1;
49676 +
49677 +       /*
49678 +        * Register the UART driver and add the ports
49679 +        */
49680 +       ret = uart_register_driver(&ubi32_uarttio_uart_driver);
49681 +       if (ret != 0) {
49682 +               goto fail;
49683 +       }
49684 +       uarttio_inst.driver_registered = 1;
49685 +
49686 +       ret = ubi32_uarttio_add_ports();
49687 +       if (ret != 0) {
49688 +               ubi32_uarttio_cleanup();
49689 +               return ret;
49690 +       }
49691 +
49692 +       /*
49693 +        * Start the thread
49694 +        */
49695 +       thread_enable(uarttio_inst.regs->thread);
49696 +
49697 +       for (i = 0; i < uarttio_nports; i++) {
49698 +               pr_info("Serial: Ubicom32 uarttio #%d: tx:%d rx:%d baud:%d\n",
49699 +                       i, uarttio_ports[i].tx_pin, uarttio_ports[i].rx_pin,
49700 +                       uarttio_ports[i].uart->current_baud_rate);
49701 +       }
49702 +       pr_info("Serial: Ubicom32 uarttio started on thread:%d irq:%d\n", uarttio_inst.regs->thread, uarttio_inst.irq);
49703 +
49704 +       return ret;
49705 +
49706 +fail:
49707 +       ubi32_uarttio_cleanup();
49708 +       return ret;
49709 +}
49710 +module_init(ubi32_uarttio_init);
49711 +
49712 +/*
49713 + * ubi32_uarttio_exit
49714 + */
49715 +static void __exit ubi32_uarttio_exit(void)
49716 +{
49717 +       platform_driver_unregister(&ubi32_uarttio_platform_driver);
49718 +}
49719 +module_exit(ubi32_uarttio_exit);
49720 +
49721 +module_param_string(ports, utio_ports_param, sizeof(utio_ports_param), 0444);
49722 +MODULE_PARM_DESC(ports, "Sets the ports to allocate: ports=TIONAME,(baud,txpin,rxpin,handshake[,ctspin,rtspin],...)\n"
49723 +                       "     TIONAME is the name of the devtree node which describes the UARTTIO\n"
49724 +                       "     pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]\n"
49725 +                       "     handshake = 1 to enable handshaking, provide ctspin, rtspin (UNSUPPORTED)\n"
49726 +                       "     handshake = 0 to disable handshaking, do not provide ctspin, rtspin\n"
49727 +                       "     Ex: ports=UARTTIO,57600,7,6,0,9600,8,9,0\n");
49728 +MODULE_AUTHOR("Patrick Tjin <pat.tjin@ubicom.com>");
49729 +MODULE_DESCRIPTION("Ubicom serial virtual peripherial driver");
49730 +MODULE_LICENSE("GPL");
49731 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_UARTTIO_MAJOR);
49732 +MODULE_ALIAS("platform:" DRIVER_NAME);
49733 --- a/drivers/spi/Kconfig
49734 +++ b/drivers/spi/Kconfig
49735 @@ -196,6 +196,15 @@ config SPI_S3C24XX
49736         help
49737           SPI driver for Samsung S3C24XX series ARM SoCs
49738  
49739 +config SPI_UBICOM32_GPIO
49740 +       tristate "Ubicom32 SPI over GPIO"
49741 +       depends on SPI_MASTER && UBICOM32 && EXPERIMENTAL
49742 +       select SPI_BITBANG
49743 +       select HAS_DMA
49744 +       help
49745 +         SPI driver for the Ubicom32 architecture using
49746 +         GPIO lines to provide the SPI bus.
49747 +
49748  config SPI_S3C24XX_GPIO
49749         tristate "Samsung S3C24XX series SPI by GPIO"
49750         depends on ARCH_S3C2410 && EXPERIMENTAL
49751 --- a/drivers/spi/Makefile
49752 +++ b/drivers/spi/Makefile
49753 @@ -27,6 +27,7 @@ obj-$(CONFIG_SPI_ORION)                       += orion_spi.o
49754  obj-$(CONFIG_SPI_MPC52xx_PSC)          += mpc52xx_psc_spi.o
49755  obj-$(CONFIG_SPI_MPC83xx)              += spi_mpc83xx.o
49756  obj-$(CONFIG_SPI_S3C24XX_GPIO)         += spi_s3c24xx_gpio.o
49757 +obj-$(CONFIG_SPI_UBICOM32_GPIO)                += spi_ubicom32_gpio.o
49758  obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx.o
49759  obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
49760  obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
49761 --- /dev/null
49762 +++ b/drivers/spi/spi_ubicom32_gpio.c
49763 @@ -0,0 +1,267 @@
49764 +/*
49765 + * drivers/spi_spi_ubicom32_gpio.c
49766 + *     Ubicom32 GPIO based SPI driver
49767 + *
49768 + * (C) Copyright 2009, Ubicom, Inc.
49769 + *
49770 + * This file is part of the Ubicom32 Linux Kernel Port.
49771 + *
49772 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
49773 + * it and/or modify it under the terms of the GNU General Public License
49774 + * as published by the Free Software Foundation, either version 2 of the
49775 + * License, or (at your option) any later version.
49776 + *
49777 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
49778 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
49779 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
49780 + * the GNU General Public License for more details.
49781 + *
49782 + * You should have received a copy of the GNU General Public License
49783 + * along with the Ubicom32 Linux Kernel Port.  If not,
49784 + * see <http://www.gnu.org/licenses/>.
49785 + *
49786 + * Ubicom32 implementation derived from (with many thanks):
49787 + *   arch/m68knommu
49788 + *   arch/blackfin
49789 + *   arch/parisc
49790 + */
49791 +#include <linux/kernel.h>
49792 +#include <linux/init.h>
49793 +#include <linux/delay.h>
49794 +#include <linux/spinlock.h>
49795 +#include <linux/workqueue.h>
49796 +#include <linux/platform_device.h>
49797 +
49798 +#include <linux/spi/spi.h>
49799 +#include <linux/spi/spi_bitbang.h>
49800 +
49801 +#include <linux/gpio.h>
49802 +
49803 +#include <asm/ubicom32-spi-gpio.h>
49804 +
49805 +#define DRIVER_NAME "ubicom32-spi-gpio"
49806 +
49807 +struct ubicom32_spi_gpio {
49808 +       struct spi_bitbang                       bitbang;
49809 +
49810 +       struct ubicom32_spi_gpio_platform_data  *pdata;
49811 +
49812 +       struct platform_device                  *dev;
49813 +};
49814 +
49815 +/*
49816 + * The following 4 functions are used by EXPAND_BITBANG_TXRX to bitbang the data out.
49817 + */
49818 +static inline void setsck(struct spi_device *dev, int on)
49819 +{
49820 +       struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
49821 +       gpio_set_value(usg->pdata->pin_clk, on ? 1 : 0);
49822 +}
49823 +
49824 +static inline void setmosi(struct spi_device *dev, int on)
49825 +{
49826 +       struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
49827 +       gpio_set_value(usg->pdata->pin_mosi, on ? 1 : 0);
49828 +}
49829 +
49830 +static inline u32 getmiso(struct spi_device *dev)
49831 +{
49832 +       struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
49833 +       return gpio_get_value(usg->pdata->pin_miso) ? 1 : 0;
49834 +}
49835 +
49836 +#define spidelay(x) ndelay(x)
49837 +
49838 +#define        EXPAND_BITBANG_TXRX
49839 +#include <linux/spi/spi_bitbang.h>
49840 +
49841 +/*
49842 + * ubicom32_spi_gpio_txrx_mode0
49843 + */
49844 +static u32 ubicom32_spi_gpio_txrx_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49845 +{
49846 +       return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
49847 +}
49848 +
49849 +/*
49850 + * ubicom32_spi_gpio_txrx_mode1
49851 + */
49852 +static u32 ubicom32_spi_gpio_txrx_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49853 +{
49854 +       return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
49855 +}
49856 +
49857 +/*
49858 + * ubicom32_spi_gpio_txrx_mode2
49859 + */
49860 +static u32 ubicom32_spi_gpio_txrx_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49861 +{
49862 +       return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
49863 +}
49864 +
49865 +/*
49866 + * ubicom32_spi_gpio_txrx_mode3
49867 + */
49868 +static u32 ubicom32_spi_gpio_txrx_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49869 +{
49870 +       return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
49871 +}
49872 +
49873 +/*
49874 + * ubicom32_spi_gpio_chipselect
49875 + */
49876 +static void ubicom32_spi_gpio_chipselect(struct spi_device *dev, int value)
49877 +{
49878 +       struct ubicom32_spi_gpio_controller_data *cd = (struct ubicom32_spi_gpio_controller_data *)dev->controller_data;
49879 +       unsigned int cs_polarity = dev->mode & SPI_CS_HIGH ? 1 : 0;
49880 +
49881 +       if (value == BITBANG_CS_ACTIVE) {
49882 +               gpio_set_value(cd->pin_cs, cs_polarity);
49883 +               return;
49884 +       }
49885 +       gpio_set_value(cd->pin_cs, !cs_polarity);
49886 +}
49887 +
49888 +/*
49889 + * ubicom32_spi_gpio_probe
49890 + */
49891 +static int ubicom32_spi_gpio_probe(struct platform_device *dev)
49892 +{
49893 +       struct ubicom32_spi_gpio_platform_data *pdata;
49894 +       struct spi_master *master;
49895 +       struct ubicom32_spi_gpio *usg;
49896 +       int ret;
49897 +
49898 +       master = spi_alloc_master(&dev->dev, sizeof(struct ubicom32_spi_gpio));
49899 +       if (master == NULL) {
49900 +               dev_err(&dev->dev, "failed to allocate spi master\n");
49901 +               ret = -ENOMEM;
49902 +               goto err;
49903 +       }
49904 +
49905 +       usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(master);
49906 +
49907 +       platform_set_drvdata(dev, usg);
49908 +
49909 +       /*
49910 +        * Copy in the platform data
49911 +        */
49912 +       pdata = dev->dev.platform_data;
49913 +       usg->pdata = dev->dev.platform_data;
49914 +
49915 +       /*
49916 +        * Request the GPIO lines
49917 +        */
49918 +       ret = gpio_request(pdata->pin_mosi, "spi-mosi");
49919 +       if (ret) {
49920 +               dev_err(&dev->dev, "Failed to allocate spi-mosi GPIO\n");
49921 +               goto err;
49922 +       }
49923 +
49924 +       ret = gpio_request(pdata->pin_miso, "spi-miso");
49925 +       if (ret) {
49926 +               dev_err(&dev->dev, "Failed to allocate spi-miso GPIO\n");
49927 +               goto err_nomiso;
49928 +       }
49929 +
49930 +       ret = gpio_request(pdata->pin_clk, "spi-clk");
49931 +       if (ret) {
49932 +               dev_err(&dev->dev, "Failed to allocate spi-clk GPIO\n");
49933 +               goto err_noclk;
49934 +       }
49935 +
49936 +       /*
49937 +        * Setup spi-bitbang adaptor
49938 +        */
49939 +       usg->bitbang.flags |= SPI_CS_HIGH;
49940 +       usg->bitbang.master = spi_master_get(master);
49941 +       usg->bitbang.master->bus_num = pdata->bus_num;
49942 +       usg->bitbang.master->num_chipselect = pdata->num_chipselect;
49943 +       usg->bitbang.chipselect = ubicom32_spi_gpio_chipselect;
49944 +
49945 +       usg->bitbang.txrx_word[SPI_MODE_0] = ubicom32_spi_gpio_txrx_mode0;
49946 +       usg->bitbang.txrx_word[SPI_MODE_1] = ubicom32_spi_gpio_txrx_mode1;
49947 +       usg->bitbang.txrx_word[SPI_MODE_2] = ubicom32_spi_gpio_txrx_mode2;
49948 +       usg->bitbang.txrx_word[SPI_MODE_3] = ubicom32_spi_gpio_txrx_mode3;
49949 +
49950 +       /*
49951 +        * Setup the GPIO pins
49952 +        */
49953 +       gpio_direction_output(pdata->pin_clk, pdata->clk_default);
49954 +       gpio_direction_output(pdata->pin_mosi, 0);
49955 +       gpio_direction_input(pdata->pin_miso);
49956 +
49957 +       /*
49958 +        * Ready to go
49959 +        */
49960 +       ret = spi_bitbang_start(&usg->bitbang);
49961 +       if (ret) {
49962 +               goto err_no_bitbang;
49963 +       }
49964 +
49965 +       return 0;
49966 +
49967 +err_no_bitbang:
49968 +       spi_master_put(usg->bitbang.master);
49969 +
49970 +       gpio_free(pdata->pin_clk);
49971 +
49972 +err_noclk:
49973 +       gpio_free(pdata->pin_miso);
49974 +
49975 +err_nomiso:
49976 +       gpio_free(pdata->pin_mosi);
49977 +
49978 +err:
49979 +       return ret;
49980 +}
49981 +
49982 +/*
49983 + * ubicom32_spi_gpio_remove
49984 + */
49985 +static int ubicom32_spi_gpio_remove(struct platform_device *dev)
49986 +{
49987 +       struct ubicom32_spi_gpio *sp = platform_get_drvdata(dev);
49988 +
49989 +       spi_bitbang_stop(&sp->bitbang);
49990 +       spi_master_put(sp->bitbang.master);
49991 +
49992 +       return 0;
49993 +}
49994 +
49995 +/*
49996 + * Work with hotplug and coldplug
49997 + */
49998 +MODULE_ALIAS("platform:ubicom32_spi_gpio");
49999 +
50000 +static struct platform_driver ubicom32_spi_gpio_drv = {
50001 +       .probe          = ubicom32_spi_gpio_probe,
50002 +        .remove                = ubicom32_spi_gpio_remove,
50003 +        .driver                = {
50004 +               .name   = DRIVER_NAME,
50005 +               .owner  = THIS_MODULE,
50006 +        },
50007 +};
50008 +
50009 +/*
50010 + * ubicom32_spi_gpio_init
50011 + */
50012 +static int __init ubicom32_spi_gpio_init(void)
50013 +{
50014 +        return platform_driver_register(&ubicom32_spi_gpio_drv);
50015 +}
50016 +
50017 +/*
50018 + * ubicom32_spi_gpio_exit
50019 + */
50020 +static void __exit ubicom32_spi_gpio_exit(void)
50021 +{
50022 +        platform_driver_unregister(&ubicom32_spi_gpio_drv);
50023 +}
50024 +
50025 +module_init(ubicom32_spi_gpio_init);
50026 +module_exit(ubicom32_spi_gpio_exit);
50027 +
50028 +MODULE_DESCRIPTION("Ubicom32 SPI-GPIO Driver");
50029 +MODULE_AUTHOR("Pat Tjin, <@ubicom.com>");
50030 +MODULE_LICENSE("GPL");
50031 --- a/drivers/uio/Kconfig
50032 +++ b/drivers/uio/Kconfig
50033 @@ -89,4 +89,12 @@ config UIO_SERCOS3
50034  
50035           If you compile this as a module, it will be called uio_sercos3.
50036  
50037 +config UIO_UBICOM32RING
50038 +       tristate "Ubicom32 Ring Buffer driver"
50039 +       default n
50040 +       help
50041 +         Userspace I/O interface for a Ubicom32 Ring Buffer.
50042 +
50043 +         If you compile this as a module, it will be called uio_ubicom32ring
50044 +
50045  endif
50046 --- a/drivers/uio/Makefile
50047 +++ b/drivers/uio/Makefile
50048 @@ -5,3 +5,4 @@ obj-$(CONFIG_UIO_PDRV_GENIRQ)   += uio_pdr
50049  obj-$(CONFIG_UIO_SMX)  += uio_smx.o
50050  obj-$(CONFIG_UIO_AEC)  += uio_aec.o
50051  obj-$(CONFIG_UIO_SERCOS3)      += uio_sercos3.o
50052 +obj-$(CONFIG_UIO_UBICOM32RING) += uio_ubicom32ring.o
50053 --- /dev/null
50054 +++ b/drivers/uio/uio_ubicom32ring.c
50055 @@ -0,0 +1,288 @@
50056 +/*
50057 + * drivers/uio/uio_ubicom32ring.c
50058 + *
50059 + * Userspace I/O platform driver for Ubicom32 ring buffers
50060 + *
50061 + * (C) Copyright 2009, Ubicom, Inc.
50062 + *
50063 + * This file is part of the Ubicom32 Linux Kernel Port.
50064 + *
50065 + * Based on uio_ubicom32ring.c by Magnus Damm
50066 + *
50067 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
50068 + * it and/or modify it under the terms of the GNU General Public License
50069 + * as published by the Free Software Foundation, either version 2 of the
50070 + * License, or (at your option) any later version.
50071 + *
50072 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
50073 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
50074 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
50075 + * the GNU General Public License for more details.
50076 + *
50077 + * You should have received a copy of the GNU General Public License
50078 + * along with the Ubicom32 Linux Kernel Port.  If not,
50079 + * see <http://www.gnu.org/licenses/>.
50080 + */
50081 +
50082 +#include <linux/platform_device.h>
50083 +#include <linux/uio_driver.h>
50084 +#include <linux/spinlock.h>
50085 +#include <linux/bitops.h>
50086 +#include <linux/interrupt.h>
50087 +#include <linux/stringify.h>
50088 +
50089 +#include <asm/ip5000.h>
50090 +#include <asm/ubicom32ring.h>
50091 +
50092 +#define DRIVER_NAME "uio_ubicom32ring"
50093 +
50094 +struct uio_ubicom32ring_data {
50095 +       struct uio_info                 *uioinfo;
50096 +
50097 +       struct uio_ubicom32ring_regs    *regs;
50098 +
50099 +       /*
50100 +        * IRQ used to kick the ring buffer
50101 +        */
50102 +       int                             irq_tx;
50103 +       int                             irq_rx;
50104 +
50105 +       spinlock_t                      lock;
50106 +
50107 +       unsigned long                   flags;
50108 +
50109 +       char                            name[0];
50110 +};
50111 +
50112 +static irqreturn_t uio_ubicom32ring_handler(int irq, struct uio_info *dev_info)
50113 +{
50114 +       struct uio_ubicom32ring_data *priv = dev_info->priv;
50115 +
50116 +       /* Just disable the interrupt in the interrupt controller, and
50117 +        * remember the state so we can allow user space to enable it later.
50118 +        */
50119 +
50120 +       if (!test_and_set_bit(0, &priv->flags))
50121 +               disable_irq_nosync(irq);
50122 +
50123 +       return IRQ_HANDLED;
50124 +}
50125 +
50126 +static int uio_ubicom32ring_irqcontrol(struct uio_info *dev_info, s32 irq_on)
50127 +{
50128 +       struct uio_ubicom32ring_data *priv = dev_info->priv;
50129 +       unsigned long flags;
50130 +
50131 +       /* Allow user space to enable and disable the interrupt
50132 +        * in the interrupt controller, but keep track of the
50133 +        * state to prevent per-irq depth damage.
50134 +        *
50135 +        * Serialize this operation to support multiple tasks.
50136 +        */
50137 +
50138 +       spin_lock_irqsave(&priv->lock, flags);
50139 +
50140 +       if (irq_on & 2) {
50141 +               /*
50142 +                * Kick the ring buffer (if we can)
50143 +                */
50144 +               if (priv->irq_tx != 0xFF) {
50145 +                       ubicom32_set_interrupt(priv->irq_tx);
50146 +               }
50147 +       }
50148 +
50149 +       if (priv->irq_rx != 0xFF) {
50150 +               if (irq_on & 1) {
50151 +                       if (test_and_clear_bit(0, &priv->flags))
50152 +                               enable_irq(dev_info->irq);
50153 +               } else {
50154 +                       if (!test_and_set_bit(0, &priv->flags))
50155 +                               disable_irq(dev_info->irq);
50156 +               }
50157 +       }
50158 +
50159 +       spin_unlock_irqrestore(&priv->lock, flags);
50160 +
50161 +       return 0;
50162 +}
50163 +
50164 +static int uio_ubicom32ring_probe(struct platform_device *pdev)
50165 +{
50166 +       struct uio_info *uioinfo;
50167 +       struct uio_mem *uiomem;
50168 +       struct uio_ubicom32ring_data *priv;
50169 +       struct uio_ubicom32ring_regs *regs;
50170 +       struct resource *mem_resource;
50171 +       struct resource *irqtx_resource;
50172 +       struct resource *irqrx_resource;
50173 +       int ret = -EINVAL;
50174 +       int i;
50175 +
50176 +       uioinfo = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
50177 +       if (!uioinfo) {
50178 +               dev_err(&pdev->dev, "unable to kmalloc\n");
50179 +               return -ENOMEM;
50180 +       }
50181 +
50182 +       /*
50183 +        * Allocate private data with some string space after
50184 +        */
50185 +       i = sizeof(DRIVER_NAME) + 1;
50186 +       i += pdev->dev.platform_data ? strlen(pdev->dev.platform_data) : 0;
50187 +       priv = kzalloc(sizeof(struct uio_ubicom32ring_data) + i, GFP_KERNEL);
50188 +       if (!priv) {
50189 +               dev_err(&pdev->dev, "unable to kmalloc\n");
50190 +               kfree(uioinfo);
50191 +               return -ENOMEM;
50192 +       }
50193 +
50194 +       strcpy(priv->name, DRIVER_NAME ":");
50195 +       if (pdev->dev.platform_data) {
50196 +               strcat(priv->name, pdev->dev.platform_data);
50197 +       }
50198 +       uioinfo->priv = priv;
50199 +       uioinfo->name = priv->name;
50200 +       uioinfo->version = "0.1";
50201 +
50202 +       priv->uioinfo = uioinfo;
50203 +       spin_lock_init(&priv->lock);
50204 +       priv->flags = 0; /* interrupt is enabled to begin with */
50205 +
50206 +       /*
50207 +        * Get our resources, the IRQ_TX and IRQ_RX are optional.
50208 +        */
50209 +       priv->irq_tx = 0xFF;
50210 +       irqtx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
50211 +       if (irqtx_resource) {
50212 +               priv->irq_tx = irqtx_resource->start;
50213 +       }
50214 +
50215 +       uioinfo->irq = -1;
50216 +       priv->irq_rx = 0xFF;
50217 +       irqrx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
50218 +       if (irqrx_resource) {
50219 +               priv->irq_rx = irqrx_resource->start;
50220 +               uioinfo->irq = priv->irq_rx;
50221 +               uioinfo->handler = uio_ubicom32ring_handler;
50222 +       }
50223 +
50224 +       mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
50225 +       if (!mem_resource || !mem_resource->start) {
50226 +               dev_err(&pdev->dev, "No valid memory resource found\n");
50227 +               ret = -ENODEV;
50228 +               goto fail;
50229 +       }
50230 +       regs = (struct uio_ubicom32ring_regs *)mem_resource->start;
50231 +       priv->regs = regs;
50232 +
50233 +       if (regs->version != UIO_UBICOM32RING_REG_VERSION) {
50234 +               dev_err(&pdev->dev, "version %d not supported\n", regs->version);
50235 +               ret = -ENODEV;
50236 +               goto fail;
50237 +       }
50238 +
50239 +       /*
50240 +        * First range is the shared register space, if we have any
50241 +        */
50242 +       uiomem = &uioinfo->mem[0];
50243 +       if (regs->regs_size) {
50244 +               uiomem->memtype = UIO_MEM_PHYS;
50245 +               uiomem->addr = (u32_t)regs->regs;
50246 +               uiomem->size = regs->regs_size;
50247 +               ++uiomem;
50248 +               dev_info(&pdev->dev, "regs:%p (%u) / rings: %d found\n", regs->regs, regs->regs_size, regs->num_rings);
50249 +       } else {
50250 +               dev_info(&pdev->dev, "rings: %d found\n", regs->num_rings);
50251 +       }
50252 +
50253 +       /*
50254 +        * The rest of the range correspond to the rings
50255 +        */
50256 +       for (i = 0; i < regs->num_rings; i++) {
50257 +               dev_info(&pdev->dev, "\t%d: entries:%d ring:%p\n",
50258 +                        i, regs->rings[i]->entries, &(regs->rings[i]->ring));
50259 +               if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
50260 +                       dev_warn(&pdev->dev, "device has more than "
50261 +                                       __stringify(MAX_UIO_MAPS)
50262 +                                       " I/O memory resources.\n");
50263 +                       break;
50264 +               }
50265 +
50266 +               uiomem->memtype = UIO_MEM_PHYS;
50267 +               uiomem->addr = (u32_t)&(regs->rings[i]->head);
50268 +               uiomem->size = (regs->rings[i]->entries * sizeof(u32_t)) +
50269 +                               sizeof(struct uio_ubicom32ring_desc);
50270 +               ++uiomem;
50271 +       }
50272 +
50273 +       while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
50274 +               uiomem->size = 0;
50275 +               ++uiomem;
50276 +       }
50277 +
50278 +       /* This driver requires no hardware specific kernel code to handle
50279 +        * interrupts. Instead, the interrupt handler simply disables the
50280 +        * interrupt in the interrupt controller. User space is responsible
50281 +        * for performing hardware specific acknowledge and re-enabling of
50282 +        * the interrupt in the interrupt controller.
50283 +        *
50284 +        * Interrupt sharing is not supported.
50285 +        */
50286 +       uioinfo->irq_flags = IRQF_DISABLED;
50287 +       uioinfo->irqcontrol = uio_ubicom32ring_irqcontrol;
50288 +
50289 +       ret = uio_register_device(&pdev->dev, priv->uioinfo);
50290 +       if (ret) {
50291 +               dev_err(&pdev->dev, "unable to register uio device\n");
50292 +               goto fail;
50293 +       }
50294 +
50295 +       platform_set_drvdata(pdev, priv);
50296 +
50297 +       dev_info(&pdev->dev, "'%s' using irq: rx %d tx %d, regs %p\n",
50298 +                priv->name, priv->irq_rx, priv->irq_tx, priv->regs);
50299 +
50300 +       return 0;
50301 +
50302 +fail:
50303 +       kfree(uioinfo);
50304 +       kfree(priv);
50305 +       return ret;
50306 +}
50307 +
50308 +static int uio_ubicom32ring_remove(struct platform_device *pdev)
50309 +{
50310 +       struct uio_ubicom32ring_data *priv = platform_get_drvdata(pdev);
50311 +
50312 +       uio_unregister_device(priv->uioinfo);
50313 +       kfree(priv->uioinfo);
50314 +       kfree(priv);
50315 +       return 0;
50316 +}
50317 +
50318 +static struct platform_driver uio_ubicom32ring = {
50319 +       .probe = uio_ubicom32ring_probe,
50320 +       .remove = uio_ubicom32ring_remove,
50321 +       .driver = {
50322 +               .name = DRIVER_NAME,
50323 +               .owner = THIS_MODULE,
50324 +       },
50325 +};
50326 +
50327 +static int __init uio_ubicom32ring_init(void)
50328 +{
50329 +       return platform_driver_register(&uio_ubicom32ring);
50330 +}
50331 +
50332 +static void __exit uio_ubicom32ring_exit(void)
50333 +{
50334 +       platform_driver_unregister(&uio_ubicom32ring);
50335 +}
50336 +
50337 +module_init(uio_ubicom32ring_init);
50338 +module_exit(uio_ubicom32ring_exit);
50339 +
50340 +MODULE_AUTHOR("Patrick Tjin");
50341 +MODULE_DESCRIPTION("Userspace I/O driver for Ubicom32 ring buffers");
50342 +MODULE_LICENSE("GPL v2");
50343 +MODULE_ALIAS("platform:" DRIVER_NAME);
50344 --- a/drivers/usb/gadget/epautoconf.c
50345 +++ b/drivers/usb/gadget/epautoconf.c
50346 @@ -154,6 +154,10 @@ ep_matches (
50347                         /* configure your hardware with enough buffering!! */
50348                 }
50349                 break;
50350 +
50351 +       case USB_ENDPOINT_XFER_BULK:
50352 +               if ((gadget->is_dualspeed) && (ep->maxpacket < 512))
50353 +                       return 0;
50354         }
50355  
50356         /* MATCH!! */
50357 --- a/drivers/usb/Kconfig
50358 +++ b/drivers/usb/Kconfig
50359 @@ -22,6 +22,7 @@ config USB_ARCH_HAS_HCD
50360         default y if PCMCIA && !M32R                    # sl811_cs
50361         default y if ARM                                # SL-811
50362         default y if SUPERH                             # r8a66597-hcd
50363 +       default y if UBICOM32                           # Ubicom's onchip USB Duial role controller
50364         default PCI
50365  
50366  # many non-PCI SOC chips embed OHCI
50367 --- a/drivers/usb/musb/Kconfig
50368 +++ b/drivers/usb/musb/Kconfig
50369 @@ -12,7 +12,7 @@ config USB_MUSB_HDRC
50370         depends on !SUPERH
50371         select TWL4030_USB if MACH_OMAP_3430SDP
50372         select USB_OTG_UTILS
50373 -       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
50374 +       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, Ubicom, ...)'
50375         help
50376           Say Y here if your system has a dual role high speed USB
50377           controller based on the Mentor Graphics silicon IP.  Then
50378 --- a/drivers/usb/musb/Makefile
50379 +++ b/drivers/usb/musb/Makefile
50380 @@ -30,6 +30,10 @@ ifeq ($(CONFIG_BF52x),y)
50381         musb_hdrc-objs  += blackfin.o
50382  endif
50383  
50384 +ifeq ($(CONFIG_UBICOM32), y)
50385 +        musb_hdrc-objs  += ubi32_usb.o
50386 +endif
50387 +
50388  ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
50389         musb_hdrc-objs          += musb_gadget_ep0.o musb_gadget.o
50390  endif
50391 --- a/drivers/usb/musb/musb_core.c
50392 +++ b/drivers/usb/musb/musb_core.c
50393 @@ -105,6 +105,13 @@
50394  #include <asm/mach-types.h>
50395  #endif
50396  
50397 +#ifdef CONFIG_UBICOM32
50398 +#include <asm/ip5000.h>
50399 +#include <asm/ubicom32-tio.h>
50400 +extern void ubi32_usb_init(void);
50401 +extern void ubi32_usb_int_clr(void);
50402 +#endif
50403 +
50404  #include "musb_core.h"
50405  
50406  
50407 @@ -147,8 +154,37 @@ static inline struct musb *dev_to_musb(s
50408  }
50409  
50410  /*-------------------------------------------------------------------------*/
50411 +#if defined(CONFIG_UBICOM32)
50412 +
50413 +/*
50414 + * Load an endpoint's FIFO
50415 + */
50416 +void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 wCount, const u8 *pSource)
50417 +{
50418 +       void __iomem *fifo = hw_ep->fifo;
50419 +
50420 +       prefetch((u8 *)pSource);
50421 +
50422 +       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50423 +                       'T', hw_ep->epnum, fifo, wCount, pSource);
50424 +
50425 +       usb_tio_write_fifo((u32)fifo, (u32)pSource, wCount);
50426 +
50427 +}
50428 +
50429 +/*
50430 + * Unload an endpoint's FIFO
50431 + */
50432 +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 wCount, u8 *pDest)
50433 +{
50434 +
50435 +       void __iomem *fifo = hw_ep->fifo;
50436 +       DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50437 +                       'R', hw_ep->epnum, fifo, wCount, pDest);
50438 +       usb_tio_read_fifo((u32)fifo, (u32)pDest, wCount);
50439 +}
50440  
50441 -#if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50442 +#elif !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50443  
50444  /*
50445   * Load an endpoint's FIFO
50446 @@ -227,8 +263,7 @@ void musb_read_fifo(struct musb_hw_ep *h
50447                 readsb(fifo, dst, len);
50448         }
50449  }
50450 -
50451 -#endif /* normal PIO */
50452 +#endif /* !T6010 && !BLACKFIN */
50453  
50454  
50455  /*-------------------------------------------------------------------------*/
50456 @@ -874,12 +909,19 @@ void musb_start(struct musb *musb)
50457         musb_writeb(regs, MUSB_TESTMODE, 0);
50458  
50459         /* put into basic highspeed mode and start session */
50460 +#ifndef CONFIG_UBICOM32
50461         musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
50462                                                 | MUSB_POWER_SOFTCONN
50463                                                 | MUSB_POWER_HSENAB
50464                                                 /* ENSUSPEND wedges tusb */
50465                                                 /* | MUSB_POWER_ENSUSPEND */
50466                                                 );
50467 +#else
50468 +       musb_writeb(regs, MUSB_POWER,  MUSB_POWER_HSENAB
50469 +                                               /* ENSUSPEND wedges tusb */
50470 +                                               /* | MUSB_POWER_ENSUSPEND */
50471 +                                               );
50472 +#endif
50473  
50474         musb->is_active = 0;
50475         devctl = musb_readb(regs, MUSB_DEVCTL);
50476 @@ -1081,6 +1123,7 @@ static struct fifo_cfg __initdata mode_4
50477  };
50478  
50479  
50480 +#ifndef CONFIG_UBICOM32
50481  /*
50482   * configure a fifo; for non-shared endpoints, this may be called
50483   * once for a tx fifo and once for an rx fifo.
50484 @@ -1240,7 +1283,7 @@ static int __init ep_config_from_table(s
50485  
50486         return 0;
50487  }
50488 -
50489 +#endif /* CONFIG_UBICOM32 */
50490  
50491  /*
50492   * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
50493 @@ -1256,6 +1299,11 @@ static int __init ep_config_from_hw(stru
50494         DBG(2, "<== static silicon ep config\n");
50495  
50496         /* FIXME pick up ep0 maxpacket size */
50497 +#ifdef CONFIG_UBICOM32
50498 +       /* set ep0 to shared_fifo, otherwise urb will be put to out_qh but ep0_irq try to get the urb from in_qh*/
50499 +       hw_ep = musb->endpoints;
50500 +       hw_ep->is_shared_fifo = true;
50501 +#endif
50502  
50503         for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
50504                 musb_ep_select(mbase, epnum);
50505 @@ -1276,14 +1324,27 @@ static int __init ep_config_from_hw(stru
50506                 /* REVISIT:  this algorithm is lazy, we should at least
50507                  * try to pick a double buffered endpoint.
50508                  */
50509 +#ifndef CONFIG_UBICOM32
50510                 if (musb->bulk_ep)
50511                         continue;
50512                 musb->bulk_ep = hw_ep;
50513 +#else
50514 +               if ((musb->bulk_ep_in) && (musb->bulk_ep_out))
50515 +                       continue;
50516 +               /* Save theEP with 1024 Bytes FIFO for ISO */
50517 +               if(hw_ep->max_packet_sz_tx == 512) {
50518 +                       if (!musb->bulk_ep_in) {
50519 +                               musb->bulk_ep_in = hw_ep;
50520 +                       } else if (!musb->bulk_ep_out) {
50521 +                               musb->bulk_ep_out = hw_ep;
50522 +                       }
50523 +               }
50524 +#endif /* CONFIG_UBICOM32 */
50525  #endif
50526         }
50527  
50528  #ifdef CONFIG_USB_MUSB_HDRC_HCD
50529 -       if (!musb->bulk_ep) {
50530 +       if ((!musb->bulk_ep_in) || (!musb->bulk_ep_out)) {
50531                 pr_debug("%s: missing bulk\n", musb_driver_name);
50532                 return -EINVAL;
50533         }
50534 @@ -1393,12 +1454,16 @@ static int __init musb_core_init(u16 mus
50535         musb->epmask = 1;
50536  
50537         if (reg & MUSB_CONFIGDATA_DYNFIFO) {
50538 +#ifndef CONFIG_UBICOM32
50539                 if (musb->config->dyn_fifo)
50540                         status = ep_config_from_table(musb);
50541 -               else {
50542 +               else
50543 +#endif
50544 +               {
50545                         ERR("reconfigure software for Dynamic FIFOs\n");
50546                         status = -ENODEV;
50547                 }
50548 +
50549         } else {
50550                 if (!musb->config->dyn_fifo)
50551                         status = ep_config_from_hw(musb);
50552 @@ -1462,8 +1527,8 @@ static int __init musb_core_init(u16 mus
50553  
50554  /*-------------------------------------------------------------------------*/
50555  
50556 -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
50557 -
50558 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_UBICOM32)
50559 +static u32_t musb_int_count = 0;
50560  static irqreturn_t generic_interrupt(int irq, void *__hci)
50561  {
50562         unsigned long   flags;
50563 @@ -1472,10 +1537,17 @@ static irqreturn_t generic_interrupt(int
50564  
50565         spin_lock_irqsave(&musb->lock, flags);
50566  
50567 +#ifndef CONFIG_UBICOM32
50568         musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
50569         musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
50570         musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
50571 +#else
50572 +       musb_read_int_status(&musb->int_usb, &musb->int_tx, &musb->int_rx);
50573 +       //ubi32_usb_int_clr();
50574 +       musb_int_count++;
50575 +#endif
50576  
50577 +       DBG(4, "usb %x, tx %x, rx %x", musb->int_usb, musb->int_tx, musb->int_rx);
50578         if (musb->int_usb || musb->int_tx || musb->int_rx)
50579                 retval = musb_interrupt(musb);
50580  
50581 @@ -2210,6 +2282,10 @@ static struct platform_driver musb_drive
50582  
50583  static int __init musb_init(void)
50584  {
50585 +#ifdef CONFIG_UBICOM32
50586 +       ubi32_usb_init();
50587 +#endif
50588 +
50589  #ifdef CONFIG_USB_MUSB_HDRC_HCD
50590         if (usb_disabled())
50591                 return 0;
50592 --- a/drivers/usb/musb/musb_core.h
50593 +++ b/drivers/usb/musb/musb_core.h
50594 @@ -326,7 +326,12 @@ struct musb {
50595          * queue until it completes or NAKs too much; then we try the next
50596          * endpoint.
50597          */
50598 +#ifdef CONFIG_UBICOM32
50599 +       struct musb_hw_ep       *bulk_ep_in;
50600 +       struct musb_hw_ep       *bulk_ep_out;
50601 +#else
50602         struct musb_hw_ep       *bulk_ep;
50603 +#endif
50604  
50605         struct list_head        control;        /* of musb_qh */
50606         struct list_head        in_bulk;        /* of musb_qh */
50607 --- a/drivers/usb/musb/musb_gadget.c
50608 +++ b/drivers/usb/musb/musb_gadget.c
50609 @@ -432,7 +432,7 @@ void musb_g_tx(struct musb *musb, u8 epn
50610                  * probably rates reporting as a host error
50611                  */
50612                 if (csr & MUSB_TXCSR_P_SENTSTALL) {
50613 -                       csr |= MUSB_TXCSR_P_WZC_BITS;
50614 +                       csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50615                         csr &= ~MUSB_TXCSR_P_SENTSTALL;
50616                         musb_writew(epio, MUSB_TXCSR, csr);
50617                         if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
50618 @@ -448,7 +448,7 @@ void musb_g_tx(struct musb *musb, u8 epn
50619  
50620                 if (csr & MUSB_TXCSR_P_UNDERRUN) {
50621                         /* we NAKed, no big deal ... little reason to care */
50622 -                       csr |= MUSB_TXCSR_P_WZC_BITS;
50623 +                       csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50624                         csr &= ~(MUSB_TXCSR_P_UNDERRUN
50625                                         | MUSB_TXCSR_TXPKTRDY);
50626                         musb_writew(epio, MUSB_TXCSR, csr);
50627 @@ -584,10 +584,16 @@ static void rxstate(struct musb *musb, s
50628         u16                     csr = 0;
50629         const u8                epnum = req->epnum;
50630         struct usb_request      *request = &req->request;
50631 -       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
50632 +       struct musb_ep          *musb_ep = NULL;
50633         void __iomem            *epio = musb->endpoints[epnum].regs;
50634 -       unsigned                fifo_count = 0;
50635 -       u16                     len = musb_ep->packet_sz;
50636 +       u16                     fifo_count = 0;
50637 +       u16                     len = 0;
50638 +
50639 +       if (musb->endpoints[epnum].is_shared_fifo)
50640 +               musb_ep = &musb->endpoints[epnum].ep_in;
50641 +       else
50642 +               musb_ep = &musb->endpoints[epnum].ep_out;
50643 +       len =  musb_ep->packet_sz;
50644  
50645         csr = musb_readw(epio, MUSB_RXCSR);
50646  
50647 @@ -726,7 +732,7 @@ static void rxstate(struct musb *musb, s
50648                          */
50649  
50650                         /* ack the read! */
50651 -                       csr |= MUSB_RXCSR_P_WZC_BITS;
50652 +                       csr &= ~MUSB_RXCSR_P_WZC_BITS;
50653                         csr &= ~MUSB_RXCSR_RXPKTRDY;
50654                         musb_writew(epio, MUSB_RXCSR, csr);
50655                 }
50656 @@ -745,10 +751,15 @@ void musb_g_rx(struct musb *musb, u8 epn
50657         u16                     csr;
50658         struct usb_request      *request;
50659         void __iomem            *mbase = musb->mregs;
50660 -       struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
50661 +       struct musb_ep          *musb_ep = NULL;
50662         void __iomem            *epio = musb->endpoints[epnum].regs;
50663         struct dma_channel      *dma;
50664  
50665 +       if (musb->endpoints[epnum].is_shared_fifo)
50666 +               musb_ep = &musb->endpoints[epnum].ep_in;
50667 +       else
50668 +               musb_ep = &musb->endpoints[epnum].ep_out;
50669 +
50670         musb_ep_select(mbase, epnum);
50671  
50672         request = next_request(musb_ep);
50673 @@ -1769,7 +1780,9 @@ int usb_gadget_register_driver(struct us
50674                         }
50675                 }
50676         }
50677 -
50678 +#ifndef CONFIG_USB_MUSB_OTG
50679 +       musb_pullup(musb, 1);
50680 +#endif
50681         return retval;
50682  }
50683  EXPORT_SYMBOL(usb_gadget_register_driver);
50684 --- a/drivers/usb/musb/musb_gadget_ep0.c
50685 +++ b/drivers/usb/musb/musb_gadget_ep0.c
50686 @@ -240,14 +240,14 @@ __acquires(musb->lock)
50687                 case USB_REQ_SET_ADDRESS:
50688                         /* change it after the status stage */
50689                         musb->set_address = true;
50690 -                       musb->address = (u8) (ctrlrequest->wValue & 0x7f);
50691 +                       musb->address = (u8) (le16_to_cpu(ctrlrequest->wValue) & 0x7f);
50692                         handled = 1;
50693                         break;
50694  
50695                 case USB_REQ_CLEAR_FEATURE:
50696                         switch (recip) {
50697                         case USB_RECIP_DEVICE:
50698 -                               if (ctrlrequest->wValue
50699 +                               if (le16_to_cpu(ctrlrequest->wValue)
50700                                                 != USB_DEVICE_REMOTE_WAKEUP)
50701                                         break;
50702                                 musb->may_wakeup = 0;
50703 @@ -261,8 +261,8 @@ __acquires(musb->lock)
50704  
50705                                 if (num == 0
50706                                                 || num >= MUSB_C_NUM_EPS
50707 -                                               || ctrlrequest->wValue
50708 -                                                       != USB_ENDPOINT_HALT)
50709 +                                               || le16_to_cpu(ctrlrequest->wValue
50710 +                                                       != USB_ENDPOINT_HALT))
50711                                         break;
50712  
50713                                 if (ctrlrequest->wIndex & USB_DIR_IN)
50714 @@ -292,7 +292,7 @@ __acquires(musb->lock)
50715                         switch (recip) {
50716                         case USB_RECIP_DEVICE:
50717                                 handled = 1;
50718 -                               switch (ctrlrequest->wValue) {
50719 +                               switch (le16_to_cpu(ctrlrequest->wValue)) {
50720                                 case USB_DEVICE_REMOTE_WAKEUP:
50721                                         musb->may_wakeup = 1;
50722                                         break;
50723 @@ -374,8 +374,8 @@ stall:
50724  
50725                                 if (epnum == 0
50726                                                 || epnum >= MUSB_C_NUM_EPS
50727 -                                               || ctrlrequest->wValue
50728 -                                                       != USB_ENDPOINT_HALT)
50729 +                                               || le16_to_cpu(ctrlrequest->wValue
50730 +                                                       != USB_ENDPOINT_HALT))
50731                                         break;
50732  
50733                                 ep = musb->endpoints + epnum;
50734 --- a/drivers/usb/musb/musb_host.c
50735 +++ b/drivers/usb/musb/musb_host.c
50736 @@ -160,7 +160,11 @@ static inline void musb_h_tx_start(struc
50737         /* NOTE: no locks here; caller should lock and select EP */
50738         if (ep->epnum) {
50739                 txcsr = musb_readw(ep->regs, MUSB_TXCSR);
50740 +#ifndef CONFIG_UBICOM32
50741                 txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
50742 +#else
50743 +               txcsr |= (MUSB_TXCSR_TXPKTRDY & (~MUSB_TXCSR_H_WZC_BITS));
50744 +#endif
50745                 musb_writew(ep->regs, MUSB_TXCSR, txcsr);
50746         } else {
50747                 txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
50748 @@ -223,6 +227,8 @@ musb_start_urb(struct musb *musb, int is
50749                 break;
50750         default:                /* bulk, interrupt */
50751                 /* actual_length may be nonzero on retry paths */
50752 +               if (urb->actual_length)
50753 +                       DBG(3 ,"musb_start_urb: URB %p retried, len: %d\n", urb, urb->actual_length);
50754                 buf = urb->transfer_buffer + urb->actual_length;
50755                 len = urb->transfer_buffer_length - urb->actual_length;
50756         }
50757 @@ -342,13 +348,13 @@ musb_save_toggle(struct musb_hw_ep *ep, 
50758         if (!is_in) {
50759                 csr = musb_readw(epio, MUSB_TXCSR);
50760                 usb_settoggle(udev, qh->epnum, 1,
50761 -                       (csr & MUSB_TXCSR_H_DATATOGGLE)
50762 -                               ? 1 : 0);
50763 +                       ((csr & MUSB_TXCSR_H_DATATOGGLE)
50764 +                               ? 1 : 0));
50765         } else {
50766                 csr = musb_readw(epio, MUSB_RXCSR);
50767                 usb_settoggle(udev, qh->epnum, 0,
50768 -                       (csr & MUSB_RXCSR_H_DATATOGGLE)
50769 -                               ? 1 : 0);
50770 +                       ((csr & MUSB_RXCSR_H_DATATOGGLE)
50771 +                               ? 1 : 0));
50772         }
50773  }
50774  
50775 @@ -556,7 +562,11 @@ musb_host_packet_rx(struct musb *musb, s
50776         musb_read_fifo(hw_ep, length, buf);
50777  
50778         csr = musb_readw(epio, MUSB_RXCSR);
50779 +#ifndef CONFIG_UBICOM32
50780         csr |= MUSB_RXCSR_H_WZC_BITS;
50781 +#else
50782 +       csr &= ~MUSB_RXCSR_H_WZC_BITS;
50783 +#endif
50784         if (unlikely(do_flush))
50785                 musb_h_flush_rxfifo(hw_ep, csr);
50786         else {
50787 @@ -590,6 +600,7 @@ musb_rx_reinit(struct musb *musb, struct
50788  
50789         /* if programmed for Tx, put it in RX mode */
50790         if (ep->is_shared_fifo) {
50791 +#ifndef  CONFIG_UBICOM32
50792                 csr = musb_readw(ep->regs, MUSB_TXCSR);
50793                 if (csr & MUSB_TXCSR_MODE) {
50794                         musb_h_tx_flush_fifo(ep);
50795 @@ -604,7 +615,18 @@ musb_rx_reinit(struct musb *musb, struct
50796                  */
50797                 if (csr & MUSB_TXCSR_DMAMODE)
50798                         musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
50799 +
50800 +#else
50801 +               /* clear mode (and everything else) to enable Rx */
50802                 musb_writew(ep->regs, MUSB_TXCSR, 0);
50803 +               /* scrub all previous state, clearing toggle */
50804 +               csr = musb_readw(ep->regs, MUSB_RXCSR);
50805 +               if (csr & MUSB_RXCSR_RXPKTRDY)
50806 +                       WARNING("rx%d, packet/%d ready?\n", ep->epnum,
50807 +                               musb_readw(ep->regs, MUSB_RXCOUNT));
50808 +
50809 +               musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
50810 +#endif
50811  
50812         /* scrub all previous state, clearing toggle */
50813         } else {
50814 @@ -1138,8 +1160,18 @@ void musb_host_tx(struct musb *musb, u8 
50815         void __iomem            *mbase = musb->mregs;
50816         struct dma_channel      *dma;
50817  
50818 +#ifdef CONFIG_UBICOM32
50819 +       if (hw_ep->is_shared_fifo) {
50820 +               qh = hw_ep->in_qh;
50821 +       }
50822 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
50823 +       printk(KERN_DEBUG "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr,
50824 +                       dma ? ", dma" : "");
50825 +#endif
50826 +#endif
50827         urb = next_urb(qh);
50828  
50829 +
50830         musb_ep_select(mbase, epnum);
50831         tx_csr = musb_readw(epio, MUSB_TXCSR);
50832  
50833 @@ -1180,9 +1212,14 @@ void musb_host_tx(struct musb *musb, u8 
50834                  * we have a candidate... NAKing is *NOT* an error
50835                  */
50836                 musb_ep_select(mbase, epnum);
50837 +#ifndef CONFIG_UBICOM32
50838                 musb_writew(epio, MUSB_TXCSR,
50839                                 MUSB_TXCSR_H_WZC_BITS
50840                                 | MUSB_TXCSR_TXPKTRDY);
50841 +#else
50842 +               musb_writew(epio, MUSB_TXCSR,
50843 +                                MUSB_TXCSR_TXPKTRDY);
50844 +#endif
50845                 return;
50846         }
50847  
50848 @@ -1353,8 +1390,14 @@ void musb_host_tx(struct musb *musb, u8 
50849         qh->segsize = length;
50850  
50851         musb_ep_select(mbase, epnum);
50852 +#ifndef CONFIG_UBICOM32
50853 +       musb_writew(epio, MUSB_TXCSR,
50854 +                   MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
50855 +#else
50856         musb_writew(epio, MUSB_TXCSR,
50857 -                       MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
50858 +                   MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
50859 +#endif
50860 +
50861  }
50862  
50863  
50864 @@ -1414,7 +1457,11 @@ static void musb_bulk_rx_nak_timeout(str
50865  
50866         /* clear nak timeout bit */
50867         rx_csr = musb_readw(epio, MUSB_RXCSR);
50868 +#ifndef CONFIG_UBICOM32
50869         rx_csr |= MUSB_RXCSR_H_WZC_BITS;
50870 +#else
50871 +       rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
50872 +#endif
50873         rx_csr &= ~MUSB_RXCSR_DATAERROR;
50874         musb_writew(epio, MUSB_RXCSR, rx_csr);
50875  
50876 @@ -1483,6 +1530,13 @@ void musb_host_rx(struct musb *musb, u8 
50877  
50878         pipe = urb->pipe;
50879  
50880 +#ifdef CONFIG_UBICOM32
50881 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
50882 +               printk(KERN_DEBUG  "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
50883 +                               xfer_len, dma ? ", dma" : "");
50884 +#endif
50885 +#endif
50886 +
50887         DBG(5, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
50888                 epnum, rx_csr, urb->actual_length,
50889                 dma ? dma->actual_len : 0);
50890 @@ -1521,8 +1575,15 @@ void musb_host_rx(struct musb *musb, u8 
50891                                 return;
50892                         }
50893                         musb_ep_select(mbase, epnum);
50894 +#ifndef CONFIG_UBICOM32
50895                         rx_csr |= MUSB_RXCSR_H_WZC_BITS;
50896                         rx_csr &= ~MUSB_RXCSR_DATAERROR;
50897 +#else
50898 +                       /* NEED TO EVALUATE CHANGE */
50899 +                       rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
50900 +                       rx_csr &= ~MUSB_RXCSR_DATAERROR;
50901 +//                     musb_writew(epio, MUSB_RXCSR, (~(MUSB_RXCSR_H_WZC_BITS))| MUSB_RXCSR_H_REQPKT);
50902 +#endif
50903                         musb_writew(epio, MUSB_RXCSR, rx_csr);
50904  
50905                         goto finish;
50906 @@ -1579,8 +1640,13 @@ void musb_host_rx(struct musb *musb, u8 
50907                 rx_csr &= ~MUSB_RXCSR_H_REQPKT;
50908  
50909                 musb_ep_select(mbase, epnum);
50910 +#ifndef CONFIG_UBICOM32
50911                 musb_writew(epio, MUSB_RXCSR,
50912                                 MUSB_RXCSR_H_WZC_BITS | rx_csr);
50913 +#else
50914 +               musb_writew(epio, MUSB_RXCSR,
50915 +                               (~MUSB_RXCSR_H_WZC_BITS) & rx_csr);
50916 +#endif
50917         }
50918  #endif
50919         if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
50920 @@ -1610,7 +1676,7 @@ void musb_host_rx(struct musb *musb, u8 
50921                         else
50922                                 done = false;
50923  
50924 -               } else  {
50925 +               } else {
50926                 /* done if urb buffer is full or short packet is recd */
50927                 done = (urb->actual_length + xfer_len >=
50928                                 urb->transfer_buffer_length
50929 @@ -1823,7 +1889,11 @@ static int musb_schedule(
50930                 } else  if (hw_ep->out_qh != NULL)
50931                         continue;
50932  
50933 +#ifndef CONFIG_UBICOM32
50934                 if (hw_ep == musb->bulk_ep)
50935 +#else
50936 +               if ((hw_ep == musb->bulk_ep_in) || (hw_ep == musb->bulk_ep_out)) /* Ubicom */
50937 +#endif
50938                         continue;
50939  
50940                 if (is_in)
50941 @@ -1836,7 +1906,14 @@ static int musb_schedule(
50942                         best_end = epnum;
50943                 }
50944         }
50945 +
50946 +#ifdef CONFIG_UBICOM32
50947 +       if (((best_diff >= qh->maxpacket)) && ((qh->type == USB_ENDPOINT_XFER_BULK) && (!is_in)))
50948 +               best_end = -1;
50949 +#endif
50950 +
50951         /* use bulk reserved ep1 if no other ep is free */
50952 +#ifndef CONFIG_UBICOM32
50953         if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
50954                 hw_ep = musb->bulk_ep;
50955                 if (is_in)
50956 @@ -1858,6 +1935,22 @@ static int musb_schedule(
50957         } else if (best_end < 0) {
50958                 return -ENOSPC;
50959         }
50960 +#else
50961 +       if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
50962 +               /* hw_ep = musb->bulk_ep; */
50963 +               if (is_in) {
50964 +                       head = &musb->in_bulk;
50965 +                       hw_ep = musb->bulk_ep_in; /* UBICOM */
50966 +               }
50967 +               else {
50968 +                       head = &musb->out_bulk;
50969 +                       hw_ep = musb->bulk_ep_out; /* UBICOM */
50970 +               }
50971 +               goto success;
50972 +       } else if (best_end < 0) {
50973 +               return -ENOSPC;
50974 +       }
50975 +#endif
50976  
50977         idle = 1;
50978         qh->mux = 0;
50979 @@ -1869,6 +1962,13 @@ success:
50980                 list_add_tail(&qh->ring, head);
50981                 qh->mux = 1;
50982         }
50983 +       /*
50984 +        * It's not make sense to set NAK timeout when qh->mux = 0,
50985 +        * There is nothing else to schedule
50986 +        */
50987 +       if ((qh->type == USB_ENDPOINT_XFER_BULK) && (qh->mux == 0))
50988 +               qh->intv_reg = 0;
50989 +
50990         qh->hw_ep = hw_ep;
50991         qh->hep->hcpriv = qh;
50992         if (idle)
50993 @@ -1975,6 +2075,15 @@ static int musb_urb_enqueue(
50994                 /* ISO always uses logarithmic encoding */
50995                 interval = min_t(u8, epd->bInterval, 16);
50996                 break;
50997 +#ifdef COMFIG_UBICOM32
50998 +       case USB_ENDPOINT_XFER_BULK:
50999 +                if (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
51000 +                       interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16: 2;
51001 +                else
51002 +                       interval = 0;
51003 +                break;
51004 +#endif
51005 +
51006         default:
51007                 /* REVISIT we actually want to use NAK limits, hinting to the
51008                  * transfer scheduling logic to try some other qh, e.g. try
51009 --- a/drivers/usb/musb/musb_io.h
51010 +++ b/drivers/usb/musb/musb_io.h
51011 @@ -58,6 +58,7 @@ static inline void writesb(const void __
51012  
51013  #ifndef CONFIG_BLACKFIN
51014  
51015 +#ifndef CONFIG_UBICOM32
51016  /* NOTE:  these offsets are all in bytes */
51017  
51018  static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51019 @@ -72,7 +73,37 @@ static inline void musb_writew(void __io
51020  
51021  static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
51022         { __raw_writel(data, addr + offset); }
51023 +#else
51024 +#include <asm/ubicom32-tio.h>
51025 +static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51026 +{
51027 +        u16 data;
51028 +        usb_tio_read_u16((u32)(addr + offset), &data);
51029 +        return data;
51030 +}
51031  
51032 +static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51033 +{
51034 +        u8 data;
51035 +        usb_tio_read_u8((u32)(addr + offset), &data);
51036 +        return data;
51037 +}
51038 +
51039 +static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
51040 +{
51041 +        usb_tio_write_u16((u32)(addr + offset), data);
51042 +}
51043 +
51044 +static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
51045 +{
51046 +        usb_tio_write_u8((u32)(addr + offset), data);
51047 +}
51048 +
51049 +static inline void  musb_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
51050 +{
51051 +       return usb_tio_read_int_status(int_usb, int_tx, int_rx);
51052 +}
51053 +#endif /* CONFIG_UBICOM32 */
51054  
51055  #ifdef CONFIG_USB_TUSB6010
51056  
51057 @@ -106,7 +137,7 @@ static inline void musb_writeb(void __io
51058         __raw_writew(tmp, addr + (offset & ~1));
51059  }
51060  
51061 -#else
51062 +#elif !defined(CONFIG_UBICOM32)
51063  
51064  static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51065         { return __raw_readb(addr + offset); }
51066 --- a/drivers/usb/musb/musb_regs.h
51067 +++ b/drivers/usb/musb/musb_regs.h
51068 @@ -167,6 +167,7 @@
51069         (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
51070         | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
51071  
51072 +
51073  /* RXCSR in Peripheral and Host mode */
51074  #define MUSB_RXCSR_AUTOCLEAR           0x8000
51075  #define MUSB_RXCSR_DMAENAB             0x2000
51076 --- /dev/null
51077 +++ b/drivers/usb/musb/ubi32_usb.c
51078 @@ -0,0 +1,156 @@
51079 +/*
51080 + * drivers/usb/musb/ubi32_usb.c
51081 + *   Ubicom32 usb controller driver.
51082 + *
51083 + * (C) Copyright 2009, Ubicom, Inc.
51084 + * Copyright (C) 2005-2006 by Texas Instruments
51085 + *
51086 + * Derived from the Texas Instruments Inventra Controller Driver for Linux.
51087 + *
51088 + * This file is part of the Ubicom32 Linux Kernel Port.
51089 + *
51090 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51091 + * it and/or modify it under the terms of the GNU General Public License
51092 + * as published by the Free Software Foundation, either version 2 of the
51093 + * License, or (at your option) any later version.
51094 + *
51095 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51096 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51097 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
51098 + * the GNU General Public License for more details.
51099 + *
51100 + * You should have received a copy of the GNU General Public License
51101 + * along with the Ubicom32 Linux Kernel Port.  If not,
51102 + * see <http://www.gnu.org/licenses/>.
51103 + *
51104 + * Ubicom32 implementation derived from (with many thanks):
51105 + *   arch/m68knommu
51106 + *   arch/blackfin
51107 + *   arch/parisc
51108 + */
51109 +#include <linux/module.h>
51110 +#include <linux/kernel.h>
51111 +#include <linux/sched.h>
51112 +#include <linux/slab.h>
51113 +#include <linux/init.h>
51114 +#include <linux/list.h>
51115 +#include <linux/clk.h>
51116 +#include <linux/io.h>
51117 +
51118 +#include <asm/io.h>
51119 +#include <asm/ip5000.h>
51120 +#include "musb_core.h"
51121 +
51122 +void musb_platform_enable(struct musb *musb)
51123 +{
51124 +}
51125 +void musb_platform_disable(struct musb *musb)
51126 +{
51127 +}
51128 +
51129 +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {
51130 +       return 0;
51131 +}
51132 +
51133 +static void ip5k_usb_hcd_vbus_power(struct musb *musb, int is_on, int sleeping)
51134 +{
51135 +}
51136 +
51137 +static void ip5k_usb_hcd_set_vbus(struct musb *musb, int is_on)
51138 +{
51139 +       u8              devctl;
51140 +       /* HDRC controls CPEN, but beware current surges during device
51141 +        * connect.  They can trigger transient overcurrent conditions
51142 +        * that must be ignored.
51143 +        */
51144 +
51145 +       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
51146 +
51147 +       if (is_on) {
51148 +               musb->is_active = 1;
51149 +               musb->xceiv.default_a = 1;
51150 +               musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
51151 +               devctl |= MUSB_DEVCTL_SESSION;
51152 +
51153 +               MUSB_HST_MODE(musb);
51154 +       } else {
51155 +               musb->is_active = 0;
51156 +
51157 +               /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
51158 +                * jumping right to B_IDLE...
51159 +                */
51160 +
51161 +               musb->xceiv.default_a = 0;
51162 +               musb->xceiv.state = OTG_STATE_B_IDLE;
51163 +               devctl &= ~MUSB_DEVCTL_SESSION;
51164 +
51165 +               MUSB_DEV_MODE(musb);
51166 +       }
51167 +       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
51168 +
51169 +       DBG(1, "VBUS %s, devctl %02x "
51170 +               /* otg %3x conf %08x prcm %08x */ "\n",
51171 +               otg_state_string(musb),
51172 +               musb_readb(musb->mregs, MUSB_DEVCTL));
51173 +}
51174 +static int ip5k_usb_hcd_set_power(struct otg_transceiver *x, unsigned mA)
51175 +{
51176 +       return 0;
51177 +}
51178 +
51179 +static int musb_platform_resume(struct musb *musb);
51180 +
51181 +int __init musb_platform_init(struct musb *musb)
51182 +{
51183 +
51184 +#ifdef CONFIG_UBICOM32_V4
51185 +       u32_t chip_id;
51186 +       asm volatile (
51187 +                     "move.4   %0, CHIP_ID     \n\t"
51188 +                     : "=r" (chip_id)
51189 +       );
51190 +       if (chip_id == 0x30001) {
51191 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 30);
51192 +               udelay(1);
51193 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 31);
51194 +       } else {
51195 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 17);
51196 +               udelay(1);
51197 +               *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 14);
51198 +       }
51199 +#endif
51200 +
51201 +        *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_CFG)) |= ((1 << 14) | (1 <<15));
51202 +
51203 +       /* The i-clk is AUTO gated. Hence there is no need
51204 +        * to disable it until the driver is shutdown */
51205 +
51206 +       clk_enable(musb->clock);
51207 +       musb_platform_resume(musb);
51208 +
51209 +       ip5k_usb_hcd_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
51210 +
51211 +       if (is_host_enabled(musb))
51212 +               musb->board_set_vbus = ip5k_usb_hcd_set_vbus;
51213 +       if (is_peripheral_enabled(musb))
51214 +               musb->xceiv.set_power = ip5k_usb_hcd_set_power;
51215 +
51216 +       return 0;
51217 +}
51218 +
51219 +
51220 +int musb_platform_suspend(struct musb *musb)
51221 +{
51222 +       return 0;
51223 +}
51224 +int musb_platform_resume(struct musb *musb)
51225 +{
51226 +       return 0;
51227 +}
51228 +
51229 +int musb_platform_exit(struct musb *musb)
51230 +{
51231 +       ip5k_usb_hcd_vbus_power(musb, 0 /*off*/, 1);
51232 +       musb_platform_suspend(musb);
51233 +       return 0;
51234 +}
51235 --- a/drivers/video/backlight/Kconfig
51236 +++ b/drivers/video/backlight/Kconfig
51237 @@ -93,6 +93,63 @@ config LCD_HP700
51238           If you have an HP Jornada 700 series handheld (710/720/728)
51239           say Y to enable LCD control driver.
51240  
51241 +config LCD_UBICOM32POWER
51242 +       tristate "Ubicom LCD power Driver"
51243 +       depends on LCD_CLASS_DEVICE && UBICOM32
51244 +       default n
51245 +       help
51246 +         If you have a Ubicom32 based system with an LCD panel that requires
51247 +         power control, say Y to enable the power control driver for it.
51248 +
51249 +config LCD_UBICOM32
51250 +       tristate "Ubicom Backlight Driver"
51251 +       depends on LCD_CLASS_DEVICE && UBICOM32
51252 +       default n
51253 +       help
51254 +         This driver takes care of initialization of LCD panels with
51255 +         built in controllers.
51256 +
51257 +menu "Ubicom32 LCD Panel Support"
51258 +       depends on UBICOM32 && LCD_UBICOM32
51259 +
51260 +config LCD_UBICOM32_TFT2N0369E_P
51261 +       bool "TFT2N0369E (Portrait)"
51262 +       default n
51263 +       help
51264 +         Support for TFT2N0369 in portrait mode
51265 +
51266 +config LCD_UBICOM32_TFT2N0369E_L
51267 +       bool "TFT2N0369E (Landscape)"
51268 +       default n
51269 +       help
51270 +         Support for TFT2N0369 in landscape mode
51271 +
51272 +config LCD_UBICOM32_CFAF240320KTTS
51273 +       bool "CFAF240320KTTS"
51274 +       default n
51275 +       help
51276 +         Support for CFAF240320KTTS
51277 +
51278 +config LCD_UBICOM32_CFAF240320KTTS_180
51279 +       bool "CFAF240320KTTS (180 rotation)"
51280 +       default n
51281 +       help
51282 +         Support for CFAF240320KTTS rotated 180 degrees
51283 +
51284 +config LCD_UBICOM32_CFAF240320D
51285 +       bool "CFAF240320D"
51286 +       default n
51287 +       help
51288 +         Support for CFAF240320D
51289 +
51290 +config LCD_UBICOM32_CFAF320240F
51291 +       bool "CFAF320240F"
51292 +       default n
51293 +       help
51294 +         Support for CFAF320240F
51295 +
51296 +endmenu
51297 +
51298  #
51299  # Backlight
51300  #
51301 @@ -229,3 +286,11 @@ config BACKLIGHT_SAHARA
51302         help
51303           If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
51304           backlight driver.
51305 +
51306 +config BACKLIGHT_UBICOM32
51307 +       tristate "Ubicom Backlight Driver"
51308 +       depends on BACKLIGHT_CLASS_DEVICE && UBICOM32
51309 +       default n
51310 +       help
51311 +         If you have a Ubicom32 based system with a backlight say Y to enable the
51312 +         backlight driver.
51313 --- a/drivers/video/backlight/Makefile
51314 +++ b/drivers/video/backlight/Makefile
51315 @@ -9,6 +9,9 @@ obj-$(CONFIG_LCD_PLATFORM)         += platfor
51316  obj-$(CONFIG_LCD_VGG2432A4)       += vgg2432a4.o
51317  obj-$(CONFIG_LCD_TDO24M)          += tdo24m.o
51318  obj-$(CONFIG_LCD_TOSA)            += tosa_lcd.o
51319 +obj-$(CONFIG_LCD_LTV350QV)        += ltv350qv.o
51320 +obj-$(CONFIG_LCD_UBICOM32POWER)           += ubicom32lcdpower.o
51321 +obj-$(CONFIG_LCD_UBICOM32)        += ubicom32lcd.o
51322  
51323  obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
51324  obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)    += atmel-pwm-bl.o
51325 @@ -24,4 +27,4 @@ obj-$(CONFIG_BACKLIGHT_DA903X)        += da903x
51326  obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
51327  obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
51328  obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
51329 -
51330 +obj-$(CONFIG_BACKLIGHT_UBICOM32) += ubicom32bl.o
51331 --- /dev/null
51332 +++ b/drivers/video/backlight/ubicom32bl.c
51333 @@ -0,0 +1,399 @@
51334 +/*
51335 + * drivers/video/backlight/ubicom32bl.c
51336 + *     Backlight driver for the Ubicom32 platform
51337 + *
51338 + * (C) Copyright 2009, Ubicom, Inc.
51339 + *
51340 + * This file is part of the Ubicom32 Linux Kernel Port.
51341 + *
51342 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51343 + * it and/or modify it under the terms of the GNU General Public License
51344 + * as published by the Free Software Foundation, either version 2 of the
51345 + * License, or (at your option) any later version.
51346 + *
51347 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51348 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51349 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
51350 + * the GNU General Public License for more details.
51351 + *
51352 + * You should have received a copy of the GNU General Public License
51353 + * along with the Ubicom32 Linux Kernel Port.  If not,
51354 + * see <http://www.gnu.org/licenses/>.
51355 + *
51356 + * Ubicom32 implementation derived from (with many thanks):
51357 + *   arch/m68knommu
51358 + *   arch/blackfin
51359 + *   arch/parisc
51360 + */
51361 +#include <linux/init.h>
51362 +#include <linux/kernel.h>
51363 +#include <linux/module.h>
51364 +#include <linux/platform_device.h>
51365 +#include <linux/backlight.h>
51366 +#include <linux/fb.h>
51367 +
51368 +#include <asm/ubicom32bl.h>
51369 +#include <asm/ip5000.h>
51370 +
51371 +#define DRIVER_NAME                    "ubicom32bl"
51372 +#define UBICOM32BL_MAX_BRIGHTNESS      255
51373 +
51374 +struct ubicom32bl_data {
51375 +       /*
51376 +        * Pointer to the platform data structure.  Keep this around since we need values
51377 +        * from it to set the backlight intensity.
51378 +        */
51379 +       const struct ubicom32bl_platform_data   *pdata;
51380 +
51381 +       /*
51382 +        * Backlight device, we have to save this for use when we remove ourselves.
51383 +        */
51384 +       struct backlight_device                 *bldev;
51385 +
51386 +       /*
51387 +        * Current intensity, used for get_intensity.
51388 +        */
51389 +       int                                     cur_intensity;
51390 +
51391 +       /*
51392 +        * Init function for PWM
51393 +        */
51394 +       int (*init_fn)(struct ubicom32bl_data *);
51395 +
51396 +       /*
51397 +        * Set intensity function depending on the backlight type
51398 +        */
51399 +       int (*set_intensity_fn)(struct ubicom32bl_data *, int);
51400 +};
51401 +
51402 +/*
51403 + * ubicom32bl_set_intensity_gpio
51404 + */
51405 +static int ubicom32bl_set_intensity_gpio(struct ubicom32bl_data *ud, int intensity)
51406 +{
51407 +       ud->cur_intensity = intensity ? 255 : 0;
51408 +
51409 +       if (intensity) {
51410 +               // set gpio
51411 +               return 0;
51412 +       }
51413 +
51414 +       // clear gpio
51415 +       return 0;
51416 +}
51417 +
51418 +/*
51419 + * ubicom32bl_set_intensity_hw
51420 + */
51421 +static int ubicom32bl_set_intensity_hw(struct ubicom32bl_data *ud, int intensity)
51422 +{
51423 +       u16_t period = ud->pdata->pwm_period;
51424 +       u16_t duty;
51425 +
51426 +       /*
51427 +        * Calculate the new duty cycle
51428 +        */
51429 +       duty = (period * intensity) / (UBICOM32BL_MAX_BRIGHTNESS + 1);
51430 +
51431 +       /*
51432 +        * Set the new duty cycle
51433 +        */
51434 +       switch (ud->pdata->pwm_channel) {
51435 +       case 0:
51436 +               /*
51437 +                * Channel 0 is in the lower half of PORT C ctl0 and ctl1
51438 +                */
51439 +               UBICOM32_IO_PORT(RC)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51440 +               break;
51441 +
51442 +       case 1:
51443 +               /*
51444 +                * Channel 1 is in the upper half of PORT C ctl0 and ctl2
51445 +                */
51446 +               UBICOM32_IO_PORT(RC)->ctl2 = (ud->pdata->pwm_period << 16) | duty;
51447 +               break;
51448 +
51449 +       case 2:
51450 +               /*
51451 +                * Channel 2 is in PORT H ctl0 and ctl1
51452 +                */
51453 +               UBICOM32_IO_PORT(RH)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51454 +               break;
51455 +       }
51456 +
51457 +       ud->cur_intensity = intensity;
51458 +
51459 +       return 0;
51460 +}
51461 +
51462 +/*
51463 + * ubicom32bl_set_intensity
51464 + */
51465 +static int ubicom32bl_set_intensity(struct backlight_device *bd)
51466 +{
51467 +       struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51468 +       int intensity = bd->props.brightness;
51469 +
51470 +       /*
51471 +        * If we're blanked the the intensity doesn't matter.
51472 +        */
51473 +       if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
51474 +               intensity = 0;
51475 +       }
51476 +
51477 +       /*
51478 +        * Check for inverted backlight.
51479 +        */
51480 +       if (ud->pdata->invert) {
51481 +               intensity = UBICOM32BL_MAX_BRIGHTNESS - intensity;
51482 +       }
51483 +
51484 +       if (ud->set_intensity_fn) {
51485 +               return ud->set_intensity_fn(ud, intensity);
51486 +       }
51487 +
51488 +       return -ENXIO;
51489 +}
51490 +
51491 +/*
51492 + * ubicom32bl_get_intensity
51493 + *     Return the current intensity of the backlight.
51494 + */
51495 +static int ubicom32bl_get_intensity(struct backlight_device *bd)
51496 +{
51497 +       struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51498 +
51499 +       return ud->cur_intensity;
51500 +}
51501 +
51502 +/*
51503 + * ubicom32bl_init_hw_pwm
51504 + *     Set the appropriate PWM registers
51505 + */
51506 +static int ubicom32bl_init_hw_pwm(struct ubicom32bl_data *ud)
51507 +{
51508 +       /*
51509 +        * bit 13: enable
51510 +        */
51511 +       u16_t pwm_cfg = (1 << 13) | (ud->pdata->pwm_prescale << 8) ;
51512 +
51513 +       switch (ud->pdata->pwm_channel) {
51514 +       case 0:
51515 +               /*
51516 +                * Channel 0 is in the lower half of PORT C ctl0 and ctl1 (PA5)
51517 +                */
51518 +               UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF;
51519 +               UBICOM32_IO_PORT(RC)->ctl0 |= pwm_cfg;
51520 +               UBICOM32_IO_PORT(RC)->ctl1 = ud->pdata->pwm_period << 16;
51521 +
51522 +               /*
51523 +                * If the port function is not set, set it to GPIO/PWM
51524 +                */
51525 +               if (!UBICOM32_IO_PORT(RA)->function) {
51526 +                       UBICOM32_IO_PORT(RA)->function = 3;
51527 +               }
51528 +               break;
51529 +
51530 +       case 1:
51531 +               /*
51532 +                * Channel 1 is in the upper half of PORT C ctl0 and ctl2 (PE4)
51533 +                */
51534 +               UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF0000;
51535 +               UBICOM32_IO_PORT(RC)->ctl0 |= (pwm_cfg << 16);
51536 +               UBICOM32_IO_PORT(RC)->ctl2 = ud->pdata->pwm_period << 16;
51537 +
51538 +               /*
51539 +                * If the port function is not set, set it to GPIO/ExtIOInt
51540 +                */
51541 +               if (!UBICOM32_IO_PORT(RE)->function) {
51542 +                       UBICOM32_IO_PORT(RE)->function = 3;
51543 +               }
51544 +               break;
51545 +
51546 +       case 2:
51547 +               /*
51548 +                * Channel 2 is in PORT H ctl0 and ctl1 (PD0)
51549 +                */
51550 +               UBICOM32_IO_PORT(RH)->ctl0 &= ~0xFFFF0000;
51551 +               UBICOM32_IO_PORT(RH)->ctl0 = pwm_cfg;
51552 +               UBICOM32_IO_PORT(RH)->ctl1 = ud->pdata->pwm_period << 16;
51553 +
51554 +               /*
51555 +                * If the port function is not set, set it to GPIO
51556 +                */
51557 +               if (!UBICOM32_IO_PORT(RD)->function) {
51558 +                       UBICOM32_IO_PORT(RD)->function = 3;
51559 +               }
51560 +               break;
51561 +       }
51562 +
51563 +       return 0;
51564 +}
51565 +
51566 +/*
51567 + * ubicom32bl_init_gpio
51568 + *     Allocate the appropriate GPIO
51569 + */
51570 +static int ubicom32bl_init_gpio(struct ubicom32bl_data *ud)
51571 +{
51572 +       return 0;
51573 +}
51574 +
51575 +static struct backlight_ops ubicom32bl_ops = {
51576 +       .get_brightness = ubicom32bl_get_intensity,
51577 +       .update_status  = ubicom32bl_set_intensity,
51578 +};
51579 +
51580 +/*
51581 + * ubicom32bl_probe
51582 + */
51583 +static int ubicom32bl_probe(struct platform_device *pdev)
51584 +{
51585 +       const struct ubicom32bl_platform_data *pdata = pdev->dev.platform_data;
51586 +       struct ubicom32bl_data *ud;
51587 +       struct backlight_device *bldev;
51588 +       int retval;
51589 +
51590 +       /*
51591 +        * Check to see if we have any platform data, if we don't then the backlight is not
51592 +        * configured on this device.
51593 +        */
51594 +       if (!pdata) {
51595 +               return -ENODEV;
51596 +       }
51597 +
51598 +       /*
51599 +        * Allocate our private data
51600 +        */
51601 +       ud = kzalloc(sizeof(struct ubicom32bl_data), GFP_KERNEL);
51602 +       if (!ud) {
51603 +               return -ENOMEM;
51604 +       }
51605 +
51606 +       ud->pdata = pdata;
51607 +
51608 +       /*
51609 +        * Check to see that the platform data is valid for this driver
51610 +        */
51611 +       switch (pdata->type) {
51612 +       case UBICOM32BL_TYPE_PWM:
51613 +               {
51614 +                       /*
51615 +                        * Make sure we have a PWM peripheral
51616 +                        */
51617 +                       u32_t chipid;
51618 +                       asm volatile (
51619 +                               "move.4         %0, CHIP_ID     \n\t"
51620 +                               : "=r" (chipid)
51621 +                       );
51622 +                       if (chipid != 0x00030001) {
51623 +                               retval = -ENODEV;
51624 +                               goto fail;
51625 +                       }
51626 +
51627 +                       if (pdata->pwm_channel > 3) {
51628 +                               retval = -ENODEV;
51629 +                               goto fail;
51630 +                       }
51631 +                       if (pdata->pwm_prescale > 16) {
51632 +                               retval = -EINVAL;
51633 +                               goto fail;
51634 +                       }
51635 +
51636 +                       ud->init_fn = ubicom32bl_init_hw_pwm;
51637 +                       ud->set_intensity_fn = ubicom32bl_set_intensity_hw;
51638 +                       break;
51639 +               }
51640 +
51641 +       case UBICOM32BL_TYPE_PWM_HRT:
51642 +               // For now, PWM HRT devices are treated as binary lights.
51643 +
51644 +       case UBICOM32BL_TYPE_BINARY:
51645 +               ud->init_fn = ubicom32bl_init_gpio;
51646 +               ud->set_intensity_fn = ubicom32bl_set_intensity_gpio;
51647 +               break;
51648 +       }
51649 +
51650 +       /*
51651 +        * Register our backlight device
51652 +        */
51653 +       bldev = backlight_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32bl_ops);
51654 +       if (IS_ERR(bldev)) {
51655 +               retval = PTR_ERR(bldev);
51656 +               goto fail;
51657 +       }
51658 +
51659 +       ud->bldev = bldev;
51660 +       ud->cur_intensity = pdata->default_intensity;
51661 +       platform_set_drvdata(pdev, ud);
51662 +
51663 +       /*
51664 +        * Start up the backlight at the prescribed default intensity
51665 +        */
51666 +       bldev->props.power = FB_BLANK_UNBLANK;
51667 +       bldev->props.max_brightness = UBICOM32BL_MAX_BRIGHTNESS;
51668 +       bldev->props.brightness = pdata->default_intensity;
51669 +
51670 +       if (ud->init_fn) {
51671 +               if (ud->init_fn(ud) != 0) {
51672 +                       retval = -ENODEV;
51673 +                       backlight_device_unregister(ud->bldev);
51674 +                       goto fail;
51675 +               }
51676 +       }
51677 +       ubicom32bl_set_intensity(bldev);
51678 +
51679 +       printk(KERN_INFO DRIVER_NAME ": Backlight driver started\n");
51680 +
51681 +       return 0;
51682 +
51683 +fail:
51684 +       platform_set_drvdata(pdev, NULL);
51685 +       kfree(ud);
51686 +       return retval;
51687 +}
51688 +
51689 +/*
51690 + * ubicom32bl_remove
51691 + */
51692 +static int __exit ubicom32bl_remove(struct platform_device *pdev)
51693 +{
51694 +       struct ubicom32bl_data *ud = platform_get_drvdata(pdev);
51695 +
51696 +       backlight_device_unregister(ud->bldev);
51697 +       platform_set_drvdata(pdev, NULL);
51698 +       kfree(ud);
51699 +
51700 +       return 0;
51701 +}
51702 +
51703 +static struct platform_driver ubicom32bl_driver = {
51704 +       .driver = {
51705 +               .name = DRIVER_NAME,
51706 +               .owner = THIS_MODULE,
51707 +       },
51708 +
51709 +       .remove = __exit_p(ubicom32bl_remove),
51710 +};
51711 +
51712 +/*
51713 + * ubicom32bl_init
51714 + */
51715 +static int __init ubicom32bl_init(void)
51716 +{
51717 +       return platform_driver_probe(&ubicom32bl_driver, ubicom32bl_probe);
51718 +}
51719 +module_init(ubicom32bl_init);
51720 +
51721 +/*
51722 + * ubicom32bl_exit
51723 + */
51724 +static void __exit ubicom32bl_exit(void)
51725 +{
51726 +       platform_driver_unregister(&ubicom32bl_driver);
51727 +}
51728 +module_exit(ubicom32bl_exit);
51729 +
51730 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
51731 +MODULE_DESCRIPTION("Ubicom32 backlight driver");
51732 +MODULE_LICENSE("GPL");
51733 --- /dev/null
51734 +++ b/drivers/video/backlight/ubicom32lcd.c
51735 @@ -0,0 +1,372 @@
51736 +/*
51737 + * drivers/video/ubicom32lcd.c
51738 + *     LCD initilization code
51739 + *
51740 + * (C) Copyright 2009, Ubicom, Inc.
51741 + *
51742 + * This file is part of the Ubicom32 Linux Kernel Port.
51743 + *
51744 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51745 + * it and/or modify it under the terms of the GNU General Public License
51746 + * as published by the Free Software Foundation, either version 2 of the
51747 + * License, or (at your option) any later version.
51748 + *
51749 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51750 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51751 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
51752 + * the GNU General Public License for more details.
51753 + *
51754 + * You should have received a copy of the GNU General Public License
51755 + * along with the Ubicom32 Linux Kernel Port.  If not,
51756 + * see <http://www.gnu.org/licenses/>.
51757 + */
51758 +#include <linux/init.h>
51759 +#include <linux/kernel.h>
51760 +#include <linux/module.h>
51761 +#include <linux/platform_device.h>
51762 +#include <linux/delay.h>
51763 +
51764 +#include <asm/ip5000.h>
51765 +#include <asm/gpio.h>
51766 +#include <asm/ubicom32lcd.h>
51767 +
51768 +#include "ubicom32lcd.h"
51769 +
51770 +#define DRIVER_NAME                    "ubicom32lcd"
51771 +
51772 +struct ubicom32lcd_data {
51773 +       const struct ubicom32lcd_panel  *panel;
51774 +
51775 +       int                             pin_cs;
51776 +       int                             pin_rd;
51777 +       int                             pin_rs;
51778 +       int                             pin_wr;
51779 +       int                             pin_reset;
51780 +       struct ubicom32_io_port         *port_data;
51781 +       int                             data_shift;
51782 +};
51783 +
51784 +/*
51785 + * ubicom32lcd_write
51786 + *     Performs a write cycle on the bus (assumes CS asserted, RD & WR set)
51787 + */
51788 +static void ubicom32lcd_write(struct ubicom32lcd_data *ud, int command, u16 data)
51789 +{
51790 +       if (command) {
51791 +               UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rs);
51792 +       } else {
51793 +               UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51794 +       }
51795 +
51796 +       asm volatile (
51797 +               "or.4   4(%[port]), 4(%[port]), %[mask] \n\t"
51798 +               "not.4  %[mask], %[mask]                \n\t"
51799 +               "and.4  8(%[port]), 8(%[port]), %[mask] \n\t"
51800 +               "or.4   8(%[port]), 8(%[port]), %[cmd]  \n\t"
51801 +               :
51802 +               : [port] "a" (ud->port_data),
51803 +                 [mask] "d" (0xFFFF << ud->data_shift),
51804 +                 [cmd] "d" (data << ud->data_shift)
51805 +               : "cc"
51806 +       );
51807 +
51808 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_wr);
51809 +
51810 +       //ndelay(50);
51811 +       udelay(1);
51812 +
51813 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
51814 +
51815 +       udelay(1);
51816 +       //ndelay(50);
51817 +}
51818 +
51819 +/*
51820 + * ubicom32lcd_read_data
51821 + *     Performs a read cycle on the bus (assumes CS asserted, RD & WR set)
51822 + */
51823 +static u16 ubicom32lcd_read_data(struct ubicom32lcd_data *ud)
51824 +{
51825 +       u32_t data;
51826 +
51827 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51828 +
51829 +       asm volatile (
51830 +               "and.4  4(%[port]), 4(%[port]), %[mask]\n\t"
51831 +               :
51832 +               : [port] "a" (ud->port_data),
51833 +                 [mask] "d" (~(0xFFFF << ud->data_shift))
51834 +               : "cc"
51835 +       );
51836 +
51837 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rd);
51838 +
51839 +       ndelay(300);
51840 +
51841 +       asm volatile (
51842 +               "lsr.4  %[data], 12(%[port]), %[shamt]  \n\t"
51843 +               "and.4  %[data], %[data], %[mask]       \n\t"
51844 +               : [data] "=d" (data)
51845 +               : [port] "a" (ud->port_data),
51846 +                 [mask] "d" (0xFFFF),
51847 +                 [shamt] "d" (ud->data_shift)
51848 +               : "cc"
51849 +       );
51850 +
51851 +       ndelay(200);
51852 +
51853 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
51854 +
51855 +       ndelay(500);
51856 +
51857 +       return data;
51858 +}
51859 +
51860 +/*
51861 + * ubicom32lcd_execute
51862 + *     Executes a script for performing operations on the LCD (assumes CS set)
51863 + */
51864 +static void ubicom32lcd_execute(struct ubicom32lcd_data *ud, const struct ubicom32lcd_step *script)
51865 +{
51866 +       while (1) {
51867 +               switch (script->op) {
51868 +               case LCD_STEP_CMD:
51869 +                       ubicom32lcd_write(ud, 1, script->cmd);
51870 +                       break;
51871 +
51872 +               case LCD_STEP_DATA:
51873 +                       ubicom32lcd_write(ud, 0, script->data);
51874 +                       break;
51875 +
51876 +               case LCD_STEP_CMD_DATA:
51877 +                       ubicom32lcd_write(ud, 1, script->cmd);
51878 +                       ubicom32lcd_write(ud, 0, script->data);
51879 +                       break;
51880 +
51881 +               case LCD_STEP_SLEEP:
51882 +                       udelay(script->data);
51883 +                       break;
51884 +
51885 +               case LCD_STEP_DONE:
51886 +                       return;
51887 +               }
51888 +               script++;
51889 +       }
51890 +}
51891 +
51892 +/*
51893 + * ubicom32lcd_goto
51894 + *     Places the gram pointer at a specific X, Y address
51895 + */
51896 +static void ubicom32lcd_goto(struct ubicom32lcd_data *ud, int x, int y)
51897 +{
51898 +       ubicom32lcd_write(ud, 1, ud->panel->horz_reg);
51899 +       ubicom32lcd_write(ud, 0, x);
51900 +       ubicom32lcd_write(ud, 1, ud->panel->vert_reg);
51901 +       ubicom32lcd_write(ud, 0, y);
51902 +       ubicom32lcd_write(ud, 1, ud->panel->gram_reg);
51903 +}
51904 +
51905 +/*
51906 + * ubicom32lcd_panel_init
51907 + *     Initializes the lcd panel.
51908 + */
51909 +static int ubicom32lcd_panel_init(struct ubicom32lcd_data *ud)
51910 +{
51911 +       u16 id;
51912 +
51913 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_reset);
51914 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_reset);
51915 +       UBICOM32_GPIO_ENABLE(ud->pin_reset);
51916 +
51917 +       asm volatile (
51918 +               "or.4   0x50(%[port]), 0x50(%[port]), %[mask]   \n\t"
51919 +               "not.4  %[mask], %[mask]                        \n\t"
51920 +               "and.4  0x04(%[port]), 0x04(%[port]), %[mask]   \n\t"
51921 +               :
51922 +               : [port] "a" (ud->port_data),
51923 +                 [mask] "d" (0xFFFF << ud->data_shift)
51924 +               : "cc"
51925 +       );
51926 +
51927 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51928 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
51929 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
51930 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
51931 +
51932 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rs);
51933 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rd);
51934 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_wr);
51935 +       UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_cs);
51936 +
51937 +       UBICOM32_GPIO_ENABLE(ud->pin_rs);
51938 +       UBICOM32_GPIO_ENABLE(ud->pin_rd);
51939 +       UBICOM32_GPIO_ENABLE(ud->pin_wr);
51940 +       UBICOM32_GPIO_ENABLE(ud->pin_cs);
51941 +
51942 +       udelay(20);
51943 +
51944 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_reset);
51945 +
51946 +       udelay(20);
51947 +
51948 +       UBICOM32_GPIO_SET_PIN_LOW(ud->pin_cs);
51949 +
51950 +       id = ubicom32lcd_read_data(ud);
51951 +
51952 +       /*
51953 +        * We will try to figure out what kind of panel we have if we were not told.
51954 +        */
51955 +       if (!ud->panel) {
51956 +               const struct ubicom32lcd_panel **p = ubicom32lcd_panels;
51957 +               while (*p) {
51958 +                       if ((*p)->id && ((*p)->id == id)) {
51959 +                               break;
51960 +                       }
51961 +                       p++;
51962 +               }
51963 +               if (!*p) {
51964 +                       printk(KERN_WARNING DRIVER_NAME ":Could not find compatible panel, id=%x\n", id);
51965 +                       return -ENODEV;
51966 +               }
51967 +               ud->panel = *p;
51968 +       }
51969 +
51970 +       /*
51971 +        * Make sure panel ID matches if we were supplied a panel type
51972 +        */
51973 +       if (ud->panel->id && (ud->panel->id != id)) {
51974 +               UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
51975 +
51976 +               return -ENODEV;
51977 +       }
51978 +
51979 +       ubicom32lcd_execute(ud, ud->panel->init_seq);
51980 +
51981 +       ubicom32lcd_goto(ud, 0, 0);
51982 +
51983 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
51984 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
51985 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
51986 +       UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51987 +
51988 +       printk(KERN_INFO DRIVER_NAME ": Initialized panel %s\n", ud->panel->desc);
51989 +
51990 +       return 0;
51991 +}
51992 +
51993 +/*
51994 + * ubicom32lcd_probe
51995 + */
51996 +static int ubicom32lcd_probe(struct platform_device *pdev)
51997 +{
51998 +       const struct ubicom32lcd_platform_data *pdata = pdev->dev.platform_data;
51999 +       struct ubicom32lcd_data *ud;
52000 +       int retval;
52001 +
52002 +       /*
52003 +        * Allocate our private data
52004 +        */
52005 +       ud = kzalloc(sizeof(struct ubicom32lcd_data), GFP_KERNEL);
52006 +       if (!ud) {
52007 +               return -ENOMEM;
52008 +       }
52009 +
52010 +       if (pdata) {
52011 +               ud->pin_cs = pdata->pin_cs;
52012 +               ud->pin_rd = pdata->pin_rd;
52013 +               ud->pin_wr = pdata->pin_wr;
52014 +               ud->pin_rs = pdata->pin_rs;
52015 +               ud->pin_reset = pdata->pin_reset;
52016 +               ud->port_data = pdata->port_data;
52017 +               ud->data_shift = pdata->data_shift;
52018 +       } else {
52019 +               /*
52020 +                * Defaults
52021 +                */
52022 +               ud->pin_cs = GPIO_RD_4;
52023 +               ud->pin_rd = GPIO_RD_5;
52024 +               ud->pin_rs = GPIO_RD_3;
52025 +               ud->pin_wr = GPIO_RD_2;
52026 +               ud->pin_reset = GPIO_RD_7;
52027 +               ud->port_data = (struct ubicom32_io_port *)RI;
52028 +               ud->data_shift = 0;
52029 +       }
52030 +
52031 +       /*
52032 +        * Initialize the display
52033 +        */
52034 +       retval = ubicom32lcd_panel_init(ud);
52035 +       if (retval) {
52036 +               kfree(ud);
52037 +               return retval;
52038 +       }
52039 +
52040 +       printk(KERN_INFO DRIVER_NAME ": LCD initialized\n");
52041 +
52042 +       return 0;
52043 +}
52044 +
52045 +/*
52046 + * ubicom32lcd_remove
52047 + */
52048 +static int __exit ubicom32lcd_remove(struct platform_device *pdev)
52049 +{
52050 +       struct ubicom32lcd_data *ud = platform_get_drvdata(pdev);
52051 +
52052 +       kfree(ud);
52053 +
52054 +       return 0;
52055 +}
52056 +
52057 +static struct platform_driver ubicom32lcd_driver = {
52058 +       .probe          = ubicom32lcd_probe,
52059 +       .remove         = ubicom32lcd_remove,
52060 +
52061 +       .driver = {
52062 +               .name = DRIVER_NAME,
52063 +               .owner = THIS_MODULE,
52064 +       },
52065 +
52066 +       .remove = __exit_p(ubicom32lcd_remove),
52067 +};
52068 +
52069 +static struct platform_device *ubicom32lcd_device;
52070 +
52071 +/*
52072 + * ubicom32lcd_init
52073 + */
52074 +static int __init ubicom32lcd_init(void)
52075 +{
52076 +       int res;
52077 +
52078 +       res = platform_driver_register(&ubicom32lcd_driver);
52079 +       if (res == 0) {
52080 +               ubicom32lcd_device = platform_device_alloc(DRIVER_NAME, 0);
52081 +               if (ubicom32lcd_device) {
52082 +                       res = platform_device_add(ubicom32lcd_device);
52083 +               } else {
52084 +                       res = -ENOMEM;
52085 +               }
52086 +               if (res) {
52087 +                       platform_device_put(ubicom32lcd_device);
52088 +                       platform_driver_unregister(&ubicom32lcd_driver);
52089 +               }
52090 +       }
52091 +       return res;
52092 +}
52093 +module_init(ubicom32lcd_init);
52094 +
52095 +/*
52096 + * ubicom32lcd_exit
52097 + */
52098 +static void __exit ubicom32lcd_exit(void)
52099 +{
52100 +       platform_device_unregister(ubicom32lcd_device);
52101 +       platform_driver_unregister(&ubicom32lcd_driver);
52102 +}
52103 +module_exit(ubicom32lcd_exit);
52104 +
52105 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52106 +MODULE_DESCRIPTION("Ubicom32 LCD driver");
52107 +MODULE_LICENSE("GPL");
52108 --- /dev/null
52109 +++ b/drivers/video/backlight/ubicom32lcd.h
52110 @@ -0,0 +1,546 @@
52111 +/*
52112 + * ubicom32lcd.h
52113 + *     Ubicom32 lcd panel drivers
52114 + *
52115 + * (C) Copyright 2009, Ubicom, Inc.
52116 + *
52117 + * This file is part of the Ubicom32 Linux Kernel Port.
52118 + *
52119 + * This Ubicom32 library is free software: you can redistribute
52120 + * it and/or modify it under the terms of the GNU General Public License
52121 + * as published by the Free Software Foundation, either version 2 of the
52122 + * License, or (at your option) any later version.
52123 + *
52124 + * This Ubicom32 library is distributed in the hope that it
52125 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52126 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
52127 + * the GNU General Public License for more details.
52128 + *
52129 + * You should have received a copy of the GNU General Public License
52130 + * along with the Ubicom32 Linux Kernel Port.  If not,
52131 + * see <http://www.gnu.org/licenses/>.
52132 + */
52133 +
52134 +#ifndef _UBICOM32LCD_H_
52135 +#define _UBICOM32LCD_H_
52136 +
52137 +enum ubicom32lcd_op {
52138 +       /*
52139 +        * Sleep for (data) ms
52140 +        */
52141 +       LCD_STEP_SLEEP,
52142 +
52143 +       /*
52144 +        * Execute write of command
52145 +        */
52146 +       LCD_STEP_CMD,
52147 +
52148 +       /*
52149 +        * Execute write of data
52150 +        */
52151 +       LCD_STEP_DATA,
52152 +
52153 +       /*
52154 +        * Execute write of command/data
52155 +        */
52156 +       LCD_STEP_CMD_DATA,
52157 +
52158 +       /*
52159 +        * Script done
52160 +        */
52161 +       LCD_STEP_DONE,
52162 +};
52163 +
52164 +struct ubicom32lcd_step {
52165 +       enum ubicom32lcd_op             op;
52166 +       u16                             cmd;
52167 +       u16                             data;
52168 +};
52169 +
52170 +struct ubicom32lcd_panel {
52171 +       const struct ubicom32lcd_step   *init_seq;
52172 +       const char                      *desc;
52173 +
52174 +       u32                             xres;
52175 +       u32                             yres;
52176 +       u32                             stride;
52177 +       u32                             flags;
52178 +
52179 +       u16                             id;
52180 +       u16                             horz_reg;
52181 +       u16                             vert_reg;
52182 +       u16                             gram_reg;
52183 +};
52184 +
52185 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS
52186 +static const struct ubicom32lcd_step cfaf240320ktts_init_0[] = {
52187 +       {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h)          Page 14, SPFD5408B Datasheet
52188 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h)            Page 15, SPFD5408B Datasheet
52189 +       {LCD_STEP_CMD_DATA, 0x0003, 0x50A0,}, // Entry Mode (R03h)                              0 degrees
52190 +       {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h)                Page 16, SPFD5408B Datasheet
52191 +       {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h)                       Page 17, SPFD5408B Datasheet
52192 +       {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h)                       Page 18, SPFD5408B Datasheet
52193 +       {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah)                     Page 19, SPFD5408B Datasheet
52194 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch)    Page 20, SPFD5408B Datasheet
52195 +       {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh)                    Page 21, SPFD5408B Datasheet
52196 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh)    Page 21, SPFD5408B Datasheet
52197 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52198 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52199 +       {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52200 +       {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52201 +       {LCD_STEP_SLEEP, 0, 200},
52202 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52203 +       {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52204 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52205 +       {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52206 +       {LCD_STEP_SLEEP, 0, 50},
52207 +       {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52208 +       {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h)                         Page 30, SPFD5408B Datasheet
52209 +       {LCD_STEP_SLEEP, 0, 50},
52210 +       {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1                                Page 32, SPFD5408B Datasheet
52211 +       {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2                                Page 32, SPFD5408B Datasheet
52212 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3                                Page 32, SPFD5408B Datasheet
52213 +       {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4                                Page 32, SPFD5408B Datasheet
52214 +       {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5                                Page 32, SPFD5408B Datasheet
52215 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6                                Page 32, SPFD5408B Datasheet
52216 +       {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7                                Page 32, SPFD5408B Datasheet
52217 +       {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8                                Page 32, SPFD5408B Datasheet
52218 +       {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9                                Page 32, SPFD5408B Datasheet
52219 +       {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10                               Page 32, SPFD5408B Datasheet
52220 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11                               Page 32, SPFD5408B Datasheet
52221 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12                               Page 32, SPFD5408B Datasheet
52222 +       {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13                               Page 32, SPFD5408B Datasheet
52223 +       {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14                               Page 32, SPFD5408B Datasheet
52224 +       {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15                               Page 32, SPFD5408B Datasheet
52225 +       {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16                               Page 32, SPFD5408B Datasheet
52226 +       {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h)     Page 32, SPFD5408B Datasheet
52227 +       {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h)       Page 32, SPFD5408B Datasheet
52228 +       {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h)       Page 33, SPFD5408B Datasheet
52229 +       {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h)         Page 33, SPFD5408B Datasheet
52230 +       {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h)                   Page 33, SPFD5408B Datasheet
52231 +       {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h)                   Page 35, SPFD5408B Datasheet
52232 +       {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah)                 Page 35, SPFD5408B Datasheet
52233 +       {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h)    Page 35, SPFD5408B Datasheet
52234 +       {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h)   Page 35, SPFD5408B Datasheet
52235 +       {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h)     Page 36, SPFD5408B Datasheet
52236 +       {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h)    Page 36, SPFD5408B Datasheet
52237 +       {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h)   Page 36, SPFD5408B Datasheet
52238 +       {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h)     Page 36, SPFD5408B Datasheet
52239 +       {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h)               Page 36, SPFD5408B Datasheet
52240 +       {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h)               Page 37, SPFD5408B Datasheet
52241 +       {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h)               Page 38, SPFD5408B Datasheet
52242 +       {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h)               Page 38, SPFD5408B Datasheet
52243 +       {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h)               Page 40, SPFD5408B Datasheet
52244 +       {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h)               Page 41, SPFD5408B Datasheet
52245 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52246 +       {LCD_STEP_DONE, 0, 0},
52247 +};
52248 +
52249 +const struct ubicom32lcd_panel cfaf240320ktts_0 = {
52250 +       .desc           = "CFAF240320KTTS",
52251 +       .init_seq       = cfaf240320ktts_init_0,
52252 +       .horz_reg       = 0x20,
52253 +       .vert_reg       = 0x21,
52254 +       .gram_reg       = 0x22,
52255 +       .xres           = 240,
52256 +       .yres           = 320,
52257 +       .stride         = 240,
52258 +       .id             = 0x5408,
52259 +};
52260 +#endif
52261 +
52262 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS_180
52263 +static const struct ubicom32lcd_step cfaf240320ktts_init_180[] = {
52264 +       {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h)          Page 14, SPFD5408B Datasheet
52265 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h)            Page 15, SPFD5408B Datasheet
52266 +       {LCD_STEP_CMD_DATA, 0x0003, 0x5000,}, // Entry Mode (R03h)                              180 degrees
52267 +       {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h)                Page 16, SPFD5408B Datasheet
52268 +       {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h)                       Page 17, SPFD5408B Datasheet
52269 +       {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h)                       Page 18, SPFD5408B Datasheet
52270 +       {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah)                     Page 19, SPFD5408B Datasheet
52271 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch)    Page 20, SPFD5408B Datasheet
52272 +       {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh)                    Page 21, SPFD5408B Datasheet
52273 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh)    Page 21, SPFD5408B Datasheet
52274 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52275 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52276 +       {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52277 +       {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52278 +       {LCD_STEP_SLEEP, 0, 200},
52279 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52280 +       {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h)                         Page 22, SPFD5408B Datasheet
52281 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h)                         Page 23, SPFD5408B Datasheet
52282 +       {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h)                         Page 24, SPFD5408B Datasheet
52283 +       {LCD_STEP_SLEEP, 0, 50},
52284 +       {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h)                         Page 25, SPFD5408B Datasheet
52285 +       {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h)                         Page 30, SPFD5408B Datasheet
52286 +       {LCD_STEP_SLEEP, 0, 50},
52287 +       {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1                                Page 32, SPFD5408B Datasheet
52288 +       {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2                                Page 32, SPFD5408B Datasheet
52289 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3                                Page 32, SPFD5408B Datasheet
52290 +       {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4                                Page 32, SPFD5408B Datasheet
52291 +       {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5                                Page 32, SPFD5408B Datasheet
52292 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6                                Page 32, SPFD5408B Datasheet
52293 +       {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7                                Page 32, SPFD5408B Datasheet
52294 +       {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8                                Page 32, SPFD5408B Datasheet
52295 +       {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9                                Page 32, SPFD5408B Datasheet
52296 +       {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10                               Page 32, SPFD5408B Datasheet
52297 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11                               Page 32, SPFD5408B Datasheet
52298 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12                               Page 32, SPFD5408B Datasheet
52299 +       {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13                               Page 32, SPFD5408B Datasheet
52300 +       {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14                               Page 32, SPFD5408B Datasheet
52301 +       {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15                               Page 32, SPFD5408B Datasheet
52302 +       {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16                               Page 32, SPFD5408B Datasheet
52303 +       {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h)     Page 32, SPFD5408B Datasheet
52304 +       {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h)       Page 32, SPFD5408B Datasheet
52305 +       {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h)       Page 33, SPFD5408B Datasheet
52306 +       {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h)         Page 33, SPFD5408B Datasheet
52307 +       {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h)                   Page 33, SPFD5408B Datasheet
52308 +       {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h)                   Page 35, SPFD5408B Datasheet
52309 +       {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah)                 Page 35, SPFD5408B Datasheet
52310 +       {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h)    Page 35, SPFD5408B Datasheet
52311 +       {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h)   Page 35, SPFD5408B Datasheet
52312 +       {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h)     Page 36, SPFD5408B Datasheet
52313 +       {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h)    Page 36, SPFD5408B Datasheet
52314 +       {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h)   Page 36, SPFD5408B Datasheet
52315 +       {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h)     Page 36, SPFD5408B Datasheet
52316 +       {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h)               Page 36, SPFD5408B Datasheet
52317 +       {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h)               Page 37, SPFD5408B Datasheet
52318 +       {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h)               Page 38, SPFD5408B Datasheet
52319 +       {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h)               Page 38, SPFD5408B Datasheet
52320 +       {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h)               Page 40, SPFD5408B Datasheet
52321 +       {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h)               Page 41, SPFD5408B Datasheet
52322 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h)                         Page 16, SPFD5408B Datasheet
52323 +       {LCD_STEP_DONE, 0, 0},
52324 +};
52325 +
52326 +const struct ubicom32lcd_panel cfaf240320ktts_180 = {
52327 +       .desc           = "CFAF240320KTTS 180",
52328 +       .init_seq       = cfaf240320ktts_init_180,
52329 +       .horz_reg       = 0x20,
52330 +       .vert_reg       = 0x21,
52331 +       .gram_reg       = 0x22,
52332 +       .xres           = 240,
52333 +       .yres           = 320,
52334 +       .stride         = 240,
52335 +       .id             = 0x5408,
52336 +};
52337 +#endif
52338 +
52339 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52340 +static const struct ubicom32lcd_step tft2n0369ep_init[] = {
52341 +       {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52342 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52343 +       {LCD_STEP_SLEEP, 0, 15},
52344 +       {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52345 +       {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52346 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52347 +       {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52348 +       {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52349 +       {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52350 +       {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52351 +       {LCD_STEP_SLEEP, 0, 15},
52352 +       {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52353 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52354 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52355 +       {LCD_STEP_CMD_DATA, 0x0011, 0x6030},
52356 +       {LCD_STEP_SLEEP, 0, 20},
52357 +       {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52358 +       {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52359 +       {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52360 +       {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52361 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52362 +       {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52363 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52364 +       {LCD_STEP_SLEEP, 0, 20},
52365 +       {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52366 +       {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52367 +       {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52368 +       {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52369 +       {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52370 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52371 +       {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52372 +       {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52373 +       {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52374 +       {LCD_STEP_SLEEP, 0, 20},
52375 +       {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52376 +       {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52377 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52378 +       {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52379 +       {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52380 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52381 +       {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52382 +       {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52383 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52384 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52385 +       {LCD_STEP_SLEEP, 0, 20},
52386 +       {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52387 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52388 +       {LCD_STEP_CMD_DATA, 0x0046, 319},
52389 +       {LCD_STEP_DONE, 0, 0},
52390 +};
52391 +
52392 +const struct ubicom32lcd_panel tft2n0369ep = {
52393 +       .desc           = "TFT2N0369E-Portrait",
52394 +       .init_seq       = tft2n0369ep_init,
52395 +       .horz_reg       = 0x4e,
52396 +       .vert_reg       = 0x4f,
52397 +       .gram_reg       = 0x22,
52398 +       .xres           = 240,
52399 +       .yres           = 320,
52400 +       .stride         = 240,
52401 +       .id             = 0x8989,
52402 +};
52403 +#endif
52404 +
52405 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52406 +static const struct ubicom32lcd_step tft2n0369e_init[] = {
52407 +       {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52408 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52409 +       {LCD_STEP_SLEEP, 0, 15},
52410 +       {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52411 +       {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52412 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52413 +       {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52414 +       {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52415 +       {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52416 +       {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52417 +       {LCD_STEP_SLEEP, 0, 15},
52418 +       {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52419 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52420 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52421 +       {LCD_STEP_CMD_DATA, 0x0011, 0x60A8},
52422 +       {LCD_STEP_SLEEP, 0, 20},
52423 +       {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52424 +       {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52425 +       {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52426 +       {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52427 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52428 +       {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52429 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52430 +       {LCD_STEP_SLEEP, 0, 20},
52431 +       {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52432 +       {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52433 +       {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52434 +       {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52435 +       {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52436 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52437 +       {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52438 +       {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52439 +       {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52440 +       {LCD_STEP_SLEEP, 0, 20},
52441 +       {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52442 +       {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52443 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52444 +       {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52445 +       {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52446 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52447 +       {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52448 +       {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52449 +       {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52450 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52451 +       {LCD_STEP_SLEEP, 0, 20},
52452 +       {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52453 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52454 +       {LCD_STEP_CMD_DATA, 0x0046, 319},
52455 +       {LCD_STEP_DONE, 0, 0},
52456 +};
52457 +
52458 +const struct ubicom32lcd_panel tft2n0369e = {
52459 +       .desc           = "TFT2N0369E-Landscape",
52460 +       .init_seq       = tft2n0369e_init,
52461 +       .horz_reg       = 0x4e,
52462 +       .vert_reg       = 0x4f,
52463 +       .gram_reg       = 0x22,
52464 +       .xres           = 320,
52465 +       .yres           = 240,
52466 +       .stride         = 320,
52467 +       .id             = 0x8989,
52468 +};
52469 +#endif
52470 +
52471 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52472 +static const struct ubicom32lcd_step cfaf240400d_init[] = {
52473 +       {LCD_STEP_CMD_DATA, 0x0606, 0x0000},    // Pin Control (R606h)          // Page 41 of SPFD5420A Datasheet
52474 +       {LCD_STEP_SLEEP, 0, 50},
52475 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0001},    // Display Control 1 (R007h)    // Page 16 of SPFD5420A Datasheet
52476 +       {LCD_STEP_SLEEP, 0, 50},
52477 +       {LCD_STEP_CMD_DATA, 0x0110, 0x0001},    // Power Control 6(R110h)       // Page 30 of SPFD5420A Datasheet
52478 +       {LCD_STEP_SLEEP, 0, 50},
52479 +       {LCD_STEP_CMD_DATA, 0x0100, 0x17B0},    // Power Control 1 (R100h)      // Page 26 of SPFD5420A Datasheet
52480 +       {LCD_STEP_CMD_DATA, 0x0101, 0x0147},    // Power Control 2 (R101h)      // Page 27 of SPFD5420A Datasheet
52481 +       {LCD_STEP_CMD_DATA, 0x0102, 0x019D},    // Power Control 3 (R102h)      // Page 28 of SPFD5420A Datasheet
52482 +       {LCD_STEP_CMD_DATA, 0x0103, 0x3600},    // Power Control 4 (R103h)      // Page 29 of SPFD5420A Datasheet
52483 +       {LCD_STEP_CMD_DATA, 0x0281, 0x0010},    // NVM read data 2 (R281h)      // Page 34 of SPFD5420A Datasheet
52484 +       {LCD_STEP_SLEEP, 0, 50},
52485 +       {LCD_STEP_CMD_DATA, 0x0102, 0x01BD},    // Power Control 3 (R102h)      // Page 28 of SPFD5420A Datasheet
52486 +       {LCD_STEP_SLEEP, 0, 50},
52487 +
52488 +       //--------------- Power control 1~6 ---------------//
52489 +       {LCD_STEP_CMD_DATA, 0x0100, 0x16B0},    // Power Control 1 (R100h)      // Page 26 of SPFD5420A Datasheet
52490 +       {LCD_STEP_CMD_DATA, 0x0101, 0x0147},    // Power Control 2 (R101h)      // Page 27 of SPFD5420A Datasheet
52491 +       {LCD_STEP_CMD_DATA, 0x0102, 0x01BD},    // Power Control 3 (R102h)      // Page 28 of SPFD5420A Datasheet
52492 +       {LCD_STEP_CMD_DATA, 0x0103, 0x2d00},    // Power Control 4 (R103h)      // Page 29 of SPFD5420A Datasheet
52493 +       {LCD_STEP_CMD_DATA, 0x0107, 0x0000},    // Power Control 5 (R107h)      // Page 30 of SPFD5420A Datasheet
52494 +       {LCD_STEP_CMD_DATA, 0x0110, 0x0001},    // Power Control 6(R110h)       // Page 30 of SPFD5420A Datasheet
52495 +       {LCD_STEP_CMD_DATA, 0x0280, 0x0000},    // NVM read data 1 (R280h)      // Page 33 of SPFD5420A Datasheet
52496 +       {LCD_STEP_CMD_DATA, 0x0281, 0x0006},    // NVM read data 2 (R281h)      // Page 34 of SPFD5420A Datasheet
52497 +       {LCD_STEP_CMD_DATA, 0x0282, 0x0000},    // NVM read data 3 (R282h)      // Page 34 of SPFD5420A Datasheet
52498 +
52499 +       //------- Gamma 2.2 control (R300h to R30Fh) ------//
52500 +       {LCD_STEP_CMD_DATA, 0x0300, 0x0101},
52501 +       {LCD_STEP_CMD_DATA, 0x0301, 0x0b27},
52502 +       {LCD_STEP_CMD_DATA, 0x0302, 0x132a},
52503 +       {LCD_STEP_CMD_DATA, 0x0303, 0x2a13},
52504 +       {LCD_STEP_CMD_DATA, 0x0304, 0x270b},
52505 +       {LCD_STEP_CMD_DATA, 0x0305, 0x0101},
52506 +       {LCD_STEP_CMD_DATA, 0x0306, 0x1205},
52507 +       {LCD_STEP_CMD_DATA, 0x0307, 0x0512},
52508 +       {LCD_STEP_CMD_DATA, 0x0308, 0x0005},
52509 +       {LCD_STEP_CMD_DATA, 0x0309, 0x0003},
52510 +       {LCD_STEP_CMD_DATA, 0x030A, 0x0f04},
52511 +       {LCD_STEP_CMD_DATA, 0x030B, 0x0f00},
52512 +       {LCD_STEP_CMD_DATA, 0x030C, 0x000f},
52513 +       {LCD_STEP_CMD_DATA, 0x030D, 0x040f},
52514 +       {LCD_STEP_CMD_DATA, 0x030E, 0x0300},
52515 +       {LCD_STEP_CMD_DATA, 0x030F, 0x0500},
52516 +
52517 +       {LCD_STEP_CMD_DATA, 0x0400, 0x3500},    // Base Image Number of Line (R400h)            // Page 36 of SPFD5420A Datasheet
52518 +       {LCD_STEP_CMD_DATA, 0x0401, 0x0001},    // Base Image Display Control (R401h)           // Page 39 of SPFD5420A Datasheet
52519 +       {LCD_STEP_CMD_DATA, 0x0404, 0x0000},    // Based Image Vertical Scroll Control (R404h)  // Page 40 of SPFD5420A Datasheet
52520 +
52521 +       //--------------- Normal set ---------------//
52522 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0000},    // ID Read Register (R000h)                     // Page 13 of SPFD5420A Datasheet
52523 +       {LCD_STEP_CMD_DATA, 0x0001, 0x0100},    // Driver Output Control Register (R001h)       // Page 14 of SPFD5420A Datasheet
52524 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0100},    // LCD Driving Waveform Control (R002h)         // Page 14 of SPFD5420A Datasheet
52525 +       {LCD_STEP_CMD_DATA, 0x0003, 0x1030},    // Entry Mode (R003h)                           // Page 15 of SPFD5420A Datasheet
52526 +       {LCD_STEP_CMD_DATA, 0x0006, 0x0000},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52527 +       {LCD_STEP_CMD_DATA, 0x0008, 0x0808},    // Display Control 2 (R008h)                    // Page 17 of SPFD5420A Datasheet
52528 +       {LCD_STEP_CMD_DATA, 0x0009, 0x0001},    // Display Control 3 (R009h)                    // Page 18 of SPFD5420A Datasheet
52529 +       {LCD_STEP_CMD_DATA, 0x000B, 0x0010},    // Low Power Control (R00Bh)                    // Page 19 of SPFD5420A Datasheet
52530 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0000},    // External Display Interface Control 1 (R00Ch) // Page 19 of SPFD5420A Datasheet
52531 +       {LCD_STEP_CMD_DATA, 0x000F, 0x0000},    // External Display Interface Control 2 (R00Fh) // Page 20 of SPFD5420A Datasheet
52532 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0001},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52533 +
52534 +       //--------------- Panel interface control 1~6 ---------------//
52535 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0012},    // Panel Interface Control 1 (R010h)            // Page 20 of SPFD5420A Datasheet
52536 +       {LCD_STEP_CMD_DATA, 0x0011, 0x0202},    // Panel Interface Control 2 (R011h)            // Page 21 of SPFD5420A Datasheet
52537 +       {LCD_STEP_CMD_DATA, 0x0012, 0x0300},    // Panel Interface control 3 (R012h)            // Page 22 of SPFD5420A Datasheet
52538 +       {LCD_STEP_CMD_DATA, 0x0020, 0x021E},    // Panel Interface control 4 (R020h)            // Page 22 of SPFD5420A Datasheet
52539 +       {LCD_STEP_CMD_DATA, 0x0021, 0x0202},    // Panel Interface Control 5 (021Rh)            // Page 24 of SPFD5420A Datasheet
52540 +       {LCD_STEP_CMD_DATA, 0x0022, 0x0100},    // Panel Interface Control 6 (R022h)            // Page 25 of SPFD5420A Datasheet
52541 +       {LCD_STEP_CMD_DATA, 0x0090, 0x8000},    // Frame Marker Control (R090h)                 // Page 25 of SPFD5420A Datasheet
52542 +
52543 +       //--------------- Partial display ---------------//
52544 +       {LCD_STEP_CMD_DATA, 0x0210, 0x0000},    // Window Horizontal RAM Address Start (R210h)  // Page 35 of SPFD5420A Datasheet
52545 +       {LCD_STEP_CMD_DATA, 0x0211, 0x00EF},    // Window Horziontal RAM Address End (R211h)    // Page 35 of SPFD5420A Datasheet
52546 +       {LCD_STEP_CMD_DATA, 0x0212, 0x0000},    // Window Vertical RAM Address Start (R212h)    // Page 35 of SPFD5420A Datasheet
52547 +       {LCD_STEP_CMD_DATA, 0x0213, 0x018F},    // Window Vertical RAM Address End (R213h)      // Page 35 of SPFD5420A Datasheet
52548 +       {LCD_STEP_CMD_DATA, 0x0500, 0x0000},    // Display Position - Partial Display 1 (R500h) // Page 40 of SPFD5420A Datasheet
52549 +       {LCD_STEP_CMD_DATA, 0x0501, 0x0000},    // RAM Address Start - Partial Display 1 (R501h)// Page 40 of SPFD5420A Datasheet
52550 +       {LCD_STEP_CMD_DATA, 0x0502, 0x0000},    // RAM Address End - Partail Display 1 (R502h)  // Page 40 of SPFD5420A Datasheet
52551 +       {LCD_STEP_CMD_DATA, 0x0503, 0x0000},    // Display Position - Partial Display 2 (R503h) // Page 40 of SPFD5420A Datasheet
52552 +       {LCD_STEP_CMD_DATA, 0x0504, 0x0000},    // RAM Address Start . Partial Display 2 (R504h)// Page 41 of SPFD5420A Datasheet
52553 +       {LCD_STEP_CMD_DATA, 0x0505, 0x0000},    // RAM Address End . Partial Display 2 (R505h)  // Page 41 of SPFD5420A Datasheet
52554 +       {LCD_STEP_CMD_DATA, 0x0606, 0x0000},    // Pin Control (R606h)                          // Page 41 of SPFD5420A Datasheet
52555 +       {LCD_STEP_CMD_DATA, 0x06F0, 0x0000},    // NVM Access Control (R6F0h)                   // Page 41 of SPFD5420A Datasheet
52556 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52557 +       {LCD_STEP_SLEEP, 0, 50},
52558 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0171},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52559 +       {LCD_STEP_SLEEP, 0, 10},
52560 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0173},    // Display Control 1 (R007h)                    // Page 16 of SPFD5420A Datasheet
52561 +       {LCD_STEP_DONE, 0, 0},
52562 +};
52563 +
52564 +const struct ubicom32lcd_panel cfaf240400d = {
52565 +       .desc           = "CFAF240400D",
52566 +       .init_seq       = cfaf240400d_init,
52567 +       .horz_reg       = 0x0200,
52568 +       .vert_reg       = 0x0201,
52569 +       .gram_reg       = 0x0202,
52570 +       .xres           = 240,
52571 +       .yres           = 400,
52572 +       .stride         = 240,
52573 +       .id             = 0x5420,
52574 +};
52575 +#endif
52576 +
52577 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52578 +static const struct ubicom32lcd_step cfaf320240f_init[] = {
52579 +       {LCD_STEP_CMD_DATA, 0x0028, 0x0006},    // VCOM OTP                             Page 55-56 of SSD2119 datasheet
52580 +       {LCD_STEP_CMD_DATA, 0x0000, 0x0001},    // start Oscillator                     Page 36 of SSD2119 datasheet
52581 +       {LCD_STEP_CMD_DATA, 0x0010, 0x0000},    // Sleep mode                           Page 49 of SSD2119 datasheet
52582 +       {LCD_STEP_CMD_DATA, 0x0001, 0x32EF},    // Driver Output Control                Page 36-39 of SSD2119 datasheet
52583 +       {LCD_STEP_CMD_DATA, 0x0002, 0x0600},    // LCD Driving Waveform Control         Page 40-42 of SSD2119 datasheet
52584 +       {LCD_STEP_CMD_DATA, 0x0003, 0x6A38},    // Power Control 1                      Page 43-44 of SSD2119 datasheet
52585 +       {LCD_STEP_CMD_DATA, 0x0011, 0x6870},    // Entry Mode                           Page 50-52 of SSD2119 datasheet
52586 +       {LCD_STEP_CMD_DATA, 0X000F, 0x0000},    // Gate Scan Position                   Page 49 of SSD2119 datasheet
52587 +       {LCD_STEP_CMD_DATA, 0X000B, 0x5308},    // Frame Cycle Control                  Page 45 of SSD2119 datasheet
52588 +       {LCD_STEP_CMD_DATA, 0x000C, 0x0003},    // Power Control 2                      Page 47 of SSD2119 datasheet
52589 +       {LCD_STEP_CMD_DATA, 0x000D, 0x000A},    // Power Control 3                      Page 48 of SSD2119 datasheet
52590 +       {LCD_STEP_CMD_DATA, 0x000E, 0x2E00},    // Power Control 4                      Page 48 of SSD2119 datasheet
52591 +       {LCD_STEP_CMD_DATA, 0x001E, 0x00BE},    // Power Control 5                      Page 53 of SSD2119 datasheet
52592 +       {LCD_STEP_CMD_DATA, 0x0025, 0x8000},    // Frame Frequency Control              Page 53 of SSD2119 datasheet
52593 +       {LCD_STEP_CMD_DATA, 0x0026, 0x7800},    // Analog setting                       Page 54 of SSD2119 datasheet
52594 +       {LCD_STEP_CMD_DATA, 0x004E, 0x0000},    // Ram Address Set                      Page 58 of SSD2119 datasheet
52595 +       {LCD_STEP_CMD_DATA, 0x004F, 0x0000},    // Ram Address Set                      Page 58 of SSD2119 datasheet
52596 +       {LCD_STEP_CMD_DATA, 0x0012, 0x08D9},    // Sleep mode                           Page 49 of SSD2119 datasheet
52597 +
52598 +       // Gamma Control (R30h to R3Bh) -- Page 56 of SSD2119 datasheet
52599 +       {LCD_STEP_CMD_DATA, 0x0030, 0x0000},
52600 +       {LCD_STEP_CMD_DATA, 0x0031, 0x0104},
52601 +       {LCD_STEP_CMD_DATA, 0x0032, 0x0100},
52602 +       {LCD_STEP_CMD_DATA, 0x0033, 0x0305},
52603 +       {LCD_STEP_CMD_DATA, 0x0034, 0x0505},
52604 +       {LCD_STEP_CMD_DATA, 0x0035, 0x0305},
52605 +       {LCD_STEP_CMD_DATA, 0x0036, 0x0707},
52606 +       {LCD_STEP_CMD_DATA, 0x0037, 0x0300},
52607 +       {LCD_STEP_CMD_DATA, 0x003A, 0x1200},
52608 +       {LCD_STEP_CMD_DATA, 0x003B, 0x0800},
52609 +
52610 +       {LCD_STEP_CMD_DATA, 0x0007, 0x0033},    // Display Control                       Page 45 of SSD2119 datasheet
52611 +
52612 +       {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},    // Vertical RAM address position         Page 57 of SSD2119 datasheet
52613 +       {LCD_STEP_CMD_DATA, 0x0045, 0x0000},    // Horizontal RAM address position       Page 57 of SSD2119 datasheet
52614 +       {LCD_STEP_CMD_DATA, 0x0046, 0x013F},    // Horizontal RAM address position       Page 57 of SSD2119 datasheet
52615 +
52616 +       {LCD_STEP_SLEEP, 0, 150},
52617 +
52618 +       {LCD_STEP_DONE, 0, 0},
52619 +};
52620 +
52621 +const struct ubicom32lcd_panel cfaf320240f = {
52622 +       .desc           = "CFAF320240F",
52623 +       .init_seq       = cfaf320240f_init,
52624 +       .horz_reg       = 0x4e,
52625 +       .vert_reg       = 0x4f,
52626 +       .gram_reg       = 0x22,
52627 +       .xres           = 320,
52628 +       .yres           = 240,
52629 +       .stride         = 320,
52630 +       .id             = 0x9919,
52631 +};
52632 +#endif
52633 +
52634 +const struct ubicom32lcd_panel *ubicom32lcd_panels[] = {
52635 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS_180
52636 +       &cfaf240320ktts_180,
52637 +#endif
52638 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS
52639 +       &cfaf240320ktts_0,
52640 +#endif
52641 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52642 +       &cfaf240400d,
52643 +#endif
52644 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52645 +       &tft2n0369ep,
52646 +#endif
52647 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52648 +       &tft2n0369e,
52649 +#endif
52650 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52651 +       &cfaf320240f,
52652 +#endif
52653 +       NULL,
52654 +};
52655 +
52656 +#endif
52657 --- /dev/null
52658 +++ b/drivers/video/backlight/ubicom32lcdpower.c
52659 @@ -0,0 +1,194 @@
52660 +/*
52661 + * drivers/video/backlight/ubicom32lcdpowerpower.c
52662 + *     LCD power driver for the Ubicom32 platform
52663 + *
52664 + * (C) Copyright 2009, Ubicom, Inc.
52665 + *
52666 + * This file is part of the Ubicom32 Linux Kernel Port.
52667 + *
52668 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52669 + * it and/or modify it under the terms of the GNU General Public License
52670 + * as published by the Free Software Foundation, either version 2 of the
52671 + * License, or (at your option) any later version.
52672 + *
52673 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52674 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52675 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
52676 + * the GNU General Public License for more details.
52677 + *
52678 + * You should have received a copy of the GNU General Public License
52679 + * along with the Ubicom32 Linux Kernel Port.  If not,
52680 + * see <http://www.gnu.org/licenses/>.
52681 + *
52682 + * Ubicom32 implementation derived from (with many thanks):
52683 + *   arch/m68knommu
52684 + *   arch/blackfin
52685 + *   arch/parisc
52686 + */
52687 +#include <linux/init.h>
52688 +#include <linux/kernel.h>
52689 +#include <linux/module.h>
52690 +#include <linux/platform_device.h>
52691 +#include <linux/lcd.h>
52692 +#include <linux/fb.h>
52693 +#include <linux/gpio.h>
52694 +
52695 +#include <asm/ubicom32lcdpower.h>
52696 +#include <asm/ip5000.h>
52697 +
52698 +#define DRIVER_NAME                    "ubicom32lcdpower"
52699 +
52700 +struct ubicom32lcdpower_data {
52701 +       /*
52702 +        * Pointer to the platform data structure.  Keep this around since we need values
52703 +        * from it to set the backlight intensity.
52704 +        */
52705 +       const struct ubicom32lcdpower_platform_data     *pdata;
52706 +
52707 +       /*
52708 +        * LCD device, we have to save this for use when we remove ourselves.
52709 +        */
52710 +       struct lcd_device                       *lcddev;
52711 +};
52712 +
52713 +/*
52714 + * ubicom32lcdpower_set_power
52715 + */
52716 +static int ubicom32lcdpower_set_power(struct lcd_device *ld, int power)
52717 +{
52718 +       struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
52719 +       if (power == FB_BLANK_UNBLANK) {
52720 +               gpio_direction_output(ud->pdata->vgh_gpio, ud->pdata->vgh_polarity);
52721 +               return 0;
52722 +       }
52723 +
52724 +       gpio_direction_output(ud->pdata->vgh_gpio, !ud->pdata->vgh_polarity);
52725 +       return 0;
52726 +}
52727 +
52728 +/*
52729 + * ubicom32lcdpower_get_power
52730 + */
52731 +static int ubicom32lcdpower_get_power(struct lcd_device *ld)
52732 +{
52733 +       struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
52734 +       int vgh = gpio_get_value(ud->pdata->vgh_gpio);
52735 +       if ((vgh && ud->pdata->vgh_polarity) || (!vgh && !ud->pdata->vgh_polarity)) {
52736 +               return 1;
52737 +       }
52738 +
52739 +       return 0;
52740 +}
52741 +
52742 +static struct lcd_ops ubicom32lcdpower_ops = {
52743 +       .get_power = ubicom32lcdpower_get_power,
52744 +       .set_power = ubicom32lcdpower_set_power,
52745 +};
52746 +
52747 +/*
52748 + * ubicom32lcdpower_probe
52749 + */
52750 +static int ubicom32lcdpower_probe(struct platform_device *pdev)
52751 +{
52752 +       const struct ubicom32lcdpower_platform_data *pdata = pdev->dev.platform_data;
52753 +       struct ubicom32lcdpower_data *ud;
52754 +       struct lcd_device *lcddev;
52755 +       int retval;
52756 +
52757 +       /*
52758 +        * Check to see if we have any platform data, if we don't have a LCD to control
52759 +        */
52760 +       if (!pdata) {
52761 +               return -ENODEV;
52762 +       }
52763 +
52764 +       /*
52765 +        * Allocate our private data
52766 +        */
52767 +       ud = kzalloc(sizeof(struct ubicom32lcdpower_data), GFP_KERNEL);
52768 +       if (!ud) {
52769 +               return -ENOMEM;
52770 +       }
52771 +
52772 +       ud->pdata = pdata;
52773 +
52774 +       /*
52775 +        * Request our GPIOs
52776 +        */
52777 +       retval = gpio_request(pdata->vgh_gpio, "vgh");
52778 +       if (retval) {
52779 +               dev_err(&pdev->dev, "Failed to allocate vgh GPIO\n");
52780 +               goto fail_gpio;
52781 +       }
52782 +
52783 +       /*
52784 +        * Register our lcd device
52785 +        */
52786 +       lcddev = lcd_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32lcdpower_ops);
52787 +       if (IS_ERR(lcddev)) {
52788 +               retval = PTR_ERR(lcddev);
52789 +               goto fail;
52790 +       }
52791 +
52792 +       ud->lcddev = lcddev;
52793 +       platform_set_drvdata(pdev, ud);
52794 +
52795 +       ubicom32lcdpower_set_power(lcddev, FB_BLANK_UNBLANK);
52796 +
52797 +       printk(KERN_INFO DRIVER_NAME ": LCD driver started\n");
52798 +
52799 +       return 0;
52800 +
52801 +fail:
52802 +       gpio_free(pdata->vgh_gpio);
52803 +
52804 +fail_gpio:
52805 +       platform_set_drvdata(pdev, NULL);
52806 +       kfree(ud);
52807 +       return retval;
52808 +}
52809 +
52810 +/*
52811 + * ubicom32lcdpower_remove
52812 + */
52813 +static int __exit ubicom32lcdpower_remove(struct platform_device *pdev)
52814 +{
52815 +       struct ubicom32lcdpower_data *ud = platform_get_drvdata(pdev);
52816 +
52817 +       lcd_device_unregister(ud->lcddev);
52818 +       platform_set_drvdata(pdev, NULL);
52819 +       kfree(ud);
52820 +
52821 +       return 0;
52822 +}
52823 +
52824 +static struct platform_driver ubicom32lcdpower_driver = {
52825 +       .driver = {
52826 +               .name = DRIVER_NAME,
52827 +               .owner = THIS_MODULE,
52828 +       },
52829 +
52830 +       .remove = __exit_p(ubicom32lcdpower_remove),
52831 +};
52832 +
52833 +/*
52834 + * ubicom32lcdpower_init
52835 + */
52836 +static int __init ubicom32lcdpower_init(void)
52837 +{
52838 +       return platform_driver_probe(&ubicom32lcdpower_driver, ubicom32lcdpower_probe);
52839 +}
52840 +module_init(ubicom32lcdpower_init);
52841 +
52842 +/*
52843 + * ubicom32lcdpower_exit
52844 + */
52845 +static void __exit ubicom32lcdpower_exit(void)
52846 +{
52847 +       platform_driver_unregister(&ubicom32lcdpower_driver);
52848 +}
52849 +module_exit(ubicom32lcdpower_exit);
52850 +
52851 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52852 +MODULE_DESCRIPTION("Ubicom32 lcd power driver");
52853 +MODULE_LICENSE("GPL");
52854 --- a/drivers/video/Kconfig
52855 +++ b/drivers/video/Kconfig
52856 @@ -609,6 +609,50 @@ config FB_BFIN_T350MCQB
52857          This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
52858          It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
52859  
52860 +config FB_UBICOM32
52861 +       tristate "Ubicom32 Frame Buffer driver"
52862 +       depends on FB && UBICOM32
52863 +       select FB_CFB_FILLRECT
52864 +       select FB_CFB_COPYAREA
52865 +       select FB_CFB_IMAGEBLIT
52866 +       select FONT_6x11 if FRAMEBUFFER_CONSOLE
52867 +       help
52868 +        This is the framebuffer device driver for the Ubicom32 architecture.
52869 +        You can configure video memory by using kernel command line parameters, for example:
52870 +               video=ubicomfb:vram_size=512,init_value=0xffff
52871 +
52872 +config FB_UBICOM32_PLIO80
52873 +       tristate "Ubicom32 80 Bus PLIO Frame Buffer driver"
52874 +       depends on FB && UBICOM32
52875 +       select FB_CFB_FILLRECT
52876 +       select FB_CFB_COPYAREA
52877 +       select FB_CFB_IMAGEBLIT
52878 +       select FONT_6x11 if FRAMEBUFFER_CONSOLE
52879 +       select UBICOM32_PLIO
52880 +       help
52881 +        This is a framebuffer device driver for the Ubicom32 architecture.
52882 +        You can configure the xres, yres and vram size (in kilobytes) by using
52883 +        kernel command line parameters, for example:
52884 +               video=ubicom32vfb:xres=320,yres=240,vram_size=512
52885 +
52886 +config FB_UBICOM32_VIRTUAL
52887 +       tristate "Ubicom32 Virtual Frame Buffer driver"
52888 +       depends on FB && UBICOM32
52889 +       select FB_CFB_FILLRECT
52890 +       select FB_CFB_COPYAREA
52891 +       select FB_CFB_IMAGEBLIT
52892 +       select FONT_6x11 if FRAMEBUFFER_CONSOLE
52893 +       help
52894 +        This is a virtual framebuffer device driver for the Ubicom32 architecture.
52895 +        You can configure the xres, yres and vram size (in kilobytes) by using
52896 +        kernel command line parameters, for example:
52897 +               video=ubicom32vfb:xres=320,yres=240,vram_size=512
52898 +
52899 +config FB_UBICOM32_VIRTUAL_NOAUTO
52900 +       bool "Do not automatically load"
52901 +       depends on FB_UBICOM32_VIRTUAL
52902 +       help
52903 +        Select this option to prevent the VFB from automatically loading at boot.
52904  
52905  config FB_STI
52906         tristate "HP STI frame buffer device support"
52907 --- a/drivers/video/Makefile
52908 +++ b/drivers/video/Makefile
52909 @@ -136,6 +136,10 @@ obj-$(CONFIG_FB_BF54X_LQ043)         += bf54x-
52910  obj-$(CONFIG_FB_BFIN_T350MCQB)   += bfin-t350mcqb-fb.o
52911  obj-$(CONFIG_FB_MX3)             += mx3fb.o
52912  
52913 +obj-$(CONFIG_FB_UBICOM32)         += ubicom32fb.o
52914 +obj-$(CONFIG_FB_UBICOM32_PLIO80)  += ubicom32plio80.o
52915 +obj-$(CONFIG_FB_UBICOM32_VIRTUAL) += ubicom32vfb.o
52916 +
52917  # the test framebuffer is last
52918  obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
52919  
52920 --- /dev/null
52921 +++ b/drivers/video/ubicom32fb.c
52922 @@ -0,0 +1,779 @@
52923 +/*
52924 + * drivers/video/ubicom32fb.c
52925 + *     Ubicom32 frame buffer driver
52926 + *
52927 + * (C) Copyright 2009, Ubicom, Inc.
52928 + *
52929 + * This file is part of the Ubicom32 Linux Kernel Port.
52930 + *
52931 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52932 + * it and/or modify it under the terms of the GNU General Public License
52933 + * as published by the Free Software Foundation, either version 2 of the
52934 + * License, or (at your option) any later version.
52935 + *
52936 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52937 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52938 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
52939 + * the GNU General Public License for more details.
52940 + *
52941 + * You should have received a copy of the GNU General Public License
52942 + * along with the Ubicom32 Linux Kernel Port.  If not,
52943 + * see <http://www.gnu.org/licenses/>.
52944 + *
52945 + * Ubicom32 implementation derived from (with many thanks):
52946 + *   arch/m68knommu
52947 + *   arch/blackfin
52948 + *   arch/parisc
52949 + */
52950 +
52951 +/*
52952 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
52953 + * Geert Uytterhoeven.
52954 + */
52955 +
52956 +#include <linux/device.h>
52957 +#include <linux/module.h>
52958 +#include <linux/kernel.h>
52959 +#include <linux/version.h>
52960 +#include <linux/errno.h>
52961 +#include <linux/string.h>
52962 +#include <linux/mm.h>
52963 +#include <linux/fb.h>
52964 +#include <linux/init.h>
52965 +#include <linux/dma-mapping.h>
52966 +#include <linux/platform_device.h>
52967 +#include <linux/device.h>
52968 +#include <linux/uaccess.h>
52969 +#include <linux/interrupt.h>
52970 +
52971 +#include <asm/io.h>
52972 +#include <asm/ip5000.h>
52973 +#include <asm/vdc_tio.h>
52974 +#include <asm/ubicom32fb.h>
52975 +
52976 +#define DRIVER_NAME            "ubicom32fb"
52977 +#define DRIVER_DESCRIPTION     "Ubicom32 frame buffer driver"
52978 +
52979 +#define PALETTE_ENTRIES_NO     16
52980 +
52981 +/*
52982 + * Option variables
52983 + *
52984 + * vram_size:  VRAM size in kilobytes, subject to alignment
52985 + */
52986 +static int vram_size = 0;
52987 +module_param(vram_size, int, 0);
52988 +MODULE_PARM_DESC(vram, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
52989 +static int init_value = 0;
52990 +module_param(init_value, int, 0);
52991 +MODULE_PARM_DESC(init, "Initial value of the framebuffer (16-bit number).");
52992 +
52993 +/*
52994 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
52995 + */
52996 +static struct fb_fix_screeninfo ubicom32fb_fix = {
52997 +       .id =           "Ubicom32",
52998 +       .type =         FB_TYPE_PACKED_PIXELS,
52999 +       .visual =       FB_VISUAL_TRUECOLOR,
53000 +       .accel =        FB_ACCEL_UBICOM32,
53001 +};
53002 +
53003 +/*
53004 + * Filled in at probe time when we find out what the hardware supports
53005 + */
53006 +static struct fb_var_screeninfo ubicom32fb_var;
53007 +
53008 +/*
53009 + * Private data structure
53010 + */
53011 +struct ubicom32fb_drvdata {
53012 +       struct fb_info                  *fbinfo;
53013 +       bool                            cmap_alloc;
53014 +
53015 +       /*
53016 +        * The address of the framebuffer in memory
53017 +        */
53018 +       void                            *fb;
53019 +       void                            *fb_aligned;
53020 +
53021 +       /*
53022 +        * Total size of vram including alignment allowance
53023 +        */
53024 +       u32                             total_vram_size;
53025 +
53026 +       /*
53027 +        * Interrupt to set when changing registers
53028 +        */
53029 +       u32                             vp_int;
53030 +
53031 +       /*
53032 +        * Optional: Interrupt used by TIO to signal us
53033 +        */
53034 +       u32                             rx_int;
53035 +
53036 +       /*
53037 +        * Base address of the regs for VDC_TIO
53038 +        */
53039 +       volatile struct vdc_tio_vp_regs *regs;
53040 +
53041 +       /*
53042 +        * non-zero if we are in yuv mode
53043 +        */
53044 +       u8_t                            is_yuv;
53045 +
53046 +       /*
53047 +        * Fake palette of 16 colors
53048 +        */
53049 +       u32                             pseudo_palette[PALETTE_ENTRIES_NO];
53050 +
53051 +       /*
53052 +        * Wait queue and lock used to block when we need to wait
53053 +        * for something to happen.
53054 +        */
53055 +       wait_queue_head_t               waitq;
53056 +       struct mutex                    lock;
53057 +
53058 +};
53059 +
53060 +/*
53061 + * ubicom32fb_set_next_frame
53062 + *     Sets the next frame buffer to display
53063 + *
53064 + * if sync is TRUE then this function will block until the hardware
53065 + * acknowledges the change
53066 + */
53067 +static inline void ubicom32fb_set_next_frame(struct ubicom32fb_drvdata *ud, void *fb, u8_t sync)
53068 +{
53069 +       ud->regs->next_frame_flags = ud->is_yuv ? VDCTIO_NEXT_FRAME_FLAG_YUV : 0;
53070 +       ud->regs->next_frame = (void *)((u32_t)fb | 1);
53071 +
53072 +       /*
53073 +        * If we have interrupts, then we can wait on it
53074 +        */
53075 +       if (ud->rx_int != -1) {
53076 +               DEFINE_WAIT(wait);
53077 +               unsigned long flags;
53078 +
53079 +               spin_lock_irqsave(&ud->lock, flags);
53080 +               prepare_to_wait(&ud->waitq, &wait, TASK_INTERRUPTIBLE);
53081 +               spin_unlock_irqrestore(&ud->lock, flags);
53082 +               schedule();
53083 +               finish_wait(&ud->waitq, &wait);
53084 +               return;
53085 +       }
53086 +
53087 +       /*
53088 +        * No interrupt, we will just spin here
53089 +        */
53090 +       while (sync && ((u32_t)ud->regs->next_frame & 1));
53091 +}
53092 +
53093 +/*
53094 + * ubicom32fb_send_command
53095 + *     Sends a command/data pair to the VDC
53096 + */
53097 +static inline void ubicom32fb_send_command(struct ubicom32fb_drvdata *ud, u16 command, u8_t block)
53098 +{
53099 +       ud->regs->command = command;
53100 +       ubicom32_set_interrupt(ud->vp_int);
53101 +       while (block && ud->regs->command);
53102 +}
53103 +
53104 +/*
53105 + * ubicom32fb_ioctl
53106 + *     Handles any ioctls sent to us
53107 + */
53108 +static int ubicom32fb_ioctl(struct fb_info *fbi, unsigned int cmd,
53109 +                      unsigned long arg)
53110 +{
53111 +       struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53112 +       void __user *argp = (void __user *)arg;
53113 +       int retval = -EFAULT;
53114 +
53115 +       switch (cmd) {
53116 +       case UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC:
53117 +               // check alignment, return -EINVAL if necessary
53118 +               ubicom32fb_set_next_frame(ud, argp, 1);
53119 +               retval = 0;
53120 +               break;
53121 +
53122 +       case UBICOM32FB_IOCTL_SET_NEXT_FRAME:
53123 +               // check alignment, return -EINVAL if necessary
53124 +               ubicom32fb_set_next_frame(ud, argp, 0);
53125 +               retval = 0;
53126 +               break;
53127 +
53128 +       case UBICOM32FB_IOCTL_SET_MODE:
53129 +               if (!(ud->regs->caps & VDCTIO_CAPS_SUPPORTS_SCALING)) {
53130 +                       break;
53131 +               } else {
53132 +                       struct ubicom32fb_mode mode;
53133 +                       volatile struct vdc_tio_vp_regs *regs = ud->regs;
53134 +                       u32_t flags = 0;
53135 +
53136 +                       if (copy_from_user(&mode, argp, sizeof(mode))) {
53137 +                               break;
53138 +                       }
53139 +
53140 +                       regs->x_in = mode.width;
53141 +                       regs->y_in = mode.height;
53142 +                       regs->x_out = regs->xres;
53143 +                       regs->y_out = regs->yres;
53144 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER) {
53145 +                               flags |= VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER;
53146 +                       }
53147 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER) {
53148 +                               flags |= VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER;
53149 +                       }
53150 +                       ud->is_yuv = mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV;
53151 +                       if (ud->is_yuv) {
53152 +                               flags |= VDCTIO_SCALE_FLAG_YUV;
53153 +                       }
53154 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255) {
53155 +                               flags |= VDCTIO_SCALE_FLAG_VRANGE_16_255;
53156 +                       }
53157 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255) {
53158 +                               flags |= VDCTIO_SCALE_FLAG_VRANGE_0_255;
53159 +                       }
53160 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB) {
53161 +                               flags |= VDCTIO_SCALE_FLAG_VSUB;
53162 +                       }
53163 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1) {
53164 +                               flags |= VDCTIO_SCALE_FLAG_HSUB_2_1;
53165 +                       }
53166 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1) {
53167 +                               flags |= VDCTIO_SCALE_FLAG_HSUB_1_1;
53168 +                       }
53169 +                       if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE) {
53170 +                               flags |= VDCTIO_SCALE_FLAG_ENABLE;
53171 +                       }
53172 +                       if (mode.next_frame) {
53173 +                               flags |= VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER;
53174 +                               regs->next_frame = mode.next_frame;
53175 +                       }
53176 +
53177 +                       regs->scale_flags = flags;
53178 +                       ubicom32fb_send_command(ud, VDCTIO_COMMAND_SET_SCALE_MODE, 1);
53179 +                       retval = 0;
53180 +                       break;
53181 +               }
53182 +
53183 +       default:
53184 +               retval = -ENOIOCTLCMD;
53185 +               break;
53186 +       }
53187 +
53188 +       return retval;
53189 +}
53190 +
53191 +/*
53192 + * ubicom32fb_interrupt
53193 + *     Called by the OS when the TIO has set the rx_int
53194 + */
53195 +static irqreturn_t ubicom32fb_interrupt(int vec, void *appdata)
53196 +{
53197 +       struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)appdata;
53198 +
53199 +       spin_lock(&ud->lock);
53200 +       if (waitqueue_active(&ud->waitq)) {
53201 +               wake_up(&ud->waitq);
53202 +       }
53203 +       spin_unlock(&ud->lock);
53204 +
53205 +       return IRQ_HANDLED;
53206 +}
53207 +
53208 +/*
53209 + * ubicom32fb_pan_display
53210 + *     Pans the display to a given location.  Supports only y direction panning.
53211 + */
53212 +static int ubicom32fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
53213 +{
53214 +       struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53215 +       void *new_addr;
53216 +
53217 +       /*
53218 +        * Get the last y line that would be displayed.  Since we don't support YWRAP,
53219 +        * it must be less than our virtual y size.
53220 +        */
53221 +       u32 lasty = var->yoffset + var->yres;
53222 +       if (lasty > fbi->var.yres_virtual) {
53223 +               /*
53224 +                * We would fall off the end of our frame buffer if we panned here.
53225 +                */
53226 +               return -EINVAL;
53227 +       }
53228 +
53229 +       if (var->xoffset) {
53230 +               /*
53231 +                * We don't support panning in the x direction
53232 +                */
53233 +               return -EINVAL;
53234 +       }
53235 +
53236 +       /*
53237 +        * Everything looks sane, go ahead and pan
53238 +        *
53239 +        * We have to calculate a new address for the VDC to look at
53240 +        */
53241 +       new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
53242 +
53243 +       /*
53244 +        * Send down the command.  The buffer will switch at the next vertical blank
53245 +        */
53246 +       ubicom32fb_set_next_frame(ud, (void *)new_addr, 0);
53247 +
53248 +       return 0;
53249 +}
53250 +
53251 +/*
53252 + * ubicom32fb_setcolreg
53253 + *     Sets a color in our virtual palette
53254 + */
53255 +static int ubicom32fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
53256 +{
53257 +       u32 *palette = fbi->pseudo_palette;
53258 +
53259 +       if (regno >= PALETTE_ENTRIES_NO) {
53260 +               return -EINVAL;
53261 +       }
53262 +
53263 +       /*
53264 +        * We only use 8 bits from each color
53265 +        */
53266 +       red >>= 8;
53267 +       green >>= 8;
53268 +       blue >>= 8;
53269 +
53270 +       /*
53271 +        * Convert any grayscale values
53272 +        */
53273 +       if (fbi->var.grayscale) {
53274 +               u16 gray = red + green + blue;
53275 +               gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
53276 +               gray >>= 2;
53277 +               if (gray > 255) {
53278 +                       gray = 255;
53279 +               }
53280 +               red = gray;
53281 +               blue = gray;
53282 +               green = gray;
53283 +       }
53284 +
53285 +       palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
53286 +                        (blue << fbi->var.blue.offset);
53287 +
53288 +       return 0;
53289 +}
53290 +
53291 +/*
53292 + * ubicom32fb_mmap
53293 + */
53294 +static int ubicom32fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
53295 +{
53296 +       struct ubicom32fb_drvdata *drvdata = (struct ubicom32fb_drvdata *)info->par;
53297 +
53298 +       vma->vm_start = (unsigned long)(drvdata->fb_aligned);
53299 +
53300 +       vma->vm_end = vma->vm_start + info->fix.smem_len;
53301 +
53302 +       /* For those who don't understand how mmap works, go read
53303 +        *   Documentation/nommu-mmap.txt.
53304 +        * For those that do, you will know that the VM_MAYSHARE flag
53305 +        * must be set in the vma->vm_flags structure on noMMU
53306 +        *   Other flags can be set, and are documented in
53307 +        *   include/linux/mm.h
53308 +        */
53309 +
53310 +       vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
53311 +
53312 +       return 0;
53313 +}
53314 +
53315 +/*
53316 + * ubicom32fb_blank
53317 + */
53318 +static int ubicom32fb_blank(int blank_mode, struct fb_info *fbi)
53319 +{
53320 +       return 0;
53321 +#if 0
53322 +       struct ubicom32fb_drvdata *drvdata = to_ubicom32fb_drvdata(fbi);
53323 +
53324 +       switch (blank_mode) {
53325 +       case FB_BLANK_UNBLANK:
53326 +               /* turn on panel */
53327 +               ubicom32fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
53328 +               break;
53329 +
53330 +       case FB_BLANK_NORMAL:
53331 +       case FB_BLANK_VSYNC_SUSPEND:
53332 +       case FB_BLANK_HSYNC_SUSPEND:
53333 +       case FB_BLANK_POWERDOWN:
53334 +               /* turn off panel */
53335 +               ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53336 +       default:
53337 +               break;
53338 +
53339 +       }
53340 +       return 0; /* success */
53341 +#endif
53342 +}
53343 +
53344 +static struct fb_ops ubicom32fb_ops =
53345 +{
53346 +       .owner                  = THIS_MODULE,
53347 +       .fb_pan_display         = ubicom32fb_pan_display,
53348 +       .fb_setcolreg           = ubicom32fb_setcolreg,
53349 +       .fb_blank               = ubicom32fb_blank,
53350 +       .fb_mmap                = ubicom32fb_mmap,
53351 +       .fb_ioctl               = ubicom32fb_ioctl,
53352 +       .fb_fillrect            = cfb_fillrect,
53353 +       .fb_copyarea            = cfb_copyarea,
53354 +       .fb_imageblit           = cfb_imageblit,
53355 +};
53356 +
53357 +/*
53358 + * ubicom32fb_release
53359 + */
53360 +static int ubicom32fb_release(struct device *dev)
53361 +{
53362 +       struct ubicom32fb_drvdata *ud = dev_get_drvdata(dev);
53363 +
53364 +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
53365 +       //ubicom32fb_blank(VESA_POWERDOWN, &drvdata->info);
53366 +#endif
53367 +
53368 +       unregister_framebuffer(ud->fbinfo);
53369 +
53370 +       if (ud->cmap_alloc) {
53371 +               fb_dealloc_cmap(&ud->fbinfo->cmap);
53372 +       }
53373 +
53374 +       if (ud->fb) {
53375 +               kfree(ud->fb);
53376 +       }
53377 +
53378 +       if (ud->rx_int != -1) {
53379 +               free_irq(ud->rx_int, ud);
53380 +       }
53381 +
53382 +       /*
53383 +        * Turn off the display
53384 +        */
53385 +       //ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53386 +       //iounmap(drvdata->regs);
53387 +
53388 +       framebuffer_release(ud->fbinfo);
53389 +       dev_set_drvdata(dev, NULL);
53390 +
53391 +       return 0;
53392 +}
53393 +
53394 +/*
53395 + * ubicom32fb_platform_probe
53396 + */
53397 +static int __init ubicom32fb_platform_probe(struct platform_device *pdev)
53398 +{
53399 +       struct ubicom32fb_drvdata *ud;
53400 +       struct resource *irq_resource_rx;
53401 +       struct resource *irq_resource_tx;
53402 +       struct resource *mem_resource;
53403 +       struct fb_info *fbinfo;
53404 +       int rc;
53405 +       size_t fbsize;
53406 +       struct device *dev = &pdev->dev;
53407 +       int offset;
53408 +       struct vdc_tio_vp_regs *regs;
53409 +
53410 +       /*
53411 +        * Get our resources
53412 +        */
53413 +       irq_resource_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
53414 +       if (!irq_resource_tx) {
53415 +               dev_err(dev, "No tx IRQ resource assigned\n");
53416 +               return -ENODEV;
53417 +       }
53418 +
53419 +       irq_resource_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
53420 +       if (!irq_resource_rx) {
53421 +               dev_err(dev, "No rx IRQ resource assigned\n");
53422 +               return -ENODEV;
53423 +       }
53424 +
53425 +       mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
53426 +       if (!mem_resource || !mem_resource->start) {
53427 +               dev_err(dev, "No mem resource assigned\n");
53428 +               return -ENODEV;
53429 +       }
53430 +       regs = (struct vdc_tio_vp_regs *)mem_resource->start;
53431 +       if (regs->version != VDCTIO_VP_VERSION) {
53432 +               dev_err(dev, "VDCTIO is not compatible with this driver tio:%x drv:%x\n",
53433 +                       regs->version, VDCTIO_VP_VERSION);
53434 +               return -ENODEV;
53435 +       }
53436 +
53437 +       /*
53438 +        * This is the minimum VRAM size
53439 +        */
53440 +       fbsize = regs->xres * regs->yres * (regs->bpp / 8);
53441 +       if (!vram_size) {
53442 +               vram_size = (fbsize + 1023) / 1024;
53443 +       } else {
53444 +               if (fbsize > (vram_size * 1024)) {
53445 +                       dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
53446 +                       return -ENOMEM; // should be ebadparam?
53447 +               }
53448 +       }
53449 +
53450 +       /*
53451 +        * Allocate the framebuffer instance + our private data
53452 +        */
53453 +       fbinfo = framebuffer_alloc(sizeof(struct ubicom32fb_drvdata), &pdev->dev);
53454 +       if (!fbinfo) {
53455 +               dev_err(dev, "Not enough memory to allocate instance.\n");
53456 +               return -ENOMEM;
53457 +       }
53458 +
53459 +       /*
53460 +        * Fill in our private data.
53461 +        */
53462 +       ud = (struct ubicom32fb_drvdata *)fbinfo->par;
53463 +       ud->fbinfo = fbinfo;
53464 +       ud->regs = (struct vdc_tio_vp_regs *)(mem_resource->start);
53465 +       dev_set_drvdata(dev, ud);
53466 +
53467 +       ud->vp_int = irq_resource_tx->start;
53468 +
53469 +       /*
53470 +        * If we were provided an rx_irq then we need to init the appropriate
53471 +        * queues, locks, and functions.
53472 +        */
53473 +       ud->rx_int = -1;
53474 +       if (irq_resource_rx->start != DEVTREE_IRQ_NONE) {
53475 +               init_waitqueue_head(&ud->waitq);
53476 +               mutex_init(&ud->lock);
53477 +               if (request_irq(ud->rx_int, ubicom32fb_interrupt, IRQF_SHARED, "ubicom32fb_rx", ud)) {
53478 +                       dev_err(dev, "Couldn't request rx IRQ\n");
53479 +                       rc = -ENOMEM;
53480 +                       goto fail;
53481 +               }
53482 +               ud->rx_int = irq_resource_rx->start;
53483 +       }
53484 +
53485 +       /*
53486 +        * Allocate and align the requested amount of VRAM
53487 +        */
53488 +       ud->total_vram_size = (vram_size * 1024) + regs->fb_align;
53489 +       ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
53490 +       if (ud->fb == NULL) {
53491 +               dev_err(dev, "Couldn't allocate VRAM\n");
53492 +               rc = -ENOMEM;
53493 +               goto fail;
53494 +       }
53495 +
53496 +       offset = (u32_t)ud->fb & (regs->fb_align - 1);
53497 +       if (!offset) {
53498 +               ud->fb_aligned = ud->fb;
53499 +       } else {
53500 +               offset = regs->fb_align - offset;
53501 +               ud->fb_aligned = ud->fb + offset;
53502 +       }
53503 +
53504 +       /*
53505 +        * Clear the entire frame buffer
53506 +        */
53507 +       if (!init_value) {
53508 +               memset(ud->fb_aligned, 0, vram_size * 1024);
53509 +       } else {
53510 +               unsigned short *p = ud->fb_aligned;
53511 +               int i;
53512 +               for (i = 0; i < ((vram_size * 1024) / sizeof(u16_t)); i++) {
53513 +                       *p++ = init_value;
53514 +               }
53515 +       }
53516 +
53517 +       /*
53518 +        * Fill in the fb_var_screeninfo structure
53519 +        */
53520 +       memset(&ubicom32fb_var, 0, sizeof(ubicom32fb_var));
53521 +       ubicom32fb_var.bits_per_pixel = regs->bpp;
53522 +       ubicom32fb_var.red.offset = regs->rshift;
53523 +       ubicom32fb_var.green.offset = regs->gshift;
53524 +       ubicom32fb_var.blue.offset = regs->bshift;
53525 +       ubicom32fb_var.red.length = regs->rbits;
53526 +       ubicom32fb_var.green.length = regs->gbits;
53527 +       ubicom32fb_var.blue.length = regs->bbits;
53528 +       ubicom32fb_var.activate = FB_ACTIVATE_NOW;
53529 +
53530 +#if 0
53531 +       /*
53532 +        * Turn on the display
53533 +        */
53534 +       ud->reg_ctrl_default = REG_CTRL_ENABLE;
53535 +       if (regs->rotate_screen)
53536 +               ud->reg_ctrl_default |= REG_CTRL_ROTATE;
53537 +       ubicom32fb_out_be32(ud, REG_CTRL, ud->reg_ctrl_default);
53538 +#endif
53539 +
53540 +       /*
53541 +        * Fill in the fb_info structure
53542 +        */
53543 +       ud->fbinfo->device = dev;
53544 +       ud->fbinfo->screen_base = (void *)ud->fb_aligned;
53545 +       ud->fbinfo->fbops = &ubicom32fb_ops;
53546 +       ud->fbinfo->fix = ubicom32fb_fix;
53547 +       ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
53548 +       ud->fbinfo->fix.smem_len = vram_size * 1024;
53549 +       ud->fbinfo->fix.line_length = regs->xres * (regs->bpp / 8);
53550 +       ud->fbinfo->fix.mmio_start = (u32)regs;
53551 +       ud->fbinfo->fix.mmio_len = sizeof(struct vdc_tio_vp_regs);
53552 +
53553 +       /*
53554 +        * We support panning in the y direction only
53555 +        */
53556 +       ud->fbinfo->fix.xpanstep = 0;
53557 +       ud->fbinfo->fix.ypanstep = 1;
53558 +
53559 +       ud->fbinfo->pseudo_palette = ud->pseudo_palette;
53560 +       ud->fbinfo->flags = FBINFO_DEFAULT;
53561 +       ud->fbinfo->var = ubicom32fb_var;
53562 +       ud->fbinfo->var.xres = regs->xres;
53563 +       ud->fbinfo->var.yres = regs->yres;
53564 +
53565 +       /*
53566 +        * We cannot pan in the X direction, so xres_virtual is regs->xres
53567 +        * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
53568 +        */
53569 +       ud->fbinfo->var.xres_virtual = regs->xres;
53570 +       ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
53571 +
53572 +       //ud->fbinfo->var.height = regs->height_mm;
53573 +       //ud->fbinfo->var.width = regs->width_mm;
53574 +
53575 +       /*
53576 +        * Allocate a color map
53577 +        */
53578 +       rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
53579 +       if (rc) {
53580 +               dev_err(dev, "Fail to allocate colormap (%d entries)\n",
53581 +                       PALETTE_ENTRIES_NO);
53582 +               goto fail;
53583 +       }
53584 +       ud->cmap_alloc = true;
53585 +
53586 +       /*
53587 +        * Register new frame buffer
53588 +        */
53589 +       rc = register_framebuffer(ud->fbinfo);
53590 +       if (rc) {
53591 +               dev_err(dev, "Could not register frame buffer\n");
53592 +               goto fail;
53593 +       }
53594 +
53595 +       /*
53596 +        * Start up the VDC
53597 +        */
53598 +       ud->regs->next_frame = ud->fb;
53599 +       ubicom32fb_send_command(ud, VDCTIO_COMMAND_START, 0);
53600 +
53601 +       /*
53602 +        * Tell the log we are here
53603 +        */
53604 +       dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u), regs=%p irqtx=%u irqrx=%u\n",
53605 +               ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
53606 +               ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual, ud->regs,
53607 +               irq_resource_tx->start, irq_resource_rx->start);
53608 +
53609 +       /*
53610 +        * Success
53611 +        */
53612 +       return 0;
53613 +
53614 +fail:
53615 +       ubicom32fb_release(dev);
53616 +       return rc;
53617 +}
53618 +
53619 +/*
53620 + * ubicom32fb_platform_remove
53621 + */
53622 +static int ubicom32fb_platform_remove(struct platform_device *pdev)
53623 +{
53624 +       dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
53625 +       return ubicom32fb_release(&pdev->dev);
53626 +}
53627 +
53628 +static struct platform_driver ubicom32fb_platform_driver = {
53629 +       .probe          = ubicom32fb_platform_probe,
53630 +       .remove         = ubicom32fb_platform_remove,
53631 +       .driver = {
53632 +               .name = DRIVER_NAME,
53633 +               .owner = THIS_MODULE,
53634 +       },
53635 +};
53636 +
53637 +#ifndef MODULE
53638 +/*
53639 + * ubicom32fb_setup
53640 + *     Process kernel boot options
53641 + */
53642 +static int __init ubicom32fb_setup(char *options)
53643 +{
53644 +       char *this_opt;
53645 +
53646 +       if (!options || !*options) {
53647 +               return 0;
53648 +       }
53649 +
53650 +       while ((this_opt = strsep(&options, ",")) != NULL) {
53651 +               if (!*this_opt) {
53652 +                       continue;
53653 +               }
53654 +
53655 +               if (!strncmp(this_opt, "init_value=", 10)) {
53656 +                       init_value = simple_strtoul(this_opt + 11, NULL, 0);
53657 +                       continue;
53658 +               }
53659 +
53660 +               if (!strncmp(this_opt, "vram_size=", 10)) {
53661 +                       vram_size = simple_strtoul(this_opt + 10, NULL, 0);
53662 +                       continue;
53663 +               }
53664 +       }
53665 +       return 0;
53666 +}
53667 +#endif /* MODULE */
53668 +
53669 +/*
53670 + * ubicom32fb_init
53671 + */
53672 +static int __devinit ubicom32fb_init(void)
53673 +{
53674 +#ifndef MODULE
53675 +       /*
53676 +        * Get kernel boot options (in 'video=ubicom32fb:<options>')
53677 +        */
53678 +       char *option = NULL;
53679 +
53680 +       if (fb_get_options(DRIVER_NAME, &option)) {
53681 +               return -ENODEV;
53682 +       }
53683 +       ubicom32fb_setup(option);
53684 +#endif /* MODULE */
53685 +
53686 +       return platform_driver_register(&ubicom32fb_platform_driver);
53687 +}
53688 +module_init(ubicom32fb_init);
53689 +
53690 +/*
53691 + * ubicom32fb_exit
53692 + */
53693 +static void __exit ubicom32fb_exit(void)
53694 +{
53695 +       platform_driver_unregister(&ubicom32fb_platform_driver);
53696 +}
53697 +module_exit(ubicom32fb_exit);
53698 +
53699 +MODULE_LICENSE("GPL");
53700 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
53701 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
53702 --- /dev/null
53703 +++ b/drivers/video/ubicom32plio80.c
53704 @@ -0,0 +1,780 @@
53705 +/*
53706 + * drivers/video/ubicom32plio80.c
53707 + *     Ubicom32 80 bus PLIO buffer driver
53708 + *
53709 + * (C) Copyright 2009, Ubicom, Inc.
53710 + *
53711 + * This file is part of the Ubicom32 Linux Kernel Port.
53712 + *
53713 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
53714 + * it and/or modify it under the terms of the GNU General Public License
53715 + * as published by the Free Software Foundation, either version 2 of the
53716 + * License, or (at your option) any later version.
53717 + *
53718 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
53719 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
53720 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
53721 + * the GNU General Public License for more details.
53722 + *
53723 + * You should have received a copy of the GNU General Public License
53724 + * along with the Ubicom32 Linux Kernel Port.  If not,
53725 + * see <http://www.gnu.org/licenses/>.
53726 + */
53727 +
53728 +/*
53729 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
53730 + * Geert Uytterhoeven.
53731 + */
53732 +
53733 +#include <linux/device.h>
53734 +#include <linux/module.h>
53735 +#include <linux/kernel.h>
53736 +#include <linux/version.h>
53737 +#include <linux/errno.h>
53738 +#include <linux/string.h>
53739 +#include <linux/mm.h>
53740 +#include <linux/fb.h>
53741 +#include <linux/init.h>
53742 +#include <linux/interrupt.h>
53743 +#include <linux/dma-mapping.h>
53744 +#include <linux/platform_device.h>
53745 +#include <linux/device.h>
53746 +#include <linux/uaccess.h>
53747 +#include <asm/plio.h>
53748 +
53749 +#define DRIVER_NAME            "ubicom32plio80"
53750 +#define DRIVER_DESCRIPTION     "Ubicom32 80 bus PLIO frame buffer driver"
53751 +
53752 +#define PALETTE_ENTRIES_NO     16
53753 +
53754 +/*
53755 + * Option variables
53756 + *
53757 + * vram_size:  VRAM size in kilobytes, subject to alignment
53758 + */
53759 +static int vram_size = 0;
53760 +module_param(vram_size, int, 0);
53761 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
53762 +
53763 +static int xres = 240;
53764 +module_param(xres, int, 0);
53765 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
53766 +
53767 +static int yres = 320;
53768 +module_param(yres, int, 0);
53769 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
53770 +
53771 +static int bgr = 0;
53772 +module_param(bgr, int, 0);
53773 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
53774 +
53775 +#define BITS_PER_PIXEL 16
53776 +
53777 +/*
53778 + * Buffer alignment, must not be 0
53779 + */
53780 +#define UBICOM32PLIO80_ALIGNMENT 4
53781 +
53782 +/*
53783 + * PLIO FSM
53784 + *     16-bit data bus on port I
53785 + *     CS on EXTCTL[6]
53786 + *     WR on EXTCTL[4]
53787 + */
53788 +static const plio_fctl_t plio_fctl = {
53789 +       .fctl0 = {
53790 +               .ptif_port_mode = PLIO_PORT_MODE_DI,
53791 +               .ptif_portd_cfg = 0,
53792 +               .ptif_porti_cfg = 3,
53793 +               .edif_ds = 6,
53794 +               .edif_cmp_mode = 1,
53795 +               .ecif_extclk_ena = 0, // enable clock output on PD7 table 2.65/p111 says extctl[0]?
53796 +               .icif_clk_src_sel = PLIO_CLK_IO,
53797 +       },
53798 +       .fctl2 = {
53799 +               .icif_eclk_div = 10,
53800 +               .icif_iclk_div = 10,
53801 +       },
53802 +
53803 +       };
53804 +
53805 +       static const plio_config_t plio_config = {
53806 +       .pfsm = {
53807 +               /*
53808 +                * Table 12.63
53809 +                */
53810 +               .grpsel[0] = {1,1,1,1,1,1,1,1,1,1},
53811 +
53812 +               /*
53813 +               * Table 12.66 Counter load value
53814 +               */
53815 +               .cs_lut[0] = {0,0,0,0,0,0,0,0},
53816 +
53817 +               /*
53818 +                * Table 2.75 PLIO PFSM Configuration Registers
53819 +                */
53820 +               //                      3     2     1     0
53821 +               .extctl_o_lut[0] = {0x3f, 0x2f, 0x3f, 0x3f},
53822 +               //                      7     6     5     4
53823 +               .extctl_o_lut[1] = {0x3f, 0x3f, 0x3f, 0x2f},
53824 +       },
53825 +       .edif = {
53826 +               .odr_oe = 0xffff,
53827 +       },
53828 +       .ecif = {
53829 +               .output_ena = (1 << 6) | (1 << 4),
53830 +       },
53831 +};
53832 +
53833 +static const u32_t ubicom32plio80_plio_fsm[] = {
53834 +       // 0-F
53835 +       0x00070007, 0x00070007,
53836 +       0x00070007, 0x00070007,
53837 +       0x00070007, 0x00070007,
53838 +       0x00070007, 0x00070007,
53839 +
53840 +       0x16260806, 0x16260806,
53841 +       0x16260806, 0x16260806,
53842 +       0x16260806, 0x16260806,
53843 +       0x16260806, 0x16260806,
53844 +
53845 +       // 10 - 1f
53846 +       0x22061806, 0x22061806,
53847 +       0x22061806, 0x22061806,
53848 +       0x22061806, 0x22061806,
53849 +       0x22061806, 0x22061806,
53850 +
53851 +       0x22061806, 0x22061806,
53852 +       0x22061806, 0x22061806,
53853 +       0x22061806, 0x22061806,
53854 +       0x22061806, 0x22061806,
53855 +
53856 +       // 20 - 2f
53857 +       0x00070806, 0x00070806,
53858 +       0x00070806, 0x00070806,
53859 +       0x00070806, 0x00070806,
53860 +       0x00070806, 0x00070806,
53861 +
53862 +       0x00070806, 0x00070806,
53863 +       0x00070806, 0x00070806,
53864 +       0x00070806, 0x00070806,
53865 +       0x00070806, 0x00070806,
53866 +};
53867 +
53868 +/*
53869 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
53870 + */
53871 +static struct fb_fix_screeninfo ubicom32plio80_fix = {
53872 +       .id =           "Ubicom32",
53873 +       .type =         FB_TYPE_PACKED_PIXELS,
53874 +       .visual =       FB_VISUAL_TRUECOLOR,
53875 +       .accel =        FB_ACCEL_UBICOM32_PLIO80,
53876 +};
53877 +
53878 +/*
53879 + * Filled in at probe time when we find out what the hardware supports
53880 + */
53881 +static struct fb_var_screeninfo ubicom32plio80_var;
53882 +
53883 +/*
53884 + * Private data structure
53885 + */
53886 +struct ubicom32plio80_drvdata {
53887 +       struct fb_info                  *fbinfo;
53888 +       bool                            cmap_alloc;
53889 +
53890 +       /*
53891 +        * The address of the framebuffer in memory
53892 +        */
53893 +       void                            *fb;
53894 +       void                            *fb_aligned;
53895 +
53896 +       /*
53897 +        * Total size of vram including alignment allowance
53898 +        */
53899 +       u32                             total_vram_size;
53900 +
53901 +       /*
53902 +        * Fake palette of 16 colors
53903 +        */
53904 +       u32                             pseudo_palette[PALETTE_ENTRIES_NO];
53905 +
53906 +       int                             irq_req;
53907 +
53908 +       /*
53909 +        * Current pointer and bytes left to transfer with the PLIO
53910 +        */
53911 +       void                            *xfer_ptr;
53912 +       u32                             bytes_to_xfer;
53913 +       u32                             busy;
53914 +};
53915 +
53916 +static struct platform_device *ubicom32plio80_platform_device;
53917 +
53918 +/*
53919 + * ubicom32plio80_isr
53920 + */
53921 +static int ubicom32plio80_isr(int irq, void *appdata)
53922 +{
53923 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)appdata;
53924 +
53925 +       if (!ud->bytes_to_xfer) {
53926 +               ubicom32_disable_interrupt(TX_FIFO_INT(PLIO_PORT));
53927 +               PLIO_NBR->intmask.txfifo_wm = 0;
53928 +               ud->busy = 0;
53929 +               return IRQ_HANDLED;
53930 +       }
53931 +
53932 +       asm volatile (
53933 +               ".rept 8                                \n\t"
53934 +               "move.4 (%[fifo]), (%[data])4++         \n\t"
53935 +               ".endr                                  \n\t"
53936 +               : [data] "+a" (ud->xfer_ptr)
53937 +               : [fifo] "a" (&PLIO_NBR->tx_lo)
53938 +       );
53939 +
53940 +       ud->bytes_to_xfer -= 32;
53941 +
53942 +       return IRQ_HANDLED;
53943 +}
53944 +
53945 +/*
53946 + * ubicom32plio80_update
53947 + */
53948 +static void ubicom32plio80_update(struct ubicom32plio80_drvdata *ud, u32 *fb)
53949 +{
53950 +       struct ubicom32_io_port *ri = (struct ubicom32_io_port *)RI;
53951 +       struct ubicom32_io_port *rd = (struct ubicom32_io_port *)RD;
53952 +
53953 +       ud->xfer_ptr = fb;
53954 +       ud->bytes_to_xfer = (xres * yres * 2) - 64;
53955 +       ud->busy = 1;
53956 +
53957 +       ri->gpio_mask = 0;
53958 +       rd->gpio_mask &= ~((1 << 4) | (1 << 2));
53959 +
53960 +       *(u32 *)(&PLIO_NBR->intclr) = ~0;
53961 +       PLIO_NBR->intmask.txfifo_wm = 1;
53962 +       PLIO_NBR->fifo_wm.tx = 8;
53963 +       ubicom32_enable_interrupt(TX_FIFO_INT(PLIO_PORT));
53964 +
53965 +       asm volatile (
53966 +               ".rept 16                               \n\t"
53967 +               "move.4 (%[fifo]), (%[data])4++         \n\t"
53968 +               ".endr                                  \n\t"
53969 +               : [data] "+a" (ud->xfer_ptr)
53970 +               : [fifo] "a" (&PLIO_NBR->tx_lo)
53971 +       );
53972 +}
53973 +
53974 +/*
53975 + * ubicom32plio80_pan_display
53976 + *     Pans the display to a given location.  Supports only y direction panning.
53977 + */
53978 +static int ubicom32plio80_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
53979 +{
53980 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)fbi->par;
53981 +       void *new_addr;
53982 +
53983 +       /*
53984 +        * Get the last y line that would be displayed.  Since we don't support YWRAP,
53985 +        * it must be less than our virtual y size.
53986 +        */
53987 +       u32 lasty = var->yoffset + var->yres;
53988 +       if (lasty > fbi->var.yres_virtual) {
53989 +               /*
53990 +                * We would fall off the end of our frame buffer if we panned here.
53991 +                */
53992 +               return -EINVAL;
53993 +       }
53994 +
53995 +       if (var->xoffset) {
53996 +               /*
53997 +                * We don't support panning in the x direction
53998 +                */
53999 +               return -EINVAL;
54000 +       }
54001 +
54002 +       /*
54003 +        * Everything looks sane, go ahead and pan
54004 +        *
54005 +        * We have to calculate a new address for the VDC to look at
54006 +        */
54007 +       new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54008 +
54009 +       return 0;
54010 +}
54011 +
54012 +/*
54013 + * ubicom32plio80_setcolreg
54014 + *     Sets a color in our virtual palette
54015 + */
54016 +static int ubicom32plio80_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54017 +{
54018 +       u32 *palette = fbi->pseudo_palette;
54019 +
54020 +       if (regno >= PALETTE_ENTRIES_NO) {
54021 +               return -EINVAL;
54022 +       }
54023 +
54024 +       /*
54025 +        * We only use 8 bits from each color
54026 +        */
54027 +       red >>= 8;
54028 +       green >>= 8;
54029 +       blue >>= 8;
54030 +
54031 +       /*
54032 +        * Convert any grayscale values
54033 +        */
54034 +       if (fbi->var.grayscale) {
54035 +               u16 gray = red + green + blue;
54036 +               gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54037 +               gray >>= 2;
54038 +               if (gray > 255) {
54039 +                       gray = 255;
54040 +               }
54041 +               red = gray;
54042 +               blue = gray;
54043 +               green = gray;
54044 +       }
54045 +
54046 +       palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54047 +                        (blue << fbi->var.blue.offset);
54048 +
54049 +       return 0;
54050 +}
54051 +
54052 +/*
54053 + * ubicom32plio80_mmap
54054 + */
54055 +static int ubicom32plio80_mmap(struct fb_info *info, struct vm_area_struct *vma)
54056 +{
54057 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54058 +
54059 +       vma->vm_start = (unsigned long)(ud->fb_aligned);
54060 +
54061 +       vma->vm_end = vma->vm_start + info->fix.smem_len;
54062 +
54063 +       /* For those who don't understand how mmap works, go read
54064 +        *   Documentation/nommu-mmap.txt.
54065 +        * For those that do, you will know that the VM_MAYSHARE flag
54066 +        * must be set in the vma->vm_flags structure on noMMU
54067 +        *   Other flags can be set, and are documented in
54068 +        *   include/linux/mm.h
54069 +        */
54070 +
54071 +       vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
54072 +
54073 +       return 0;
54074 +}
54075 +
54076 +/*
54077 + * ubicom32plio80_check_var
54078 + *     Check the var, tweak it but don't change operational parameters.
54079 + */
54080 +static int ubicom32plio80_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
54081 +{
54082 +       struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54083 +       u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
54084 +
54085 +       /*
54086 +        * See if we can handle this bpp
54087 +        */
54088 +       if (var->bits_per_pixel > BITS_PER_PIXEL) {
54089 +               return -EINVAL;
54090 +       }
54091 +       var->bits_per_pixel = BITS_PER_PIXEL;
54092 +
54093 +       /*
54094 +        * See if we have enough memory to handle this resolution
54095 +        */
54096 +       if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
54097 +               return -EINVAL;
54098 +       }
54099 +
54100 +       var->xres_virtual = var->xres;
54101 +       var->yres_virtual = ud->total_vram_size / line_size;
54102 +
54103 +       var->red.length = 5;
54104 +       var->green.length = 6;
54105 +       var->green.offset = 5;
54106 +       var->blue.length = 5;
54107 +       var->transp.offset = var->transp.length = 0;
54108 +
54109 +       if (bgr) {
54110 +               var->red.offset = 0;
54111 +               var->blue.offset = 11;
54112 +       } else {
54113 +               var->red.offset = 11;
54114 +               var->blue.offset = 0;
54115 +       }
54116 +
54117 +       var->nonstd = 0;
54118 +       var->height = -1;
54119 +       var->width = -1;
54120 +       var->vmode = FB_VMODE_NONINTERLACED;
54121 +       var->sync = 0;
54122 +
54123 +       return 0;
54124 +}
54125 +
54126 +/*
54127 + * ubicom32plio80_set_par
54128 + *     Set the video mode according to info->var
54129 + */
54130 +static int ubicom32plio80_set_par(struct fb_info *info)
54131 +{
54132 +       /*
54133 +        * Anything changed?
54134 +        */
54135 +       if ((xres == info->var.xres) && (yres == info->var.yres)) {
54136 +               return 0;
54137 +       }
54138 +
54139 +       /*
54140 +        * Implement changes
54141 +        */
54142 +       xres = info->var.xres;
54143 +       yres = info->var.yres;
54144 +       info->fix.visual = FB_VISUAL_TRUECOLOR;
54145 +       info->fix.xpanstep = 0;
54146 +       info->fix.ypanstep = 1;
54147 +       info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
54148 +
54149 +       return 0;
54150 +}
54151 +
54152 +/*
54153 + * ubicom32plio80_ops
54154 + *     List of supported operations
54155 + */
54156 +static struct fb_ops ubicom32plio80_ops =
54157 +{
54158 +       .owner                  = THIS_MODULE,
54159 +       .fb_pan_display         = ubicom32plio80_pan_display,
54160 +       .fb_setcolreg           = ubicom32plio80_setcolreg,
54161 +       .fb_mmap                = ubicom32plio80_mmap,
54162 +       .fb_check_var           = ubicom32plio80_check_var,
54163 +       .fb_set_par             = ubicom32plio80_set_par,
54164 +       .fb_fillrect            = cfb_fillrect,
54165 +       .fb_copyarea            = cfb_copyarea,
54166 +       .fb_imageblit           = cfb_imageblit,
54167 +};
54168 +
54169 +/*
54170 + * ubicom32plio80_release
54171 + */
54172 +static int ubicom32plio80_release(struct device *dev)
54173 +{
54174 +       struct ubicom32plio80_drvdata *ud = dev_get_drvdata(dev);
54175 +
54176 +       unregister_framebuffer(ud->fbinfo);
54177 +
54178 +       if (ud->irq_req) {
54179 +               free_irq(TX_FIFO_INT(PLIO_PORT), ud);
54180 +       }
54181 +       if (ud->cmap_alloc) {
54182 +               fb_dealloc_cmap(&ud->fbinfo->cmap);
54183 +       }
54184 +
54185 +       if (ud->fb) {
54186 +               kfree(ud->fb);
54187 +       }
54188 +
54189 +       framebuffer_release(ud->fbinfo);
54190 +       dev_set_drvdata(dev, NULL);
54191 +
54192 +       return 0;
54193 +}
54194 +
54195 +/*
54196 + * ubicom32plio80_platform_probe
54197 + */
54198 +static int __init ubicom32plio80_platform_probe(struct platform_device *pdev)
54199 +{
54200 +       struct ubicom32plio80_drvdata *ud;
54201 +       struct fb_info *fbinfo;
54202 +       int rc;
54203 +       size_t fbsize;
54204 +       struct device *dev = &pdev->dev;
54205 +       int offset;
54206 +
54207 +       /*
54208 +        * This is the minimum VRAM size
54209 +        */
54210 +       fbsize = xres * yres * 2;
54211 +       if (!vram_size) {
54212 +               vram_size = (fbsize + 1023) / 1024;
54213 +       } else {
54214 +               if (fbsize > (vram_size * 1024)) {
54215 +                       dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
54216 +                       return -ENOMEM; // should be ebadparam?
54217 +               }
54218 +       }
54219 +
54220 +       /*
54221 +        * Allocate the framebuffer instance + our private data
54222 +        */
54223 +       fbinfo = framebuffer_alloc(sizeof(struct ubicom32plio80_drvdata), &pdev->dev);
54224 +       if (!fbinfo) {
54225 +               dev_err(dev, "Not enough memory to allocate instance.\n");
54226 +               return -ENOMEM;
54227 +       }
54228 +
54229 +       /*
54230 +        * Fill in our private data.
54231 +        */
54232 +       ud = (struct ubicom32plio80_drvdata *)fbinfo->par;
54233 +       ud->fbinfo = fbinfo;
54234 +       dev_set_drvdata(dev, ud);
54235 +
54236 +       /*
54237 +        * Allocate and align the requested amount of VRAM
54238 +        */
54239 +       ud->total_vram_size = (vram_size * 1024) + UBICOM32PLIO80_ALIGNMENT;
54240 +       ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
54241 +       if (ud->fb == NULL) {
54242 +               dev_err(dev, "Couldn't allocate VRAM\n");
54243 +               rc = -ENOMEM;
54244 +               goto fail;
54245 +       }
54246 +
54247 +       offset = (u32_t)ud->fb & (UBICOM32PLIO80_ALIGNMENT - 1);
54248 +       if (!offset) {
54249 +               ud->fb_aligned = ud->fb;
54250 +       } else {
54251 +               offset =  UBICOM32PLIO80_ALIGNMENT - offset;
54252 +               ud->fb_aligned = ud->fb + offset;
54253 +       }
54254 +
54255 +       /*
54256 +        * Clear the entire frame buffer
54257 +        */
54258 +       memset(ud->fb_aligned, 0, vram_size * 1024);
54259 +
54260 +       /*
54261 +        * Fill in the fb_var_screeninfo structure
54262 +        */
54263 +       memset(&ubicom32plio80_var, 0, sizeof(ubicom32plio80_var));
54264 +       ubicom32plio80_var.bits_per_pixel = BITS_PER_PIXEL;
54265 +       ubicom32plio80_var.red.length = 5;
54266 +       ubicom32plio80_var.green.length = 6;
54267 +       ubicom32plio80_var.green.offset = 5;
54268 +       ubicom32plio80_var.blue.length = 5;
54269 +       ubicom32plio80_var.activate = FB_ACTIVATE_NOW;
54270 +
54271 +       if (bgr) {
54272 +               ubicom32plio80_var.red.offset = 0;
54273 +               ubicom32plio80_var.blue.offset = 11;
54274 +       } else {
54275 +               ubicom32plio80_var.red.offset = 11;
54276 +               ubicom32plio80_var.blue.offset = 0;
54277 +       }
54278 +
54279 +       /*
54280 +        * Fill in the fb_info structure
54281 +        */
54282 +       ud->fbinfo->device = dev;
54283 +       ud->fbinfo->screen_base = (void *)ud->fb_aligned;
54284 +       ud->fbinfo->fbops = &ubicom32plio80_ops;
54285 +       ud->fbinfo->fix = ubicom32plio80_fix;
54286 +       ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
54287 +       ud->fbinfo->fix.smem_len = vram_size * 1024;
54288 +       ud->fbinfo->fix.line_length = xres * 2;
54289 +       ud->fbinfo->fix.mmio_start = (u32)ud;
54290 +       ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32plio80_drvdata);
54291 +
54292 +       /*
54293 +        * We support panning in the y direction only
54294 +        */
54295 +       ud->fbinfo->fix.xpanstep = 0;
54296 +       ud->fbinfo->fix.ypanstep = 1;
54297 +
54298 +       ud->fbinfo->pseudo_palette = ud->pseudo_palette;
54299 +       ud->fbinfo->flags = FBINFO_DEFAULT;
54300 +       ud->fbinfo->var = ubicom32plio80_var;
54301 +       ud->fbinfo->var.xres = xres;
54302 +       ud->fbinfo->var.yres = yres;
54303 +
54304 +       /*
54305 +        * We cannot pan in the X direction, so xres_virtual is xres
54306 +        * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
54307 +        */
54308 +       ud->fbinfo->var.xres_virtual = xres;
54309 +       ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
54310 +
54311 +       /*
54312 +        * Allocate a color map
54313 +        */
54314 +       rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
54315 +       if (rc) {
54316 +               dev_err(dev, "Fail to allocate colormap (%d entries)\n",
54317 +                       PALETTE_ENTRIES_NO);
54318 +               goto fail;
54319 +       }
54320 +       ud->cmap_alloc = true;
54321 +
54322 +       /*
54323 +        * Register new frame buffer
54324 +        */
54325 +       rc = register_framebuffer(ud->fbinfo);
54326 +       if (rc) {
54327 +               dev_err(dev, "Could not register frame buffer\n");
54328 +               goto fail;
54329 +       }
54330 +
54331 +       /*
54332 +        * request the PLIO IRQ
54333 +        */
54334 +       rc = request_irq(TX_FIFO_INT(PLIO_PORT), ubicom32plio80_isr, IRQF_DISABLED, "ubicom32plio80", ud);
54335 +       if (rc) {
54336 +               dev_err(dev, "Could not request IRQ\n");
54337 +               goto fail;
54338 +       }
54339 +       ud->irq_req = 1;
54340 +
54341 +       /*
54342 +        * Clear any garbage out of the TX FIFOs (idif_txfifo_flush)
54343 +        *
54344 +        * cast through ubicom32_io_port to make sure the compiler does a word write
54345 +        */
54346 +       ((struct ubicom32_io_port *)PLIO_NBR)->int_set = (1 << 18);
54347 +
54348 +       /*
54349 +        * Start up the state machine
54350 +        */
54351 +       plio_init(&plio_fctl, &plio_config, (plio_sram_t *)ubicom32plio80_plio_fsm, sizeof(ubicom32plio80_plio_fsm));
54352 +       PLIO_NBR->fctl0.pfsm_cmd = 0;
54353 +
54354 +       ubicom32plio80_update(ud, ud->fb_aligned);
54355 +
54356 +       /*
54357 +        * Tell the log we are here
54358 +        */
54359 +       dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
54360 +               ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
54361 +               ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
54362 +
54363 +       /*
54364 +        * Success
54365 +        */
54366 +       return 0;
54367 +
54368 +fail:
54369 +       ubicom32plio80_release(dev);
54370 +       return rc;
54371 +}
54372 +
54373 +/*
54374 + * ubicom32plio80_platform_remove
54375 + */
54376 +static int ubicom32plio80_platform_remove(struct platform_device *pdev)
54377 +{
54378 +       dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
54379 +       return ubicom32plio80_release(&pdev->dev);
54380 +}
54381 +
54382 +static struct platform_driver ubicom32plio80_platform_driver = {
54383 +       .probe          = ubicom32plio80_platform_probe,
54384 +       .remove         = ubicom32plio80_platform_remove,
54385 +       .driver = {
54386 +               .name = DRIVER_NAME,
54387 +               .owner = THIS_MODULE,
54388 +       },
54389 +};
54390 +
54391 +#ifndef MODULE
54392 +/*
54393 + * ubicom32plio80_setup
54394 + *     Process kernel boot options
54395 + */
54396 +static int __init ubicom32plio80_setup(char *options)
54397 +{
54398 +       char *this_opt;
54399 +
54400 +       if (!options || !*options) {
54401 +               return 0;
54402 +       }
54403 +
54404 +       while ((this_opt = strsep(&options, ",")) != NULL) {
54405 +               if (!*this_opt) {
54406 +                       continue;
54407 +               }
54408 +
54409 +               if (!strncmp(this_opt, "vram_size=", 10)) {
54410 +                       vram_size = simple_strtoul(this_opt + 10, NULL, 0);
54411 +                       continue;
54412 +               }
54413 +
54414 +               if (!strncmp(this_opt, "bgr=", 4)) {
54415 +                       bgr = simple_strtoul(this_opt + 4, NULL, 0);
54416 +                       continue;
54417 +               }
54418 +
54419 +               if (!strncmp(this_opt, "xres=", 5)) {
54420 +                       xres = simple_strtoul(this_opt + 5, NULL, 0);
54421 +                       continue;
54422 +               }
54423 +
54424 +               if (!strncmp(this_opt, "yres=", 5)) {
54425 +                       yres = simple_strtoul(this_opt + 5, NULL, 0);
54426 +                       continue;
54427 +               }
54428 +       }
54429 +       return 0;
54430 +}
54431 +#endif /* MODULE */
54432 +
54433 +/*
54434 + * ubicom32plio80_init
54435 + */
54436 +static int __devinit ubicom32plio80_init(void)
54437 +{
54438 +       int ret;
54439 +
54440 +#ifndef MODULE
54441 +       /*
54442 +        * Get kernel boot options (in 'video=ubicom32plio80:<options>')
54443 +        */
54444 +       char *option = NULL;
54445 +
54446 +       if (fb_get_options(DRIVER_NAME, &option)) {
54447 +               return -ENODEV;
54448 +       }
54449 +       ubicom32plio80_setup(option);
54450 +#endif /* MODULE */
54451 +
54452 +       ret = platform_driver_register(&ubicom32plio80_platform_driver);
54453 +
54454 +       if (!ret) {
54455 +               ubicom32plio80_platform_device = platform_device_alloc(DRIVER_NAME, 0);
54456 +
54457 +               if (ubicom32plio80_platform_device)
54458 +                       ret = platform_device_add(ubicom32plio80_platform_device);
54459 +               else
54460 +                       ret = -ENOMEM;
54461 +
54462 +               if (ret) {
54463 +                       platform_device_put(ubicom32plio80_platform_device);
54464 +                       platform_driver_unregister(&ubicom32plio80_platform_driver);
54465 +               }
54466 +       }
54467 +
54468 +       return ret;
54469 +}
54470 +module_init(ubicom32plio80_init);
54471 +
54472 +/*
54473 + * ubicom32plio80_exit
54474 + */
54475 +static void __exit ubicom32plio80_exit(void)
54476 +{
54477 +       platform_device_unregister(ubicom32plio80_platform_device);
54478 +       platform_driver_unregister(&ubicom32plio80_platform_driver);
54479 +}
54480 +module_exit(ubicom32plio80_exit);
54481 +
54482 +MODULE_LICENSE("GPL");
54483 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
54484 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
54485 --- /dev/null
54486 +++ b/drivers/video/ubicom32vfb.c
54487 @@ -0,0 +1,603 @@
54488 +/*
54489 + * drivers/video/ubicom32vfb.c
54490 + *     Ubicom32 virtual frame buffer driver
54491 + *
54492 + * (C) Copyright 2009, Ubicom, Inc.
54493 + *
54494 + * This file is part of the Ubicom32 Linux Kernel Port.
54495 + *
54496 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
54497 + * it and/or modify it under the terms of the GNU General Public License
54498 + * as published by the Free Software Foundation, either version 2 of the
54499 + * License, or (at your option) any later version.
54500 + *
54501 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
54502 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
54503 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
54504 + * the GNU General Public License for more details.
54505 + *
54506 + * You should have received a copy of the GNU General Public License
54507 + * along with the Ubicom32 Linux Kernel Port.  If not,
54508 + * see <http://www.gnu.org/licenses/>.
54509 + */
54510 +
54511 +/*
54512 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
54513 + * Geert Uytterhoeven.
54514 + */
54515 +
54516 +#include <linux/device.h>
54517 +#include <linux/module.h>
54518 +#include <linux/kernel.h>
54519 +#include <linux/version.h>
54520 +#include <linux/errno.h>
54521 +#include <linux/string.h>
54522 +#include <linux/mm.h>
54523 +#include <linux/fb.h>
54524 +#include <linux/init.h>
54525 +#include <linux/dma-mapping.h>
54526 +#include <linux/platform_device.h>
54527 +#include <linux/device.h>
54528 +#include <linux/uaccess.h>
54529 +
54530 +#define DRIVER_NAME            "ubicom32vfb"
54531 +#define DRIVER_DESCRIPTION     "Ubicom32 virtual frame buffer driver"
54532 +
54533 +#define PALETTE_ENTRIES_NO     16
54534 +
54535 +/*
54536 + * Option variables
54537 + *
54538 + * vram_size:  VRAM size in kilobytes, subject to alignment
54539 + */
54540 +static int vram_size = 0;
54541 +module_param(vram_size, int, 0);
54542 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
54543 +
54544 +static int xres = 320;
54545 +module_param(xres, int, 0);
54546 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
54547 +
54548 +static int yres = 240;
54549 +module_param(yres, int, 0);
54550 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
54551 +
54552 +static int bgr = 0;
54553 +module_param(bgr, int, 0);
54554 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
54555 +
54556 +#define BITS_PER_PIXEL 16
54557 +
54558 +/*
54559 + * Buffer alignment, must not be 0
54560 + */
54561 +#define UBICOM32VFB_ALIGNMENT 4
54562 +
54563 +/*
54564 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
54565 + */
54566 +static struct fb_fix_screeninfo ubicom32vfb_fix = {
54567 +       .id =           "Ubicom32",
54568 +       .type =         FB_TYPE_PACKED_PIXELS,
54569 +       .visual =       FB_VISUAL_TRUECOLOR,
54570 +       .accel =        FB_ACCEL_UBICOM32_VFB,
54571 +};
54572 +
54573 +/*
54574 + * Filled in at probe time when we find out what the hardware supports
54575 + */
54576 +static struct fb_var_screeninfo ubicom32vfb_var;
54577 +
54578 +/*
54579 + * Private data structure
54580 + */
54581 +struct ubicom32vfb_drvdata {
54582 +       struct fb_info                  *fbinfo;
54583 +       bool                            cmap_alloc;
54584 +
54585 +       /*
54586 +        * The address of the framebuffer in memory
54587 +        */
54588 +       void                            *fb;
54589 +       void                            *fb_aligned;
54590 +
54591 +       /*
54592 +        * Total size of vram including alignment allowance
54593 +        */
54594 +       u32                             total_vram_size;
54595 +
54596 +       /*
54597 +        * Fake palette of 16 colors
54598 +        */
54599 +       u32                             pseudo_palette[PALETTE_ENTRIES_NO];
54600 +};
54601 +
54602 +static struct platform_device *ubicom32vfb_platform_device;
54603 +
54604 +/*
54605 + * ubicom32vfb_pan_display
54606 + *     Pans the display to a given location.  Supports only y direction panning.
54607 + */
54608 +static int ubicom32vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
54609 +{
54610 +       struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)fbi->par;
54611 +       void *new_addr;
54612 +
54613 +       /*
54614 +        * Get the last y line that would be displayed.  Since we don't support YWRAP,
54615 +        * it must be less than our virtual y size.
54616 +        */
54617 +       u32 lasty = var->yoffset + var->yres;
54618 +       if (lasty > fbi->var.yres_virtual) {
54619 +               /*
54620 +                * We would fall off the end of our frame buffer if we panned here.
54621 +                */
54622 +               return -EINVAL;
54623 +       }
54624 +
54625 +       if (var->xoffset) {
54626 +               /*
54627 +                * We don't support panning in the x direction
54628 +                */
54629 +               return -EINVAL;
54630 +       }
54631 +
54632 +       /*
54633 +        * Everything looks sane, go ahead and pan
54634 +        *
54635 +        * We have to calculate a new address for the VDC to look at
54636 +        */
54637 +       new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54638 +
54639 +       return 0;
54640 +}
54641 +
54642 +/*
54643 + * ubicom32vfb_setcolreg
54644 + *     Sets a color in our virtual palette
54645 + */
54646 +static int ubicom32vfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54647 +{
54648 +       u32 *palette = fbi->pseudo_palette;
54649 +
54650 +       if (regno >= PALETTE_ENTRIES_NO) {
54651 +               return -EINVAL;
54652 +       }
54653 +
54654 +       /*
54655 +        * We only use 8 bits from each color
54656 +        */
54657 +       red >>= 8;
54658 +       green >>= 8;
54659 +       blue >>= 8;
54660 +
54661 +       /*
54662 +        * Convert any grayscale values
54663 +        */
54664 +       if (fbi->var.grayscale) {
54665 +               u16 gray = red + green + blue;
54666 +               gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54667 +               gray >>= 2;
54668 +               if (gray > 255) {
54669 +                       gray = 255;
54670 +               }
54671 +               red = gray;
54672 +               blue = gray;
54673 +               green = gray;
54674 +       }
54675 +
54676 +       palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54677 +                        (blue << fbi->var.blue.offset);
54678 +
54679 +       return 0;
54680 +}
54681 +
54682 +/*
54683 + * ubicom32vfb_mmap
54684 + */
54685 +static int ubicom32vfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
54686 +{
54687 +       struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
54688 +
54689 +       vma->vm_start = (unsigned long)(ud->fb_aligned);
54690 +
54691 +       vma->vm_end = vma->vm_start + info->fix.smem_len;
54692 +
54693 +       /* For those who don't understand how mmap works, go read
54694 +        *   Documentation/nommu-mmap.txt.
54695 +        * For those that do, you will know that the VM_MAYSHARE flag
54696 +        * must be set in the vma->vm_flags structure on noMMU
54697 +        *   Other flags can be set, and are documented in
54698 +        *   include/linux/mm.h
54699 +        */
54700 +
54701 +       vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
54702 +
54703 +       return 0;
54704 +}
54705 +
54706 +/*
54707 + * ubicom32vfb_check_var
54708 + *     Check the var, tweak it but don't change operational parameters.
54709 + */
54710 +static int ubicom32vfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
54711 +{
54712 +       struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
54713 +       u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
54714 +
54715 +       /*
54716 +        * See if we can handle this bpp
54717 +        */
54718 +       if (var->bits_per_pixel > BITS_PER_PIXEL) {
54719 +               return -EINVAL;
54720 +       }
54721 +       var->bits_per_pixel = BITS_PER_PIXEL;
54722 +
54723 +       /*
54724 +        * See if we have enough memory to handle this resolution
54725 +        */
54726 +       if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
54727 +               return -EINVAL;
54728 +       }
54729 +
54730 +       var->xres_virtual = var->xres;
54731 +       var->yres_virtual = ud->total_vram_size / line_size;
54732 +
54733 +       var->red.length = 5;
54734 +       var->green.length = 6;
54735 +       var->green.offset = 5;
54736 +       var->blue.length = 5;
54737 +       var->transp.offset = var->transp.length = 0;
54738 +
54739 +       if (bgr) {
54740 +               var->red.offset = 0;
54741 +               var->blue.offset = 11;
54742 +       } else {
54743 +               var->red.offset = 11;
54744 +               var->blue.offset = 0;
54745 +       }
54746 +
54747 +       var->nonstd = 0;
54748 +       var->height = -1;
54749 +       var->width = -1;
54750 +       var->vmode = FB_VMODE_NONINTERLACED;
54751 +       var->sync = 0;
54752 +
54753 +       return 0;
54754 +}
54755 +
54756 +/*
54757 + * ubicom32vfb_set_par
54758 + *     Set the video mode according to info->var
54759 + */
54760 +static int ubicom32vfb_set_par(struct fb_info *info)
54761 +{
54762 +       /*
54763 +        * Anything changed?
54764 +        */
54765 +       if ((xres == info->var.xres) && (yres == info->var.yres)) {
54766 +               return 0;
54767 +       }
54768 +
54769 +       /*
54770 +        * Implement changes
54771 +        */
54772 +       xres = info->var.xres;
54773 +       yres = info->var.yres;
54774 +       info->fix.visual = FB_VISUAL_TRUECOLOR;
54775 +       info->fix.xpanstep = 0;
54776 +       info->fix.ypanstep = 1;
54777 +       info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
54778 +
54779 +       return 0;
54780 +}
54781 +
54782 +/*
54783 + * ubicom32vfb_ops
54784 + *     List of supported operations
54785 + */
54786 +static struct fb_ops ubicom32vfb_ops =
54787 +{
54788 +       .owner                  = THIS_MODULE,
54789 +       .fb_pan_display         = ubicom32vfb_pan_display,
54790 +       .fb_setcolreg           = ubicom32vfb_setcolreg,
54791 +       .fb_mmap                = ubicom32vfb_mmap,
54792 +       .fb_check_var           = ubicom32vfb_check_var,
54793 +       .fb_set_par             = ubicom32vfb_set_par,
54794 +       .fb_fillrect            = cfb_fillrect,
54795 +       .fb_copyarea            = cfb_copyarea,
54796 +       .fb_imageblit           = cfb_imageblit,
54797 +};
54798 +
54799 +/*
54800 + * ubicom32vfb_release
54801 + */
54802 +static int ubicom32vfb_release(struct device *dev)
54803 +{
54804 +       struct ubicom32vfb_drvdata *ud = dev_get_drvdata(dev);
54805 +
54806 +       unregister_framebuffer(ud->fbinfo);
54807 +
54808 +       if (ud->cmap_alloc) {
54809 +               fb_dealloc_cmap(&ud->fbinfo->cmap);
54810 +       }
54811 +
54812 +       if (ud->fb) {
54813 +               kfree(ud->fb);
54814 +       }
54815 +
54816 +       framebuffer_release(ud->fbinfo);
54817 +       dev_set_drvdata(dev, NULL);
54818 +
54819 +       return 0;
54820 +}
54821 +
54822 +/*
54823 + * ubicom32vfb_platform_probe
54824 + */
54825 +static int __init ubicom32vfb_platform_probe(struct platform_device *pdev)
54826 +{
54827 +       struct ubicom32vfb_drvdata *ud;
54828 +       struct fb_info *fbinfo;
54829 +       int rc;
54830 +       size_t fbsize;
54831 +       struct device *dev = &pdev->dev;
54832 +       int offset;
54833 +
54834 +       /*
54835 +        * This is the minimum VRAM size
54836 +        */
54837 +       fbsize = xres * yres * 2;
54838 +       if (!vram_size) {
54839 +               vram_size = (fbsize + 1023) / 1024;
54840 +       } else {
54841 +               if (fbsize > (vram_size * 1024)) {
54842 +                       dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
54843 +                       return -ENOMEM; // should be ebadparam?
54844 +               }
54845 +       }
54846 +
54847 +       /*
54848 +        * Allocate the framebuffer instance + our private data
54849 +        */
54850 +       fbinfo = framebuffer_alloc(sizeof(struct ubicom32vfb_drvdata), &pdev->dev);
54851 +       if (!fbinfo) {
54852 +               dev_err(dev, "Not enough memory to allocate instance.\n");
54853 +               return -ENOMEM;
54854 +       }
54855 +
54856 +       /*
54857 +        * Fill in our private data.
54858 +        */
54859 +       ud = (struct ubicom32vfb_drvdata *)fbinfo->par;
54860 +       ud->fbinfo = fbinfo;
54861 +       dev_set_drvdata(dev, ud);
54862 +
54863 +       /*
54864 +        * Allocate and align the requested amount of VRAM
54865 +        */
54866 +       ud->total_vram_size = (vram_size * 1024) + UBICOM32VFB_ALIGNMENT;
54867 +       ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
54868 +       if (ud->fb == NULL) {
54869 +               dev_err(dev, "Couldn't allocate VRAM\n");
54870 +               rc = -ENOMEM;
54871 +               goto fail;
54872 +       }
54873 +
54874 +       offset = (u32_t)ud->fb & (UBICOM32VFB_ALIGNMENT - 1);
54875 +       if (!offset) {
54876 +               ud->fb_aligned = ud->fb;
54877 +       } else {
54878 +               offset =  UBICOM32VFB_ALIGNMENT - offset;
54879 +               ud->fb_aligned = ud->fb + offset;
54880 +       }
54881 +
54882 +       /*
54883 +        * Clear the entire frame buffer
54884 +        */
54885 +       memset(ud->fb_aligned, 0, vram_size * 1024);
54886 +
54887 +       /*
54888 +        * Fill in the fb_var_screeninfo structure
54889 +        */
54890 +       memset(&ubicom32vfb_var, 0, sizeof(ubicom32vfb_var));
54891 +       ubicom32vfb_var.bits_per_pixel = BITS_PER_PIXEL;
54892 +       ubicom32vfb_var.red.length = 5;
54893 +       ubicom32vfb_var.green.length = 6;
54894 +       ubicom32vfb_var.green.offset = 5;
54895 +       ubicom32vfb_var.blue.length = 5;
54896 +       ubicom32vfb_var.activate = FB_ACTIVATE_NOW;
54897 +
54898 +       if (bgr) {
54899 +               ubicom32vfb_var.red.offset = 0;
54900 +               ubicom32vfb_var.blue.offset = 11;
54901 +       } else {
54902 +               ubicom32vfb_var.red.offset = 11;
54903 +               ubicom32vfb_var.blue.offset = 0;
54904 +       }
54905 +
54906 +       /*
54907 +        * Fill in the fb_info structure
54908 +        */
54909 +       ud->fbinfo->device = dev;
54910 +       ud->fbinfo->screen_base = (void *)ud->fb_aligned;
54911 +       ud->fbinfo->fbops = &ubicom32vfb_ops;
54912 +       ud->fbinfo->fix = ubicom32vfb_fix;
54913 +       ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
54914 +       ud->fbinfo->fix.smem_len = vram_size * 1024;
54915 +       ud->fbinfo->fix.line_length = xres * 2;
54916 +       ud->fbinfo->fix.mmio_start = (u32)ud;
54917 +       ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32vfb_drvdata);
54918 +
54919 +       /*
54920 +        * We support panning in the y direction only
54921 +        */
54922 +       ud->fbinfo->fix.xpanstep = 0;
54923 +       ud->fbinfo->fix.ypanstep = 1;
54924 +
54925 +       ud->fbinfo->pseudo_palette = ud->pseudo_palette;
54926 +       ud->fbinfo->flags = FBINFO_DEFAULT;
54927 +       ud->fbinfo->var = ubicom32vfb_var;
54928 +       ud->fbinfo->var.xres = xres;
54929 +       ud->fbinfo->var.yres = yres;
54930 +
54931 +       /*
54932 +        * We cannot pan in the X direction, so xres_virtual is xres
54933 +        * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
54934 +        */
54935 +       ud->fbinfo->var.xres_virtual = xres;
54936 +       ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
54937 +
54938 +       /*
54939 +        * Allocate a color map
54940 +        */
54941 +       rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
54942 +       if (rc) {
54943 +               dev_err(dev, "Fail to allocate colormap (%d entries)\n",
54944 +                       PALETTE_ENTRIES_NO);
54945 +               goto fail;
54946 +       }
54947 +       ud->cmap_alloc = true;
54948 +
54949 +       /*
54950 +        * Register new frame buffer
54951 +        */
54952 +       rc = register_framebuffer(ud->fbinfo);
54953 +       if (rc) {
54954 +               dev_err(dev, "Could not register frame buffer\n");
54955 +               goto fail;
54956 +       }
54957 +
54958 +       /*
54959 +        * Tell the log we are here
54960 +        */
54961 +       dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
54962 +               ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
54963 +               ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
54964 +
54965 +       /*
54966 +        * Success
54967 +        */
54968 +       return 0;
54969 +
54970 +fail:
54971 +       ubicom32vfb_release(dev);
54972 +       return rc;
54973 +}
54974 +
54975 +/*
54976 + * ubicom32vfb_platform_remove
54977 + */
54978 +static int ubicom32vfb_platform_remove(struct platform_device *pdev)
54979 +{
54980 +       dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
54981 +       return ubicom32vfb_release(&pdev->dev);
54982 +}
54983 +
54984 +static struct platform_driver ubicom32vfb_platform_driver = {
54985 +       .probe          = ubicom32vfb_platform_probe,
54986 +       .remove         = ubicom32vfb_platform_remove,
54987 +       .driver = {
54988 +               .name = DRIVER_NAME,
54989 +               .owner = THIS_MODULE,
54990 +       },
54991 +};
54992 +
54993 +#ifndef MODULE
54994 +/*
54995 + * ubicom32vfb_setup
54996 + *     Process kernel boot options
54997 + */
54998 +static int __init ubicom32vfb_setup(char *options)
54999 +{
55000 +       char *this_opt;
55001 +
55002 +       if (!options || !*options) {
55003 +               return 0;
55004 +       }
55005 +
55006 +       while ((this_opt = strsep(&options, ",")) != NULL) {
55007 +               if (!*this_opt) {
55008 +                       continue;
55009 +               }
55010 +
55011 +               if (!strncmp(this_opt, "vram_size=", 10)) {
55012 +                       vram_size = simple_strtoul(this_opt + 10, NULL, 0);
55013 +                       continue;
55014 +               }
55015 +
55016 +               if (!strncmp(this_opt, "bgr=", 4)) {
55017 +                       bgr = simple_strtoul(this_opt + 4, NULL, 0);
55018 +                       continue;
55019 +               }
55020 +
55021 +               if (!strncmp(this_opt, "xres=", 5)) {
55022 +                       xres = simple_strtoul(this_opt + 5, NULL, 0);
55023 +                       continue;
55024 +               }
55025 +
55026 +               if (!strncmp(this_opt, "yres=", 5)) {
55027 +                       yres = simple_strtoul(this_opt + 5, NULL, 0);
55028 +                       continue;
55029 +               }
55030 +       }
55031 +       return 0;
55032 +}
55033 +#endif /* MODULE */
55034 +
55035 +/*
55036 + * ubicom32vfb_init
55037 + */
55038 +static int __devinit ubicom32vfb_init(void)
55039 +{
55040 +       int ret;
55041 +
55042 +#ifndef MODULE
55043 +       /*
55044 +        * Get kernel boot options (in 'video=ubicom32vfb:<options>')
55045 +        */
55046 +       char *option = NULL;
55047 +
55048 +       if (fb_get_options(DRIVER_NAME, &option)) {
55049 +               return -ENODEV;
55050 +       }
55051 +       ubicom32vfb_setup(option);
55052 +#endif /* MODULE */
55053 +
55054 +       ret = platform_driver_register(&ubicom32vfb_platform_driver);
55055 +
55056 +#ifdef CONFIG_FB_UBICOM32_VIRTUAL_NOAUTO
55057 +       return ret;
55058 +#else
55059 +       if (!ret) {
55060 +               ubicom32vfb_platform_device = platform_device_alloc(DRIVER_NAME, 0);
55061 +
55062 +               if (ubicom32vfb_platform_device)
55063 +                       ret = platform_device_add(ubicom32vfb_platform_device);
55064 +               else
55065 +                       ret = -ENOMEM;
55066 +
55067 +               if (ret) {
55068 +                       platform_device_put(ubicom32vfb_platform_device);
55069 +                       platform_driver_unregister(&ubicom32vfb_platform_driver);
55070 +               }
55071 +       }
55072 +
55073 +       return ret;
55074 +#endif
55075 +}
55076 +module_init(ubicom32vfb_init);
55077 +
55078 +/*
55079 + * ubicom32vfb_exit
55080 + */
55081 +static void __exit ubicom32vfb_exit(void)
55082 +{
55083 +       platform_device_unregister(ubicom32vfb_platform_device);
55084 +       platform_driver_unregister(&ubicom32vfb_platform_driver);
55085 +}
55086 +module_exit(ubicom32vfb_exit);
55087 +
55088 +MODULE_LICENSE("GPL");
55089 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
55090 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
55091 --- a/drivers/watchdog/Kconfig
55092 +++ b/drivers/watchdog/Kconfig
55093 @@ -887,6 +887,19 @@ config WATCHDOG_RIO
55094           machines.  The watchdog timeout period is normally one minute but
55095           can be changed with a boot-time parameter.
55096  
55097 +# Ubicom32
55098 +
55099 +config UBI32_WDT
55100 +       tristate "Ubicom32 Hardware Watchdog support"
55101 +       depends on UBICOM32
55102 +       ---help---
55103 +         If you say yes here you will get support for the Ubicom32 On-Chip
55104 +         Watchdog Timer. If you have one of these processors and wish to
55105 +         have watchdog support enabled, say Y, otherwise say N.
55106 +
55107 +         To compile this driver as a module, choose M here: the
55108 +         module will be called ubi32_wdt.
55109 +
55110  # XTENSA Architecture
55111  
55112  #
55113 --- a/drivers/watchdog/Makefile
55114 +++ b/drivers/watchdog/Makefile
55115 @@ -131,6 +131,9 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
55116  obj-$(CONFIG_WATCHDOG_RIO)             += riowd.o
55117  obj-$(CONFIG_WATCHDOG_CP1XXX)          += cpwd.o
55118  
55119 +# Ubicom32 Architecture
55120 +obj-$(CONFIG_UBI32_WDT)                        += ubi32_wdt.o
55121 +
55122  # XTENSA Architecture
55123  
55124  # Architecture Independant
55125 --- /dev/null
55126 +++ b/drivers/watchdog/ubi32_wdt.c
55127 @@ -0,0 +1,630 @@
55128 +/*
55129 + * drivers/watchdog/ubi32_wdt.c
55130 + *   Ubicom32 Watchdog Driver
55131 + *
55132 + * Originally based on softdog.c
55133 + * Copyright 2006-2007 Analog Devices Inc.
55134 + * Copyright 2006-2007 Michele d'Amico
55135 + * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
55136 + * (C) Copyright 2009, Ubicom, Inc.
55137 + *
55138 + * This file is part of the Ubicom32 Linux Kernel Port.
55139 + *
55140 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
55141 + * it and/or modify it under the terms of the GNU General Public License
55142 + * as published by the Free Software Foundation, either version 2 of the
55143 + * License, or (at your option) any later version.
55144 + *
55145 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
55146 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
55147 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
55148 + * the GNU General Public License for more details.
55149 + *
55150 + * You should have received a copy of the GNU General Public License
55151 + * along with the Ubicom32 Linux Kernel Port.  If not,
55152 + * see <http://www.gnu.org/licenses/>.
55153 + *
55154 + * Ubicom32 implementation derived from (with many thanks):
55155 + *   arch/m68knommu
55156 + *   arch/blackfin
55157 + *   arch/parisc
55158 + */
55159 +#include <linux/platform_device.h>
55160 +#include <linux/module.h>
55161 +#include <linux/moduleparam.h>
55162 +#include <linux/types.h>
55163 +#include <linux/timer.h>
55164 +#include <linux/miscdevice.h>
55165 +#include <linux/watchdog.h>
55166 +#include <linux/fs.h>
55167 +#include <linux/notifier.h>
55168 +#include <linux/reboot.h>
55169 +#include <linux/init.h>
55170 +#include <linux/interrupt.h>
55171 +#include <linux/uaccess.h>
55172 +#include <asm/ip5000.h>
55173 +
55174 +#define WATCHDOG_NAME "ubi32-wdt"
55175 +#define PFX WATCHDOG_NAME ": "
55176 +
55177 +#define OSC1_FREQ 12000000
55178 +#define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
55179 +#define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
55180 +
55181 +#define MIN_PROCESSOR_ADDRESS 0x03000000
55182 +
55183 +static DEFINE_SPINLOCK(ubi32_wdt_spinlock);
55184 +
55185 +#define WATCHDOG_TIMEOUT 20
55186 +
55187 +#if defined(CONFIG_WATCHDOG_NOWAYOUT)
55188 +#define WATCHDOG_NOWAYOUT 1
55189 +#else
55190 +#define WATCHDOG_NOWAYOUT 0
55191 +#endif
55192 +
55193 +static unsigned int timeout = WATCHDOG_TIMEOUT;
55194 +static int nowayout = WATCHDOG_NOWAYOUT;
55195 +static struct watchdog_info ubi32_wdt_info;
55196 +static unsigned long open_check;
55197 +static char expect_close;
55198 +
55199 +#if !defined(CONFIG_SMP)
55200 +#define UBI32_WDT_LOCK(lock, flags) local_irq_save(flags)
55201 +#define UBI32_WDT_UNLOCK(lock, flags) local_irq_restore(flags)
55202 +#define UBI32_WDT_LOCK_CHECK()
55203 +#else
55204 +#define UBI32_WDT_LOCK(lock, flags) spin_lock_irqsave((lock), (flags));
55205 +#define UBI32_WDT_UNLOCK(lock, flags) spin_unlock_irqrestore((lock), (flags));
55206 +#define UBI32_WDT_LOCK_CHECK() BUG_ON(!spin_is_locked(&ubi32_wdt_spinlock));
55207 +#endif
55208 +
55209 +/*
55210 + * ubi32_wdt_remaining()
55211 + *     Return the approximate number of seconds remaining
55212 + */
55213 +static int ubi32_wdt_remaining(void)
55214 +{
55215 +       int compare;
55216 +       int curr;
55217 +
55218 +       UBI32_WDT_LOCK_CHECK();
55219 +
55220 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55221 +       compare = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcom);
55222 +       curr = ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval);
55223 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55224 +       return (compare - curr) / OSC1_FREQ;
55225 +
55226 +}
55227 +
55228 +/*
55229 + * ubi32_wdt_keepalive()
55230 + *     Keep the Userspace Watchdog Alive
55231 + *
55232 + * The Userspace watchdog got a KeepAlive: schedule the next timeout.
55233 + */
55234 +static int ubi32_wdt_keepalive(void)
55235 +{
55236 +       UBI32_WDT_LOCK_CHECK();
55237 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55238 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55239 +                       ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55240 +                       + WATCHDOG_SEC_TO_CYC(timeout));
55241 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55242 +       return 0;
55243 +}
55244 +
55245 +/*
55246 + * ubi32_wdt_stop()
55247 + *     Stop the on-chip Watchdog
55248 + */
55249 +static int ubi32_wdt_stop(void)
55250 +{
55251 +       UBI32_WDT_LOCK_CHECK();
55252 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55253 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, TIMER_WATCHDOG_DISABLE);
55254 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55255 +       return 0;
55256 +}
55257 +
55258 +/*
55259 + * ubi32_wdt_start()
55260 + *     Start the on-chip Watchdog
55261 + */
55262 +static int ubi32_wdt_start(void)
55263 +{
55264 +       UBI32_WDT_LOCK_CHECK();
55265 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55266 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55267 +                       ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55268 +                       + WATCHDOG_SEC_TO_CYC(timeout));
55269 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, ~TIMER_WATCHDOG_DISABLE);
55270 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55271 +       return 0;
55272 +}
55273 +
55274 +/*
55275 + * ubi32_wdt_running()
55276 + *     Return true if the watchdog is configured
55277 + */
55278 +static int ubi32_wdt_running(void)
55279 +{
55280 +       int enabled;
55281 +
55282 +       UBI32_WDT_LOCK_CHECK();
55283 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55284 +       enabled = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcfg) == ~TIMER_WATCHDOG_DISABLE;
55285 +       ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55286 +       return enabled;
55287 +}
55288 +
55289 +/*
55290 + * ubi32_wdt_set_timeout()
55291 + *     Set the Userspace Watchdog timeout
55292 + *
55293 + * - @t: new timeout value (in seconds)
55294 + */
55295 +static int ubi32_wdt_set_timeout(unsigned long t)
55296 +{
55297 +       UBI32_WDT_LOCK_CHECK();
55298 +
55299 +       if (t > WATCHDOG_MAX_SEC) {
55300 +               printk(KERN_WARNING PFX "request to large: %ld [1-%d] sec)\n", t, WATCHDOG_MAX_SEC);
55301 +               return -EINVAL;
55302 +       }
55303 +
55304 +       /*
55305 +        * If we are running, then reset the time value so
55306 +        * that the new value has an immediate effect.
55307 +        */
55308 +       timeout = t;
55309 +       if (ubi32_wdt_running()) {
55310 +               ubi32_wdt_keepalive();
55311 +       }
55312 +       return 0;
55313 +}
55314 +
55315 +/*
55316 + * ubi32_wdt_open()
55317 + *     Open the Device
55318 + */
55319 +static int ubi32_wdt_open(struct inode *inode, struct file *file)
55320 +{
55321 +       unsigned long flags;
55322 +
55323 +       if (test_and_set_bit(0, &open_check))
55324 +               return -EBUSY;
55325 +
55326 +       if (nowayout)
55327 +               __module_get(THIS_MODULE);
55328 +
55329 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55330 +       ubi32_wdt_start();
55331 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55332 +
55333 +       return nonseekable_open(inode, file);
55334 +}
55335 +
55336 +/*
55337 + * ubi32_wdt_close()
55338 + *     Close the Device
55339 + */
55340 +static int ubi32_wdt_release(struct inode *inode, struct file *file)
55341 +{
55342 +       unsigned long flags;
55343 +
55344 +       /*
55345 +        * If we don't expect a close, then the watchdog continues
55346 +        * even though the device is closed.  The caller will have
55347 +        * a full timeout value to reopen the device and continue
55348 +        * stroking it.
55349 +        */
55350 +       if (expect_close != 42) {
55351 +               printk(KERN_CRIT PFX
55352 +                       "Unexpected close, not stopping watchdog!\n");
55353 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55354 +               ubi32_wdt_keepalive();
55355 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55356 +       } else {
55357 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55358 +               ubi32_wdt_stop();
55359 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55360 +       }
55361 +
55362 +       expect_close = 0;
55363 +       clear_bit(0, &open_check);
55364 +       return 0;
55365 +}
55366 +
55367 +/*
55368 + * ubi32_wdt_write()
55369 + *     Write to Device
55370 + *
55371 + * If the user writes nothing, nothing happens.
55372 + * If the user writes a V, then we expect a close and allow a release.
55373 + * If the user writes anything else, it is ignored.
55374 + */
55375 +static ssize_t ubi32_wdt_write(struct file *file, const char __user *data,
55376 +                                               size_t len, loff_t *ppos)
55377 +{
55378 +       size_t i;
55379 +       unsigned long flags;
55380 +
55381 +       /*
55382 +        * Every write resets the expect_close.  The last write
55383 +        * must be a V to allow shutdown on close.
55384 +        */
55385 +       expect_close = 0;
55386 +
55387 +       /*
55388 +        * Empty writes still ping.
55389 +        */
55390 +       if (!len) {
55391 +               goto ping;
55392 +       }
55393 +
55394 +       /*
55395 +        * If nowayout is set, it does not matter if the caller
55396 +        * is trying to send the magic 'V' we will not allow a
55397 +        * close to stop us.
55398 +        */
55399 +       if (nowayout) {
55400 +               goto ping;
55401 +       }
55402 +
55403 +       /*
55404 +        * See if the program wrote a 'V' and if so disable
55405 +        * the watchdog on release.
55406 +        */
55407 +       for (i = 0; i < len; i++) {
55408 +               char c;
55409 +               if (get_user(c, data + i)) {
55410 +                       return -EFAULT;
55411 +               }
55412 +
55413 +               if (c == 'V') {
55414 +                       expect_close = 42;
55415 +               }
55416 +       }
55417 +
55418 +ping:
55419 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55420 +       ubi32_wdt_keepalive();
55421 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55422 +       return len;
55423 +}
55424 +
55425 +/*
55426 + * ubi32_wdt_ioctl()
55427 + *     Query the watchdog device.
55428 + *
55429 + * Query basic information from the device or ping it, as outlined by the
55430 + * watchdog API.
55431 + */
55432 +static long ubi32_wdt_ioctl(struct file *file,
55433 +                               unsigned int cmd, unsigned long arg)
55434 +{
55435 +       void __user *argp = (void __user *)arg;
55436 +       int __user *p = argp;
55437 +
55438 +       switch (cmd) {
55439 +       case WDIOC_GETSUPPORT:
55440 +               if (copy_to_user(argp, &ubi32_wdt_info, sizeof(ubi32_wdt_info))) {
55441 +                       return -EFAULT;
55442 +               }
55443 +               return 0;
55444 +
55445 +       case WDIOC_GETSTATUS: {
55446 +               unsigned long flags;
55447 +               int running;
55448 +
55449 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55450 +               running = ubi32_wdt_running();
55451 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55452 +               return running;
55453 +       }
55454 +
55455 +       case WDIOC_GETBOOTSTATUS:
55456 +               return ubicom32_get_reset_reason();
55457 +
55458 +       case WDIOC_SETOPTIONS: {
55459 +               unsigned long flags;
55460 +               int options, ret = -EINVAL;
55461 +
55462 +               /*
55463 +                * The sample application does not pass a pointer
55464 +                * but directly passes a value of 1 or 2; however
55465 +                * all of the implementations (and thus probably
55466 +                * the real applications) pass a pointer to a value.
55467 +                *
55468 +                * It should be noted that  WDIOC_SETOPTIONS is defined as
55469 +                * _IOR(WATCHDOG_IOCTL_BASE, 4, int), which means
55470 +                * that it should be an int and NOT a pointer.
55471 +                *
55472 +                * TODO: Examine this code for future chips.
55473 +                * TODO: Report the sample code defect.
55474 +                */
55475 +               if ((int)p < MIN_PROCESSOR_ADDRESS) {
55476 +                       options = (int)p;
55477 +               } else {
55478 +                       if (get_user(options, p))
55479 +                       return -EFAULT;
55480 +               }
55481 +
55482 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55483 +               if (options & WDIOS_DISABLECARD) {
55484 +                       ubi32_wdt_stop();
55485 +                       ret = 0;
55486 +               }
55487 +               if (options & WDIOS_ENABLECARD) {
55488 +                       ubi32_wdt_start();
55489 +                       ret = 0;
55490 +               }
55491 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55492 +               return ret;
55493 +       }
55494 +
55495 +       case WDIOC_KEEPALIVE: {
55496 +               unsigned long flags;
55497 +
55498 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55499 +               ubi32_wdt_keepalive();
55500 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55501 +               return 0;
55502 +       }
55503 +
55504 +       case WDIOC_SETTIMEOUT: {
55505 +               int new_timeout;
55506 +               unsigned long flags;
55507 +               int ret  = 0;
55508 +
55509 +               if (get_user(new_timeout, p))
55510 +                       return -EFAULT;
55511 +
55512 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55513 +               ret = ubi32_wdt_set_timeout(new_timeout);
55514 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55515 +               return ret;
55516 +
55517 +       }
55518 +
55519 +       case WDIOC_GETTIMEOUT:
55520 +               return put_user(timeout, p);
55521 +
55522 +       case WDIOC_GETTIMELEFT: {
55523 +               unsigned long flags;
55524 +               int remaining = 0;
55525 +
55526 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55527 +               remaining = ubi32_wdt_remaining();
55528 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55529 +               return put_user(remaining, p);
55530 +       }
55531 +
55532 +       default:
55533 +               return -ENOTTY;
55534 +       }
55535 +}
55536 +
55537 +/*
55538 + * ubi32_wdt_notify_sys()
55539 + *     Notification callback function for system events.
55540 + *
55541 + * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
55542 + */
55543 +static int ubi32_wdt_notify_sys(struct notifier_block *this,
55544 +                                       unsigned long code, void *unused)
55545 +{
55546 +       if (code == SYS_DOWN || code == SYS_HALT) {
55547 +               unsigned long flags;
55548 +
55549 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55550 +               ubi32_wdt_stop();
55551 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55552 +       }
55553 +
55554 +       return NOTIFY_DONE;
55555 +}
55556 +
55557 +#ifdef CONFIG_PM
55558 +static int state_before_suspend;
55559 +
55560 +/*
55561 + * ubi32_wdt_suspend()
55562 + *     suspend the watchdog
55563 + *
55564 + * Remember if the watchdog was running and stop it.
55565 + */
55566 +static int ubi32_wdt_suspend(struct platform_device *pdev, pm_message_t state)
55567 +{
55568 +       unsigned long flags;
55569 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55570 +       state_before_suspend = ubi32_wdt_running();
55571 +       ubi32_wdt_stop();
55572 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55573 +
55574 +       return 0;
55575 +}
55576 +
55577 +/*
55578 + * ubi32_wdt_resume()
55579 + *     Resume the watchdog
55580 + *
55581 + * If the watchdog was running, turn it back on.
55582 + */
55583 +static int ubi32_wdt_resume(struct platform_device *pdev)
55584 +{
55585 +       if (state_before_suspend) {
55586 +               unsigned long flags;
55587 +               spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55588 +               ubi32_wdt_set_timeout(timeout);
55589 +               ubi32_wdt_start();
55590 +               spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55591 +       }
55592 +
55593 +       return 0;
55594 +}
55595 +#else
55596 +# define ubi32_wdt_suspend NULL
55597 +# define ubi32_wdt_resume NULL
55598 +#endif
55599 +
55600 +static const struct file_operations ubi32_wdt_fops = {
55601 +       .owner          = THIS_MODULE,
55602 +       .llseek         = no_llseek,
55603 +       .write          = ubi32_wdt_write,
55604 +       .unlocked_ioctl = ubi32_wdt_ioctl,
55605 +       .open           = ubi32_wdt_open,
55606 +       .release        = ubi32_wdt_release,
55607 +};
55608 +
55609 +static struct miscdevice ubi32_wdt_miscdev = {
55610 +       .minor    = WATCHDOG_MINOR,
55611 +       .name     = "watchdog",
55612 +       .fops     = &ubi32_wdt_fops,
55613 +};
55614 +
55615 +static struct watchdog_info ubi32_wdt_info = {
55616 +       .identity = "Ubicom32 Watchdog",
55617 +       .options  = WDIOF_SETTIMEOUT |
55618 +                   WDIOF_KEEPALIVEPING |
55619 +                   WDIOF_MAGICCLOSE,
55620 +};
55621 +
55622 +static struct notifier_block ubi32_wdt_notifier = {
55623 +       .notifier_call = ubi32_wdt_notify_sys,
55624 +};
55625 +
55626 +/*
55627 + * ubi32_wdt_probe()
55628 + *     Probe/register the watchdog module
55629 + *
55630 + * Registers the misc device and notifier handler.  Actual device
55631 + * initialization is handled by ubi32_wdt_open().
55632 + */
55633 +static int __devinit ubi32_wdt_probe(struct platform_device *pdev)
55634 +{
55635 +       int ret;
55636 +
55637 +       ret = register_reboot_notifier(&ubi32_wdt_notifier);
55638 +       if (ret) {
55639 +               printk(KERN_ERR PFX
55640 +                       "cannot register reboot notifier (err=%d)\n", ret);
55641 +               return ret;
55642 +       }
55643 +
55644 +       ret = misc_register(&ubi32_wdt_miscdev);
55645 +       if (ret) {
55646 +               printk(KERN_ERR PFX
55647 +                       "cannot register miscdev on minor=%d (err=%d)\n",
55648 +                               WATCHDOG_MINOR, ret);
55649 +               unregister_reboot_notifier(&ubi32_wdt_notifier);
55650 +               return ret;
55651 +       }
55652 +
55653 +       printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
55654 +              timeout, nowayout);
55655 +
55656 +       return 0;
55657 +}
55658 +
55659 +/*
55660 + * ubi32_wdt_remove()
55661 + *     Uninstall the module
55662 + *
55663 + * Unregisters the misc device and notifier handler.  Actual device
55664 + * deinitialization is handled by ubi32_wdt_close().
55665 + */
55666 +static int __devexit ubi32_wdt_remove(struct platform_device *pdev)
55667 +{
55668 +       misc_deregister(&ubi32_wdt_miscdev);
55669 +       unregister_reboot_notifier(&ubi32_wdt_notifier);
55670 +       return 0;
55671 +}
55672 +
55673 +static struct platform_device *ubi32_wdt_device;
55674 +
55675 +static struct platform_driver ubi32_wdt_driver = {
55676 +       .probe     = ubi32_wdt_probe,
55677 +       .remove    = __devexit_p(ubi32_wdt_remove),
55678 +       .suspend   = ubi32_wdt_suspend,
55679 +       .resume    = ubi32_wdt_resume,
55680 +       .driver    = {
55681 +               .name  = WATCHDOG_NAME,
55682 +               .owner = THIS_MODULE,
55683 +       },
55684 +};
55685 +
55686 +/*
55687 + * ubi32_wdt_init()
55688 + *     Initialize the watchdog.
55689 + *
55690 + * Checks the module params and registers the platform device & driver.
55691 + * Real work is in the platform probe function.
55692 + */
55693 +static int __init ubi32_wdt_init(void)
55694 +{
55695 +       unsigned long flags;
55696 +       int ret;
55697 +
55698 +       /*
55699 +        * Check that the timeout value is within range
55700 +        */
55701 +       spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55702 +       ret = ubi32_wdt_set_timeout(timeout);
55703 +       spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55704 +       if (ret) {
55705 +               return ret;
55706 +       }
55707 +
55708 +       /*
55709 +        * Since this is an on-chip device and needs no board-specific
55710 +        * resources, we'll handle all the platform device stuff here.
55711 +        */
55712 +       ret = platform_driver_register(&ubi32_wdt_driver);
55713 +       if (ret) {
55714 +               printk(KERN_ERR PFX "unable to register driver\n");
55715 +               return ret;
55716 +       }
55717 +
55718 +       ubi32_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
55719 +       if (IS_ERR(ubi32_wdt_device)) {
55720 +               printk(KERN_ERR PFX "unable to register device\n");
55721 +               platform_driver_unregister(&ubi32_wdt_driver);
55722 +               return PTR_ERR(ubi32_wdt_device);
55723 +       }
55724 +
55725 +       return 0;
55726 +}
55727 +
55728 +/*
55729 + * ubi32_wdt_exit()
55730 + *     Deinitialize module
55731 + *
55732 + * Back out the platform device & driver steps.  Real work is in the
55733 + * platform remove function.
55734 + */
55735 +static void __exit ubi32_wdt_exit(void)
55736 +{
55737 +       platform_device_unregister(ubi32_wdt_device);
55738 +       platform_driver_unregister(&ubi32_wdt_driver);
55739 +}
55740 +
55741 +module_init(ubi32_wdt_init);
55742 +module_exit(ubi32_wdt_exit);
55743 +
55744 +MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>");
55745 +MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver");
55746 +MODULE_LICENSE("GPL");
55747 +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
55748 +
55749 +module_param(timeout, uint, 0);
55750 +MODULE_PARM_DESC(timeout,
55751 +       "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
55752 +               __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
55753 +
55754 +module_param(nowayout, int, 0);
55755 +MODULE_PARM_DESC(nowayout,
55756 +       "Watchdog cannot be stopped once started (default="
55757 +               __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
55758 --- a/fs/binfmt_flat.c
55759 +++ b/fs/binfmt_flat.c
55760 @@ -67,6 +67,11 @@
55761  #define FLAT_DATA_ALIGN        (sizeof(void *))
55762  #endif
55763  
55764 +#ifndef ARCH_FLAT_ALIGN
55765 +#undef FLAT_DATA_ALIGN
55766 +#define FLAT_DATA_ALIGN        ARCH_FLAT_ALIGN
55767 +#endif
55768 +
55769  #define RELOC_FAILED 0xff00ff01                /* Relocation incorrect somewhere */
55770  #define UNLOADED_LIB 0x7ff000ff                /* Placeholder for unused library */
55771  
55772 @@ -436,6 +441,7 @@ static int load_flat_file(struct linux_b
55773         loff_t fpos;
55774         unsigned long start_code, end_code;
55775         int ret;
55776 +       int flush_happened = 0;
55777  
55778         hdr = ((struct flat_hdr *) bprm->buf);          /* exec-header */
55779         inode = bprm->file->f_path.dentry->d_inode;
55780 @@ -521,6 +527,7 @@ static int load_flat_file(struct linux_b
55781  
55782                 /* OK, This is the point of no return */
55783                 set_personality(PER_LINUX_32BIT);
55784 +               flush_happened = 1;
55785         }
55786  
55787         /*
55788 @@ -535,6 +542,12 @@ static int load_flat_file(struct linux_b
55789          * it all together.
55790          */
55791         if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
55792 +
55793 +#ifdef ARCH_FLAT_ALIGN_TEXT
55794 +               printk("Unable to mmap rom with ARCH alignment requirements\n");
55795 +               ret = -ENOEXEC;
55796 +               goto err;
55797 +#endif
55798                 /*
55799                  * this should give us a ROM ptr,  but if it doesn't we don't
55800                  * really care
55801 @@ -553,7 +566,7 @@ static int load_flat_file(struct linux_b
55802                         goto err;
55803                 }
55804  
55805 -               len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
55806 +               len = data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
55807                 len = PAGE_ALIGN(len);
55808                 down_write(&current->mm->mmap_sem);
55809                 realdatastart = do_mmap(0, 0, len,
55810 @@ -572,6 +585,7 @@ static int load_flat_file(struct linux_b
55811                 datapos = ALIGN(realdatastart +
55812                                 MAX_SHARED_LIBS * sizeof(unsigned long),
55813                                 FLAT_DATA_ALIGN);
55814 +               //datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
55815  
55816                 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
55817                                 (int)(data_len + bss_len + stack_len), (int)datapos);
55818 @@ -600,7 +614,11 @@ static int load_flat_file(struct linux_b
55819                 memp_size = len;
55820         } else {
55821  
55822 -               len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
55823 +               len = text_len + data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
55824 +#ifdef ARCH_FLAT_ALIGN_TEXT
55825 +               /* Reserve space for the text alignment. */
55826 +               len += FLAT_DATA_ALIGN;
55827 +#endif
55828                 len = PAGE_ALIGN(len);
55829                 down_write(&current->mm->mmap_sem);
55830                 textpos = do_mmap(0, 0, len,
55831 @@ -616,10 +634,17 @@ static int load_flat_file(struct linux_b
55832                         goto err;
55833                 }
55834  
55835 +               memp = textpos;
55836 +#ifdef ARCH_FLAT_ALIGN_TEXT
55837 +               textpos = ALIGN(textpos + sizeof(struct flat_hdr), FLAT_DATA_ALIGN) - sizeof(struct flat_hdr);
55838 +#endif
55839                 realdatastart = textpos + ntohl(hdr->data_start);
55840                 datapos = ALIGN(realdatastart +
55841                                 MAX_SHARED_LIBS * sizeof(unsigned long),
55842                                 FLAT_DATA_ALIGN);
55843 +//             datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
55844 +//             reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
55845 +//                                        ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN));
55846  
55847                 reloc = (unsigned long *)
55848                         (datapos + (ntohl(hdr->reloc_start) - text_len));
55849 @@ -659,7 +684,7 @@ static int load_flat_file(struct linux_b
55850                 }
55851                 if (result >= (unsigned long)-4096) {
55852                         printk("Unable to read code+data+bss, errno %d\n",(int)-result);
55853 -                       do_munmap(current->mm, textpos, text_len + data_len + extra +
55854 +                       do_munmap(current->mm, memp, text_len + data_len + extra +
55855                                 MAX_SHARED_LIBS * sizeof(unsigned long));
55856                         ret = result;
55857                         goto err;
55858 @@ -672,6 +697,9 @@ static int load_flat_file(struct linux_b
55859  
55860         /* The main program needs a little extra setup in the task structure */
55861         start_code = textpos + sizeof (struct flat_hdr);
55862 +#ifdef ARCH_FLAT_ALIGN_TEXT
55863 +       BUG_ON(ALIGN(start_code, FLAT_DATA_ALIGN) != start_code);
55864 +#endif
55865         end_code = textpos + text_len;
55866         if (id == 0) {
55867                 current->mm->start_code = start_code;
55868 @@ -800,6 +828,13 @@ static int load_flat_file(struct linux_b
55869  
55870         return 0;
55871  err:
55872 +       if (flush_happened) {
55873 +               /*
55874 +                * The parent process has already started running. We cannot allow the child to return back to user space
55875 +                * as this child is still uning the parent stack and 2 will clobber each other. We are going to kill this child.
55876 +                */
55877 +               do_exit(SIGTERM);
55878 +       }
55879         return ret;
55880  }
55881  
55882 --- a/fs/Kconfig.binfmt
55883 +++ b/fs/Kconfig.binfmt
55884 @@ -30,7 +30,7 @@ config COMPAT_BINFMT_ELF
55885  config BINFMT_ELF_FDPIC
55886         bool "Kernel support for FDPIC ELF binaries"
55887         default y
55888 -       depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
55889 +       depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || UBICOM32)
55890         help
55891           ELF FDPIC binaries are based on ELF, but allow the individual load
55892           segments of a binary to be located in memory independently of each
55893 --- a/include/asm-generic/resource.h
55894 +++ b/include/asm-generic/resource.h
55895 @@ -69,13 +69,16 @@
55896  /*
55897   * boot-time rlimit defaults for the init task:
55898   */
55899 +#ifndef        CONFIG_ELF_CORE
55900 +#define        CONFIG_USER_ELF_CORE_SIZE       0
55901 +#endif
55902  #define INIT_RLIMITS                                                   \
55903  {                                                                      \
55904         [RLIMIT_CPU]            = {  RLIM_INFINITY,  RLIM_INFINITY },   \
55905         [RLIMIT_FSIZE]          = {  RLIM_INFINITY,  RLIM_INFINITY },   \
55906         [RLIMIT_DATA]           = {  RLIM_INFINITY,  RLIM_INFINITY },   \
55907         [RLIMIT_STACK]          = {       _STK_LIM,   _STK_LIM_MAX },   \
55908 -       [RLIMIT_CORE]           = {              0,  RLIM_INFINITY },   \
55909 +       [RLIMIT_CORE]           = { CONFIG_USER_ELF_CORE_SIZE,  RLIM_INFINITY },        \
55910         [RLIMIT_RSS]            = {  RLIM_INFINITY,  RLIM_INFINITY },   \
55911         [RLIMIT_NPROC]          = {              0,              0 },   \
55912         [RLIMIT_NOFILE]         = {       INR_OPEN,       INR_OPEN },   \
55913 --- a/include/linux/elf-em.h
55914 +++ b/include/linux/elf-em.h
55915 @@ -41,6 +41,7 @@
55916   * up with a final number.
55917   */
55918  #define EM_ALPHA       0x9026
55919 +#define EM_UBICOM32            0xde3d  /* Ubicom32; no ABI */
55920  
55921  /* Bogus old v850 magic number, used by old tools. */
55922  #define EM_CYGNUS_V850 0x9080
55923 --- a/include/linux/fb.h
55924 +++ b/include/linux/fb.h
55925 @@ -151,6 +151,10 @@ struct dentry;
55926  #define FB_ACCEL_PROSAVAGE_DDR  0x8d   /* S3 ProSavage DDR             */
55927  #define FB_ACCEL_PROSAVAGE_DDRK 0x8e   /* S3 ProSavage DDR-K           */
55928  
55929 +#define FB_ACCEL_UBICOM32              0x0100  /* Ubicom32                     */
55930 +#define FB_ACCEL_UBICOM32_VFB          0x0101  /* Ubicom32 VFB                 */
55931 +#define FB_ACCEL_UBICOM32_PLIO80       0x0102  /* Ubicom32 PLIO80              */
55932 +
55933  struct fb_fix_screeninfo {
55934         char id[16];                    /* identification string eg "TT Builtin" */
55935         unsigned long smem_start;       /* Start of frame buffer mem */
55936 --- a/include/linux/if_ppp.h
55937 +++ b/include/linux/if_ppp.h
55938 @@ -114,14 +114,14 @@ struct pppol2tp_ioc_stats {
55939         __u16           tunnel_id;      /* redundant */
55940         __u16           session_id;     /* if zero, get tunnel stats */
55941         __u32           using_ipsec:1;  /* valid only for session_id == 0 */
55942 -       aligned_u64     tx_packets;
55943 -       aligned_u64     tx_bytes;
55944 -       aligned_u64     tx_errors;
55945 -       aligned_u64     rx_packets;
55946 -       aligned_u64     rx_bytes;
55947 -       aligned_u64     rx_seq_discards;
55948 -       aligned_u64     rx_oos_packets;
55949 -       aligned_u64     rx_errors;
55950 +       __u64   tx_packets;
55951 +       __u64   tx_bytes;
55952 +       __u64   tx_errors;
55953 +       __u64   rx_packets;
55954 +       __u64   rx_bytes;
55955 +       __u64   rx_seq_discards;
55956 +       __u64   rx_oos_packets;
55957 +       __u64   rx_errors;
55958  };
55959  
55960  #define ifr__name       b.ifr_ifrn.ifrn_name
55961 --- a/include/linux/oprofile.h
55962 +++ b/include/linux/oprofile.h
55963 @@ -99,6 +99,8 @@ void oprofile_add_sample(struct pt_regs 
55964   */
55965  void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
55966                                 unsigned long event, int is_kernel);
55967 +void oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
55968 +                               unsigned long event, int is_kernel, int cpu);
55969  
55970  /* Use this instead when the PC value is not from the regs. Doesn't
55971   * backtrace. */
55972 --- a/include/linux/serial_core.h
55973 +++ b/include/linux/serial_core.h
55974 @@ -167,6 +167,9 @@
55975  /* MAX3100 */
55976  #define PORT_MAX3100    86
55977  
55978 +/* Ubicom32 */
55979 +#define PORT_UBI32_UARTTIO     87
55980 +
55981  #ifdef __KERNEL__
55982  
55983  #include <linux/compiler.h>
55984 --- a/include/linux/slab.h
55985 +++ b/include/linux/slab.h
55986 @@ -317,4 +317,14 @@ static inline void *kzalloc_node(size_t 
55987         return kmalloc_node(size, flags | __GFP_ZERO, node);
55988  }
55989  
55990 +struct kmem_cache_size_info {
55991 +       unsigned short page;
55992 +       unsigned short order;
55993 +};
55994 +
55995 +/*
55996 + * get info on all the memory allocated by slab for this named cache
55997 + */
55998 +extern int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data);
55999 +
56000  #endif /* _LINUX_SLAB_H */
56001 --- a/init/Kconfig
56002 +++ b/init/Kconfig
56003 @@ -865,6 +865,12 @@ config ELF_CORE
56004         help
56005           Enable support for generating core dumps. Disabling saves about 4k.
56006  
56007 +config USER_ELF_CORE_SIZE
56008 +       int "user core dump size (10MB to 32MB)"
56009 +       range 10485760 33554432
56010 +       default 16777216
56011 +       depends on ELF_CORE
56012 +
56013  config PCSPKR_PLATFORM
56014         bool "Enable PC-Speaker support" if EMBEDDED
56015         depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
56016 --- a/kernel/module.c
56017 +++ b/kernel/module.c
56018 @@ -2688,6 +2688,9 @@ static int m_show(struct seq_file *m, vo
56019         /* Used by oprofile and other similar tools. */
56020         seq_printf(m, " 0x%p", mod->module_core);
56021  
56022 +#ifdef ARCH_PROC_MODULES_EXTRA
56023 +       ARCH_PROC_MODULES_EXTRA(m, mod);
56024 +#endif
56025         /* Taints info */
56026         if (mod->taints)
56027                 seq_printf(m, " %s", module_flags(mod, buf));
56028 @@ -2840,8 +2843,12 @@ void print_modules(void)
56029         printk("Modules linked in:");
56030         /* Most callers should already have preempt disabled, but make sure */
56031         preempt_disable();
56032 -       list_for_each_entry_rcu(mod, &modules, list)
56033 +       list_for_each_entry_rcu(mod, &modules, list) {
56034                 printk(" %s%s", mod->name, module_flags(mod, buf));
56035 +#ifdef ARCH_OOPS_MODULE_EXTRA
56036 +               ARCH_OOPS_MODULE_EXTRA(mod);
56037 +#endif
56038 +       }
56039         preempt_enable();
56040         if (last_unloaded_module[0])
56041                 printk(" [last unloaded: %s]", last_unloaded_module);
56042 --- a/kernel/sched_clock.c
56043 +++ b/kernel/sched_clock.c
56044 @@ -38,8 +38,7 @@
56045   */
56046  unsigned long long __attribute__((weak)) sched_clock(void)
56047  {
56048 -       return (unsigned long long)(jiffies - INITIAL_JIFFIES)
56049 -                                       * (NSEC_PER_SEC / HZ);
56050 +       return (get_jiffies_64() - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
56051  }
56052  
56053  static __read_mostly int sched_clock_running;
56054 --- a/lib/Kconfig.debug
56055 +++ b/lib/Kconfig.debug
56056 @@ -621,7 +621,7 @@ config FRAME_POINTER
56057         bool "Compile the kernel with frame pointers"
56058         depends on DEBUG_KERNEL && \
56059                 (CRIS || M68K || M68KNOMMU || FRV || UML || \
56060 -                AVR32 || SUPERH || BLACKFIN || MN10300) || \
56061 +                AVR32 || SUPERH || BLACKFIN || MN10300 || UBICOM32) || \
56062                 ARCH_WANT_FRAME_POINTERS
56063         default y if (DEBUG_INFO && UML) || ARCH_WANT_FRAME_POINTERS
56064         help
56065 --- a/mm/Makefile
56066 +++ b/mm/Makefile
56067 @@ -38,3 +38,5 @@ obj-$(CONFIG_SMP) += allocpercpu.o
56068  endif
56069  obj-$(CONFIG_QUICKLIST) += quicklist.o
56070  obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
56071 +
56072 +CFLAGS_slab.o := $(PROFILING) -O2
56073 --- a/mm/slab.c
56074 +++ b/mm/slab.c
56075 @@ -4100,6 +4100,68 @@ out:
56076  
56077  #ifdef CONFIG_SLABINFO
56078  
56079 +
56080 +/*
56081 + * get info on all the memory allocated by slab for this named cache
56082 + */
56083 +int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data)
56084 +{
56085 +       int res = 0;
56086 +       int found = 0;
56087 +       int node;
56088 +       struct kmem_cache *cachep;
56089 +       struct kmem_list3 *l3;
56090 +       struct slab *slabp;
56091 +
56092 +       /* Find the cache in the chain of caches. */
56093 +       mutex_lock(&cache_chain_mutex);
56094 +       list_for_each_entry(cachep, &cache_chain, next) {
56095 +               if (strcmp(cachep->name, name) == 0) {
56096 +                       found = 1;
56097 +                       break;
56098 +               }
56099 +       }
56100 +       mutex_unlock(&cache_chain_mutex);
56101 +       if (!found) {
56102 +               return 0;
56103 +       }
56104 +       for_each_online_node(node) {
56105 +               l3 = cachep->nodelists[node];
56106 +               if (!l3)
56107 +                       continue;
56108 +               if (res >= max_data)
56109 +                       break;
56110 +               check_irq_on();
56111 +               spin_lock_irq(&l3->list_lock);
56112 +
56113 +               list_for_each_entry(slabp, &l3->slabs_full, list) {
56114 +                       if (res >= max_data)
56115 +                               break;
56116 +                       data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56117 +                       data[res].order = cachep->gfporder;
56118 +                       res++;
56119 +               }
56120 +               list_for_each_entry(slabp, &l3->slabs_partial, list) {
56121 +                       if (res >= max_data)
56122 +                               break;
56123 +                       data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56124 +                       data[res].order = cachep->gfporder;
56125 +                       res++;
56126 +               }
56127 +               list_for_each_entry(slabp, &l3->slabs_free, list) {
56128 +                       if (res >= max_data)
56129 +                               break;
56130 +                       data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56131 +                       data[res].order = cachep->gfporder;
56132 +                       res++;
56133 +               }
56134 +
56135 +               spin_unlock_irq(&l3->list_lock);
56136 +       }
56137 +
56138 +       return res;
56139 +}
56140 +
56141  static void print_slabinfo_header(struct seq_file *m)
56142  {
56143         /*
56144 --- a/scripts/mod/file2alias.c
56145 +++ b/scripts/mod/file2alias.c
56146 @@ -774,6 +774,15 @@ void handle_moddevtable(struct module *m
56147                         + sym->st_value;
56148         }
56149  
56150 +       /*
56151 +        * somehow our gcc is not generating st_size correctly and set 0 for some symbols.
56152 +        * and 0 size will break do_table since it adjust size to (size - id_size)
56153 +        * this is to make sure st_size fall in range.
56154 +        */
56155 +       if (sym->st_size == 0 || sym->st_size > info->sechdrs[sym->st_shndx].sh_size) {
56156 +               sym->st_size = info->sechdrs[sym->st_shndx].sh_size;
56157 +       }
56158 +
56159         if (sym_is(symname, "__mod_pci_device_table"))
56160                 do_table(symval, sym->st_size,
56161                          sizeof(struct pci_device_id), "pci",
56162 --- a/sound/Kconfig
56163 +++ b/sound/Kconfig
56164 @@ -82,6 +82,8 @@ source "sound/parisc/Kconfig"
56165  
56166  source "sound/soc/Kconfig"
56167  
56168 +source "sound/ubicom32/Kconfig"
56169 +
56170  endif # SND
56171  
56172  menuconfig SOUND_PRIME
56173 --- a/sound/Makefile
56174 +++ b/sound/Makefile
56175 @@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmw
56176  obj-$(CONFIG_SOUND_PRIME) += oss/
56177  obj-$(CONFIG_DMASOUND) += oss/
56178  obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
56179 -       sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
56180 +       sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ ubicom32/
56181  obj-$(CONFIG_SND_AOA) += aoa/
56182  
56183  # This one must be compilable even if sound is configured out
56184 --- /dev/null
56185 +++ b/sound/ubicom32/Kconfig
56186 @@ -0,0 +1,42 @@
56187 +# ALSA Ubicom32 drivers
56188 +
56189 +menuconfig SND_UBI32
56190 +       tristate "Ubicom32 sound devices"
56191 +       select SND_PCM
56192 +       default n
56193 +       help
56194 +         Say Y here to include support for audio on the Ubicom32 platform.
56195 +         To compile this driver as a module, say M here: the module will be
56196 +         called snd_ubi32.
56197 +
56198 +if SND_UBI32
56199 +
56200 +config SND_UBI32_AUDIO_GENERIC_CAPTURE
56201 +       bool "Generic Capture Support"
56202 +       default n
56203 +       help
56204 +         Use this option to support ADCs which don't require special drivers.
56205 +
56206 +config SND_UBI32_AUDIO_GENERIC
56207 +       bool "Generic Playback Support"
56208 +       default n
56209 +       help
56210 +         Use this option to support DACs which don't require special drivers.
56211 +
56212 +comment "I2C Based Codecs"
56213 +
56214 +config SND_UBI32_AUDIO_CS4350
56215 +       bool "Cirrus Logic CS4350 DAC"
56216 +       depends on I2C
56217 +       default n
56218 +       help
56219 +         Support for the Cirrus Logic CS4350 DAC.
56220 +
56221 +config SND_UBI32_AUDIO_CS4384
56222 +       bool "Cirrus Logic CS4384 DAC"
56223 +       depends on I2C
56224 +       default n
56225 +       help
56226 +         Support for the Cirrus Logic CS4384 DAC.
56227 +
56228 +endif #SND_UBI32
56229 --- /dev/null
56230 +++ b/sound/ubicom32/Makefile
56231 @@ -0,0 +1,41 @@
56232 +#
56233 +# sound/ubicom32/Makefile
56234 +#      Makefile for ALSA
56235 +#
56236 +# (C) Copyright 2009, Ubicom, Inc.
56237 +#
56238 +# This file is part of the Ubicom32 Linux Kernel Port.
56239 +#
56240 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
56241 +# it and/or modify it under the terms of the GNU General Public License
56242 +# as published by the Free Software Foundation, either version 2 of the
56243 +# License, or (at your option) any later version.
56244 +#
56245 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
56246 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
56247 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
56248 +# the GNU General Public License for more details.
56249 +#
56250 +# You should have received a copy of the GNU General Public License
56251 +# along with the Ubicom32 Linux Kernel Port.  If not,
56252 +# see <http://www.gnu.org/licenses/>.
56253 +#
56254 +# Ubicom32 implementation derived from (with many thanks):
56255 +#   arch/m68knommu
56256 +#   arch/blackfin
56257 +#   arch/parisc
56258 +#
56259 +
56260 +CFLAGS_ubi32.o += -O2
56261 +snd-ubi32-pcm-objs := ubi32-pcm.o
56262 +snd-ubi32-generic-objs := ubi32-generic.o
56263 +snd-ubi32-generic-capture-objs := ubi32-generic-capture.o
56264 +snd-ubi32-cs4350-objs := ubi32-cs4350.o
56265 +snd-ubi32-cs4384-objs := ubi32-cs4384.o
56266 +
56267 +# Toplevel Module Dependency
56268 +obj-$(CONFIG_SND_UBI32) += snd-ubi32-pcm.o
56269 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC) += snd-ubi32-generic.o
56270 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC_CAPTURE) += snd-ubi32-generic-capture.o
56271 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4350) += snd-ubi32-cs4350.o
56272 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4384) += snd-ubi32-cs4384.o
56273 --- /dev/null
56274 +++ b/sound/ubicom32/ubi32-cs4350.c
56275 @@ -0,0 +1,583 @@
56276 +/*
56277 + * sound/ubicom32/ubi32-cs4350.c
56278 + *     Interface to ubicom32 virtual audio peripheral - using CS4350 DAC
56279 + *
56280 + * (C) Copyright 2009, Ubicom, Inc.
56281 + *
56282 + * This file is part of the Ubicom32 Linux Kernel Port.
56283 + *
56284 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
56285 + * it and/or modify it under the terms of the GNU General Public License
56286 + * as published by the Free Software Foundation, either version 2 of the
56287 + * License, or (at your option) any later version.
56288 + *
56289 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
56290 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
56291 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
56292 + * the GNU General Public License for more details.
56293 + *
56294 + * You should have received a copy of the GNU General Public License
56295 + * along with the Ubicom32 Linux Kernel Port.  If not,
56296 + * see <http://www.gnu.org/licenses/>.
56297 + */
56298 +
56299 +#include <linux/i2c.h>
56300 +#include <linux/module.h>
56301 +#include <linux/moduleparam.h>
56302 +#include <sound/core.h>
56303 +#include <sound/tlv.h>
56304 +#include <sound/control.h>
56305 +#include <sound/pcm.h>
56306 +#include <sound/initval.h>
56307 +#include "ubi32.h"
56308 +
56309 +#define DRIVER_NAME "snd-ubi32-cs4350"
56310 +
56311 +/*
56312 + * Module properties
56313 + */
56314 +static const struct i2c_device_id snd_ubi32_cs4350_id[] = {
56315 +       {"cs4350", 0 },
56316 +       { }
56317 +};
56318 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
56319 +
56320 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
56321 +
56322 +/*
56323 + * The dB scale for the Cirrus Logic cs4350.  The output range is from
56324 + * -127.5 dB to 0 dB.
56325 + */
56326 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4350_db, -12750, 50, 0);
56327 +
56328 +#define ubi32_cs4350_mute_info snd_ctl_boolean_stereo_info
56329 +
56330 +/*
56331 + * Private data for cs4350 chip
56332 + */
56333 +struct ubi32_cs4350_priv {
56334 +       /*
56335 +        * The current volume settings
56336 +        */
56337 +       uint8_t volume[2];
56338 +
56339 +       /*
56340 +        * Bitmask of mutes MSB (unused, ..., unused, right_ch, left_ch) LSB
56341 +        */
56342 +       uint8_t mute;
56343 +
56344 +       /*
56345 +        * Lock to protect this struct because callbacks are not atomic.
56346 +        */
56347 +       spinlock_t lock;
56348 +};
56349 +
56350 +/*
56351 + * The info for the cs4350.  The volume currently has one channel,
56352 + * and 255 possible settings.
56353 + */
56354 +static int ubi32_cs4350_volume_info(struct snd_kcontrol *kcontrol,
56355 +                                   struct snd_ctl_elem_info *uinfo)
56356 +{
56357 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
56358 +       uinfo->count = 2;
56359 +       uinfo->value.integer.min = 0;
56360 +       uinfo->value.integer.max = 255; // 8 bits in cirrus logic cs4350 volume register
56361 +       return 0;
56362 +}
56363 +
56364 +static int ubi32_cs4350_volume_get(struct snd_kcontrol *kcontrol,
56365 +                                  struct snd_ctl_elem_value *ucontrol)
56366 +{
56367 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56368 +       struct ubi32_cs4350_priv *cs4350_priv;
56369 +       unsigned long flags;
56370 +
56371 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56372 +
56373 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56374 +
56375 +       ucontrol->value.integer.value[0] = cs4350_priv->volume[0];
56376 +       ucontrol->value.integer.value[1] = cs4350_priv->volume[1];
56377 +
56378 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56379 +
56380 +       return 0;
56381 +}
56382 +
56383 +static int ubi32_cs4350_volume_put(struct snd_kcontrol *kcontrol,
56384 +                                  struct snd_ctl_elem_value *ucontrol)
56385 +{
56386 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56387 +       struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56388 +       struct ubi32_cs4350_priv *cs4350_priv;
56389 +       unsigned long flags;
56390 +       int ret, changed;
56391 +       char send[2];
56392 +       uint8_t volume_reg_value_left, volume_reg_value_right;
56393 +
56394 +       changed = 0;
56395 +
56396 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56397 +       volume_reg_value_left = 255 - (ucontrol->value.integer.value[0] & 0xFF);
56398 +       volume_reg_value_right = 255 - (ucontrol->value.integer.value[1] & 0xFF);
56399 +
56400 +#if SND_UBI32_DEBUG
56401 +       snd_printk(KERN_INFO "Setting volume: writing %d,%d to CS4350 volume registers\n", volume_reg_value_left, volume_reg_value_right);
56402 +#endif
56403 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56404 +
56405 +       if (cs4350_priv->volume[0] != ucontrol->value.integer.value[0]) {
56406 +               send[0] = 0x05; // left channel
56407 +               send[1] = volume_reg_value_left;
56408 +               ret = i2c_master_send(client, send, 2);
56409 +               if (ret != 2) {
56410 +                       snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56411 +                       return changed;
56412 +               }
56413 +               cs4350_priv->volume[0] = ucontrol->value.integer.value[0];
56414 +               changed = 1;
56415 +       }
56416 +
56417 +       if (cs4350_priv->volume[1] != ucontrol->value.integer.value[1]) {
56418 +               send[0] = 0x06; // right channel
56419 +               send[1] = volume_reg_value_right;
56420 +               ret = i2c_master_send(client, send, 2);
56421 +               if (ret != 2) {
56422 +                       snd_printk(KERN_ERR "Failed to set channel B volume on CS4350\n");
56423 +                       return changed;
56424 +               }
56425 +               cs4350_priv->volume[1] = ucontrol->value.integer.value[1];
56426 +               changed = 1;
56427 +       }
56428 +
56429 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56430 +
56431 +       return changed;
56432 +}
56433 +
56434 +static struct snd_kcontrol_new ubi32_cs4350_volume __devinitdata = {
56435 +       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56436 +       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56437 +                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56438 +       .name = "PCM Playback Volume",
56439 +       .info = ubi32_cs4350_volume_info,
56440 +       .get = ubi32_cs4350_volume_get,
56441 +       .put = ubi32_cs4350_volume_put,
56442 +       .tlv.p = snd_ubi32_cs4350_db,
56443 +};
56444 +
56445 +static int ubi32_cs4350_mute_get(struct snd_kcontrol *kcontrol,
56446 +                                struct snd_ctl_elem_value *ucontrol)
56447 +{
56448 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56449 +       struct ubi32_cs4350_priv *cs4350_priv;
56450 +       unsigned long flags;
56451 +
56452 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56453 +
56454 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56455 +
56456 +       ucontrol->value.integer.value[0] = cs4350_priv->mute & 1;
56457 +       ucontrol->value.integer.value[1] = (cs4350_priv->mute & (1 << 1)) ? 1 : 0;
56458 +
56459 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56460 +
56461 +       return 0;
56462 +}
56463 +
56464 +static int ubi32_cs4350_mute_put(struct snd_kcontrol *kcontrol,
56465 +                                struct snd_ctl_elem_value *ucontrol)
56466 +{
56467 +       struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56468 +       struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56469 +       struct ubi32_cs4350_priv *cs4350_priv;
56470 +       unsigned long flags;
56471 +       int ret, changed;
56472 +       char send[2];
56473 +       char recv[1];
56474 +       uint8_t mute;
56475 +
56476 +        changed = 0;
56477 +
56478 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56479 +
56480 +       spin_lock_irqsave(&cs4350_priv->lock, flags);
56481 +
56482 +       if ((cs4350_priv->mute & 1) != ucontrol->value.integer.value[0]) {
56483 +               send[0] = 0x04;
56484 +               ret = i2c_master_send(client, send, 1);
56485 +               if (ret != 1) {
56486 +                       snd_printk(KERN_ERR "Failed to write to mute register: channel 0\n");
56487 +                       return changed;
56488 +               }
56489 +
56490 +               ret = i2c_master_recv(client, recv, 1);
56491 +               if (ret != 1) {
56492 +                       snd_printk(KERN_ERR "Failed to read mute register: channel 0\n");
56493 +                       return changed;
56494 +               }
56495 +
56496 +               mute = recv[0];
56497 +
56498 +               if (ucontrol->value.integer.value[0]) {
56499 +                       cs4350_priv->mute |= 1;
56500 +                       mute &= ~(1 << 4);
56501 +#if SND_UBI32_DEBUG
56502 +                       snd_printk(KERN_INFO "Unmuted channel A\n");
56503 +#endif
56504 +               } else {
56505 +                       cs4350_priv->mute &= ~1;
56506 +                       mute |= (1 << 4);
56507 +#if SND_UBI32_DEBUG
56508 +                       snd_printk(KERN_INFO "Muted channel A\n");
56509 +#endif
56510 +               }
56511 +
56512 +               send[0] = 0x04;
56513 +               send[1] = mute;
56514 +               ret = i2c_master_send(client, send, 2);
56515 +               if (ret != 2) {
56516 +                       snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56517 +                       return changed;
56518 +               }
56519 +               changed = 1;
56520 +       }
56521 +
56522 +       if (((cs4350_priv->mute & 2) >> 1) != ucontrol->value.integer.value[1]) {
56523 +               send[0] = 0x04;
56524 +               ret = i2c_master_send(client, send, 1);
56525 +               if (ret != 1) {
56526 +                       snd_printk(KERN_ERR "Failed to write to mute register: channel 1\n");
56527 +                       return changed;
56528 +               }
56529 +
56530 +               ret = i2c_master_recv(client, recv, 1);
56531 +               if (ret != 1) {
56532 +                       snd_printk(KERN_ERR "Failed to read mute register: channel 1\n");
56533 +                       return changed;
56534 +               }
56535 +
56536 +               mute = recv[0];
56537 +
56538 +               if (ucontrol->value.integer.value[1]) {
56539 +                       cs4350_priv->mute |= (1 << 1);
56540 +                       mute &= ~(1 << 3);
56541 +#if SND_UBI32_DEBUG
56542 +                       snd_printk(KERN_INFO "Unmuted channel B\n");
56543 +#endif
56544 +               } else {
56545 +                       cs4350_priv->mute &= ~(1 << 1);
56546 +                       mute |= (1 << 3);
56547 +#if SND_UBI32_DEBUG
56548 +                       snd_printk(KERN_INFO "Muted channel B\n");
56549 +#endif
56550 +               }
56551 +
56552 +               send[0] = 0x04;
56553 +               send[1] = mute;
56554 +               ret = i2c_master_send(client, send, 2);
56555 +               if (ret != 2) {
56556 +                       snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56557 +                       return changed;
56558 +               }
56559 +               changed = 1;
56560 +       }
56561 +
56562 +       spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56563 +
56564 +       return changed;
56565 +}
56566 +
56567 +static struct snd_kcontrol_new ubi32_cs4350_mute __devinitdata = {
56568 +       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56569 +       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
56570 +       .name = "PCM Playback Switch",
56571 +       .info = ubi32_cs4350_mute_info,
56572 +       .get = ubi32_cs4350_mute_get,
56573 +       .put = ubi32_cs4350_mute_put,
56574 +};
56575 +
56576 +/*
56577 + * snd_ubi32_cs4350_free
56578 + *     Card private data free function
56579 + */
56580 +void snd_ubi32_cs4350_free(struct snd_card *card)
56581 +{
56582 +       struct ubi32_snd_priv *ubi32_priv;
56583 +       struct ubi32_cs4350_priv *cs4350_priv;
56584 +
56585 +       ubi32_priv = card->private_data;
56586 +       cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56587 +       if (cs4350_priv) {
56588 +               kfree(cs4350_priv);
56589 +       }
56590 +}
56591 +
56592 +/*
56593 + * snd_ubi32_cs4350_dac_init
56594 + */
56595 +static int snd_ubi32_cs4350_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
56596 +{
56597 +       int ret;
56598 +       char send[2];
56599 +       char recv[8];
56600 +
56601 +       /*
56602 +        * Initialize the CS4350 DAC over the I2C interface
56603 +        */
56604 +       snd_printk(KERN_INFO "Initializing CS4350 DAC\n");
56605 +
56606 +       /*
56607 +        * Register 0x01: device/revid
56608 +        */
56609 +       send[0] = 0x01;
56610 +       ret = i2c_master_send(client, send, 1);
56611 +       if (ret != 1) {
56612 +               snd_printk(KERN_ERR "Failed 1st attempt to write to CS4350 register 0x01\n");
56613 +               goto fail;
56614 +       }
56615 +       ret = i2c_master_recv(client, recv, 1);
56616 +       if (ret != 1) {
56617 +               snd_printk(KERN_ERR "Failed initial read of CS4350 registers\n");
56618 +               goto fail;
56619 +       }
56620 +       snd_printk(KERN_INFO "CS4350 DAC Device/Rev: %08x\n", recv[0]);
56621 +
56622 +       /*
56623 +        * Register 0x02: Mode control
56624 +        *      I2S DIF[2:0] = 001, no De-Emphasis, Auto speed mode
56625 +        */
56626 +       send[0] = 0x02;
56627 +       send[1] = 0x10;
56628 +       ret = i2c_master_send(client, send, 2);
56629 +       if (ret != 2) {
56630 +               snd_printk(KERN_ERR "Failed to set CS4350 to I2S mode\n");
56631 +               goto fail;
56632 +       }
56633 +
56634 +       /*
56635 +        * Register 0x05/0x06: Volume control
56636 +        *      Channel A volume set to 0 dB
56637 +        *      Channel B volume set to 0 dB
56638 +        */
56639 +       send[0] = 0x05;
56640 +       send[1] = 0x00;
56641 +       ret = i2c_master_send(client, send, 2);
56642 +       if (ret != 2) {
56643 +               snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56644 +               goto fail;
56645 +       }
56646 +
56647 +       send[0] = 0x06;
56648 +       send[1] = 0x00;
56649 +       ret = i2c_master_send(client, send, 2);
56650 +       if (ret != 2) {
56651 +               snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56652 +               goto fail;
56653 +       }
56654 +
56655 +       /*
56656 +        * Make sure the changes took place, this helps verify we are talking to
56657 +        * the correct chip.
56658 +        */
56659 +       send[0] = 0x81;
56660 +       ret = i2c_master_send(client, send, 1);
56661 +       if (ret != 1) {
56662 +               snd_printk(KERN_ERR "Failed to initiate readback\n");
56663 +               goto fail;
56664 +       }
56665 +
56666 +       ret = i2c_master_recv(client, recv, 8);
56667 +       if (ret != 8) {
56668 +               snd_printk(KERN_ERR "Failed second read of CS4350 registers\n");
56669 +               goto fail;
56670 +       }
56671 +
56672 +       if ((recv[1] != 0x10) || (recv[4] != 0x00) || (recv[5] != 0x00)) {
56673 +               snd_printk(KERN_ERR "Failed to initialize CS4350 DAC\n");
56674 +               goto fail;
56675 +       }
56676 +
56677 +       snd_printk(KERN_INFO "CS4350 DAC Initialized\n");
56678 +       return 0;
56679 +
56680 +fail:
56681 +       return -ENODEV;
56682 +}
56683 +
56684 +/*
56685 + * snd_ubi32_cs4350_i2c_probe
56686 + */
56687 +static int snd_ubi32_cs4350_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
56688 +{
56689 +       struct snd_card *card;
56690 +       struct ubi32_snd_priv *ubi32_priv;
56691 +       struct ubi32_cs4350_priv *cs4350_priv;
56692 +       int err, ret;
56693 +       struct platform_device *pdev;
56694 +
56695 +       pdev = client->dev.platform_data;
56696 +       if (!pdev) {
56697 +               return -ENODEV;
56698 +       }
56699 +
56700 +       /*
56701 +        * Initialize the CS4350 DAC
56702 +        */
56703 +       ret = snd_ubi32_cs4350_dac_init(client, id);
56704 +       if (ret < 0) {
56705 +               /*
56706 +                * Initialization failed.  Propagate the error.
56707 +                */
56708 +               return ret;
56709 +       }
56710 +
56711 +       /*
56712 +        * Create a snd_card structure
56713 +        */
56714 +       card = snd_card_new(index, "Ubi32-CS4350", THIS_MODULE, sizeof(struct ubi32_snd_priv));
56715 +       if (card == NULL) {
56716 +               return -ENOMEM;
56717 +       }
56718 +
56719 +       card->private_free = snd_ubi32_cs4350_free; /* Not sure if correct */
56720 +       ubi32_priv = card->private_data;
56721 +
56722 +       /*
56723 +        * CS4350 DAC has a minimum sample rate of 30khz and an
56724 +        * upper limit of 216khz for it's auto-detect.
56725 +        */
56726 +       ubi32_priv->min_sample_rate = 30000;
56727 +       ubi32_priv->max_sample_rate = 216000;
56728 +
56729 +       /*
56730 +        * Initialize the snd_card's private data structure
56731 +        */
56732 +       ubi32_priv->card = card;
56733 +       ubi32_priv->client = client;
56734 +
56735 +       /*
56736 +        * Create our private data structure
56737 +        */
56738 +       cs4350_priv = kzalloc(sizeof(struct ubi32_cs4350_priv), GFP_KERNEL);
56739 +       if (!cs4350_priv) {
56740 +               snd_card_free(card);
56741 +               return -ENOMEM;
56742 +       }
56743 +       snd_ubi32_priv_set_drv(ubi32_priv, cs4350_priv);
56744 +       spin_lock_init(&cs4350_priv->lock);
56745 +
56746 +       /*
56747 +        * Initial volume is set to max by probe function
56748 +        */
56749 +       cs4350_priv->volume[0] = 0xFF;
56750 +       cs4350_priv->volume[1] = 0xFF;
56751 +
56752 +       /*
56753 +        * The CS4350 starts off unmuted (bit set = not muted)
56754 +        */
56755 +       cs4350_priv->mute = 3;
56756 +
56757 +       /*
56758 +        * Create the new PCM instance
56759 +        */
56760 +       err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
56761 +       if (err < 0) {
56762 +               snd_card_free(card);
56763 +               return err; /* What is err?  Need to include correct file */
56764 +       }
56765 +
56766 +       strcpy(card->driver, "Ubi32-CS4350");
56767 +       strcpy(card->shortname, "Ubi32-CS4350");
56768 +       snprintf(card->longname, sizeof(card->longname),
56769 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
56770 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
56771 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
56772 +
56773 +       snd_card_set_dev(card, &client->dev);
56774 +
56775 +       /*
56776 +        * Set up the mixer components
56777 +        */
56778 +       err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_volume, ubi32_priv));
56779 +       if (err) {
56780 +               snd_printk(KERN_WARNING "Failed to add volume mixer control\n");
56781 +       }
56782 +       err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_mute, ubi32_priv));
56783 +       if (err) {
56784 +               snd_printk(KERN_WARNING "Failed to add mute mixer control\n");
56785 +       }
56786 +
56787 +       /*
56788 +        * Register the sound card
56789 +        */
56790 +       if ((err = snd_card_register(card)) != 0) {
56791 +               snd_printk(KERN_WARNING "snd_card_register error\n");
56792 +       }
56793 +
56794 +       /*
56795 +        * Store card for access from other methods
56796 +        */
56797 +       i2c_set_clientdata(client, card);
56798 +
56799 +       return 0;
56800 +}
56801 +
56802 +/*
56803 + * snd_ubi32_cs4350_i2c_remove
56804 + */
56805 +static int __devexit snd_ubi32_cs4350_i2c_remove(struct i2c_client *client)
56806 +{
56807 +       struct snd_card *card;
56808 +       struct ubi32_snd_priv *ubi32_priv;
56809 +
56810 +       card = i2c_get_clientdata(client);
56811 +
56812 +       ubi32_priv = card->private_data;
56813 +       snd_ubi32_pcm_remove(ubi32_priv);
56814 +
56815 +       snd_card_free(i2c_get_clientdata(client));
56816 +       i2c_set_clientdata(client, NULL);
56817 +
56818 +       return 0;
56819 +}
56820 +
56821 +/*
56822 + * I2C driver description
56823 + */
56824 +static struct i2c_driver snd_ubi32_cs4350_driver = {
56825 +       .driver = {
56826 +               .name = DRIVER_NAME,
56827 +               .owner = THIS_MODULE,
56828 +       },
56829 +       .id_table       = snd_ubi32_cs4350_id,
56830 +       .probe          = snd_ubi32_cs4350_i2c_probe,
56831 +       .remove         = __devexit_p(snd_ubi32_cs4350_i2c_remove),
56832 +};
56833 +
56834 +/*
56835 + * Driver init
56836 + */
56837 +static int __init snd_ubi32_cs4350_init(void)
56838 +{
56839 +       return i2c_add_driver(&snd_ubi32_cs4350_driver);
56840 +}
56841 +module_init(snd_ubi32_cs4350_init);
56842 +
56843 +/*
56844 + * snd_ubi32_cs4350_exit
56845 + */
56846 +static void __exit snd_ubi32_cs4350_exit(void)
56847 +{
56848 +       i2c_del_driver(&snd_ubi32_cs4350_driver);
56849 +}
56850 +module_exit(snd_ubi32_cs4350_exit);
56851 +
56852 +/*
56853 + * Module properties
56854 + */
56855 +MODULE_ALIAS("i2c:" DRIVER_NAME);
56856 +MODULE_AUTHOR("Patrick Tjin");
56857 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4350");
56858 +MODULE_LICENSE("GPL");
56859 --- /dev/null
56860 +++ b/sound/ubicom32/ubi32-cs4384.c
56861 @@ -0,0 +1,996 @@
56862 +/*
56863 + * sound/ubicom32/ubi32-cs4384.c
56864 + *     Interface to ubicom32 virtual audio peripheral - using CS4384 DAC
56865 + *
56866 + * (C) Copyright 2009, Ubicom, Inc.
56867 + *
56868 + * This file is part of the Ubicom32 Linux Kernel Port.
56869 + *
56870 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
56871 + * it and/or modify it under the terms of the GNU General Public License
56872 + * as published by the Free Software Foundation, either version 2 of the
56873 + * License, or (at your option) any later version.
56874 + *
56875 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
56876 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
56877 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
56878 + * the GNU General Public License for more details.
56879 + *
56880 + * You should have received a copy of the GNU General Public License
56881 + * along with the Ubicom32 Linux Kernel Port.  If not,
56882 + * see <http://www.gnu.org/licenses/>.
56883 + */
56884 +
56885 +#include <linux/i2c.h>
56886 +#include <linux/module.h>
56887 +#include <linux/moduleparam.h>
56888 +#include <linux/delay.h>
56889 +#include <sound/core.h>
56890 +#include <sound/tlv.h>
56891 +#include <sound/control.h>
56892 +#include <sound/pcm.h>
56893 +#include <sound/initval.h>
56894 +#include <asm/ip5000.h>
56895 +#include <asm/gpio.h>
56896 +#include <asm/audio.h>
56897 +#include <asm/ubi32-cs4384.h>
56898 +#include "ubi32.h"
56899 +
56900 +#define DRIVER_NAME "snd-ubi32-cs4384"
56901 +
56902 +/*
56903 + * Module properties
56904 + */
56905 +static const struct i2c_device_id snd_ubi32_cs4384_id[] = {
56906 +       {"cs4384", 0 },
56907 +       { }
56908 +};
56909 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
56910 +
56911 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
56912 +
56913 +/*
56914 + * Mixer properties
56915 + */
56916 +enum {
56917 +       /*
56918 +        * Be careful of changing the order of these IDs, they
56919 +        * are used to index the volume array.
56920 +        */
56921 +       SND_UBI32_CS4384_FRONT_ID,
56922 +       SND_UBI32_CS4384_SURROUND_ID,
56923 +       SND_UBI32_CS4384_CENTER_ID,
56924 +       SND_UBI32_CS4384_LFE_ID,
56925 +       SND_UBI32_CS4384_REAR_ID,
56926 +
56927 +       /*
56928 +        * This should be the last ID
56929 +        */
56930 +       SND_UBI32_CS4384_LAST_ID,
56931 +};
56932 +static const u8_t snd_ubi32_cs4384_ch_ofs[] = {0, 2, 4, 5, 6};
56933 +
56934 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4384_db, -12750, 50, 0);
56935 +
56936 +#define snd_ubi32_cs4384_info_mute     snd_ctl_boolean_stereo_info
56937 +#define snd_ubi32_cs4384_info_mute_mono        snd_ctl_boolean_mono_info
56938 +
56939 +/*
56940 + * Mixer controls
56941 + */
56942 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
56943 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56944 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56945 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56946 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56947 +
56948 +/*
56949 + * Make sure to update these if the structure below is changed
56950 + */
56951 +#define SND_UBI32_MUTE_CTL_START       5
56952 +#define SND_UBI32_MUTE_CTL_END         9
56953 +static struct snd_kcontrol_new snd_ubi32_cs4384_controls[] __devinitdata = {
56954 +       {
56955 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56956 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56957 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56958 +               .name = "Front Playback Volume",
56959 +               .info = snd_ubi32_cs4384_info_volume,
56960 +               .get = snd_ubi32_cs4384_get_volume,
56961 +               .put = snd_ubi32_cs4384_put_volume,
56962 +               .private_value = SND_UBI32_CS4384_FRONT_ID,
56963 +               .tlv = {
56964 +                       .p = snd_ubi32_cs4384_db,
56965 +               },
56966 +       },
56967 +       {
56968 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56969 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56970 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56971 +               .name = "Surround Playback Volume",
56972 +               .info = snd_ubi32_cs4384_info_volume,
56973 +               .get = snd_ubi32_cs4384_get_volume,
56974 +               .put = snd_ubi32_cs4384_put_volume,
56975 +               .private_value = SND_UBI32_CS4384_SURROUND_ID,
56976 +               .tlv = {
56977 +                       .p = snd_ubi32_cs4384_db,
56978 +               },
56979 +       },
56980 +       {
56981 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56982 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56983 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56984 +               .name = "Center Playback Volume",
56985 +               .info = snd_ubi32_cs4384_info_volume,
56986 +               .get = snd_ubi32_cs4384_get_volume,
56987 +               .put = snd_ubi32_cs4384_put_volume,
56988 +               .private_value = SND_UBI32_CS4384_CENTER_ID,
56989 +               .tlv = {
56990 +                       .p = snd_ubi32_cs4384_db,
56991 +               },
56992 +       },
56993 +       {
56994 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56995 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56996 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56997 +               .name = "LFE Playback Volume",
56998 +               .info = snd_ubi32_cs4384_info_volume,
56999 +               .get = snd_ubi32_cs4384_get_volume,
57000 +               .put = snd_ubi32_cs4384_put_volume,
57001 +               .private_value = SND_UBI32_CS4384_LFE_ID,
57002 +               .tlv = {
57003 +                       .p = snd_ubi32_cs4384_db,
57004 +               },
57005 +       },
57006 +       {
57007 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57008 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57009 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57010 +               .name = "Rear Playback Volume",
57011 +               .info = snd_ubi32_cs4384_info_volume,
57012 +               .get = snd_ubi32_cs4384_get_volume,
57013 +               .put = snd_ubi32_cs4384_put_volume,
57014 +               .private_value = SND_UBI32_CS4384_REAR_ID,
57015 +               .tlv = {
57016 +                       .p = snd_ubi32_cs4384_db,
57017 +               },
57018 +       },
57019 +       {
57020 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57021 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57022 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57023 +               .name = "Front Playback Switch",
57024 +               .info = snd_ubi32_cs4384_info_mute,
57025 +               .get = snd_ubi32_cs4384_get_mute,
57026 +               .put = snd_ubi32_cs4384_put_mute,
57027 +               .private_value = SND_UBI32_CS4384_FRONT_ID,
57028 +       },
57029 +       {
57030 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57031 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57032 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57033 +               .name = "Surround Playback Switch",
57034 +               .info = snd_ubi32_cs4384_info_mute,
57035 +               .get = snd_ubi32_cs4384_get_mute,
57036 +               .put = snd_ubi32_cs4384_put_mute,
57037 +               .private_value = SND_UBI32_CS4384_SURROUND_ID,
57038 +       },
57039 +       {
57040 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57041 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57042 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57043 +               .name = "Center Playback Switch",
57044 +               .info = snd_ubi32_cs4384_info_mute_mono,
57045 +               .get = snd_ubi32_cs4384_get_mute,
57046 +               .put = snd_ubi32_cs4384_put_mute,
57047 +               .private_value = SND_UBI32_CS4384_CENTER_ID,
57048 +       },
57049 +       {
57050 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57051 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57052 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57053 +               .name = "LFE Playback Switch",
57054 +               .info = snd_ubi32_cs4384_info_mute_mono,
57055 +               .get = snd_ubi32_cs4384_get_mute,
57056 +               .put = snd_ubi32_cs4384_put_mute,
57057 +               .private_value = SND_UBI32_CS4384_LFE_ID,
57058 +       },
57059 +       {
57060 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57061 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57062 +                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57063 +               .name = "Rear Playback Switch",
57064 +               .info = snd_ubi32_cs4384_info_mute,
57065 +               .get = snd_ubi32_cs4384_get_mute,
57066 +               .put = snd_ubi32_cs4384_put_mute,
57067 +               .private_value = SND_UBI32_CS4384_REAR_ID,
57068 +       },
57069 +};
57070 +
57071 +/*
57072 + * Our private data
57073 + */
57074 +struct snd_ubi32_cs4384_priv {
57075 +       /*
57076 +        * Array of current volumes
57077 +        *      (L, R, SL, SR, C, LFE, RL, RR)
57078 +        */
57079 +       uint8_t volume[8];
57080 +
57081 +       /*
57082 +        * Bitmask of mutes
57083 +        *      MSB (RR, RL, LFE, C, SR, SL, R, L) LSB
57084 +        */
57085 +       uint8_t mute;
57086 +
57087 +       /*
57088 +        * Array of controls
57089 +        */
57090 +       struct snd_kcontrol *kctls[ARRAY_SIZE(snd_ubi32_cs4384_controls)];
57091 +
57092 +       /*
57093 +        * Lock to protect our card
57094 +        */
57095 +       spinlock_t lock;
57096 +};
57097 +
57098 +/*
57099 + * snd_ubi32_cs4384_info_volume
57100 + */
57101 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
57102 +{
57103 +       unsigned int id = (unsigned int)kcontrol->private_value;
57104 +
57105 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
57106 +       uinfo->count = 1;
57107 +       if ((id != SND_UBI32_CS4384_LFE_ID) &&
57108 +           (id != SND_UBI32_CS4384_CENTER_ID)) {
57109 +               uinfo->count = 2;
57110 +       }
57111 +       uinfo->value.integer.min = 0;
57112 +       uinfo->value.integer.max = 255;
57113 +       return 0;
57114 +}
57115 +
57116 +/*
57117 + * snd_ubi32_cs4384_get_volume
57118 + */
57119 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57120 +{
57121 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57122 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57123 +       unsigned int id = (unsigned int)kcontrol->private_value;
57124 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57125 +       unsigned long flags;
57126 +
57127 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57128 +               return -EINVAL;
57129 +       }
57130 +
57131 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57132 +
57133 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57134 +
57135 +       ucontrol->value.integer.value[0] = cs4384_priv->volume[ch];
57136 +       if ((id != SND_UBI32_CS4384_LFE_ID) &&
57137 +           (id != SND_UBI32_CS4384_CENTER_ID)) {
57138 +               ch++;
57139 +               ucontrol->value.integer.value[1] = cs4384_priv->volume[ch];
57140 +       }
57141 +
57142 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57143 +
57144 +       return 0;
57145 +}
57146 +
57147 +/*
57148 + * snd_ubi32_cs4384_put_volume
57149 + */
57150 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57151 +{
57152 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57153 +       struct i2c_client *client = (struct i2c_client *)priv->client;
57154 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57155 +       unsigned int id = (unsigned int)kcontrol->private_value;
57156 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57157 +       unsigned long flags;
57158 +       unsigned char send[3];
57159 +       int nch;
57160 +       int ret = -EINVAL;
57161 +
57162 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57163 +               return -EINVAL;
57164 +       }
57165 +
57166 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57167 +
57168 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57169 +
57170 +       send[0] = 0;
57171 +       switch (id) {
57172 +       case SND_UBI32_CS4384_REAR_ID:
57173 +               send[0] = 0x06;
57174 +
57175 +               /*
57176 +                * Fall through
57177 +                */
57178 +
57179 +       case SND_UBI32_CS4384_SURROUND_ID:
57180 +               send[0] += 0x03;
57181 +
57182 +               /*
57183 +                * Fall through
57184 +                */
57185 +
57186 +       case SND_UBI32_CS4384_FRONT_ID:
57187 +               send[0] += 0x8B;
57188 +               nch = 2;
57189 +               send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57190 +               send[2] = 255 - (ucontrol->value.integer.value[1] & 0xFF);
57191 +               cs4384_priv->volume[ch++] = send[1];
57192 +               cs4384_priv->volume[ch] = send[2];
57193 +               break;
57194 +
57195 +       case SND_UBI32_CS4384_LFE_ID:
57196 +               send[0] = 0x81;
57197 +
57198 +               /*
57199 +                * Fall through
57200 +                */
57201 +
57202 +       case SND_UBI32_CS4384_CENTER_ID:
57203 +               send[0] += 0x11;
57204 +               nch = 1;
57205 +               send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57206 +               cs4384_priv->volume[ch] = send[1];
57207 +               break;
57208 +
57209 +       default:
57210 +               spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57211 +               goto done;
57212 +
57213 +       }
57214 +
57215 +       /*
57216 +        * Send the volume to the chip
57217 +        */
57218 +       nch++;
57219 +       ret = i2c_master_send(client, send, nch);
57220 +       if (ret != nch) {
57221 +               snd_printk(KERN_ERR "Failed to set volume on CS4384\n");
57222 +       }
57223 +
57224 +done:
57225 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57226 +
57227 +       return ret;
57228 +}
57229 +
57230 +/*
57231 + * snd_ubi32_cs4384_get_mute
57232 + */
57233 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57234 +{
57235 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57236 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57237 +       unsigned int id = (unsigned int)kcontrol->private_value;
57238 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57239 +       unsigned long flags;
57240 +
57241 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57242 +               return -EINVAL;
57243 +       }
57244 +
57245 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57246 +
57247 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57248 +
57249 +       ucontrol->value.integer.value[0] = !(cs4384_priv->mute & (1 << ch));
57250 +
57251 +       if ((id != SND_UBI32_CS4384_LFE_ID) &&
57252 +           (id != SND_UBI32_CS4384_CENTER_ID)) {
57253 +               ch++;
57254 +               ucontrol->value.integer.value[1] = !(cs4384_priv->mute & (1 << ch));
57255 +       }
57256 +
57257 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57258 +
57259 +       return 0;
57260 +}
57261 +
57262 +/*
57263 + * snd_ubi32_cs4384_put_mute
57264 + */
57265 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57266 +{
57267 +       struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57268 +       struct i2c_client *client = (struct i2c_client *)priv->client;
57269 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57270 +       unsigned int id = (unsigned int)kcontrol->private_value;
57271 +       int ch = snd_ubi32_cs4384_ch_ofs[id];
57272 +       unsigned long flags;
57273 +       unsigned char send[2];
57274 +       int ret = -EINVAL;
57275 +
57276 +       if (id >= SND_UBI32_CS4384_LAST_ID) {
57277 +               return -EINVAL;
57278 +       }
57279 +
57280 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57281 +
57282 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57283 +
57284 +       if (ucontrol->value.integer.value[0]) {
57285 +               cs4384_priv->mute &= ~(1 << ch);
57286 +       } else {
57287 +               cs4384_priv->mute |= (1 << ch);
57288 +       }
57289 +
57290 +       if ((id != SND_UBI32_CS4384_LFE_ID) && (id != SND_UBI32_CS4384_CENTER_ID)) {
57291 +               ch++;
57292 +               if (ucontrol->value.integer.value[1]) {
57293 +                       cs4384_priv->mute &= ~(1 << ch);
57294 +               } else {
57295 +                       cs4384_priv->mute |= (1 << ch);
57296 +               }
57297 +       }
57298 +
57299 +       /*
57300 +        * Update the chip's mute reigster
57301 +        */
57302 +       send[0] = 0x09;
57303 +       send[1] = cs4384_priv->mute;
57304 +       ret = i2c_master_send(client, send, 2);
57305 +       if (ret != 2) {
57306 +               snd_printk(KERN_ERR "Failed to set mute on CS4384\n");
57307 +       }
57308 +
57309 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57310 +
57311 +       return ret;
57312 +}
57313 +
57314 +/*
57315 + * snd_ubi32_cs4384_mixer
57316 + *     Setup the mixer controls
57317 + */
57318 +static int __devinit snd_ubi32_cs4384_mixer(struct ubi32_snd_priv *priv)
57319 +{
57320 +       struct snd_card *card = priv->card;
57321 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57322 +       int i;
57323 +
57324 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57325 +       for (i = 0; i < ARRAY_SIZE(snd_ubi32_cs4384_controls); i++) {
57326 +               int err;
57327 +
57328 +               cs4384_priv->kctls[i] = snd_ctl_new1(&snd_ubi32_cs4384_controls[i], priv);
57329 +               err = snd_ctl_add(card, cs4384_priv->kctls[i]);
57330 +               if (err) {
57331 +                       snd_printk(KERN_WARNING "Failed to add control %d\n", i);
57332 +                       return err;
57333 +               }
57334 +       }
57335 +       return 0;
57336 +}
57337 +
57338 +/*
57339 + * snd_ubi32_cs4384_free
57340 + *     Card private data free function
57341 + */
57342 +void snd_ubi32_cs4384_free(struct snd_card *card)
57343 +{
57344 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57345 +       struct ubi32_snd_priv *ubi32_priv;
57346 +
57347 +       ubi32_priv = card->private_data;
57348 +       cs4384_priv = snd_ubi32_priv_get_drv(ubi32_priv);
57349 +       if (cs4384_priv) {
57350 +               kfree(cs4384_priv);
57351 +       }
57352 +}
57353 +
57354 +/*
57355 + * snd_ubi32_cs4384_setup_mclk
57356 + */
57357 +static int snd_ubi32_cs4384_setup_mclk(struct ubi32_cs4384_platform_data *pdata)
57358 +{
57359 +       struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57360 +       struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57361 +       struct ubicom32_io_port *iod = (struct ubicom32_io_port *)RD;
57362 +       struct ubicom32_io_port *ioe = (struct ubicom32_io_port *)RE;
57363 +       struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57364 +       unsigned int ctl0;
57365 +       unsigned int ctlx;
57366 +       unsigned int div;
57367 +
57368 +       div = pdata->mclk_entries[0].div;
57369 +
57370 +       ctl0 = (1 << 13);
57371 +       ctlx = ((div - 1) << 16) | (div / 2);
57372 +
57373 +       switch (pdata->mclk_src) {
57374 +       case UBI32_CS4384_MCLK_PWM_0:
57375 +               ioc->function |= 2;
57376 +               ioc->ctl0 |= ctl0;
57377 +               ioc->ctl1 = ctlx;
57378 +               if (!ioa->function) {
57379 +                       ioa->function = 3;
57380 +               }
57381 +               return 0;
57382 +
57383 +       case UBI32_CS4384_MCLK_PWM_1:
57384 +               ioc->function |= 2;
57385 +               ioc->ctl0 |= ctl0 << 16;
57386 +               ioc->ctl2 = ctlx;
57387 +               if (!ioe->function) {
57388 +                       ioe->function = 3;
57389 +               }
57390 +               return 0;
57391 +
57392 +       case UBI32_CS4384_MCLK_PWM_2:
57393 +               ioh->ctl0 |= ctl0;
57394 +               ioh->ctl1 = ctlx;
57395 +               if (!iod->function) {
57396 +                       iod->function = 3;
57397 +               }
57398 +               return 0;
57399 +
57400 +       case UBI32_CS4384_MCLK_CLKDIV_1:
57401 +               ioa->gpio_mask &= (1 << 7);
57402 +               ioa->ctl1 &= ~(0x7F << 14);
57403 +               ioa->ctl1 |= ((div - 1) << 14);
57404 +               return 0;
57405 +
57406 +       case UBI32_CS4384_MCLK_OTHER:
57407 +               return 0;
57408 +       }
57409 +
57410 +       return 1;
57411 +}
57412 +
57413 +/*
57414 + * snd_ubi32_cs4384_set_rate
57415 + */
57416 +static int snd_ubi32_cs4384_set_rate(struct ubi32_snd_priv *priv, int rate)
57417 +{
57418 +       struct ubi32_cs4384_platform_data *cpd = priv->pdata->priv_data;
57419 +       struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57420 +       struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57421 +       struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57422 +       unsigned int ctl;
57423 +       unsigned int div = 0;
57424 +       const u16_t mult[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024};
57425 +       int i;
57426 +       int j;
57427 +
57428 +
57429 +       for (i = 0; i < sizeof(mult) / sizeof(u16_t); i++) {
57430 +               for (j = 0; j < cpd->n_mclk; j++) {
57431 +                       if (((unsigned int)rate * (unsigned int)mult[i]) ==
57432 +                            cpd->mclk_entries[j].rate) {
57433 +                               div = cpd->mclk_entries[j].div;
57434 +                               break;
57435 +                       }
57436 +               }
57437 +       }
57438 +
57439 +       ctl = ((div - 1) << 16) | (div / 2);
57440 +
57441 +       switch (cpd->mclk_src) {
57442 +       case UBI32_CS4384_MCLK_PWM_0:
57443 +               ioc->ctl1 = ctl;
57444 +               return 0;
57445 +
57446 +       case UBI32_CS4384_MCLK_PWM_1:
57447 +               ioc->ctl2 = ctl;
57448 +               return 0;
57449 +
57450 +       case UBI32_CS4384_MCLK_PWM_2:
57451 +               ioh->ctl1 = ctl;
57452 +               return 0;
57453 +
57454 +       case UBI32_CS4384_MCLK_CLKDIV_1:
57455 +               ioa->ctl1 &= ~(0x7F << 14);
57456 +               ioa->ctl1 |= ((div - 1) << 14);
57457 +               return 0;
57458 +
57459 +       case UBI32_CS4384_MCLK_OTHER:
57460 +               return 0;
57461 +       }
57462 +
57463 +       return 1;
57464 +}
57465 +
57466 +/*
57467 + * snd_ubi32_cs4384_set_channels
57468 + *     Mute unused channels
57469 + */
57470 +static int snd_ubi32_cs4384_set_channels(struct ubi32_snd_priv *priv, int channels)
57471 +{
57472 +       struct i2c_client *client = (struct i2c_client *)priv->client;
57473 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57474 +       unsigned char send[2];
57475 +       int ret;
57476 +       int i;
57477 +       unsigned long flags;
57478 +
57479 +       /*
57480 +        * Only support 0, 2, 4, 6, 8 channels
57481 +        */
57482 +       if ((channels > 8) || (channels & 1)) {
57483 +               return -EINVAL;
57484 +       }
57485 +
57486 +       cs4384_priv = snd_ubi32_priv_get_drv(priv);
57487 +       spin_lock_irqsave(&cs4384_priv->lock, flags);
57488 +
57489 +       /*
57490 +        * Address 09h, Mute control
57491 +        */
57492 +       send[0] = 0x09;
57493 +       send[1] = (unsigned char)(0xFF << channels);
57494 +
57495 +       ret = i2c_master_send(client, send, 2);
57496 +
57497 +       spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57498 +
57499 +       /*
57500 +        * Notify the system that we changed the mutes
57501 +        */
57502 +       cs4384_priv->mute = (unsigned char)(0xFF << channels);
57503 +
57504 +       for (i = SND_UBI32_MUTE_CTL_START; i < SND_UBI32_MUTE_CTL_END; i++) {
57505 +               snd_ctl_notify(priv->card, SNDRV_CTL_EVENT_MASK_VALUE,
57506 +                              &cs4384_priv->kctls[i]->id);
57507 +       }
57508 +
57509 +       if (ret != 2) {
57510 +               return -ENXIO;
57511 +       }
57512 +
57513 +       return 0;
57514 +}
57515 +
57516 +/*
57517 + * snd_ubi32_cs4384_dac_init
57518 + */
57519 +static int snd_ubi32_cs4384_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
57520 +{
57521 +       int ret;
57522 +       unsigned char send[2];
57523 +       unsigned char recv[2];
57524 +
57525 +       /*
57526 +        * Initialize the CS4384 DAC over the I2C interface
57527 +        */
57528 +       snd_printk(KERN_INFO "Initializing CS4384 DAC\n");
57529 +
57530 +       /*
57531 +        * Register 0x01: device/revid
57532 +        */
57533 +       send[0] = 0x01;
57534 +       ret = i2c_master_send(client, send, 1);
57535 +       if (ret != 1) {
57536 +               snd_printk(KERN_ERR "Failed 1st attempt to write to CS4384 register 0x01\n");
57537 +               goto fail;
57538 +       }
57539 +       ret = i2c_master_recv(client, recv, 1);
57540 +       if (ret != 1) {
57541 +               snd_printk(KERN_ERR "Failed initial read of CS4384 registers\n");
57542 +               goto fail;
57543 +       }
57544 +       snd_printk(KERN_INFO "CS4384 DAC Device/Rev: %08x\n", recv[0]);
57545 +
57546 +       /*
57547 +        * Register 0x02: Mode Control 1
57548 +        *      Control Port Enable, PCM, All DACs enabled, Power Down
57549 +        */
57550 +       send[0] = 0x02;
57551 +       send[1] = 0x81;
57552 +       ret = i2c_master_send(client, send, 2);
57553 +       if (ret != 2) {
57554 +               snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57555 +               goto fail;
57556 +       }
57557 +
57558 +       /*
57559 +        * Register 0x08: Ramp and Mute
57560 +        *      RMP_UP, RMP_DN, PAMUTE, DAMUTE
57561 +        */
57562 +       send[0] = 0x08;
57563 +       send[1] = 0xBC;
57564 +       ret = i2c_master_send(client, send, 2);
57565 +       if (ret != 2) {
57566 +               snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57567 +               goto fail;
57568 +       }
57569 +
57570 +       /*
57571 +        * Register 0x03: PCM Control
57572 +        *      I2S DIF[3:0] = 0001, no De-Emphasis, Auto speed mode
57573 +        */
57574 +       send[0] = 0x03;
57575 +       send[1] = 0x13;
57576 +       ret = i2c_master_send(client, send, 2);
57577 +       if (ret != 2) {
57578 +               snd_printk(KERN_ERR "Failed to set CS4384 to I2S mode\n");
57579 +               goto fail;
57580 +       }
57581 +
57582 +       /*
57583 +        * Register 0x0B/0x0C: Volume control A1/B1
57584 +        * Register 0x0E/0x0F: Volume control A2/B2
57585 +        * Register 0x11/0x12: Volume control A3/B3
57586 +        * Register 0x14/0x15: Volume control A4/B4
57587 +        */
57588 +       send[0] = 0x80 | 0x0B;
57589 +       send[1] = 0x00;
57590 +       send[2] = 0x00;
57591 +       ret = i2c_master_send(client, send, 3);
57592 +       if (ret != 3) {
57593 +               snd_printk(KERN_ERR "Failed to set ch1 volume on CS4384\n");
57594 +               goto fail;
57595 +       }
57596 +
57597 +       send[0] = 0x80 | 0x0E;
57598 +       send[1] = 0x00;
57599 +       send[2] = 0x00;
57600 +       ret = i2c_master_send(client, send, 3);
57601 +       if (ret != 3) {
57602 +               snd_printk(KERN_ERR "Failed to set ch2 volume on CS4384\n");
57603 +               goto fail;
57604 +       }
57605 +
57606 +       send[0] = 0x80 | 0x11;
57607 +       send[1] = 0x00;
57608 +       send[2] = 0x00;
57609 +       ret = i2c_master_send(client, send, 3);
57610 +       if (ret != 3) {
57611 +               snd_printk(KERN_ERR "Failed to set ch3 volume on CS4384\n");
57612 +               goto fail;
57613 +       }
57614 +
57615 +       send[0] = 0x80 | 0x14;
57616 +       send[1] = 0x00;
57617 +       send[2] = 0x00;
57618 +       ret = i2c_master_send(client, send, 3);
57619 +       if (ret != 3) {
57620 +               snd_printk(KERN_ERR "Failed to set ch4 volume on CS4384\n");
57621 +               goto fail;
57622 +       }
57623 +
57624 +       /*
57625 +        * Register 09h: Mute control
57626 +        *      Mute all (we will unmute channels as needed)
57627 +        */
57628 +       send[0] = 0x09;
57629 +       send[1] = 0xFF;
57630 +       ret = i2c_master_send(client, send, 2);
57631 +       if (ret != 2) {
57632 +               snd_printk(KERN_ERR "Failed to power up CS4384\n");
57633 +               goto fail;
57634 +       }
57635 +
57636 +       /*
57637 +        * Register 0x02: Mode Control 1
57638 +        *      Control Port Enable, PCM, All DACs enabled, Power Up
57639 +        */
57640 +       send[0] = 0x02;
57641 +       send[1] = 0x80;
57642 +       ret = i2c_master_send(client, send, 2);
57643 +       if (ret != 2) {
57644 +               snd_printk(KERN_ERR "Failed to power up CS4384\n");
57645 +               goto fail;
57646 +       }
57647 +
57648 +       /*
57649 +        * Make sure the changes took place, this helps verify we are talking to
57650 +        * the correct chip.
57651 +        */
57652 +       send[0] = 0x80 | 0x03;
57653 +       ret = i2c_master_send(client, send, 1);
57654 +       if (ret != 1) {
57655 +               snd_printk(KERN_ERR "Failed to initiate readback\n");
57656 +               goto fail;
57657 +       }
57658 +
57659 +       ret = i2c_master_recv(client, recv, 1);
57660 +       if (ret != 1) {
57661 +               snd_printk(KERN_ERR "Failed second read of CS4384 registers\n");
57662 +               goto fail;
57663 +       }
57664 +
57665 +       if (recv[0] != 0x13) {
57666 +               snd_printk(KERN_ERR "Failed to initialize CS4384 DAC\n");
57667 +               goto fail;
57668 +       }
57669 +
57670 +       snd_printk(KERN_INFO "CS4384 DAC Initialized\n");
57671 +       return 0;
57672 +
57673 +fail:
57674 +       return -ENODEV;
57675 +}
57676 +
57677 +/*
57678 + * snd_ubi32_cs4384_i2c_probe
57679 + */
57680 +static int snd_ubi32_cs4384_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
57681 +{
57682 +       struct snd_card *card;
57683 +       struct ubi32_snd_priv *ubi32_priv;
57684 +       int err, ret;
57685 +       struct platform_device *pdev;
57686 +       struct ubi32_cs4384_platform_data *pdata;
57687 +       struct snd_ubi32_cs4384_priv *cs4384_priv;
57688 +
57689 +       /*
57690 +        * pdev is audio device
57691 +        */
57692 +       pdev = client->dev.platform_data;
57693 +       if (!pdev) {
57694 +               return -ENODEV;
57695 +       }
57696 +
57697 +       /*
57698 +        * pdev->dev.platform_data is ubi32-pcm platform_data
57699 +        */
57700 +       pdata = audio_device_priv(pdev);
57701 +       if (!pdata) {
57702 +               return -ENODEV;
57703 +       }
57704 +
57705 +       /*
57706 +        * Initialize the CS4384 DAC
57707 +        */
57708 +       ret = snd_ubi32_cs4384_dac_init(client, id);
57709 +       if (ret < 0) {
57710 +               /*
57711 +                * Initialization failed.  Propagate the error.
57712 +                */
57713 +               return ret;
57714 +       }
57715 +
57716 +       if (snd_ubi32_cs4384_setup_mclk(pdata)) {
57717 +               return -EINVAL;
57718 +       }
57719 +
57720 +       /*
57721 +        * Create a snd_card structure
57722 +        */
57723 +       card = snd_card_new(index, "Ubi32-CS4384", THIS_MODULE, sizeof(struct ubi32_snd_priv));
57724 +       if (card == NULL) {
57725 +               return -ENOMEM;
57726 +       }
57727 +
57728 +       card->private_free = snd_ubi32_cs4384_free;
57729 +       ubi32_priv = card->private_data;
57730 +
57731 +       /*
57732 +        * Initialize the snd_card's private data structure
57733 +        */
57734 +       ubi32_priv->card = card;
57735 +       ubi32_priv->client = client;
57736 +       ubi32_priv->set_channels = snd_ubi32_cs4384_set_channels;
57737 +       ubi32_priv->set_rate = snd_ubi32_cs4384_set_rate;
57738 +
57739 +       /*
57740 +        * CS4384 DAC has a minimum sample rate of 4khz and an
57741 +        * upper limit of 216khz for it's auto-detect.
57742 +        */
57743 +       ubi32_priv->min_sample_rate = 4000;
57744 +       ubi32_priv->max_sample_rate = 216000;
57745 +
57746 +       /*
57747 +        * Create our private data (to manage volume, etc)
57748 +        */
57749 +       cs4384_priv = kzalloc(sizeof(struct snd_ubi32_cs4384_priv), GFP_KERNEL);
57750 +       if (!cs4384_priv) {
57751 +               snd_card_free(card);
57752 +               return -ENOMEM;
57753 +       }
57754 +       snd_ubi32_priv_set_drv(ubi32_priv, cs4384_priv);
57755 +       spin_lock_init(&cs4384_priv->lock);
57756 +
57757 +       /*
57758 +        * We start off all muted and max volume
57759 +        */
57760 +       cs4384_priv->mute = 0xFF;
57761 +       memset(cs4384_priv->volume, 0xFF, 8);
57762 +
57763 +       /*
57764 +        * Create the new PCM instance
57765 +        */
57766 +       err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
57767 +       if (err < 0) {
57768 +               snd_card_free(card);
57769 +               return err; /* What is err?  Need to include correct file */
57770 +       }
57771 +
57772 +       strcpy(card->driver, "Ubi32-CS4384");
57773 +       strcpy(card->shortname, "Ubi32-CS4384");
57774 +       snprintf(card->longname, sizeof(card->longname),
57775 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
57776 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
57777 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
57778 +
57779 +       snd_card_set_dev(card, &client->dev);
57780 +
57781 +       /*
57782 +        * Set up the mixer
57783 +        */
57784 +       snd_ubi32_cs4384_mixer(ubi32_priv);
57785 +
57786 +       /*
57787 +        * Register the sound card
57788 +        */
57789 +       if ((err = snd_card_register(card)) != 0) {
57790 +               snd_printk(KERN_INFO "snd_card_register error\n");
57791 +       }
57792 +
57793 +       /*
57794 +        * Store card for access from other methods
57795 +        */
57796 +       i2c_set_clientdata(client, card);
57797 +
57798 +       return 0;
57799 +}
57800 +
57801 +/*
57802 + * snd_ubi32_cs4384_i2c_remove
57803 + */
57804 +static int __devexit snd_ubi32_cs4384_i2c_remove(struct i2c_client *client)
57805 +{
57806 +       struct snd_card *card;
57807 +       struct ubi32_snd_priv *ubi32_priv;
57808 +
57809 +       card = i2c_get_clientdata(client);
57810 +
57811 +       ubi32_priv = card->private_data;
57812 +       snd_ubi32_pcm_remove(ubi32_priv);
57813 +
57814 +       snd_card_free(i2c_get_clientdata(client));
57815 +       i2c_set_clientdata(client, NULL);
57816 +
57817 +       return 0;
57818 +}
57819 +
57820 +/*
57821 + * I2C driver description
57822 + */
57823 +static struct i2c_driver snd_ubi32_cs4384_driver = {
57824 +       .driver = {
57825 +               .name = DRIVER_NAME,
57826 +               .owner = THIS_MODULE,
57827 +       },
57828 +       .id_table       = snd_ubi32_cs4384_id,
57829 +       .probe          = snd_ubi32_cs4384_i2c_probe,
57830 +       .remove         = __devexit_p(snd_ubi32_cs4384_i2c_remove),
57831 +};
57832 +
57833 +/*
57834 + * Driver init
57835 + */
57836 +static int __init snd_ubi32_cs4384_init(void)
57837 +{
57838 +       return i2c_add_driver(&snd_ubi32_cs4384_driver);
57839 +}
57840 +module_init(snd_ubi32_cs4384_init);
57841 +
57842 +/*
57843 + * snd_ubi32_cs4384_exit
57844 + */
57845 +static void __exit snd_ubi32_cs4384_exit(void)
57846 +{
57847 +       i2c_del_driver(&snd_ubi32_cs4384_driver);
57848 +}
57849 +module_exit(snd_ubi32_cs4384_exit);
57850 +
57851 +/*
57852 + * Module properties
57853 + */
57854 +MODULE_ALIAS("i2c:" DRIVER_NAME);
57855 +MODULE_AUTHOR("Patrick Tjin");
57856 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4384");
57857 +MODULE_LICENSE("GPL");
57858 --- /dev/null
57859 +++ b/sound/ubicom32/ubi32-generic.c
57860 @@ -0,0 +1,166 @@
57861 +/*
57862 + * sound/ubicom32/ubi32-generic.c
57863 + *     Interface to ubicom32 virtual audio peripheral
57864 + *
57865 + * (C) Copyright 2009, Ubicom, Inc.
57866 + *
57867 + * This file is part of the Ubicom32 Linux Kernel Port.
57868 + *
57869 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
57870 + * it and/or modify it under the terms of the GNU General Public License
57871 + * as published by the Free Software Foundation, either version 2 of the
57872 + * License, or (at your option) any later version.
57873 + *
57874 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
57875 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
57876 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
57877 + * the GNU General Public License for more details.
57878 + *
57879 + * You should have received a copy of the GNU General Public License
57880 + * along with the Ubicom32 Linux Kernel Port.  If not,
57881 + * see <http://www.gnu.org/licenses/>.
57882 + *
57883 + * Ubicom32 implementation derived from (with many thanks):
57884 + *   arch/m68knommu
57885 + *   arch/blackfin
57886 + *   arch/parisc
57887 + */
57888 +
57889 +#include <linux/platform_device.h>
57890 +#include <linux/module.h>
57891 +#include <linux/moduleparam.h>
57892 +#include <sound/core.h>
57893 +#include <sound/pcm.h>
57894 +#include <sound/initval.h>
57895 +#include "ubi32.h"
57896 +
57897 +#define DRIVER_NAME "snd-ubi32-generic"
57898 +
57899 +/*
57900 + * Module properties
57901 + */
57902 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
57903 +
57904 +/*
57905 + * Card private data free function
57906 + */
57907 +void snd_ubi32_generic_free(struct snd_card *card)
57908 +{
57909 +       /*
57910 +        * Free all the fields in the snd_ubi32_priv struct
57911 +        */
57912 +       // Nothing to free at this time because ubi32_priv just maintains pointers
57913 +}
57914 +
57915 +/*
57916 + * Ubicom audio driver probe() method.  Args change depending on whether we use
57917 + * platform_device or i2c_device.
57918 + */
57919 +static int snd_ubi32_generic_probe(struct platform_device *dev)
57920 +{
57921 +       struct snd_card *card;
57922 +       struct ubi32_snd_priv *ubi32_priv;
57923 +       int err;
57924 +
57925 +       /*
57926 +        * Create a snd_card structure
57927 +        */
57928 +       card = snd_card_new(index, "Ubi32-Generic", THIS_MODULE, sizeof(struct ubi32_snd_priv));
57929 +
57930 +       if (card == NULL) {
57931 +               return -ENOMEM;
57932 +       }
57933 +
57934 +       card->private_free = snd_ubi32_generic_free; /* Not sure if correct */
57935 +       ubi32_priv = card->private_data;
57936 +
57937 +       /*
57938 +        * Initialize the snd_card's private data structure
57939 +        */
57940 +       ubi32_priv->card = card;
57941 +
57942 +       /*
57943 +        * Create the new PCM instance
57944 +        */
57945 +       err = snd_ubi32_pcm_probe(ubi32_priv, dev);
57946 +       if (err < 0) {
57947 +               snd_card_free(card);
57948 +               return err;
57949 +       }
57950 +
57951 +       strcpy(card->driver, "Ubi32-Generic");
57952 +       strcpy(card->shortname, "Ubi32-Generic");
57953 +       snprintf(card->longname, sizeof(card->longname),
57954 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
57955 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
57956 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
57957 +
57958 +       snd_card_set_dev(card, &dev->dev);
57959 +
57960 +       /* Register the sound card */
57961 +       if ((err = snd_card_register(card)) != 0) {
57962 +               snd_printk(KERN_INFO "snd_card_register error\n");
57963 +       }
57964 +
57965 +       /* Store card for access from other methods */
57966 +       platform_set_drvdata(dev, card);
57967 +
57968 +       return 0;
57969 +}
57970 +
57971 +/*
57972 + * Ubicom audio driver remove() method
57973 + */
57974 +static int __devexit snd_ubi32_generic_remove(struct platform_device *dev)
57975 +{
57976 +       struct snd_card *card;
57977 +       struct ubi32_snd_priv *ubi32_priv;
57978 +
57979 +       card = platform_get_drvdata(dev);
57980 +       ubi32_priv = card->private_data;
57981 +       snd_ubi32_pcm_remove(ubi32_priv);
57982 +
57983 +       snd_card_free(platform_get_drvdata(dev));
57984 +       platform_set_drvdata(dev, NULL);
57985 +       return 0;
57986 +}
57987 +
57988 +/*
57989 + * Platform driver definition
57990 + */
57991 +static struct platform_driver snd_ubi32_generic_driver = {
57992 +       .driver = {
57993 +               .name = DRIVER_NAME,
57994 +               .owner = THIS_MODULE,
57995 +       },
57996 +       .probe = snd_ubi32_generic_probe,
57997 +       .remove = __devexit_p(snd_ubi32_generic_remove),
57998 +};
57999 +
58000 +/*
58001 + * snd_ubi32_generic_init
58002 + */
58003 +static int __init snd_ubi32_generic_init(void)
58004 +{
58005 +       return platform_driver_register(&snd_ubi32_generic_driver);
58006 +}
58007 +module_init(snd_ubi32_generic_init);
58008 +
58009 +/*
58010 + * snd_ubi32_generic_exit
58011 + */
58012 +static void __exit snd_ubi32_generic_exit(void)
58013 +{
58014 +       platform_driver_unregister(&snd_ubi32_generic_driver);
58015 +}
58016 +module_exit(snd_ubi32_generic_exit);
58017 +
58018 +/*
58019 + * Module properties
58020 + */
58021 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58022 +//MODULE_ALIAS("i2c:snd-ubi32");
58023 +//#endif
58024 +MODULE_AUTHOR("Aaron Jow, Patrick Tjin");
58025 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58026 +MODULE_LICENSE("GPL");
58027 --- /dev/null
58028 +++ b/sound/ubicom32/ubi32-generic-capture.c
58029 @@ -0,0 +1,167 @@
58030 +/*
58031 + * sound/ubicom32/ubi32-generic-capture.c
58032 + *     Interface to ubicom32 virtual audio peripheral
58033 + *
58034 + * (C) Copyright 2009, Ubicom, Inc.
58035 + *
58036 + * This file is part of the Ubicom32 Linux Kernel Port.
58037 + *
58038 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58039 + * it and/or modify it under the terms of the GNU General Public License
58040 + * as published by the Free Software Foundation, either version 2 of the
58041 + * License, or (at your option) any later version.
58042 + *
58043 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58044 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58045 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58046 + * the GNU General Public License for more details.
58047 + *
58048 + * You should have received a copy of the GNU General Public License
58049 + * along with the Ubicom32 Linux Kernel Port.  If not,
58050 + * see <http://www.gnu.org/licenses/>.
58051 + *
58052 + * Ubicom32 implementation derived from (with many thanks):
58053 + *   arch/m68knommu
58054 + *   arch/blackfin
58055 + *   arch/parisc
58056 + */
58057 +
58058 +#include <linux/platform_device.h>
58059 +#include <linux/module.h>
58060 +#include <linux/moduleparam.h>
58061 +#include <sound/core.h>
58062 +#include <sound/pcm.h>
58063 +#include <sound/initval.h>
58064 +#include "ubi32.h"
58065 +
58066 +#define DRIVER_NAME "snd-ubi32-generic-capture"
58067 +
58068 +/*
58069 + * Module properties
58070 + */
58071 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
58072 +
58073 +/*
58074 + * Card private data free function
58075 + */
58076 +void snd_ubi32_generic_capture_free(struct snd_card *card)
58077 +{
58078 +       /*
58079 +        * Free all the fields in the snd_ubi32_priv struct
58080 +        */
58081 +       // Nothing to free at this time because ubi32_priv just maintains pointers
58082 +}
58083 +
58084 +/*
58085 + * Ubicom audio driver probe() method.  Args change depending on whether we use
58086 + * platform_device or i2c_device.
58087 + */
58088 +static int snd_ubi32_generic_capture_probe(struct platform_device *dev)
58089 +{
58090 +       struct snd_card *card;
58091 +       struct ubi32_snd_priv *ubi32_priv;
58092 +       int err;
58093 +
58094 +       /*
58095 +        * Create a snd_card structure
58096 +        */
58097 +       card = snd_card_new(index, "Ubi32-Generic-C", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58098 +
58099 +       if (card == NULL) {
58100 +               return -ENOMEM;
58101 +       }
58102 +
58103 +       card->private_free = snd_ubi32_generic_capture_free; /* Not sure if correct */
58104 +       ubi32_priv = card->private_data;
58105 +
58106 +       /*
58107 +        * Initialize the snd_card's private data structure
58108 +        */
58109 +       ubi32_priv->card = card;
58110 +       ubi32_priv->is_capture = 1;
58111 +
58112 +       /*
58113 +        * Create the new PCM instance
58114 +        */
58115 +       err = snd_ubi32_pcm_probe(ubi32_priv, dev);
58116 +       if (err < 0) {
58117 +               snd_card_free(card);
58118 +               return err;
58119 +       }
58120 +
58121 +       strcpy(card->driver, "Ubi32-Generic-C");
58122 +       strcpy(card->shortname, "Ubi32-Generic-C");
58123 +       snprintf(card->longname, sizeof(card->longname),
58124 +               "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58125 +               card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58126 +               ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58127 +
58128 +       snd_card_set_dev(card, &dev->dev);
58129 +
58130 +       /* Register the sound card */
58131 +       if ((err = snd_card_register(card)) != 0) {
58132 +               snd_printk(KERN_INFO "snd_card_register error\n");
58133 +       }
58134 +
58135 +       /* Store card for access from other methods */
58136 +       platform_set_drvdata(dev, card);
58137 +
58138 +       return 0;
58139 +}
58140 +
58141 +/*
58142 + * Ubicom audio driver remove() method
58143 + */
58144 +static int __devexit snd_ubi32_generic_capture_remove(struct platform_device *dev)
58145 +{
58146 +       struct snd_card *card;
58147 +       struct ubi32_snd_priv *ubi32_priv;
58148 +
58149 +       card = platform_get_drvdata(dev);
58150 +       ubi32_priv = card->private_data;
58151 +       snd_ubi32_pcm_remove(ubi32_priv);
58152 +
58153 +       snd_card_free(platform_get_drvdata(dev));
58154 +       platform_set_drvdata(dev, NULL);
58155 +       return 0;
58156 +}
58157 +
58158 +/*
58159 + * Platform driver definition
58160 + */
58161 +static struct platform_driver snd_ubi32_generic_capture_driver = {
58162 +       .driver = {
58163 +               .name = DRIVER_NAME,
58164 +               .owner = THIS_MODULE,
58165 +       },
58166 +       .probe = snd_ubi32_generic_capture_probe,
58167 +       .remove = __devexit_p(snd_ubi32_generic_capture_remove),
58168 +};
58169 +
58170 +/*
58171 + * snd_ubi32_generic_capture_init
58172 + */
58173 +static int __init snd_ubi32_generic_capture_init(void)
58174 +{
58175 +       return platform_driver_register(&snd_ubi32_generic_capture_driver);
58176 +}
58177 +module_init(snd_ubi32_generic_capture_init);
58178 +
58179 +/*
58180 + * snd_ubi32_generic_capture_exit
58181 + */
58182 +static void __exit snd_ubi32_generic_capture_exit(void)
58183 +{
58184 +       platform_driver_unregister(&snd_ubi32_generic_capture_driver);
58185 +}
58186 +module_exit(snd_ubi32_generic_capture_exit);
58187 +
58188 +/*
58189 + * Module properties
58190 + */
58191 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58192 +//MODULE_ALIAS("i2c:snd-ubi32");
58193 +//#endif
58194 +MODULE_AUTHOR("Patrick Tjin");
58195 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58196 +MODULE_LICENSE("GPL");
58197 --- /dev/null
58198 +++ b/sound/ubicom32/ubi32.h
58199 @@ -0,0 +1,102 @@
58200 +/*
58201 + * sound/ubicom32/ubi32.h
58202 + *     Common header file for all ubi32- sound drivers
58203 + *
58204 + * (C) Copyright 2009, Ubicom, Inc.
58205 + *
58206 + * This file is part of the Ubicom32 Linux Kernel Port.
58207 + *
58208 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58209 + * it and/or modify it under the terms of the GNU General Public License
58210 + * as published by the Free Software Foundation, either version 2 of the
58211 + * License, or (at your option) any later version.
58212 + *
58213 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58214 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58215 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58216 + * the GNU General Public License for more details.
58217 + *
58218 + * You should have received a copy of the GNU General Public License
58219 + * along with the Ubicom32 Linux Kernel Port.  If not,
58220 + * see <http://www.gnu.org/licenses/>.
58221 + */
58222 +
58223 +#ifndef _UBI32_H
58224 +#define _UBI32_H
58225 +
58226 +#define SND_UBI32_DEBUG 0 // Debug flag
58227 +
58228 +#include <linux/platform_device.h>
58229 +#include <asm/devtree.h>
58230 +#include <asm/audio.h>
58231 +#include <asm/ubi32-pcm.h>
58232 +
58233 +struct ubi32_snd_priv;
58234 +
58235 +typedef int (*set_channels_t)(struct ubi32_snd_priv *priv, int channels);
58236 +typedef int (*set_rate_t)(struct ubi32_snd_priv *priv, int rate);
58237 +
58238 +struct ubi32_snd_priv {
58239 +       /*
58240 +        * Any variables that are needed locally here but NOT in
58241 +        * the VP itself should go in here.
58242 +        */
58243 +       struct snd_card *card;
58244 +       struct snd_pcm *pcm;
58245 +
58246 +       /*
58247 +        * capture (1) or playback (0)
58248 +        */
58249 +       int is_capture;
58250 +       /*
58251 +        * DAC parameters.  These are the parameters for the specific
58252 +        * DAC we are driving.  The I2S component can run at a range
58253 +        * of frequencies, but the DAC may be limited.  We may want
58254 +        * to make this an array of some sort in the future?
58255 +        *
58256 +        * min/max_sample_rate if set to 0 are ignored.
58257 +        */
58258 +       int max_sample_rate;
58259 +       int min_sample_rate;
58260 +
58261 +       /*
58262 +        * The size a period (group) of audio samples.  The VP does
58263 +        * not need to know this; each DMA transfer is made to be
58264 +        * one period.
58265 +        */
58266 +       u32_t period_size;
58267 +
58268 +       spinlock_t ubi32_lock;
58269 +
58270 +       struct audio_regs *ar;
58271 +       struct audio_dev_regs *adr;
58272 +       u32 irq_idx;
58273 +       u8 tx_irq;
58274 +       u8 rx_irq;
58275 +
58276 +       void *client;
58277 +
58278 +       /*
58279 +        * Operations which the base DAC driver can implement
58280 +        */
58281 +       set_channels_t set_channels;
58282 +       set_rate_t set_rate;
58283 +
58284 +       /*
58285 +        * platform data
58286 +        */
58287 +       struct ubi32pcm_platform_data *pdata;
58288 +
58289 +       /*
58290 +        * Private driver data (used for DAC driver control, etc)
58291 +        */
58292 +       void *drvdata;
58293 +};
58294 +
58295 +#define snd_ubi32_priv_get_drv(priv) ((priv)->drvdata)
58296 +#define snd_ubi32_priv_set_drv(priv, data) (((priv)->drvdata) = (void *)(data))
58297 +
58298 +extern int snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev);
58299 +extern void snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv);
58300 +
58301 +#endif
58302 --- /dev/null
58303 +++ b/sound/ubicom32/ubi32-pcm.c
58304 @@ -0,0 +1,711 @@
58305 +/*
58306 + * sound/ubicom32/ubi32-pcm.c
58307 + *     Interface to ubicom32 virtual audio peripheral
58308 + *
58309 + * (C) Copyright 2009, Ubicom, Inc.
58310 + *
58311 + * This file is part of the Ubicom32 Linux Kernel Port.
58312 + *
58313 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58314 + * it and/or modify it under the terms of the GNU General Public License
58315 + * as published by the Free Software Foundation, either version 2 of the
58316 + * License, or (at your option) any later version.
58317 + *
58318 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58319 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58320 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
58321 + * the GNU General Public License for more details.
58322 + *
58323 + * You should have received a copy of the GNU General Public License
58324 + * along with the Ubicom32 Linux Kernel Port.  If not,
58325 + * see <http://www.gnu.org/licenses/>.
58326 + *
58327 + * Ubicom32 implementation derived from (with many thanks):
58328 + *   arch/m68knommu
58329 + *   arch/blackfin
58330 + *   arch/parisc
58331 + */
58332 +
58333 +#include <linux/interrupt.h>
58334 +#include <sound/core.h>
58335 +#include <sound/pcm.h>
58336 +#include <sound/pcm_params.h>
58337 +#include <asm/ip5000.h>
58338 +#include <asm/ubi32-pcm.h>
58339 +#include <linux/dma-mapping.h>
58340 +#include <linux/delay.h>
58341 +#include "ubi32.h"
58342 +
58343 +struct ubi32_snd_runtime_data {
58344 +       dma_addr_t dma_buffer;          /* Physical address of DMA buffer */
58345 +       dma_addr_t dma_buffer_end;      /* First address beyond end of DMA buffer */
58346 +       size_t period_size;
58347 +       dma_addr_t period_ptr;          /* Physical address of next period */
58348 +       unsigned int flags;
58349 +};
58350 +
58351 +static void snd_ubi32_vp_int_set(struct snd_pcm *pcm)
58352 +{
58353 +       struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
58354 +       ubi32_priv->ar->int_req |= (1 << ubi32_priv->irq_idx);
58355 +       ubicom32_set_interrupt(ubi32_priv->tx_irq);
58356 +}
58357 +
58358 +static snd_pcm_uframes_t snd_ubi32_pcm_pointer(struct snd_pcm_substream *substream)
58359 +{
58360 +
58361 +       struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58362 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58363 +       struct snd_pcm_runtime *runtime = substream->runtime;
58364 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58365 +
58366 +       dma_addr_t read_pos;
58367 +
58368 +       snd_pcm_uframes_t frames;
58369 +       if (!adr->primary_os_buffer_ptr) {
58370 +               /*
58371 +                * If primary_os_buffer_ptr is NULL (e.g. right after the HW is started or
58372 +                * when the HW is stopped), then handle this case separately.
58373 +                */
58374 +               return 0;
58375 +       }
58376 +
58377 +       read_pos = (dma_addr_t)adr->primary_os_buffer_ptr;
58378 +       frames = bytes_to_frames(runtime, read_pos - ubi32_rd->dma_buffer);
58379 +       if (frames == runtime->buffer_size) {
58380 +               frames = 0;
58381 +       }
58382 +       return frames;
58383 +}
58384 +
58385 +/*
58386 + * Audio trigger
58387 + */
58388 +static int snd_ubi32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
58389 +{
58390 +       struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58391 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58392 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58393 +       int ret = 0;
58394 +
58395 +#ifdef CONFIG_SND_DEBUG
58396 +       snd_printk(KERN_INFO "snd_ubi32_pcm_trigger cmd=%d=", cmd);
58397 +#endif
58398 +
58399 +       if (adr->command != AUDIO_CMD_NONE) {
58400 +               snd_printk(KERN_WARNING "Can't send command to audio device at this time\n");
58401 +               // Set a timer to call this function back later.  How to do this?
58402 +               return 0;
58403 +       }
58404 +
58405 +       /*
58406 +        * Set interrupt flag to indicate that we interrupted audio device
58407 +        * to send a command
58408 +        */
58409 +
58410 +       switch (cmd) {
58411 +       case SNDRV_PCM_TRIGGER_START:
58412 +
58413 +#ifdef CONFIG_SND_DEBUG
58414 +               snd_printk(KERN_INFO "START\n");
58415 +#endif
58416 +               /*
58417 +                * Ready the DMA transfer
58418 +                */
58419 +               ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
58420 +
58421 +#ifdef CONFIG_SND_DEBUG
58422 +               snd_printk(KERN_INFO "trigger period_ptr=%lx\n", (unsigned long)ubi32_rd->period_ptr);
58423 +#endif
58424 +               adr->dma_xfer_requests[0].ptr = (void *)ubi32_rd->period_ptr;
58425 +               adr->dma_xfer_requests[0].ctr = ubi32_rd->period_size;
58426 +               adr->dma_xfer_requests[0].active = 1;
58427 +
58428 +#ifdef CONFIG_SND_DEBUG
58429 +               snd_printk(KERN_INFO "xfer_request 0 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58430 +#endif
58431 +
58432 +               ubi32_rd->period_ptr += ubi32_rd->period_size;
58433 +               adr->dma_xfer_requests[1].ptr = (void *)ubi32_rd->period_ptr;
58434 +               adr->dma_xfer_requests[1].ctr = ubi32_rd->period_size;
58435 +               adr->dma_xfer_requests[1].active = 1;
58436 +
58437 +#ifdef CONFIG_SND_DEBUG
58438 +               snd_printk(KERN_INFO "xfer_request 1 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58439 +#endif
58440 +
58441 +               /*
58442 +                * Tell the VP that we want to begin playback by filling in the
58443 +                * command field and then interrupting the audio VP
58444 +                */
58445 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58446 +               adr->command = AUDIO_CMD_START;
58447 +               snd_ubi32_vp_int_set(substream->pcm);
58448 +               break;
58449 +
58450 +       case SNDRV_PCM_TRIGGER_STOP:
58451 +
58452 +#ifdef CONFIG_SND_DEBUG
58453 +               snd_printk(KERN_INFO "STOP\n");
58454 +#endif
58455 +
58456 +               /*
58457 +                * Tell the VP that we want to stop playback by filling in the
58458 +                * command field and then interrupting the audio VP
58459 +                */
58460 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58461 +               adr->command = AUDIO_CMD_STOP;
58462 +               snd_ubi32_vp_int_set(substream->pcm);
58463 +               break;
58464 +
58465 +       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
58466 +
58467 +#ifdef CONFIG_SND_DEBUG
58468 +               snd_printk(KERN_INFO "PAUSE_PUSH\n");
58469 +#endif
58470 +
58471 +               /*
58472 +                * Tell the VP that we want to pause playback by filling in the
58473 +                * command field and then interrupting the audio VP
58474 +                */
58475 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58476 +               adr->command = AUDIO_CMD_PAUSE;
58477 +               snd_ubi32_vp_int_set(substream->pcm);
58478 +               break;
58479 +
58480 +       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
58481 +
58482 +#ifdef CONFIG_SND_DEBUG
58483 +               snd_printk(KERN_INFO "PAUSE_RELEASE\n");
58484 +#endif
58485 +               /*
58486 +                * Tell the VP that we want to resume paused playback by filling
58487 +                * in the command field and then interrupting the audio VP
58488 +                */
58489 +               adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58490 +               adr->command = AUDIO_CMD_RESUME;
58491 +               snd_ubi32_vp_int_set(substream->pcm);
58492 +               break;
58493 +
58494 +       default:
58495 +               snd_printk(KERN_WARNING "Unhandled trigger\n");
58496 +               ret = -EINVAL;
58497 +               break;
58498 +       }
58499 +
58500 +       return ret;
58501 +}
58502 +
58503 +/*
58504 + * Prepare to transfer an audio stream to the codec
58505 + */
58506 +static int snd_ubi32_pcm_prepare(struct snd_pcm_substream *substream)
58507 +{
58508 +       /*
58509 +        * Configure registers and setup the runtime instance for DMA transfers
58510 +        */
58511 +       struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58512 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58513 +
58514 +#ifdef CONFIG_SND_DEBUG
58515 +       snd_printk(KERN_INFO "snd_ubi32_pcm_prepare: sending STOP command to audio device\n");
58516 +#endif
58517 +
58518 +       /*
58519 +        * Make sure the audio device is stopped
58520 +        */
58521 +
58522 +       /*
58523 +        * Set interrupt flag to indicate that we interrupted audio device
58524 +        * to send a command
58525 +        */
58526 +       adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58527 +       adr->command = AUDIO_CMD_STOP;
58528 +       snd_ubi32_vp_int_set(substream->pcm);
58529 +
58530 +       return 0;
58531 +}
58532 +
58533 +/*
58534 + * Allocate DMA buffers from preallocated memory.
58535 + * Preallocation was done in snd_ubi32_pcm_new()
58536 + */
58537 +static int snd_ubi32_pcm_hw_params(struct snd_pcm_substream *substream,
58538 +                                       struct snd_pcm_hw_params *hw_params)
58539 +{
58540 +       struct snd_pcm_runtime *runtime = substream->runtime;
58541 +       struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58542 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58543 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58544 +
58545 +       /*
58546 +        * Use pre-allocated memory from ubi32_snd_pcm_new() to satisfy
58547 +        * this memory request.
58548 +        */
58549 +       int ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
58550 +       if (ret < 0) {
58551 +               return ret;
58552 +       }
58553 +
58554 +#ifdef CONFIG_SND_DEBUG
58555 +       snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params\n");
58556 +#endif
58557 +
58558 +       if (!(adr->channel_mask & (1 << params_channels(hw_params)))) {
58559 +               snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params unsupported number of channels %d mask %08x\n", params_channels(hw_params), adr->channel_mask);
58560 +               return -EINVAL;
58561 +       }
58562 +
58563 +       if (ubi32_priv->set_channels) {
58564 +               int ret = ubi32_priv->set_channels(ubi32_priv, params_channels(hw_params));
58565 +               if (ret) {
58566 +                       snd_printk(KERN_WARNING "Unable to set channels to %d, ret=%d\n", params_channels(hw_params), ret);
58567 +                       return ret;
58568 +               }
58569 +       }
58570 +
58571 +       if (ubi32_priv->set_rate) {
58572 +               int ret = ubi32_priv->set_rate(ubi32_priv, params_rate(hw_params));
58573 +               if (ret) {
58574 +                       snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58575 +                       return ret;
58576 +               }
58577 +       }
58578 +
58579 +       if (ubi32_priv->pdata->set_rate) {
58580 +               int ret = ubi32_priv->pdata->set_rate(ubi32_priv->pdata->appdata, params_rate(hw_params));
58581 +               if (ret) {
58582 +                       snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58583 +                       return ret;
58584 +               }
58585 +       }
58586 +
58587 +       if (adr->command != AUDIO_CMD_NONE) {
58588 +               snd_printk(KERN_WARNING "snd_ubi32_pcm_hw_params: tio busy\n");
58589 +               return -EAGAIN;
58590 +       }
58591 +
58592 +       if (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) {
58593 +               adr->flags |= CMD_START_FLAG_LE;
58594 +       } else {
58595 +               adr->flags &= ~CMD_START_FLAG_LE;
58596 +       }
58597 +       adr->channels = params_channels(hw_params);
58598 +       adr->sample_rate = params_rate(hw_params);
58599 +       adr->command = AUDIO_CMD_SETUP;
58600 +       adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58601 +       snd_ubi32_vp_int_set(substream->pcm);
58602 +
58603 +       /*
58604 +        * Wait for the command to complete
58605 +        */
58606 +       while (adr->command != AUDIO_CMD_NONE) {
58607 +               udelay(1);
58608 +       }
58609 +
58610 +       /*
58611 +        * Put the DMA info into the DMA descriptor that we will
58612 +        * use to do transfers to our audio VP "hardware"
58613 +        */
58614 +
58615 +       /*
58616 +        * Mark both DMA transfers as not ready/inactive
58617 +        */
58618 +       adr->dma_xfer_requests[0].active = 0;
58619 +       adr->dma_xfer_requests[1].active = 0;
58620 +
58621 +       /*
58622 +        * Put the location of the buffer into the runtime data instance
58623 +        */
58624 +       ubi32_rd->dma_buffer = (dma_addr_t)runtime->dma_area;
58625 +       ubi32_rd->dma_buffer_end = (dma_addr_t)(runtime->dma_area + runtime->dma_bytes);
58626 +
58627 +       /*
58628 +        * Get the period size
58629 +        */
58630 +       ubi32_rd->period_size = params_period_bytes(hw_params);
58631 +
58632 +#ifdef CONFIG_SND_DEBUG
58633 +       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);
58634 +       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);
58635 +#endif
58636 +
58637 +       return ret;
58638 +}
58639 +
58640 +/*
58641 + * This is the reverse of snd_ubi32_pcm_hw_params
58642 + */
58643 +static int snd_ubi32_pcm_hw_free(struct snd_pcm_substream *substream)
58644 +{
58645 +#ifdef CONFIG_SND_DEBUG
58646 +       snd_printk(KERN_INFO "snd_ubi32_pcm_hw_free\n");
58647 +#endif
58648 +       return snd_pcm_lib_free_pages(substream);
58649 +}
58650 +
58651 +/*
58652 + * Audio virtual peripheral capabilities (capture and playback are identical)
58653 + */
58654 +static struct snd_pcm_hardware snd_ubi32_pcm_hw =
58655 +{
58656 +       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
58657 +                SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
58658 +       .buffer_bytes_max = (64*1024),
58659 +       .period_bytes_min       = 64,
58660 +       .period_bytes_max       = 8184,//8184,//8176,
58661 +       .periods_min = 2,
58662 +       .periods_max = 255,
58663 +       .fifo_size = 0, // THIS IS IGNORED BY ALSA
58664 +};
58665 +
58666 +/*
58667 + * We fill this in later
58668 + */
58669 +static struct snd_pcm_hw_constraint_list ubi32_pcm_rates;
58670 +
58671 +/*
58672 + * snd_ubi32_pcm_close
58673 + */
58674 +static int snd_ubi32_pcm_close(struct snd_pcm_substream *substream)
58675 +{
58676 +       /* Disable codec, stop DMA, free private data structures */
58677 +       //struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58678 +       struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58679 +
58680 +#ifdef CONFIG_SND_DEBUG
58681 +       snd_printk(KERN_INFO "snd_ubi32_pcm_close\n");
58682 +#endif
58683 +
58684 +       substream->runtime->private_data = NULL;
58685 +
58686 +       kfree(ubi32_rd);
58687 +
58688 +       return 0;
58689 +}
58690 +
58691 +/*
58692 + * snd_ubi32_pcm_open
58693 + */
58694 +static int snd_ubi32_pcm_open(struct snd_pcm_substream *substream)
58695 +{
58696 +       struct snd_pcm_runtime *runtime = substream->runtime;
58697 +       struct ubi32_snd_runtime_data *ubi32_rd;
58698 +       int ret = 0;
58699 +
58700 +#ifdef CONFIG_SND_DEBUG
58701 +       snd_printk(KERN_INFO "ubi32 pcm open\n");
58702 +#endif
58703 +
58704 +       /* Associate capabilities with component */
58705 +       runtime->hw = snd_ubi32_pcm_hw;
58706 +
58707 +       /*
58708 +        * Inform ALSA about constraints of the audio device
58709 +        */
58710 +       ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &ubi32_pcm_rates);
58711 +       if (ret < 0) {
58712 +               snd_printk(KERN_INFO "invalid rate\n");
58713 +               goto out;
58714 +       }
58715 +
58716 +       /* Force the buffer size to be an integer multiple of period size */
58717 +       ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
58718 +       if (ret < 0) {
58719 +               snd_printk(KERN_INFO "invalid period\n");
58720 +               goto out;
58721 +       }
58722 +       /* Initialize structures/registers */
58723 +       ubi32_rd = kzalloc(sizeof(struct ubi32_snd_runtime_data), GFP_KERNEL);
58724 +       if (ubi32_rd == NULL) {
58725 +               ret = -ENOMEM;
58726 +               goto out;
58727 +       }
58728 +
58729 +       runtime->private_data = ubi32_rd;
58730 +
58731 +#ifdef CONFIG_SND_DEBUG
58732 +       snd_printk(KERN_INFO "snd_ubi32_pcm_open returned 0\n");
58733 +#endif
58734 +
58735 +       return 0;
58736 +out:
58737 +#ifdef CONFIG_SND_DEBUG
58738 +       snd_printk(KERN_INFO "snd_ubi32_pcm_open returned %d\n", ret);
58739 +#endif
58740 +
58741 +       return ret;
58742 +}
58743 +
58744 +static struct snd_pcm_ops snd_ubi32_pcm_ops = {
58745 +       .open =         snd_ubi32_pcm_open, /* Open */
58746 +       .close =        snd_ubi32_pcm_close, /* Close */
58747 +       .ioctl =        snd_pcm_lib_ioctl, /* Generic IOCTL handler */
58748 +       .hw_params =    snd_ubi32_pcm_hw_params, /* Hardware parameters/capabilities */
58749 +       .hw_free =      snd_ubi32_pcm_hw_free, /* Free function for hw_params */
58750 +       .prepare =      snd_ubi32_pcm_prepare,
58751 +       .trigger =      snd_ubi32_pcm_trigger,
58752 +       .pointer =      snd_ubi32_pcm_pointer,
58753 +};
58754 +
58755 +/*
58756 + * Interrupt handler that gets called when the audio device
58757 + * interrupts Linux
58758 + */
58759 +static irqreturn_t snd_ubi32_pcm_interrupt(int irq, void *appdata)
58760 +{
58761 +       struct snd_pcm *pcm = (struct snd_pcm *)appdata;
58762 +       struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
58763 +       struct audio_dev_regs *adr = ubi32_priv->adr;
58764 +       struct snd_pcm_substream *substream;
58765 +       struct ubi32_snd_runtime_data *ubi32_rd;
58766 +       int dma_to_fill = 0;
58767 +
58768 +       /*
58769 +        * Check to see if the interrupt is for us
58770 +        */
58771 +       if (!(ubi32_priv->ar->int_status & (1 << ubi32_priv->irq_idx))) {
58772 +               return IRQ_NONE;
58773 +       }
58774 +
58775 +       /*
58776 +        * Clear the interrupt
58777 +        */
58778 +       ubi32_priv->ar->int_status &= ~(1 << ubi32_priv->irq_idx);
58779 +
58780 +       /*
58781 +        * We only have one stream since we don't mix.  Therefore
58782 +        * we don't need to search through substreams.
58783 +        */
58784 +       if (ubi32_priv->is_capture) {
58785 +               substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
58786 +       } else {
58787 +               substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
58788 +       }
58789 +
58790 +       if (!substream->runtime) {
58791 +               snd_printk(KERN_WARNING "No runtime data\n");
58792 +               return IRQ_NONE;
58793 +       }
58794 +
58795 +       ubi32_rd = substream->runtime->private_data;
58796 +
58797 +#ifdef CONFIG_SND_DEBUG
58798 +       snd_printk(KERN_INFO "Ubi32 ALSA interrupt\n");
58799 +#endif
58800 +
58801 +       if (ubi32_rd == NULL) {
58802 +               snd_printk(KERN_WARNING "No private data\n");
58803 +               return IRQ_NONE;
58804 +       }
58805 +
58806 +       // Check interrupt cause
58807 +       if (0) {
58808 +               // Handle the underflow case
58809 +       } else if ((adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) ||
58810 +                  (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST)) {
58811 +               if (adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) {
58812 +                       dma_to_fill = 0;
58813 +                       adr->status &= ~AUDIO_STATUS_PLAY_DMA0_REQUEST;
58814 +               } else if (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST) {
58815 +                       dma_to_fill = 1;
58816 +                       adr->status &= ~AUDIO_STATUS_PLAY_DMA1_REQUEST;
58817 +               }
58818 +               ubi32_rd->period_ptr += ubi32_rd->period_size;
58819 +               if (ubi32_rd->period_ptr >= ubi32_rd->dma_buffer_end) {
58820 +                       ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
58821 +               }
58822 +               adr->dma_xfer_requests[dma_to_fill].ptr = (void *)ubi32_rd->period_ptr;
58823 +               adr->dma_xfer_requests[dma_to_fill].ctr = ubi32_rd->period_size;
58824 +               adr->dma_xfer_requests[dma_to_fill].active = 1;
58825 +#ifdef CONFIG_SND_DEBUG
58826 +               snd_printk(KERN_INFO "xfer_request %d ptr=0x%x ctr=%u\n", dma_to_fill, ubi32_rd->period_ptr, ubi32_rd->period_size);
58827 +#endif
58828 +               adr->int_flags |= AUDIO_INT_FLAG_MORE_SAMPLES;
58829 +               snd_ubi32_vp_int_set(substream->pcm);
58830 +       }
58831 +       // If we are interrupted by the VP, that means we completed
58832 +       // processing one period of audio.  We need to inform the upper
58833 +       // layers of ALSA of this.
58834 +       snd_pcm_period_elapsed(substream);
58835 +
58836 +       return IRQ_HANDLED;
58837 +}
58838 +
58839 +void __devexit snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv)
58840 +{
58841 +       struct snd_pcm *pcm = ubi32_priv->pcm;
58842 +       free_irq(ubi32_priv->rx_irq, pcm);
58843 +}
58844 +
58845 +#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
58846 +#error "Change this table to match pcm.h"
58847 +#endif
58848 +static unsigned int rates[] __initdata = {5512, 8000, 11025, 16000, 22050,
58849 +                                         32000, 44100, 48000, 64000, 88200,
58850 +                                         96000, 176400, 192000};
58851 +
58852 +/*
58853 + * snd_ubi32_pcm_probe
58854 + */
58855 +int __devinit snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev)
58856 +{
58857 +       struct snd_pcm *pcm;
58858 +       int ret, err;
58859 +       int i;
58860 +       int j;
58861 +       int nrates;
58862 +       unsigned int rate_max = 0;
58863 +       unsigned int rate_min = 0xFFFFFFFF;
58864 +       unsigned int rate_mask = 0;
58865 +       struct audio_dev_regs *adr;
58866 +       struct resource *res_adr;
58867 +       struct resource *res_irq_tx;
58868 +       struct resource *res_irq_rx;
58869 +       struct ubi32pcm_platform_data *pdata;
58870 +
58871 +       pdata = pdev->dev.platform_data;
58872 +       if (!pdata) {
58873 +               return -ENODEV;
58874 +       }
58875 +
58876 +       /*
58877 +        * Get our resources, adr is the hardware driver base address
58878 +        * and the tx and rx irqs are used to communicate with the
58879 +        * hardware driver.
58880 +        */
58881 +       res_adr = platform_get_resource(pdev, IORESOURCE_MEM, AUDIO_MEM_RESOURCE);
58882 +       res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_TX_IRQ_RESOURCE);
58883 +       res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_RX_IRQ_RESOURCE);
58884 +       if (!res_adr || !res_irq_tx || !res_irq_rx) {
58885 +               snd_printk(KERN_WARNING "Could not get resources");
58886 +               return -ENODEV;
58887 +       }
58888 +
58889 +       ubi32_priv->ar = (struct audio_regs *)res_adr->start;
58890 +       ubi32_priv->tx_irq = res_irq_tx->start;
58891 +       ubi32_priv->rx_irq = res_irq_rx->start;
58892 +       ubi32_priv->irq_idx = pdata->inst_num;
58893 +       ubi32_priv->adr = &(ubi32_priv->ar->adr[pdata->inst_num]);
58894 +
58895 +       /*
58896 +        * Check the version
58897 +        */
58898 +       adr = ubi32_priv->adr;
58899 +       if (adr->version != AUDIO_DEV_REGS_VERSION) {
58900 +               snd_printk(KERN_WARNING "This audio_dev_reg is not compatible with this driver\n");
58901 +               return -ENODEV;
58902 +       }
58903 +
58904 +       /*
58905 +        * Find out the standard rates, also find max and min rates
58906 +        */
58907 +       for (i = 0; i < ARRAY_SIZE(rates); i++) {
58908 +               int found = 0;
58909 +               for (j = 0; j < adr->n_sample_rates; j++) {
58910 +                       if (rates[i] == adr->sample_rates[j]) {
58911 +                               /*
58912 +                                * Check to see if it is supported by the dac
58913 +                                */
58914 +                               if ((rates[i] >= ubi32_priv->min_sample_rate) &&
58915 +                                   (!ubi32_priv->max_sample_rate ||
58916 +                                    (ubi32_priv->max_sample_rate && (rates[i] <= ubi32_priv->max_sample_rate)))) {
58917 +                                       found = 1;
58918 +                                       rate_mask |= (1 << i);
58919 +                                       nrates++;
58920 +                                       if (rates[i] < rate_min) {
58921 +                                               rate_min = rates[i];
58922 +                                       }
58923 +                                       if (rates[i] > rate_max) {
58924 +                                               rate_max = rates[i];
58925 +                                       }
58926 +                                       break;
58927 +                               }
58928 +                       }
58929 +               }
58930 +               if (!found) {
58931 +                       rate_mask |= SNDRV_PCM_RATE_KNOT;
58932 +               }
58933 +       }
58934 +
58935 +       snd_ubi32_pcm_hw.rates = rate_mask;
58936 +       snd_ubi32_pcm_hw.rate_min = rate_min;
58937 +       snd_ubi32_pcm_hw.rate_max = rate_max;
58938 +       ubi32_pcm_rates.count = adr->n_sample_rates;
58939 +       ubi32_pcm_rates.list = (unsigned int *)adr->sample_rates;
58940 +       ubi32_pcm_rates.mask = 0;
58941 +
58942 +       for (i = 0; i < 32; i++) {
58943 +               if (adr->channel_mask & (1 << i)) {
58944 +                       if (!snd_ubi32_pcm_hw.channels_min) {
58945 +                               snd_ubi32_pcm_hw.channels_min = i;
58946 +                       }
58947 +                       snd_ubi32_pcm_hw.channels_max = i;
58948 +               }
58949 +       }
58950 +       snd_printk(KERN_INFO "Ubi32PCM: channels_min:%u channels_max:%u\n",
58951 +                  snd_ubi32_pcm_hw.channels_min,
58952 +                  snd_ubi32_pcm_hw.channels_max);
58953 +
58954 +       if (adr->caps & AUDIONODE_CAP_BE) {
58955 +               snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_BE;
58956 +       }
58957 +       if (adr->caps & AUDIONODE_CAP_LE) {
58958 +               snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
58959 +       }
58960 +
58961 +       snd_printk(KERN_INFO "Ubi32PCM: rates:%08x min:%u max:%u count:%d fmts:%016llx (%s)\n",
58962 +                  snd_ubi32_pcm_hw.rates,
58963 +                  snd_ubi32_pcm_hw.rate_min,
58964 +                  snd_ubi32_pcm_hw.rate_max,
58965 +                  ubi32_pcm_rates.count,
58966 +                  snd_ubi32_pcm_hw.formats,
58967 +                  ubi32_priv->is_capture ? "capture" : "playback");
58968 +
58969 +       if (ubi32_priv->is_capture) {
58970 +               ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 0, 1, &pcm);
58971 +       } else {
58972 +               ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 1, 0, &pcm);
58973 +       }
58974 +
58975 +       if (ret < 0) {
58976 +               return ret;
58977 +       }
58978 +
58979 +       pcm->private_data = ubi32_priv;
58980 +       ubi32_priv->pcm = pcm;
58981 +       ubi32_priv->pdata = pdata;
58982 +
58983 +       pcm->info_flags = 0;
58984 +
58985 +       strcpy(pcm->name, "Ubi32-PCM");
58986 +
58987 +       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
58988 +                                             snd_dma_continuous_data(GFP_KERNEL),
58989 +                                             45*1024, 64*1024);
58990 +
58991 +       if (ubi32_priv->is_capture) {
58992 +               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ubi32_pcm_ops);
58993 +       } else {
58994 +               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ubi32_pcm_ops);
58995 +       }
58996 +
58997 +       /*
58998 +        * Start up the audio device
58999 +        */
59000 +       adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
59001 +       adr->command = AUDIO_CMD_ENABLE;
59002 +       snd_ubi32_vp_int_set(pcm);
59003 +
59004 +       /*
59005 +        * Request IRQ
59006 +        */
59007 +       err = request_irq(ubi32_priv->rx_irq, snd_ubi32_pcm_interrupt, IRQF_SHARED | IRQF_DISABLED, pcm->name, pcm);
59008 +       if (err) {
59009 +               snd_printk(KERN_WARNING "request_irq failed: irq=%d err=%d\n", ubi32_priv->rx_irq, err);
59010 +               return -ENODEV;
59011 +       }
59012 +
59013 +       return ret;
59014 +
59015 +}